← Makalelere geri dön
May 25, 2026
5 dakikalık okuma

Kendi Algoritmamızın İçinde: HRP + Long/Short + CVaR ve Hull-White

Kendi Algoritmamızın İçinde: HRP + Long/Short + CVaR ve Hull-White
#portföy optimizasyonu
#HRP
#hiyerarşik risk paritesi
#CVaR
#Hull-White
#EWMA
#long/short
#risk yönetimi
#Rust
#kantitatif finans

«12 Portföy Optimizasyon Algoritması, Karşılaştırmalı» başlıklı genel bakış yazımızda bir düzine tahsis yöntemini yan yana koşturduk. Bunların on biri ders kitabı klasikleri. On ikincisi, Pipeline, bize ait — ve o yazıda tam olarak tek bir madde hakkı bulabildi. Bu makale ise derinlemesine inceleme: içinde ne var, her formül nereden geliyor ve spesifikasyon Rust'a nasıl dönüşüyor.

Pipeline, ağırlık hesaplamak için yeni bir yöntem icat etmiyor. Bilinen en sağlam tarifi — Hiyerarşik Risk Paritesi (HRP) — alıyor ve gerçek bir canlı işlem hesabının ihtiyaç duyduğu ama saf HRP'nin sunmadığı iki katmanla sarıyor: yön (strateji sinyallerinden gelen long/short) ve sabit bir risk bütçesi (mevcut volatilite rejimine göre ayarlanmış CVaR). Bu dört aşama oluşturuyor.

Dört aşama

fiyatlar  I  log getiriler  II  HRP ag˘ırlıkları  III  long/short  IV  CVaR bu¨tc¸esi\text{fiyatlar} \;\xrightarrow{\text{I}}\; \text{log getiriler} \;\xrightarrow{\text{II}}\; \text{HRP ağırlıkları} \;\xrightarrow{\text{III}}\; \text{long/short} \;\xrightarrow{\text{IV}}\; \text{CVaR bütçesi}
  • I — her varlığın log getirileri.
  • II — HRP'den temel ağırlıklar.
  • III — ajan sinyallerinden gelen long/short bölünmesi; risk payları güven düzeyine göre belirlenir.
  • IV — Hull-White volatilite düzeltmesiyle CVaR kontrolü; fazla risk nakde aktarılır.

Sırayla inceleyelim.

Aşama I. Log getiriler

Her şey fiyatlardan log getirilere geçişle başlar:

ri,t=ln ⁣(Si,tSi,t1)r_{i,t} = \ln\!\left(\frac{S_{i,t}}{S_{i,t-1}}\right)

burada ii varlık, tt ise zaman adımıdır. Log getiriler zaman içinde birikir ve düz yüzde değişimlerine kıyasla daha simetrik bir dağılım sergiler — herhangi bir kovaryans hesabının standart girdisidir.

Aşama II. Temel olarak HRP

HRP, 2016 yılında Marcos López de Prado tarafından önerilmiş ve Ortalama-Varyans Optimizasyonu'nun temel hastalığını — kötü koşullu bir kovaryans matrisini ters çevirmeyi — tamamen bertaraf etmiştir. Matrisi hiç ters çevirmez. Bunun yerine korelasyonların yapısıyla çalışır.

Kovaryans ve korelasyon

Getirilerden kovaryans matrisi Σ\Sigma'yı inşa eder ve onu korelasyon matrisi CC'ye normalize ederiz:

Σi,j=Cov(ri,rj),Ci,j=ρi,j=Cov(ri,rj)σiσj\Sigma_{i,j} = \mathrm{Cov}(r_i, r_j), \qquad C_{i,j} = \rho_{i,j} = \frac{\mathrm{Cov}(r_i, r_j)}{\sigma_i \sigma_j}

Uzaklık matrisi

Korelasyonu, güçlü şekilde ilişkili varlıkların birbirine "yakın" konumlandığı bir uzaklık metriğine dönüştürürüz:

di,j=1ρi,j2d_{i,j} = \sqrt{\frac{1 - \rho_{i,j}}{2}}

