← 返回文章列表
August 2, 2026
5 分鐘閱讀

Double Machine Learning:估計因果參數而非預測報酬

Double Machine Learning:估計因果參數而非預測報酬
#causal-inference
#double-ML
#treatment-effect
#econometrics
#quant

本博客至今所有建模文章都提出同樣形態的問題:給定特徵,預測一個數字,然後驗證該預測在樣本外成立。價差模型預測價差。成交模型預測成交機率。整個驗證機制——清理的 walk-forward、縮水的 Sharpe、前瞻分類——的存在是為了檢查預測是否真實。

本文提出不同形態的問題,這是博客從未擁有的唯一機械部分:估計具有因果解釋的單一純量參數,並為其附上一個標準誤差,該誤差在到達該點時使用了靈活 ML 模型的情況下仍然有效。

這不僅僅是修辭上的區別。「隊列位置預測成交機率」顯然正確但操作上無用——當然如此,兩者都由深度和波動性驅動。「在隊列中前進一個位置導致成交機率變化 θ\theta,保持市場狀態不變」這是一個可以放入訂單放置政策的數字。前者是回歸擬合。後者需要一個不存在於標準 ML 工具箱中的估計器,因為靈活第一階段的正則化和過度擬合會使您關心的係數產生偏誤。

Double Machine Learning (Chernozhukov, Chetverikov, Demirer, Duflo, Hansen, Newey & Robins, 2018) 是修正此問題的估計器。每個量化交易員都聽說過:相關性不意味因果性。DML 是這句話之後的部分。

為何樸素回歸失敗

隱藏的市場狀態干擾因素同時驅動隊列放置和成交結果,產生欺騙性的樸素關聯

在博客自己的領域中建立問題。我們想要隊列位置對成交機率的因果效應:

  • YiY_i:觀測 ii 處的休市限價單是否在時間範圍內成交。
  • DiD_i:放置時的隊列位置(由層級大小標準化)。
  • XiX_i:干擾因素——實現波動性、報價價差、深度不平衡、層級大小、一天中的時間、制度標籤。這些是博客已經在 spread modeling with machine learning 中計算的市場狀態變量。

因果參數是 θ0\theta_0,在

Yi=Diθ0+g0(Xi)+ϵiY_i = D_i \theta_0 + g_0(X_i) + \epsilon_i

其中 g0(Xi)g_0(X_i) 捕捉市場狀態與成交結果之間的(可能複雜、非線性)關係。

處理並非隨機分配。您位於隊列前列是因為層級薄,或因為您在平靜時期發布,或因為訂單簿對您有利。相同條件獨立驅動您是否成交。這就是干擾。

方法 1:忽略干擾因素。YYDD 單獨回歸。估計吸收與兩者都相關的每個干擾因素的效應。教科書式的遺漏變量偏誤:薄層級既給您好的隊列位置又給您高成交率,因此您誇大了位置本身的價值。

方法 2:帶控制的線性回歸。YYDDXX 回歸。這僅在 g0(X)g_0(X) 真正線性時才有效。訂單簿動態並非如此——成交/波動性關係有閾值,深度不平衡效應按制度翻轉符號。錯誤指定 g0g_0 會重新引入偏誤。

方法 3:ML 預測。(D,X)(D, X) 上擬合梯度提升模型。您獲得良好的樣本外判別,但完全沒有因果解釋。模型捕捉每個預測模式,無論因果與否;正則化以偏誤 θ\theta 的方式縮小處理的貢獻;且沒有可信賴的標準誤差。

這是核心張力。ML 擅長預測,但對因果參數的樸素應用會產生偏誤、非正態、不可靠的估計。

部分線性模型

兩個同步殘差化通道在乾淨的殘差流於正交因果估計相遇之前移除煩人的市場狀態

DML 在結構框架內運作。主力是部分線性回歸 (PLR)

Y=Dθ0+g0(X)+U,E[UX,D]=0Y = D\theta_0 + g_0(X) + U, \quad \mathbb{E}[U \mid X, D] = 0

D=m0(X)+V,E[VX]=0D = m_0(X) + V, \quad \mathbb{E}[V \mid X] = 0

  • θ0\theta_0 是感興趣的因果參數。
  • g0(X)g_0(X) 是煩函數——結果中由市場狀態解釋的部分。
  • m0(X)m_0(X) 是另一個煩函數——給定市場狀態的處理條件期望(連續處理設置中的「propensity」)。
  • UUVV 是結構殘差。

