DM 檢定說三種做法顯著較好,結論卻是 NULL:K546 的裁決規則拆給你看
讀者互動
登入會員可按讚與收藏。
持續追蹤這項研究
收藏、追蹤與明日提醒只保存必要識別資料,可在會員中心檢視或刪除。
研究資訊不構成個人投資建議;提醒僅代表研究更新,不代表交易訊號。
K546 問的是一個乾淨的問題:在一個股票一半、黃金一半的組合裡,能不能用黃金自己的波動體制決定要不要調整黃金的比重。資料是 2005-02-03 到 2026-03-27、5,320 個交易日的 SPY、GLD 與 ^VIX 日資料,來源 yfinance。對照組是靜態五五分。
結論欄位寫得很直接:conclusion.verdict 是 NULL — No GLD-vol-based allocation timing beats static 50/50,any_strategy_passes 是 false。
但同一份結果檔裡,四種擇時做法有三種的 Diebold-Mariano 統計量落在 3.27 到 8.93 之間,p 值 0.001065 或更小。
一般讀者版〈黃金自己抖的時候就少放一點黃金?二十一年資料跑完,四種做法沒有一種贏過固定五五分〉已經把這個現象講成「兩把尺量的是不同的東西」,並停在那裡。這篇要往下走一層: 那把說「顯著較好」的尺,量的到底是什麼,以及判 NULL 的機制其實不在它身上。 前一篇沒有回答這件事,本篇的主張都是新的。
一、全期成績與三道閘的原始數字
先把兩張表放上來,後面所有推論都只用這裡的數字。
全期績效(full_period_results,n_days 欄位如表)
| 做法 | 年化報酬 | 年化波動 | Sharpe | 淨 Sharpe | 最大回落 | Calmar | n_days |
|---|---|---|---|---|---|---|---|
| A 靜態五五分 | 0.0751 | 0.0787 | 0.954 | 0.878 | -0.128 | 0.587 | 5319 |
| B 黃金波動調整 | 0.0746 | 0.0774 | 0.964 | 0.886 | -0.1741 | 0.428 | 5319 |
| C 黃金動能 | 0.0807 | 0.0853 | 0.946 | 0.876 | -0.1693 | 0.476 | 5319 |
| D 波動倒數 | 0.0715 | 0.0731 | 0.978 | 0.896 | -0.1368 | 0.523 | 5298 |
| E 兩邊波動比 | 0.0726 | 0.0728 | 0.998 | 0.915 | -0.1511 | 0.481 | 5298 |
三道閘(statistical_tests 與 cross_oos_summary)
| 做法 | DM 統計量 | DM p 值 | Sharpe 差 | bootstrap SE | bootstrap t | bootstrap 95% CI | 五折贏幾折 | 過 4/5 |
|---|---|---|---|---|---|---|---|---|
| B 黃金波動調整 | 3.2745 | 0.001065 | 0.0095 | 0.0397 | 0.2402 | [-0.0687, 0.0881] | 4 | 是 |
| C 黃金動能 | -8.2208 | 0.0 | -0.0081 | 0.0711 | -0.1136 | [-0.1475, 0.131] | 3 | 否 |
| D 波動倒數 | 8.9348 | 0.0 | -0.0157 | 0.3149 | -0.05 | [-0.6354, 0.6021] | 3 | 否 |
| E 兩邊波動比 | 7.5094 | 0.0 | 0.0038 | 0.3156 | 0.0121 | [-0.6244, 0.6273] | 3 | 否 |
表格數字的口徑再用文字複述一次,方便對照:B 的年化波動是 0.0774、對照組的年化波動是 0.0787;B 的 DM 統計量是 3.2745、DM p 值是 0.001065;B 的 bootstrap Sharpe 差是 0.0095、bootstrap 標準誤是 0.0397、bootstrap t 統計量是 0.2402。D 的年化波動是 0.0731、DM 統計量是 8.9348。E 的年化波動是 0.0728、DM 統計量是 7.5094。C 的年化波動是 0.0853、DM 統計量是 -8.2208。
二、DM 檢定在這支程式裡被套用在什麼上
這是本文的第一個主張,而它只能靠讀原始碼確認,不能從 methodology 欄位那句 Cross-OOS 5-fold + DM test + Bootstrap Sharpe diff + Harvey t>3.0 推出來。
experiments/k546/k546_gld_timing.py 的主程序把損失序列定義成組合日報酬的平方:bench_loss = bench_ret ** 2,策略端同樣是 strat_loss = strat_ret ** 2,然後把這兩條序列送進 diebold_mariano_test。函式的 docstring 自己寫著 loss1, loss2: squared return loss series 與 Positive DM stat → loss2 is better (lower loss)。
所以這個 DM 檢定問的問題是: 這個做法的日報酬平方,平均而言是不是比對照組低。 日報酬平方的樣本平均就是(去掉均值項之後的)已實現變異數。換句話說,它在檢定的是波動有沒有被壓低。
它不是在檢定報酬、不是在檢定 Sharpe、也不是在檢定效用。
而 B、D、E 三種做法在設計上就是波動目標型的規則:依黃金近期已實現波動調降權重、依波動倒數配權、依兩邊波動比把權重推向較安靜的一側。壓低組合波動是它們的設計目標,不是它們的績效發現。
三、把 DM 統計量對年化波動畫出來,順序完全一致
如果上一節的判讀成立,那 DM 統計量應該幾乎只是年化波動的一個單調變換。這件事可以直接畫。

