Files
big-qmt/docs/zt.md
2026-09-15 20:02:05 +08:00

6.8 KiB
Raw Blame History

ZT 日内做 T 策略

正T先买后卖与反T先卖后买共用一套轮次状态机。持仓数量、可卖数量、 成本一律以券商快照为准;本地只记录"打算做什么、做到哪一步",不重算持仓。

启用

在账户 YAML 中设置:

strategy: zt
signal_allow: ["dcm"]      # zt 只接受 dcm
zt_open_hands: 1           # 建仓与正T买入的手数0 表示不启动策略
zt_sell_ratio: 0.5         # 反T卖出建仓数量的比例
zt_buy_fall_pct: 1.0       # 反T买回较卖出均价回落的百分比
zt_max_price: 200          # 高于此价不新开轮次
zt_t_band_pct: 1.0         # 中性带:建仓价 ±N% 内不动手
zt_max_hold_days: 5        # 单轮最长持有自然日,超期放弃

只管自己建的仓

本策略不接管账户已有持仓。 只有建仓腿由本策略成交、在轮次表里留下 base_source=opened 基准的证券才会被管理:

  • 账户里其它持仓原样保留,既不写基准、也不做 T日志里以 [ZT跳过] 未接管持仓 N 只…[ZT汇总] … 未接管=N … 体现;
  • 建仓只能由 dcm 信号触发(signal_allow),建仓成交均价即建仓价;
  • 升级时如果状态文件里还留着旧版本的"接管"记录,启动会丢弃它们 (已结束的轮次删掉,未平轮次保留到敞口处理完),保证这条规则成立。

两种 T 与 T+1 约束

正TLONG_T 反TSHORT_T
开仓腿 买入(低吸) 卖出(高抛)
平仓腿 卖出(高抛) 买入(低吸)
触发位置 现价 ≤ 建仓价×(1zt_t_band_pct%) 现价 ≥ 建仓价×(1+zt_t_band_pct%)
买入腿约束 可用资金
卖出腿约束 底仓可卖数量can_use_volume 底仓可卖数量

A股 T+1 决定了正T 能否当天闭环当天买入的份额当天不可卖所以正T 的平仓腿 只能卖底仓原有可用量。卖不动就自然留成隔夜持仓,次日再卖——这正是"允许隔夜" 存在的原因。

触发条件

  • 正T 开仓:现价低于中性带下沿,且 DipWatch 反弹确认(不接下跌中的飞刀)。
  • 反T 开仓:现价高于中性带上沿,且盈利网格出现回撤(GridTrailingTrackerRETREAT),不追最高点。
  • 反T 平仓:现价 ≤ 卖出均价×(1zt_buy_fall_pct%),且反弹确认。
  • 正T 平仓:现价 ≥ 买入均价×(1+grid_step_pct%)。
  • 平仓腿不受中性带限制正T 开仓受大盘与资金闸门反T 开仓(减仓)不受资金限制。

数量

计划量 上限
建仓 / 正T 买入 zt_open_hands × 100 本轮剩余可用资金,向下取整手
正T 卖出 买入已成交量 底仓可卖量,向下取整手
反T 卖出 floor(建仓数量 × zt_sell_ratio / 100) × 100 底仓可卖量
反T 买回 卖出已成交量 本轮剩余可用资金

同一轮 tick 内串行处理所有证券,共享一份剩余资金,不会重复花同一笔钱。 资金买不起一手时返回 0不会强迫成交。

轮次与每日限额

状态机:IDLE → OPENING开仓腿在途→ OPEN待平仓→ CLOSING平仓腿在途→ CLOSED

  • 一只证券任意时刻最多一个未平轮次。
  • 每天最多一轮:当天开过、或有任一条腿成交过,都不再开新轮。
  • 允许隔夜:OPEN / CLOSING 可以跨日持有,不做尾盘强平。
  • 超过 zt_max_hold_days 自然日仍未平仓 → 告警并把未平敞口并回底仓数量 base_cost 仍是建仓价),避免在裸敞口上继续开新轮。

建底仓与基准成本

  • 底仓只能由 dcm 信号触发建仓,成交均价写入 base_cost base_source=opened);账户已有持仓不会被接管,因此基准只有这一个来源。
  • base_cost 不随做 T 买卖摊薄;超期放弃时未平敞口并回 base_qty base_cost 保持不变。

日志

所有日志都带方括号标签,直接 grep 即可定位:

标签 内容
[ZT启动] 启动参数、状态文件路径、未平轮次明细、信号列表
[ZT成交] 逐笔成交入账(腿、数量、价格、编号、累计量、均价);被忽略的非本策略成交
[ZT状态] 轮次阶段流转
[ZT轮次] 一轮结束:结局、买卖均价、价差收益、基准、持有天数、备注
[ZT决策] 每只受管证券每轮一行:现价、基准、偏离%、类型、阶段、敞口、可卖、持仓成本、最终动作或等待原因
[ZT下单] 实际提交的委托(数量、价格、目标价、订单号)
[ZT跳过] 未接管的账户持仓、排除证券、行情无效
[ZT汇总] 本轮账户概览:持仓/管理/新委托数、总资产、可用、大盘与资金闸门、耗时
[ZT异常] 被捕获并降级的错误(含堆栈)

排查常见问题:

grep '\[ZT决策\] 600000.SH' 20260915.log     # 某只证券每轮为什么没动手
grep '\[ZT下单\]' 20260915.log               # 今天实际报出去的委托
grep '\[ZT轮次\]' 20260915.log               # 每轮的结果与价差收益
grep '\[ZT跳过\]' 20260915.log | tail -1     # 哪些账户持仓没被接管
grep '\[ZT异常\]' 20260915.log               # 被降级的错误

状态文件

{qmt_data_dir}/zt_{account_id}_rounds.json,一只证券一条记录,整文件原子替换。 关键字段:kindphaseopen_datebase_qty/base_cost/base_source、 两条腿各自的 order_id/plan_qty/filled_qty/amountseen_deal_idslast_trade_date

  • 成交按 order_sys_id 幂等累计:重复同步不会重复计入,跨日重启靠 seen_deal_ids 记住已成交多少。
  • 订单号统一 zt- 前缀(zt-base- / zt-entry- / zt-exit-。手工单、IPO 单 和其他策略单不带该前缀,一律不进入本策略轮次。
  • 文件损坏时备份为 .corrupt 并由券商持仓重建,不阻断启动。

委托与容错

  • 撤单只限 zt- 前缀,超时 300 秒;撤单不会丢轮次状态——余量会让轮次回到 OPEN,下一轮按新价重新判断。
  • 防重以券商在途委托为唯一依据(同证券同方向有在途委托就不下单)。
  • 先落盘意图再发请求:请求未受理且无成交的轮次会被判为作废,已受理的委托 仍在途、成交照常累计,两种崩溃点都能自愈。
  • 单证券异常只跳过该证券;账户快照、轮次推进、行情任一失败只跳过本轮,下轮重试。

迁移

旧账本 zt_{account_id}_state.dblibs/state.py 已删除,不再读写;旧库保留为 审计记录。不接管账户已有持仓:升级后只有本策略新建立的底仓会进入轮次, 老持仓保持不动。