# 量化交易学习路径：从程序员到独立研究者

> **目标读者**：有编程经验的开发者，量化知识和股票交易知识趋近于零。  
> **前置条件**：Python 熟练，了解 numpy/pandas 基本用法。  
> **学习方式**：概念先行 → Demo 跟进 → 动手修改 → 平台实战。  
> **预计时间**：6-12 周（业余时间，每周 8-12 小时）。

---

## 目录

1. [你的起点：程序员学量化的优势和陷阱](#1-你的起点程序员学量化的优势和陷阱)
2. [路线图总览](#2-路线图总览)
3. [第一阶段：基础交易概念（第 1 周）](#3-第一阶段基础交易概念第-1-周)
4. [第二阶段：数据管道（第 2-3 周）](#4-第二阶段数据管道第-2-3-周)
5. [第三阶段：策略与回测（第 4-6 周）](#5-第三阶段策略与回测第-4-6-周)
6. [第四阶段：因子研究（第 7-8 周）](#6-第四阶段因子研究第-7-8-周)
7. [第五阶段：组合优化（第 9-10 周）](#7-第五阶段组合优化第-9-10-周)
8. [第六阶段：实战项目 — ETF 轮动（第 11-12 周）](#8-第六阶段实战项目--etf-轮动第-11-12-周)
9. [从 Demo 到平台的切换时机](#9-从-demo-到平台的切换时机)
10. [贯穿全程的学习方法](#10-贯穿全程的学习方法)

---

## 1. 你的起点：程序员学量化的优势和陷阱

### 你的优势

- **代码不是障碍**。Demo 的逻辑你看得懂，不需要花时间学 Python 语法。
- **系统思维**。事件驱动架构、数据管道、模块化设计——这些对你是天然的语言。
- **调试能力**。策略跑不出效果？你会 print 中间变量、画分布图、对比预期值，而不是对着屏幕发呆。

### 程序员学量化最常见的陷阱

| 陷阱 | 表现 | 为什么有害 |
|------|------|-----------|
| **把代码复杂度当成策略质量** | "我这个策略用了 LSTM + Transformer + 强化学习" | 复杂的模型 ≠ 能赚钱的策略。很多最赚钱的策略是小学算术级别的公式 |
| **过度关注实现，忽略概念** | 上来就写代码，不知道 Sharpe 和 Sortino 的区别 | 你写再多代码也是在错误的路上加速 |
| **把回测结果当真** | 回测年年化 50%，以为自己找到了圣杯 | 99% 是过拟合、前视偏差或幸存者偏差。回测不是验证策略好不好，是验证策略有没有明显漏洞 |
| **跳过模拟交易直接实盘** | 回测漂亮 → 真金白银 → 亏钱 | 回测和实盘之间有巨大的鸿沟：成交价格、滑点、流动性、交易心理……模拟交易是发现这些的唯一零成本方式 |
| **追求全自动，排斥理解** | 调库跑回测，只看最终 Sharpe 数字 | 你不知道策略什么时候会失效，因为你不知道它赚的什么钱 |

> **核心原则：先理解概念，再写代码。先小数据手动算，再全市场自动跑。先模拟交易，再实盘。**

---

## 2. 路线图总览

```
第一周     基础交易概念
           "什么是股票、什么是ETF、怎么看K线"

第二~三周   数据管道 (Demo 1)
           "原始数据长什么样、为什么要清洗、收益率怎么算"

第四~六周   策略与回测 (Demo 2 → Demo 3)
           "怎么用均线/RSI生成买卖信号、怎么回测、怎么看绩效报告"

第七~八周   因子研究 (Demo 4)
           "怎么判断一个指标有没有预测能力、IC是什么、因子怎么合成"

第九~十周   组合优化 (Demo 5)
           "持有多只股票时怎么分配权重、有效前沿是什么意思"

第十一~十二周 实战项目 (Demo 7)
           "把学到的全部串起来：ETF轮动策略 + 真实数据 + 绩效分析"

之后        平台实战
           "在聚宽/米筐上用全市场数据验证策略 → 模拟交易 → 实盘"
```

每个阶段的结构一致：

```
① 先阅读 doc_0X_xxx.md 的概念部分  (30 分钟)
② 打开 demo 对应的 .py 文件，读代码和注释 (1 小时)
③ 跑一遍 demo，看输出图表 (30 分钟)
④ 动手修改一个参数 or 实现一个变体 (1-2 小时)
⑤ 回答 "我学到了什么"  (10 分钟写笔记)
```

---

## 3. 第一阶段：基础交易概念（第 1 周）

### 3.1 需要理解的概念

如果你是程序员但没炒过股，这些是你必须补齐的基础知识。**不要跳过**——后面的所有 Demo 都建立在这些概念之上。

#### 股票基础

| 概念 | 一句话解释 | 为什么要知道 |
|------|-----------|-------------|
| **股票 (Stock)** | 上市公司的所有权份额。买 1 股 = 你拥有公司的一小部分 | 所有策略操作的对象 |
| **A 股** | 在中国大陆交易所（上交所/深交所）上市交易的股票 | 你的策略最终要在这个市场上跑 |
| **股票代码** | 每只股票的唯一标识，如 `000001.SZ`（平安银行）、`600519.SH`（贵州茅台） | 代码即数据索引 |
| **开盘价/收盘价** | 每个交易日第一笔/最后一笔成交的价格 | 收盘价是大部分策略使用的基准价 |
| **最高价/最低价** | 当天成交的最高/最低价格 | OHLC 中的 H 和 L |
| **成交量 (Volume)** | 当天成交了多少股 | 衡量市场活跃度和流动性 |
| **K 线 (Candlestick)** | 把 O/H/L/C 四个价格画成一根"蜡烛" | 技术分析的最基本可视化单元 |
| **T+1 制度** | A 股今天买的股票明天才能卖 | 日频策略必须知道的事——你今天发出的买入信号，买了以后今天不能卖 |

#### ETF 基础

| 概念 | 一句话解释 |
|------|-----------|
| **ETF (交易型开放式指数基金)** | 一种在交易所买卖的基金，追踪某个指数或行业。买 1 份芯片 ETF ≈ 同时买了芯片行业的一篮子股票 |
| **行业 ETF** | 追踪某个行业的 ETF，如芯片 ETF (159995)、消费 ETF (159928) |
| **宽基 ETF** | 追踪大盘指数的 ETF，如沪深 300 ETF (510300) |
| **为什么个人投资者适合 ETF** | 避免个股暴雷（财务造假、退市）、降低选股难度、流动性好、手续费低 |

#### 量化交易基础

| 概念 | 一句话解释 |
|------|-----------|
| **策略 (Strategy)** | 一套明确的规则，告诉你什么时候买、买多少、什么时候卖 |
| **回测 (Backtest)** | 在历史数据上模拟策略的表现，回答"如果过去按这个规则交易，结果会如何" |
| **收益率 (Return)** | 价格变化的百分比：`r = (今天价格 / 昨天价格) - 1` |
| **年化收益率 (CAGR)** | 把总收益率折算成"平均每年赚多少" |
| **波动率 (Volatility)** | 收益率的标准差，衡量"价格有多颠簸" |
| **夏普比率 (Sharpe Ratio)** | `(年化收益 - 无风险利率) / 年化波动率`，衡量"每承担一单位风险，能赚多少钱" |
| **最大回撤 (Max Drawdown)** | 从历史最高点到最低点的最大跌幅。如果策略历史上最多亏过 30%，你能承受吗？ |
| **过拟合 (Overfitting)** | 策略在历史数据上表现极好，但在未来数据上表现极差——你只是记住了历史，没有找到规律 |
| **前视偏差 (Look-Ahead Bias)** | 回测中错误地使用了"未来的数据"做决策。例如用今天的收盘价决定今天的交易——但今天收盘时你还没法交易。代码层面最常犯的错误是 `bfill()` |

#### 学习资源

- 任何一本 A 股入门科普书的前两章（什么是股票、怎么开户、怎么看行情软件）
- [聚宽课堂](https://www.joinquant.com/help) 的"量化交易入门"系列（免费、中文、半小时看完基础概念）
- 打开东方财富或同花顺 App，随便翻几只股票，感受一下 K 线图、成交量柱、PE/PB 数字——建立直观感觉

### 3.2 不急着碰代码

这一周**不需要打开 Demo**。你需要的是建立金融直觉：当你听到"这只股票今天涨了 5%"，你脑子里应该有个画面——K 线跳上去、成交量可能放大了、PE 可能变高了。这种东西 Demo 教不了你，只能靠多看行情软件培养。

---

## 4. 第二阶段：数据管道（第 2-3 周）

> **配套 Demo**: `quant_data_pipeline_demo.py` (920 行)  
> **配套文档**: `doc_01_data_pipeline.md`  
> **核心问题**: 原始行情数据长什么样 → 怎么把它变成能研究的数据

### 4.1 先理解的概念（读 doc_01 前先想清楚）

| 概念 | 为什么重要 |
|------|-----------|
| **复权 (Adjustment)** | 股票分红或拆股时价格会跳空。不复权的话，你的策略会看到虚假的"暴跌"信号 |
| **前复权 vs 后复权** | 前复权：历史价格按今天的股本折算（当前价格真实，历史价格被修改）。大部分策略用前复权 |
| **简单收益率 vs 对数收益率** | 对数收益时间可加（`ln(P_t/P_0) = Σ ln(P_i/P_{i-1})`），统计性质更好。日频差异极小，但月频以上必须区分 |
| **缺失值处理 (ffill)** | 停牌时用前一天的价格填充。**只有 ffill 是安全的**——bfill 会把未来价格泄露到今天 |
| **异常值 (Outlier)** | 一天涨 500% 多半是数据错误而不是真实行情。不处理的话你的均值和标准差全被拉偏 |
| **Winsorize (缩尾)** | 不删除异常值，而是把它"拉回"到合理边界。保留数据量，同时消除极端值影响 |
| **涨跌停 (Price Limit)** | A 股 ±10% 涨跌停（ST 股 ±5%）。涨停日的 +10% 是真的价格，但你买不到——策略需要标记这些天 |

### 4.2 如何 Dig In

**第一步：跑一遍 Demo 1（1 小时）**
```bash
python quant_data_pipeline_demo.py
```
不要改任何代码。观察输出：
- 6 个 Topic 都生成了什么图表
- 每个 Topic 的 print 输出说了什么
- DataPipeline 类的 `run()` 方法执行了哪 5 个 Step

**第二步：读代码，画出数据流（2 小时）**
```
原始价格 Panel (未复权) 
  ↓ generate_raw_stock_data()
  → 复权 (forward_adjust / backward_adjust)
  → 简单收益 vs 对数收益对比
  → 多标的 Panel + 缺失值填充 (ffill only!)
  → 异常值检测 (MAD) + Winsorize
  → 涨跌停标记
  → 交易日历对齐
  → DataPipeline.run() 端到端
```
读完代码后，合上文件，自己画一遍这条数据流。如果能不看代码画出 6 个步骤，说明你理解了。

**第三步：动手修改（2 小时）**

搞三个微小的改动，跑通就能建立信心：

1. **改参数看影响**：把 `winsorize_pct=(0.01, 0.99)` 改成 `(0.05, 0.95)`，看收益率分布怎么变
2. **改检测阈值**：把 `detect_outliers_mad(series, threshold=5.0)` 的 threshold 改成 3.0 和 7.0，观察检测出的异常值数量变化
3. **自己造一个带问题的数据集**：手动改几天的价格为 NaN 或极端值，看 DataPipeline 清洗后的结果是否正确

**第四步：概念验收（20 分钟）**

能用自己的话回答以下问题，就过了：
- 为什么 bfill 在量化研究中是危险的？
- MAD 和 Z-score 哪个更稳健？为什么？
- 涨跌停日的数据应该删除还是保留？为什么？

---

## 5. 第三阶段：策略与回测（第 4-6 周）

> **配套 Demo**: `quant_strategy_backtest_demo.py` (912 行) + `quant_event_driven_backtest_demo.py` (1532 行)  
> **配套文档**: `doc_02_strategy_backtest.md` + `doc_03_event_driven_backtest.md`  
> **核心问题**: 怎么把"感觉要涨"变成可量化的规则 → 怎么在历史上验证这个规则

### 5.1 先理解的概念

#### 技术指标

| 指标 | 一句话 | 属于哪一类 |
|------|--------|-----------|
| **SMA (简单移动平均)** | 过去 N 天收盘价的平均值 | 趋势跟随 |
| **EMA (指数移动平均)** | 近期价格权重更高，比 SMA 反应更快 | 趋势跟随 |
| **RSI (相对强弱指数)** | 0-100 的值，>70 超买（该跌了），<30 超卖（该涨了） | 均值回归 |
| **MACD** | 两条 EMA 的差值，反映趋势的强度和方向 | 趋势跟随 |
| **布林带 (Bollinger Bands)** | SMA ± 2×标准差。价格碰到下轨 = 超卖，碰到上轨 = 超买 | 均值回归 |

#### 策略概念

| 概念 | 为什么重要 |
|------|-----------|
| **趋势跟随 (Trend Following)** | 涨了就追、跌了就卖。在趋势市赚钱，在震荡市反复打脸 |
| **均值回归 (Mean Reversion)** | 涨多了就卖、跌多了就买。在震荡市赚钱，在强趋势市被趋势碾过 |
| **两类策略的互补性** | 没有任何策略能同时在趋势市和震荡市赚钱。你必须知道你的策略在什么市场环境中会失效 |
| **金叉 / 死叉** | 短期均线上穿长期均线 = 金叉（买）。下穿 = 死叉（卖） |

#### 回测概念

| 概念 | 为什么重要 |
|------|-----------|
| **向量化回测** | 用 pandas 数组运算一次性算出整个历史的所有收益。速度快，但无法模拟复杂交易逻辑 |
| **事件驱动回测** | 逐天模拟真实交易流程（行情→信号→订单→成交）。速度慢，但真实度高，和实盘系统架构一致 |
| **滑点 (Slippage)** | 你下单时的价格和实际成交价格的差异。大单、高波动时滑点更严重 |
| **佣金 (Commission)** | 券商手续费。A 股 ETF 佣金约万三（0.03%），单向 |
| **印花税 (Stamp Duty)** | 政府收的交易税。A 股 ETF 仅卖方收 0.1% |
| **训练集 vs 测试集** | 在训练集上优化参数，在测试集上验证。如果在同一份数据上既优化又验证，你只是在过拟合 |
| **滚动前向验证 (Walk-Forward)** | 用历史数据训练 → 用未来数据测试 → 向前滚动。防止过拟合的标准做法 |

### 5.2 如何 Dig In — Demo 2（向量化回测）

**第一步：跑 Demo 2（1 小时）**

输出一张大图，包含 6 个子图：价格+均线信号、RSI、布林带、MACD、净值曲线、回撤曲线。

你关注的三个数字：**Sharpe**、**Max Drawdown**、**Win Rate**。这三个数字的组合比任何一个单独看都有意义。

**第二步：逐函数阅读（3 小时）**

```
generate_price_series()  ← 几何布朗运动生成模拟价格
sma() / ema() / rsi() / macd() / bollinger_bands()  ← 纯数学，你作为程序员应该 5 分钟看明白
MA Crossover 信号:  short_ma > long_ma → +1 (做多)
RSI 信号: RSI < 30 → 超卖买入, RSI > 70 → 超买卖出
VectorizedBacktester 类:
  _run():  信号 × 日收益率 = 策略日收益, 扣除交易成本
  metrics(): 返回全套绩效指标
Walk-Forward: 80% 训练 → 网格搜索最优参数 → 20% 测试验证
```

**第三步：动手修改（2 小时）**

1. **改均线参数**：把 SHORT_WIN=20, LONG_WIN=60 改成 (5,20), (10,30), (50,200)，对比 Sharpe 的变化
2. **改 RSI 阈值**：把 OVERSOLD=30, OVERBOUGHT=70 改成 (20,80) 和 (40,60)，观察交易频率和绩效变化
3. **自己实现一个新的指标策略**：基于布林带的策略——价格触及下轨买入、回到中轨卖出。不需要完美，重点是体验"信号规则 → 回测 → 看报告"的完整循环

**第四步：概念验收**

- 均线策略在什么时候疯狂亏钱？看图找答案（提示：价格横盘震荡时均线反复交叉）
- 为什么训练集的 Sharpe 总是高于测试集？
- `ma_signal.shift(1)` 里的 shift(1) 是干嘛的？删掉它会怎样？

### 5.3 如何 Dig In — Demo 3（事件驱动回测）

> **关键认知**：Demo 3 不是为了"再学一种回测方法"。它是为了让你理解**实盘交易系统是什么架构**。你未来用 vnpy 或自己写实盘系统，架构就是 Demo 3 的样子。

**第一步：跑 Demo 3，对比 Demo 2（30 分钟）**

同一个策略（MA Crossover 20/60），分别在 Demo 2（向量化）和 Demo 3（事件驱动）上跑。结果不一样——想想为什么不一样（提示：成交时机、最低佣金、整数股数）。

**第二步：理解事件循环（重点，2 小时）**

这是整个 Demo 系列最重要的架构图。你必须能闭着眼睛画出来：

```
Event Queue (FIFO)
      │
      ├── MarketEvent   ← DataHandler 逐天发送行情
      ├── SignalEvent   ← Strategy 收到行情后生成信号
      ├── OrderEvent    ← Portfolio 决定下多少单
      └── FillEvent     ← SimulatedBroker 模拟成交

主循环:
  while 还有更多数据:
    1. DataHandler.stream_next()  → 推一个 MarketEvent
    2. Broker.fill_pending(bar)   → 昨天订单今天开盘成交(无前视偏差!)
    3. while 队列不空:
         MarketEvent → Strategy.on_market()
         SignalEvent → Portfolio.on_signal()
         OrderEvent  → Broker.on_order()
         FillEvent   → Portfolio.on_fill()
    4. Portfolio.record_equity()  → 记录当日净值
```

**第三步：动手修改（1 小时）**

不需要大改。做一个概念验证就行——在 `Portfolio.on_signal()` 里加一个"单只股票最大仓位 20%"的限制：

```python
# 在 on_signal 中，计算 qty 后插入
max_qty = int((self.cash * 0.20) / current_price)
qty = min(qty, max_qty)
```

看看这个简单的风控规则对回测结果有什么影响。

---

## 6. 第四阶段：因子研究（第 7-8 周）

> **配套 Demo**: `quant_alpha_factor_demo.py` (1023 行)  
> **配套文档**: `doc_04_alpha_factor.md`  
> **核心问题**: 在 5000 只股票中，怎么知道哪些指标"有用"、哪些是噪音？

### 6.1 先理解的概念

这是整个学习路径中概念密度最高的阶段。必须逐条吃透。

| 概念 | 一句话解释 |
|------|-----------|
| **Alpha 因子** | 一个从数据中提取信号、能预测股票未来收益的数学公式。例如"过去 12 个月涨得多的股票，未来还会涨"——这就是动量因子 |
| **IC (Information Coefficient)** | 因子的当期值 与 股票未来收益 之间的 Spearman 相关系数。IC 越高 = 因子预测能力越强 |
| **IC 均值** | IC 时间序列的平均值。>0.05 算有效，>0.08 算强 |
| **ICIR** | IC 均值 / IC 标准差。类似夏普比率——衡量预测能力的稳定性。>0.5 算不错 |
| **截面 (Cross-Section)** | 同一个时间点上横跨多只股票的比较。例如"今天 50 只股票里谁的动量最高" |
| **分层回测 (Quantile Backtest)** | 按因子值将股票等分为 5 组，看最高组是不是真的跑赢最低组。比 IC 更直观 |
| **去极值 (Winsorize)** | 截断异常值。Demo 1 学过 |
| **Z-score 标准化** | 使因子均值=0，标准差=1。不同因子的量纲（% vs 元 vs 倍数）才能互相比较 |
| **市值中性化** | 回归剔除市值的影响。否则你的"高动量因子"可能只是在选小市值股票——动量是假的，小市值效应才是真的 |

### 6.2 关键直觉

因子研究最核心的哲学问题：**这个因子赚的是什么钱？** 如果你答不上来，说明你还没理解。

- 动量因子赚的是"趋势持续性"的钱——人们反应不足，好消息需要时间消化
- 价值因子赚的是"市场过度悲观后恢复"的钱——坏消息被过度定价，回归均值时你赚了
- 低波动因子赚的是"机构不能买低波动股票"的钱——机构受基准约束被迫买高波动，低波动被低估

### 6.3 如何 Dig In

**第一步：跑 Demo 4（30 分钟）**

输出 `alpha_factor_demo.png`（9 面板综合图）。重点关注：
- Panel 2: IC 时间序列 —— 哪个因子的 IC 最稳定？
- Panel 6: 分层回测 —— Q1 到 Q5 是不是单调递增？
- Panel 9: 因子衰减 —— IC 随着持有期延长怎么衰减？

**第二步：概念串联（2 小时）**

Demo 4 的流程 = 因子研究的标准工作流。把这个流程焊在脑子里：

```
§1 因子构建: 从原始价格中算出 5 个因子值
  ↓
§2 预处理:   去极值 → Z-score → 市值中性化
  ↓
§3 IC 分析:  每个因子和未来收益有多大相关性？
  ↓
§4 分层回测: 因子真的能把好股票和坏股票分开吗？
  ↓
§5 因子合成: 把多个因子合并成一个更强更稳的综合因子
  ↓
§6 多空组合: 买因子分最高的 20%，卖最低的 20%
  ↓
§7 因子衰减: 信号的有效期有多长？多久需要换仓？
```

**第三步：动手修改（2 小时）**

1. **改持有期**：把 `FORWARD_PERIOD = 21`（1个月）改成 5、42、63，观察各因子的 IC 怎么变
2. **自己构造一个新因子**：比如"成交量变化率"——过去 5 日成交量均值 / 过去 20 日成交量均值 - 1。写进 FACTORS 字典，跑一遍 IC 分析
3. **去掉市值中性化**：注释掉 `neutralize_mktcap` 那一步，对比 IC 的变化。如果 IC 大幅提升——你的因子可能只是在选小市值股票

**第四步：概念验收**

- IC=0.03 的因子能用吗？为什么？
- 为什么 IC 在持有期 63 天时通常比 1 天时低？
- 市值中性化后 IC 下降了，说明什么？

---

## 7. 第五阶段：组合优化（第 9-10 周）

> **配套 Demo**: `quant_portfolio_optimization_demo.py` (950 行)  
> **配套文档**: `doc_05_portfolio_optimization.md`  
> **核心问题**: 选了 N 只好股票，每只各买多少？

### 7.1 先理解的概念

| 概念 | 一句话解释 |
|------|-----------|
| **有效前沿 (Efficient Frontier)** | 所有"最优组合"连成的线——在相同风险下收益最高，在相同收益下风险最低 |
| **马科维兹优化** | 输入：预期收益 μ + 协方差矩阵 Σ。输出：最优权重 w。问题是 μ 非常难估计 |
| **最小方差组合** | 有效前沿最左边的点——风险最低的组合。不需要估计任何收益，只需要协方差 |
| **最大夏普组合** | 从无风险利率出发，与有效前沿相切的那个点 |
| **风险平价 (Risk Parity)** | 每只资产对组合总风险的贡献相等。桥水全天候策略的理论基础。比等权分散得更彻底 |
| **Black-Litterman** | 贝叶斯框架：从市场均衡权重出发（先验），加入你自己的观点（后验）。解决了马科维兹"μ 难估计"的痛点 |
| **Ledoit-Wolf 收缩** | 协方差矩阵的估计是有误差的。收缩到结构化目标矩阵后的协方差更稳健——条件数更低 |
| **条件数 (Condition Number)** | 矩阵"病态"程度。条件数高 → 优化对输入误差极度敏感 → 鲁棒性差 |

### 7.2 关键直觉

组合优化不是让你"算出最优权重然后去赚大钱"。它的真正价值是**约束你的贪婪**——告诉你在分散风险的前提下，你能合理预期赚多少。

Demo 5 的图 1（有效前沿图）多看几眼：那团灰色的随机组合云和那条金色的有效前沿曲线——任何一个随机组合，要么在有效前沿下方（同样风险但收益更低），要么在有效前沿右侧（同样收益但风险更高）。这就是"分散投资"的数学本质。

### 7.3 如何 Dig In

**第一步：跑 Demo 5（30 分钟）**

输出 `portfolio_optimization_demo.png`。重点看：
- Panel 1: 有效前沿 + 5 个关键组合的位置
- Panel 4: 5 种策略的净值曲线——谁跑赢了谁？
- Panel 7: 月度收益箱形图——哪种策略的月度收益最平稳？

**第二步：理解核心公式（1 小时）**

打开 `portfolio_stats()` 函数：
```python
ret   = w @ mu          # 组合收益 = 权重 × 预期收益
var   = w @ Σ @ w       # 组合方差 = 权重 × 协方差矩阵 × 权重
vol   = sqrt(var)        # 组合波动率
sharpe = (ret - rf) / vol
```
这就是组合优化的全部数学。你作为程序员，线性代数不用教。

**第三步：动手修改（1 小时）**

1. **改约束**：把 `MAX_STOCK_WT = 0.15` 改成 `0.30`，看最大夏普组合的权重变化
2. **观察无约束组合**：把 `allow_short=True` 传给 `max_sharpe()`，看允许做空后权重长什么样（会有负权重）
3. **对比滚动回测**：demo 里 §7 的滚动回测演示了 5 种策略在样本外的真实表现差异——最大夏普组合在样本外不一定是最好的

---

## 8. 第六阶段：实战项目 — ETF 轮动（第 11-12 周）

> **配套 Demo**: `quant_etf_rotation_demo.py` (849 行)  
> **配套文档**: `doc_07_etf_rotation.md`  
> **核心问题**: 把学到的全部串起来，做一个接近实战的策略

### 8.1 为什么以 ETF 轮动作为终章

- 逻辑简单：每月算一次动量 → 买最强的 3 只 ETF → 持有一个月 → 重复
- 实盘可行：ETF 流动性好、T+0 可交易、不怕个股暴雷
- 整合了所有前置知识：数据清洗 (Demo 1) → 信号生成 (Demo 2) → 回测引擎 (Demo 3) → 因子/分层 (Demo 4)
- 双动量策略自带风控：熊市自动切换国债 ETF

### 8.2 如何 Dig In

**第一步：跑 Demo 7 + 读文档 + 读代码（3 小时）**

这是你第一次看到"完整策略"的全貌。关注点不是代码细节，而是**各部分如何组合**。

**第二步：切换到真实数据（2 小时）**

```bash
python demo_akshare_data.py  # 拉取真实 ETF 日线数据
```

然后把 `demo_akshare_data.py` 生成的 `data/etf_price_panel_clean.csv` 读入 Demo 7，替代合成数据：
- 找到 Demo 7 的合成数据生成部分（`returns_df` 和 `price_df`）
- 替换为 `pd.read_csv("data/etf_price_panel_clean.csv", index_col=0, parse_dates=True)`
- 重新运行，对比合成数据的回测结果和真实数据的回测结果有什么不同

**第三步：参数敏感性分析（2 小时）**

对下面三个参数做简单扫描：
- `top_k` ∈ {2, 3, 4, 5}
- 动量回望期 ∈ {(3,1), (6,1), (12,1), (6,1)+(12,1)合成}
- 国债 ETF 切换阈值 ∈ {0, 国债收益率, 均线}

每个参数组合记录 Sharpe 和 Max Drawdown，观察哪个参数最敏感。

**这个练习的价值不在于"找到最优参数"——而在于让你意识到：回测结果对这些参数有多敏感。如果你发现改一个参数 Sharpe 从 1.5 变成 0.3，说明策略非常脆弱。**

---

## 9. 从 Demo 到平台的切换时机

### 什么时候该从本地 Demo 切换到在线平台？

**当你开始问以下问题时：**

- "我想在沪深 300 成分股里按动量因子排序，选前 30 只——但本地只有 50 只股票的 Demo 数据"
- "我想知道这个因子在 2010-2020 年的表现——但本地没有这么长的全市场数据"
- "我想看看真实交易成本对策略的影响——但本地模拟的滑点模型太简单了"

**切换路径**：

```
① 注册聚宽 或 米筐
② 在平台 Notebook 里重写你的因子/策略代码
   (代码结构几乎一样，只是数据获取方式从 ak.fund_xxx() 变成平台内置 API)
③ 利用平台的现成数据，跑全市场回测
④ 开模拟交易，让策略自动运行
```

本地 Demo 是你的**概念实验室**，平台是你的**全市场验证场**。两者不是替代关系，是配合关系。

---

## 10. 贯穿全程的学习方法

### 十条原则

1. **先理解概念，再写代码。** 不知道 Sharpe 怎么算就写回测引擎，等于蒙着眼睛开车。

2. **小数据手动验证，再大规模自动跑。** 用 20 只股票验证你的逻辑正确，再放到 5000 只上跑。

3. **每次只改一个参数，看它的影响。** 一次改三个参数，你不知道是哪个导致了结果变化。

4. **把每次实验结果记录下来。** 日期、改了哪个参数、Sharpe/MaxDD 变成多少、你的判断。两周后你绝对记不清。

5. **读代码时，画出数据流图。** 合上文件能画出数据怎么流动，说明真懂了。

6. **不要迷信一个数字。** Sharpe 1.5 不代表策略好——可能只是过拟合。看一组指标：Sharpe + MaxDD + Win Rate + Calmar。

7. **遇到不懂的，先手动算一遍。** "IC 到底怎么算的？"——取 5 只股票某一天的因子值和它们下一个月的收益，用 Excel 或 NumPy 手动算一遍 Spearman 秩相关。比看十遍文档都管用。

8. **对比永远比绝对值重要。** "我写的因子 IC = 0.04"——在 0.04 是好是坏？你得和经典因子（动量/反转/低波）的 IC 对比才知道。

9. **模拟交易是实盘的必修课。** 没有在模拟环境跑满 1-2 个月的策略，不上实盘资金。不是技术问题——是你会发现自己对策略的信任程度完全不够。

10. **如果一个策略你不能用三句话讲清楚它赚的是谁的钱，就不要投钱。**

### 每周时间分配

```
读文档 + 学概念:  1-2 小时
读代码:           1-2 小时
跑 Demo + 观察:   30 分钟
动手修改代码:      1-2 小时
写笔记:            20 分钟
浏览行情软件:      随意，建立市场感觉
─────────────────────────
每周总计:          5-8 小时
```

### 笔记模板

每个 Demo 学完后，用这个模板写 5 分钟笔记：

```
【Demo X: 名称】  日期:

三个核心概念:
  1. ...
  2. ...
  3. ...

一个疑问 (还没想明白的事):
  ...

一个改动 (我改了什么、结果怎么变了):
  ...
```

---

## 附录：关键概念速查卡

```
┌──────────────┬─────────────────────────────────────────────┐
│ 数据层        │                                             │
├──────────────┼─────────────────────────────────────────────┤
│ 前复权        │ 历史价格按今天股本折算，当前价 = 真实价       │
│ ffill         │ 向前填充缺失值；禁止 bfill (前视偏差)        │
│ Winsorize     │ 截断极端值到分位数边界，不删除数据点          │
│ MAD           │ 比 Z-score 更稳健的异常值检测方法             │
├──────────────┼─────────────────────────────────────────────┤
│ 策略层        │                                             │
├──────────────┼─────────────────────────────────────────────┤
│ 趋势跟随      │ 追涨杀跌；震荡市反复亏损                      │
│ 均值回归      │ 反转交易；强趋势中逆势被碾压                  │
│ 金叉/死叉     │ 短期均线上穿/下穿长期均线                     │
│ RSI           │ 0-100；>70 超买(该跌)；<30 超卖(该涨)        │
├──────────────┼─────────────────────────────────────────────┤
│ 因子层        │                                             │
├──────────────┼─────────────────────────────────────────────┤
│ IC            │ 因子值与未来收益的秩相关系数；衡量预测力       │
│ ICIR          │ IC均值/IC标准差；衡量预测稳定性               │
│ 截面标准化    │ 同一天内不同股票之间做 Z-score                │
│ 市值中性化    │ 回归剔除市值影响，提取纯净的因子信号           │
│ 分层回测      │ 按因子分 5 组，Q5-Q1 价差 = 因子收益          │
├──────────────┼─────────────────────────────────────────────┤
│ 组合层        │                                             │
├──────────────┼─────────────────────────────────────────────┤
│ 有效前沿      │ 风险收益空间中所有最优组合连成的曲线           │
│ 风险平价      │ 每只资产贡献相同风险；比等权更均衡             │
│ Black-Litterman│ 先验(市场均衡) + 你的观点 → 后验权重          │
├──────────────┼─────────────────────────────────────────────┤
│ 评估层        │                                             │
├──────────────┼─────────────────────────────────────────────┤
│ Sharpe        │ (年化收益-无风险利率)/年化波动；>1 算不错      │
│ Max Drawdown  │ 历史最大回撤；你能承受的极限是策略的底线       │
│ Calmar        │ 年化收益/|最大回撤|；越高越好                │
│ 前视偏差      │ 回测中使用了未来信息 → 结果不可信              │
│ 幸存者偏差    │ 只回测现在还活着的股票 → 遗漏了退市的失败者     │
└──────────────┴─────────────────────────────────────────────┘
```