四個點的排序是這樣的:D 的年化波動 0.0731、DM 8.9348;E 的年化波動 0.0728、DM 7.5094;B 的年化波動 0.0774、DM 3.2745;C 的年化波動 0.0853、DM -8.2208。對照組的年化波動 0.0787 是圖上那條垂直虛線。 落在虛線左邊的三種做法 DM 統計量為正,落在右邊的那一種為負,沒有例外。
D 與 E 的年化波動只差 0.0003,DM 統計量卻差了 1.4254,所以這不是嚴格的單調對應;但正負號與大致順序完全由波動決定這件事,圖上一眼可見。
這給出一個對讀者有用的結論: 在 K546 這個設定裡,「DM 顯著」不構成任何績效證據。 它幾乎是恆真的,一個以壓低波動為目標的規則,在一個以波動為損失函數的檢定上顯著,這中間沒有資訊。要讓 DM 在這裡承載績效意義,損失函數必須換成與投資目標對齊的東西(例如效用損失或風險調整後報酬的某個代理),而不是報酬平方。
四、順帶記一項規格細節:h=1 時沒有做自相關修正
diebold_mariano_test(loss1, loss2, h=1) 的長期變異數是這樣算的:先取 gamma_0 = np.var(d, ddof=1),接著用一個 for 迴圈累加自相關項,迴圈上界取 h 與一個常數的較小者。h 傳進來是 1,於是 range 的起點與終點相同,這個迴圈的範圍是空的,一項都不會加。
也就是說,這裡的 DM 統計量等於「損失差的樣本平均除以 iid 標準誤」,自由度 n-1 的 t 分配。日報酬平方序列有很強的正自相關(波動叢聚),這種修正的缺席會讓標準誤偏小、統計量偏大。
這一項不會改變第三節的結論,正負號與排序是由波動決定的,跟標準誤怎麼算無關,但它會讓 3.2745 這類數字看起來比實際上更有力。記在這裡,是因為引用 K546 的 DM 數字時應該連這個規格一起引用。
五、真正在判 NULL 的是哪兩道閘
程式尾端的裁決規則是三個條件的連言:passes_harvey and passes_oos and sharpe_improvement。
passes_harvey取的是abs(stat_tests[name]['bootstrap']['t_stat']) > 3.0——注意它掛在 bootstrap 的 t 統計量上,不是 DM 統計量上。passes_oos取的是cross_oos_summary[name]['passes_4of5']。sharpe_improvement比的是全期 Sharpe 是否高於對照組的 0.954。
DM 完全不在這個連言裡。 它被算出來、被寫進結果檔,但不參與裁決。
逐一對照:
| 做法 | Sharpe 高於 0.954 | 過 4/5 cross-OOS | bootstrap t 絕對值 > 3.0 | 判定 |
|---|---|---|---|---|
| B 黃金波動調整 | 是(0.964) | 是 | 否(0.2402) | 失敗,只差一道 |
| C 黃金動能 | 否(0.946) | 否 | 否(-0.1136) | 失敗,三道全掛 |
| D 波動倒數 | 是(0.978) | 否 | 否(-0.05) | 失敗 |
| E 兩邊波動比 | 是(0.998) | 否 | 否(0.0121) | 失敗 |