關鍵見解:θ0\theta_0 是低維的,但 g0g_0m0m_0 可以任意複雜。我們希望 ML 處理煩函數,同時仍在標量上提供有效推斷。

為何「雙重」?

兩個 ML 模型,不是一個:

  1. 結果模型^(X)E[YX]\hat{\ell}(X) \approx \mathbb{E}[Y \mid X] —— 僅從市場狀態預測結果。
  2. 處理模型m^(X)E[DX]\hat{m}(X) \approx \mathbb{E}[D \mid X] —— 僅從市場狀態預測處理。

形成殘差

Y~i=Yi^(Xi),D~i=Dim^(Xi)\tilde{Y}_i = Y_i - \hat{\ell}(X_i), \quad \tilde{D}_i = D_i - \hat{m}(X_i)

並通過將 Y~\tilde{Y}D~\tilde{D} 回歸來估計 θ0\theta_0

θ^0=iD~iY~iiD~i2\hat{\theta}_0 = \frac{\sum_i \tilde{D}_i \tilde{Y}_i}{\sum_i \tilde{D}_i^2}

這是 Frisch-Waugh-Lovell 的加強版:用 ML 而非線性投影將干擾因素部分化,然後從殘差變異中讀取處理效應。

Neyman 正交性:為何有效

樸素部分外方法(估計 g0g_0,減去,回歸)失敗,因為 g^0\hat{g}_0 中的 ML 估計誤差直接傳播到 θ^0\hat\theta_0。DML 分數構建為 Neyman 正交——對煩函數中的小干擾不敏感。

PLR 的正交分數:

ψ(W;θ,η)=[Y(X)θ(Dm(X))][Dm(X)]\psi(W; \theta, \eta) = \big[Y - \ell(X) - \theta(D - m(X))\big] \cdot \big[D - m(X)\big]

其中 η=(,m)\eta = (\ell, m)。正交條件是

ηE[ψ(W;θ0,η)]η=η0=0\left. \frac{\partial}{\partial \eta} \mathbb{E}\big[\psi(W; \theta_0, \eta)\big] \right|_{\eta = \eta_0} = 0

直觀上,分數僅使用 DDYY 中獨立於 XX 的變異,且一個煩函數中的誤差被另一個補償。如果 m^\hat{m} 稍微過高預測處理,D~\tilde{D} 稍微太小,但來自錯誤估計 \ellY~\tilde{Y} 中對應誤差會向補償方向推動。偏誤變成二階——兩個第一階誤差的乘積——而非一階。

正式地,如果兩個煩擾估計器以 n1/4n^{-1/4} 速度收斂(溫和;大多數合理的 ML 方法通過),則

N(θ^0θ0)dN(0,σ2)\sqrt{N}(\hat{\theta}_0 - \theta_0) \xrightarrow{d} \mathcal{N}(0, \sigma^2)

因此 θ^0\hat\theta_0 以參數速度收斂且漸近正態。

交叉擬合:為何在此必須

僅正交性不夠。如果煩擾模型在用於估計 θ0\theta_0 的相同行上擬合,第一階過度擬合會污染第二階段——具體傷害值得精確說明,因為它不是您習慣的傷害。在其他地方,過度擬合作為膨脹的驗證分數出現:您注意到它,您打折它,您繼續。在這裡它作為 θ0\theta_0偏移點估計出現,伴隨仍然狹窄且仍然以錯誤數字為中心的信賴區間。沒有可疑的分數。估計器只是安靜地撒謊。

交叉擬合打破依賴:每個觀察的煩擾預測來自未包含它的模型,且 θ0\theta_0 從池化的 held-out 殘差估計。機制是普通的 K-fold 機械,在 spread modeling with machine learning 中涵蓋;下面重要的是您給它哪些折疊。

DML 算法逐步

輸入:數據 {(Yi,Di,Xi)}i=1N\{(Y_i, D_i, X_i)\}_{i=1}^N,ML 方法 M\mathcal{M}_\ellMm\mathcal{M}_m,折疊 KK

步驟 1 —— 分割:將 {1,,N}\{1, \ldots, N\} 分割為 KK 個不相交折疊。

