投資組合建構實驗室
同一批股票,用 6 種方法建投組,權重差多少、績效差多少? 在這裡親手選股、勾方法、即時比較,完成後可以帶走一份完整的策略報告。
開始之前
🕹️ 你要做什麼
- 讀「觀念導覽」——點開各建構法的公式與直覺。
- 進入實驗室:選資產、設回測區間、勾選 6 種建構法。
- 看並排比較:權重、效率前緣、權益曲線、回撤、KPI 表。
- 完成 5 題引導式練習,自己算一遍。
- 讀「教學洞見」,把 Markowitz 詛咒、估計誤差等陷阱內化。
- 進階:打開 Colab 區塊,用 NumPy / cvxpy 親手解同一批權重。
🧠 要建立的觀念
- 建投組的核心是「在風險與報酬之間取捨」,不是選「最好的」一檔。
- 每種建構法背後都有哲學假設:用不用 μ?重風險還是重資本?
- 樣本內(in-sample)漂亮 ≠ 樣本外(out-of-sample)也漂亮,要警覺過擬合。
- 效率前緣告訴你「報酬-風險最佳可能」,但實務上常做不到。
🛠️ 會學到的方法
- 等權、市值、逆波動、風險平價、GMV、Max Sharpe 的完整公式。
- 共變異數矩陣 $\Sigma$ 與矩陣反運算 $\Sigma^{-1}$ 的計算。
- 求切點組合(Tangency Portfolio)的閉式解。
- 用牛頓迭代解風險平價權重。
📘 觀念導覽 · 6 種建構法的哲學與公式
投資組合建構的核心問題是:「有 N 檔資產,該把資金怎麼分配?」不同流派給出不同答案。 點擊下方各方法展開,看公式、直覺、優缺點。
- 是否用到預期報酬 $\mu$?(用了就會放大估計誤差)
- 是否有閉合解(一條公式算出)還是需要迭代?
- 是否允許放空(負權重)?
① 等權 (1/N) 最簡單
② 市值加權 (Market-Cap) 指數基金的底層
③ 逆波動加權 (Inverse Volatility) 風險感知
④ 風險平價 (Risk Parity / ERC) Bridgewater 流派
⑤ 最小變異 (GMV) 馬可維茲 · 封閉解
⑥ 最大夏普 / 切點組合 (Max Sharpe / Tangency) 理論最優
1. 等權 / 市值 / 逆波動不需要估 $\mu$ 或 $\Sigma$(或只估一部分),穩健但不最優。
2. 風險平價 / GMV需要估 $\Sigma$,次穩健,不用 $\mu$,實務常見。
3. Max Sharpe需要估 $\mu$ 與 $\Sigma$,最不穩健,理論最優但樣本外常翻車。
STEP 1選擇資產
建議選 3 ~ 6 檔資產:太少看不出分散效果,太多矩陣運算會失真。點擊卡片勾選/取消。
STEP 2回測設定
這些參數會影響「怎麼算」出來的結果。方法論的第一層選擇,就從這裡開始。
(1+μ_daily)^252 - 1(幾何法);
學術文獻常見另一種 μ_daily × 252(算術法),兩者在高波動時會差很多。
本實驗室採幾何法,因為它能還原實際累積報酬。
STEP 3挑選建構方法(可多選)
勾越多可以並排比較;建議至少勾 3 種,才看得出差異。
STEP 4權重與績效比較
同一批資產、同一段期間,不同方法的權重分配與績效表現。
視覺化馬可維茲效率前緣
雙曲線上的每一點都代表「那個報酬下,變異數最低的組合」。你選的 6 種建構法會標在圖上, 離前緣越近代表越有效率。
風險 - 報酬平面 橫軸:年化波動度 ・ 縱軸:年化報酬率
權益曲線(累積報酬) 以 1 元為起始本金
回撤 (Drawdown) 從歷史高點往下跌的比例
📝 引導式練習題
下列題目指定了資產與期間(仿照你熟悉的 Word 習題風格)。請自己動手算, 或用上方實驗室輔助,填入答案後點「核對」,系統會告訴你對不對、並回饋正確解。 數值格式一律 XX.XX% 或 0.XXXX,誤差 < 0.05% 視為正確。
🔍 教學洞見 · 6 個關鍵觀念
實驗室讓你看到「結果」,這一段解釋「為什麼」。每張卡片都指出一個 投資組合理論裡容易被忽略、但會直接影響你投資決策的細節。
Markowitz 詛咒:μ 難估,動一點 Max Sharpe 就全變
Max Sharpe 的公式是 $w \propto \Sigma^{-1}(\mu - r_f \mathbf{1})$。把任何一檔資產的 年化報酬估計調高 1%,權重常常就會從 +30% 跳到 +80%、甚至負值翻正。 $\mu$ 的估計誤差平均約 $\sigma/\sqrt{T}$,用 5 年日資料仍是報酬本身的 1/√1260 × 年化 ≈ 2~5%,跟真值根本同量級。
親手驗:把 STEP 2 起始日調早/晚半年,看 Max Sharpe 權重變化幅度,再看 GMV 幾乎不動。
mu2 = mu.copy(); mu2[0] += 0.01
w_a = np.linalg.solve(Σ, mu - rf)
w_b = np.linalg.solve(Σ, mu2 - rf)
# normalize, 看 (w_b - w_a) 常常是 20~60% 級的差
GMV 不用 μ,所以穩定——但它不是「最好」,是「最穩」
GMV 的封閉解 $w = \Sigma^{-1}\mathbf{1} / (\mathbf{1}^\top \Sigma^{-1} \mathbf{1})$ 只仰賴 $\Sigma$ 估計,完全不用 $\mu$。相當於告訴你 「在所有權重相加 = 1 的組合裡,哪一個的波動度最小」。 實務上 GMV 樣本外的 Sharpe 常常比 Max Sharpe 還高,穩定 > 最優。
親手驗:在實驗室裡比較 GMV 和 Max Sharpe 的「權重分散度」, GMV 通常更集中在低波動的債券 ETF(如 TLT)。
ones = np.ones(len(tickers))
w_gmv = np.linalg.solve(Σ, ones)
w_gmv /= w_gmv.sum()
共變異數條件數:Σ 幾乎不可逆時,$\Sigma^{-1}$ 會爆炸
當資產高度相關(例如全是美股科技股),$\Sigma$ 的最小特徵值接近 0, 求逆之後數值會放大 1000 倍以上。條件數 $\kappa(\Sigma) = \lambda_{max}/\lambda_{min}$ 超過 1000 就該警戒。 解法:對 $\Sigma$ 做 Ledoit-Wolf shrinkage,朝對角線收縮一點。
親手驗:用 python 算 $\kappa = $ np.linalg.cond(sigma),
把 AAPL/MSFT/GOOGL/META 放一起你會看到 κ > 500。
κ = np.linalg.cond(Σ) # > 1000 警戒
from sklearn.covariance import LedoitWolf
Σ_shrunk = LedoitWolf().fit(rets).covariance_ * 252
風險平價的槓桿問題:低風險資產會被買爆
Risk Parity 要求每檔資產對總風險的貢獻相等,結果就是 低波動的債券 / 黃金被加重。Bridgewater 的 All Weather 因此要搭配槓桿 (借錢買債),才能讓組合總報酬拉到跟股票相近。不上槓桿的 RP 報酬會偏低。
親手驗:勾選 VTI + TLT + GLD,比 RP 和等權的年化波動度。 RP 波動度低一半,但 CAGR 也低一半,Sharpe 卻相近。
mrc = Σ @ w # 邊際風險貢獻
rc = w * mrc # 各資產風險貢獻
# RP 目標:rc[i] 全部相等 = σ_p² / N
樣本內 vs 樣本外:績效評估的黃金準則
所有用整段期間資料算出來的權重,套回整段期間報酬,都是「樣本內」。 樣本內的 Sharpe 跟明牌沒兩樣——資料都看過了當然漂亮。 要真正評估一個方法,必須切 train/test:前 3 年估權重,後 1 年看表現;滾動做。
親手驗:打開 Colab notebook 看 2015–2021 train → 2022–2026 test 的 OOS 對照,Max Sharpe 會掉很多。
train = rets.loc[:"2021-12-31"]
test = rets.loc[ "2022-01-01":]
w = solve_msr(train) # 只用過去估
oos = test @ w # 在未來看表現
放空限制:實務上的 $w_i \geq 0$ 會改變一切
閉式解常給出負權重(尤其 Max Sharpe),但真實投資人大多不能放空。 加上 $w_i \geq 0$ 後問題變成 QP (二次規劃),沒有封閉解,要用 cvxpy / scipy。 限制後的 GMV 通常集中在 2~3 檔資產——能分散的路就少了。
親手驗:在 Colab 裡用 cvxpy 加上 w >= 0 約束,
比較「有/無放空限制」的 Max Sharpe 權重差幾倍。
import cvxpy as cp
w = cp.Variable(n)
cp.Problem(cp.Minimize(cp.quad_form(w, cp.psd_wrap(Σ))),
[cp.sum(w) == 1, w >= 0]).solve()
上方每張洞見卡都附 3~5 行對應程式碼。完整版 notebook 把它們串成: 下載資料 → 求 GMV/MSR → cvxpy 加限制 → Train/Test OOS 對比。 在
lab3_markowitz.ipynb 一鍵重現。