B 是唯一只掛一道的:它的 bootstrap t 統計量是 0.2402,門檻是 3.0。而那道閘量的正是效果的經濟規模——Sharpe 差 0.0095、標準誤 0.0397,雜訊大約是效果的四倍,95% 信賴區間 [-0.0687, 0.0881] 把零包在中間。
所以 K546 的 NULL 是這樣被判出來的: 顯著性由 bootstrap 那道閘決定,穩健性由 cross-OOS 那道閘決定,而 DM 只是被記錄下來的一個副產品。 一個只讀 DM 欄位的引用者會得到與結果檔完全相反的印象。
六、bootstrap 的規格與一個沒被解釋的異常
bootstrap_sharpe_diff 用 np.random.default_rng(seed),seed 是 42,n_boot 是 10000。重抽方式是 iid 的 rng.integers(0, n, size=n),而且同一組索引同時套用在兩條報酬序列上,這是配對重抽,會保留兩條序列的同期相關結構。Sharpe 用 mean / std * sqrt(252) 年化。它不是 block bootstrap,所以序列相關結構沒有被保留。
有一件事這份結果檔沒有解釋,本文也只能描述不能歸因:B 與 C 的 bootstrap 標準誤是 0.0397 與 0.0711,D 與 E 卻是 0.3149 與 0.3156,差了大約八倍。D 與 E 是唯二用倒數型權重的做法,也是唯二 n_days 為 5298 而非 5319 的做法。這個標準誤級距差異的成因需要另做實驗才能確認,本文不做推測。
它的實務後果倒是明確的:D 與 E 的 95% 信賴區間寬到 [-0.6354, 0.6021] 與 [-0.6244, 0.6273],這個寬度下,Harvey 那道閘對它們本來就不可能通過,不是因為效果小,是因為估計太不精確。
七、跨期異質性遠大於做法之間的差異
cross_oos_summary 的五折 Sharpe 值:
| 做法 | 2005-02-03 起 | 2009-04-28 起 | 2013-07-19 起 | 2017-10-09 起 | 2021-12-30 起 | 五折平均 |
|---|---|---|---|---|---|---|
| A 靜態五五分 | 0.94 | 0.732 | 0.555 | 1.233 | 1.355 | 0.963 |
| B 黃金波動調整 | 0.863 | 0.782 | 0.619 | 1.267 | 1.478 | 1.002 |
| C 黃金動能 | 0.952 | 1.007 | 0.226 | 1.325 | 1.27 | 0.956 |
| D 波動倒數 | 0.704 | 0.957 | 0.527 | 1.299 | 1.472 | 0.992 |
| E 波動比 | 0.648 | 1.067 | 0.484 | 1.265 | 1.58 | 1.009 |

同一條靜態五五分規則,Sharpe 在第三折是 0.555、在第五折是 1.355。而五種做法在同一折內的離散遠小於此。五折平均的全距是 0.956 到 1.009。
這是為什麼 passes_4of5 這道閘有存在必要:它擋的不是「有沒有效果」,是「效果會不會只出現在某一段年代」。B 是唯一在五折裡贏了四折的做法,它也是唯一過這道閘的。
八、機制面的解釋,以及它與既有 K 的一致性
diagnostics 裡有兩個數字直接對上這個 NULL:SPY 與 GLD 的日報酬相關係數 spy_gld_corr 是 0.0576,兩者的波動相關係數 spy_gld_vol_corr 是 0.5409。
報酬幾乎不相關,波動卻相當相關。黃金自身的波動體制因此不是一個黃金專屬的訊號,它有相當一部分是市場整體風險溫度的投影,而那個溫度在權重規則裡已經由 12/VIX 縮放吃掉了。結果檔的 conclusion.implication 也是這樣寫的,並指向 K507(VIX、動能、倒數波動全部 null)與 K275(雙資產等波動情形下五五分接近解析最適)。
diagnostics 另外兩個數字值得一起讀:GLD 的年化波動 gld_ann_vol 是 0.1812,SPY 的年化波動 spy_ann_vol 是 0.1902。黃金在這段樣本裡不是低波動資產,它的配置價值來自不同步而不是不動。
九、這個結論的邊界
- 樣本是兩資產、日頻、單一權重家族。換成多資產、換成月頻再平衡、換成別的權重函數,本文不宣稱結論會保留。
- 交易成本是
compute_metrics的tx_cost_annual參數(0.006 年化)估計值,不是特定券商費率。方向上它只會讓擇時更不利。 - 第三節的主張是關於這支程式裡的 DM 設定,不是關於 DM 檢定本身。損失函數換成預測誤差或效用損失時,DM 就重新具有它應有的意義。
- 第四節的自相關修正缺席,本文只指出它會讓統計量偏大,沒有重算修正後的數值。要知道修正後 3.2745 會變成多少,需要重跑,這篇沒有做。
- 第六節的標準誤級距差異沒有根因,只有描述。
十、可帶走的判準
引用任何一份含 DM 檢定的結果檔之前,先問一句: 這個 DM 的損失函數是什麼?
如果損失函數恰好就是那個策略被設計來降低的量,DM 顯著只是在確認設計生效,不構成績效證據。K546 是這個情形的一個乾淨案例:三個 p 值小於等於 0.001065 的統計量,一個都沒有進入裁決規則,而最終結論是 NULL。
資料來源 :yfinance(SPY、GLD、^VIX),data_source 欄位。
期間 :2005-02-03 到 2026-03-27,n_observations 為 5320。
實驗 :K546,正式結果檔 experiments/k546/k546_gld_timing_results.json,程式 experiments/k546/k546_gld_timing.py。
方法 :methodology 欄位為 Cross-OOS 5-fold + DM test + Bootstrap Sharpe diff + Harvey t>3.0;bootstrap seed 42、n_boot 10000。
文獻 :Baur & Lucey (2010) "Is Gold a Hedge or Safe Haven?" JBF;Ciner et al. (2013) "Hedges and safe havens" IBR;平台內部 K507 Dynamic SPY/GLD Allocation (null);K275 Complete 50/50 Case Synthesis。
與既有文章的關係 :一般讀者版是 mile_4efc3ca1,本篇不重述它的論證,新增的是 DM 損失函數的判讀、DM 對年化波動的對應、h=1 下自相關修正的缺席,以及裁決規則裡 DM 不參與的事實。