PCMCI: Causal Discovery in Multivariate Crypto Time Series
PCMCI 由 Jakob Runge(2018、2020)開發,是一種多變量時間序列因果發現演算法。它把用於圖模型學習的 PC 演算法,與瞬時條件獨立(MCI)檢驗結合起來;條件集的設計同時消除三種因素:共同驅動、間接路徑,以及來源變數的自相關。最後一點尤其值得仔細閱讀 - 這正是 PCMCI 不會繼承虛假陽性率的原因,而虛假陽性率會摧毀動量密集序列上的天真領先-滯後檢驗。
本文從第一原理拆解兩階段建構,使用 tigramite 函式庫實作,並列出這個方法在成為交易輸入前仍需要的真實資料研究。
這為現有內容補充了什麼

本部落格已經完成相關性方面的工作。加密貨幣的共同運動很大程度上是共同因子的產物 - 交易對之間的訊號相關性顯示,PC1 單獨吸收了十對訂單簿中 65% 的變異。高交易對相關性不是可交易的關係,這正是統計套利與配對交易轉而使用協整的原因。依賴性本身甚至不穩定:DCC-GARCH 動態相關性列出了靜態樣本相關性所暗含的依賴平穩、邊際波動率恒定和方向對稱假設,而這些假設都不成立。
這些方法都不會產生有向圖。它們能告訴你 BTC、ETH 和 SOL 一起移動,且大部分變化由共同因子解釋;卻不能告訴你 BTC 是否直接驅動 SOL,或這種關聯是否完全由 ETH 中介。格蘭傑因果關係通常用來尋找方向,但標準 Granger 是二元方法,無法把未觀察到的共同驅動與真正因果關係分開。
第三種失效模式比表面看來更重要。每個加密貨幣收益序列都有正自相關,自相關會放大在兩個此類序列之間執行的任何依賴性檢驗統計量:兩個相互獨立的自相關過程,在有限樣本上也會看起來顯著相關。相關性工作把這視為樣本量修正(訊號相關性文章中的 effective_N 討論)。但對因果發現而言,這不是修正,而是核心設計問題 - 也正是第 2 階段條件集要解決的問題。
PCMCI 演算法

