DCC-GARCH: ペアトレードとポートフォリオリスクのための動的相関
多くの暗号資産デスクにBTCとETHの相関を尋ねると、誰も選んだ理由を覚えていないウィンドウで計算された単一の数値——0.8、あるいは0.75——が返ってくる。その数値は嘘だ。少なくとも危険な単純化である。サンプル相関は、その期間中に真の依存構造が絶えず動いていた期間にわたる平均にすぎない。穏やかな市場ではBTCとETHは十分に乖離し、マーケットニュートラルなペアが魅力的に見える。清算カスケードが起きれば両者は互いに、そして他のすべてと連動し、支払ったはずの分散効果はまさにそれが必要な瞬間に消え去る。
これは微妙な効果ではない。2022年のどのドローダウンを取っても——5月のLUNA崩壊、6月の3AC解体、11月のFTX破綻——上位20トークン間の平均ペアワイズ相関が0.4〜0.6のレンジから数日以内に0.9以上へと行進するのが見て取れる。相関は時折推定を誤る定数ではなく、それ自体のダイナミクス、それ自体のクラスタリング、それ自体のレジームを持つ時系列である。それをスカラーとして扱うことは、単一資産に対してこのシリーズのパート1で既に論破した「ボラティリティ一定」の仮定の多変量版に相当する誤りだ。
この記事は4部構成のボラティリティシリーズのパート3である。パート1ではarchライブラリを使って単変量GARCH(1,1)を構築し、ボラティリティがクラスター化し平均回帰する様子を示した。パート2では非対称性(GJR-GARCH、EGARCH)とStudent-tイノベーションを追加し、レバレッジ効果とファットテールを捉えた。ここでは多変量に踏み込み、エングルの動的条件付き相関(DCC)モデルを使って、条件付き共分散行列全体がどのように推移するかをモデル化する。これによりスカラー相関では決して得られない2つのものが手に入る——ペアトレードのための動的ヘッジ比率と、リスクベースの資産配分のための誠実な時間変化ポートフォリオ分散だ。パート4では、単変量・多変量の予測をポジションサイジングルールに結びつけるボラティリティターゲットバックテストでシリーズを締めくくる。
パート1と2は読了済みという前提で進めるため、単変量GARCHの再導出はしない。もし共同のテール挙動——2つの資産が同時に1%分位点を突破する確率——が知りたいなら、それはコピュラの問題であり、共同リスクのためのコピュラモデルで扱っている。DCCとコピュラは相補的だ。コピュラは静的だが柔軟なテール依存構造を与え、DCCは相関行列全体の扱いやすい時系列を与える。この記事は後者についてのものである。
なぜ暗号資産では静的相関が破綻するのか
仕組みに入る前に、何が失敗するのかを正確に述べておこう。ウィンドウにわたる単一のサンプル相関は以下を推定する。
これは3つの暗黙の仮定を伴い、いずれも暗号資産では誤っている。
- 依存関係の定常性。 ウィンドウには唯一の真のがあるという仮定。実際には依存関係にはレジームがある——0.5付近の平穏な市場レジームと0.95付近のストレスレジーム——であり、はそれらを意味のない中間値に混ぜ合わせてしまう。
- 周辺ボラティリティの一定性。 ピアソン相関は正規化された共分散である。もしと自体が動いているなら(実際に動いている——それがパート1と2全体の前提だ)、一定の共分散でさえ時間変化する相関を生み出し、その逆もまた然りである。下にボラティリティモデルなしにこの2つを分離することはできない。
- 市場方向に対する対称性。 相関はラリー時よりもドローダウン時に上昇する。これはレバレッジ効果の多変量版だ。ローリングウィンドウは、純粋なノイズになるほど短くしない限りこれを表現できない。
ローリングウィンドウによる修正——直近30日または60日にわたってを再計算する——は、ある問題を別の問題と交換するだけだ。短いウィンドウは反応が速いがノイズが多く、実際のブレイクに遅れる。長いウィンドウは安定しているが古い。さらに悪いことに、資産にわたるローリング相関行列は、縮小や補正を始めると正定値性が保証されず、下流のあらゆるオプティマイザを壊してしまう。私たちが求めているのは、(a)各資産の適切なボラティリティプロセスに駆動され、(b)構成上あらゆるステップで有効な相関行列を生成し、(c)ウィンドウ長を勘で選ぶのではなく最尤法で推定できるパラメータを持つモデルだ。それがDCC-GARCHである。
多変量問題:条件付き共分散行列
を時刻における資産のリターンベクトルとし、条件付き平均を(しばしば単なる定数か小さなAR項)、残差をとする。以下を仮定する。
ここでは情報集合の下での条件付き共分散行列であり、は何らかの条件付き分布(ガウス分布、あるいは暗号資産にはより適した多変量Student-t分布)である。多変量ボラティリティモデリングにおけるすべては、一つの問いに対する異なる答えだ。パラメータ爆発を起こすことなく、あらゆるステップで対称正定値性を保ちながらのダイナミクスをどうパラメータ化するか?
2つの古典的な答えが、この問題の難しさを物語っている。
VECH
VECHモデル(Bollerslev, Engle, Wooldridge 1988)は、の半ベクトル化を過去の残差二乗と過去の共分散の線形関数として書く。
ここでは対称行列の下三角部分を長さのベクトルに積み重ねる。これは最大限に一般的である——すべての分散と共分散が過去のすべての分散と共分散に依存する——が、を超えると最大限に使い物にならなくなる。資産に対して、とはそれぞれである。では、2つの行列、およそ450パラメータに加えて、表現することさえ苦痛な正定値性制約が課される。尤度曲面は沼地である。
BEKK
BEKKモデル(Engle & Kroner 1995)は、二次形式を使って構成上正定値性を保証する。
ここでは上三角行列である。すべての項が二次形式であるため、である限りは自動的に成り立つ。BEKKはVECHより簡素だが、それでもとの行列はそれぞれであり、パラメータ数はでスケールする。では、ノイズの多い日次暗号資産データに対して200以上のパラメータをMLEで同時推定することになり、オプティマイザが意味のある値に収束する保証はない。実務上、フルBEKKはに限定され、その場合でさえ、クロスダイナミクスの大半を捨てる「対角」あるいは「スカラー」制約が使われる。
これが多変量GARCHにおける次元の呪いである。パラメータ数は二次的に増加するが、データ中の情報量はそうではない。関心のある資産数に達するはるか前に自由度が尽きてしまう。10〜30トークンを持つどんな暗号資産ポートフォリオも、VECHやBEKKでは完全に手が届かない。
エングルによる打開策は、を直接モデル化しようとするのをやめて、既に安価に推定する方法を知っている要素に因数分解することだ。
エングルのDCC(2002):2段階分解
Bollerslevの定条件付き相関(CCC)モデル(1990)は、最初の簡素な因数分解だった。それは以下のように書く。
ここでは条件付き標準偏差の対角行列——資産ごとの単変量GARCH——であり、は一定の相関行列である。これは大きな単純化だ。個の独立な単変量GARCHモデルを当てはめ、その後標準化残差の単一のサンプル相関行列を推定すればよい。が有効な相関行列であり、すべてのである限り、正定値性は自動的に成り立つ。
CCCの問題はその名前そのものにある——相関が一定であることは、まさにこの記事の冒頭で退けた仮定である。エングルの動的条件付き相関(2002)はCCCの美しい因数分解を保ちながら、相関行列に呼吸をさせる。
今度はが時間変化する。天才的な点は、ボラティリティと相関が2つの別々のステップで推定されるため、完全なの同時最適化に直面することが決してないことだ。
ステップ1:資産ごとの単変量GARCH
各資産について、パート1と2でと全く同じように単変量GARCHモデル——GARCH(1,1)、GJR-GARCH、あるいはEGARCH with Student-tイノベーション、その系列に最も適合するもの——を当てはめる。これにより条件付き分散、したがってが得られる。
当てはめたモデルから標準化残差を抽出する。
構成上、各は(近似的に)単位条件付き分散を持つ。これらをベクトルとして積み重ねる。この標準化残差が相関ステップの原材料となる——個々のボラティリティダイナミクスが取り除かれているため、残っている共変動は純粋な依存関係であり、ボラティリティのアーティファクトではない。(これはコピュラ記事が周辺分布を当てはめる前に使うPIT的なロジックと同じだが、ここでは一様分布まで持っていかず標準化で止める。)
ステップ2:DCC相関の漸化式
の対称正定値行列である補助プロセスを、標準化残差の外積に駆動されるGARCH的な漸化式でモデル化する。
ここで:
- は標準化残差の無条件相関行列である(これが相関ターゲティングと呼ばれるものであり、詳しくは後述する)、
- は今日のショックが相関をどれだけ強く引っ張るかを支配する、
- は持続性——昨日のがどれだけ引き継がれるか——を支配する、
- そして平均回帰の制約は()で、これは単変量GARCHにおけるに直接対応する。
この構造がスカラーGARCH(1,1)の漸化式と行列版で同一であることに注目してほしい——長期的な錨、ショック項、持続項だ。これは半正定値行列(、ランク1の外積、そして前の)の凸結合であるため、であり重みが非負である限り、は正定値のままである。これが有効な共分散行列を無償で保証してくれる仕組みだ。
はほぼ相関行列だが、正確にはそうではない——対角要素が正確に1ではない。そこで正規化する。
要素ごとに書くと、資産との間の条件付き相関は
このは、あらゆる時点において構成上——単位対角、範囲の非対角要素、正定値性を持つ——真の相関行列である。完全な条件付き共分散を再構成すると、
この最後の要素ごとの形は常用することになる。2資産の条件付き共分散は、それらの動的相関にそれぞれの動的ボラティリティを掛けたものだ。右辺のすべての要素が時間変化し、推定可能なモデルから得られる。
このモデル全体には、であろうとであろうと、たった2つの相関パラメータとしかない。ボラティリティ側は線形にスケールする(資産ごとに約4〜5パラメータの単変量GARCHが1つずつ、すべて独立に、恥ずかしいほど並列に当てはめ可能)。これがDCCがBEKKやVECHでは不可能なスケーリングを実現できる理由である。次元の呪いは、最適化されるのではなくターゲティングされる(サンプル推定値としてプラグインされる)に閉じ込められている。
スカラー制約とそのコスト
がスカラーであるということは、すべての資産ペアが同じ相関ダイナミクス——同じ調整速度、同じ持続性——を共有することを意味する。BTC-ETH相関とDOGE-SHIB相関は、その経済的背景が異なるにもかかわらず、同じリズムで動く。これが扱いやすさの代償であり、通常は許容できる代償である。一般化(行列を持つGeneralized DCC、Cappiello-Engle-Sheppardの非対称DCC)はパラメータ数と推定の安定性を犠牲にしてこの制約を緩和する。aDCCについては後述する。
DCC準対数尤度
とを推定するには尤度が必要だ。エングルの核心的な結果は、ガウス対数尤度がボラティリティ部分と相関部分に分離できるということであり、これが2段階推定量を正当化する。を仮定すると、時刻における対数尤度の寄与は
を代入する。すると、であり、を使うと、
ここでを加えて引くことで分割する。
ボラティリティ部分は(を通じて)単変量GARCHパラメータのみに依存する——これを最大化することは、まさにステップ1で行った個の独立な単変量GARCHモデルの当てはめそのものである。相関部分は(ステップ1の標準化残差が与えられた上で、を通じて)とに依存する。したがってステップ2では以下のみを最大化する。
(項はに依存しないため落とす)。これは資産数に関わらず2パラメータの最適化である——それがまさに要点だ。2段階推定量は一致性を持つが完全な効率性は持たないため、これは準尤度と呼ばれる。標準誤差には補正が必要だが(Engle & Sheppard 2001)、シグナル生成には点推定値さえあれば十分だ。
暗号資産にとって、ガウスイノベーションはテールリスクを過小評価する。多変量Student-t尤度への差し替えはに対する単純な変更である(ガウスカーネルを多変量t密度に置き換え、自由度パラメータを追加する)。以下の推定量ではガウス準尤度を明確さのために維持し、がどこに入るかを注記する——パート1〜2からの標準化は既に周辺分布にt-イノベーションを使用しており、テールの恩恵の大半を捉えている。
Python実装
率直だが重要な事実——archライブラリは多変量GARCHもDCCも行わない。 archは優れた単変量エンジンであり(まさにその用途で頼りにしている)、dcc_modelは存在しない。実用的な選択肢は以下の通りだ。
archの上に自前でDCCを構築する —archで単変量モデルを当てはめ、標準化残差を抽出し、漸化式と相関準尤度をNumPy/SciPyで実装し、2つのスカラーを最適化する。以下で行うのはこれだ。約60行で完全に透明である。mgarchPyPIパッケージ — 軽量な純Python製DCC-GARCH実装。手早く当てはめるには便利だが、GJRの周辺分布やt-イノベーションを精密に組み込みたい場合には柔軟性に欠ける。- RのRの
rmgarch(Alexios Galanos著) — リファレンス実装。dccspec/dccfitはDCC、aDCC、GARCH-コピュラ、Student-t、そして適切な標準誤差をサポートする。本格的な多変量ボラティリティ研究を行うなら、rmgarch(必要ならrpy2経由でPythonから呼び出す)がゴールドスタンダードだ。
私たちは選択肢1を構築する。それがあらゆる可動部分を明示的にし、パート1〜2の単変量スキルを再利用するからだ。
ステップ1:archで単変量GARCHの周辺分布を当てはめる
import numpy as np
import pandas as pd
from arch import arch_model
from scipy.optimize import minimize
def fetch_returns(symbols, start="2022-01-01", end="2025-12-31"):
"""
Daily log returns for a list of crypto symbols.
Replace with your data source (ccxt for 24/7 exchange data,
yfinance for a quick sketch).
"""
import yfinance as yf
px = yf.download([f"{s}-USD" for s in symbols],
start=start, end=end)["Close"]
px.columns = symbols
rets = np.log(px / px.shift(1)).dropna()
return rets
symbols = ["BTC", "ETH", "SOL", "BNB"]
returns = fetch_returns(symbols)
def fit_univariate(series, dist="t"):
"""
Fit GJR-GARCH(1,1) with Student-t innovations (Part 2 model).
Returns the fitted result and the *scaled* series it was fit on.
We scale returns by 100 for the optimizer's numerical health,
exactly as in Parts 1 and 2.
"""
scaled = series * 100.0
model = arch_model(scaled, mean="Constant",
vol="GARCH", p=1, o=1, q=1, dist=dist)
res = model.fit(disp="off")
return res
fits = {s: fit_univariate(returns[s]) for s in symbols}
Z = pd.DataFrame({s: fits[s].std_resid for s in symbols}).dropna()
Sigma = pd.DataFrame({s: fits[s].conditional_volatility
for s in symbols}).loc[Z.index]
print(Z.describe())
標準化残差に対する簡単な健全性チェックが重要だ。いずれかの列の標準偏差が1から大きく離れている場合、あるいはに残存する自己相関(Ljung-Box検定)が強い場合、単変量の周辺モデルは仕様が誤っており、DCCステップはその誤りを引き継いでしまう。まず周辺分布を修正すること——それがパート2の役目だった。
ステップ2:DCCの漸化式と準対数尤度
def dcc_negloglik(params, Z):
"""
Negative DCC quasi-log-likelihood (Gaussian) in (a, b).
Z : (T, d) array of standardized residuals from Step 1.
Implements:
Q_t = (1-a-b) Qbar + a z_{t-1} z_{t-1}' + b Q_{t-1}
R_t = diag(Q_t)^{-1/2} Q_t diag(Q_t)^{-1/2}
LL = -1/2 sum_t ( log|R_t| + z_t' R_t^{-1} z_t )
with correlation targeting: Qbar = sample corr of Z.
"""
a, b = params
if a <= 0 or b <= 0 or a + b >= 1.0:
return 1e10
Z = np.asarray(Z)
T, d = Z.shape
Qbar = np.cov(Z, rowvar=False, bias=True) # unconditional (targeted)
dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
Qbar = dinv @ Qbar @ dinv
Q = Qbar.copy() # initialize Q_1 at the target
ll = 0.0
for t in range(T):
q_diag = np.sqrt(np.diag(Q))
R = Q / np.outer(q_diag, q_diag)
sign, logdet = np.linalg.slogdet(R)
if sign <= 0:
return 1e10
z = Z[t]
Rinv_z = np.linalg.solve(R, z)
ll += -0.5 * (logdet + z @ Rinv_z)
Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
return -ll
def fit_dcc(Z):
"""Estimate (a, b) by maximizing the DCC quasi-log-likelihood."""
res = minimize(
dcc_negloglik, x0=[0.03, 0.94], args=(np.asarray(Z),),
method="L-BFGS-B",
bounds=[(1e-6, 0.5), (1e-6, 0.999)],
)
a, b = res.x
print(f"DCC estimates: a = {a:.4f}, b = {b:.4f}, a+b = {a+b:.4f}")
print(f"log-likelihood: {-res.fun:.2f}")
return a, b
a_hat, b_hat = fit_dcc(Z)
これをBTC/ETH/SOL/BNBのポートフォリオに対して数年分の日次データで実行すると、以下のような形の出力が得られる(下記の数値は例示であり、特定の日付での実験結果ではない——自分のデータで実行すること)。
DCC estimates: a = 0.0287, b = 0.9401, a+b = 0.9688
log-likelihood: -3812.44
この読み方は以下の通り。
- ****は小さい——相関行列が単一日のショックで急変することはない。毎日、は外積に向けてわずか約3%だけ引き寄せられる。
- ****は大きい——相関は非常に持続性が高い。一度ポートフォリオがストレスイベントで連動すると、しばらくその状態が続き、へとゆっくり減衰していく。これは暗号資産のドローダウンで実際に体験することと一致する。価格が安定した瞬間に相関が元に戻ることはない。
- ****は平均回帰を確認する。相関プロセスには戻っていく定常的な長期水準()があり、半減期はおよそ日である。もしが本質的に1に等しいと推定された場合、相関プロセスは単位根を持つ——長期的な錨がない状態であり、通常はサンプル内の構造的ブレイクをモデルが無限の持続性として吸収している症状である。
この「単位根に近い持続性と小さなショック負荷」というパターンは、資産クラスを問わずDCCの典型的な特徴であり、暗号資産も例外ではない。これはまた、30日ローリング相関がなぜこれほど貧弱な代替物であるかの理由でもある。ローリングウィンドウは、この減衰構造とはまったく一致しない暗黙のとを仮定していることになる。
実際のデバッグ時間を節約するいくつかの実装上の注意点。
- 初期化。
[0.03, 0.94]から始めるのは典型的な暗号資産の推定値を反映している。小さい(相関はショックに反応するが激しくはない)、大きい(相関は持続する)。オプティマイザがに迷い込む場合、相関プロセスは単位根を持つ——通常はサンプル内の構造的ブレイク(モデルが持続性として無理に適合させようとしているレジーム変化)の兆候である。 - タイミング規約。 ループ内ではをに対してスコアリングし、その後でを次のステップ用に更新する。これによりはまでの情報のみの関数であり続ける——先読みはない。このオフバイワンを間違えることは最もよくあるDCCのバグであり、静かにサンプル内適合度を膨らませてしまう。
- 相関ターゲティング。 を推定するのではなく、サンプル相関としてプラグインする。これが最適化を2次元にしている理由だ。代償は、がフルサンプルを使用することであり、厳密なウォークフォワードでは訓練ウィンドウのみで再推定する必要がある(後述)。
ステップ3:相関と共分散のパスを再構築する
が固定されたら、漸化式をもう一度実行し、今度は完全な(と)のパスを保存して、下流の戦略が使えるようにする。
def dcc_filter(Z, Sigma, a, b):
"""
Run the DCC recursion with fixed (a,b) and return the full paths:
R_path : (T, d, d) conditional correlation matrices
H_path : (T, d, d) conditional covariance matrices (scaled units)
Sigma : (T, d) conditional volatilities aligned with Z.
"""
Z = np.asarray(Z); Sig = np.asarray(Sigma)
T, d = Z.shape
Qbar = np.cov(Z, rowvar=False, bias=True)
dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
Qbar = dinv @ Qbar @ dinv
Q = Qbar.copy()
R_path = np.empty((T, d, d))
H_path = np.empty((T, d, d))
for t in range(T):
q_diag = np.sqrt(np.diag(Q))
R = Q / np.outer(q_diag, q_diag)
R_path[t] = R
Dt = np.diag(Sig[t]) # D_t = diag(sigma_i,t)
H_path[t] = Dt @ R @ Dt # H_t = D_t R_t D_t
z = Z[t]
Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
return R_path, H_path
R_path, H_path = dcc_filter(Z, Sigma, a_hat, b_hat)
i, j = symbols.index("BTC"), symbols.index("ETH")
rho_btc_eth = pd.Series(R_path[:, i, j], index=Z.index, name="rho_BTC_ETH")
print(rho_btc_eth.describe())
print("min/max correlation:", rho_btc_eth.min().round(3),
rho_btc_eth.max().round(3))
rho_btc_eth系列は、この演習全体の成果である。単一の数値の代わりに、プロットしたり、閾値を設けたり、戦略にフィードしたりできる日次相関が手に入る。実際の暗号資産データでは、静かな期間ではおよそ0.5、ストレス期には0.9を超える範囲にわたるのが典型的だ——これはまさに単一のサンプル相関が平均化してならしてしまう幅である。
1期先予測
ライブトレードには、現時点で利用可能な情報から次期のが必要だ。ボラティリティ側は各archモデルの1期先予測から得られ、相関側は漸化式をもう一段回すだけだ。
def dcc_forecast_next(Z, a, b, fits, symbols):
"""One-step-ahead H_{t+1} using info through the last observation."""
Z = np.asarray(Z); T, d = Z.shape
Qbar = np.cov(Z, rowvar=False, bias=True)
dinv = np.diag(1.0 / np.sqrt(np.diag(Qbar)))
Qbar = dinv @ Qbar @ dinv
Q = Qbar.copy()
for t in range(T):
z = Z[t]
Q = (1 - a - b) * Qbar + a * np.outer(z, z) + b * Q
q_diag = np.sqrt(np.diag(Q))
R_next = Q / np.outer(q_diag, q_diag)
sig_next = np.array([
np.sqrt(fits[s].forecast(horizon=1, reindex=False)
.variance.iloc[-1, 0])
for s in symbols
])
Dt = np.diag(sig_next)
H_next = Dt @ R_next @ Dt
return R_next, H_next, sig_next
R_next, H_next, sig_next = dcc_forecast_next(Z, a_hat, b_hat, fits, symbols)
series * 100でarchを当てはめたため、すべてがスケーリング(×100)された単位であることを忘れないこと。戦略にフィードする前に、ボラティリティは100で(共分散はで)割って生のリターン単位に戻すこと。このスケーリングを正しく保つのは面倒だが、静かなバグの頻出源だ。
応用1:ペアトレードのための動的ヘッジ比率
古典的なマーケットニュートラルなペア——一方の資産をロングし、他方をベータで加重してショートする——は、ヘッジ比率次第で成否が決まる。それを訓練ウィンドウにわたる静的OLSで推定すると、この記事全体のテーマである陳腐化した相関の問題をそのまま引き継ぐことになる。先四半期にマーケットエクスポージャーを中立化したヘッジは、今四半期には誤っている。
DCCはヘッジ比率を時系列として与えてくれる。BTCを使ったETHエクスポージャーの最小分散ヘッジは、条件付き回帰係数である。
右辺のすべての項がDCCの出力である。ヘッジ比率は2つの異なる理由で動き、DCCはそれをきれいに分離する。相関が変化する(資産が連動または乖離する)ことと、ボラティリティ比が変化する(一方の資産が相対的により変動的になる)ことだ。ローリングOLSベータはこの2つの効果を遅れを伴って混ぜ合わせてしまうが、DCCはそれらを帰属させる。
def dynamic_hedge_ratio(R_path, Sigma, base="BTC", target="ETH",
symbols=symbols, index=Z.index):
"""
beta_t to hedge `target` exposure with `base`:
beta_t = rho_t * sigma_target,t / sigma_base,t
(Scaling cancels in the ratio, so scaled units are fine here.)
"""
i = symbols.index(target)
j = symbols.index(base)
rho = R_path[:, i, j]
sig = np.asarray(Sigma)
beta = rho * sig[:, i] / sig[:, j]
return pd.Series(beta, index=index, name=f"beta_{target}_{base}")
beta_t = dynamic_hedge_ratio(R_path, Sigma)
print(beta_t.describe())
spread = (returns["ETH"] - beta_t.shift(1) * returns["BTC"]).dropna()
spreadをどのペアトレードエンジンにでもフィードすればよい。動的ヘッジそれ自体がエッジを生み出すわけではない——それが実現するのは、実際にトレードするスプレッドが時間を通じて本当にマーケットニュートラルになることであり、平均回帰シグナルが乖離する方向性エクスポージャーに汚染されなくなることだ。ペアトレード戦略を構築しているなら、これは暗号資産における統計的裁定取引とペアトレードやペアトレードの距離アプローチのフレームワークにそのまま組み込め、固定ヘッジ比率を置き換えられる。相関系列自体も、相関ベースのペアシグナルへのより清潔な入力になる——ノイズの多いウィンドウ推定の代わりに、平滑化されたモデル整合的なが得られる。
ライブでを使う際の注意点は2つある。第一に、ラグをかけること——同時点のではなくでトレードすること。さもなければ先読みになる。第二に、日々激しく動くヘッジ比率は回転率と手数料を生む。暗号資産の24時間市場ではショートレッグにファンディングコストがかかるため、過剰反応するヘッジは、それが補正するドリフト以上に損失を出しかねない。を平滑化(EWMA、あるいはある帯域を超えたときのみヘッジをリバランス)し、全体を賢明にサイジングすること——ノイズの多いシグナルからのポジションサイジングはそれ自体の規律であり、ケリー基準サイジングで扱っている。
応用2:時間変化するポートフォリオ分散
ウェイトベクトルを持つポートフォリオについて、条件付き分散は
静的な共分散行列——マーコウィッツのデフォルト——では、この数値は一度計算した定数であり、それが今も真実だと思い込んでいるだけだ。実際にはそうではない。ポートフォリオリスクは市場とともに呼吸し、相関が急騰するまさにその瞬間に最も激しく呼吸する。なぜなら、ドローダウンでは項と項の両方が同時に上昇し、掛け合わさるからだ。穏やかな市場では年率40%のボラティリティに見えたポートフォリオが、ストレス週には80%以上を記録しうるが、静的な共分散行列は何も変わっていないと告げてくる。
def portfolio_vol_path(H_path, weights, index=Z.index, unscale=1e4):
"""
Conditional portfolio volatility sigma_{p,t} = sqrt(w' H_t w).
H_path is in scaled (x100) units, so covariances carry a 100^2
factor: divide by unscale=1e4 to return to raw-return variance.
"""
w = np.asarray(weights)
var_t = np.einsum("i,tij,j->t", w, H_path, w) / unscale
return pd.Series(np.sqrt(var_t), index=index, name="port_vol")
w = np.array([0.4, 0.3, 0.2, 0.1]) # BTC, ETH, SOL, BNB
pv = portfolio_vol_path(H_path, w)
pv_annual = pv * np.sqrt(365)
print(pv_annual.describe())
この時間変化するこそ、リスクベースの資産配分に必要な誠実な入力である。静的なサンプル共分散を使った平均分散最適化(暗号資産のためのマーコウィッツ)は、フィクションに対して最適化しているにすぎない。(あるいはその短期予測)をフィードすれば、効率的フロンティア自体が時間変化するようになり、オプティマイザは相関上昇レジームに入った後ではなく、その中でリスクを削減するよう強制される。リスクパリティや階層的アプローチ——HRP + CVaRパイプライン——は共分散の入力にさらに敏感だ。配分全体が丸ごとリスク行列の関数だからだ。そして比較されるポートフォリオ最適化アルゴリズムのように配分手法を比較しているなら、静的か動的かの共分散を消費するかどうかは、アルゴリズムの選択よりも実現リスクの大きなドライバーであることが多い。
直接的な応用が、ポートフォリオ全体のボラティリティターゲティングである。目標年率ボラティリティを選び、毎期グロスエクスポージャーをでスケールすることで、実現リスクを危機時に膨れ上がらせずにほぼ一定に保つ。これはパート4でこのルールを構築しバックテストすることでループを閉じる。
応用3:レジームシグナルとしての相関
ヘッジとサイジングを超えて、相関行列はマクロシグナルを内包している。抽出できる最も有用な単一スカラーは平均ペアワイズ相関である。
がポートフォリオ全体で上昇するとき、市場はリスクオフレジームに入りつつある——個別のストーリーは意味を失い、すべてが単一のマクロベータとして取引される。これが「危機では相関が1に向かう」という定性的認識の定量的な指紋である。これはドローダウンに先行するか同時に起こる傾向があり、遅行的な事後分析ではなく使えるレジーム指標になる。
def avg_pairwise_corr(R_path, index=Z.index):
T, d, _ = R_path.shape
iu = np.triu_indices(d, k=1) # upper-triangle off-diagonals
avg = R_path[:, iu[0], iu[1]].mean(axis=1)
return pd.Series(avg, index=index, name="avg_corr")
avg_corr = avg_pairwise_corr(R_path)
roll_q = avg_corr.rolling(365, min_periods=90).quantile(0.80)
risk_off = (avg_corr > roll_q)
risk_offは単独のスロットル(グロスエクスポージャーを削減し、ストップを広げ、みんなが同じ方向にトレンドする際にひかれてしまう平均回帰戦略を停止する)として、あるいはより正式なレジームモデルの特徴量として使える。これはHMMによるレジーム検出における隠れマルコフアプローチと自然に組み合わさる。平均DCC相関は、遅行的なリターンとは異なる形でシステミックストレスについて先読み的であるため、HMMに渡せる最も情報量の多い観測変数の一つだ。誠実な注意点は以下の通りだ——相関の上昇は分散が失敗しつつあることを教えてくれるが、市場がどちらに向かうかは教えてくれない。それはリスクシグナルであってアルファシグナルではなく、そのようにサイジングすべきだ——リスクレジームを方向性のあるベットとして扱うとなぜ悪い結果に終わるかについては、損失と利益の非対称性を参照のこと。
実務上の考慮事項
推定の安定性と資産数
DCCはBEKKよりはるかによくスケールするが、「スケールする」は「無償」を意味しない。相関ターゲティング行列はのサンプル相関であり、が観測数に近づくにつれてサンプル相関行列は条件が悪化する。4資産で1000日あれば問題ない。60資産で400日では、はほぼ特異になり、尤度中のその逆行列は爆発し、は数値ノイズから非正定値へと迷走しうる。対策を、必要になる頻度が高い順に挙げると以下の通り。
- を縮小する——漸化式を実行する前に、構造化されたターゲット(Ledoit-Wolf、あるいは単位行列や定相関行列)に向けて縮小する。これは大きなポートフォリオに対する最もレバレッジの高い単一の修正策だ。
- 資産をグループ化する——主要銘柄、L1、DeFi、ミームなどいくつかのセクターにまとめ、セクター内・セクター間でモデル化するか、生の資産ではなく主成分ファクターに対してDCCを実行する。
- 資産数よりデータ量を優先する。 DCCは長く、清潔で、同時期の履歴に飽くなき欲求を持つ——これはまさに新しいトークンが持っていないものだ。
現実的には、直接DCCを適用する資産は多くても数十にとどめること。より大きなユニバースには、ファクターリターンと固有残差に対するDCCが標準的な回避策である。
相関ターゲティングはコストを伴う近道である
をターゲティングすることは推定を扱いやすくするが、全サンプルの無条件相関をすべてのに焼き込んでしまう。厳密なバックテストでは、これは先読みリークである。日の相関行列は、未来を含むサンプル全体の平均相関を「知って」しまっている。誠実な評価のためには、を訓練ウィンドウのみで再推定し、サンプル外では固定するか、あるいは前方に転がしていく必要がある。これはウォークフォワード最適化フレームワーク全体が課している規律と同じであり、上記の教育用コードがそうであるように、便利なnp.cov(Z)をフルアレイに対して使ってしまい、うっかり破ってしまいやすい。単一のP&L数値を信頼する前にこれを修正すること。
再適合の頻度と先読み規律
を毎日再最適化する必要はない——それらは安定したパラメータだ。実務上妥当なケイデンスは以下の通り。
- と単変量GARCHパラメータを再推定する——週次か月次で。
- フィルター(、の更新)を毎期実行する——固定されたパラメータで、新鮮なとを得るために。フィルタリングは安価だが、当てはめは安価ではない。
- 常に予測し、決して平滑化しない。 までの情報から構築したを使ってでトレードする。2パスの構造(ウィンドウで当てはめ、それから前方にフィルターする)が誠実さを保つ鍵だ。
DCCのバックテストとライブパフォーマンスの間のギャップは、ほぼ常に先読みリーク——全サンプルの、同時点の、あるいは評価対象のトレードを含むデータでの再適合——である。バックテストとライブ条件を一致させる規律はそれ自体がバックテストとライブの整合性というトピックであり、DCCはこの点でずさんさを他のどのモデルよりも厳しく罰するモデルだ。清潔なウォークフォワード評価の後、動的相関が単純なローリング推定に対してあなたの戦略に何も付け加えないなら、それは実際の、そして公表に値するネガティブな結果である——誠実なネガティブな結果の心構えがそのまま当てはまる。
非対称DCC(aDCC)
単変量のレバレッジ効果(パート2)で悪材料が好材料よりもボラティリティを大きく引き上げるのと同様に、相関は同時ポジティブショックの後よりも同時ネガティブショックの後の方が大きく上昇する。Cappiello, Engle & Sheppard(2006)はこれを、負の部分の標準化残差の外積に駆動される項を追加する非対称DCCで捉える。
ここでであり、は同時下落から生まれる追加の相関上昇を測る。クラッシュ相関が支配的なリスクである暗号資産では、この非対称性項は通常有意であり、追加の1パラメータの価値がある。rmgarchは既定でaDCCを当てはめる(model="aDCC")。私たちのNumPy推定量に項を追加するのは単純な演習である。
比較:代替手法に対するDCC
暗号資産のポートフォリオの共分散行列を得る方法の中で、DCCはどこに位置するのか。誠実なまとめは以下の通り。
| 手法 | パラメータ | スケール可能な資産数 | 時間変化する? | 正定値性の保証? | テール依存性? |
|---|---|---|---|---|---|
| サンプル/ローリング共分散 | 0(ウィンドウ長) | 任意の | 粗い(遅延、ノイズ) | なし(補正が必要) | なし |
| EWMA(RiskMetrics) | 1() | 任意の | あり(単一の減衰) | あり | なし |
| CCC-GARCH | 個の周辺分布 + | 数十 | なし(定相関) | あり | なし |
| DCC-GARCH | 個の周辺分布 + 2 | 数十 | あり | あり | なし |
| aDCC-GARCH | 個の周辺分布 + 3 | 数十 | あり、非対称 | あり | 部分的 |
| BEKK | あり(豊か) | あり | なし | ||
| VECH | あり(最も豊か) | 困難 | なし | ||
| GARCH-コピュラ | 個の周辺分布 + コピュラ | 数十(ヴァイン) | 静的コピュラ | あり | あり |
この表からいくつか読み取れることがある。
- EWMAは、DCCが役立つと主張する前に誰もが上回るべき安価なベースラインだ。それは精神的には1パラメータの特殊ケースであり——共分散に直接単一の指数減衰を適用する——多くのポートフォリオにおいて、サンプル外で改善するのが驚くほど難しい。もしDCCが清潔なウォークフォワードでEWMAを上回らないなら、EWMAを使うこと。
- CCC対DCCはこの記事全体の要点である。同じ因数分解だが、CCCはを凍結し、DCCはそれを動かす。2つの追加パラメータ()がすべての違いであり、暗号資産ではそれらは十分にその価値を発揮する。
- BEKK/VECHはより豊かなダイナミクス——あらゆる共分散が過去のあらゆるショックに反応できる——を買うが、パラメータのコストが小さなポートフォリオに限定してしまう。4資産を超えると現実的な選択肢ではない。
- GARCH-コピュラはテール依存性の列で唯一「あり」となる手法だ。それが再びの相補性である。DCCは同時分布の動的な中心をモデル化し、コピュラはその静的なテールをモデル化する。リスクの問いが「すべてが同時に崩壊したらどうなるか」ならコピュラパイプラインを、「今のヘッジ比率/ポートフォリオ分散はどうなっているか」なら、DCCを使うこと。
システマティックな暗号資産デスクの実務上のデフォルトは、本体のヘッジ比率と動的共分散にはDCC(あるいはaDCC)、テールリスクとCVaRにはコピュラオーバーレイ、そして追加の機構が見合っているかどうかを誠実に確認するサニティチェックのベースラインにはEWMAである。
限界
- スカラーダイナミクス。 すべてのペアに対して単一のと単一のというのは強い制約だ。BTC-ETHと2つの無名アルトコインが同じ調整速度を共有する。Generalized DCCはこれを緩和するが、DCCが避けようとしたパラメータ爆発を再導入してしまう。
- 2段階推定による効率損失。 準尤度推定量は一致性を持つが完全な効率性は持たず、素朴な標準誤差は誤っている。推論を気にするならEngle-Sheppard補正を使うこと。シグナル生成には点推定値で十分だ。
- 既定でガウステール。 素のガウス準尤度は同時テールリスクを過小評価する。Student-tイノベーションは助けになるが、真のテール依存性(同時に極端な動きが起こる確率)については、DCCは間違った道具であり、コピュラモデルが正しい道具だ。DCCは相関の動的な本体を与え、コピュラは静的なテールを与える。本格的なデスクは両方を使う。
- 相関は因果ではなく、方向でもない。 の上昇は分散が失敗しつつあることを警告するが、市場の方向については何も語らない。リスクシグナルに方向性の期待を過剰に負わせないこと。
- データへの飢え。 上記のすべては、長く、清潔で、同期した履歴を前提としている。暗号資産の最も新しく最も興味深いトークンはその3つすべてに違反する。
まとめ
- 静的相関は暗号資産における嘘である。 相関はクラスター化し、持続し、ドローダウンで1に向けて急騰する——まさに分散効果が助けになるはずの瞬間に。単一のサンプルは、レジームが切り替わるプロセスを意味のない中間値に平均化してしまう。
- 完全な多変量GARCH(VECH、BEKK)はスケールしない。 パラメータ数はで増加し、両方とも実務上は少数の資産に限定される。
- DCC(Engle 2002)は問題を因数分解する。 であり、は独立な単変量GARCHの当てはめから(パート1〜2を再利用)、は2パラメータの漸化式から得られる。のみが最適化されるため、数十の資産にスケールする。
- 漸化式は、に正規化され、、のもとで、あらゆるステップで有効な正定値相関行列を生成する。
archはDCCを行わない。archで周辺分布を当てはめ、ここで示した約60行のNumPy/SciPy推定量を実装するか、mgarch(Python)やrmgarch(R、リファレンス実装)を使うこと。- 3つの具体的な成果。 ペアトレードのための動的ヘッジ比率、リスクベースの資産配分のための誠実な時間変化ポートフォリオ分散、そしてリスクオフレジームシグナルとしての平均ペアワイズ相関。
- 規律がすべてだ。 相関ターゲティングは全サンプル平均をリークするため、は訓練データのみで再推定すること。すべてのヘッジ比率にラグをかけること。前方にフィルターし、決して平滑化しないこと。ウォークフォワード評価は交渉の余地がない。
- aDCCは下方非対称性の項を追加し、クラッシュ相関が支配的な暗号資産では通常その価値がある。
- パート4では、これらの予測を使ってボラティリティターゲット戦略を構築しバックテストする。
参考文献:
- Engle, R. (2002). Dynamic Conditional Correlation: A Simple Class of Multivariate Generalized Autoregressive Conditional Heteroskedasticity Models. Journal of Business & Economic Statistics, 20(3), 339-350. DOI
- Engle, R. & Sheppard, K. (2001). Theoretical and Empirical Properties of Dynamic Conditional Correlation Multivariate GARCH. NBER Working Paper 8554. DOI
- Bollerslev, T. (1990). Modelling the Coherence in Short-Run Nominal Exchange Rates: A Multivariate Generalized ARCH Model. Review of Economics and Statistics, 72(3), 498-505. DOI
- Cappiello, L., Engle, R., & Sheppard, K. (2006). Asymmetric Dynamics in the Correlations of Global Equity and Bond Returns. Journal of Financial Econometrics, 4(4), 537-572. DOI
- Engle, R. & Kroner, K. (1995). Multivariate Simultaneous Generalized ARCH. Econometric Theory, 11(1), 122-150. DOI
- Bollerslev, T., Engle, R., & Wooldridge, J. (1988). A Capital Asset Pricing Model with Time-Varying Covariances. Journal of Political Economy, 96(1), 116-131. DOI
- Galanos, A. (2022). rmgarch: Multivariate GARCH Models. R package. CRAN.
MarketMaker.cc Team
クオンツ・リサーチ&戦略