Subscription.positions
读取私有订阅根据推送维护的最新持仓,仅适用于channel为private的订阅。
positions()示例
订阅私有流,在快照就绪后以及每次持仓变化时输出全部持仓。
javascript
function main() {
var acct = ctx.subscribe(exchange, {channel: "private"})
while (true) {
var ev = ctx.poll([], 1000)
if (!ev || ev.stream !== acct.id) {
continue
}
var ready = ev.kind === 35 && ev.prefillStatus === 1
if (ready || (ev.channel === "positions" && !ev.snapshot)) {
var positions = acct.positions()
if (positions === null) {
continue // 账户快照尚未就绪
}
positions.forEach(function(p) {
Log(p.symbol, p.posSide, "qty:", p.qty, "avgPx:", p.avgPx, "profit:", p.profit)
})
}
}
}
python
def main():
acct = ctx.subscribe(exchange, {"channel": "private"})
while True:
ev = ctx.poll([], 1000)
if ev is None or ev.stream != acct.id:
continue
ready = ev.kind == 35 and ev.prefillStatus == 1
if ready or (ev.channel == "positions" and not ev.snapshot):
positions = acct.positions()
if positions is None:
continue # 账户快照尚未就绪
for p in positions:
# 交易所未推送的金额字段不在字典中,需用get读取
profit = p.get("profit")
Log(p.symbol, p.posSide, "qty:", p.qty, "avgPx:", p.avgPx, "profit:", profit)
rust
use sdk::ctx::EventExt;
fn main() {
let acct = ctx::subscribe(exchange, ctx::SubOpts::private()).unwrap();
loop {
match ctx::poll(&[], Some(1000)) {
ctx::Polled::Event(ev) if ev.stream() == acct.id() => {
if ev.channel() != "private" && ev.channel() != "positions" {
continue;
}
match acct.positions() {
Ok(Some(rows)) => {
for p in rows {
Log!(p.symbol, p.pos_side, "qty:", p.qty, "avgPx:", p.avg_px);
}
}
Ok(None) => {} // 账户快照尚未就绪
Err(e) => panic!("positions failed: {e}"),
}
}
ctx::Polled::Stopped => break,
_ => {}
}
}
}返回值
| 类型 | 描述 |
array / 空值 | 持仓数组,每个元素表示一个持仓槽当前的完整状态,按品种和持仓槽排序;账户快照尚未就绪时返回空值。 |
参考
备注
数组元素的字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| symbol | string | 品种代码,例如BTC_USDT.swap |
| side | string | buy(多头)或sell(空头) |
| posSide | string | 持仓槽:双向持仓模式下为long或short,单向持仓模式下为net |
| qty | number | 持仓数量,单位与exchange.GetPositions相同 |
| avgPx | number | 持仓均价 |
| profit、margin、liqPx、markPx、leverage | number | 未实现盈亏、保证金、强平价格、标记价格、杠杆倍数;交易所未推送时不包含该字段 |
| time | number | 交易所更新时间(毫秒);交易所未提供时不包含该字段 |
已平仓(数量为0)的持仓不会出现在数组中。
返回空值表示状态未知,而非没有持仓:订阅后,需等到该事件流上收到channel为private、prefillStatus为1的初始化状态事件后才有数据;最近一次快照失败时(例如断线重连后快照请求失败)也返回空值,直到下一次快照就绪。现货账户没有持仓,就绪后返回空数组。
托管者根据推送的持仓事件(kind为17)更新这份状态,因此需要持续调用ctx.poll获取事件。实时推送是否包含持仓因交易所而异,部分交易所仅在订阅时和重连后提供快照,详见各交易所页面的说明。如需可靠的最新持仓,仍可使用exchange.GetPositions查询,该函数始终请求REST接口,不依赖推送。
对非私有订阅调用,或在订阅对象已退订后调用,会抛出异常。
Rust中为sub.positions() -> Result<Option<Vec<ctx::PositionRow>>, String>,Ok(None)表示快照尚未就绪;PositionRow的字段为symbol、side、pos_side、qty、avg_px、profit、margin、liq_px、mark_px、leverage、time(金额与时间字段为Option类型)。Python中为sub.positions(),返回字典列表(字段同上,也支持属性访问写法),快照尚未就绪时返回None。