Skip to content

Trading

Orders and trades live on two services:

  • STXOrderService: place, cancel, and query orders
  • STXTradeService: query fills (trades)
using STX.Sdk.Enums;
using STX.Sdk.Services;
var orders = serviceProvider.GetRequiredService<STXOrderService>();
var order = await orders.ConfirmOrderAsync(
price: 10, // cents
quantity: 1,
marketId: "mkt_abc",
action: STXOrderAction.buy,
orderType: STXOrderType.limit,
clientOrderId: "my-ref-1", // optional idempotency key
cancelOnDisconnect: true);
Console.WriteLine($"Order {order.Id} placed at {order.Price}c x {order.Quantity}");
price Integer cents. 50 = 50¢. Ignored for market orders. The REST and WebSocket surfaces write this same price as the dollar string "0.50".
quantity Number of contracts.
marketId From STXMarketService.GetMarketInfosWithCountAsync.
action STXOrderAction.buy / STXOrderAction.sell
orderType STXOrderType.limit / STXOrderType.market
clientOrderId Your idempotency key. If the call retries you won’t get a double-fill.
cancelOnDisconnect If true, the exchange cancels this order when the websocket drops. Requires STXActiveOrdersChannel to be joined (see below).

Cancel-on-disconnect requires the active orders channel

Section titled “Cancel-on-disconnect requires the active orders channel”

If you pass cancelOnDisconnect: true but haven’t joined STXActiveOrdersChannel, the call throws STXCancelOnDisconnectNotEnabledException. For the market-maker workflow, always join the channel first (it costs nothing):

var activeOrders = serviceProvider.GetRequiredService<STXActiveOrdersChannel>();
await activeOrders.StartAsync();

If you only want a simple place-and-leave-it order, pass cancelOnDisconnect: false.

Placing many orders at once is one round-trip instead of N:

var batch = new[]
{
new STXConfirmOrderParams { Price = 10, Quantity = 1, MarketId = "mkt_a", Action = STXOrderAction.buy, OrderType = STXOrderType.limit },
new STXConfirmOrderParams { Price = 85, Quantity = 2, MarketId = "mkt_b", Action = STXOrderAction.sell, OrderType = STXOrderType.limit },
};
var placed = await orders.ConfirmOrdersAsync(batch);
await orders.CancelOrderAsync(orderId); // one
await orders.CancelOrdersAsync(new[] { orderId1, orderId2 }); // several
await orders.CancelAllOrdersAsync(); // everything open on this account

CancelAllOrdersAsync returns the list of every cancelled order, which is handy to reconcile against your own state.

var history = await orders.GetMyOrdersAsync(
statusFilter: new[] { STXOrderStatus.filled, STXOrderStatus.cancelled },
limit: 50,
sortBy: STXOrdersSortByField.insertedAt,
sortOrder: STXSortOrder.desc);
foreach (var o in history.Orders)
{
Console.WriteLine($"{o.Id,-10} {o.Status,-10} {o.MarketId,-12} {o.Price}c x {o.Quantity}");
}

Each fill is a trade:

var trades = serviceProvider.GetRequiredService<STXTradeService>();
// Everything
var hist = await trades.GetMyTradesAsync(
limit: 50,
sortBy: STXTradesSortByField.time,
sortOrder: STXSortOrder.desc);
// Fills for a specific order
var orderFills = await trades.GetMyTradesForOrderAsync(orderId);

Polling the REST endpoints works but adds latency. The websocket channels push updates as they happen:

  • STXActiveOrdersChannel: every state change on an open order (open → partially_filled → filled / cancelled)
  • STXActiveTradesChannel: every new trade (fill)

See WebSockets → Orders & trades.

Pulled straight from the example console app’s STXWorker.cs:

// 1. Learn who the key belongs to, then connect channels.
// Channel topics are keyed on the user id, and with an API key there is no
// login response to read it from.
await _identity.GetMeAsync();
await _ordersChannel.StartAsync();
await _tradesChannel.StartAsync();
await _portfolioChannel.StartAsync();
// 2. Subscribe to market updates
_marketChannel.SetOnReceiveAction(OnPriceTick);
await _marketChannel.StartAsync();
// 3. On each tick, quote
void OnPriceTick(STXMarketInfoChannelData tick) {
// Cancel stale orders and place fresh ones
await _orderService.CancelAllOrdersAsync();
await _orderService.ConfirmOrdersAsync(BuildQuotes(tick));
}

Cancel-on-disconnect, automatic session refresh, and portfolio-balance tracking are all handled by registered services; the loop above is the whole app.

v1.5.9Changelogllms.txtllms-full.txt