45 KiB
策略自动化框架
RaptorBT v0.5.0+ 内置的 AI 友好策略自动化框架
RaptorBT 策略自动化框架覆盖从策略开发到交付的完整流程:
scaffold 生成模板 → 编写信号逻辑 → optimize 参数优化
→ walkforward 验证 → acceptance 验收 → deliver 生成交付包
设计目标:让 AI agent 能自主完成策略研发、优化、验证、交付的全流程,无需人工干预。
目录
- 快速开始
- CLI 命令参考
- 策略框架 (strategies/)
- CSV 数据加载器 (data_loader.py)
- 参数优化器 (optimizer.py)
- Walk-Forward 验证 (walk_forward.py)
- 验收检查 (acceptance.py)
- 策略模板生成器 (scaffold.py)
- 交付包导出 (exporter.py)
- 前视偏差防护 (lookahead_check.py)
- 自定义指标库 (indicators.py)
- 指标目录 (indicator_catalog.py)
- AI agent 集成指南
快速开始
环境准备
# 1. 安装依赖
pip install -r requirements.txt
# 2. 设置 Mt5Bridge (可选, 用于最终验证)
set MT5_BRIDGE_URL=http://61.164.252.86:13485
set MT5_BRIDGE_KEY=your-api-key
编译 RaptorBT 引擎 (换电脑必读)
策略自动化框架依赖 raptorbt 原生扩展。项目已内置 vendor/ferro-ta-main/(80+ 指标的 Rust 源码,随项目提交),换电脑或部署新环境后只需按以下步骤编译:
前置依赖:
| 依赖 | 版本 | 说明 |
|---|---|---|
| Rust toolchain | 1.70+ | cargo、rustc(从 https://rustup.rs 安装) |
| Python | 3.10+ | 与编译时 Python 版本一致 |
| maturin | latest | pip install maturin,Rust → Python 扩展构建工具 |
vendor/ferro-ta-main/ |
— | 已随项目提交,Cargo.toml 通过 path 引用,无需联网拉取 |
编译方式:
# 方式 A: 构建 whl 包 (推荐, 全局安装)
maturin build --release
# 产物: target/wheels/raptorbt-0.4.1-cp312-cp312-win_amd64.whl
pip install --force-reinstall target/wheels/raptorbt-*.whl
# 方式 B: 虚拟环境开发模式 (需先激活 venv/conda)
maturin develop --release
# 编译到 python/raptorbt/_raptorbt.*.pyd
⚠️
maturin develop需要虚拟环境:必须在已激活的 venv/conda 环境中运行,否则会报 "Couldn't find a virtualenv or conda environment"。全局安装请用maturin build+pip install方式。
💡 可移植性保障:Cargo.toml 中
ferro_ta_core通过path = "vendor/ferro-ta-main/crates/ferro_ta_core"引用源码,vendor/ 目录必须随项目提交(已在 .gitignore 中注明不可忽略)。换电脑 clone 项目后无需联网拉取外部 crate,直接maturin build --release即可编译。
数据准备
框架支持两种数据源,默认使用 CSV 离线数据(适合策略研究):
- CSV(默认):把 MT5 History Center / quant data manager 导出的 M1 CSV 放到项目根目录的
data/目录。文件名需包含品种代码(如XAUUSD)和时区信息(如UTCPlus02),加载器会自动识别品种、时区并重采样到目标周期。spread 列会自动转为 slippage。 - Mt5Bridge:用
--source mt5切换,从远程 MT5 拉取实时数据。适合最终策略验证,不建议用于参数搜索阶段。
# data/ 目录示例
# data/2021.7.6-2026.07.03M1XAUUSD_TICK_UTCPlus02.csv
# data/2021.7.6-2026.07.03M1EURUSD_TICK_UTCPlus02.csv
python -m app.main list # 会自动列出 data/ 下可用的 CSV 品种
30 秒体验
# 列出所有策略
python -m app.main list
# 生成一个 RSI 策略模板
python -m app.main scaffold --name my_rsi --template mean_reversion
# 优化 SMA 交叉策略参数 (默认用 CSV 离线数据)
python -m app.main optimize --strategy sma_cross \
--param fast=5,10,15 --param slow=20,30,40 --export
# 生成完整交付包
python -m app.main deliver --strategy sma_cross \
--param fast=5,10 --param slow=20,30
CLI 命令参考
1. list — 列出所有策略 / 可用指标
python -m app.main list # 列出策略
python -m app.main list --indicators # 列出所有可用指标 (80 个)
python -m app.main list --indicators --json # JSON 结构化输出 (供 AI agent 解析)
| 参数 | 默认 | 说明 |
|---|---|---|
--indicators |
false | 列出所有可用指标及签名 (供 AI agent 查询) |
--json |
false | 输出 JSON (供 AI agent 解析) |
输出示例 (策略):
可用策略 (4 个):
════════════════════════════════════════════════════════════
atr_stop_rr SMA(10/20) 交叉 + 2.0×ATR(14) 止损 + 2.0:1 风险回报止盈
rsi_mean_reversion RSI(14) 均值回归, 买入<30.0/卖出>70.0, 3% 追踪止损
sar_adx_cci SAR(0.02/0.2) + ADX(14)>25.0 + CCI(20)±100.0, 2.5×ATR 止损/4% 止盈
sma_cross SMA(10)/SMA(20) 双均线交叉, 2% 止损/4% 止盈
════════════════════════════════════════════════════════════
输出示例 (指标 --indicators):
可用指标目录 (80 个)
════════════════════════════════════════════════════════════
调用方式: import raptorbt; raptorbt.<name>(numpy_array, ...)
输入约定: close/high/low/open/volume 都是 float64 numpy array
── 趋势 (8 个) ──
sma(close, period)
→ 1 array
简单移动平均, 最基础的趋势指标
...
── 动量 (13 个) ──
...
💡 AI agent 开发策略前建议先
list --indicators --json,获取 80 个指标的完整签名、输入需求、默认值和返回值结构,详见 指标目录 章节。
2. run — 运行单个策略
python -m app.main run --strategy sma_cross \
--symbol XAUUSD --timeframe H1 --bars 500 --export
| 参数 | 默认 | 说明 |
|---|---|---|
--strategy |
(必填) | 策略名称 |
--symbol |
XAUUSD | 交易品种 |
--timeframe |
H1 | K 线周期 |
--bars |
500 | K 线数量 |
--source |
csv | 数据源 (csv 离线 / mt5 实时) |
--data-file |
None | 显式指定 CSV 文件路径 (默认按 symbol 自动查找) |
--export |
false | 导出 CSV 结果 (trades/curves/metrics) |
--json |
false | 输出 JSON (含 metrics + 前 50 条 trades, 供 AI agent 解析) |
3. compare — 对比所有策略
python -m app.main compare --symbol XAUUSD --bars 500 --export
在相同数据上跑所有策略,输出对比表格。
4. optimize — 参数网格搜索
python -m app.main optimize --strategy sma_cross \
--param fast=5,10,15,20 --param slow=20,30,40,50 \
--metric sharpe_ratio --symbol XAUUSD --bars 1000 --export
| 参数 | 默认 | 说明 |
|---|---|---|
--param |
(必填,可多次) | 参数空间,格式 name=v1,v2,v3 |
--metric |
sharpe_ratio | 优化目标指标 |
--export |
false | 导出完整响应面到 CSV |
--json |
false | 输出 JSON (含 best_params + Top 10 组合, 供 AI agent 解析) |
支持的 metric:sharpe_ratio、total_return_pct、max_drawdown_pct(最小化)、profit_factor、win_rate_pct、sortino_ratio 等。
5. walkforward — Walk-Forward 验证
python -m app.main walkforward --strategy sma_cross \
--param fast=5,10 --param slow=20,30 \
--bars 1000 --train-size 300 --test-size 100 --export
| 参数 | 默认 | 说明 |
|---|---|---|
--train-size |
300 | 训练窗口大小 (bars) |
--test-size |
100 | 测试窗口大小 (bars) |
--export |
false | 导出逐窗口明细到 CSV |
--json |
false | 输出 JSON (含逐窗口 IS/OOS 明细, 供 AI agent 解析) |
输出包含:IS/OOS 夏普对比、衰减比、过拟合判定、参数稳定性分布。
6. validate — 策略验收
python -m app.main validate --strategy sma_cross \
--param fast=5,10 --param slow=20,30 --bars 1000
执行 Walk-Forward + 三层盈利优先验收标准检查(L1 盈利性必须 / L2 风险可控 / L3 健壮性),输出通过/失败判定。
| 参数 | 默认 | 说明 |
|---|---|---|
--json |
false | 输出 JSON (含 lookahead + walk_forward + acceptance, 供 AI agent 解析) |
💡 失败诊断:当某条标准未通过时,输出会附带该标准的
suggestions修复建议(每条标准 5 条具体可执行建议,按 L1/L2/L3 分级)。L1 失败时建议是根本性调整(换策略/换品种),不要在参数上浪费时间。AI agent 可直接读取建议决定下一步调整方向。详见 验收检查 章节。
7. scaffold — 生成策略模板
python -m app.main scaffold --name my_rsi \
--template mean_reversion \
--description "RSI 超卖反弹策略"
| 参数 | 默认 | 说明 |
|---|---|---|
--name |
(必填) | 策略名称 (snake_case) |
--template |
custom | 模板类型 |
--description |
"" | 策略描述 |
--overwrite |
false | 覆盖已存在文件 |
模板类型:
crossover— 均线交叉 (SMA)mean_reversion— RSI 均值回归trend_following— ADX 趋势跟踪breakout— Donchian 通道突破custom— 空白模板
8. deliver — 生成交付包
python -m app.main deliver --strategy sma_cross \
--param fast=5,10 --param slow=20,30 \
--symbol XAUUSD --bars 1000
一键执行:优化 → Walk-Forward → 验收 → 导出交付包。
| 参数 | 默认 | 说明 |
|---|---|---|
--json |
false | 输出 JSON (含 lookahead + optimization + walk_forward + acceptance + package_path) |
⚠️ 强制前视检测:deliver 在执行前会强制运行前视偏差静态扫描,若检测到 HIGH 级别前视模式(如
.shift(-N)、负索引访问未来 bar),会拒绝生成交付包,JSON 中delivered=false且error字段说明原因。详见 前视偏差防护 章节。
9. check — 前视偏差检测 ★
# 静态扫描所有策略
python -m app.main check --strategy all
# 静态扫描 + 动态验证单个策略 (修改未来 bar, 看历史信号是否变化)
python -m app.main check --strategy sma_cross --dynamic \
--symbol XAUUSD --timeframe H1 --bars 500
| 参数 | 默认 | 说明 |
|---|---|---|
--strategy |
(必填) | 策略名称,或 all 扫描所有策略 |
--dynamic |
false | 启用动态扰动验证(修改未来 bar,检查历史信号是否变化) |
--symbol |
XAUUSD | 品种(动态验证用) |
--timeframe |
H1 | 周期(动态验证用) |
--bars |
500 | K 线数量(动态验证用) |
--source |
csv | 数据源 |
--data-file |
None | CSV 文件路径 |
--json |
false | 输出 JSON (单个策略含 issues + fix_suggestions; all 含所有策略汇总) |
输出示例(检测到前视):
🔴 L27: 使用 .shift(-N) 访问未来 bar, 这是明确的前视偏差
...future_close = df["close"].shift(-1)...
总结: ❌ 未通过
策略框架 (strategies/)
Strategy 基类
所有策略继承 Strategy 基类(位于 strategies/base.py):
class Strategy(ABC):
name: str # 策略唯一标识
@abstractmethod
def warmup_bars(self) -> int:
"""返回指标预热所需的最小 bar 数"""
@abstractmethod
def generate_signals(self, df: pd.DataFrame) -> SignalResult:
"""根据 K 线数据生成入场/出场信号"""
@abstractmethod
def build_config(self) -> raptorbt.PyBacktestConfig:
"""构建回测配置 (止损/止盈/资金/费率)"""
def description(self) -> str:
"""策略描述 (用于 list 和报告)"""
SignalResult
@dataclass
class SignalResult:
entries: np.ndarray # bool 数组, True=入场
exits: np.ndarray # bool 数组, True=出场
direction: int = 1 # 1=做多, -1=做空
extra: dict = None # 可选: 附加指标数据
内置辅助方法
# 交叉信号
entries = self.cross_above(ma_fast, ma_slow) # fast 上穿 slow
exits = self.cross_below(ma_fast, ma_slow) # fast 下穿 slow
# 预热期处理 (预热期内的信号置 False)
entries, exits = self.apply_warmup(entries, exits)
自动注册机制
strategies/__init__.py 实现自动发现:扫描 strategies/ 目录下所有 .py 文件,若文件中定义了 STRATEGY_CLASS 常量,则自动注册。
新增策略只需 3 步:
- 在
strategies/下创建.py文件 - 继承
Strategy实现子类 - 在文件末尾添加
STRATEGY_CLASS = YourStrategy
无需修改任何注册代码,python -m app.main list 立即可见。
完整策略示例
"""my_strategy — 我的策略描述"""
from __future__ import annotations
import numpy as np
import raptorbt
from .base import Strategy, SignalResult
class MyStrategy(Strategy):
"""我的策略描述"""
name = "my_strategy"
def __init__(self, period: int = 14, threshold: float = 30.0):
self.period = period
self.threshold = threshold
def warmup_bars(self) -> int:
return self.period + 1
def generate_signals(self, df) -> SignalResult:
close = df["close"].values.astype(np.float64)
rsi = raptorbt.rsi(close, period=self.period)
entries = (rsi < self.threshold).astype(bool)
exits = (rsi > 70).astype(bool)
entries, exits = self.apply_warmup(entries, exits)
return SignalResult(
entries=entries, exits=exits, direction=1,
extra={"rsi": rsi},
)
def build_config(self) -> raptorbt.PyBacktestConfig:
config = raptorbt.PyBacktestConfig(
initial_capital=100000.0, fees=0.001, slippage=0.0005,
)
config.set_fixed_stop(0.02)
config.set_fixed_target(0.04)
return config
def description(self) -> str:
return f"RSI({self.period}) < {self.threshold} 入场"
STRATEGY_CLASS = MyStrategy
CSV 数据加载器 (data_loader.py)
app/data_loader.py 加载 MT5 History Center / quant data manager 导出的 M1 CSV,支持自动品种识别、时区处理、多周期重采样、spread→slippage 自动转换。
CSV 格式
加载器期望 9 列无表头格式(MT5 History Center 标准):
date,time,open,high,low,close,vol,vol_real,spread
2021.07.06,01:00,1791.37,1791.37,1790.55,1791.27,25850.0,25850.0,98
| 列 | 说明 |
|---|---|
| date / time | 日期和时间,格式 YYYY.MM.DD / HH:MM |
| open / high / low / close | OHLC |
| vol | tick volume |
| vol_real | real volume(加载时丢弃) |
| spread | 点差点数(自动转 slippage) |
文件名约定
文件名应包含品种代码和时区,加载器自动解析:
2021.7.6-2026.07.03M1XAUUSD_TICK_UTCPlus02.csv
^^^^^ ^^^^^^^^
品种 时区 UTC+2
- 品种识别:内置 17 个常见品种(XAUUSD、EURUSD、USDJPY 等),按长度降序匹配,避免子串误匹配。
- 时区识别:从
UTCPlusNN/UTCMINUSNN提取,未识别时默认 UTC。 - 自动查找:
find_csv_for_symbol("XAUUSD")优先匹配M1文件,回退到任意匹配。
多周期重采样
加载 M1 后可重采样到 13 种周期:
from app.data_loader import load_csv
# 加载并重采样到 H1
df = load_csv("data/XAUUSD.csv", symbol="XAUUSD", timeframe="H1")
支持周期:M1、M5、M15、M30、H1、H2、H4、H6、H8、H12、D1、W1、MN1。
重采样规则(pandas 风格,label="left", closed="left"):
open= 窗口第一根high= 窗口最高low= 窗口最低close= 窗口最后一根tick_volume= 求和spread= 平均
spread → slippage 自动转换
CSV 模式下,fetch_klines 会自动计算 slippage 并注入 PyBacktestConfig:
slippage = (avg_spread × tick_size) / avg_price
示例:XAUUSD avg_spread=98、tick_size=0.01、avg_price=1791 → slippage ≈ 0.000547 (0.055%)。
内置 17 个品种的 tick_size 配置(SYMBOL_TICK_SIZE 字典)。未识别品种回退到 0.0001。
Python API
from app.data_loader import (
load_csv, find_csv_for_symbol, compute_slippage,
list_available_symbols, get_tick_size,
)
# 1. 自动查找 + 加载
path = find_csv_for_symbol("XAUUSD") # 在 data/ 下查找
df = load_csv(path, timeframe="H1")
# 2. 显式指定文件
df = load_csv("data/XAUUSD.csv", symbol="XAUUSD", timeframe="H1")
# 3. 列出所有可用品种
for symbol, filename in list_available_symbols():
print(symbol, filename)
# 4. 单独计算 slippage
slippage = compute_slippage(df["spread"], df["close"], "XAUUSD")
周末数据处理
quant data manager 导出的外汇 CSV 已自动过滤周末(外汇市场周六周日休市),因此 load_csv 默认 drop_weekend=False。若你的 CSV 含周末数据(如加密货币),调用时传 drop_weekend=True:
df = load_csv("data/BTCUSD.csv", timeframe="H1", drop_weekend=True)
返回 DataFrame 列:time、open、high、low、close、tick_volume、spread。time 列为带时区的 datetime64[ns, tz]。
参数优化器 (optimizer.py)
app/optimizer.py 提供策略参数网格搜索。
Python API
from app.optimizer import StrategyOptimizer
from strategies.sma_cross import SmaCrossStrategy
opt = StrategyOptimizer(metric="sharpe_ratio")
result = opt.optimize(
strategy_class=SmaCrossStrategy,
df=df,
param_grid={"fast": [5, 10, 15], "slow": [20, 30, 40]},
symbol="XAUUSD",
)
print(result.best_params) # {"fast": 10, "slow": 30}
print(result.best_score) # 1.234
print(result.summary()) # 优化完成: 9 个组合, ...
print(result.top_n(5)) # 前 5 个参数组合 DataFrame
result.export("optimization.csv") # 导出完整响应面
优化方向
sharpe_ratio、total_return_pct、profit_factor、win_rate_pct→ 最大化max_drawdown_pct→ 最小化- 其他指标自动推断方向
错误恢复
优化器内置错误恢复:参数组合导致 0 信号或回测异常时,记录 error 字段但不中断搜索,对应 metric 设为 NaN。
Walk-Forward 验证 (walk_forward.py)
app/walk_forward.py 提供滚动窗口验证。
验证流程
数据: |----train1----|--test1--|----train2----|--test2--|----train3----|--test3--|
每个窗口:
- 在
train上跑参数优化 → 得到最优参数 (IS) - 用最优参数在
test上回测 → 得到 OOS 指标 - 记录 IS/OOS 对比
Python API
from app.walk_forward import WalkForwardValidator
from strategies.sma_cross import SmaCrossStrategy
wf = WalkForwardValidator(train_size=300, test_size=100)
result = wf.validate(
strategy_class=SmaCrossStrategy,
df=df,
param_grid={"fast": [5, 10], "slow": [20, 30]},
metric="sharpe_ratio",
)
print(result.is_sharpe_avg) # IS 平均夏普
print(result.oos_sharpe_avg) # OOS 平均夏普
print(result.decay_ratio) # 衰减比 OOS/IS
print(result.is_overfit) # 是否过拟合 (< 0.5)
print(result.param_stability) # 参数频次分布
print(result.summary()) # 完整报告
result.export("walkforward.csv")
过拟合判定
- 衰减比 = OOS 平均夏普 / IS 平均夏普
- 衰减比 < 0.5 → 判定过拟合
- 衰减比 ≥ 0.5 → 非过拟合
参数稳定性
输出各参数值被选中的频次分布。若同一参数值在多个窗口被频繁选中,说明参数稳定;若参数值频繁变化,说明对数据过拟合。
验收检查 (acceptance.py)
app/acceptance.py 采用盈利优先三层结构的量化验收标准。
设计哲学
策略的最终目的是赚钱,不是为了优化指标而优化指标。
"当一个指标变成目标时,它就不再是好指标。" — Goodhart 法则
旧的"4 条平等标准"有一个根本问题:全部是过程质量指标,没有一条直接验证"是否赚钱"。这会导致两类误判:
- 假阳性:Sharpe=1.06 ✅、衰减比=3.0 ✅ 看似通过,但年化收益只有 2.5%(跑不赢通胀),根本没赚到钱
- 假阴性:PF=1.8、年化 25% 的策略因 Sharpe=0.8 被拒收(实际是赚钱策略,只是曲线不够平滑)
- 误导性通过:IS/OOS 都在亏损的策略,衰减比反而很高(3.09),这个"通过"毫无意义
新标准把盈利性(PF/收益/期望)放到 L1 必须层,先确认策略真的赚钱,再看风险和健壮性。
三层默认标准
| 层级 | 标准 | 阈值 | 说明 |
|---|---|---|---|
| L1 盈利性(必须) | oos_profit_factor_min |
1.3 | OOS 盈利因子下限(总盈利/总亏损多 30%) |
oos_return_min_pct |
0.0 | OOS 平均收益率下限(真赚到钱) | |
oos_expectancy_min |
0.0 | OOS 每笔期望值下限(平均每单为正) | |
| L2 风险可控(应该) | oos_max_drawdown_max_pct |
20.0 | OOS 最大回撤上限(%)(放宽原 15%) |
| L3 健壮性(建议) | oos_sharpe_min |
0.7 | OOS 夏普比率下限(放宽原 1.0,降为参考) |
oos_total_trades_min |
30 | OOS 总交易数下限(统计显著性) | |
is_oos_decay_min |
0.5 | IS/OOS 衰减比下限(非过拟合) |
判定逻辑:
passed = L1 全过 AND L2 全过 AND L3 全过(保持严格)l1_passed=False时直接拒收,不再看 L2/L3- 分层让 AI agent 一眼看出"问题严重程度",优先解决 L1
Python API
from app.acceptance import StrategyAcceptance
# 使用默认三层标准
checker = StrategyAcceptance()
report = checker.check(wf_result)
# 自定义标准 (可只覆盖某几条)
checker = StrategyAcceptance(criteria={
"oos_profit_factor_min": 1.5, # L1 更严格
"oos_max_drawdown_max_pct": 15.0, # L2 更紧
# 其他条目用默认值
})
report = checker.check(wf_result)
print(report.passed) # 总判定
print(report.l1_passed) # L1 盈利性是否全过 (最关键)
print(report.l2_passed) # L2 风险可控
print(report.l3_passed) # L3 健壮性
print(report.summary()) # 分层人类可读报告
验收报告(分层)
验收结果: ❌ 未通过 (L1 盈利性未达标 — 策略不赚钱, 无需看 L2/L3)
──────────────────────────────────────────────────────────────────────
[L1 盈利性] 必须 — 策略是否真的赚钱, 任一失败即拒收 ✗
──────────────────────────────────────────────────────────────────
OOS 盈利因子 阈值= 1.30 实际= 0.00 ✗
└ 总盈利/总亏损 = 0.00, < 阈值 1.3 (亏损或勉强盈利)
└ 修复建议:
1. 策略逻辑本身可能不盈利, 重新审视入场/出场条件是否真的捕捉到正向期望
2. 切换策略类型 (趋势跟踪在震荡市会持续亏 PF<1, 均值回归在趋势市会亏)
3. 切换品种或周期 (当前 XAUUSD M5 可能不适合本策略逻辑)
...
OOS 净收益率 阈值= 0.00 实际= -0.02 ✗
OOS 每笔期望 阈值= 0.00 实际= -119.53 ✗
[L2 风险可控] 应该 — 回撤是否在可接受范围 ✓
──────────────────────────────────────────────────────────────────
OOS 最大回撤 阈值= 20.00 实际= 0.46 ✓
[L3 健壮性] 建议 — 统计显著性和非过拟合, 参考性指标 ✗
──────────────────────────────────────────────────────────────────
OOS 夏普比率 阈值= 0.70 实际= -0.39 ✗
OOS 总交易数 阈值= 30.00 实际= 11.00 ✗
IS/OOS 衰减比 阈值= 0.50 实际= -21.01 ✗
└ OOS/IS = -2101.3%, 过拟合风险 (注意: 若 IS 也是亏损, 高衰减比不代表策略好)
──────────────────────────────────────────────────────────────────────
失败诊断建议(按层分级) ★
L1 失败的建议是根本性调整(换策略/换市场/换周期),不是小修小补;L2 是风控调整;L3 是统计性问题。
| 失败标准 | 层 | 建议方向 |
|---|---|---|
| OOS 盈利因子 < 1.3 | L1 | 重新审视信号逻辑、切换策略类型(趋势↔均值回归)、切换品种/周期、检查止损是否过紧、尝试反向信号 |
| OOS 净收益 ≤ 0 | L1 | 检查 IS 是否也亏(若也亏=逻辑问题)、评估交易成本侵蚀、减少交易频率、切换顺势品种/周期、反向信号 |
| OOS 每笔期望 ≤ 0 | L1 | 检查胜率×盈亏比、盈亏比失衡→放大止盈/追踪止损、胜率低→加过滤、止损过紧→放宽或换 ATR 止损 |
| OOS 最大回撤 > 20% | L2 | 收紧止损、ATR 动态止损、追踪止损、降仓位、加趋势过滤 |
| OOS 夏普 < 0.7 | L3 | 放宽止损、加趋势过滤、切大周期、加成交量过滤(注:已降为参考,L1 全过时可接受略低) |
| OOS 交易数 < 30 | L3 | 缩短指标周期、降低入场阈值、切更小周期、放宽过滤、检查 warmup |
| 衰减比 < 0.5 | L3 | 缩小参数空间、增加 WF 窗口数、简化策略、用中位数参数、检查前视 |
⚠️ 关键提示:衰减比高不代表策略好。若 IS 和 OOS 都在亏损,衰减比反而会很高(如 3.0),这个"通过"是假象。必须先看 L1 的 PF/收益/期望,L1 通过后衰减比才有意义。
JSON 输出
AcceptanceReport.to_dict() 返回分层结构的 JSON,CLI 加 --json 标志后直接输出:
{
"passed": false,
"l1_passed": false,
"l2_passed": true,
"l3_passed": false,
"verdict": "L1 盈利性未达标 — 策略不赚钱, 无需看 L2/L3",
"criteria": [
{
"name": "OOS 盈利因子",
"layer": "L1",
"layer_name": "盈利性",
"level": "必须",
"threshold": 1.3,
"actual": 0.0,
"passed": false,
"description": "总盈利/总亏损 = 0.00, < 阈值 1.3 (亏损或勉强盈利)",
"suggestions": [
"策略逻辑本身可能不盈利, 重新审视入场/出场条件是否真的捕捉到正向期望",
"切换策略类型 (趋势跟踪在震荡市会持续亏 PF<1, 均值回归在趋势市会亏)",
...
]
},
{
"name": "OOS 最大回撤",
"layer": "L2",
"layer_name": "风险可控",
"level": "应该",
"threshold": 20.0,
"actual": 0.46,
"passed": true,
"description": "低于最大回撤限制 20.0%",
"suggestions": []
}
]
}
AI agent 决策逻辑:
1. 调用 validate --json
2. 检查 l1_passed:
- False → 策略不赚钱, 不要在参数上浪费时间, 按 L1 suggestions 换策略逻辑/品种/周期
- True → 进入 L2/L3 检查
3. 检查 l2_passed: False → 按 L2 suggestions 调整风控 (止损/仓位)
4. 检查 l3_passed: False → 按 L3 suggestions 处理统计性问题
5. 全过 → deliver --json 生成交付包
💡 通过的标准
suggestions为空数组,未通过的才填充建议。NaN/Inf 已自动转为null。
策略模板生成器 (scaffold.py)
app/scaffold.py 生成符合框架约定的策略模板。
Python API
from app.scaffold import scaffold_strategy
# 生成 RSI 均值回归模板
path = scaffold_strategy(
name="my_rsi",
template="mean_reversion",
description="RSI 超卖反弹策略",
)
print(f"模板已生成: {path}")
# 覆盖已存在文件
path = scaffold_strategy(
name="my_rsi",
template="mean_reversion",
overwrite=True,
)
模板类型
| 模板 | 策略逻辑 | 适用场景 |
|---|---|---|
crossover |
SMA 双均线交叉 | 趋势市场 |
mean_reversion |
RSI 超卖买入/超买卖出 | 震荡市场 |
trend_following |
ADX + DI 方向确认 | 强趋势市场 |
breakout |
Donchian 通道突破 | 突破行情 |
custom |
空白模板 | 自定义逻辑 |
生成的模板已包含完整的 Strategy 子类骨架,包括 __init__、warmup_bars、generate_signals、build_config、description 和 STRATEGY_CLASS 常量。
交付包导出 (exporter.py)
app/exporter.py 生成完整的策略交付包。
Python API
from app.exporter import StrategyExporter
exporter = StrategyExporter()
pkg_path = exporter.deliver(
strategy_name="sma_cross",
df=df,
symbol="XAUUSD",
opt_result=opt_result,
wf_result=wf_result,
accept_report=accept_report,
param_grid={"fast": [5, 10], "slow": [20, 30]},
data_info={
"source": "Mt5Bridge",
"range": "2026-01-01 ~ 2026-06-30",
"bars": 1000,
"timeframe": "H1",
},
)
交付包结构
deliverables/{strategy_name}_{timestamp}/
├── {strategy_name}.py 策略源文件 (从 strategies/ 复制)
├── STRATEGY_REPORT.md 完整交付报告 (8 个章节)
├── optimization.csv 参数优化响应面
├── walkforward.csv Walk-Forward 逐窗口明细
└── backtest_metrics.csv 最优参数回测指标
Markdown 报告章节
- 策略概述 (名称/描述/标的/最优参数/预热期)
- 参数优化 (目标/组合数/Top 5 参数表)
- Walk-Forward 验证 (IS/OOS 对比/衰减比/过拟合判定/参数稳定性)
- 验收结果 (三层盈利优先标准/L1-L2-L3 分层)
- 最优参数完整回测指标
- 数据信息 (来源/范围/K 线数/周期)
- 风险提示 (5 条)
- 复现方式 (CLI 命令)
前视偏差防护 (lookahead_check.py)
app/lookahead_check.py 是防止 AI agent 在自动开发策略时引入前视偏差的核心防护层。两层防护:静态 AST 扫描 + 动态扰动验证。
为什么需要前视防护
前视偏差(look-ahead bias)是量化策略最隐蔽的 bug:策略生成信号时使用了未来才能获取的数据,回测结果虚高,实盘后立即崩溃。常见诱因:
.shift(-N)— 访问未来第 N 根 barclose[-1]/high[-1]— 负索引访问(numpy 从数组末尾取,等价于未来)df.iloc[i+N:]— 切片到未来索引rolling(...).mean().shift(-1)— 滚动统计后向未来偏移np.roll— 把末尾元素循环到开头(本项目曾因此 bug 修复)
静态扫描规则
11 条正则 + AST 检测,分三级严重度:
| 严重度 | 含义 | 示例 |
|---|---|---|
| 🔴 HIGH | 确定前视,拒绝交付 | .shift(-1)、close[-1]、iloc[i+10:] |
| 🟡 MEDIUM | 可疑模式,需人工确认 | future/lookahead 关键词、np.roll、.shift(0) |
| 🟢 LOW | 建议检查 | values[i + N] 基于索引访问 |
判定规则:只要存在 HIGH 级别问题就判定失败。
动态扰动验证
原理:策略只用过去 + 当前数据生成信号,所以修改未来 bar 不应影响历史信号。
1. 用原始数据生成基准信号 → base_entries[:N]
2. 修改 bar N+1..N+K 的 OHLC ±5% → 生成扰动信号 perturbed_entries[:N]
3. 比较 base_entries[:N] 与 perturbed_entries[:N]
4. 若有差异 → 存在前视偏差
参数:check_bars=50(检查前 50 根)、perturb_range=10(扰动 10 根未来 bar)。
Python API
from app.lookahead_check import (
check_strategy_code, check_strategy_file, check_all_strategies,
dynamic_check, full_check,
)
# 1. 静态扫描源码字符串
report = check_strategy_code(code, "my_strategy.py")
print(report.passed) # True/False
print(report.summary()) # 人类可读报告
# 2. 静态扫描文件
report = check_strategy_file("strategies/sma_cross.py")
# 3. 批量扫描 strategies/ 目录
for path, report in check_all_strategies("strategies"):
print(os.path.basename(path), report.passed)
# 4. 动态验证 (需策略类 + 数据)
result = dynamic_check(
SmaCrossStrategy, df,
params={"fast": 10, "slow": 20},
check_bars=50, perturb_range=10,
)
print(result.passed, result.reason)
# 5. 综合检查 (静态 + 动态)
report = full_check(
SmaCrossStrategy, "strategies/sma_cross.py",
df=df, params={"fast": 10, "slow": 20}, run_dynamic=True,
)
print(report.summary())
强制集成点
前视检测已在三处强制接入,AI agent 无法绕过:
| 集成点 | 行为 |
|---|---|
check 命令 |
单独运行静态 + 动态检测 |
validate 命令 |
前置检测,未通过则终止验收 |
deliver 命令 |
前置检测,未通过则拒绝生成交付包 |
scaffold 模板 |
生成的策略文件头部自带 ⚠️ 前视警告,列出禁用模式 |
scaffold 模板的前视警告
用 scaffold 生成的策略文件头部会自动包含警告块:
"""my_strategy — RSI 超卖反弹策略
⚠️ 前视偏差 (Look-Ahead Bias) 注意事项:
信号生成时只能用当前 bar 及之前的数据, 严禁使用未来 bar。
以下模式会引入前视偏差, 必须避免:
- .shift(-N) # 访问未来 bar (N>0)
- close[-1] / high[-1] # 负索引访问未来
- df.iloc[i+N:] # 切片到未来索引
- 滚动统计后 shift 负值
正确做法:
- 用 cross_above / cross_below (基类已内置前视安全)
- 信号在 bar 收盘后生成, 用 close 成交 (引擎默认 upon_bar_close=True)
- 检测: python -m app.main check my_strategy
"""
引擎层的前视防护
RaptorBT 引擎层已内置前视防护:PyBacktestConfig(upon_bar_close=True)(默认)确保信号在 bar 收盘后生成、以 close 价成交,杜绝同一根 bar 内的信号→成交前视。
自定义指标库 (indicators.py)
app/indicators.py 提供自定义指标库,全部转发到 ferro-ta Rust 原生实现以获得亚毫秒级性能。
可用指标
| 函数 | 转发到 | 说明 |
|---|---|---|
typical_price(h, l, c) |
raptorbt.typprice |
典型价格 |
cci(h, l, c, period) |
raptorbt.cci |
商品通道指数 |
williams_r(h, l, c, period) |
raptorbt.willr |
威廉指标 |
roc(data, period) |
raptorbt.roc |
变化率 |
trix(data, period) |
raptorbt.trix |
三重指数平滑变化率 |
dmi(h, l, c, period) |
raptorbt.adx_all |
DMI (ADX + DI) |
ichimoku(h, l, c, ...) |
raptorbt.ichimoku |
一目均衡表 |
parabolic_sar(h, l, ...) |
raptorbt.sar |
抛物线 SAR |
mfi(h, l, c, v, period) |
raptorbt.mfi |
资金流量指数 |
obv(c, v) |
raptorbt.obv |
能量潮 |
awesome_oscillator(h, l, ...) |
sma(medprice) 组合 |
震荡指标 (原生组合) |
用法
from app.indicators import cci, williams_r, dmi
cci_vals = cci(high, low, close, period=20)
willr_vals = williams_r(high, low, close, period=14)
adx, plus_di, minus_di = dmi(high, low, close, period=14)
指标目录 (indicator_catalog.py)
app/indicator_catalog.py 提供 80 个原生指标的完整目录,让 AI agent 在不读完整手册的情况下也能快速查询可用指标、签名、输入需求和返回值结构。
覆盖范围
| 分类 | 数量 | 代表指标 |
|---|---|---|
| 趋势 | 8 | sma / ema / wma / dema / tema / kama / supertrend / sar |
| 动量 | 13 | rsi / macd / cci / stochastic / willr / roc / mom / trix / cmo / bop / ultosc / stochrsi / ppo |
| 强度 | 7 | adx / adx_all / plus_di / minus_di / adxr / aroon / aroonosc |
| 波动率 | 6 | atr / natr / trange / bollinger_bands / stddev / var |
| 成交量 | 4 | obv / mfi / ad / adosc |
| 统计 | 7 | linearreg / linearreg_slope / linearreg_intercept / linearreg_angle / tsf / beta / correl |
| 滚动 | 2 | rolling_min / rolling_max |
| 量价 | 1 | vwap |
| 价格变换 | 6 | typprice / medprice / avgprice / wclprice / midpoint / midprice |
| 高阶均线 | 5 | t3 / trima / vwma / hull_ma / apo |
| 通道 | 4 | donchian / chandelier_exit / ichimoku / pivot_points |
| Hilbert | 6 | ht_trendline / ht_dcperiod / ht_dcphase / ht_phasor / ht_sine / ht_trendmode |
| 市场状态 | 5 | choppiness_index / regime_adx / regime_combined / detect_breaks_cusum / rolling_variance_break |
| 投资组合 | 6 | rolling_beta / drawdown_series / zscore_series / relative_strength / spread / ratio |
IndicatorInfo 字段
每个指标记录 9 个字段:
| 字段 | 说明 | 示例 |
|---|---|---|
name |
函数名 (raptorbt.xxx) | adx_all |
category |
分类 | 强度 |
inputs |
输入数组需求 | ["high", "low", "close"] |
params |
参数名列表 | ["period"] |
defaults |
参数默认值 (与 params 一一对应, "—" 为必填) | ["—"] |
returns |
返回说明 | "3 arrays (adx, plus_di, minus_di)" |
description |
简短中文说明 | "ADX + +DI - DI, 一次拿全方向信息" |
signature() |
可读签名 | adx_all(high, low, close, period) |
usage |
完整调用示例 | adx, plus_di, minus_di = raptorbt.adx_all(...) |
CLI 查询
# 文本版 (人读, 按分类展示)
python -m app.main list --indicators
# JSON 版 (AI agent 解析)
python -m app.main list --indicators --json
JSON 结构:
{
"total": 48,
"categories": {
"趋势": [{...}, ...],
"动量": [{...}, ...],
...
},
"all_names": ["sma", "ema", "wma", ...],
"usage_note": "调用方式: import raptorbt; raptorbt.<name>(numpy_array, ...)"
}
Python API
from app.indicator_catalog import CATALOG, list_by_category, find, format_text, format_json
# 1. 按名称查找单个指标
info = find("adx_all")
print(info.signature()) # adx_all(high, low, close, period)
print(info.returns) # 3 arrays (adx, plus_di, minus_di)
print(info.usage) # adx, plus_di, minus_di = raptorbt.adx_all(high, low, close, period=14)
# 2. 按分类遍历
for cat, inds in list_by_category().items():
print(f"{cat}: {len(inds)} 个")
# 3. 获取所有指标名称 (快速判断某指标是否存在)
all_names = [i.name for i in CATALOG] # ['sma', 'ema', 'wma', ...]
# 4. 生成文本/JSON 目录
print(format_text())
payload = format_json()
AI agent 集成指南
推荐工作流
AI agent 可按以下流程自主开发策略:
0. list --indicators --json 查询可用指标 (80 个, 含签名/默认值/返回值)
↓
1. scaffold 生成策略模板 (自带前视警告头部)
↓
2. 编辑模板,填入信号生成逻辑 (用 raptorbt.<指标名> 调用)
↓
3. check 前视偏差检测 (静态 + 动态) ★ 强制
↓
4. optimize 搜索参数空间
↓
5. walkforward 验证泛化能力
↓
6. acceptance 检查是否达标 (失败时自动给修复建议)
↓
7. 若未通过 → 读取 suggestions 调整逻辑或参数, 回到 2/4
若通过 → 继续 8
↓
8. deliver 生成交付包 (再次强制前视检测, 失败则拒绝生成)
⚠️ 前视检测是强制门槛:步骤 3 和 8 都会运行前视偏差检测。即使 AI agent 在步骤 2 不小心引入了
.shift(-N)等前视模式,也会在交付前被拦截。详见 前视偏差防护 章节。
💡 步骤 0 的价值:AI agent 在编写策略前先查询指标目录,可以避免调用不存在的指标或用错参数签名。JSON 输出中
all_names数组可快速判断某指标是否存在,usage字段提供完整调用示例。
通过 CLI 调用 (推荐)
AI agent 可通过 RunCommand 工具直接调用 CLI:
# 0. 查询可用指标 (AI agent 开发策略前先了解工具箱)
python -m app.main list --indicators --json
# 1. 生成模板 (自带前视警告头部)
python -m app.main scaffold --name ai_strategy_v1 --template breakout
# 2. (AI 编辑 strategies/ai_strategy_v1.py 填入逻辑)
# 3. 前视偏差检测 (静态 + 动态) — 强制门槛
python -m app.main check --strategy ai_strategy_v1 --dynamic --bars 500
# 4. 参数优化
python -m app.main optimize --strategy ai_strategy_v1 \
--param period=10,15,20,25 --param threshold=0.5,1.0,1.5
# 5. Walk-Forward 验证
python -m app.main walkforward --strategy ai_strategy_v1 \
--param period=10,15,20 --bars 2000
# 6. 验收
python -m app.main validate --strategy ai_strategy_v1 \
--param period=10,15,20 --bars 2000
# 7. 交付 (内置强制前视检测, 失败则拒绝生成)
python -m app.main deliver --strategy ai_strategy_v1 \
--param period=10,15 --bars 2000
JSON 输出 + 失败驱动迭代 ★
所有命令支持 --json 标志,输出结构化 JSON(自动清理 NaN/Inf,不转义中文),AI agent 可直接解析无需正则匹配表格:
# 推荐: AI agent 用 --json 获取结构化输出
python -m app.main validate --strategy ai_strategy_v1 \
--param period=10,15,20 --bars 2000 --json
失败驱动的自动迭代:当 validate 未通过时,JSON 中 acceptance.criteria 数组的每条失败标准都带 suggestions 字段(5 条具体可执行建议)。AI agent 可按以下逻辑自动调整:
1. 调用 validate --json
2. 解析 JSON, 找到 passed=false 的标准
3. 读取该标准的 suggestions 数组
4. 根据 suggestions 修改策略 (如 "缩短指标周期" → 把 RSI 14 改为 7)
5. 重新 check → optimize → validate, 直到全部通过
6. 通过后 deliver --json 生成交付包
各命令的 JSON 结构:
| 命令 | JSON 关键字段 |
|---|---|
list --indicators --json |
total + categories (按分类) + all_names (快速判断指标是否存在) + usage_note |
run --json |
metrics (33 项指标) + trades (前 50 条) + n_trades |
optimize --json |
best_params + best_score + top_10 (Top 10 参数组合) |
walkforward --json |
is_sharpe_avg + oos_sharpe_avg + decay_ratio + is_overfit + windows (逐窗口明细) |
validate --json |
lookahead + walk_forward + acceptance (含 suggestions) |
check --json |
单个策略: passed + issues + fix_suggestions; all: n_pass + n_fail + strategies |
deliver --json |
delivered + package_path + lookahead + optimization + walk_forward + acceptance |
💡 NaN 处理:JSON 输出已自动把所有 NaN/Inf 转为
null,AI agent 无需特殊处理。
通过 Python API 调用
from app.optimizer import StrategyOptimizer
from app.walk_forward import WalkForwardValidator
from app.acceptance import StrategyAcceptance
from app.exporter import StrategyExporter
# 完整流程
opt = StrategyOptimizer(metric="sharpe_ratio")
opt_result = opt.optimize(...)
wf = WalkForwardValidator(train_size=300, test_size=100)
wf_result = wf.validate(...)
checker = StrategyAcceptance()
report = checker.check(wf_result)
if report.passed:
exporter = StrategyExporter()
pkg = exporter.deliver(...)
验收通过判据
策略通过验收需满足盈利优先三层全部标准:
- L1 盈利性(必须,任一失败即拒收)
- OOS 盈利因子 ≥ 1.3(总盈利比总亏损多 30%)
- OOS 净收益率 > 0%(样本外真的赚到钱)
- OOS 每笔期望 > 0(平均每单为正)
- L2 风险可控(应该) 4. OOS 最大回撤 ≤ 20%
- L3 健壮性(建议) 5. OOS 夏普比率 ≥ 0.7(已降为参考) 6. OOS 总交易数 ≥ 30 7. IS/OOS 衰减比 ≥ 0.5(注意:IS 也亏时高衰减比无意义)
优先级:L1 失败 = 策略根本不赚钱,不要在参数优化上浪费时间,直接换策略逻辑或品种/周期。详见 验收检查 章节。
通过后 deliver 生成的交付包可作为最终交付物。
环境变量
| 变量 | 默认 | 说明 |
|---|---|---|
MT5_BRIDGE_URL |
http://61.164.252.86:13485 |
Mt5Bridge 服务地址 |
MT5_BRIDGE_KEY |
(内置默认) | Mt5Bridge API Key |
安全建议:生产环境务必通过环境变量设置 MT5_BRIDGE_KEY,不要硬编码到代码中。