固定部位大小會忽略市場環境。波動度目標化根據當前市場波動程度,自動調整每次下注的規模。
基本的 Type A 策略輸出 1.0(做多)或 0.0(空手)。Runner 在訊號為 1.0 時把全部配置資金都投入。這樣做有效,但有個隱性問題:不管市場是平靜還是劇烈波動,策略下的注都一樣大。
在低波動期,1% 的日線波動已經算大。在高波動期,1% 的波動只是雜訊。如果策略在兩種環境都用同樣的部位大小進場,實際的金額風險就會大幅波動——高波動期的回撤會遠大於回測平均所暗示的水準。
BlaveClaw 的波動度目標化分兩步:
log_return = log(Close / Close.shift(1)) realized_vol = log_return.rolling(lookback).std() * sqrt(periods_per_year)
計算對數報酬率的滾動標準差,再乘以 sqrt(periods_per_year) 換算成年化。結果就是年化已實現波動度——和 Sharpe ratio 使用的波動度單位相同。
預設值:lookback=720 根 K 棒、periods_per_year=8760。這是為1h 週期策略校準的:720 根 = 30 天 × 24 小時;8760 = 24 × 365。
scale = (target_vol / realized_vol).clip(upper=vol_cap) scaled_signal = signal * scale
訊號(1.0 = 全額做多)乘以波動度比值,上限為 vol_cap,得到小數部位大小。
預設值:target_vol=0.30(年化 30%)、vol_cap=2.0(最大 2 倍槓桿)。
| 已實現波動(年化) | 目標波動 | 原始倍數 | 套用上限後 | 部位大小 |
|---|---|---|---|---|
| 10% | 30% | 3.0× | 2.0×(上限) | 配置資金的 200% |
| 20% | 30% | 1.5× | 1.5× | 配置資金的 150% |
| 30% | 30% | 1.0× | 1.0× | 100%——基準 |
| 60% | 30% | 0.5× | 0.5× | 配置資金的 50% |
| 90% | 30% | 0.33× | 0.33× | 配置資金的 33% |
已實現波動在 30% 時,策略以全額運行。危機期間波動飆升到 90% 時,策略自動縮減至三分之一部位。平靜期波動降至 10% 時,放大到上限 2 倍。
預設值(lookback=720、periods_per_year=8760)是為1h 策略設定的。其他週期必須重新計算:
| 週期 | periods_per_year | lookback(30 天窗口) |
|---|---|---|
5min | 105,120(12 × 24 × 365) | 8,640 根 |
1h(預設) | 8,760 | 720 根 |
4h | 2,190 | 180 根 |
8h | 1,095 | 90 根 |
1d | 365 | 30 根 |
VOL_TARGETING = True
TARGET_VOL = 0.30 # 年化目標波動 30%
VOL_CAP = 2.0 # 最大 2 倍槓桿
VOL_LOOKBACK = 720 # lookback 窗口長度(根 K 棒)
PERIODS_PER_YEAR = 8760 # 1h 週期用
def fetch_data(hdrs):
from lib.data import fetch_kline
from lib.strategy import add_realized_vol
df = fetch_kline(SYMBOL, INTERVAL, START, END, hdrs)
if VOL_TARGETING:
add_realized_vol(df, VOL_LOOKBACK, PERIODS_PER_YEAR)
return df
def compute_signals(df):
from lib.strategy import apply_vol_scaling
signal = pd.Series(np.nan, index=df.index)
# ... 訊號邏輯 ...
if VOL_TARGETING:
return apply_vol_scaling(signal, df, TARGET_VOL, VOL_CAP)
return signal
注意:add_realized_vol 必須在 fetch_data 裡呼叫(訊號計算之前),因為 apply_vol_scaling 會讀取 df['realized_vol'],而這個欄位是第一個函式就地寫入的。
上限的存在是因為在持續低波動的環境下,波動度目標化可能產生極端槓桿。如果已實現波動降到 5%,沒有上限的倍數會是 6 倍。單日不利的走勢就可能造成毀滅性的回撤,即使訊號本身完全正確。
預設 2× 的上限讓策略最多只用到配置資金的兩倍。如果你完全不想有槓桿,把 vol_cap=1.0——波動度目標化就只會在高波動時縮減部位,不會在低波動時放大超過全額。
一個實用的經驗法則:target_vol ≈ 可接受 MDD ÷ 2。這來自趨勢追蹤策略中年化波動度和最大回撤的經驗關係。
| target_vol | 隱含典型 MDD | 適合情境 |
|---|---|---|
| 10% | 約 −20% | 保守型,資金保全優先 |
| 20% | 約 −40% | 中等 |
| 30%(預設) | 約 −60% | 積極型——用滿風險預算 |
組合 Manager 在決定整體組合槓桿時也用同樣的邏輯:槓桿 = target_vol / 組合已實現波動。把個別策略的 TARGET_VOL 設定和 Manager 的 target_vol_pct 保持一致,可以避免多個策略組合時重複計算風險。