A股公募基金量化分析系统。每日自动筛选基金池、获取净值与盘中估值、计算技术指标、规则匹配买卖信号、生成持仓建议、推送微信报告。内置回测引擎,支持策略参数化与历史验证。
- 全市场覆盖:从 27,000+ 只公募基金中筛选,支持股票型、混合型、债券型、QDII、ETF 等
- 规则驱动 + 参数可配:9 条买入规则 + 10 条卖出规则,所有阈值在
config.yaml中配置,无需改代码即可调参 - 学术理论支撑:仓位计算基于 Half-Kelly、Vol Targeting(Moreira & Muir 2017)、Drawdown Constraint(Grossman & Zhou 1993)
- 盘中估值:集成天天基金实时估值,盘前即可预判当日走势
- 微信推送:通过 PushPlus 每日自动推送完整报告
- 基金池缓存:首次筛选后缓存,后续秒级加载
- 策略回测:逐日历史回测,无未来信息泄露,输出收益指标 + 规则有效性 + 交易记录 CSV
- Python 3.8+
- Windows / Linux / macOS
- 网络可访问东方财富 API 和天天基金
git clone https://github.com/SuperBigFive/quant-fund.git
cd quant-fund
pip install -r requirements.txt# 1. 创建环境变量文件
echo "PUSHPLUS_TOKEN=你的token" > .env
# 2. 编辑持仓列表(每行一个 6 位基金代码)
# 编辑 holdings.txtPushPlus token 在 pushplus.plus 免费获取。
# 日常运行
python main.py # 完整流程(估值 + 推送)
python main.py --no-estimate # 跳过盘中估值(盘后使用)
python main.py --no-push # 不推送微信
python main.py --refresh-universe # 强制重建基金池
python main.py --fund 000001 # 单只基金诊断
# 策略回测
python main.py --backtest # 全量回测(自动区间)
python main.py --backtest --bt-start 2024-06-01 # 指定起始日期
python main.py --backtest --bt-end 2026-06-18 # 指定结束日期
python main.py --backtest --bt-capital 500000 # 自定义初始资金 ┌─────────────────┐
│ 1. 基金池筛选 │ universe.py
│ 类型/关键词过滤 │ 规模≥5亿 成立≥1年
│ 同类去重 │
└────────┬────────┘
↓
┌─────────────────┐
│ 2. 净值获取 │ data_fetcher.py
│ 东方财富 API │ 8线程并行 + SQLite 缓存
└────────┬────────┘
↓
┌─────────────────┐
│ 2.5 盘中估值 │ 天天基金 fundgz
│ 追加今日数据点 │ 并行获取 + 重试
└────────┬────────┘
↓
┌─────────────────┐
│ 3. 技术指标 │ indicators.py
│ MA200/RSI/夏普 │ 异常基金自动排除
└────────┬────────┘
↓
┌─────────────────┐
│ 4. 规则匹配 │ scorer.py
│ 8买 + 8卖规则 │ 买入 TOP 10
└────────┬────────┘
↓
┌─────────────────┐
│ 5. 仓位计算 │ position_advisor.py
│ Kelly + Vol + DD│ 单只≤10% 总仓≤80%
└────────┬────────┘
↓
┌─────────────────┐
│ 6. 报告推送 │ reporter.py
│ PushPlus → 微信 │ 持仓建议 + 买入推荐
└─────────────────┘
独立的回测引擎(backtest/),用于策略开发与参数优化,不参与日常运行。
回测引擎忠实模拟实盘操作:假设投资者每天收到基金分析报告后,严格按报告建议执行操作。
| 操作 | 触发条件 | 执行方式 |
|---|---|---|
| 清仓 | 报告建议"清仓" | 卖出该基金 100% 仓位 |
| 减仓 | 报告建议"减仓" | 按报告给出的比例卖出部分仓位 |
| 买入 | 持仓 < 30 只 + 有买入推荐 | 买入排名第一的未持仓基金,金额 = 总资产 × 报告建议仓位比例 |
| 尘埃清理 | 持仓价值 < 总资产 0.1% | 自动清仓 |
回测引擎调用与实盘完全相同的代码路径生成交易建议:
indicators.compute_indicators()— 计算技术指标scorer.select_buy_candidates(top_n=10)— 买入候选(与报告一致取 TOP 10)scorer.select_sell_candidates()— 卖出预警holdings.analyze_holdings()— 持仓分析position_advisor.compute_position_advice()— 仓位计算(Half-Kelly + Vol Targeting + DD Constraint)
回测中每个交易日的买卖建议,与当天运行 main.py 生成的报告完全一致。
python main.py --backtest
│
▼
┌───────────────────────┐
│ BacktestEngine │ 逐日推进
│ ├─ 数据截断(无未来) │ 每天只用当日及之前的数据
│ ├─ 尘埃持仓清理 │ < 总资产 0.1% 的持仓自动清仓
│ ├─ 指标计算 │ 复用 indicators.py
│ ├─ 信号生成 │ 复用 scorer.py + holdings.py + position_advisor.py
│ ├─ 执行卖出建议 │ 清仓 100% / 减仓 pct%
│ ├─ 执行买入建议 │ 排名第一的未持仓基金,仓位 = 报告比例
│ └─ 结果汇总 │ 收益 + 规则有效性 + CSV
└───────────────────────┘
- 控制台:收益指标(年化/夏普/最大回撤)、规则胜率、最佳/最差基金
- CSV 文件:
cache/backtest_daily.csv(日净值)、cache/backtest_trades.csv(逐笔交易)
所有阈值可在 config.yaml 的 strategy.rules.buy 段调整。
| 规则 | 条件 | 可配参数 |
|---|---|---|
| P1 黄金回调 | MA200 上方 ∧ 连跌 N 天 ∧ RSI < M | decline_min/max, rsi_max |
| P2 超跌反弹 | MA200 上方 ∧ RSI < M ∧ 60 日回撤 > N% | rsi_max, max_drawdown_min |
| P3 趋势回调 | MA200 上方 ∧ 连跌 N 天 ∧ 夏普 > M | decline_min/max, sharpe_min |
| P4 低波抄底 | MA200 上方 ∧ RSI < M ∧ 波动率 < 历史 | rsi_max, vol_ratio_max |
| P5 深度价值 | MA200 上方 ∧ 60 日回撤 > N% ∧ RSI < M | max_drawdown_min, rsi_max |
| P6 优质回调 | MA200 上方 ∧ 夏普 > M ∧ 连跌 N 天 | sharpe_min, decline_min/max |
| P7 波动收缩 | MA200 上方 ∧ 波动率 < M × ∧ 高点回撤 > N% | vol_ratio_max, pullback_min |
| P8 强趋势回调 | MA200 上方 ∧ 趋势强度 > N% ∧ 连跌 ≥ M 天 | trend_strength_min, decline_min |
| P9 趋势跟踪 | TSMOM(126d) > 0 ∧ MA100 > MA200(默认禁用,长线策略) | enabled |
所有阈值可在 config.yaml 的 strategy.rules.sell 段调整。
| 规则 | 条件 | 操作 | 可配参数 |
|---|---|---|---|
| S1 硬止损 | 60 日最大回撤 > N% | 清仓 | max_drawdown_min |
| S2 连涨止盈 | 连涨 ≥ N 天 ∧ RSI > M | 减仓 | rise_min, rsi_min |
| S3 暴涨止盈 | 月涨幅 > N% ∧ RSI > M | 减仓 | monthly_return_min, rsi_min |
| S4 风险恶化 | 夏普 < M ∧ 月度亏损 < N% | 减仓 | sharpe_max, monthly_return_max |
| S5 高位回撤 | MA200 上方 ∧ 高点回撤 > N% ∧ 连跌 ≥ M 天 | 减仓 | pullback_min, decline_min |
| S6 偏离回归 | 偏离 MA200 > N% ∧ RSI > M | 减仓 | trend_strength_min, rsi_min |
| S7 波动飙升 | 波动率 > M × 历史 | 减仓 | vol_ratio_min |
| S8 趋势确认 | 跌破 MA200 ∧ 月度亏损 < N%(默认禁用) | 清仓 | monthly_return_max |
| S9 趋势反转 | TSMOM(126d) < 0 ∧ MA100 < MA200(默认禁用,长线策略) | 清仓 | enabled |
| S10 死叉 | MA50 < MA200(默认禁用) | 减仓 | enabled |
| 场景 | 方法 | 理论来源 |
|---|---|---|
| 买入 | Half-Kelly × 波动率调整 × 回撤缩放 | Kelly (1956), Moreira & Muir (2017) |
| 卖出 | max(Vol Targeting, DD Constraint) | Moreira & Muir (2017), Grossman & Zhou (1993) |
| 约束 | 单只 ≤ 10%,总仓 ≤ 80%,最多 30 只 | — |
每只基金计算 18 个指标:
| 类别 | 指标 | 说明 |
|---|---|---|
| 趋势 | MA200、MA100、趋势强度、是否站上 MA200、金叉(MA100>MA200) | 均线系统与趋势判断 |
| 动量 | TSMOM(126d)、TSMOM(252d)、RSI(14)、单日涨跌、近月收益 | 时间序列动量与相对强弱 |
| 回调 | 连跌/连涨天数、累计跌幅、高点回撤 | 近期调整幅度 |
| 风险 | 波动率比、60 日最大回撤、滚动夏普 | 风险度量 |
| 估值 | 盘中实时估值(天天基金) | 当日预判 |
编辑 config.yaml:
strategy:
# 基础参数
ma_period: 200
target_annual_vol: 0.10
# 规则参数(可独立调整每条规则的阈值)
rules:
buy:
P1_golden_pullback:
rsi_max: 40
decline_min: 3
decline_max: 5
# ... 更多规则
sell:
S4_risk_decay:
sharpe_max: 0.0
monthly_return_max: -0.05
# ... 更多规则
universe:
min_aum_yi: 5 # 排除规模 < 5 亿的小基金
min_fund_age_days: 365 # 排除成立 < 1 年的新基金
backtest:
initial_capital: 100000 # 回测初始资金quant-fund/
├── main.py # 主入口 + CLI(运行/回测/诊断)
├── config.yaml # 策略参数 + 基金池配置 + 规则阈值
├── requirements.txt # Python 依赖
├── universe.py # 基金池筛选(类型/规模/年龄/去重)
├── data_fetcher.py # 数据获取(净值 + 估值 + 基本信息)
├── nav_cache.py # NAV 净值 SQLite 缓存(nav_history + nav_meta 表)
├── cache_db.py # 通用 SQLite 缓存(基金列表 + 筛选池 + 基金信息)
├── indicators.py # 技术指标计算
├── scorer.py # 买卖规则匹配(参数化)
├── holdings.py # 持仓分析
├── position_advisor.py # 仓位计算(Kelly + Vol + DD)
├── reporter.py # 报告生成
├── notifier.py # PushPlus 微信推送
├── estimate.py # 独立估值工具
├── backtest/ # 回测引擎
│ ├── __init__.py
│ ├── engine.py # 逐日回测引擎(报告驱动,忠实模拟实盘操作)
│ ├── portfolio.py # 模拟账户 + 费率模型(支持加仓累加份额)
│ └── report.py # 回测报告生成 + CSV 导出
├── .env # 密钥(不入版本控制)
├── holdings.txt # 持仓代码(不入版本控制)
└── cache/ # SQLite 缓存 (nav_cache.db) + 回测结果(不入版本控制)
策略参数化后可通过回测快速验证改进效果:
| 迭代 | 改动 | 效果 |
|---|---|---|
| v1 | 原始 8 买 + 8 卖 | 1年 +4.31%,夏普 1.38,波动 4.3% |
| v1 优化 | 关 S2/S7,收 S4,加 7 天冷却期 | 交易 -57%,胜率 19%→84% |
| v2 | 回测引擎重构:忠实模拟实盘操作(每日买 1 只、报告驱动卖出、尘埃清理 0.1%) | 6个月 -0.13%,76笔交易,回撤 0.99% |
| v2.1 | 最低仓位 0.5%→2%,最大仓位 5%→10% | 6个月 +0.81%,61笔交易,胜率100%,回撤1.2% |
| v2.2 | 目标波动率 10%→15%(减少 Vol Target 过度卖出) | 6个月 +1.44%,66笔交易,胜率91%,回撤1.0%,夏普0.26 |
| v2.3 | 排除债券型基金 + 目标波动率 15%→25% | 2年 +14.18%,年化+7.29%,夏普1.22,胜率82%,回撤3.4% |
| v2.3-fix | 修复 equity_codes 子串匹配 bug(0→1268只) | 2年 +13.86%,年化+7.13%,夏普1.15,胜率71%,回撤3.3% |
| v2.4 | 禁用S8清仓 + 移除硬编码清仓 + target_vol 40% + DD阈值 10%/20% | 2年 +16.58%,年化+8.48%,夏普1.22,胜率82%,回撤4.2% |
| v2.5 | 新增 P9/S9 趋势跟踪规则(TSMOM 126d + MA100/200 AND 逻辑)+ 200 只基金多窗口验证 | 近3年 +5.94%,近5年 +14.21%,熊市3年 +16.96%(超额收益) |
| v2.6 | 禁用 P9/S9(长线策略与短线 swing trading 目标冲突)+ 项目改名 fund-metrics → quant-fund | 定位调整:专注几天到两周的短线波段操作 |
| v2.7 | MA200 非对称确认择时(退出12d+入场1d)+ 200只基金×4窗口验证 | ≥2窗口赢 78.9%,沪深300 4/4全赢,平均超额 +4%~+14% |
| v2.8 | MA200→MA50(短期投资导向)+ 混合策略测试 + 双均线扫描 | ≥2窗口赢 71.6%,沪深300 2/4(近5年+熊市3年),持有周期~8个月/笔 |
| v2.9 | 布林带核心卫星策略(BB下轨买入+中轨卖出,7-14天持有)+ MA200趋势过滤 | 牛市-0.1%,非牛市+1.9%,CSI300非牛市+2.8%~+6.3%,≥2窗口赢59% |
| v3.0 | P1-P8规则网格搜索优化(3轮270组合)+ 核心卫星+MA200框架 | 牛市+2.1%,非牛市+8.5%,CSI300非牛市+2.5%~+5.5%,≥2窗口赢74.7% |
| v3.1 | 仓位比例化策略(每日目标仓位+渐进买卖,不再全仓/清仓)+ 网格搜索优化 | 牛市-5.7%,非牛市+4.3%,CSI300非牛市+1.9%~+4.5%,≥2窗口赢67.4%,17-31笔交易 |
每次迭代只需修改 config.yaml,运行 --backtest 验证。
- 每次运行从 API 拉取全部基金净值(8 线程并行,约 3-4 分钟),API 失败的基金自动降级使用缓存
- 债券型和部分 QDII 无盘中估值,报告自动回退到前日净值
- 东方财富 API 对并发敏感,净值拉取已优化为 8 线程并行(需 V8 引擎预热),全量约 3-4 分钟
- 所有缓存统一存储在
cache/nav_cache.db(SQLite):净值历史、基金列表、筛选池、基金信息、基准指数 - NAV 缓存策略:每次运行都从 API 拉取全部基金最新净值并更新缓存(UPSERT 自动去重),API 失败时降级返回缓存数据
- 基金池缓存不自动过期,需
--refresh-universe手动触发重建 - 回测引擎为离线开发工具,不参与每日运行管道
MIT