Skip to content
Back to App

Positions

Position endpoints let you query currently open positions, close an entire position, or partially close a position. Positions are created automatically when orders are filled and represent your current exposure in a given instrument.

Position fields

FieldTypeDescription
idnumberPosition index within the response (1-based)
accountIdnumberAccount ID
contractIdstringContract ID for the position
contractDisplayNamestringFull instrument name (e.g., "E-Mini NASDAQ 100 Futures")
creationTimestampstringISO 8601 timestamp (time of the query)
typenumberPosition direction: 1 = Long, 2 = Short
sizenumberNumber of contracts currently held
averagePricenumberAverage entry price across all fills

POST Position/searchOpen

Get all currently open positions for an account.

URL: POST /api/topstep-sim/Position/searchOpen

Authentication: Bearer token required.

Request body

{
"accountId": 12345
}
FieldTypeRequiredDescription
accountIdnumberYesAccount ID

Response

{
"success": true,
"errorCode": 0,
"errorMessage": null,
"positions": [
{
"id": 1,
"accountId": 12345,
"contractId": "CON.F.US.ENQ.H25",
"contractDisplayName": "E-Mini NASDAQ 100 Futures",
"creationTimestamp": "2025-01-15T14:30:05.000Z",
"type": 1,
"size": 2,
"averagePrice": 21503.50
}
]
}
FieldTypeDescription
positionsarrayList of open position objects. Empty array [] if no positions are open.

Example

result = api("Position/searchOpen", {"accountId": ACCOUNT_ID})
positions = result.get("positions", [])
if positions:
for pos in positions:
direction = "LONG" if pos["type"] == 1 else "SHORT"
print(f"{direction} {pos['size']} @ {pos['averagePrice']:.2f}")
else:
print("No open positions")

POST Position/closeContract

Close an entire position in a given contract. This is equivalent to placing a market order in the opposite direction for the full position size.

URL: POST /api/topstep-sim/Position/closeContract

Authentication: Bearer token required.

Request body

{
"accountId": 12345,
"contractId": "CON.F.US.ENQ.H25"
}
FieldTypeRequiredDescription
accountIdnumberYesAccount ID
contractIdstringYesContract ID of the position to close

Response

{
"success": true,
"errorCode": 0,
"errorMessage": null
}

Example

# Close the entire NQ position
result = api("Position/closeContract", {
"accountId": ACCOUNT_ID,
"contractId": CONTRACT_ID
})
if result["success"]:
print("Position closed")
else:
print(f"Close failed: {result['errorMessage']}")

Error responses

ScenarioerrorCodeerrorMessage
Invalid or unowned accountId1"Account not found"
No open positions2"Position not found"
Challenge no longer active4"Account violation"
Closing order rejected by the engine5The rejection reason

POST Position/partialCloseContract

Partially close a position by specifying the number of contracts to close. Useful for scaling out of a trade.

URL: POST /api/topstep-sim/Position/partialCloseContract

Authentication: Bearer token required.

Request body

{
"accountId": 12345,
"contractId": "CON.F.US.ENQ.H25",
"size": 1
}
FieldTypeRequiredDescription
accountIdnumberYesAccount ID
contractIdstringYesContract ID of the position to partially close
sizenumberYesNumber of contracts to close (must be less than or equal to the current position size)

Response

{
"success": true,
"errorCode": 0,
"errorMessage": null
}

Example

# Scale out: close 1 of 3 contracts at the first target
positions = get_positions(ACCOUNT_ID)
for pos in positions:
if pos["size"] > 1 and current_price >= first_target:
result = api("Position/partialCloseContract", {
"accountId": ACCOUNT_ID,
"contractId": pos["contractId"],
"size": 1 # Close 1 contract, keep the rest running
})
if result["success"]:
print(f"[INFO] Scaled out 1 contract at {current_price}")

Error responses

ScenarioerrorCodeerrorMessage
Invalid or unowned accountId1"Account not found"
No open positions2"Position not found"
Challenge no longer active4"Account violation"
Size missing, non-integer, ≤ 0, or larger than the position5"Invalid close size"
Closing order rejected by the engine6The rejection reason

Common patterns

Flatten all positions

Close every open position across all contracts:

result = api("Position/searchOpen", {"accountId": ACCOUNT_ID})
for pos in result.get("positions", []):
api("Position/closeContract", {
"accountId": ACCOUNT_ID,
"contractId": pos["contractId"]
})
print("All positions flattened")

Scale-out strategy

Exit in stages to lock in profit while letting the remaining position run:

# Entry: buy 3 contracts
api("Order/place", {
"accountId": ACCOUNT_ID,
"contractId": CONTRACT_ID,
"type": 2, "side": 0, "size": 3
})
# In your main loop:
positions = get_positions(ACCOUNT_ID)
if positions:
pos = positions[0]
pnl_ticks = (bar["c"] - pos["averagePrice"]) / TICK_SIZE
# Take 1/3 off at +10 ticks
if pnl_ticks >= 10 and pos["size"] == 3:
api("Position/partialCloseContract", {
"accountId": ACCOUNT_ID,
"contractId": CONTRACT_ID,
"size": 1
})
# Take another 1/3 off at +20 ticks
elif pnl_ticks >= 20 and pos["size"] == 2:
api("Position/partialCloseContract", {
"accountId": ACCOUNT_ID,
"contractId": CONTRACT_ID,
"size": 1
})
# Let the last contract run with a trailing stop

Check if currently in a position

positions = get_positions(ACCOUNT_ID)
is_long = any(p["type"] == 1 for p in positions)
is_short = any(p["type"] == 2 for p in positions)
is_flat = len(positions) == 0