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

下单,并在交易所返回订单号后返回。默认通过交易所的REST接口下单;选项via设为ws时,通过交易所的WebSocket交易接口下单。订单后续的状态变化和成交情况由ctx.subscribe订阅的private私有流推送。调用前无需先订阅;主线程和threading.Thread()创建的线程均可调用。不等待结果的版本为ctx.orderAsync。

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

示例

  • 以比买一价低1%的价格挂出一张只做maker的限价买单,5秒后撤单;下单或撤单失败时均返回错误对象,而不抛出异常。

    javascript
    function main() { var t = exchange.GetTicker("BTC_USDT") if (!t) { return } var id = ctx.order(exchange, "BTC_USDT", "buy", _N(t.Buy * 0.99, 2), 0.001, {postOnly: true}) if (id instanceof Error) { Log("order failed:", id.message) return } Log("order id:", id) Sleep(5000) var r = ctx.cancel(exchange, "BTC_USDT", id) if (r instanceof Error) { Log("cancel failed:", r.message) // 例如订单已成交 } }
    python
    def main(): t = exchange.GetTicker("BTC_USDT") if not t: return oid = ctx.order(exchange, "BTC_USDT", "buy", _N(t["Buy"] * 0.99, 2), 0.001, {"postOnly": True}) if isinstance(oid, CtxError): Log("order failed:", oid) return Log("order id:", oid) Sleep(5000) r = ctx.cancel(exchange, "BTC_USDT", oid) if isinstance(r, CtxError): Log("cancel failed:", r) # 例如订单已成交
    rust
    fn main() { let Ok(t) = exchange.GetTicker("BTC_USDT") else { return }; // 选项以JSON字符串形式传入,无选项时传"{}" let px = _N(t.Buy * 0.99, 2); let id = match ctx::order(exchange, "BTC_USDT", "buy", px, 0.001, r#"{"postOnly":true}"#) { Ok(id) => id, Err(e) => { Log!("order failed:", e); return; } }; Log!("order id:", id); Sleep(5000); if let Err(e) = ctx::cancel(exchange, "BTC_USDT", &id) { Log!("cancel failed:", e); // 例如订单已成交 } }
  • 通过WebSocket下一张IOC买单并指定客户端订单号,再从私有流接收该订单的成交回报和最终状态;若订单状态未知,不要重新下单,应按客户端订单号核对订单。

    javascript
    function main() { var acct = ctx.subscribe(exchange, {channel: "private"}) var t = exchange.GetTicker("BTC_USDT") if (!t) { return } var cid = "demo" + Date.now() var px = _N(t.Sell * 1.001, 2) var id = ctx.order(exchange, "BTC_USDT", "buy", px, 0.001, {via: "ws", tif: "ioc", clientId: cid}) if (id instanceof Error) { if (id.message.indexOf("order state unknown") === 0) { Log("state unknown, check the order by clientId", cid) // 不要重复下单 } else { Log("order failed:", id.message) } return } var t0 = Date.now() while (Date.now() - t0 < 10000) { var ev = ctx.poll([acct], 1000) if (!ev) { continue } if (ev.kind === 19 && ev.orderId === id) { Log("fill", ev.tradeId, ev.px, ev.qty, ev.liquidity, "fee:", ev.fee, ev.feeCcy) } else if (ev.kind === 16 && ev.id === id) { if (ev.state === "filled" || ev.state === "canceled") { Log("order done:", ev.state, "filled:", ev.filledQty, "avgPx:", ev.avgPx) break } } } }
    python
    import time def main(): acct = ctx.subscribe(exchange, {"channel": "private"}) t = exchange.GetTicker("BTC_USDT") if not t: return cid = "demo%d" % int(time.time() * 1000) opts = {"via": "ws", "tif": "ioc", "clientId": cid} oid = ctx.order(exchange, "BTC_USDT", "buy", _N(t["Sell"] * 1.001, 2), 0.001, opts) if isinstance(oid, CtxError): if str(oid).startswith("order state unknown"): Log("state unknown, check the order by clientId", cid) # 不要重复下单 else: Log("order failed:", oid) return t0 = time.time() while time.time() - t0 < 10: ev = ctx.poll([acct], 1000) if ev is None: continue if ev.kind == 19 and ev.orderId == oid: Log("fill", ev.tradeId, ev.px, ev.qty, ev.liquidity, "fee:", ev.get("fee"), ev.feeCcy) elif ev.kind == 16 and ev.id == oid and ev.state in ("filled", "canceled"): Log("order done:", ev.state, "filled:", ev.filledQty, "avgPx:", ev.avgPx) break
    rust
    use sdk::ctx::EventExt; fn main() { let acct = ctx::subscribe(exchange, ctx::SubOpts::private()).unwrap(); let Ok(t) = exchange.GetTicker("BTC_USDT") else { return }; let cid = format!("demo{}", UnixNano() / 1_000_000); let opts = format!(r#"{{"via":"ws","tif":"ioc","clientId":"{}"}}"#, cid); let id = match ctx::order(exchange, "BTC_USDT", "buy", _N(t.Sell * 1.001, 2), 0.001, &opts) { Ok(id) => id, Err(e) if e.contains("order state unknown") => { Log!("state unknown, check the order by clientId", cid); // 不要重复下单 return; } Err(e) => { Log!("order failed:", e); return; } }; let t0 = Unix(); while Unix() - t0 < 10 { match ctx::poll(&[acct.id()], Some(1000)) { ctx::Polled::Event(ev) => { if let Some(f) = ev.fill().filter(|f| f.order_id == id) { let fee = format!("{:?}", f.fee); // None:交易所未提供手续费 Log!("fill", f.trade_id, f.px, f.qty, f.liquidity, "fee:", fee, f.fee_ccy); } else if let Some(o) = ev.order().filter(|o| o.id == id) { if o.state == "filled" || o.state == "canceled" { Log!("order done:", o.state, "filled:", o.filled_qty, "avgPx:", o.avg_px); break; } } } ctx::Polled::Stopped => break, _ => {} } } }

返回值

类型描述

string / object

成功时返回交易所的订单号,与私有流订单回报中的id及成交回报中的orderId一致。失败时不抛出异常,而是返回Error对象,其message为失败原因。

参数

名称类型必填描述

ex

object / number

是

下单账户:交易所对象(exchange、exchanges[1]等),或该账户在exchanges数组中的下标(也可传入数字字符串"0")。不支持传入账户标签。

symbol

string

是

品种代码,例如BTC_USDT、BTC_USDT.swap,格式说明见品种代码。

side

string

是

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

px

number

是

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

qty

number

是

委托数量,必须大于0,计量口径与该交易所通过REST接口下单时一致(期货为合约张数或币数;部分交易所的现货市价买单为计价币金额),详见各交易所页面。

options

object

否

下单选项{type, tif, reduceOnly, postOnly, extra, clientId, via, timeout},所有字段均可省略,具体说明见下文。

参考

备注

options支持的字段:

字段说明
type订单类型:limit(默认,限价单)、market(市价单)
tif有效期类型:gtc(默认)、ioc、fak、fok、postOnly
reduceOnly是否只减仓,默认false
postOnly是否只做maker,默认false
extra交易所专属参数,原样透传给交易所
clientId客户端订单号,原样透传给交易所,最长64字节。通过WebSocket下单且未指定时,按交易所要求的格式自动生成
via下单通道:rest(默认)、ws(交易所的WebSocket交易接口)
timeout等待交易所应答的超时时间(毫秒),不传或传0时使用默认值

options只接受上表所列字段:包含未知字段(例如拼写错误的reduceonly)时不会下单,而是返回错误,不会忽略该字段。条件单与改单不使用本函数,请参见exchange.CreateConditionOrder、exchange.ModifyOrder。

失败时不抛出异常,一律通过返回值报告:参数有误、交易所拒单、触发限频或网络失败时均返回Error对象,绝不会返回虚假的订单号。使用返回值前,请先用instanceof Error判断。

via为ws时,通过交易所的WebSocket交易接口下单:

  • 仅支持WebSocket下单的交易所可用,目前包括币安现货与U本位合约、OKX现货与合约、Bybit现货与合约(模拟盘不支持)、Gate.io现货与永续合约、Bitget现货与合约,具体以各交易所页面的说明为准。不支持的交易所返回错误,不会自动改用REST接口下单。
  • 每个账户使用一条独立的交易连接,在首次WebSocket下单时建立。每笔WebSocket订单都携带客户端订单号,未指定clientId时自动生成。
  • 若请求发出前交易连接不可用(未连接或未登录),自动改用REST接口下单。
  • 若请求发出后未收到应答(超时、连接中途断开或交易所返回执行状态未知),会按客户端订单号查询一次订单,查到即视为成功;仍无法确认时,返回message以order state unknown (clientId ...)开头的错误。此时订单可能已提交到交易所:不要重复下单,应按客户端订单号查询订单,或等待私有流的订单回报确认。
  • 交易所的下单频率限额通常与REST接口共用;超出限额时直接返回限频错误,不会排队等待,也不会改用REST接口。

调用会阻塞当前线程,直到收到交易所的应答(一次往返)。如需同时发出多笔订单,或不希望阻塞等待,请使用ctx.orderAsync。下单前无需订阅;如需接收订单状态变化和成交信息,请用ctx.subscribe订阅private频道,订单回报(kind为16)和成交回报(kind为19)的字段说明见ctx.poll。

在Python中为ctx.order(ex, symbol, side, px, qty, opts=None),opts为字典,字段相同;成功时返回订单号字符串,失败时返回CtxError对象(不抛出异常),可用isinstance(r, CtxError)判断。在Rust中为ctx::order(ex, symbol: &str, side: &str, px: f64, qty: f64, opts_json: &str) -> Result<String, String>,选项以JSON字符串传入(例如r#"{"via":"ws"}"#),无选项时传"{}";失败时返回Err,不会panic。