ρi,j\rho_{i,j} 1'e ne kadar yakınsa, di,jd_{i,j} 0'a o kadar yakındır — ve bu varlıkların aynı kümeyi paylaşma olasılığı o kadar yüksektir.

Dendrogram ve yaprak sırası

Uzaklık matrisinden ortalama bağlantı yöntemiyle bir küme hiyerarşisi oluşturur ve yaprak sırasını π=(π1,,πN)\pi = (\pi_1, \ldots, \pi_N) okuruz — benzer varlıkların birbirine bitişik konumlandığı bir permütasyon.

İsteğe bağlı adım: optimal küme sayısı silhouette katsayısıyla si=biaimax(bi,ai)s_i = \dfrac{b_i - a_i}{\max(b_i, a_i)} seçilebilir; burada aia_i küme içi ortalama uzaklık, bib_i ise en yakın komşu kümeye ortalama uzaklıktır. Temel geçiş buna ihtiyaç duymaz — özyinelemeli ikiye bölme hiyerarşiye zaten saygı gösterir.

Yarı-köşegenleştirme

Σ\Sigma'nın satır ve sütunlarını π\pi'ye göre permüte ederek büyük değerleri köşegen boyunca toplarız:

Σi,jq=Σπi,πj\Sigma^{q}_{i,j} = \Sigma_{\pi_i, \pi_j}

Özyinelemeli ikiye bölme

Ardından özyineleme yukarıdan aşağıya çalışır. Her adımda bir küme LL ve RR olmak üzere ikiye bölünür ve sermaye iki yarı arasında varyanslarıyla ters orantılı şekilde dağıtılır:

wL=1/σL21σL2+1σR2,wR=1wLw_L = \frac{1/\sigma_L^2}{\dfrac{1}{\sigma_L^2} + \dfrac{1}{\sigma_R^2}}, \qquad w_R = 1 - w_L

Bir kümenin varyansı, kovaryans alt bloğu üzerinde σC2=1m2i,jCΣi,jq\sigma_C^2 = \tfrac{1}{m^2}\sum_{i,j \in C}\Sigma^{q}_{i,j} olarak hesaplanır. İniş, her düğüm tek bir varlık içerene kadar sürer. Ağırlıklar yalnızca long, negatif değer almaz ve toplamları 1.0'dır.

Uygulamamamızda bu, hrp_from_cov(cov) -> Vec<f64> fonksiyonudur: korelasyon → uzaklık → ortalama bağlantı → yaprak sırası → yarı-köşegenleştirme → özyinelemeli ikiye bölme. Pipeline bunu temel olarak kullanır — ve aynı zamanda sinyalsiz durum için genel optimize() fonksiyonudur.

Aşama III. Long/short katmanı

Saf HRP, "yalnızca alım" yapan bir portföydür. Ancak bir strateji çoğunlukla yalnızca ne kadar değil, hangi yönde olduğunu da söyler. Aşama III, ajandan varlık bazında sinyaller (Long/Short) alır ve iki alt portföy oluşturur.

  1. Varlıklar sinyale göre long ve short sepetlerine ayrılır.
  2. Her sepet içinde ağırlıklar, aynı HRP ile (o varlıkların kovaryans alt bloğu üzerinde) hesaplanır ve her sepet için toplamı 1 olacak şekilde normalize edilir.
  3. Ajan ayrıca bir güven düzeyi pip_i yayımlıyorsa, taraflar arasındaki risk payları toplam güven düzeyine göre belirlenir:

ξL=iLpi,ξS=iSpi,λL=ξLξL+ξS,λS=ξSξL+ξS\xi_L = \sum_{i \in L} p_i, \quad \xi_S = \sum_{i \in S} p_i, \qquad \lambda_L = \frac{\xi_L}{\xi_L + \xi_S}, \quad \lambda_S = \frac{\xi_S}{\xi_L + \xi_S}

