社内アルゴリズムの内側: HRP + ロング/ショート + Hull-WhiteによるCVaR
「12のポートフォリオ最適化アルゴリズムを比較」という概要記事では、12の資産配分手法を並べて比較しました。そのうち11は教科書的な古典です。12番目のPipelineは当社独自のもので、その記事では1つの箇条書きでしか触れていませんでした。この記事では、その詳細、各数式の由来、そして仕様がどのようにRustに変換されるかについて深く掘り下げます。
Pipelineは、ウェイトを計算する新しい方法を発明するものではありません。それは、最も堅牢な既知のレシピである階層的リスクパリティ(HRP)を採用し、実際のライブ取引口座が必要とするが、プレーンなHRPには欠けている2つの層でそれを包み込みます。それは、方向性(戦略シグナルからのロング/ショート)と厳格なリスク予算(現在のボラティリティ体制に合わせて調整されたCVaR)です。これにより、4つのステージが生まれます。
4つのステージ
- I — 各資産の対数リターン。
- II — HRPからの基本ウェイト。
- III — エージェントシグナルからのロング/ショート分割、確信度によってリスクシェアを設定。
- IV — Hull-WhiteボラティリティによるCVaR補正。余剰リスクは現金に。
順に見ていきましょう。
ステージ I. 対数リターン
すべては価格から対数リターンへの移行から始まります。
ここで、は資産、は時間ステップです。対数リターンは時間とともに加算され、単純なパーセンテージ変化よりも対称的であり、あらゆる共分散計算の標準入力となります。
ステージ II. HRPを基盤として
2016年にMarcos López de Pradoによって提案されたHRPは、平均分散最適化の中心的な問題である、条件の悪い共分散行列の逆行列計算を回避します。HRPは逆行列をまったく計算しません。代わりに、相関の構造を扱います。
共分散と相関
リターンから共分散行列を構築し、それを正規化して相関行列にします。
距離行列
相関を距離指標に変換し、相関の強い資産が「近く」に配置されるようにします。
が1に近づくほど、は0に近づき、資産がクラスターを共有する可能性が高くなります。
デンドログラムと葉の順序
距離行列から平均連結法によってクラスター階層を構築し、葉の順序 を読み取ります。これは、類似した資産が隣接するように並べられた資産の順列です。
オプションのステップ:最適なクラスター数は、シルエット係数 によって選択できます。ここで、はクラスター内の平均距離、は最も近い隣接クラスターへの平均距離です。基本パスではこれは必要ありません。再帰的二分法はすでに階層を尊重しています。
準対角化
の行と列をで並べ替え、対角線に沿って大きな値を集めます。
再帰的二分法
次に、再帰はトップダウンで実行されます。各ステップでクラスターはとの半分に分割され、資本は両方の半分に分散に反比例して割り当てられます。
クラスターの分散は、その共分散サブブロックでとして計算されます。各ノードが単一の資産を保持するまで降下は続きます。ウェイトはロングオンリー、非負で、合計は1.0です。
当社の実装では、これは関数hrp_from_cov(cov) -> Vec<f64>です。相関 → 距離 → 平均連結法 → 葉の順序 → 準対角化 → 再帰的二分法。Pipelineはこれをベースとして呼び出し、シグナルなしの場合の公開optimize()でもあります。
ステージ III. ロング/ショートオーバーレイ
プレーンなHRPは「買いのみ」のポートフォリオです。しかし、戦略はしばしばどれくらいだけでなくどちらの方向も示します。ステージIIIでは、エージェントからの資産ごとのシグナル(Long/Short)を受け取り、2つのサブポートフォリオを構築します。
- 資産はシグナルによってロングとショートのバスケットに分割されます。
- 各バスケット内で、ウェイトは同じHRP(それらの資産の共分散サブブロック上)で計算され、バスケットごとに合計1になります。
- エージェントが確信度 も出力する場合、両サイド間のリスクシェアは総確信度によって設定されます。
確信度がない場合、シェアは各バスケット内の資産数に戻ります。最終的な符号付きウェイトは、ロングの場合は、ショートの場合はとなり、その後、総グロスエクスポージャーは1に正規化されます。
コードに関する正直な注記。 元の仕様には補正係数、が含まれていますが、それらには「このステップは本当に必要か?」というマークも付いています。実装ではこれらは適用されません。両サイドはリスクシェアによって直接結合され、グロスエクスポージャーを正確に1に保ち、隠れたレバレッジを生み出しません。これは仕様の意図的な簡素化であり、見落としではありません。
ステージ IV. Hull-White調整によるCVaR
HRPはリスクを構造的にバランスさせますが、金銭的な絶対的なリスクレベルについては何も知りません。最終段階では、テールリスクに厳格な上限を設け、市場体制の変化に敏感に対応させます。
ポートフォリオリターンとEWMAボラティリティ
まず、ウェイトをポートフォリオリターンに集約し、EWMAで条件付きボラティリティを推定します。
ここで(古典的なRiskMetrics値)です。EWMAは、全履歴にわたって平均化されたものではなく、「今日の」ボラティリティを提供します。
Hull-Whiteリスケーリング
重要なアイデア:過去のリターンはそのままでは使えません。それらは異なるボラティリティの下で発生したものです。Hull-White法は、各過去のリターンを現在のレベルにリスケールします。
穏やかな月は「引き伸ばされ」、激動の月は「圧縮され」、分布は現在の体制に持ち込まれます。
VaRとCVaR
リスケールされた分布上で、損失の分位数とテールにおける平均損失を求めます。
CVaR(別名Expected Shortfall)は、「典型的な悪い日はどれくらい悪いか」ではなく、「最悪の パーセントにわたって平均してどれくらい悪いか」に答えるため、テールの厚さを見ることができ、その端だけではありません。
リスク予算と現金
CVaRが許容しきい値を超えた場合、すべてのリスクのあるポジションは単一の係数で縮小され、解放された資本は現金に移動します。
したがって、テールリスクが増大するとポートフォリオはリスクを軽減し、落ち着くと市場に再参入します。
仕様からコードへ
アルゴリズム全体は単一のRustクレートportfolio-pipelineにあり、ワークスペースの統一された契約に従います。
pub fn optimize(prices: &[Vec<f64>]) -> Vec<f64>
これはロングオンリーのプロジェクション(シグナルなしのステージI、II、IV)であり、他の11のアルゴリズムとまったく同じprices -> weightsインターフェースであるため、Pipelineはそれらのいずれかのドロップイン代替品です。すべてのステージを含む完全版は別の関数です。
pub fn run(
prices: &[Vec<f64>],
signals: Option<&[Side]>, // Long / Short per asset
confidence: Option<&[f64]>, // agent confidence → risk shares λ
cfg: &PipelineConfig, // CVaR / Hull-White parameters
) -> PipelineResult // signed weights + cash + cvar + σ
オーバーレイのデフォルトは、テールcvar_alpha = 0.05、予算cvar_max = 0.05、EWMA ewma_lambda = 0.94、Hull-Whiteウィンドウhw_window = 0(全履歴)です。実装には外部依存関係がなく、意図的に防御的です。短い履歴(4つ未満の価格ポイント)では等しいウェイトを返し、CVaRオーバーレイは8つ以上のリターン観測値がある場合にのみ機能します。そうでなければ、テールを推定するものはありません。
Rustを使用する理由:バックテストと本番の両方で1つの決定論的なコードベースを使用し、「研究はPython、本番は別のもの」というずれがなく、比較バックエンドを通じて1回のリクエストですべての12のアルゴリズムを実行するのに十分な速さです。
時間コスト
「十分な速さ」とはどれくらい速いのでしょうか?HRPコア(対数リターン → 共分散 → 平均連結法 → 準対角化 → 再帰的ウェイト)をスタンドアロンのベンチマークに抽出し、まったく同じ計算を7つの言語 — C、C++、Rust、Zig、Python、Node.js、Bun — で同一条件下で実行しました:Apple Silicon、シングルスレッド、資産あたり365日間の日次観測、合成価格、資産数は10から10,000まで。
計算量について一言。これは全体の形を決めるからです。平均連結法の教科書的なバージョンは、マージのたびに最も近いペアを求めて距離行列全体を再走査します — これはであり、数千資産でボトルネックになります。本ベンチマークでは代わりに**の最近傍チェーンアルゴリズム(Müllner 2011)を使用しています — SciPyのlinkage(method='average')の背後にあるものと同じです。これにより、クラスタリングはもはや支配的なステージではありません:では、約0.5秒のパスのうち約15 msにすぎません。コストは今や共分散行列、**に支配されています — これはHRP系のどの手法も回避できない唯一のステージです。
実行結果が示すもの(言語ごとの完全な表とワンコマンドの再現スクリプトはプロジェクトリポジトリにあります):
- 現実的なポートフォリオでは実質ゼロコストです。 暗号通貨バスケットは数十の資産であり、100を超えることはめったにありません。の場合、フルHRPパスはNodeでも1桁ミリ秒、Rust/Cではマイクロ秒です。毎ティックウェイトを再計算することは問題ありません。
- RustはCの約1.0~1.3倍の範囲に収まります — 同じオーダーであり、両方ともコンパイルされ、が数千に達すると実質的に互角です。Cは生の算術演算ではわずかに速いですが、RustはガベージコレクタもUBもなしで同じ予測可能性を提供します。
- 数千の資産までスケールします。 の連結法では、コンパイル言語でフルパスはで約0.5秒、で数秒です。解釈実行のNodeでさえを2秒未満でこなします。今や上限を決めるのはクラスタリングではなく共分散ステージです。
実用的な結論:当社のポートフォリオサイズでは、Rustを選ぶのは「Cに勝つ」ためではありません(Cはここでは少し速いですが) — 研究と本番の両方で1つの決定論的なコードベースを使用し、GCの一時停止がなく、何年ものパフォーマンスの余裕があるためです。結果と再現スクリプトを含む7言語の完全なベンチマークは、プロジェクトリポジトリで公開されています。
Pipelineが12のアルゴリズムの中で占める位置
意図的に操作された単一のバスケットでの比較では、PipelineはHRPのように振る舞いました。なぜなら、ロングオンリーのoptimize()エントリポイントを通じて、それはCVaRオーバーレイを備えたHRPだからです。その方向性メカニズムは、戦略シグナルを供給したときにのみ活性化します。それが全体的なポイントです。Pipelineは「バックテストウェイトのためのもう1つの最適化ツール」ではなく、戦略シグナルと実際の注文の間の実行層です。それはあなたの買い/売りコールを受け取り、各サイド内でHRPによって資本を配置し、確信度によってサイドをバランスさせ、テールリスクを設定された予算にまで削減します。
他の11の方法が存在し、どのように異なるかという完全なコンテキストについては、概要記事「12のポートフォリオ最適化アルゴリズムを比較」を参照してください。そして、portfolio-optimizer.marketmaker.ccでこれらすべてをライブで試すことができます。
参考文献
- López de Prado, M. (2016). Building Diversified Portfolios that Outperform Out of Sample. The Journal of Portfolio Management.
- López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley.
- Hull, J., & White, A. (1998). Incorporating Volatility Updating into the Historical Simulation Method for Value at Risk. Journal of Risk.
- Rockafellar, R. T., & Uryasev, S. (2000). Optimization of Conditional Value-at-Risk. Journal of Risk.
- RiskMetrics Group (1996). RiskMetrics — Technical Document. J.P. Morgan.
- Marketmaker.cc: marketmaker.cc
引用
@article{soloviov2026pipeline,
author = {Soloviov, Eugen and Zhuravleva, Marina and Kiselev, Kirill},
title = {Inside Our House Algorithm: HRP + Long/Short + CVaR with Hull-White Adjustment},
year = {2026},
url = {https://marketmaker.cc/ja/blog/post/portfolio-pipeline-hrp-cvar},
description = {A deep dive into Pipeline, a composite portfolio allocation algorithm built on Hierarchical Risk Parity with a signal-driven long/short overlay and a Hull-White CVaR risk-budget correction, with the full specification and its Rust implementation.}
}
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.
Financial mathematics
Fifth-year student at Bauman Moscow State Technical University (Automatic Control Systems), specializing in financial mathematics. Background in calibrating stochastic-volatility (Heston) and local-volatility (Dupire) models, fair pricing of options including exotics via both Monte-Carlo and analytic formulas, hedging-error reduction, and exposure to LSV models.
Portfolio optimization
Fourth-year student at the Faculty of Mechanics and Mathematics, Novosibirsk State University (NSU); thesis on Heston-model calibration and delta-hedging within the same model. Works on portfolio optimization.