从 Point-in-Time 股票筛选到统一 Web 前端的完整链路: 筛选 → 画像 → 策略 → 回测 → Walk-forward → 绩效分析 → 报告/前端。 架构 - 数据层与策略层分离;策略代码不写 SQL,只经 data/repo.py 取数 - 所有业务阈值集中在 config/*.yml,代码零硬编码(字段写错直接报错) - 报告只做「run_id → SQL → 渲染」,不做任何计算,数字可追溯 - 前后端分离:output/ 静态站点 + hdiv web 提供的 REST API 数据安全 - 只增不删:SQL 钩子拦截 DELETE/DROP/TRUNCATE,并有源码扫描测试守护 - qlib 原有表只读,本项目数据写入 hd_ 前缀表 - 回补使用 INSERT IGNORE,保证既有行零改动 - .env 存密钥且已 gitignore;output/、logs/、.venv/ 不入库 交付物 - 30 张 hd_* 表、7 个 YAML 配置、283 项自动化测试 - 统一 Web 前端(hash 路由 SPA)+ nginx 部署配置与 launchd 托管脚本 如实声明的限制 - 策略缺少稳定的样本外超额收益(Walk-forward 7 窗口均值 -0.95%, 基准 +2.29%);其价值体现在回撤控制,而非超额收益 - 涨跌停/停牌约束仅覆盖 2019 年起;index_weight 尚未填充 - AI Agent 层(plan.md 第四版 P8)未实现 详见 docs/user-guide.md 与 docs/implementation-status.md。
26 KiB
A股投资策略制定与回测方案
版本:V1.0 目标:建立一套可扩展的 A 股投资策略研究、策略制定、个股分析与回测体系。 核心案例:高股息 + 安全边际 + 估值均值回归策略
1. 项目目标
实现一套从:
股票筛选
↓
个股特性分析
↓
因子研究
↓
交易策略制定
↓
历史回测
↓
样本外验证
↓
策略评价
↓
策略报告
的完整 A 股投资策略研究系统。
系统不以“预测明天涨跌”为主要目标,而是通过:
- 基本面筛选
- 历史估值分析
- 安全边际分析
- 交易规则参数化
- 历史回测
- Walk-forward 验证
寻找长期具有可重复性的投资策略。
2. 核心投资思想
以高股息策略为例:
寻找长期稳定分红、财务质量较好、规模较大、上市时间较长的公司,当其股息率进入历史相对高位时买入,当股息率下降到历史相对低位时卖出或减仓。
核心思想:
公司质量
+
长期稳定分红
+
合理/低估价格
+
安全边际
+
估值均值回归
↓
形成交易策略
3. 整体系统流程
A股全市场
│
↓
Point-in-Time 数据
│
↓
股票初步筛选
│
┌───────────────┼───────────────┐
↓ ↓ ↓
基本面 估值 风险
│ │ │
└───────────────┼───────────────┘
↓
候选股票池
│
↓
个股特性分析
│
┌───────────────┼───────────────┐
↓ ↓ ↓
股息率历史 财务质量 风险特征
估值分布 分红质量 波动特征
│ │ │
└───────────────┼───────────────┘
↓
因子研究
│
↓
策略参数制定
│
↓
Walk-forward 回测
│
┌───────────────┼───────────────┐
↓ ↓ ↓
收益分析 风险分析 交易分析
│ │ │
└───────────────┼───────────────┘
↓
样本外验证
│
↓
策略稳定性分析
│
↓
AI策略分析
│
↓
策略报告
4. 第一阶段:股票筛选
4.1 基础筛选条件
以高股息策略为例:
universe:
min_market_cap: 50000000000
min_listing_years: 10
exclude_st: true
dividend:
min_continuous_dividend_years: 5
min_dividend_yield: 0.03
基础条件:
| 条件 | 默认值 | 说明 |
|---|---|---|
| 连续分红年限 | ≥5年 | 判断分红稳定性 |
| 最低股息率 | ≥3% | 初步估值过滤 |
| 市值 | ≥500亿元 | 降低小市值风险 |
| 上市年限 | ≥10年 | 获得较长历史数据 |
| ST | 排除 | 极端风险过滤 |
这些参数必须支持用户调整。
5. 2. 股票筛选条件分类
股票筛选不要全部写死在程序中,应拆成不同类型的 Filter。
5.1 市场属性
MarketFilter
包括:
- A股
- 沪市/深市/北交所
- 主板/创业板/科创板
- 上市时间
- 市值
- 流通市值
5.2 风险过滤
RiskFilter
包括:
- ST
- *ST
- 退市整理
- 已退市
- 连续亏损
- 大股东高比例质押
- 重大诉讼
- 商誉异常
- 经营异常
5.3 分红过滤
DividendFilter
包括:
- 连续分红年数
- 最近N年分红次数
- 最近N年现金分红
- DPS
- 股息率
- 分红增长率
- 分红支付率
- FCF覆盖分红
5.4 财务质量过滤
FinancialQualityFilter
包括:
- ROE
- ROIC
- 毛利率
- 净利率
- 营业利润率
- 经营现金流
- 自由现金流
- 资产负债率
- 净现金
- 利息覆盖倍数
6. 3. Point-in-Time 数据原则
这是整个回测系统必须遵守的核心原则。
任何历史回测都只能使用:
在当时已经公开、并且投资者当时能够获得的数据。
例如:
2018-06-01
只能使用在:
2018-06-01
之前已经公布的数据。
不能使用:
2019年年报
2020年年报
2021年财务数据
判断 2018 年股票是否符合条件。
6.1 财务数据必须保存
至少保存:
report_period
publication_date
effective_date
例如:
report_period:
2017-12-31
publication_date:
2018-03-30
effective_date:
2018-03-30
回测时按照:
effective_date <= strategy_date
进行数据查询。
7. 4. 生存者偏差
股票池必须支持:
Point-in-Time Universe
不能只使用今天仍然存在的股票。
例如:
2016年A股股票池
↓
2017年新增股票
↓
2018年新增股票
↓
退市股票
↓
ST股票
每个交易日的股票池应该反映当时真实市场状态。
必须保留:
上市日期
退市日期
ST日期
暂停上市日期
恢复上市日期
8. 第二阶段:个股特性分析
股票经过筛选后,不直接进入交易。
首先建立:
StockProfile
个股画像。
9. 1. 股息率分析
计算:
Dividend Yield
并建立长期历史序列。
例如:
2016 ───────────────────── 2026
2.5%
3.0%
3.5%
4.0%
4.5%
5.0%
统计:
Min
Max
Mean
Median
P10
P25
P50
P75
P90
Std
10. 2. 股息率历史分布
核心指标:
DividendYieldPercentile
例如:
当前股息率 = 4.8%
历史分位:
P75 = 4.2%
P90 = 5.1%
当前 = 4.8%
则当前股息率处于:
75% ~ 90%
的历史高位区间。
这可以作为买入信号的重要依据。
11. 3. 股息率波动分析
计算:
日波动
Daily Std
月度波动
Monthly Std
季度波动
Quarterly Std
年度波动
Annual Std
目的:
判断:
该股票的股息率是否长期稳定,还是经常发生剧烈变化。
12. 4. 个股估值分布
除股息率外,建议同时建立:
PE
PB
PS
EV/EBITDA
Dividend Yield
历史分布。
例如:
指标 P10 P25 P50 P75 P90
Dividend Yield 2.3% 2.8% 3.5% 4.2% 5.1%
PE 8 10 13 17 22
PB 0.8 1.0 1.3 1.7 2.2
形成:
个股历史估值画像。
13. 5. 财务质量画像
每只候选股票计算:
ROE
ROIC
Revenue CAGR
Profit CAGR
FCF CAGR
Debt Ratio
Operating Cash Flow
Free Cash Flow
Dividend Payout Ratio
并观察:
5年
8年
10年
趋势。
14. 6. 分红质量
高股息策略不能只看股息率。
必须区分:
高股息
和:
高质量高股息
重点分析:
分红连续性
连续分红年数
分红稳定性
DPS volatility
分红增长
DPS CAGR
分红支付率
Dividend / Net Profit
自由现金流覆盖
Dividend / FCF
15. 7. 安全边际模型
建立:
MarginOfSafety
可以由多个因子组成:
MarginOfSafety
=
Dividend Yield Score
+
Valuation Score
+
Financial Quality Score
+
Balance Sheet Score
+
Dividend Quality Score
第一版不建议直接复杂加权。
可以先分别展示:
股息率安全边际
估值安全边际
财务安全边际
分红安全边际
之后再考虑综合评分。
16. 第三阶段:交易策略
策略不要写死在代码中。
应该设计为:
Strategy Definition
例如:
strategy:
name: high_dividend_mean_reversion
version: 1.0
universe:
min_market_cap: 50000000000
min_listing_years: 10
exclude_st: true
dividend:
min_yield: 0.03
min_continuous_years: 5
entry:
yield_percentile: 75
exit:
yield_percentile: 25
risk:
max_position: 0.10
max_drawdown: 0.20
17. 1. 买入规则
第一版:
当:
股息率 >= 历史75%分位
AND
股票通过基本面筛选
AND
股票未进入风险状态
→ 买入
进一步可以设计:
股息率 >= P75
↓
观察
股息率 >= P80
↓
建立仓位
股息率 >= P90
↓
增加仓位
18. 2. 卖出规则
例如:
股息率 <= 历史25%分位
则:
减仓/卖出
也可以设计:
P50 → 减仓
P25 → 大幅减仓
19. 3. 加仓规则
建议支持分批建仓。
例如:
P75 → 25%仓位
P80 → 50%仓位
P85 → 75%仓位
P90 → 100%仓位
这样可以研究:
一次性买入 vs 分批买入
的差异。
20. 4. 仓位控制
每只股票增加:
max_position
例如:
单只股票最大仓位 = 10%
同时:
sector_max_position
例如:
单行业最大仓位 = 25%
防止高股息策略最终集中到少数行业。
21. 5. 风险控制
第一版可以支持:
最大单股仓位
最大行业仓位
最大组合回撤
最大单股回撤
流动性限制
不建议一开始加入大量复杂止损规则。
因为止损本身也是策略变量,很容易导致过拟合。
22. 第四阶段:回测
假设:
历史数据:10年
不要只进行一次:
8年训练 + 2年测试
而应该支持:
Walk-forward Backtest
23. Walk-forward 回测
例如:
2015 ───────── 2022 │ 2023
Training │ Test
2016 ───────── 2023 │ 2024
Training │ Test
2017 ───────── 2024 │ 2025
Training │ Test
最终:
多个样本外结果
↓
综合评价
24. Training Period
训练阶段用于:
- 确定股息率历史分布
- 确定买入阈值
- 确定卖出阈值
- 确定仓位规则
- 确定风险参数
例如:
P70
P75
P80
P85
P90
可以在训练数据中研究。
25. Test Period
测试阶段:
禁止重新调整策略参数。
例如:
Training:
2015-2022
Strategy:
Buy >= P80
Sell <= P30
Test:
2023
2023年的结果才是真正的:
Out-of-Sample Result
26. 参数过拟合控制
不能:
不断调整参数
→ 回测
→ 找到收益最高参数
→ 宣布策略有效
应该记录:
Strategy Version
Parameter Version
Training Period
Test Period
例如:
Strategy v1.0
Buy = P75
Sell = P25
Training:
2015-2022
Test:
2023
27. 参数敏感性分析
例如:
买入阈值:
P70
P75
P80
P85
P90
比较:
CAGR
Max Drawdown
Sharpe
Calmar
如果:
P75 → CAGR 13%
P80 → CAGR 13.5%
P85 → CAGR 13.2%
说明策略对参数不敏感。
如果:
P79 → CAGR 18%
P80 → CAGR 20%
P81 → CAGR 8%
说明很可能存在过拟合。
28. 第五阶段:回测结果
回测结果至少分成四类。
28.1 收益指标
Initial Capital
Final Capital
Total Return
CAGR
Annual Return
28.2 风险指标
Maximum Drawdown
Volatility
Downside Volatility
Sharpe Ratio
Sortino Ratio
Calmar Ratio
28.3 交易指标
Number of Trades
Win Rate
Average Holding Period
Average Profit
Average Loss
Profit Factor
Turnover
28.4 基准比较
至少比较:
策略
沪深300
中证红利
上证指数
根据策略类型选择合适 Benchmark。
29. 第六阶段:交易成本
必须加入:
Commission
Stamp Duty
Transfer Fee
Slippage
回测不能假设:
Buy Price = Market Price
Sell Price = Market Price
应该支持:
cost:
commission: ...
stamp_duty: ...
slippage: ...
并支持不同成本模型。
30. 第七阶段:分红处理
高股息策略必须正确处理:
现金分红
除权除息
送股
转增
配股
数据层建议独立保存:
price
dividend
split
bonus
rights_issue
31. 分红再投资
至少支持两种模式:
模式A
现金分红
→ 不再投资
模式B
现金分红
→ 按规则重新投资
最终分别计算:
Total Return
32. 第八阶段:交易记录
每一笔交易都必须记录:
trade_id
strategy_id
stock_code
signal_date
execution_date
side
price
quantity
amount
commission
tax
slippage
reason
其中:
reason
非常重要。
例如:
BUY
reason:
Dividend Yield = 4.82%
Historical Percentile = 86%
ROE = 15.3%
FCF positive = true
Risk Filter = PASS
这样后续 AI 才能分析:
为什么买?
33. 第九阶段:K线与交易点
前端个股页面建议展示:
股票K线
┌────────────────────────────┐
│ │
│ K线 │
│ ▲ BUY │
│ ▼ SELL │
│ │
└────────────────────────────┘
股息率
────────────────────────────
PE
────────────────────────────
PB
────────────────────────────
回撤
────────────────────────────
买卖点直接标记在K线上。
34. 第十阶段:策略研究页面
前端建议分成:
策略配置
↓
股票池
↓
个股画像
↓
参数研究
↓
回测
↓
交易记录
↓
绩效分析
↓
Walk-forward
↓
策略报告
35. 个股画像页面
例如:
贵州茅台
当前股息率:3.2%
历史股息率:
P10 1.8%
P25 2.1%
P50 2.6%
P75 3.4%
P90 4.1%
当前:
3.2%
历史分位:
≈70%
同时展示:
ROE
ROIC
PE
PB
FCF
DPS
Payout Ratio
Debt Ratio
36. 第十一阶段:策略解释
策略回测完成后,系统自动生成:
Strategy Explanation
包括:
策略逻辑
为什么买?
为什么卖?
为什么持有?
历史表现
收益
风险
回撤
交易次数
策略弱点
例如:
1. 对周期行业敏感
2. 高股息可能来自盈利下降
3. 行业集中风险
4. 极端行情下估值可能长期不回归
37. 第十二阶段:AI Agent
AI Agent 不负责直接修改回测结果。
建议定位为:
Data Agent
Factor Agent
Strategy Agent
Backtest Agent
Analysis Agent
Report Agent
37.1 Data Agent
负责:
检查数据完整性
检查缺失数据
检查日期问题
检查未来函数
37.2 Factor Agent
负责:
分析因子
计算因子统计
寻找因子关系
生成因子报告
37.3 Strategy Agent
根据用户自然语言生成:
strategy:
...
但必须经过:
Schema Validation
之后才能运行。
37.4 Backtest Agent
负责调用:
Backtest Engine
不能自己计算回测结果。
37.5 Analysis Agent
负责解释:
为什么策略赚钱?
为什么策略亏损?
什么时候失效?
38. 第十三阶段:策略生命周期
所有策略都应该版本化。
Strategy v1.0
↓
Backtest
↓
发现问题
↓
Strategy v1.1
↓
重新回测
↓
Walk-forward
↓
Paper Trading
↓
Live
39. 策略状态
建议:
DRAFT
RESEARCH
BACKTEST
VALIDATED
PAPER
LIVE
ARCHIVED
40. 推荐的数据结构
核心实体:
Stock
TradingCalendar
Price
CorporateAction
FinancialReport
Dividend
Factor
StockProfile
Universe
Strategy
StrategyParameter
Backtest
BacktestTrade
BacktestPosition
Performance
Benchmark
41. 核心模块
代码层建议:
data/
├── market/
├── financial/
├── dividend/
├── corporate_action/
└── calendar/
universe/
├── filters/
├── selector.py
└── universe_manager.py
factor/
├── valuation/
├── dividend/
├── financial/
├── quality/
└── factor_engine.py
profile/
├── stock_profile.py
├── dividend_profile.py
├── valuation_profile.py
└── risk_profile.py
strategy/
├── base.py
├── registry.py
├── high_dividend.py
└── rules/
backtest/
├── engine.py
├── portfolio.py
├── execution.py
├── cost.py
├── benchmark.py
└── walk_forward.py
analysis/
├── performance.py
├── risk.py
├── trade_analysis.py
├── sensitivity.py
└── attribution.py
report/
├── strategy_report.py
└── backtest_report.py
ai/
├── data_agent.py
├── factor_agent.py
├── strategy_agent.py
├── backtest_agent.py
└── analysis_agent.py
42. 第一版 MVP
不要一开始实现全部功能。
建议第一阶段只完成:
Tushare
↓
SQLite
↓
A股股票池
↓
高股息筛选
↓
个股股息率历史分析
↓
P75/P25交易规则
↓
Backtest
↓
K线 + 买卖点
↓
收益/回撤/交易报告
43. MVP 第一版策略
严格保持简单:
股票筛选
上市 ≥ 10年
市值 ≥ 500亿元
连续现金分红 ≥ 5年
当前股息率 ≥ 3%
非ST
买入
股息率 >= 历史P75
卖出
股息率 <= 历史P25
仓位
单只股票最大10%
回测
Walk-forward
Training = 5~8年
Test = 1~2年
成本
佣金
印花税
滑点
输出
CAGR
Maximum Drawdown
Sharpe
Calmar
Win Rate
Trade Count
Average Holding Period
Benchmark Comparison
44. 第二版扩展
MVP稳定后增加:
PE/PB
ROE
ROIC
FCF
Debt Ratio
Dividend Payout
然后研究:
多因子筛选
例如:
高股息
+
高ROE
+
低PE
+
低负债
+
FCF稳定
45. 第三版扩展
增加:
动态仓位
分批买入
分批卖出
行业限制
组合管理
风险预算
46. 第四版扩展
增加:
AI Agent
自然语言策略生成
策略解释
自动因子研究
自动回测
自动生成研究报告
最终形成:
用户:
“帮我找长期稳定分红、
财务质量较好,
股息率处于历史高位的A股。”
↓
AI Strategy Agent
↓
生成筛选条件
↓
Factor Engine
↓
候选股票
↓
Stock Profile
↓
Strategy Engine
↓
Walk-forward Backtest
↓
Analysis Agent
↓
策略研究报告
47. 核心设计原则
整个系统开发过程中遵循以下原则:
原则1:数据和策略分离
Data Layer
≠
Strategy Layer
原则2:策略和回测引擎分离
Strategy
↓
产生信号
Backtest Engine
↓
执行信号
原则3:所有策略参数化
不要:
if dividend_yield > 0.04:
直接写死。
应该:
if dividend_yield > strategy.params.min_yield:
原则4:所有策略版本化
strategy_id
version
parameters
created_at
原则5:严格防止未来函数
任何数据都必须带:
available_date
原则6:回测结果必须可复现
同样的:
数据版本
+
策略版本
+
参数
+
回测时间
必须产生相同结果。
原则7:收益不是唯一目标
必须同时关注:
收益
风险
回撤
稳定性
交易频率
参数敏感性
样本外表现
48. 最终目标
最终系统形成:
A股投资研究平台
┌─────────────────────────────────┐
│ Data Layer │
│ Tushare / Sina / SQLite / MySQL │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ Factor Research │
│ Dividend / Value / Quality │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ Stock Screening │
│ Point-in-Time Universe │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ Stock Profile │
│ 历史估值 / 财务 / 风险 / 股息率 │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ Strategy Engine │
│ 参数化 / DSL / Versioning │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ Backtest Engine │
│ Cost / Dividend / Corporate │
│ Action / Walk-forward │
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ Performance Analysis │
│ Return / Risk / Drawdown / Trade│
└────────────────┬────────────────┘
↓
┌─────────────────────────────────┐
│ AI Agent │
│ Research / Analysis / Report │
└─────────────────────────────────┘
49. 开发优先级
建议按照下面顺序实施:
P0
数据模型
股票基本信息
交易日历
日线
分红
复权/公司行为
↓
P1
Point-in-Time 财务数据
↓
P2
股票筛选器
↓
P3
股息率因子
↓
P4
个股画像
↓
P5
策略DSL
↓
P6
Backtest Engine
↓
P7
Walk-forward
↓
P8
Performance Analysis
↓
P9
K线 + 买卖点
↓
P10
策略版本管理
↓
P11
AI Agent
50. 第一阶段验收标准
第一版系统完成后,至少应该能够完成以下操作:
输入:
高股息策略
最低市值:500亿
上市年限:10年
连续分红:5年
最低股息率:3%
买入:历史P75
卖出:历史P25
系统自动:
① 找出符合条件的股票
② 生成股票池
③ 计算每只股票历史股息率分布
④ 计算P10/P25/P50/P75/P90
⑤ 生成买卖信号
⑥ 执行历史回测
⑦ 正确处理分红和除权
⑧ 加入交易成本
⑨ 输出K线和买卖点
⑩ 输出收益、回撤、Sharpe等指标
⑪ 与Benchmark比较
⑫ 执行Walk-forward
⑬ 输出样本内/样本外结果
⑭ 保存完整策略参数和版本
这样,第一版就已经具备一个真正的可研究、可复现、可扩展的A股策略回测框架。
51. 后续策略扩展
高股息只是第一种策略。
在相同框架下,可以继续实现:
高股息策略
价值策略
低PE策略
低PB策略
高ROE策略
质量因子策略
红利+价值
红利+质量
价值+质量
多因子策略
均值回归
趋势策略
最终统一成:
Universe
↓
Factors
↓
Stock Profile
↓
Strategy
↓
Portfolio
↓
Backtest
↓
Analysis
从而避免每增加一种投资策略,就重新开发一套系统。