前言
有同事做短线过滤时一口气订了 tick,策略 CPU 直接拉满,信号却没更准。本文说的 get_tick_serial 是天勤 TqSdk 的 tick 序列订阅接口(TqApi.get_tick_serial()),不是不能用,而是要想清楚:你的策略到底需不需要每一笔成交。多数分钟级或「只在盘口明显变化时反应」的逻辑,用 tick 订阅可以,但必须做降频和触发收敛。
我用一个「盘口变化 + 分钟趋势过滤」的小框架举例,说明怎么订 tick、怎么和 K 线时钟对齐,以及怎么避免 tick 风暴拖垮主循环。
一、先定策略粒度:你到底要不要 tick
| 需求 | 更合适的订阅 |
|---|---|
| 分钟趋势 + 盘中过滤 | K 线为主,tick 辅助 |
| 盘口微观结构 | tick 为主,严格降频 |
| 仅成交确认 | 不必全量 tick |
下面示例属于第一类:5 分钟趋势定方向,tick 只在买卖盘变化时检查是否允许开仓。
判断是否需要 tick 的一个简单标准:如果你的持仓周期小于 3 根 K 线,且决策依赖盘口变化,可以考虑 tick;否则先用 K 线 + quote 往往更划算。很多「订了 tick 却没用到微观信息」的策略,CPU 成本是纯浪费。
二、最小订阅与变化触发
from tqsdk import TqApi, TqAuth, TqSim, TargetPosTask
api = TqApi(TqSim(), auth=TqAuth("账户", "密码"))
symbol = "DCE.m2509"
tick = api.get_tick_serial(symbol)
kl = api.get_kline_serial(symbol, 300, data_length=200)
q = api.get_quote(symbol)
task = TargetPosTask(api, symbol)
def trend_bias(df):
ma10 = df.close.rolling(10).mean().iloc[-2]
ma30 = df.close.rolling(30).mean().iloc[-2]
if ma10 > ma30:
return 1
if ma10 < ma30:
return -1
return 0
while True:
api.wait_update()
# 只在 tick 变化时做盘口检查,避免空转
if not api.is_changing(tick.iloc[-1], "last_price"):
continue
bias = trend_bias(kl)
if bias == 0:
continue
# 盘口过滤:买卖价差过大时不下
spread = q.ask_price1 - q.bid_price1
if spread <= 0 or spread > 3: # 阈值按品种调
continue
task.set_target_volume(bias)
核心不是「有 tick 就算」,而是 is_changing(tick) 收窄触发面。
这段代码里 trend_bias 仍建议在 K 线换根时缓存,不要每个 tick 都重算均线。否则 tick 再降频,指标层仍在高频计算,性能瓶颈只是从「下单」挪到了「算指标」。
三、tick 与 K 线时钟不要混用
常见错误:用 tick 更新次数当 K 线 bar 计数,导致一分钟内重复调仓十几次。建议:
- 趋势方向只在 K 线换根时更新
- tick 层只做过滤或微调
- 调仓动作加冷却时间或 bar 级状态锁
import time
last_trade_ts = 0
COOLDOWN_SEC = 60
# 在下单前
now = time.time()
if now - last_trade_ts < COOLDOWN_SEC:
continue
# 通过过滤后再 set_target_volume
last_trade_ts = now
冷却时间可以和 bar 级锁叠加使用:bar 锁保证「一根 K 线最多一次方向判断」,冷却保证「即使盘口抖动也不会连发」。两层一起用,重复下单概率会再降一截。
四、性能诊断:先量化再优化
上线前临时加统计(上线可改 DEBUG):
import time
n, t0 = 0, time.time()
while True:
api.wait_update()
n += 1
if time.time() - t0 > 10:
print("wait_update/10s:", n)
n, t0 = 0, time.time()
若 10 秒内 wait_update 上万次,要么 tick 太密,要么订阅过多合约。先减订阅,再谈算法优化。
还可以加一项「每帧计算耗时」统计。若 wait_update 次数正常但耗时高,瓶颈在 pandas 滚动或日志 IO;若次数异常高,瓶颈在订阅粒度和触发条件。先定位再优化,避免盲目改参数。
五、和纯 K 线策略如何取舍
如果策略持仓周期在 15 分钟以上,多数情况下只订 K 线更稳。tick 适合:
- 需要盘口价差过滤
- 需要成交瞬间确认
- 需要微观止损
不要为了「看起来更高级」而订 tick,性能成本会反噬收益。
若策略最终只在少数时段需要 tick,可以按时段动态订阅:白盘活跃段开启,午休或夜盘低波动段退回纯 K 线。这样比全天 tick 更省资源,也更符合实际交易节奏。
总结
天勤 get_tick_serial 的价值在于提供更细的市场切片,但策略工程上必须先做触发收敛。盘口变化驱动的过滤框架,关键是 tick 负责「何时检查」,K 线负责「方向判断」,下单层再加冷却和状态锁。这样既能用到 tick 信息,又不容易把主循环拖进高频空转。
长期维护时,建议把 tick 相关逻辑封装成独立模块,并写清楚「启用条件」。团队后续扩容品种或改周期时,能一眼判断该不该上 tick,避免性能问题在规模扩大后才集中爆发。
FAQ
1)tick 和 quote 都要订吗?
看需求。价差过滤用 quote 往往够;要成交序列细节才订 tick。
2)data_length 设多少?
够算过滤指标即可,tick 序列不宜过长,避免内存压力。
3)能否 tick 驱动 K 线策略?
可以,但要加 bar 级锁,避免一分钟内多次调仓。
4)夜盘 tick 更密怎么办?
提高过滤阈值或延长冷却,必要时夜盘单独参数。
5)回测里怎么验证 tick 逻辑?
先在模拟盘跑,回测若不支持同等粒度,要单独评估执行差异。
风险提示
本文用于期货量化技术实践讨论,不构成任何投资建议。高频触发策略对成本和延迟敏感,请在可承受风险范围内验证。

211

被折叠的 条评论
为什么被折叠?



