Skip to main content
Use staging first. env="production" trades with real balances. Every snippet on this page runs against env="staging" — flip the flag only when you’ve verified the code path end-to-end.

Place an order

Two-step pattern: preview (no side effects) → confirm.
1

Preview

previewOrder calculates fees, margin, and fill estimates without touching the book.
from stx import STX, Selection

client = STX(region="ontario", env="staging")

preview = client.previewOrder(
    params={
        "marketId": "mkt_8f3...",
        "side":       "yes",
        "size":       10,
        "limitPrice": 0.52,
    },
    selections=Selection(
        "estimatedCost", "estimatedFees", "estimatedFillPrice",
    ),
)
print(preview.estimatedCost, preview.estimatedFees)
2

Confirm

Once the preview looks right, place the order:
order = client.confirmOrder(
    params={
        "marketId":   "mkt_8f3...",
        "side":       "yes",
        "size":       10,
        "limitPrice": 0.52,
    },
    selections=Selection("orderId", "status", "filledSize"),
)
print(order.orderId, order.status, order.filledSize)
Preview and confirm take the same params. The SDK doesn’t auto-confirm from a preview — you have to call confirmOrder explicitly so the trade decision stays in your code.

Cancel an order

cancelled = client.cancelOrder(
    params={"orderId": "ord_12ab..."},
    selections=Selection("orderId", "status"),
)
print(cancelled.status)
Batch cancel is not yet supported — cancel one-at-a-time for now.

List your orders

orders = client.userOrders(
    params={"status": "open"},
    selections=Selection("orderId", "marketId", "side", "size", "filledSize", "status"),
)
for order in orders:
    print(order.orderId, order.status, order.filledSize)
Statuses: pending, open, filled, cancelled, rejected.

Positions

Positions hang off userProfile:
profile = client.userProfile(
    selections=Selection(
        "id",
        "balance",
        positions=Selection(
            "marketId", "side", "size", "avgCost", "realizedPnl", "unrealizedPnl",
        ),
    ),
)
print("balance:", profile.balance)
for pos in profile.positions or []:
    print(pos.marketId, pos.side, pos.size)

Fills and trade history

trades = client.userTrades(
    params={"limit": 100},
    selections=Selection(
        "tradeId", "orderId", "marketId", "side", "size", "price", "executedAt",
    ),
)
for trade in trades:
    print(trade.tradeId, trade.price, trade.size)

Balance only

If you just need the number:
from stx import Selection

balance = client.userProfile(selections=Selection("balance")).balance
The default-all-fields behaviour would pull positions, fills, and the full profile graph — wasteful when you want a single scalar. Narrow the Selection.

Subscribing to order updates

For event-driven bots, skip polling userOrders and subscribe to the active_orders Phoenix channel instead. See WebSockets → Active orders.

Idempotency

confirmOrder is not idempotent — calling it twice with the same params places two orders. If you need retries to be safe, wrap the call yourself:
from stx._retry import RetryPolicy
from stx.exceptions import STXException

# Disable the default retry for confirmOrder specifically.
try:
    order = client.confirmOrder(params=..., retry=RetryPolicy.DISABLED)
except STXException:
    # Check userOrders to see if the order made it through before retrying.
    ...
The default retry policy (errors-and-retries) excludes confirmOrder and cancelOrder from automatic retries for exactly this reason.

What’s not here yet

The following operations are not yet supported by the SDK:
  • amendOrder
  • batchConfirmOrders
  • batchCancelOrders
File a feature request on github.com/stxapp/stx-python/issues if you need any of these.

Next

WebSockets

Live order and position updates without polling.

Errors & retries

What gets retried, what doesn’t, and why.