進階課程 · Lesson 2
簡單報酬:
r_t = P_t / P_(t-1) − 1
對數報酬:
g_t = ln(P_t / P_(t-1))
Log return 可跨期相加,simple return 才直接對應資產比例變化。上漲 50% 後下跌 50%,結果是 1.5×0.5−1 = -25%,不能將兩個百分比直接相消。
CAGR(複合年成長率):
CAGR = (V_end / V_start)^(1 / years) − 1
CAGR 只看起點、終點與時間,不描述中間是否曾經腰斬。
一般以單期報酬的 sample standard deviation(樣本標準差)估計。每日資料常用:
annual_vol = daily_std × sqrt(252)
這依賴變異數可隨時間相加的近似。報酬有 autocorrelation 或 volatility clustering 時,單純平方根年化可能失真。美股日資料常用 252;全年交易的 crypto 日資料通常用 365。年化係數必須與資料頻率一致。
William Sharpe 1994 年的表述核心是 excess return(超額報酬)相對於 variability(變異性):
Sharpe = mean(R − Rf) / std(R − Rf)
若以每日資料計算,再乘 sqrt(252) 年化。Risk-free rate 必須先換算成每日頻率。
Sharpe 回答的是「每單位總波動換到多少超額報酬」,但有五個限制:
所以清單上的 0.892 是特定估計值,不是策略永恆屬性。
Sortino 只用低於 minimum acceptable return(最低可接受報酬)的 downside deviation:
Sortino = annualized excess return / annualized downside deviation
若 Sortino 遠高於 Sharpe,常表示大部分波動來自上漲,或報酬呈正偏態;但也可能只是樣本很短、沒有捕捉到尾端虧損。
Calmar:
Calmar = CAGR / abs(max_drawdown)
它用單一最深回撤作分母,對回測起訖點與極端事件敏感。
running_peak_t = max(V_0 ... V_t)
drawdown_t = V_t / running_peak_t − 1
max_drawdown = min(drawdown_t)
資產 100 → 120 → 90 → 125 的最大回撤是 90/120−1 = -25%。Drawdown duration 則是從前高開始,到重新回到或突破前高的時間。深度相同、恢復五天與五年的策略,心理與資金成本完全不同。
| 指標 | 回答的問題 | 主要盲點 |
|---|---|---|
| CAGR | 長期複合成長多少 | 不看路徑 |
| Volatility | 報酬分散程度 | 不等同永久損失 |
| Sharpe | 每單位總波動的超額報酬 | 尾端與非正態 |
| Sortino | 每單位下行波動的報酬 | 定義不一致、短樣本 |
| Max drawdown | 歷史最深跌幅 | 只取單一事件 |
| Calmar | 每單位最深回撤的 CAGR | 對期間敏感 |
至少同時檢視:回測年數、regime、曝險、槓桿、成本、trade count、benchmark、rolling metrics 與樣本外績效。
執行:
python .\code\performance_metrics.py
接著修改範例 equity curve,使最終值相同但中間先下跌 40%,觀察 CAGR 不變而 max drawdown 與 Calmar 改變。
某策略年化報酬 30%、波動率 60%;另一策略年化報酬 12%、波動率 10%。忽略無風險利率,粗略 Sharpe 分別為 0.5 與 1.2。這不代表第二個必然值得投資,但代表它在這組假設下的風險調整效率較高。