输入/搜索内容
内置函数
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
结构体
内置变量与常量
通用约定
交易所

异步下单:立即返回请求号,不等待交易所应答。下单结果以一条应答事件(kind为20)投递给发起请求的线程,可通过ctx.poll取出。参数与ctx.order相同,适用于同时发出多笔订单,或下单时不阻塞行情处理的场景。

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

示例

异步并发挂出三档限价买单,按请求号收集下单应答,并输出每笔订单的结果与耗时。

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) // 调用即失败,不会收到应答 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) // 切勿重发 } 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) # 调用即失败,不会收到应答 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) # 切勿重发 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), // 调用即失败,不会收到应答 } } 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); // 切勿重发 } 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, _ => {} } } }

返回值

类型描述

number / object

请求号,与应答事件中的reqId一致。若参数有误、交易所不支持via为ws,或在途请求超过256个,则立即返回Error对象,此时不会产生应答事件。

参数

名称类型必填描述

ex

object / number

是

下单账户:可传入交易所对象,或该账户在exchanges数组中的索引,用法同ctx.order。

symbol

string

是

交易品种代码,例如BTC_USDT、BTC_USDT.swap。

side

string

是

交易方向:buy表示买入,sell表示卖出。

px

number

是

委托价格。市价单不使用该价格,可传入0。

qty

number

是

委托数量,必须大于0,数量单位同ctx.order。

options

object

否

下单选项,字段与ctx.order相同:{type, tif, reduceOnly, postOnly, extra, clientId, via, timeout}。

参考

备注

应答事件(kind为20,type与channel均为ack)位于内置事件流ctx.STREAM_ORDER_ACK上,只投递给调用ctx.orderAsync()的线程,其他线程无法获取,也无需订阅。ctx.poll([ctx.STREAM_ORDER_ACK], timeout)只获取应答,ctx.poll([], timeout)则将应答与已订阅的事件一并获取。除公共字段外,还包含以下字段:

字段类型说明
reqIdnumber请求号,即ctx.orderAsync()、ctx.cancelAsync()的返回值
opstringplace(下单)或cancel(撤单)
statusstringok表示成功,failed表示失败(拒单、限频、参数错误或调用失败),unknown表示状态未知(见下文)
okboolstatus为ok时为true
viastring实际使用的通道:ws或rest(WebSocket在请求发出前不可用、转而使用REST时为rest)
idstring交易所订单号:下单成功时为新订单号,撤单时为目标订单号;下单失败时为空字符串
clientIdstring客户端订单号:WebSocket下单时必定存在;REST下单仅在指定了clientId时存在
errorstring失败原因,成功时为空字符串;最长119字节,完整原因请通过同步接口ctx.order获取
reasonnumber统一原因码:0无,1请求错误,2凭据错误,3传输错误或未知,4交易所拒绝,5限频
reasonTextstringreason的文字说明
exchTimenumber交易所应答时间(毫秒);交易所未提供时(例如REST应答)为空值
latencyMsnumber从调用ctx.orderAsync()到获得结果的耗时(毫秒)

symbol、ex分别为请求中的品种与账户索引;time为交易所应答时间,若无则与ts相同。

status为unknown表示请求已通过WebSocket发出,但未等到应答,且按客户端订单号查询一次后仍无法确认。订单可能已提交到交易所:请勿重发,应按clientId查询订单,或等待私有流的订单回报进行确认。WebSocket下单的其他规则(不支持时返回错误、请求发出前连接不可用时改用REST、限频)与ctx.order相同。

异步与通道无关:不传via时,同样通过REST接口下单。同时发出的请求互不排队,应答按完成顺序到达,不一定与调用顺序一致;如需先下单再撤单,应等收到下单应答后再撤单。请求在托管者的后台线程上执行,限频规则照常生效,但不会阻塞调用线程。

主线程和threading.Thread()创建的线程均可调用,每个线程只会收到自己所发请求的应答。应答事件不会因读取不及时而被丢弃,需持续调用ctx.poll()将其取走。

Python中为ctx.orderAsync(ex, symbol, side, px, qty, opts=None),返回请求号(int)或CtxError对象,应答事件为字典,字段同上。Rust中为ctx::order_async(ex, symbol, side, px, qty, opts_json: &str) -> Result<u64, String>,应答事件通过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),事件流ID为ctx::STREAM_ORDER_ACK。