6.8 KiB
6.8 KiB
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 约束
正T(LONG_T) |
反T(SHORT_T) |
|
|---|---|---|
| 开仓腿 | 买入(低吸) | 卖出(高抛) |
| 平仓腿 | 卖出(高抛) | 买入(低吸) |
| 触发位置 | 现价 ≤ 建仓价×(1−zt_t_band_pct%) |
现价 ≥ 建仓价×(1+zt_t_band_pct%) |
| 买入腿约束 | 可用资金 | — |
| 卖出腿约束 | 底仓可卖数量(can_use_volume) |
底仓可卖数量 |
A股 T+1 决定了正T 能否当天闭环:当天买入的份额当天不可卖,所以正T 的平仓腿 只能卖底仓原有可用量。卖不动就自然留成隔夜持仓,次日再卖——这正是"允许隔夜" 存在的原因。
触发条件
- 正T 开仓:现价低于中性带下沿,且
DipWatch反弹确认(不接下跌中的飞刀)。 - 反T 开仓:现价高于中性带上沿,且盈利网格出现回撤(
GridTrailingTracker报RETREAT),不追最高点。 - 反T 平仓:现价 ≤ 卖出均价×(1−
zt_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,一只证券一条记录,整文件原子替换。
关键字段:kind、phase、open_date、base_qty/base_cost/base_source、
两条腿各自的 order_id/plan_qty/filled_qty/amount、seen_deal_ids、
last_trade_date。
- 成交按
order_sys_id幂等累计:重复同步不会重复计入,跨日重启靠seen_deal_ids记住已成交多少。 - 订单号统一
zt-前缀(zt-base-/zt-entry-/zt-exit-)。手工单、IPO 单 和其他策略单不带该前缀,一律不进入本策略轮次。 - 文件损坏时备份为
.corrupt并由券商持仓重建,不阻断启动。
委托与容错
- 撤单只限
zt-前缀,超时 300 秒;撤单不会丢轮次状态——余量会让轮次回到OPEN,下一轮按新价重新判断。 - 防重以券商在途委托为唯一依据(同证券同方向有在途委托就不下单)。
- 先落盘意图再发请求:请求未受理且无成交的轮次会被判为作废,已受理的委托 仍在途、成交照常累计,两种崩溃点都能自愈。
- 单证券异常只跳过该证券;账户快照、轮次推进、行情任一失败只跳过本轮,下轮重试。
迁移
旧账本 zt_{account_id}_state.db 与 libs/state.py 已删除,不再读写;旧库保留为
审计记录。不接管账户已有持仓:升级后只有本策略新建立的底仓会进入轮次,
老持仓保持不动。