步驟 2 —— 交叉擬合煩擾模型:對於 k=1,,Kk = 1, \ldots, K,在折疊 kk 的補集上訓練 ^(k)\hat{\ell}^{(-k)}m^(k)\hat{m}^{(-k)},然後對於 iIki \in I_k 計算 Y~i=Yi^(k)(Xi)\tilde{Y}_i = Y_i - \hat{\ell}^{(-k)}(X_i)D~i=Dim^(k)(Xi)\tilde{D}_i = D_i - \hat{m}^{(-k)}(X_i)

步驟 3 —— 估計

θ^0=(i=1ND~i2)1i=1ND~iY~i\hat{\theta}_0 = \left(\sum_{i=1}^N \tilde{D}_i^2\right)^{-1} \sum_{i=1}^N \tilde{D}_i \tilde{Y}_i

步驟 4 —— 推斷

σ^2=1Ni=1N(Y~iθ^0D~i)2D~i2/(1Ni=1ND~i2)2\hat{\sigma}^2 = \frac{1}{N} \sum_{i=1}^N \big(\tilde{Y}_i - \hat{\theta}_0 \tilde{D}_i\big)^2 \tilde{D}_i^2 \bigg/ \left(\frac{1}{N} \sum_{i=1}^N \tilde{D}_i^2\right)^2

帶有區間 θ^0±zα/2σ^/N\hat{\theta}_0 \pm z_{\alpha/2} \cdot \hat{\sigma} / \sqrt{N}

信賴區間僅對一個問題有效

這是決定 DML 結果是否有價值的警告,也是大多數該方法應用默默崩潰的地方。

上述漸近正態性是關於一個預先指定的處理、一個預先指定的干擾因素集、一個預先指定的分數的陳述。預先固定這些,運行估計器一次,區間意味它所說的。嘗試三個候選處理,或四個干擾因素集,或交換學習器直到 p 值看起來更好,您就不再在做推斷——您在運行搜索,報告的 p 值是最大值的 p 值,不是單次抽樣的。

博客已經測量了這樣做的效果。在 the deflated Sharpe ratio study 中,在零真實邊緣的純噪聲上的搜索產生 1.000 的樸素虛假發現率——未調整測試每次都觸發——而贏家的中位數樸素 p 值接近 0.0007。關於 Neyman 正交性的沒有任何保護您免受此害。正交性修正煩擾估計的偏誤;它沒有說規格搜索的偏誤。在嘗試六個規格後獲得的 1e-05 DML p 值,完全應該獲得與任何其他從網格中提取的贏家相同的 Bonferroni/Holm/BHY 處理,其中 MM 設置為您實際運行的規格數量。

這對工具的便利特性有直接的實際後果。DoubleMLData 接受 d_cols 中的列表,並會在一個摘要表中愉快地返回三個處理效應:

dml_data_multi = dml.DoubleMLData(
    df, y_col='filled', d_cols=['queue_pos', 'toxicity', 'spread_at_post'],
    x_cols=confounder_cols,
)

三行、三個 p 值,以及摘要表未提及的多重測試問題。如果您讀取全部三個,請調整全部三個。如果只有一個是預先註冊的問題,請這樣說,並明確將其他兩個視為探索性。

時間序列上的交叉擬合:清理、禁運、自定義折疊

旋轉時間序列折疊使用清理間隙和禁運區域,然後樣本外殘差組合成單一因果估計

標準 DML 假設 i.i.d. 觀察。訂單簿數據不是,失敗模式是博客已經詳細記錄的模式:相鄰行共享重疊的前瞻窗口,因此簡單的 TimeSeriesSplit 仍然會跨越折疊邊界洩漏答案。參見 spread modeling with machine learning 以了解清理的禁運 walk-forward 實現以及為何需要至少 horizon 行間隙的原因,以及 the look-ahead bias taxonomy 以了解完整的洩漏目錄及其測量幅度。

真正的 DML 特定部分是如何將清理的折疊交給估計器,因為 set_sample_splitting 有一個讓人絆倒的契約:

import numpy as np
import doubleml as dml

def purged_folds(n: int, n_splits: int, horizon: int):
    """帶有 `horizon` 行清理/禁運間隙的擴展窗口折疊。

    與 spread-modeling 文章中清理的 walk-forward CV 相同構造:
    間隙移除訓練行前瞻窗口與驗證行之間的重疊。
    """
    fold_size = n // (n_splits + 1)
    for k in range(1, n_splits + 1):
        train_end = fold_size * k
        val_start = train_end + horizon
        val_end = val_start + fold_size
        if val_end > n:
            break
        yield np.arange(0, train_end - horizon), np.arange(val_start, val_end)

