前言
国内期货量化实盘里,程序通过天勤 TqSdk(Python 期货量化 SDK)连上期货公司账户:主循环不断调用 api.wait_update() 收行情和交易回报;当 5 分钟 K 线均线等信号触发时,用 TargetPosTask.set_target_volume(n) 表达目标净持仓,天勤在后续 wait_update 里向交易所报单,真实成交由柜台回报写入内存。
除程序自动交易外,团队往往还维护一份本地「成交台账」------每笔成交的价格、手数、对应哪根 K 线信号------用来复盘滑点、对账和合规留痕。常见事故是:台账记今天开了 7 笔、合计 7 手,快期客户端和 get_position().pos 却显示 10 手,价格和成交号对不上。漏记多发生在:只在 insert_order 或 set_target_volume 当下 print 一笔、没监听成交回报;主循环里 time.sleep 或同步 HTTP 阻塞期间成交到了却没处理;进程重启后内存里的 known 集合丢失,旧成交被跳过或重复记。
天勤在 api.get_trade() 里给出账户成交全集,委托对象上还有 trade_records 属性。下面说明如何用柜台真相实时回灌台账、日终如何对账。
一、成交数据从哪来
| 来源 | 说明 |
|---|---|
api.get_trade() |
账户成交全集,key 为成交号 |
order.trade_records |
该委托下的成交 dict |
get_position().pos |
净持仓真相 |
Trade 对象含 price、volume、datetime、order_id 等(见 objs.py)。
二、实时监听写法
python
trades = api.get_trade()
known = set()
while True:
api.wait_update()
for tid, t in api.get_trade().items():
if tid in known:
continue
known.add(tid)
log_trade(
trade_id=tid,
symbol=t.instrument_id,
price=t.price,
volume=t.volume,
order_id=t.order_id,
dt=t.datetime,
)
不要假设成交发生在 set_target_volume 同一行;TargetPosTask 的成交在后续 wait_update 里陆续到达。
三、日终对账流程
wait_update()收齐尾包。- 导出
get_trade()当日成交,按datetime过滤。 - 与本地 jsonl 按
trade_id外连接,找 only_in_ctp / only_in_local。 - 用
get_position与成交汇总推理论净仓,与pos比较。
python
def reconcile_trades(api, local_ids):
ctp_ids = set(api.get_trade().keys())
missing_local = ctp_ids - local_ids
missing_ctp = local_ids - ctp_ids
return missing_local, missing_ctp
漏记补进本地账,重复记删 duplicate。
四、与 order 状态配合
order.status == FINISHED 且 volume_left == 0 时,应用 trade_records 核对总成交量是否等于 volume_orign - volume_left。部分成交长期 ALIVE 时,以 trade_records 累加为准更新本地进度。
五、多账户
TqMultiAccount 下成交归属不同 account,筛选时按 trade 对象上的账户字段或分账户调用 get_trade(以你本地 API 文档为准)。
六、重启后如何不重不漏
进程重启时 known 清空,不能对 get_trade() 全量再记一遍。启动后第一轮应:
- 加载本地已有
trade_id集合。 - 对
get_trade()里已存在的 id 只标记为 known,不写新日志。 - 仅对 diff 出的新 id 追加。
python
known = load_trade_ids_from_disk()
for tid in api.get_trade().keys():
known.add(tid) # 启动快照,不记日志
while True:
api.wait_update()
for tid, t in api.get_trade().items():
if tid not in known:
known.add(tid)
persist_trade(t)
append_trade_id(tid)
七、与滑点记账衔接
每笔成交日志建议同时写 signal_price(若当时有)与 trade.price,日终算滑点分布。漏记成交会直接污染滑点统计,导致回测校准偏乐观。trade_records 里多笔 partial fill 要按时间排序再与信号 join。
八、监管留痕最低字段
成交行建议含:trade_id、order_id、instrument_id、direction、offset、price、volume、datetime、strategy_version。与委托留痕里的 last_msg 分开存,纠纷时能还原「报单---成交」链条。
总结
成交回报漏记会让日志仓位与柜台分叉,重启后还可能重复开仓。天勤 get_trade 与 order.trade_records 提供成交全集,应在每次 wait_update 后 diff 新 trade_id 写日志,日终再与本地台账对账。以 get_position().pos 为最终真相,成交日志为解释路径,这套习惯对监管留痕和纠纷复盘都管用。
FAQ
1)get_trade 会清空吗?
进程内累积;重启后重新拉全量。
2)模拟盘 trade_id 格式?
与实盘同类字段,可对账练手。
3)一笔委托多笔成交?
trade_records 多 key,volume 求和。
4)影子模式没 trade?
正常;只有 live/sim 有成交。
本文基于天勤 TqSdk 公开 API 整理,不构成投资建议。