Skip to content

PTrade get_snapshot 大约 3 秒一帧

很多人把 get_snapshot 当「此刻盘口」。实盘里它更像录像里抽出来的一帧:大约 3 秒 才换得动。中间那两秒,快照里经常还是上一帧。

tick_data 也是这个节拍。循环再快,只读快照,读到的仍可能是同一张截面。3 秒卡的是回调和快照,不是逐笔。只谈数据口径,不构成投资建议。

两路数据,别绑在同一个 if 里

拿到什么常见节拍
tick_data进函数的机会大约 3 秒一次
get_snapshot最新价、五档、部分队列跟回调差不多
get_individual_entrust逐笔委托循环多快,就能拉多快
get_individual_transaction逐笔成交同上

最初的写法是:快照该更新了,才去拉逐笔。结果循环跑得再快,逐笔也被 3 秒门闩卡住。

快照按自己的时间戳更新;逐笔每轮都拉,不要写在「快照更新了」那个 if 里面。

python
cur = hs_timestamp_to_seconds(now_ts)
last = hs_timestamp_to_seconds(last_snap_ts)
if (cur - last) >= 3.1 or not snap:
    snap = get_snapshot(codes)
    last_snap_ts = snap_hs_timestamp(snap)

entrust = get_individual_entrust(stocks=codes, data_count=200, start_pos=0, search_direction=1)
trans = get_individual_transaction(stocks=codes, data_count=200, start_pos=0, search_direction=1)

对齐靠时间戳,不靠 sleep。快照常见 hsTimeStamp,逐笔常见 business_time。按墙钟过了 3 秒、快照没换帧,状态机已经往前走,日志会看起来像行情变了,其实是旧截面。

3 秒窗口里自己拉逐笔

平台大约 3 秒才再进一次 tick_data。要补两帧之间的变化,在这一次回调里把窗口跑满,不要等下一帧。快照该 3 秒还是 3 秒。

python
def tick_data(context, data):
    for stock in watch_list:
        if stock not in high_freq:
            continue
        n = 0
        while n < 15:  # 15 × 200ms ≈ 3 秒
            get_individual_entrust(stocks=[stock], data_count=200,
                                   start_pos=0, search_direction=1)
            get_individual_transaction(stocks=[stock], data_count=200,
                                       start_pos=0, search_direction=1)
            n += 1
            if n < 15:
                time.sleep(0.2)

最后一轮不要再 sleep,避免拖过窗口、和下一次 tick_data 叠在一起。已经处理完的代码马上 break,别空转满 15 次。

另一种是开盘后在 handle_data 里自己循环。一定要判断交易时段,并加防重入,否则午休、收盘还在转,或同一策略开两条循环。窗口用完就还控制权更稳。

全市场每 200 毫秒拉一遍逐笔,进程先胀死。常见拆法:快照 3 秒一轮只做粗筛,进监控池之后才对那几只拉逐笔。

截窗口、去重、缩池

逐笔是追加的。concat 不截、不去重,盯的代码一多,几分钟 DataFrame 就胀起来。

python
old = g.entrust_data
tmp = pd.concat([g.entrust_data, new_df], ignore_index=True)
tmp = tmp.drop_duplicates(keep='last')
g.entrust_data = filter_recent(tmp, seconds=10)
del old, tmp
  1. 只对当前真正在盯的代码拉逐笔
  2. 长时间没有新事件的,移出订阅
  3. 拼完立刻丢掉旧引用

空表不要当成「这一秒没单」。更常见是没开 Level-2,或回测环境根本没有逐笔。先打日志确认权限。

沪深字段不是同一套

同一件「这笔是撤」,两边落在不同表、不同字段:

  • 沪市:多在逐笔委托里看类型
  • 深市:多在逐笔成交里看标志;成交价为 0 的记录不能当普通成交去加总

手数、金额、队列如果混用,总量会对不上快照里的委托量。回测、研究、交易三套环境也不一样。用分钟线补出来的「近似逐笔」验不了实盘对齐。

建议顺序

  1. 连续两次 get_snapshothsTimeStamp、两次 tick_data 到底隔几秒
  2. 逐笔单独拉、单独去重、单独截窗口
  3. 沪深字段分开解析,空数据和权限失败分开打日志
  4. 最后才接任何决策层

把循环 sleep 改成 0.2 秒、判断还只读快照,等于更频繁地读同一帧。

相关:get_snapshot · API 查询 · 热门问题