folds = list(purged_folds(len(df), n_splits=5, horizon=HORIZON))

dml_plr = dml.DoubleMLPLR(dml_data, ml_l=ml_l, ml_m=ml_m)
// 元組列表的列表。一次重複:
dml_plr.set_sample_splitting([folds])
dml_plr.fit()

需要注意兩件事,沒有一件從庫文檔中明顯:

  1. 清理的 walk-forward 折疊不覆蓋每一行。 清理間隙和初始訓練塊從不是任何人的測試折疊,因此 θ0\theta_0 從嚴格少於 NN 個殘差估計。這是正確行為,不是錯誤,但這意味著方差公式中的有效 NN池化測試行的數量——檢查它而非假設。

  2. n_rep 重複在此不 free。 對隨機 K-fold,重複交叉擬合和平均是廉價的方差減少。對確定性時間順序分割只有一個分割,因此 n_rep 不購買任何東西也不隱藏任何東西;穩定性必須來自在不同數據窗口上重新運行。

對於面板結構(同期多個符號),DoubleML 支持聚類穩健標準誤——按符號聚類,而非按時間,參見 multi-symbol validation 以了解博客關於何時真正確立跨工具結果的立場。

測量案例:隊列位置與成交機率

FIFO 隊列中的訂單位置匯聚成帶有信賴光暈的 DML 調整隊列位置效應

這是文章中項目已經有數據的唯一因果問題,它應該被運行而非提出。隊列位置分析 已經涵蓋真實訂單簿數據上的位置估計、FIFO 機制、排水率和成交時間;成交模擬 涵蓋成交機率建模和對實際成交的校準循環。兩者都產生成交的預測模型。DML 將相同輸入轉換為因果估計。

預先註冊的規格(在查看估計之前):

  • 結果 YY:在 HORIZON 快照內成交(二元)。
  • 處理 DD:放置時的標準化隊列位置。
  • 干擾因素 XX:1s 實現波動性、以 bps 為單位的報價價差、深度不平衡、發布時的層級大小、以 tick 為單位的距離中點距離、一天中的時間編碼、制度標籤。
from sklearn.ensemble import GradientBoostingRegressor
import doubleml as dml

confounder_cols = [
    'rv_1s', 'spread_bps', 'depth_imbalance', 'level_size',
    'dist_from_mid_ticks', 'tod_sin', 'tod_cos', 'regime',
]

dml_data = dml.DoubleMLData(
    df, y_col='filled', d_cols='queue_pos_norm', x_cols=confounder_cols,
)

ml_l = GradientBoostingRegressor(n_estimators=300, max_depth=5)
ml_m = GradientBoostingRegressor(n_estimators=300, max_depth=5)

dml_plr = dml.DoubleMLPLR(dml_data, ml_l=ml_l, ml_m=ml_m, score='partialling out')
dml_plr.set_sample_splitting([folds])
dml_plr.fit()

print(dml_plr.summary)
dml_plr.sensitivity_analysis()
print(dml_plr.sensitivity_summary)

要報告的結果是四列比較,不是單一係數:僅 DDYY樸素 OLS 估計、DDXXYY線性控制估計、帶有其標準誤差的 DML 估計,以及靈敏度分析的穩健值——未觀察干擾因素需要多強才能使效應無效。樸素和 DML 列之間的差距是真正感興趣的數量:它是隊列位置的表面價值中有多少是市場狀態的偽裝。

此處的零或負 θ\theta 是可發布的結果,且比乾淨的正結果更適合本博客。如果一旦波動性和層級大小被部分化,隊列位置的因果效應就崩潰,那是關於訂單放置政策的直接發現:位置不是賺取成交的東西,獲得位置的條件才是。

因子因果分析

因子投資的標準方法是關聯的:按特徵排序、形成多空投資組合、觀察報酬不同。DML 啟用不同的測試——估計特徵對報酬的直接因果效應,抵消其他特徵的干擾效應。如果效應在 DML 下消失,因子不是獨立因果;它是代理。