Güven düzeyi yoksa paylar, her sepetteki varlık sayısına geri döner. Nihai işaretli ağırlık; longlar için wi=λLwiHRPw_i = \lambda_L \cdot w_i^{\text{HRP}}, shortlar için wi=λSwiHRPw_i = -\lambda_S \cdot w_i^{\text{HRP}} olur; ardından toplam brüt maruz kalma 1'e normalize edilir.

Kod hakkında dürüst bir not. Orijinal spesifikasyon αL=λL/σL\alpha_L = \sqrt{\lambda_L}/\sigma_L, αS=λS/σS\alpha_S = \sqrt{\lambda_S}/\sigma_S düzeltme faktörlerini taşır — ancak bunları "bu adıma gerçekten gerek var mı?" notiyla işaretler. Uygulama bu faktörleri uygulamaz: iki taraf doğrudan λ\lambda risk paylarıyla birleştirilir; bu sayede brüt maruz kalma tam olarak 1'de kalır ve gizli kaldıraç oluşmaz. Bu, spesifikasyonun kasıtlı bir basitleştirmesidir, bir gözden kaçırma değildir.

Aşama IV. Hull-White düzeltmesiyle CVaR

HRP riski yapısal olarak dengeler, ancak para cinsinden riskin mutlak düzeyi hakkında hiçbir şey bilmez. Son aşama, kuyruk riskine sert bir üst sınır koyar — ve bunu piyasa rejimindeki değişikliklere duyarlı hale getirir.

Portföy getirisi ve EWMA volatilitesi

Önce ağırlıkları bir portföy getirisine indirgeyip koşullu volatiliteyi EWMA ile tahmin ederiz:

rp,t=i=1nwiri,t,σp,t2=λσp,t12+(1λ)rp,t12r_{p,t} = \sum_{i=1}^{n} w_i\, r_{i,t}, \qquad \sigma_{p,t}^2 = \lambda\, \sigma_{p,t-1}^2 + (1 - \lambda)\, r_{p,t-1}^2

λ=0.94\lambda = 0.94 (klasik RiskMetrics değeri) ile. EWMA, tüm tarih boyunca ortalaması alınan bir değer yerine "bugünün" volatilitesini verir.

Hull-White yeniden ölçeklendirme

Temel fikir: geçmiş getiriler olduğu gibi alınamaz — bunlar farklı bir volatilite altında gerçekleşti. Hull-White yöntemi, geçmişteki her getiriyi mevcut düzeye yeniden ölçekler:

r~p,s=σp,t+1σp,srp,s,s=tN+1,,t\widetilde{r}_{p,s} = \frac{\sigma_{p,t+1}}{\sigma_{p,s}}\, r_{p,s}, \qquad s = t - N + 1, \ldots, t

Sakin bir ay "genişletilir", türbülanslı bir ay "sıkıştırılır" ve dağılım mevcut rejime taşınır.

VaR ve CVaR

Yeniden ölçeklendirilmiş dağılım üzerinde kayıp kantilini ve kuyruktaki ortalama kaybı alırız:

VaRαHW=q1α(r~p)VaR_\alpha^{HW} = -q_{1-\alpha}(\widetilde{r}_p)

CVaRαHW=E ⁣[r~pr~pq1α(r~p)]CVaR_\alpha^{HW} = -\mathbb{E}\!\left[\widetilde{r}_p \mid \widetilde{r}_p \le q_{1-\alpha}(\widetilde{r}_p)\right]

CVaR (Beklenen Açık olarak da bilinir), "tipik kötü bir gün ne kadar kötü" sorusunu değil, "en kötü α\alpha yüzde genelinde ortalamada ne kadar kötü" sorusunu yanıtlar — böylece yalnızca kuyruğun ucunu değil, kalınlığını da görür.

Risk bütçesi ve nakit

CVaR kabul edilebilir eşiği aşarsa, her riskli pozisyon tek bir faktörle küçültülür ve serbest kalan sermaye nakde taşınır:

winew=γwi,γ=CVaRmaxCVaRαHW,wcash=1i=1nwineww_i^{new} = \gamma\, w_i, \quad \gamma = \frac{CVaR_{\max}}{CVaR_\alpha^{HW}}, \qquad w_{cash} = 1 - \sum_{i=1}^{n} |w_i^{new}|

