今次篇文主要講點樣由搵到統計顯著性 (statistically significant) 既alpha 再嚴謹啲去證明係可靠既alpha,因為我諗好多人搞錯左搵到紙上alpha同再嚴僅驗證既分別,所以今次同大家分享真實行內quant點樣去令回測更嚴謹同準確。以前未開始做而行個陣,聽好多人 (主要係hku個陣既同學同埋一啲岩岩出黎做左無耐既junior師兄) 講咩學術既野無用,例如咩markowitz efficient frontier之類,係industry用唔著。一開始我信,仲信到十足,但慢慢入左行後發覺其實好多學校學既野都係經常會用到既concepts,只係轉換成更加realistic既模式,例如好似今日同大家分享既 Newey-West方法。
先睇睇,策略基本要求同標準 t-test 既問題:
係hedge fund既角度,一個成功既量化策略通常要滿足以下三大要求:
大家都知的一般料 -> 策略扣除所有成本後正數﹑高sharpe﹑低MDD
低相關性、容量夠大
新 alpha 要可以放大,唔同現有組合高相關。咁樣先可以避免太多 overlap,確保分散風險。
統計顯著性
策略回報要夠顯著,通常要求 alpha t-stat 要大過 3 (近而幾年有啲直頭而4 / 5),咁樣先表示個 alpha 唔似係隨機噪音。
咁如果要講到統計顯著性,standard 既 t-test 就走唔甩。我諗好多朋友都知係幾theoretical既test黎,雖然好多人會用,但我諗本身對t-test深入了解既人唔多,因為好多人用既原因都係因為可能大學做project或者交功課俾老細。T-test 假設每一筆資料都獨立,無咩自相關,但而種假設會令到係金融數據預測出黎既t-stat 結果好容易被抬高,令人誤以為策略較大機會賺錢,因為金融數據往往有自相關(Autocorrelation)同異方差(Heteroskedasticity)。例如,如果你做日頻策略,而信號半衰期得 3 天,咁即係話今日個回報同未來幾日回報係高度相關。咁樣用 t-test既話,個標準誤會被低估,結果 t-stat 就會 overestimated,令你易誤判策略真係有 alpha。
行內有好多方法去 downward adjust個t-stat,其中一個較出名而有用既方法係 Newey–West (NW) 標準誤調整方法。
咁 Newey–West 方法即係咩? 同埋點樣可以減低 t-stat overestimate的可能性?
Newey–West 方法為彌補標準 t-test 既短處,通過調整協方差矩陣,將自相關(N個lag) 同異方差考慮埋入個model。我就唔係度詳講太technical既計法,有興趣既可以直接chatgpt / grok,你應該會見到類似以下既公式:
咁條公式係做緊咩? 簡單黎講,Newey–West方法會先計算零滯後(當期)的誤差方差,然後針對一定滯後階數(Lag),計算各個滯後期誤差之間的協方差。每個滯後期的協方差會乘以一個逐漸遞減的權重(通常權重為1-滯後期/(L+1)),再加到整體的協方差矩陣。咁樣得到的調整後協方差矩陣就同時納入了資料在不同時間點間的相關性和變動性,使得估計出的標準誤更穩健(即robust)。最終,而個方法修正因自相關和異方差導致的標準誤估計偏差,令t-stat的結果更加可信。
咁你可能會問點樣選lag既periods?
教科書公式既:「floor(4*(T/100)^(2/9))」,例如月頻數據 T = 600 約等於 5。但係實戰當中,我地通常根據資料特性同市場行為作出經驗調整:
月頻 600 點:用 Lag = 5;
日頻 5000 點:用 Lag = 4;
高頻資料:就要用 HAC + Pre-whitening,再加上 Andrews (1991) 方法動態調整 Lag。
要明白,Lag 太細,可能漏左啲自相關;Lag 太大,又可能令標準誤過度膨脹,將好策略扼殺,所以呢個取捨真係需要經驗同市場觀察。我既rule of thumbs 係選lag = 1 至 理論數字而個range中最差果個,學黎明話齋,如果最差都唔太差,咁就信而個既t-value。
講多無謂,睇個例子。我地會用一個 AR(1) 模型模擬回報,加入隨機波動率,模擬出市場既異方差現象。
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
# 設定隨機種子,確保結果重現性
np.random.seed(42)
T = 5000 # 模擬 5000 天日頻數據
alpha = 0.001 # 每日平均回報
beta = 0.3 # AR(1) 自相關係數
# 模擬一組隨機波動率(異方差),介乎 1% 到 2%
vol = np.random.uniform(low=0.01, high=0.02, size=T)
# 初始化回報數據同誤差項
returns = np.zeros(T)
errors = np.random.randn(T) * vol # 將波動率引入噪音
# 利用 AR(1) 模型計算回報
for t in range(1, T):
returns[t] = alpha + beta * returns[t - 1] + errors[t]
# 畫圖展示模擬出嚟嘅回報軌跡
plt.figure(figsize=(12, 4))
plt.plot(returns, color='blue', lw=1)
plt.title("模擬日頻回報數據")
plt.xlabel("天數")
plt.ylabel("回報")
plt.tight_layout()
plt.show()
介紹返:
段code用 AR(1) 模型去產生回報數據,同時因應波動率 vol 而呈現出唔同時段既 volatility 差異,同我地實戰入面類似,因為市場唔係每日都穩定波動,同埋波動magnitude都可以好唔同,所以一定要反映到呢啲特性。
之後就做個傳統 OLS 同 NW 調整嘅回歸分析。我地做個簡單既 OLS 回歸,只用常數項(代表平均回報),然後比傳統參數估計同 NW 調整後既結果做個對比。
# 構造資料:只有常數項,代表每日平均回報
X = sm.add_constant(np.ones(T))
# 傳統 OLS 回歸(無調整標準誤)
model_standard = sm.OLS(returns, X).fit()
print("【傳統 OLS 回歸】")
print("參數估計值:", model_standard.params[0])
print("標準誤:", model_standard.bse[0])
print("t 統計量:", model_standard.tvalues[0])
print("="*60)
# 使用 Newey–West 調整,這裡預設 Lag = 10,適用於日頻 5000 點數據
model_nw = sm.OLS(returns, X).fit(cov_type='HAC', cov_kwds={'maxlags': 10})
print("【Newey–West 調整後】")
print("參數估計值:", model_nw.params[0])
print("NW 標準誤:", model_nw.bse[0])
print("NW t 統計量:", model_nw.tvalues[0])
重點黎了:
你會發現,用標準 OLS 既標準誤明顯比較細,而 NW 調整左自相關同異方差之後,標準誤會大返,t 統計量自然就低左。呢個就證明,如果唔處理好自相關,數字會overestimated,容易誤判策略有 edge / alpha。
再睇唔同 Lag 值之間比較:
記得上面講過,Lag 既選取都好重要。我地試下 Lag = 5、10 同 15 既效果,睇下 NW 標準誤同 t 統計量係點變化。
lag_values = [5, 10, 15]
nw_results = {}
print("【不同 Lag 值下嘅 NW 調整結果】")
for lag in lag_values:
model_tmp = sm.OLS(returns, X).fit(cov_type='HAC', cov_kwds={'maxlags': lag})
nw_results[lag] = {
'mean': model_tmp.params[0],
'NW_se': model_tmp.bse[0],
't_stat': model_tmp.tvalues[0]
}
print(f"Lag = {lag} -> 參數估計: {model_tmp.params[0]:.6f}, NW 標準誤: {model_tmp.bse[0]:.6f}, NW t 統計量: {model_tmp.tvalues[0]:.6f}")
小結:
當 Lag 值由 5 調升到 15,參數估計穩定,但 NW 標準誤由5升到10係逐漸升高,之後就flat;
t 統計量相應降左落嚟,反映出較大 Lag 可以捕捉更多自相關。如果按頭先講既黎明方法去選,我會選lag = 10,選個低啲既數值較安全。太大既話其實都唔太現實,一般我唔會取>5,上面只係simulated例子,大家留意。
最後,講多少少 NW 方法係capital allocation入面既真實應用
有時候你見到個策略 t-stat 好高,但佢背後既風險管理就未必夠精密,所以我地會用 NW 標準誤黎決定頭寸。
個調倉公式是咁的:
weight = target_vol / (NW_se * square root of annualization)
簡單講:
target_vol 係你目標波動率(例如 10% 年化)
NW_se 就係 NW 調整後嘅標準誤
annualization 係例如交易日數(252日)
舉個例:
如果目標年化波動率係 10%,而根據 NW 方法計算出日度 NW_se 為 0.0028,年化後大概就係:
weight = 0.1 / 0.0028 * square root of 252 = ~2.25
個implication係,當市場波動較大,NW_se 升高,頭寸就會自動調低,從而控制風險;反之,風險細既時候,有多啲信心可放大倉位。
最後,希望大家睇唔明既話,再睇多次,因為我分享緊既唔係一啲睇完就即刻明既野,我建議最好方法係,你可以諗下點樣將以上NW直接應用到你的交易風險管理同verify alpha,因為而啲都係行內practitioners用緊既方法,什至好過大家睇完好多書+應用埋但其實行內practitioners可能都唔用或者覺得無咩用,變相浪費左時間。加油!
Cheers,
阿程