更新模型与生命周期

同步推进、快照、变化检测、线程和资源释放。

本页目录

一个实例,一条更新循环

ExApi(token, account=None) 提供同步 API。所有调用必须在创建实例的线程中执行,不能在运行中的 asyncio 事件循环里直接调用。SDK 的内部 I/O 由同步调用推进,长时间 CPU 计算或阻塞业务代码会延迟更新和故障检查。

with ExApi(token) as api:
    quote = api.watch_quote(symbol)
    bars = api.watch_kline(symbol, "1m")
    while api.wait_update():
        # 在同一次提交上检查多个观察对象。
        if quote.is_changing("last_price"):
            consume_quote(quote.data())
        if bars.is_changing():
            consume_bars(bars.data())

示例中的 consume_quote、consume_bars 是你的业务函数,SDK 不提供这些方法。需要多策略时自行设计调度,不要跨线程共享同一个实例,也不要给每个句柄各写一层无限循环。

wait_update 的语义

wait_update(deadline=None) -> bool 等待并发布下一批用户可见更新;到达调用方指定的绝对期限且没有更新时返回 False。无期限时可能持续等待。SDK 错误通过异常报告,不用 False 表示致命错误。

它也负责推进连接恢复、CTP 同步及交易回报。创建观察句柄不代表已有可交易的、最新的数据。

data 返回独立快照

  • Quote、资金、持仓、订单、成交均通过快照读取;保存的快照不随未来 wait_update() 改变。
  • K 线返回独立 pandas DataFrame,带有 attrs["symbol"] 与 attrs["period"]。在快照上增加指标列不会保留到下一次 data()。
  • 持仓、订单、成交返回只读 Mapping,即使指定了单个合约,也不是单个对象。
  • 断线时仍保留最后一次快照。数据存在不等于有效;交易先检查 trading_status(),行情先检查 timestamp。

is_changing 检查最近一次提交

is_changing(key=None):不传字段检查对象变化;字符串检查单字段;字符串列表检查其中任意字段变化。K 线使用列名,例如 "timestamp"、"close"。集合句柄可按对象字段检查,成员增减也属于集合变化。

if quote.is_changing(["last_price", "volume"]):
    current = quote.data()
    print(current.last_price, current.volume)

同一合约多次订阅行情返回同一句柄。K 线按 (symbol, period, data_length) 区分句柄;不同长度是不同窗口。仅使用观察句柄的方法,不访问 _quotes、_serials 等私有结构。

清理资源

优先使用 with ExApi(...) as api:。也可以在 try/finally 中调用 api.close()。关闭释放资源,不会撤销已提交委托。如有未结束订单,退出前依据业务规则明确处理,而不是认为关闭连接等于撤单。

创建实例后跨线程、关闭后继续使用,或在 asyncio 事件循环里调用同步 API,属于使用方式错误,可能直接抛出 RuntimeError。使用独立线程运行同步程序时,必须在那个线程里创建、使用并关闭整个实例。

接口说明依据 exsdk 1.1.2 的公开接口与本地使用指南整理。