Di Balik Algoritma Kami: HRP + Long/Short + CVaR dengan Hull-White
Dalam tinjauan kami «12 Algoritma Optimisasi Portofolio, Dibandingkan» kami menguji selusin metode alokasi secara berdampingan. Sebelas di antaranya adalah klasik dari buku teks. Yang kedua belas, Pipeline, adalah milik kami — dan hanya mendapat satu poin singkat di artikel itu. Artikel ini adalah penjelasan mendalam: apa yang ada di dalamnya, dari mana setiap formula berasal, dan bagaimana spesifikasi tersebut diwujudkan dalam Rust.
Pipeline tidak menemukan cara baru untuk menghitung bobot. Pipeline mengambil resep paling andal yang dikenal — Hierarchical Risk Parity (HRP) — dan membungkusnya dalam dua lapisan yang benar-benar dibutuhkan akun trading langsung tetapi tidak dimiliki HRP biasa: arah (long/short dari sinyal strategi) dan anggaran risiko yang ketat (CVaR yang disesuaikan untuk rezim volatilitas saat ini). Ini menghasilkan empat tahap.
Empat tahap
- I — log return dari setiap aset.
- II — bobot dasar dari HRP.
- III — pembagian long/short dari sinyal agen, dengan porsi risiko ditentukan oleh tingkat kepercayaan.
- IV — koreksi CVaR dengan volatilitas Hull-White; kelebihan risiko dialihkan ke kas.
Mari kita telusuri satu per satu.
Tahap I. Log return
Semuanya dimulai dari perpindahan harga ke log return:
di mana adalah aset dan adalah langkah waktu. Log return bersifat aditif terhadap waktu dan lebih simetris dibandingkan perubahan persentase biasa — masukan standar untuk semua perhitungan kovarians.
Tahap II. HRP sebagai fondasi
HRP, yang diusulkan oleh Marcos López de Prado pada 2016, menghindari penyakit utama Mean-Variance Optimization — membalik matriks kovarians yang ill-conditioned. HRP sama sekali tidak membaliknya. Sebaliknya, HRP bekerja dengan struktur korelasi.
Kovarians dan korelasi
Dari return kita membangun matriks kovarians dan menormalisasinya menjadi matriks korelasi :
Matriks jarak
Kita mengubah korelasi menjadi metrik jarak, sehingga aset yang sangat berkorelasi berada "berdekatan":
Semakin mendekati 1, semakin mendekati 0 — dan semakin besar kemungkinan aset tersebut berbagi kluster yang sama.
Dendrogram dan urutan daun
Dari matriks jarak kita membangun hierarki kluster via average linkage dan membaca leaf order — permutasi aset di mana aset yang mirip berada bersebelahan.
Langkah opsional: jumlah kluster optimal dapat dipilih menggunakan koefisien silhouette , di mana adalah rata-rata jarak dalam kluster dan adalah rata-rata jarak ke kluster tetangga terdekat. Proses dasar tidak memerlukannya — biseksi rekursif sudah menghormati hierarki.
Kuasi-diagonalisasi
Kita mempermutasikan baris dan kolom berdasarkan , mengumpulkan nilai-nilai besar di sepanjang diagonal:
Biseksi rekursif
Kemudian rekursi berjalan dari atas ke bawah. Pada setiap langkah sebuah kluster dibagi dua menjadi dan , dan modal dialokasikan antara dua bagian tersebut berbanding terbalik dengan variansinya:
Variansi sebuah kluster dihitung pada sub-blok kovariansnya sebagai . Proses turun berlanjut hingga setiap node memuat satu aset. Bobot bersifat long-only, tidak negatif, dan berjumlah 1.0.
Dalam implementasi kami ini adalah fungsi hrp_from_cov(cov) -> Vec<f64>: korelasi → jarak → average linkage → leaf order → kuasi-diagonalisasi → biseksi rekursif. Pipeline memanggilnya sebagai dasarnya — dan juga merupakan optimize() publik untuk kasus tanpa sinyal.
Tahap III. Overlay long/short
HRP biasa adalah portofolio "beli saja". Namun sebuah strategi sering kali menunjukkan bukan hanya seberapa banyak tetapi juga ke arah mana. Tahap III mengambil sinyal per aset (Long/Short) dari agen dan membangun dua sub-portofolio.
- Aset dibagi menjadi keranjang long dan short berdasarkan sinyal.
- Di dalam masing-masing keranjang, bobot dihitung dengan HRP yang sama (pada sub-blok kovarians dari aset tersebut), berjumlah 1 per keranjang.
- Jika agen juga mengeluarkan tingkat kepercayaan , porsi risiko antara kedua sisi ditentukan oleh total kepercayaan:
Tanpa tingkat kepercayaan, porsi dikembalikan ke jumlah aset di setiap keranjang. Bobot bertanda akhir adalah untuk long dan untuk short, setelah itu seluruh gross exposure dinormalisasi menjadi 1.
Catatan jujur tentang kode. Spesifikasi asli memuat faktor koreksi , — tetapi juga menandainya dengan "apakah kita bahkan membutuhkan langkah ini?". Implementasi tidak menerapkannya: dua sisi digabungkan langsung berdasarkan porsi risiko , yang membuat gross exposure tepat di 1 dan tidak menciptakan leverage tersembunyi. Ini adalah penyederhanaan spesifikasi yang disengaja, bukan kelalaian.
Tahap IV. CVaR dengan penyesuaian Hull-White
HRP menyeimbangkan risiko secara struktural, tetapi tidak mengetahui apa-apa tentang tingkat risiko absolut dalam satuan uang. Tahap akhir menempatkan batas keras pada risiko ekor — dan membuatnya peka terhadap perubahan rezim pasar.
Return portofolio dan volatilitas EWMA
Pertama kita mereduksi bobot menjadi return portofolio dan memperkirakan volatilitas kondisional dengan EWMA:
dengan (nilai RiskMetrics klasik). EWMA memberikan volatilitas "hari ini" daripada yang dirata-ratakan sepanjang sejarah.
Penyekalaan ulang Hull-White
Ide utama: return masa lalu tidak bisa diambil apa adanya — return tersebut terjadi di bawah volatilitas yang berbeda. Metode Hull-White menyekalakan ulang setiap return masa lalu ke tingkat saat ini:
Bulan yang tenang "diregangkan", bulan yang bergolak "dikompres", dan distribusi dibawa ke rezim saat ini.
VaR dan CVaR
Pada distribusi yang telah disekalakan ulang kita mengambil kuantil kerugian dan rata-rata kerugian di ekor:
CVaR (a.k.a. Expected Shortfall) menjawab bukan "seberapa buruk hari buruk yang tipikal" tetapi "seberapa buruk rata-rata di seluruh persen terburuk" — sehingga ia melihat ketebalan ekor, bukan hanya tepinya.
Anggaran risiko dan kas
Jika CVaR melebihi ambang batas yang dapat diterima, setiap posisi berisiko dikecilkan dengan satu faktor tunggal, dan modal yang dibebaskan dipindahkan ke kas:
Dengan demikian portofolio mengurangi risiko sendiri ketika risiko ekor meningkat dan memasuki kembali pasar ketika keadaan mereda.
Dari spesifikasi ke kode
Seluruh algoritma berada dalam satu crate Rust, portfolio-pipeline, dan mengikuti kontrak seragam workspace:
pub fn optimize(prices: &[Vec<f64>]) -> Vec<f64>
Ini adalah proyeksi long-only (tahap I, II, IV tanpa sinyal) — antarmuka prices -> weights yang persis sama dengan sebelas algoritma lainnya, sehingga Pipeline dapat menggantikan semua di antaranya secara langsung. Versi lengkap dengan setiap tahap adalah fungsi terpisah:
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 + σ
Default overlay: ekor cvar_alpha = 0.05, anggaran cvar_max = 0.05, EWMA ewma_lambda = 0.94, jendela Hull-White hw_window = 0 (seluruh sejarah). Implementasi tidak memiliki dependensi eksternal dan secara sengaja bersifat defensif: pada sejarah singkat (kurang dari 4 titik harga) ia mengembalikan bobot yang sama, dan overlay CVaR hanya aktif pada ≥8 observasi return — jika tidak, tidak ada yang bisa diperkirakan dari ekor.
Mengapa Rust: satu basis kode deterministik untuk backtest dan produksi, tanpa "Python di riset, sesuatu yang lain di prod" yang menyimpang, dan cukup cepat untuk menjalankan semua dua belas algoritma dalam satu permintaan melalui backend perbandingan.
Berapa biaya waktu yang diperlukan
Seberapa cepat "cukup cepat"? Kami mengekstrak inti HRP (log return → kovarians → average linkage → kuasi-diagonalisasi → bobot rekursif) ke dalam benchmark mandiri dan menjalankan matematika yang persis sama di tujuh bahasa — C, C++, Rust, Zig, Python, Node.js dan Bun — dalam kondisi identik: Apple Silicon, satu utas, 365 observasi harian per aset, harga sintetis, jumlah aset dari 10 hingga 10.000.
Sepatah kata tentang kompleksitas, karena itu menentukan keseluruhan bentuk. Versi buku teks dari average linkage memindai ulang seluruh matriks jarak untuk menemukan pasangan terdekat pada setiap penggabungan — itu adalah dan menjadi bottleneck pada beberapa ribu aset. Benchmark ini menggunakan algoritma nearest-neighbour-chain (Müllner 2011) — yang sama dengan yang digunakan SciPy's linkage(method='average'). Dengan itu, klusterisasi bukan lagi tahap dominan: pada sekitar ~15 ms dari ~0,5 s total. Biaya sekarang didominasi oleh matriks kovarians, — satu-satunya tahap yang tidak dapat dihindari oleh metode gaya HRP mana pun.
Yang ditunjukkan oleh percobaan (tabel per bahasa lengkap dan skrip reproduksi satu perintah ada di repositori proyek):
- Pada portofolio realistis, ini gratis. Keranjang kripto terdiri dari puluhan aset, jarang lebih dari seratus. Pada satu pass HRP penuh adalah milidetik satu digit bahkan di Node dan mikrodetik di Rust/C. Menghitung ulang bobot pada setiap tick bukan masalah.
- Rust berada dalam ~1,0–1,3× dari C — urutan besaran yang sama, keduanya terkompilasi, dan efektif setara begitu mencapai ribuan. C sedikit lebih cepat pada aritmatika mentah, tetapi Rust memberikan prediktabilitas yang sama tanpa garbage collector dan tanpa UB.
- Skala hingga ribuan aset. Dengan linkage satu pass penuh adalah ~0,5 detik pada dan beberapa detik pada dalam bahasa terkompilasi; bahkan Node yang diinterpretasikan berhasil melewati dalam kurang dari dua detik. Yang menjadi batas sekarang adalah tahap kovarians, bukan klusterisasi.
Kesimpulan pragmatis: pada ukuran portofolio kami, memilih Rust bukan tentang "mengalahkan C" (C sedikit lebih cepat di sini) — ini tentang satu basis kode deterministik untuk riset dan produksi, tanpa jeda GC dan headroom performa selama bertahun-tahun. Benchmark tujuh bahasa lengkap, dengan hasil dan skrip reproduksi, terbuka di repositori proyek.
Di mana Pipeline berada di antara dua belas algoritma
Dalam perbandingan kami pada satu keranjang (yang sengaja dirancang), Pipeline berperilaku seperti HRP — karena melalui titik masuk optimize() long-only ia adalah HRP dengan overlay CVaR. Mesin arahnya hanya aktif ketika Anda memberinya sinyal strategi. Itulah inti permasalahannya: Pipeline bukan "optimizer lain untuk bobot backtesting" tetapi lapisan eksekusi antara sinyal strategi dan order nyata — Pipeline mengambil panggilan beli/jual Anda, menyusun modal berdasarkan HRP di setiap sisi, menyeimbangkan sisi-sisi berdasarkan tingkat kepercayaan, dan memotong risiko ekor hingga anggaran yang ditentukan.
Untuk konteks lengkap — sebelas metode lain apa yang ada dan bagaimana perbedaannya — lihat tinjauan, «12 Algoritma Optimisasi Portofolio, Dibandingkan». Dan Anda dapat mencoba semuanya secara langsung di portfolio-optimizer.marketmaker.cc.
Referensi
- 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
Kutipan
@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/id/blog/post/portfolio-pipeline-hrp-cvar},
description = {Penjelasan mendalam tentang Pipeline, algoritma alokasi portofolio komposit yang dibangun di atas Hierarchical Risk Parity dengan overlay long/short berbasis sinyal dan koreksi anggaran risiko CVaR Hull-White, beserta spesifikasi lengkap dan implementasi Rust-nya.}
}
Penulis
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.