這是因子懷疑論的第二種獨立形式,值得明確說明它與博客已經發布的內容的關係。The deflated Sharpe ratio選擇側攻擊因子動物園:有足夠的試驗,因子可能看起來顯著只是因為您看了很多次。DML 從干擾側攻擊它:因子可能在單次誠實測試上顯著,仍然是條件集中其他東西的代理。因子必須通過兩者才有意思,且兩種失敗模式是獨立的——通過一個並不告訴您關於另一個的任何事。

DML 不能做什麼

  1. 它要求干擾因素被觀察。 如果未觀察變量同時驅動處理和結果,DML 有偏,且沒有 ML 精緻性修正識別問題。靈敏度分析有界風險;它不消除風險。

  2. 它估計平均效應。 如果隊列位置的效應在制度間急劇變化,點估計是您樣本制度混合的平均值。對於異質性使用 Interactive Regression Model (DoubleMLIRM) 或因果森林。

  3. 它假設結構模型。 部分線性規格要求處理以特定方式進入結果方程。如果真實過程根本不同,DML 自信地錯誤。

  4. 它不發現因果結構。 DML 估計預先指定的處理的效應。它不告訴您哪些變量是原因。

  5. 它不免除您多重測試。 重複上述點因為它是最常跳過的點:正交性去偏煩擾估計,而非規格搜索。

實用註記

樣本大小。 DML 需要煩擾模型以 n1/4n^{-1/4} 收斂,實踐中這意味著足夠的行讓 ML 模型以任何方式近似 g0g_0m0m_0。與其信任取整數的閾值,不如像 multi-symbol validation 那樣實證建立充分性——檢查估計是否在工具和子週期上成立,並將不穩定性視為其信號。

學習器選擇。 DML 特定事實狹窄但有用:給定 n1/4n^{-1/4} 收斂,學習器影響 θ^0\hat\theta_0效率(區間寬度),而非其一致性。哪些學習器值得在表格市場數據上觸及,以及為何梯度提升是默認值,已經在 spread modeling with machine learning 中涵蓋。如果 θ^0\hat\theta_0 在學習器間實質移動,那不是選擇菜單——這是煩函數估計不良的證據,根據上述部分,選擇最友好的會將練習變成搜索。

結論

DML 給博客帶來了它沒有的東西:一種將市場微結構主張聲明為帶有可辯護標準誤差的因果參數,而非帶有良好驗證分數的預測的方法。

三個承重想法是:

  • 正交化分數,使第一階誤差補償到二階。
  • 交叉擬合,在時間序列數據上使用清理和禁運折疊,使第一階過度擬合無法移動 θ0\theta_0
  • 預先指定,使您報告的區間是您實際獲得的區間。

估計器是容易的部分。困難部分不變:決定哪些干擾因素重要,論證識別假設成立,以及抵抗再次運行規格的衝動。


參考文獻

DML 血統短且 worth 一行:它是 Robinson (1988) 的部分線性模型,ML 替換核估計器,達到半參數效率界限,具有追溯 Neyman C(α\alpha) 測試的正交條件,以及在靶向學習 (TMLE) 文獻中的近親。Chernozhukov 等人的貢獻是展示這可以用任意 ML 學習器運作,同時保持 N\sqrt{N} 一致、漸近正態推斷。

  1. Chernozhukov, V., Chetverikov, D., Demirer, M., Duflo, E., Hansen, C., Newey, W., & Robins, J. (2018). Double/Debiased Machine Learning for Treatment and Structural Parameters. The Econometrics Journal, 21(1), C1-C68.
  2. Robinson, P. M. (1988). Root-N-Consistent Semiparametric Regression. Econometrica, 56(4), 931-954.
  3. Bach, P., Chernozhukov, V., Kurz, M. S., & Spindler, M. (2022). DoubleML — An Object-Oriented Implementation of Double Machine Learning in Python. Journal of Machine Learning Research, 23(53), 1-6.
  4. Facure, M. (2022). Causal Inference for the Brave and True. Chapter 22: Debiased/Orthogonal Machine Learning.
  5. Cahan, E., Bai, J., & Ng, S. (2024). Causal Factor Investing. Quantitative Finance.
免責宣告:本文提供的資訊僅用於教育和參考目的,不構成財務、投資或交易建議。加密貨幣交易涉及重大損失風險。

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

緊跟市場步伐

訂閱我們的時事通訊,獲取獨家 AI 交易見解、市場分析和平台更新。

我們尊重您的隱私。您可以隨時退訂。