Böylece portföy, kuyruk riski arttığında riskini azaltır ve piyasa sakinleştiğinde yeniden girer.

Spesifikasyondan koda

Tüm algoritma tek bir Rust crate'inde, portfolio-pipeline'da yaşar ve çalışma alanının tekdüze sözleşmesine uyar:

pub fn optimize(prices: &[Vec<f64>]) -> Vec<f64>

Bu, yalnızca long projeksiyondur (sinyalsiz I, II, IV aşamaları) — diğer on bir algoritmayla aynı prices -> weights arayüzü; Pipeline, herhangi birinin doğrudan yerine geçebilir. Her aşamayla birlikte tam sürüm ayrı bir fonksiyondur:

pub fn run(
    prices: &[Vec<f64>],
    signals: Option<&[Side]>,      // her varlık için Long / Short
    confidence: Option<&[f64]>,    // ajan güveni → risk payları λ
    cfg: &PipelineConfig,          // CVaR / Hull-White parametreleri
) -> PipelineResult                // işaretli ağırlıklar + nakit + cvar + σ

Katman varsayılanları: kuyruk cvar_alpha = 0.05, bütçe cvar_max = 0.05, EWMA ewma_lambda = 0.94, Hull-White penceresi hw_window = 0 (tüm geçmiş). Uygulamanın harici bağımlılığı yoktur ve kasıtlı olarak savunmacı tasarlanmıştır: kısa geçmişlerde (4'ten az fiyat noktası) eşit ağırlıklar döndürür ve CVaR katmanı yalnızca ≥8 getiri gözleminde devreye girer — aksi takdirde bir kuyruk tahmin etmek için yeterli veri yoktur.

Neden Rust: araştırma ile üretimde tek bir deterministik kod tabanı; "araştırmada Python, üretimde başka bir şey" kaymasının önüne geçilir ve karşılaştırma arka ucu aracılığıyla tek bir istekte on iki algoritmanın tamamını çalıştıracak kadar hızlı.

Süre açısından maliyeti

"Yeterince hızlı" ne demek? HRP çekirdeğini (log getiriler → kovaryans → ortalama bağlantı → yarı-köşegenleştirme → özyinelemeli ağırlıklar) bağımsız bir karşılaştırma ölçütüne çektik ve tamamen aynı matematiği yedi dilde — C, C++, Rust, Zig, Python, Node.js ve Bun — özdeş koşullar altında çalıştırdık: Apple Silicon, tek iş parçacığı, varlık başına 365 günlük gözlem, sentetik fiyatlar, 10'dan 10.000'e kadar varlık sayısı NN.

Karmaşıklık hakkında birkaç söz; çünkü bu genel şekli belirliyor. Ortalama bağlantının ders kitabı versiyonu, her birleştirmede en yakın çifti bulmak için tam uzaklık matrisini yeniden tarar — bu O(N3)O(N^3)'tür ve birkaç bin varlıkta darboğaz haline gelir. Karşılaştırma ölçütü bunun yerine O(N2)O(N^2) en yakın komşu zinciri algoritmasını (Müllner 2011) kullanır — SciPy'nin linkage(method='average') fonksiyonunun arkasındaki algoritmanın aynısı. Bu sayede kümeleme artık baskın aşama değildir: N=2000N = 2000'de yaklaşık 0,5 s'lik bir geçişin ~15 ms'si buna gider. Maliyet artık kovaryans matrisi, O(N2T)O(N^2 \cdot T) tarafından domine edilmektedir — hiçbir HRP tarzı yöntemin kaçınamayacağı tek aşama.

Çalıştırmaların gösterdiği sonuçlar (dil bazında tam tablolar ve tek komutla tekrar etme betiği proje deposunda yer alıyor):

  • Gerçekçi portföylerde bedava. Bir kripto sepeti onlarca, nadiren yüzden fazla varlık içerir. N100N \le 100'de tam bir HRP geçişi, Node'da bile tek haneli milisaniyeler, Rust/C'de ise mikrosaniyeler düzeyindedir. Her tik'te ağırlıkları yeniden hesaplamak sorun değildir.
  • Rust, C'nin ~1,0–1,3× içinde — aynı büyüklük sırası, ikisi de derlenmiş ve NN binlere ulaştığında pratikte eşit. C, ham aritmetikte biraz daha hızlı ancak Rust, çöp toplayıcı ve tanımsız davranış olmaksızın aynı öngörülebilirliği sunar.
  • Binlerce varlığa ölçeklenir. O(N2)O(N^2) bağlantıyla derlenmiş dillerde N=2000N = 2000'de tam geçiş ~0,5 s, N=5000N = 5000'de birkaç saniyedir; yorumlanan Node bile N=2000N = 2000'i iki saniyenin altında tamamlar. Artık tavanı belirleyen kümeleme değil, kovaryans aşamasıdır.

Pratik çıkarım: portföy boyutlarımızda Rust tercihinin sebebi "C'yi geçmek" değil (C burada biraz daha hızlı) — araştırma ve üretim için tek bir deterministik kod tabanı; GC duraklamaları yok, yıllarca performans başlık alanı. Sonuçlar ve tekrar etme betiğiyle birlikte yedi dilli tam karşılaştırma ölçütü proje deposunda açık kaynak olarak yayınlanmaktadır.

Pipeline'ın on iki algoritma arasındaki yeri

Tek (kasıtlı olarak kurgulanmış) bir sepet üzerindeki karşılaştırmamızda Pipeline, HRP gibi davrandı — çünkü yalnızca long optimize() giriş noktasından bakıldığında HRP + CVaR katmanıdır. Yönsel mekanizması yalnızca strateji sinyalleri beslendiğinde devreye girer. İşin özü bu: Pipeline, "geri test ağırlıkları için bir optimizatör daha" değil, strateji sinyalleri ile gerçek emirler arasındaki yürütme katmanıdır — al/sat çağrılarınızı alır, her tarafta HRP ile sermayeyi düzenler, tarafları güven düzeyine göre dengeler ve kuyruk riskini belirlenen bütçeye kırpar.

Diğer on bir yöntemin neler olduğu ve nasıl farklılaştığı hakkındaki tam bağlam için genel bakışa bakın: «12 Portföy Optimizasyon Algoritması, Karşılaştırmalı». Ve tamamını canlı olarak şurada deneyebilirsiniz: portfolio-optimizer.marketmaker.cc.

Kaynakça

  1. López de Prado, M. (2016). Building Diversified Portfolios that Outperform Out of Sample. The Journal of Portfolio Management.
  2. López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley.
  3. Hull, J., & White, A. (1998). Incorporating Volatility Updating into the Historical Simulation Method for Value at Risk. Journal of Risk.
  4. Rockafellar, R. T., & Uryasev, S. (2000). Optimization of Conditional Value-at-Risk. Journal of Risk.
  5. RiskMetrics Group (1996). RiskMetrics — Technical Document. J.P. Morgan.
  6. Marketmaker.cc: marketmaker.cc

Atıf

@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/tr/blog/post/portfolio-pipeline-hrp-cvar},
  description = {Pipeline'ın derinlemesine incelemesi — sinyal güdümlü long/short katmanı ve Hull-White CVaR risk bütçesi düzeltmesiyle Hiyerarşik Risk Paritesi üzerine inşa edilmiş bileşik bir portföy tahsis algoritması; tam spesifikasyon ve Rust uygulaması.}
}
Sorumluluk Reddi: Bu makalede sağlanan bilgiler yalnızca eğitim ve bilgilendirme amaçlıdır ve finansal, yatırım veya ticaret tavsiyesi niteliği taşımaz. Kripto para ticareti önemli bir kayıp riski içerir.

Yazarlar

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.

Marina Zhuravleva
Marina Zhuravleva

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.

Kirill Kiselev
Kirill Kiselev

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.

Newsletter

Piyasanın Önünde Olun

Özel yapay zeka ticaret içgörüleri, piyasa analizi ve platform güncellemeleri için bültenimize abone olun.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.