PCMCI 分兩個階段運作。第一階段為每個變數找出候選因果父節點集合;第二階段使用精心建構的條件獨立檢驗測試每條候選連結。
第 1 階段:PC 穩定條件選擇(PC1)
第 1 階段的目標是為每個變數 找到其真實因果父節點的超集 。這個集合稍後會作為第 2 階段的條件集。
演算法從所有滯後變數的「完整集合」開始,將它們視為潛在父節點:
接著反覆刪除在條件下與 獨立的變數。在第 次迭代,演算法會測試每個候選父節點 與 的獨立性,條件是 個最強的剩餘父節點(不包括 本身):
其中 是 個變數,取自 ,這些變數與 的關聯最強。
「穩定」是指單次迭代 中的刪除決策,基於前一次迭代的父節點集合,從而避免結果依賴處理順序。這對可重現性至關重要。
此階段的顯著性水準 故意設得寬鬆(通常為 0.2 或更高,也可透過 tigramite 的 pc_alpha=None 自動決定)。目標不是在此控制虛假陽性,而是在盡量修剪不相關變數的同時保留所有真實父節點。 中有少量虛假陽性可以接受,但不能有虛假陰性。
第 2 階段:瞬時條件獨立(MCI)檢驗
一旦取得所有變數的估計父節點集合 ,第 2 階段便使用 MCI 統計量測試每個潛在因果關係 :
關鍵創新在於條件集。我們同時對以下兩組條件化:
- 目標的父節點 :消除共同驅動和通往 的其他間接路徑的影響。
- 來源的父節點 :消除來源變數的自相關,避免檢驗統計量膨脹。
同時對兩組條件化後,MCI 能有效隔離 對 在特定滯後 的「直接、瞬時」因果效應,扣除所有混雜因素、中介因素和自相關影響。
檢驗統計量可以是任何有效的條件獨立檢驗。對線性關係,偏相關是標準選擇;對非線性依賴,則可使用以 最近鄰方法估計的條件互資訊(CMI),或 GPDC(高斯過程距離相關)檢驗。
以偏相關作為預設檢驗
對大多數金融應用而言,偏相關檢驗(tigramite 中的 ParCorr)是主力。給定變數 、 和條件集 ,偏相關為:
其中 和 分別是將 、 對 回歸後的殘差:
換句話說,偏相關衡量 與 之間的線性關聯,並移除條件變數 的線性影響。在高斯資料的條件獨立零假設下,檢驗統計量服從已知分佈,因此可以精確計算 值。
偏相關值位於 ,可自然地用來排列因果連結強度。若滯後 1 的 BTC 與滯後 0 的 ETH 在兩組父節點集合條件下偏相關為 0.3,意思是:「消除所有已識別混雜因素和自相關影響後,BTC 收益的一個標準差衝擊,預測一個時期後 ETH 收益變動 0.3 個標準差。」
從檢驗結果到因果圖(DAG)
PCMCI 的輸出是一對矩陣:
- val_matrix:形狀為 ,包含每條有向連結 的 MCI 檢驗統計量(例如偏相關)。
- p_matrix:形狀相同,包含對應的 值。
建立因果圖時,在經校正的顯著性水準上對 矩陣設閾值:
校正方法不是可以略過的細節。PCMCI 檢驗 條連結,而這些檢驗在建構上相依:所有指向 的連結共享條件集,來源序列一開始也彼此相關。這正是普通 Benjamini-Hochberg 會失效的情況;Benjamini-Yekutieli 的調和懲罰 能在檢驗任意相依時維持控制。折減 Sharpe 與多重檢驗衡量了使這一點具體化的虛假發現率。發布任何圖時,都要同時報告檢驗連結數量和校正後閾值。
所得結構是時間序列圖(TSG),即一個有向圖:
- 節點代表特定時間滯後下的變數。
- 有向邊代表帶有相應滯後的因果連結。
- 自迴圈代表自迴歸效應。
這個 TSG 可以折疊成摘要圖,只顯示變數之間因果連結的存在與方向(跨滯後聚合),通常更便於解讀。
使用 Tigramite 實作

