一句话:用 AI Agent 自动从几万个候选技术指标里筛出真正有效的 52 个。
传统方法是人凭经验挑几个指标(比如移动平均线、RSI)去检验,既可能漏掉好指标,也可能被随机性欺骗。本项目的方法是:让程序自动生成几千个候选指标,然后用 AI Agent 动态调整搜索方向,最后用极其严格的四重统计检验筛出真有效的那几个。
论文题目:《基于智能体的金融市场投资中有效技术指标挖掘的研究》
agent_mining/
├── main_agent.py # 主入口,运行整个实验
├── agent.py # Agent 主脑,协调探索循环
├── experiment_runner.py # 核心计算引擎(Layer1/2构建、回测)
├── hypothesis_generator.py # 假设生成器(Agent的"大脑")
├── result_analyzer.py # 结果分析器(统计检验+多维分析)
├── llm_client.py # LLM客户端(rule_based模式)
├── visualization.py # 可视化引擎
├── plot_paper_figures.py # 论文图表生成脚本
├── output/ # ★ 所有输出结果
│ ├── all_backtest_results.csv # 全量回测原始数据
│ ├── effective_signals.csv # 最终有效指标(核心!)
│ ├── exploration_log.json # Agent探索决策记录
│ ├── exploration_report.md # 探索报告(人类可读)
│ ├── fig1_top5_cumulative_returns.png # Top5累积收益图
│ ├── fig2_filtering_funnel.png # 筛选漏斗图
│ ├── exploration_trajectory.png # Agent探索轨迹图
│ ├── ratio_vs_diff.png # ratio vs diff 对比图
│ ├── signal_heatmap.png # 有效信号热力图
│ ├── top_signals_ranking.png # Top信号排行榜
│ └── plot_paper_figures.py # 图1+图2的生成脚本(可改参数重出图)
├── cache/ # 缓存文件(加速重复计算)
└── data/ # 数据存放(实际在上级目录 ../data/)
| 项目 | 内容 |
|---|---|
| 样本 | 沪深300成分股中的 80 只 |
| 时间 | 2010年1月 ~ 2024年12月(15年,180个月) |
| 频率 | 日频原始数据,月频回测 |
| 变量 | 开盘价、最高价、最低价、收盘价、成交量 (OHLCV) |
| 因子 | Fama-French 三因子 (Mkt_RF, SMB, HML) |
| 数据源 | baostock API |
原始 OHLCV 数据
│
▼
Layer 1 — 滚动聚合
5个变量 × 4个窗口(1,3,5,10,20天) × 3种聚合(均值/最大/最小)
→ 生成约50个基础指标
│
▼
Layer 2 — 智能配对
两个基础指标配对:ratio(A/B) 或 diff(rank(A)-rank(B))
→ 生成3590个候选信号
│
▼
回测引擎
每月末按信号值分5组或10组,做多最高组、做空最低组
4种回测规格(5组等权/10组市值加权/5组VW name-break/5组VW FF Alpha)
│
▼
四重门统计检验
Gate 1: 5分组等权 |t| > 1.65
Gate 2: 10分组市值加权 |t| > 1.65
Gate 3: 5分组市值加权 name-break |t| > 1.65
Gate 4: FF Alpha |t| > 1.65 (控制市场/规模/价值因子后)
│
▼
有效指标: 至少通过3/4门 + 数据≥60个月
↓
┌──────────────────────────┐
│ ★ AI Agent 决策回路 ★ │
│ 分析本轮结果 → 发现规律 │
│ → 调整下一轮探索方向 │
│ → 反馈到 Layer 2 │
└──────────────────────────┘
Agent 的具体作用(这是论文最大的创新点):
Agent 不参与统计检验(检验标准是固定的、数学的),Agent 只决定"下一轮应该尝试什么样的信号"。
如果没有 Agent,暴力穷举只会停留在预设的 {1,5,10,20} 四个窗口,永远不会发现 3 天窗口才是最有预测力的参数。
| 指标 | 数值 |
|---|---|
| 候选信号总数 | 3,590 |
| 有效技术指标 | 52 个 |
| 筛选率 | 1.4% |
| 探索轮次 | 3 轮 |
| 累计 | t |
| 阶段 | 数量 | 淘汰 |
|---|---|---|
| Layer2 候选信号 | 3,590 | — |
| 至少1重门通过 | 392 | 3,198 |
| 至少2重门通过 | 117 | 275 |
| 至少3重门通过 | 52 | 65 |
| 最终有效指标 | 52 | 0 |
| 排名 | 指标名称 | 类型 | avg|t| | Sharpe | FF Alpha|t| |
|---|---|---|---|---|---|
| 1 | low_max10_minus_close_min3 | diff | 2.590 | 0.695 | 2.056 |
| 2 | close_max3_minus_close_min10 | diff | 2.476 | 0.563 | 2.668 |
| 3 | low_max3_minus_close_min3 | diff | 2.415 | 0.640 | 2.056 |
| 4 | low_t_minus_close_min3 | diff | 2.353 | 0.558 | 2.083 |
| 5 | open_max3_minus_close_min3 | diff | 2.323 | 0.584 | 2.307 |
| 6 | high_ma3_minus_low_min3 | diff | 2.292 | 0.530 | 2.278 |
| 7 | open_max3_minus_close_min10 | diff | 2.258 | 0.493 | 2.096 |
| 8 | high_max3_minus_close_min3 | diff | 2.250 | 0.539 | 2.589 |
| 9 | high_min5_div_open_t | ratio | 2.218 | 0.566 | 2.083 |
| 10 | high_ma3_minus_close_min3 | diff | 2.199 | 0.557 | 2.376 |
发现1:截面排名差(diff)优于简单比率(ratio) - diff 类有效信号:35 个(67.3%) - ratio 类有效信号:17 个(32.7%) - diff 平均 |t| = 0.634 vs ratio 平均 |t| = 0.586
发现2:短窗口(3天)是最有效的信号提取周期 - 引入 3 天窗口后,|t|>1.96 信号从 105 增至 244(+132%) - 52 个有效指标全部包含 3 天窗口参数 - 3 天窗口对 diff 类提升巨大(avg|t|: 0.567→0.764, +34.7%),但 ratio 类反而下降(0.607→0.545)
发现3:纯价格间组合主导,成交量信息有限 - 52 个有效指标中,纯价格组合占绝大多数 - 价量组合无一通过检验
| 文件 | 说明 | 论文中怎么用 |
|---|---|---|
all_backtest_results.csv |
14,360行,3590个信号 × 4种回测规格的完整结果(t值、Alpha t值、收益率、Sharpe) | 查任何信号的详细数据 |
effective_signals.csv |
52个最终有效指标的汇总(avg|t|, avg_alpha_t, avg_ann_ret, avg_sharpe, 通过门数) | 论文第四章 4.3 节,制作表4.3 |
| 文件 | 说明 | 论文中怎么用 |
|---|---|---|
exploration_log.json |
Agent 每轮探索的结构化记录(JSON格式) | 程序读取用 |
exploration_report.md |
人类可读的探索报告,包含每轮策略、关键发现、结论 | 写 4.2 节的文字素材 |
| 文件 | 大小 | 内容 | 论文位置 |
|---|---|---|---|
fig1_top5_cumulative_returns.png |
381K | Top5 有效指标多空组合累积收益折线图(持仓月数 vs 累积收益%) | 第四章 4.3/4.4 节 |
fig2_filtering_funnel.png |
172K | 技术指标筛选漏斗图(3590→392→117→52) | 第四章 4.5 节 |
exploration_trajectory.png |
55K | Agent 探索轨迹图(每轮测试数、通过数、通过率) | 第四章 4.2 节 |
ratio_vs_diff.png |
36K | ratio vs diff 类型对比柱状图 | 第四章 4.3 节 |
signal_heatmap.png |
142K | 有效指标在 4 种规格下的 t 值热力图 | 第四章 4.3 节 |
top_signals_ranking.png |
96K | Top 有效指标横向柱状图(按 avg|t| 排名) | 第四章 4.3 节 |
filtering_funnel.png |
47K | 旧版漏斗图(可忽略,用 fig2 替代) | — |
| 文件 | 说明 |
|---|---|
plot_paper_figures.py |
图1和图2的生成脚本,改参数可重出图 |
格式:变量_聚合类型窗口
| 部分 | 含义 | 示例 |
|---|---|---|
close, high, low, open, volume |
基础变量 | close = 收盘价 |
t |
窗口=1(当日值) | close_t = 当日收盘价 |
maN |
N天移动平均 | close_ma5 = 5日均收盘价 |
maxN |
N天最大值 | high_max3 = 3日最高价 |
minN |
N天最小值 | low_min10 = 10日最低价 |
格式:指标A_分隔符_指标B
| 分隔符 | 类型 | 含义 |
|---|---|---|
_div_ |
ratio | 指标A / 指标B 的比值 |
_minus_ |
diff | 指标A的截面排名 − 指标B的截面排名 |
举例解读:
low_max10_minus_close_min3
→ 指标A = low_max10(10日最低价的最大值)
→ 指标B = close_min3(3日收盘价的最小值)
→ diff 类型:两只股票比较"谁的10日底部更坚实 vs 谁的3日收盘更弱势"
→ 经济含义:捕捉短期超卖但中期底部坚实的反弹信号
high_min5_div_open_t
→ 指标A = high_min5(5日最高价的最小值)
→ 指标B = open_t(当日开盘价)
→ ratio 类型:比值高 = 近期高点下移 + 当日开盘价低 → 可能下跌中继
项目根目录下 论文_草稿.md(约 450 行)包含完整论文框架:
草稿中大部分数字已经填入真实结果,但还需要: 1. 补充英文摘要 2. 检查参考文献格式 3. 部分论文语言需要润色 4. 添加图表交叉引用
cd agent_mining
python main_agent.py --relaxed
参数说明:
- --relaxed:使用宽松标准(3/4门, |t|>1.65),不加则用严格标准(4/4门, |t|>1.96)
- --smoke-test:快速测试(10只股票),验证代码能跑
- --max-rounds 3:最大探索轮次
注意:数据文件 stock_daily.parquet 需要在 ../data/ 目录下(即 agent_mining 的同级 data 文件夹)。
Q: 为什么 3590 个候选只有 52 个通过?是不是标准太严了?
不是太严,是刻意设计成这么严的。Harvey et al. (2016) 指出,当同时检验几千个候选因子时,如果只用传统 |t|>1.96 标准,会有大量假阳性。四重门相当于让信号在四种不同条件下反复验证,只有"真材实料"的才能通关。1.4% 的通过率恰恰是方法论严谨性的体现。
Q: Agent 是干嘛的?跟暴力穷举有什么区别?
Agent 决定"下一轮该探索什么方向",统计检验判定"这个指标是真有效还是随机噪声"。
暴力穷举:预设窗口 {1,5,10,20} → 算完所有组合 → 结果。永远停在预设参数里。
Agent:第1轮发现"短窗口更好" → 引入 3 天窗口 → 第2轮 |t|>1.96 信号翻倍增长 → 第3轮聚焦最优方向。找到了暴力穷举永远找不到的参数。
Q: diff 和 ratio 的区别?
Q: 图里的 |t| 和 t_alpha 有什么区别?
t_ret:多空组合收益的 HAC t 统计量(Newey-West 标准误,最大滞后 6 期)t_alpha:控制 Fama-French 三因子(市场、规模、价值)后的 Alpha t 统计量。更严格——如果信号的收益只是因为承担了更多市场风险,Alpha t 值会很低。Q: 指标名里 _t 是什么意思?
t 表示窗口 = 1(当日值)。例如 close_t = 当日收盘价,low_t = 当日最低价。命名时用 _t 而非 _1 是为了与带窗口参数的格式统一。