Advanced orders¶
Stop orders, take-profit, trailing stops, OCO, and execution flags. Every order type below is exposed through every binding — only the method name differs.
Order types¶
| Type | Use case |
|---|---|
STOP_MARKET |
Stop loss, breakout entry |
STOP_LIMIT |
Stop with price control |
TAKE_PROFIT_MARKET |
Lock in profits |
TAKE_PROFIT_LIMIT |
Lock in profits with price control |
TRAILING_STOP |
Dynamic stop that follows price |
OCO |
One-cancels-other for breakouts |
Stop orders¶
Stop trigger logic: SELL stop fires when price <= trigger; BUY stop fires when price >= trigger.
Take-profit orders¶
SELL TP fires when price >= trigger (lock profit on a long); BUY TP fires when price <= trigger.
Trailing stops¶
SELL trailing trigger follows price up; when price drops to trigger, the order executes.
Time-in-force¶
IOC (immediate-or-cancel), FOK (fill-or-kill), POST_ONLY (maker-only — reject if would cross spread).
POST_ONLY orders that would cross the book are rejected at submit time (matches real-exchange behaviour, including in BacktestRunner since #124).
Close current position¶
close_position issues a reduce-only market order sized to flatten the existing position.
Manual TP/SL bracket¶
A common pattern: on entry-fill, place TP and SL; cancel one when the other fills.
def on_order_filled(self, order):
if order.id == self.entry_id:
entry = order.price
self.tp_id = self.take_profit_market("sell", trigger=entry * 1.06, qty=order.quantity)
self.sl_id = self.stop_market ("sell", trigger=entry * 0.98, qty=order.quantity)
elif order.id == self.tp_id:
self.cancel_order(self.sl_id)
elif order.id == self.sl_id:
self.cancel_order(self.tp_id)
onOrderFilled(order, emit) {
if (order.id === this.entryId) {
const entry = order.price;
this.tpId = emit.takeProfitMarket("sell", entry * 1.06, order.quantity);
this.slId = emit.stopMarket ("sell", entry * 0.98, order.quantity);
} else if (order.id === this.tpId) {
emit.cancel(this.slId);
} else if (order.id === this.slId) {
emit.cancel(this.tpId);
}
}
void onOrderFilled(const Order& order) {
if (order.id == _entryId) {
auto entry = order.price.toDouble();
_tpId = emitTakeProfitMarket(order.symbol, Side::SELL,
Price::fromDouble(entry * 1.06), order.quantity);
_slId = emitStopMarket (order.symbol, Side::SELL,
Price::fromDouble(entry * 0.98), order.quantity);
} else if (order.id == _tpId) {
emitCancel(_slId);
} else if (order.id == _slId) {
emitCancel(_tpId);
}
}
Checking exchange capabilities¶
Real exchanges support different subsets of order types. Before using an advanced feature in live trading, ask the executor what it supports.
Capabilities introspection isn't yet exposed in the binding APIs — check the exchange's connector source or fall back to manual TP/SL.