Tigramite 是 PCMCI 的參考實作,由德國航空太空中心(DLR)的 Jakob Runge 團隊開發和維護。它提供簡潔的資料處理 API、多種條件獨立檢驗、數個 PCMCI 變體和內建視覺化功能。
安裝
pip install tigramite
恢復健全性檢查(不是研究結果)
在市場資料上執行之前,應先確認管道能找回你植入的結構。這只是實作的單元測試,沒有其他含義 - 下方真值是手動寫入資料生成迴圈的,因此找回它只能證明程式碼可運作,完全不能說明加密貨幣。請以此方式解讀。
import numpy as np
import tigramite
from tigramite import data_processing as pp
from tigramite.pcmci import PCMCI
from tigramite.independence_tests.parcorr import ParCorr
from tigramite import plotting as tp
np.random.seed(42)
T, N = 2000, 5
var_names = ["BTC", "ETH", "SOL", "BNB", "AVAX"]
data = np.zeros((T, N))
noise = np.random.randn(T, N) * 0.5
for t in range(2, T):
data[t, 0] = 0.5 * data[t-1, 0] + noise[t, 0]
data[t, 1] = 0.5 * data[t-1, 1] + 0.4 * data[t-1, 0] + noise[t, 1]
data[t, 2] = 0.5 * data[t-1, 2] + 0.3 * data[t-1, 1] + noise[t, 2]
data[t, 3] = 0.5 * data[t-1, 3] + 0.25 * data[t-1, 0] + noise[t, 3]
data[t, 4] = 0.5 * data[t-1, 4] + 0.2 * data[t-2, 3] + noise[t, 4]
dataframe = pp.DataFrame(
data,
datatime=np.arange(T),
var_names=var_names,
)
parcorr = ParCorr(significance="analytic")
pcmci = PCMCI(
dataframe=dataframe,
cond_ind_test=parcorr,
verbosity=1,
)
results = pcmci.run_pcmci(
tau_max=4, # test lags up to 4 hours
tau_min=1, # only lagged (not contemporaneous) links
pc_alpha=None, # auto-select alpha for condition selection
alpha_level=0.01, # significance threshold for final MCI test
)
print("\n--- Significant causal links ---")
pcmci.print_significant_links(
p_matrix=results["p_matrix"],
val_matrix=results["val_matrix"],
alpha_level=0.01,
)
tp.plot_graph(
val_matrix=results["val_matrix"],
p_matrix=results["p_matrix"],
var_names=var_names,
link_colorbar_label="MCI (partial corr.)",
node_colorbar_label="Auto-MCI",
alpha_level=0.01,
figsize=(10, 6),
)
tp.plot_time_series_graph(
val_matrix=results["val_matrix"],
p_matrix=results["p_matrix"],
var_names=var_names,
link_colorbar_label="MCI (partial corr.)",
alpha_level=0.01,
figsize=(14, 6),
)
讀取輸出
在植入的 VAR 上,print_significant_links 會返回:
Variable BTC has 0 causal parent(s):
Variable ETH has 1 causal parent(s):
BTC (lag -1): val = 0.38, p = 0.000
Variable SOL has 1 causal parent(s):
ETH (lag -1): val = 0.28, p = 0.000
Variable BNB has 1 causal parent(s):
BTC (lag -1): val = 0.24, p = 0.000
Variable AVAX has 1 causal parent(s):
BNB (lag -2): val = 0.19, p = 0.000
植入的結構被找回,包括重要的負面結果:雖然 BTC 和 SOL 在此樣本中高度相關,但不存在直接的 BTC -> SOL 邊。MCI 將關聯完全歸因於 ETH 中介。這正是雙重條件集應該產生的行為,驗證它就是這段程式的全部目的。這是通過的單元測試,不是關於加密貨幣的研究發現。
使用真實市場資料
PCMCI 需要弱平穩輸入,因此應提供標準化對數收益而非價格 - 統計套利與配對交易介紹了 ADF 工具和原始價格不適用的原因。取得標準化收益矩陣後,tigramite 特有的部分只有兩行:
data = log_returns.values # (T, N) standardized log-returns
var_names = list(log_returns.columns)
dataframe = pp.DataFrame(data, var_names=var_names)
一般收益管道中的兩個細節不能直接照搬到 tigramite:
- 缺失資料:Tigramite 支援用遮罩陣列處理缺失觀察。使用
dataframe.mask標記缺口,不要向前填充,因為捏造的觀察會傳播到包含它的每個條件集。 - 頻率對齊:所有序列必須位於相同時間網格。對加密貨幣而言通常不難,因為交易所提供同步的 OHLCV 資料。
這個方法需要的研究
上面的一切都是工具。除非把工具指向真實資料並報告發現(包括答案是「沒有穩定結構」的情況),否則本文不適合在本部落格發表。需要執行的研究如下:
- 設定:在指定日期範圍內,對真實資產籃子的每小時收益執行 PCMCI+;透過領域推理固定
tau_max,並在全部 條連結上以 Benjamini-Yekutieli 校正alpha_level = 0.01。按照折減 Sharpe標準報告檢驗連結數和校正後閾值。 - 要報告的結果:哪些邊在校正後仍存在、它們的偏相關幅度,以及多少條邊能在樣本外存活。
- 至少一項穩定性測量:沒有它,本文就只是帶有加密貨幣代號的 tigramite README。可測量滾動視窗間持續存在的邊比例;恢復圖對
tau_max和pc_alpha的敏感度;或在相同資料上 ParCorr 與 CMIknn 的分歧。
不穩定的圖是一個可發表的結果,而不是失敗。「五大資產上的 PCMCI:因果圖無法在滾動視窗中維持」符合本部落格在誠實的負面結果中已採用的路線,也比一篇能運作的教學更有用。
選擇正確參數

