Type/to search
Built-in Functions
Global
Log
Market
Trade
Account
Futures
Exchange
IO
Network
Storage
Threads
exchange.Go
EventLoop
ctx.subscribe
ctx.poll
ctx.order
ctx.cancel
ctx.orderAsync
ctx.cancelAsync
Subscription
threading
Thread
ThreadLock
ThreadEvent
ThreadCondition
ThreadDict
Server
TA
Talib
OS
Structures
Built-in Variables and Constants
Conventions
Exchanges

Asynchronous order placement: returns a request ID immediately without waiting for the exchange's response. The order result is delivered as a response event (kind is 20) to the thread that sent the request, and can be retrieved with ctx.poll. The parameters are the same as for ctx.order. Use it to send several orders at once, or to place orders without blocking market data processing.

ctx.orderAsync(ex, symbol, side, px, qty)
ctx.orderAsync(ex, symbol, side, px, qty, options)

Examples

Asynchronously and concurrently place three tiers of limit buy orders, collect the order acks by request ID, and output the result and latency of each order.

javascript
function main() { var t = exchange.GetTicker("BTC_USDT") if (!t) { return } var pending = {} for (var i = 1; i <= 3; i++) { var px = _N(t.Buy * (1 - 0.01 * i), 2) var req = ctx.orderAsync(exchange, "BTC_USDT", "buy", px, 0.001, {via: "ws", postOnly: true}) if (req instanceof Error) { Log("not sent:", req.message) // The call failed immediately; no ack will be received continue } pending[req] = px } while (Object.keys(pending).length > 0) { var ack = ctx.poll([ctx.STREAM_ORDER_ACK], 10000) if (!ack) { Log("no ack in 10 seconds") break } if (ack.kind !== 20) { continue } if (ack.ok) { Log("placed", ack.id, "px:", pending[ack.reqId], ack.via, ack.latencyMs, "ms") } else if (ack.status === "unknown") { Log("state unknown, check the order by clientId", ack.clientId) // Never resend } else { Log("failed:", ack.error, ack.reasonText) } delete pending[ack.reqId] } }
python
def main(): t = exchange.GetTicker("BTC_USDT") if not t: return pending = {} for i in range(1, 4): px = _N(t["Buy"] * (1 - 0.01 * i), 2) opts = {"via": "ws", "postOnly": True} req = ctx.orderAsync(exchange, "BTC_USDT", "buy", px, 0.001, opts) if isinstance(req, CtxError): Log("not sent:", req) # The call failed immediately; no ack will be received continue pending[req] = px while pending: ack = ctx.poll([ctx.STREAM_ORDER_ACK], 10000) if ack is None: Log("no ack in 10 seconds") break if ack.kind != 20: continue if ack.ok: Log("placed", ack.id, "px:", pending.get(ack.reqId), ack.via, ack.latencyMs, "ms") elif ack.status == "unknown": Log("state unknown, check the order by clientId", ack.clientId) # Never resend else: Log("failed:", ack.error, ack.reasonText) pending.pop(ack.reqId, None)
rust
use sdk::ctx::EventExt; use std::collections::HashMap; fn main() { let Ok(t) = exchange.GetTicker("BTC_USDT") else { return }; let mut pending: HashMap<u64, f64> = HashMap::new(); for i in 1..=3 { let px = _N(t.Buy * (1.0 - 0.01 * i as f64), 2); let opts = r#"{"via":"ws","postOnly":true}"#; match ctx::order_async(exchange, "BTC_USDT", "buy", px, 0.001, opts) { Ok(req) => { pending.insert(req, px); } Err(e) => Log!("not sent:", e), // The call failed immediately; no ack will be received } } while !pending.is_empty() { match ctx::poll(&[ctx::STREAM_ORDER_ACK], Some(10000)) { ctx::Polled::Event(ev) => { let Some(ack) = ev.order_ack() else { continue }; if ack.ok { Log!("placed", ack.id, ack.via, ack.latency_ms, "ms"); } else if ack.status == "unknown" { Log!("state unknown, check the order by clientId", ack.client_id); // Never resend } else { Log!("failed:", ack.error, ack.reason_text); } pending.remove(&ack.req_id); } ctx::Polled::Empty => { Log!("no ack in 10 seconds"); break; } ctx::Polled::Stopped => break, _ => {} } } }

Returns

TypeDescription

number / object

The request ID, which matches the reqId in the response event. If a parameter is invalid, the exchange does not support via set to ws, or more than 256 requests are in flight, an Error object is returned immediately and no response event is generated.

Arguments

NameTypeRequiredDescription

ex

object / number

Yes

The account that places the order: either an exchange object or the index of that account in the exchanges array, used the same way as in ctx.order.

symbol

string

Yes

Trading symbol code, for example BTC_USDT or BTC_USDT.swap.

side

string

Yes

Order side: buy means buy, sell means sell.

px

number

Yes

Order price. Market orders do not use this price, so 0 can be passed.

qty

number

Yes

Order quantity. It must be greater than 0, and uses the same quantity unit as ctx.order.

options

object

No

Order options, with the same fields as ctx.order: {type, tif, reduceOnly, postOnly, extra, clientId, via, timeout}.

See Also

Remarks

The acknowledgement event (kind is 20, both type and channel are ack) is delivered on the built-in event stream ctx.STREAM_ORDER_ACK. It goes only to the thread that called ctx.orderAsync(). Other threads cannot receive it and do not need to subscribe to it. ctx.poll([ctx.STREAM_ORDER_ACK], timeout) retrieves only acknowledgements, while ctx.poll([], timeout) retrieves acknowledgements together with the subscribed events. Besides the common fields, it contains the following fields:

FieldTypeDescription
reqIdnumberRequest ID, i.e. the return value of ctx.orderAsync() or ctx.cancelAsync()
opstringplace (order placement) or cancel (order cancellation)
statusstringok means success, failed means failure (order rejected, rate limited, invalid parameters or call failure), unknown means the status is unknown (see below)
okbooltrue when status is ok
viastringThe channel actually used: ws or rest (rest when WebSocket was unavailable before the request was sent and REST was used instead)
idstringExchange order ID: the new order ID when placement succeeds, the target order ID for a cancellation; an empty string when placement fails
clientIdstringClient order ID: always present for WebSocket orders; for REST orders, present only when clientId was specified
errorstringFailure reason, an empty string on success; at most 119 bytes. Use the synchronous interface ctx.order to get the full reason
reasonnumberUnified reason code: 0 none, 1 request error, 2 credential error, 3 transport error or unknown, 4 rejected by exchange, 5 rate limited
reasonTextstringText description of reason
exchTimenumberExchange acknowledgement time (milliseconds); null when the exchange does not provide it (e.g. REST acknowledgements)
latencyMsnumberTime elapsed from calling ctx.orderAsync() to receiving the result (milliseconds)

symbol and ex are the symbol and account index in the request. time is the exchange acknowledgement time. If that is not available, it equals ts.

A status of unknown means the request was sent over WebSocket but no acknowledgement arrived, and one query by client order ID still could not confirm the result. The order may already have been submitted to the exchange. Do not resend it. Instead, query the order by clientId, or wait for the order report on the private stream to confirm it. The other rules for WebSocket order placement are the same as ctx.order: an error is returned when WebSocket is not supported, REST is used when the connection is unavailable before the request is sent, and rate limits apply.

Asynchronous mode does not depend on the channel: when via is not passed, the order is still placed through the REST interface. Requests sent at the same time do not queue behind each other. Acknowledgements arrive in order of completion, which is not necessarily the order of the calls. If you need to place an order and then cancel it, wait for the placement acknowledgement before cancelling. Requests run on a background thread of the docker. Rate-limit rules still apply, but the calling thread is not blocked.

Both the main thread and threads created by threading.Thread() can call it, and each thread receives only the acknowledgements for its own requests. Acknowledgement events are not dropped when they are not read promptly. You must keep calling ctx.poll() to take them.

In Python the call is ctx.orderAsync(ex, symbol, side, px, qty, opts=None). It returns a request ID (int) or a CtxError object, and the acknowledgement event is a dictionary with the same fields as above. In Rust the call is ctx::order_async(ex, symbol, side, px, qty, opts_json: &str) -> Result<u64, String>. The acknowledgement event is read through ev.order_ack() (OrderAckView: req_id, op, status, ok, via, id, client_id, symbol, error, reason, reason_text, exch_time (Option<i64>), latency_ms, time), and the event stream ID is ctx::STREAM_ORDER_ACK.