我们的内部算法揭秘:HRP + 多空 + 基于Hull-White的CVaR
在我们的概述文章《12种投资组合优化算法比较》中,我们并排比较了十几种配置方法。其中十一种是教科书经典算法。第十二种,Pipeline,是我们自己的算法——在那篇文章中它只占了一个要点。本文将深入探讨:它内部是什么,每个公式的来源,以及如何将规范转化为Rust代码。
Pipeline并没有发明一种新的计算权重的方法。它采用了最稳健的已知方法——分层风险平价(HRP)——并将其封装在实际交易账户所需、而普通HRP所缺乏的两个层中:方向(来自策略信号的多空)和硬性风险预算(根据当前波动率状态调整的CVaR)。这形成了四个阶段。
四个阶段
- I — 每种资产的对数收益率。
- II — HRP的基础权重。
- III — 来自代理信号的多空拆分,风险份额由置信度设定。
- IV — 带有Hull-White波动率的CVaR修正;多余的风险转为现金。
让我们按顺序逐一介绍。
阶段I. 对数收益率
一切都始于从价格到对数收益率的转换:
其中是资产,是时间步长。对数收益率随时间累加,并且比简单的百分比变化更对称——这是任何协方差计算的标准输入。
阶段II. HRP作为基础
HRP由Marcos López de Prado于2016年提出,它避开了均值-方差优化(Mean-Variance Optimization)的核心弊病——对病态协方差矩阵求逆。它根本不求逆。相反,它处理的是相关性的结构。
协方差和相关性
从收益率中,我们构建协方差矩阵并将其标准化为相关矩阵:
距离矩阵
我们将相关性转化为距离度量,使得强相关的资产“紧密相连”:
越接近1,则越接近0——资产共享一个聚类的可能性越大。
树状图和叶序
从距离矩阵中,我们通过平均链接法构建聚类层次结构,并读取叶序 ——一个资产的排列,其中相似的资产相邻。
可选步骤:最佳聚类数量可以通过轮廓系数 来选择,其中是聚类内的平均距离,是到最近邻聚类的平均距离。基本过程不需要它——递归二分法已经尊重了层次结构。
准对角化
我们通过置换的行和列,将大值聚集在对角线上:
递归二分法
然后递归自上而下运行。在每一步中,一个聚类被分成两半和,资本在两半之间分配,与它们的方差成反比:
一个聚类的方差在其协方差子块上计算为。下降持续进行,直到每个节点只包含一个资产。权重是只做多、非负的,总和为1.0。
在我们的实现中,这是函数hrp_from_cov(cov) -> Vec<f64>:相关性 → 距离 → 平均链接 → 叶序 → 准对角化 → 递归二分法。Pipeline将其作为基础调用——它也是无信号情况下的公共optimize()函数。
阶段III. 多空叠加
普通的HRP是一个“只买入”的投资组合。但策略通常不仅说明多少,还说明方向。阶段III从代理获取每资产信号(Long/Short),并构建两个子投资组合。
- 资产根据信号分为多头和空头篮子。
- 在每个篮子内部,权重用相同的HRP(在这些资产的协方差子块上)计算,每个篮子总和为1。
- 如果代理还发出置信度 ,则两侧之间的风险份额由总置信度设定:
如果没有置信度,份额将回落到每个篮子中的资产数量。最终的带符号权重对于多头是,对于空头是,之后整个总敞口被标准化为1。
关于代码的诚实说明。 原始规范包含修正因子, ——但它也用“我们是否需要这一步?”标记了它们。实现中没有应用它们:两边直接通过风险份额组合,这使得总敞口恰好为1,并且没有产生隐藏杠杆。这是对规范的有意简化,而不是疏忽。
阶段IV. 带有Hull-White调整的CVaR
HRP在结构上平衡风险,但对以货币计的绝对风险水平一无所知。最后阶段对尾部风险设置了硬性上限——并使其对市场状态的变化敏感。
投资组合收益和EWMA波动率
首先,我们将权重合并为投资组合收益,并用EWMA估计条件波动率:
其中(经典的RiskMetrics值)。EWMA给出的是“今天的”波动率,而不是所有历史的平均值。
Hull-White重标度
关键思想:过去的收益不能照单全收——它们发生在不同的波动率下。Hull-White方法将每个过去的收益重标度到当前水平:
平静的月份被“拉伸”,动荡的月份被“压缩”,分布被带入当前状态。
VaR和CVaR
在重标度分布上,我们取损失分位数和尾部的平均损失:
CVaR(又称预期短缺)回答的不是“一个典型的糟糕日子有多糟糕”,而是“在最糟糕的百分比中平均有多糟糕”——因此它看到了尾部的厚度,而不仅仅是它的边缘。
风险预算和现金
如果CVaR超过可接受的阈值,每个风险头寸都会按单一因子缩小,释放的资本转为现金:
因此,当尾部风险增加时,投资组合会自行去风险,当风险平静下来时,它会重新进入市场。
从规范到代码
整个算法存在于一个Rust crate中,portfolio-pipeline,并遵循工作区的统一契约:
pub fn optimize(prices: &[Vec<f64>]) -> Vec<f64>
这是只做多投影(阶段I、II、IV,无信号)——与另外十一种算法完全相同的prices -> weights接口,因此Pipeline可以替代其中任何一种。包含所有阶段的完整版本是一个单独的函数:
pub fn run(
prices: &[Vec<f64>],
signals: Option<&[Side]>, // 每资产的多/空
confidence: Option<&[f64]>, // 代理置信度 → 风险份额 λ
cfg: &PipelineConfig, // CVaR / Hull-White 参数
) -> PipelineResult // 带符号权重 + 现金 + cvar + σ
叠加默认值:尾部cvar_alpha = 0.05,预算cvar_max = 0.05,EWMA ewma_lambda = 0.94,Hull-White窗口hw_window = 0(所有历史)。该实现没有外部依赖,并且是刻意防御性的:对于短历史(少于4个价格点),它返回等权重,CVaR叠加仅在≥8个收益观测值时才启动——否则无法估计尾部。
为什么选择Rust:一个确定性的代码库,用于回测和生产,没有“研究用Python,生产用其他语言”的漂移,并且足够快,可以在单个请求中通过比较后端运行所有十二种算法。
时间成本
“足够快”到底有多快?我们将HRP核心(对数收益率 → 协方差 → 平均链接 → 准对角化 → 递归权重)提取到一个独立的基准测试中,并在七种语言——C、C++、Rust、Zig、Python、Node.js 和 Bun——上运行了完全相同的数学运算,条件完全一致:Apple Silicon,单线程,每资产365个每日观测值,合成价格,资产数量从10到10,000。
先说一句复杂度,因为它决定了整体形态。教科书版本的平均链接在每次合并时都会重新扫描整个距离矩阵以寻找最近的一对——这是,在数千种资产时会成为瓶颈。本基准测试改用**最近邻链算法(Müllner 2011)——也就是SciPy的linkage(method='average')背后所采用的同一种算法。有了它,聚类不再是主导阶段:在时,它在约0.5秒的全过程中只占约15毫秒。如今成本由协方差矩阵,**主导——这是任何HRP式方法都无法回避的唯一阶段。
运行结果表明(完整的分语言表格和一条命令即可复现的脚本见项目仓库):
- 在实际投资组合中,它是免费的。 一个加密货币篮子有几十种资产,很少超过一百种。当时,即使在Node中,完整的HRP过程也只需个位数毫秒,在Rust/C中只需微秒。在每个tick上重新计算权重不是问题。
- Rust与C的性能差距约为1.0–1.3倍——处于同一数量级,两者都是编译的,一旦达到数千级便实际上不分伯仲。C在原始算术上稍快,但Rust提供了相同的可预测性,没有垃圾回收器,也没有未定义行为。
- 它可扩展到数千种资产。 在链接下,编译型语言中完整过程在时约为0.5秒,在时为几秒;即使是解释执行的Node也能在两秒内跑完。如今决定上限的是协方差阶段,而不是聚类。
实用的结论是:在我们的投资组合规模下,选择Rust并非为了“超越C”(C在这里稍快)——而是为了研究和生产使用一个确定性的代码库,没有GC暂停,并拥有多年的性能提升空间。完整的七语言基准测试,连同结果和复现脚本,在项目仓库中是开源的。
Pipeline在十二种算法中的位置
在我们对一个单一(刻意设计)篮子的比较中,Pipeline的行为类似于HRP——因为通过只做多optimize()入口点,它就是带有CVaR叠加的HRP。它的方向性机制只有在你向它输入策略信号时才会激活。这正是重点:Pipeline不是“又一个用于回测权重的优化器”,而是策略信号与真实订单之间的执行层——它接收你的买/卖指令,在每侧内部通过HRP分配资本,通过置信度平衡两侧,并将尾部风险限制在设定的预算内。
要了解完整背景——其他十一种方法是什么以及它们有何不同——请参阅概述文章《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/zh/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.