Root README now points at the auto-trading shell and research pipeline; AGENTS.md gains a keep-docs-in-sync rule; trading/README.md maps every method from the two research docs to trading/risk and documents manage_position; research/README.md documents the backtest hook and --backtest CLI. Co-Authored-By: Claude Code <noreply@anthropic.com>
7.9 KiB
research/ —— 研究管线骨架(你的代码)
⚠️ 这是你的研究管线骨架,只用于离线研究。它包装
mtdata-cli作为子 进程拉数据/跑回测,不 import 任何 mtdata 内部模块,因此不会被上游同步覆盖。 研究结果(模型文件 + 报告)最终通过trading/的signal(ctx)接口进入执行壳。
管线一览
┌──────────┬──────────┬──────────────┬──────────────┬─────────────┬───────────┐
│ 取数据 │ 存储 │ 特征/标签 │ 前向验证 │ 训练 │ 评估 │
│ fetch │ store │ features │ walk-forward │ train │ evaluate │
├──────────┼──────────┼──────────────┼──────────────┼─────────────┼───────────┤
│ mtdata-cli│ parquet │ pandas_ta / │ mtdata-cli │ sklearn / │ sklearn │
│ data_ │ (CSV 兜底)│ 手写指标兜底 │ strategy_ │ lightgbm │ 指标 + │
│ fetch_ │ manifest │ 三触线标签 │ validate │ (可选) │ markdown │
│ candles │ │ │ 或本地 stub │ │ 报告 │
└──────────┴──────────┴──────────────┴──────────────┴─────────────┴───────────┘
快速上手(离线、无需下单)
# 一键端到端:取数 → 数据集 → 前向验证 → 训练 → OOS 评估 → 模型落盘
py -3.14 -m research --symbol EURUSD --timeframe H1 --limit 3000
# 可选:最后再对同一份数据回测一个 trading/ 注册表策略(与实盘同一套代码)
py -3.14 -m research --symbol EURUSD --timeframe H1 --limit 3000 \
--backtest --strategy ma_cross
# 也可只手动调用某个阶段(见下方"手动"示例)
py -3.14 -c "
from research.config import ResearchConfig
from research import data_pipeline as dp
cfg = ResearchConfig()
ds = dp.fetch_and_store(cfg, 'EURUSD', limit=3000)
print('stored:', ds.to_dict())
"
py -3.14 -m research 的六个阶段:
- fetch:
fetch_and_store拉 K 线并落盘(parquet 优先,无 pyarrow 时 CSV)。 - dataset:
make_dataset产出特征 + 二分类标签(1=止盈先到)。 - walk-forward:
local_walk_forward按时序分 5 折,报告每折标签命中率。 - split:按
RESEARCH_TRAIN_RATIO(默认0.8)做时序切分,留出 OOS 尾部。 - train + evaluate:训练指定模型,输出 OOS 指标 + 与"永远做多"基线的对比报告。
- save:写到
research/models/latest.joblib—— 即trading/strategies/model_threshold.py的默认model_path。 - backtest(可选,
--backtest):从trading/策略注册表加载一个策略 (--strategy,默认ma_cross),对同一份历史数据跑离线回测 —— 与实盘 同一个signal(ctx)+ 可选的manage_position,输出统计并落 markdown 报告。
入口参数:--symbol --timeframe --limit --kind(model 类型)--model-name
(默认 latest)--seed,以及回测组的 --backtest --strategy(策略名或
模块路径)--strategy-param key=value(可重复)。训练跳出或样本不足时返回码
2,成功为 0。
研究管线不接触订单:任何会触达 trade_* 的调用都留在 trading/。
文件地图
| 文件 | 职责 |
|---|---|
main.py / __main__.py |
端到端编排 CLI(py -3.14 -m research) |
config.py |
环境变量 → ResearchConfig(frozen dataclass) |
data_pipeline.py |
取 K 线 → 存储(parquet/CSV)→ manifest 记录 |
feature_engineering.py |
指标特征 + 前向三触线标签(make_dataset) |
backtest.py |
strategy_validate 包装 + 本地前向验证 + 离线回测(含持仓管理模拟) |
model_trainer.py |
sklearn / lightgbm 训练、ModelWrapper 存取(含 baseline 命中率) |
evaluate.py |
分类指标 + OOS 对比 markdown 报告 |
环境变量(默认值)
| 变量 | 默认 | 说明 |
|---|---|---|
RESEARCH_DATA_DIR |
research/data |
数据与 manifest 目录 |
RESEARCH_STORAGE_FORMAT |
parquet |
parquet / csv(parquet 需 pyarrow) |
RESEARCH_SYMBOLS |
EURUSD,GBPUSD |
默认研究品种 |
RESEARCH_TIMEFRAME |
H1 |
K 线周期 |
RESEARCH_LOOKBACK_BARS |
3000 |
默认取数根数 |
RESEARCH_INDICATORS |
rsi,atr,ema,bbands |
取数时附带指标 |
RESEARCH_LABEL_TP_PCT |
0.4 |
标签止盈距离(%) |
RESEARCH_LABEL_SL_PCT |
0.6 |
标签止损距离(%) |
RESEARCH_LABEL_HORIZON |
12 |
标签前视 K 线数 |
RESEARCH_WF_N_SPLITS |
5 |
strategy_validate 折数 |
RESEARCH_WF_MIN_TRAIN_BARS |
1000 |
前向验证最小训练根数 |
RESEARCH_TRAIN_RATIO |
0.8 |
时序切分:前 80% 训练,尾部留 OOS |
RESEARCH_SPREAD_BPS / RESEARCH_COMMISSION_BPS / RESEARCH_SLIPPAGE_BPS |
1.0 / 0.0 / 1.0 |
回测成本(bps) |
RESEARCH_MODEL_DIR |
research/models |
模型输出目录 |
RESEARCH_MODEL |
logistic |
logistic / rf / gboost / lightgbm |
RESEARCH_REPORT_DIR |
research/reports |
报告输出目录 |
MTDATA_CLI |
mtdata-cli |
CLI 路径 |
模型如何接入 trading/ 执行壳
研究侧只产出两类东西,供 trading/ 使用:
- 特征/标签约定:
feature_engineering.make_dataset(frame, cfg)的输出 直接作为训练输入;在线推理时对最新一根 K 线同样调用build_features。 目标已折叠为二分类:1= 止盈先到(+1),0= 止损先到或超时; 模型输出的单一概率即P(+1),可直接喂给signal()的阈值。 - 模型文件:
model_trainer.ModelWrapper.save(path)落盘,trading/侧 的策略模块用ModelWrapper.load读取,然后在signal(ctx)里:
def signal(ctx):
X = research.feature_engineering.build_features(ctx.candles).tail(1)
p = wrapper.predict_proba_positive(X)[0]
if p >= BUY_THRESHOLD:
return TradeSignal(side="BUY", stop_loss=..., take_profit=..., reason=f"p={p:.3f}")
return None
训练模型永远不直接下单——它只是 signal() 的一个输入;是否真的下单仍由
trading/ 的 dry-run 分层和护栏把关。任何模型上线实盘前,请先完成
docs/LIVE_TRADING_CHECKLIST.md。
前向验证(walk-forward)
- 优先:
research.backtest.run_strategy_validate(cfg, symbol, candidates)直接 调用mtdata-cli strategy_validate(含 purge/embargo 防泄漏、固定候选、 horizon-safe 结果)。 - 兜底:
local_walk_forward(frame, cfg)在本地做时序切分的标签分布摘要, 用于无 broker 环境下的骨架验证。
离线回测(可选,任意 signal(ctx) 策略)
research.backtest.backtest_strategy(strategy, frame, cfg) 用与实盘同一个
策略对象逐 bar 回测:signal(ctx) 开仓后,每根 K 线先结算服务器端 SL/TP
(价格先行动),未命中再调用策略的 manage_position(ctx, position) 做移损 /
保本 / 分批平仓 / 提前离场 —— 与实盘循环的持仓管理 pass 调用的是同一个方法,
动作语义也完全一致(apply_position_action 模拟 Executor.modify/close)。
成本按 RESEARCH_SPREAD_BPS / RESEARCH_COMMISSION_BPS /
RESEARCH_SLIPPAGE_BPS 结算。backtest_registered(spec, frame, cfg) 接受
trading/ 注册表名字(ma_cross、model_threshold 或任意模块路径),
py -3.14 -m research --backtest 即其一键入口。