期货 K 线算信号 tick 级止损:天勤双序列 wait_update 触发规则

前言

国内期货趋势量化里,开仓信号多在 K 线上算:天勤程序 get_kline_serial("DCE.m2509", 300) 订豆粕 5 分钟线,均线金叉时 TargetPosTask.set_target_volume(5) 开多。止损若也等下一根 K 线收盘才检查,夜盘一波急杀时,可能要等 5 分钟才发现亏损扩大,比 tick 级止损多滑很多个最小变动价位。去年改一条豆粕策略:开仓逻辑在 K 线,止损改到 tick(或 quote.last_price)触发,回撤明显收敛,代价是主循环要分清「谁有权改 target」。

天勤允许同一 TqApi 里同时订 get_kline_serialget_tick_serial,共用 api.wait_update() 收包。下面说明 K 线管开仓、tick 管止损的触发分工,避免两者同帧打架。

一、两个序列各自负责什么

序列 API 触发粒度 适合逻辑
K 线 get_kline_serial(symbol, duration_seconds, data_length) 新 bar 开仓、加减仓信号
Tick get_tick_serial(symbol, data_length) 每笔成交聚合 止损、移动止盈

get_tick_serial 返回 tick 表,含 datetimelast_pricevolume 等(以 objs.py 为准)。tick 表也会随 wait_update 更新,用 is_changing(ticks.iloc[-1], "datetime") 判断新 tick。

二、主循环结构示意

原则:开仓权在 K 线,平仓权可拆给 tick;同一帧只应有一个模块写 target。

python 复制代码
klines = api.get_kline_serial(SYMBOL, 300, data_length=500)
ticks = api.get_tick_serial(SYMBOL, data_length=2000)
task = TargetPosTask(api, SYMBOL, price="ACTIVE")

target = 0
entry_price = None
stop_price = None

while True:
    api.wait_update()

    # K 线:新 bar 算信号(用已收盘 bar)
    if api.is_changing(klines.iloc[-1], "datetime"):
        bar = klines.iloc[-2]
        signal = calc_signal(klines)  # 你的均线/突破逻辑
        if signal == 1 and target <= 0:
            target = 3
            entry_price = bar["close"]
            stop_price = entry_price - 2 * quote.price_tick * 10
            task.set_target_volume(target)

    # Tick:仅在有仓时检查止损
    if target != 0 and api.is_changing(ticks.iloc[-1], "datetime"):
        last = ticks.iloc[-1]["last_price"]
        if target > 0 and last <= stop_price:
            target = 0
            task.set_target_volume(0)
        elif target < 0 and last >= stop_price:
            target = 0
            task.set_target_volume(0)

quoteapi.get_quote(SYMBOL) 提前取得,用于 price_tick

三、常见坑

  1. tick 止损与 K 线反向信号同帧触发:应定优先级,通常止损优先于开新仓。
  2. 未用 is_changing 过滤,每个包都扫 tick,CPU 升高。
  3. data_length 太小,tick 表被截断,极端行情下指标辅助字段丢失。
  4. 停盘期间 tick 不更新,止损应暂停或改用 last_price 快照规则。
  5. 同一合约混用 insert_orderTargetPosTask,tick 层改 target 后 task 状态错乱。

四、止损价维护

移动止损可在 tick 分支更新 stop_price,但不要每 tick 调 set_target_volume;只有触发击穿时才调仓。若用 ATR 止损,ATR 仍建议用 K 线算,tick 只比较价格与阈值。

五、回测与实盘差异

TqBacktest 对 tick 精度取决于订阅与回测设置;K+tick 双序列在回测里能跑通,但 tick 级止损的成交假设仍比实盘理想。应用 TqSim 对价模式试一轮,记录止损滑点。

六、用 quote.last_price 的轻量替代

若觉得 get_tick_serial 订阅太重,可以只对交易品种 get_quote,在止损分支判断 api.is_changing(quote, "last_price")。这在不少商品上足够驱动止损,但要注意:行情推送频率低于真实 tick 时,止损会有延迟。股指等高频品种仍建议 tick 表。

python 复制代码
quote = api.get_quote(SYMBOL)
while True:
    api.wait_update()
    if target > 0 and api.is_changing(quote, "last_price"):
        if quote.last_price <= stop_price:
            target = 0
            task.set_target_volume(0)

七、状态机:避免双写 target

维护显式状态 FLAT / LONG / STOPPING 比仅用 target 整数更安全。进入 STOPPING 后忽略 K 线开仓信号,直到 pos 确认为 0 再回 FLAT。这能避免 tick 止损与 K 线反向信号同帧打架。

状态 允许 K 线开仓 允许 tick 止损
FLAT
LONG/SHORT 否(除非加仓规则)
STOPPING

总结

K 线算信号、tick 管止损,是国内期货程序化里很常见的分工。天勤允许在同一 TqApi 里并行 get_kline_serialget_tick_serial,靠 wait_update 统一收包,用 is_changing 把两种触发拆开;开仓逻辑放在新 K 线,止损逻辑放在新 tick,且避免双写 target。把优先级和停盘过滤写清楚,比单纯把止损周期改成 1 分钟 K 线更接近真实风控意图。

FAQ

1)tick 数据量很大怎么办?

缩小 data_length,止损只关心最新价;或用 is_changing(quote, "last_price") 替代全表扫描。

2)能否只用 quote 不用 tick_serial?

可以,get_quotelast_price 更新也能驱动止损,粒度取决于行情推送频率。

3)多品种怎么订?

每个交易品种各一对 serial;watch 列表外的品种不要订 tick。

4)反手算开仓还是止损?

建议拆成先平后开两帧,由 task 自动处理开平顺序。


本文基于天勤 TqSdk 公开 API 整理,不构成投资建议。

相关推荐
m0_738120721 小时前
HVV应急溯源基础——Linux 系统安全加固配置指南(一)
linux·运维·服务器·安全·网络安全·系统安全
武子康1 小时前
调查研究-167 Docker Compose 详解:从单容器到多服务编排的工程化入口
运维·docker·云原生·容器·kubernetes·k8s·docker-compose
聆春烟雨簌簌1 小时前
LangChain4j使用文档
开发语言·python
RisunJan1 小时前
Linux命令-perl (perl语言解释器)
linux·perl
belong_my_offer1 小时前
在Pycharm中安装conda的保姆级教学
python
github_czy1 小时前
更加优雅的类型检查与传参---mcp源码分析
java·服务器·开发语言
CTA终结者1 小时前
期货量化合约代码写错:天勤 symbol 格式与 silent 订阅坑
python·区块链
c_lb72881 小时前
期货程序化撤单改价后仓位乱了:cancel_order 与 TargetPosTask 协作
python
如烟花的信页2 小时前
加速乐cookie逆向分析
javascript·爬虫·python·js逆向