最大滯後
此參數限定因果發現的時間範圍。設定太低可能錯過緩慢傳播的效應;設定太高則會增加計算成本和多重檢驗負擔。
對每小時加密貨幣資料, 到 是合理範圍;對每日資料, 到 能捕捉大部分領先-滯後關係。領域知識很重要:如果知道資金費率效應需要 8 小時傳播,便應設定 。
條件選擇顯著性
設定 pc_alpha=None 後,tigramite 會使用 Akaike 資訊準則自動選擇此參數,這是建議的預設值。若要手動設定,0.1 到 0.4 通常效果良好。較低數值會讓第 1 階段更積極(保留較少父節點),降低計算成本,但也有刪除真實父節點的風險。
最終顯著性水準
這是標準假設檢驗閾值。探索性分析使用 即可;任何會影響交易決策的內容,都應使用 或更嚴格的值,並在前文描述的依賴感知校正之後套用。名義水準不是你實際檢驗所使用的水準。
PCMCI+:加入同期連結

標準 PCMCI 只發現滯後因果連結()。但在加密貨幣市場中,資訊可以在幾秒內跨資產傳播;每小時的採樣頻率意味著許多因果效應看起來是同期發生的()。
PCMCI+(Runge,2020)擴展 PCMCI,以同時發現滯後與同期因果連結。預設情況下,同期連結是無向的(時間順序無法區分同一時間步內的原因與結果),但部分連結可使用標準 PC 演算法的定向規則(碰撞點檢測、無循環約束)定向。
results_plus = pcmci.run_pcmciplus(
tau_max=4,
tau_min=0, # include contemporaneous links
pc_alpha=None,
)
對於每小時或更低頻率的加密貨幣應用,PCMCI+ 通常比標準 PCMCI 更合適,因為許多跨資產效應發生得比採樣間隔更快。
非線性擴展

金融時間序列通常呈現非線性依賴(例如波動聚集、依賴市場狀態的領先-滯後效應)。Tigramite 提供幾種非線性條件獨立檢驗:
高斯過程距離相關(GPDC)
from tigramite.independence_tests.gpdc import GPDC
gpdc = GPDC(significance="analytic", gp_params=None)
pcmci = PCMCI(dataframe=dataframe, cond_ind_test=gpdc)
GPDC 使用高斯過程迴歸消除條件集的影響,再對殘差套用距離相關。它檢測非線性效應的能力強於 ParCorr,但速度明顯更慢。
條件互資訊(CMIknn)
from tigramite.independence_tests.cmiknn import CMIknn
cmiknn = CMIknn(significance="shuffle_test", knn=0.1, shuffle_neighbors=5)
pcmci = PCMCI(dataframe=dataframe, cond_ind_test=cmiknn)
CMIknn 使用 最近鄰方法估計條件互資訊。它完全非參數,可以檢測任意函數依賴。代價是計算成本,以及需要更多資料才能取得統計檢驗能力。
對大多數加密貨幣交易應用,請從 ParCorr 開始。只有在有非線性因果機制的具體證據,且資料充足(通常 )時,才切換到非線性檢驗。
因果圖接入的位置

因果圖能提供相關矩陣無法提供的一點:出度。在 20-50 個資產上執行 PCMCI,擁有許多出邊的節點就是資訊領先者 - 它們的變動對其餘資產具有預測內容,而對稱相關矩陣在結構上無法做出這種有方向的陳述。因子分解告訴你 BTC 主導方差;出度排名則告訴你 BTC 主導是因為它領先,還是因為包括 BTC 在內的一切都暴露於同一宏觀衝擊。
假設成功恢復出穩定圖,其可接入本部落格既有工作的地方很清楚。圖拓撲的滾動視窗變化是一種結構斷裂訊號,這是使用 HMM 的 regime 檢測的主題 - 未解問題是因果圖能否比狀態模型更早檢測轉換。將 PCMCI 應用於跨交易所的單一資產,可處理跨交易所價格領先;這已在智能訂單路由中以毫秒解析度測量,因此每小時柱線圖需要超越那項結果,而不是重述它。資金費率套利所述 8 小時資金機制形成的定期 perp-spot 連結,是一個已知答案的測試案例:PCMCI 應該找回可獨立驗證的因果結構,因此這是驗證目標而不是發現。
這些都不是研究發現,而是等待上述研究驗證的假設。
限制與注意事項

