11 KiB
QuantDinger 信号与执行标准(SSOT)
版本:1.0
状态:现行
适用范围:所有基于 IndicatorStrategy(指标 Python + 保存为策略)的回测与实盘
关联实现:BacktestService、TradingExecutor、validate_code_safety / verifyCode
开发指南:STRATEGY_DEV_GUIDE_CN.md(教程与示例)
1. 目的
平台会同时运行多种不同逻辑的策略。若没有统一标准,会出现:
- 同一套
buy/sell在不同策略里含义不同; - 回测按「收盘 + 下一根开盘」成交,实盘按「未收盘 K + 立即平仓」执行;
- 指标内止盈止损与
# @strategy trailingEnabled叠加,导致重复平仓与拒单。
本标准定义:策略作者写什么、引擎如何解释、回测与实盘必须如何对齐。
所有新策略 SHOULD 遵循;存量策略 SHOULD 按第 9 节迁移。
2. 术语
| 术语 | 含义 |
|---|---|
| 信号 K 线 | 产生布尔信号的那根 K 线(时间戳 = 该 bar 收盘时刻) |
| 成交 K 线 | 订单实际执行所锚定的 K 线(默认 = 信号 K 的下一根) |
| 边缘触发 | 仅在与上一根 K 相比由 false→true 时记为信号 |
| 重绘 | 未收盘 K 上条件随行情变化而反复成立/消失 |
| 退出负责人 | 唯一主导平仓逻辑的层:指标信号 或 引擎风控,不可并列窄规则 |
3. 策略形态选型(必须先选)
| 形态 | 适用 | 不适用 |
|---|---|---|
A. 简单两路 buy / sell |
金叉/死叉、单方向或对称反转;无独立「仅平仓」语义 | 多空分离 tp/sl、状态机、同 bar 先平后开需写清 |
B. 专业四路 open_long / close_long / open_short / close_short |
状态机、触及止盈止损、多空分离、与回测队列一一对应 | 极简趋势(可用 A,但 B 更利于长期维护) |
C. ScriptStrategy on_bar + ctx |
强依赖持仓、分批、冷却、bot 网格 | 纯历史序列可表达的指标信号 |
平台推荐默认值:新上架、多空或带指标内退出的策略 → 形态 B(四路)。
4. 信号输出标准(IndicatorStrategy)
4.1 通用 MUST
- MUST
df = df.copy()作为首行可变操作。 - MUST 提供
output字典(含name、plots;signals可选用于图表标记)。 - MUST 执行列与
len(df)一致、类型为bool(fillna(False).astype(bool))。 - MUST 对执行列做边缘触发(见 4.3),除非策略说明中明确声明「连续持仓信号」并经产品审核。
- MUST NOT 使用
shift(-1)及任何未来数据引用。 - MUST NOT 在单脚本内混用「形态 A 执行列」与「形态 B 执行列」作为成交依据(可同时保留
buy/sell全 false 仅作兼容)。
4.2 形态 A:两路 buy / sell
tradeDirection |
buy=True 含义 |
sell=True 含义 |
|---|---|---|
long |
开多 | 平多 |
short |
平空 | 开空 |
both |
开多;若持空则先平空再开多 | 开空;若持多则先平多再开空 |
MUST NOT 在 both 下把 buy 理解为「仅平空」或「仅平多」。
若需只平仓不反手,MUST 使用形态 B 的 close_*。
4.3 形态 B:四路(推荐标准)
| 列 | 含义 |
|---|---|
open_long |
开多(或加多,若引擎配置允许) |
close_long |
平多(全部或按 reduce 配置) |
open_short |
开空 |
close_short |
平空 |
MUST 满足:
- 四列均存在且为 bool。
- SHOULD 同 bar 优先级:
close_*先于open_*(脚本内互斥或交给引擎「先平后开」)。 - SHOULD NOT 同 bar 同时
open_long与open_short为 true(反手请用close_*+ 对侧open_*,或分两根 K)。 - 使用四路时,引擎按显式信号处理(非 buy/sell 的 both 隐式映射)。
边缘触发模板:
def edge(s: pd.Series) -> pd.Series:
s = s.fillna(False).astype(bool)
return s & ~s.shift(1).fillna(False)
df['open_long'] = edge(raw_open_long)
df['close_long'] = edge(raw_close_long)
df['open_short'] = edge(raw_open_short)
df['close_short'] = edge(raw_close_short)
output['signals'] 仅用于展示;成交只认上述执行列。
4.4 tradeDirection 与四路的关系
tradeDirection |
行为 |
|---|---|
long |
忽略 open_short / close_short(或校验警告) |
short |
忽略 open_long / close_long |
both |
四路均有效;不再对 buy/sell 做反手映射 |
5. 退出与风控标准(解决重复平仓)
每个策略 MUST 在说明或注释中声明「退出负责人」之一:
| 模式 | 脚本 | # @strategy |
说明 |
|---|---|---|---|
指标退出 exit_owner: indicator |
输出 close_*,或两路中明确等价的退出语义 |
trailingEnabled false;不要依赖 stopLossPct / takeProfitPct / trailing |
触及型、中轨/轨道 tp/sl;当前实现会关闭服务端价格退出 |
引擎退出 exit_owner: engine |
只输出入场,或只输出趋势反转用的结构性 close_* |
trailingEnabled / stopLossPct / takeProfitPct 按需 |
固定止损止盈、追踪止损、简单趋势 |
MUST NOT:指标内窄 tp/sl 且 trailingEnabled true 窄移动止损(易造成 server_trailing_stop 后再发 close_* → 数量为 0)。
启用 trailing 时:SHOULD 关闭指标内同方向的 tp/sl 布尔列,或关闭 trailing。
当前后端只支持 exit_owner: indicator 与 exit_owner: engine。不要生成或上架 exit_owner: layered;若确实需要“指标退出 + 引擎兜底”的混合方案,必须先产品评审并明确改造执行器语义。
6. 执行契约(回测与实盘对齐)
以下配置在「保存后的策略」trading_config 中生效;回测与实盘 MUST 使用同一套规范化结果。
6.1 信号时刻(抗重绘)
| 项 | 标准值 | 说明 |
|---|---|---|
signal_mode |
confirmed |
入场信号仅来自上一根已收盘 K |
exit_signal_mode |
confirmed |
出场信号同上;与回测一致 |
| 形成中 K | 不参与下单 | 实盘可刷新最后一根 K 做展示,但不应作为默认成交依据 |
MAY 在产品层提供 aggressive 供研究;上线组合策略 SHOULD NOT 默认 aggressive。
6.2 成交时刻
| 项 | 标准值 |
|---|---|
回测 signalTiming / 策略快照 |
next_bar_open(默认) |
| 语义 | 信号 K 收盘确认 → 下一根 K 开盘价(±滑点)成交 |
SHOULD NOT 在未改回测配置的情况下,实盘使用 exit_trigger_mode=immediate 做指标策略。
6.3 同 bar 多信号
| 规则 | 说明 |
|---|---|
| 优先级 | close_* > reduce_* > open_* > add_* |
| 反手 | 方案 R1(推荐):同 bar 只平不開,下一根再 open_*;方案 R2:同 bar 先平后开(与历史 both 回测一致,需策略与回测均启用) |
| 每 tick | 指标模式默认每 tick 最多执行 1 个外部信号;反手若用 R2,引擎可在单次 open_* 内先平对侧 |
策略说明 MUST 注明采用 R1 或 R2。
6.4 平仓数量
| 规则 | 说明 |
|---|---|
| 数量来源 | 平仓 MUST 以本地持仓与交易所持仓较大者为准(sync + resolve) |
| 数量为 0 | MUST 再 sync 一次后重试;仍为空则拒单并记日志,MUST NOT 静默跳过 |
7. 配置标准(# @strategy / # @param)
7.1 # @strategy(SHOULD 显式声明)
| Key | 类型 | 说明 |
|---|---|---|
tradeDirection |
long | short | both |
与执行列一致 |
entryPct |
0.01–1.0 | 开仓资金占比(1 = 100%) |
stopLossPct / takeProfitPct |
0–1 | 标的涨跌幅阈值;亚 1% 写 0.001 等小数 |
trailingEnabled |
bool | 见第 5 节 |
trailingStopPct / trailingActivationPct |
0–1 | 追踪回撤/激活阈值(同为价格涨跌幅,不除杠杆) |
MUST NOT 在 @strategy 中写 leverage(由产品 UI / 策略配置)。
7.2 推荐策略头注释块(复制模板)
# --- QuantDinger execution contract (v1) ---
# signal_form: four_way # two_way | four_way
# exit_owner: indicator # indicator | engine
# flip_mode: R1 # R1=close bar then open next bar | R2=same bar flip
# tradeDirection: both
# @strategy entryPct 1
# @strategy trailingEnabled false
8. 校验与发布清单
8.1 保存 / verifyCode 时(引擎 SHOULD)
- 执行列存在且长度正确
- 禁止不安全代码(见
safe_exec) - 警告:
trailingEnabled+ 高比例close_* - 警告:同 bar
open_long&open_short - 警告:连续多根同向
open_*无 edge(可选启发式)
8.2 上线前人工清单
- 已选形态 A/B/C 并写在策略说明
- 已声明退出负责人
signal_mode/exit_signal_mode=confirmed- 回测成交时间为 next bar open,与预期一致
- 对比最近 20 笔:回测信号时间 vs 实盘日志时间偏差可解释
- 小仓位、单标的试跑 24h,无大量
invalid amount (0.0)
9. 存量策略迁移
| 优先级 | 特征 | 动作 |
|---|---|---|
| P0 | both + buy 含 tp/sl + trailingEnabled |
关 trailing 或改四路 close_* |
| P1 | 触及型逻辑 + 实盘差异大 | 改 confirmed + 四路 + edge |
| P2 | 纯金叉死叉两路 | 可保留形态 A,补全契约注释 |
| P3 | 已是四路 | 补 edge、退出负责人、配置对齐 |
MAY 在策略市场标注「契约 v1 已认证」徽章,便于用户筛选。
10. 策略分级(运营可选)
| 等级 | 要求 |
|---|---|
| L1 基础 | 通过 verifyCode + 沙箱 |
| L2 对齐 | 四路或声明两路 + confirmed + 退出负责人明确 |
| L3 生产 | L2 + 回测/实盘时间偏差评审 + 7 日模拟盘无异常拒单 |
11. 与实现的对照(便于研发)
| 标准条 | 代码锚点 |
|---|---|
| 形态 B 四路 | TradingExecutor._execute_indicator_with_prices;BacktestService norm_signals |
| both 两路映射 | 仅当无四路且 buy/sell 时;_indicator_both_mode |
| confirmed | signal_mode / exit_signal_mode 检查集 |
| 平仓重试 | PendingOrderWorker + resolve_reduce_only_quantity |
| 静态安全 | app/utils/safe_exec.py |
标准变更时 MUST 同步更新本文件版本号与 CHANGELOG。
12. 修订记录
| 版本 | 日期 | 说明 |
|---|---|---|
| 1.0 | 2026-05 | 首版:四路推荐、执行契约、退出负责人、迁移与分级 |