PCMCI 是強大的工具,但有幾項從業者必須理解的重要限制:
-
因果充分性假設:PCMCI 假設所有相關變數都已被觀察。如果隱藏的共同驅動(例如巨鯨交易活動、尚未發布的新聞)同時影響兩個已觀察資產,PCMCI 可能錯誤報告它們之間存在直接因果連結。LPCMCI 變體允許潛在混雜因素,部分處理這個問題,但代價是返回較少的定向邊。
-
平穩性假設:假設因果結構在分析視窗內保持不變。實務上加密貨幣市場動力學變化很快,應使用滾動視窗分析檢測結構斷裂。
-
線性與非線性:使用
ParCorr時只能檢測線性因果效應。非線性機制(例如「只有 BTC 下跌超過 5% 時,BTC 才會導致 ETH 下跌」)在線性檢驗中不可見。 -
採樣頻率很重要:快於採樣頻率發生的因果效應,在標準 PCMCI 中會顯示為同期()連結,方向也可能不明確。請使用 PCMCI+ 並考慮更高頻資料。
-
多重檢驗: 個相依檢驗需按上述方式校正 - 請參閱折減 Sharpe 與多重檢驗,了解依賴結構為何排除了看似明顯的選擇。
-
樣本量要求:可靠因果發現需要足夠資料。粗略而言,
ParCorr目標為 ,且變數數量為 ;對非線性檢驗或更大的變數集合,目標為 。
PCMCI 與其他方法比較

| 方法 | 處理自相關 | 處理共同驅動 | 同期連結 | 非線性 | 潛在混雜因素 |
|---|---|---|---|---|---|
| Granger 因果 | 部分 | 否(二元) | 否 | 透過擴展 | 否 |
| Transfer entropy | 部分 | 否(二元) | 否 | 是 | 否 |
| PCMCI | 是(MCI) | 是 | 否 | 透過 CMIknn/GPDC | 否 |
| PCMCI+ | 是 | 是 | 是 | 透過 CMIknn/GPDC | 否 |
| LPCMCI | 是 | 是 | 是 | 透過 CMIknn/GPDC | 是 |
| VAR-LiNGAM | 否 | 是 | 是 | 否 | 否 |
PCMCI 相對於 Granger 因果和 Transfer entropy 的主要優勢是 MCI 檢驗,它能在多變量設定中正確處理自相關和共同驅動。這正是加密貨幣市場的情況:數十個彼此相關且自相關的資產同時互動。
結論

值得帶走的貢獻是兩階段建構:先用稀疏條件選擇限制父節點集合,再使用條件集同時包含來源與目標父節點的 MCI 檢驗。後半部分正是 PCMCI 與 Granger、Transfer entropy 的區別,也正是它能在像加密貨幣收益一樣具有自相關的序列上運作的原因。
這個方法沒有附帶證據。恢復出的圖是關於資訊流的假設,而不是訊號;在本部落格中,除非它在指定資產籃子、日期範圍、依賴感知校正的真實資料上執行,並至少測量圖在視窗移動時是否保持穩定,否則它不具備任何意義。在執行研究之前,請把這裡的一切視為工具。
如果圖不穩定,那就是文章本身。這不會是本部落格第一個比能運作的教學更有價值的負面結果。
參考文獻
- Runge, J.、Nowack, P.、Kretschmer, M.、Flaxman, S.、Sejdinovic, D. (2019)。在大型非線性時間序列資料集中檢測和量化因果關聯。Science Advances,5(11),eaau4996。
- Runge, J. (2020)。在自相關非線性時間序列資料集中發現同期與滯後因果關係。第 36 屆人工智慧不確定性會議(UAI)論文集,PMLR 124:1388-1397。
- Tigramite 文件:https://jakobrunge.github.io/tigramite/
- Tigramite GitHub 儲存庫:https://github.com/jakobrunge/tigramite
Authors
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.