组合优化

EigenLedger 的四种优化器:它们到底在求什么

optimizer"EF" 改成 "HRP",你会得到完全不同的权重。原因不是「算法好坏」,而是它们优化的是不同的目标函数,且默认的收益与风险估计方法也不一样。

本页按源码逐行核对四种优化器的实际调用、默认参数与副作用,并给出「什么场景选哪一个」的对照表。

历史复权价
收益 / 协方差估计
目标函数
权重约束
求解器
权重表
示意图:四种优化器共享同一条输入链路,分叉点在「目标函数」。
EigenLedger · 对照表

EigenLedger 的四种优化器有什么差别?

下表的「求解目标」与「默认估计方法」均来自源码,不是文档转述。

optimizer 取值求解目标默认收益估计默认风险估计适用场景注意点
"EF"最大夏普(性价比最高)mean_historical_returnsample_cov希望按历史性价比配权,标的预期收益差异明显用历史均值当预期收益,本质是把过去涨幅外推
"MEANVAR"在年化波动不超过 max_vol 的前提下求最优capm_returnledoit_wolf有明确波动预算(如产品风控线)max_vol 默认 0.15,与报告里的年化波动口径不同
"HRP"层次风险平价:按相关性结构分配风险不使用不使用(直接从价格算)标的多、相关性复杂,不想猜预期收益天然更分散,但不追求收益最优,也不接受 min/max 约束
"MINVAR"最小化组合波动capm_returnledoit_wolf把回撤与波动放在第一位低波动通常伴随低收益;四个优化器中唯一没有缺失值填充
自定义函数你的逻辑自行决定自行决定接入内部打分、等风险贡献、外部模型返回值必须是与 portfolio 顺序一致的权重列表

四种优化器都在构造 Engine 时就完成求解,也就是 Engine(..., optimizer="EF") 这一行就会联网取历史价格。断网或标的缺失会让构造直接失败,报错点不在分析函数里。

EigenLedger · 内部调用

EigenLedger 的优化器实际调用了 PyPortfolioOpt 的哪个方法?

理解这一层,你才能把报错信息对应到具体环节。

优化器构造与目标函数约束与正则报错时先查什么
EFEfficientFrontier(mu, S)ef.max_sharpe()L2 正则 gamma=diversification;可选权重上下限预期收益是否有足够差异(全为负时最大夏普可能无解)
MEANVAREfficientFrontier(mu, S)ef.efficient_risk(max_vol)同上max_vol 是否低于给定标的集合的可达最小波动
HRPHRPOpt(returns_from_prices(prices))optimize()无 L2 正则、无权重上下限相关性矩阵是否可逆(标的高度重复时容易出问题)
MINVAREfficientFrontier(mu, S)ef.min_volatility()L2 正则与权重上下限均生效价格矩阵是否含 NaN(该分支不做填充)
自定义函数直接调用你传入的函数并取其返回值由你的函数内部处理返回值长度与顺序是否与组合一致
min_weights / max_weights 会被转成向量约束 x >= min_weights / x <= max_weights。约束过紧(例如所有标的都必须 ≥0.3 而标的只有 3 个)会导致求解器无解,报错来自底层 cvxpy,信息里通常不会出现「EigenLedger」字样,排查时容易迷失。
EigenLedger · 参数影响

换 EigenLedger 的估计方法,权重会差多少?

expected_returnsrisk_model 只接受白名单取值,传错会直接断言失败。

参数可选值直觉含义什么时候换
expected_returnsmean_historical_return用历史平均收益作为预期标的差异明显、区间较长(EF 默认)
ema_historical_return近期收益权重更高想弱化远期数据影响
capm_return用市场 Beta 推导预期收益认为个股跑不赢自身风险敞口(MEANVAR/MINVAR 默认)
risk_modelsample_cov样本协方差,最直接样本充足、标的少(EF 默认)
semicovariance只统计下行波动更在意亏损方向的波动
exp_cov近期样本权重更大市场结构近期发生变化
ledoit_wolf 系列 / oracle_approximating收缩估计,缓解样本噪声标的数量接近或超过样本长度时(MEANVAR/MINVAR 默认)
其它参数作用范围调大的效果副作用
diversification(默认 1)EF / MEANVAR / MINVAR权重更平均,集中度下降偏离原始最优目标,夏普可能下降
max_vol(默认 0.15)仅 MEANVAR允许更高波动,收益目标更激进设得过低会直接无解
min_weights / max_weightsEF / MEANVAR / MINVAR限制单标的下限或上限约束叠加后可行域可能为空
回测区间全部区间越长越平滑区间选择本身会影响最优权重,这就是过拟合的来源
risk_manager仅分析阶段生效按阈值提前截断收益序列截断后区间变短,年化与夏普都被改写
标的数量全部可分散的维度更多标的数接近样本长度时协方差估计不可靠
EigenLedger · 对比流程

怎么证明 EigenLedger 的「优化真的有用」?

库提供了 optimize_portfolio(),会用同一区间画出优化前后的净值曲线。

  1. 确认引擎里有优化器

    没设 optimizer 就调用,会直接抛 Exception: You didn't define any optimizer in your portfolio!

  2. 先算等权基准

    函数内部先按 1/n 等权算一条「未优化」的净值曲线,作为对比基准。

  3. 再按优化权重算第二条曲线

    零权重的标的会从组合中剔除后再计算,因此两条曲线的标的集合可能不同。

  4. 看两条曲线的差

    输出图为蓝色「未优化」与红色「已优化」。差异明显不代表优化更好——要看同期的回撤与波动是否也一起变差。

你会看到的现象含义需不需要处理建议做法
优化后曲线明显高于等权该区间内优化权重确实更优不代表未来同样成立换 2 段以上区间重跑,看结论是否稳定
优化权重集中在一两只标的目标函数把权重推向历史最优解需要处理max_weights 或提高 diversification
优化后波动更大最大夏普不等于最小风险取决于你的目标风险优先就换 MINVARMEANVAR
权重为 0 的标的消失源码会剔除零权重标的正常现象记录被剔除的标的,作为「模型不看好」的证据
两条曲线几乎重合标的本身相关性极高不必处理换标的集合再试,或直接接受等权
EigenLedger · 陷阱

哪三个细节会让 EigenLedger 权重失去意义?

都写在源码里,但不会报错。

缺失价格被填成 1

EFMEANVARHRP 三个分支会把缺失价格填充为 1(源码注释解释为「公司还没上市时不能填 0」)。若区间起点早于某标的上市日,该标的会先出现一段人为的低价区,收益与协方差都被污染。

权重会被取整

求解后统一走 clean_weights(),权重被截断到较小位数,且零权重会被删除。因此权重之和不严格等于 1,直接拿去做资金分配前需要重新归一化。

MinVar 不做填充

MINVAR 分支没有缺失值填充。同样是含缺口的数据,换一个优化器就可能从「结果偏移」变成「直接报错」,四个优化器彼此不等价。

把优化权重直接当成「目标持仓」是常见的误用。它是在给定区间与给定估计方法下的数学解,换区间、换估计方法、换标的都会变。合理的用法是把它当作一个可讨论的起点,而非结论。
EigenLedger · 选型

什么场景选 EigenLedger 的哪个优化器?

按「你的约束条件」来选,而不是按「哪个听起来高级」来选。

你的约束推荐选项理由下一步该验证什么
有明确的波动上限(风控线)MEANVAR + max_vol目标函数直接就是「不超过波动上限的最优解」用报告里的年化波动复核,注意两套口径不同
最怕回撤,收益次要MINVAR直接最小化波动,通常也压低回撤检查收益是否被压到不可接受
标的多、相关性结构复杂HRP不猜预期收益,按相关性聚类分配风险看权重是否过于平均、是否有被完全忽略的标的
想让权重差异体现预期收益差EF最大夏普会把权重推向高性价比标的换两段区间验证权重稳定性
已有内部打分模型自定义函数库允许直接传入返回权重列表的函数核对顺序与长度,并确认零权重处理符合预期
不想做任何假设不用优化器(等权)等权是难以被打败的基线,也便于解释把等权结果作为对照写进报告
对照维度EigenLedger 路线本机技能路线建议
组合优化四种优化器可复现、参数明确quant-analyst 技能声明支持组合优化两套结果交叉验证后再用
权重解释需自己读源码理解目标函数可用自然语言追问理由教学或沟通场景选后者
批量试参数脚本化,可循环遍历偏交互式批量实验选前者
结果留档脚本 + 版本即可复现对话记录留痕正式研究选前者
权重集中度披露可打印 clean_weights 结果取决于技能输出形态对外材料必须给出前两大权重占比
约束条件表达min_weights / max_weights 显式声明用自然语言描述约束约束复杂时选前者,并注意可行性

披露:本机技能目录已核验(29 个技能),EigenLedger 与 EasyClaw 无已证实集成;两边的组合优化实现与输出口径不同,不可互相替代。

FAQ

关于组合优化的常见问题

四个优化器能同时用吗?

不能。optimizer 是单值参数,只能取一个值;想对比就得跑四次,各自构造一个 Engine。注意 Engine 构造期就会求解并取数,四次对比意味着四次独立下载。

为什么优化后有些标的权重是 0?

目标函数在约束下求得的最优解把权重压到了 0,随后源码会把零权重标的从组合列表中删除。如果这种集中度不可接受,可叠加 min_weights 或提高 diversification(L2 正则强度),以官方实现为准。

max_vol=0.15 是年化波动吗?

它是交给 PyPortfolioOpt 的 efficient_risk 的目标波动水平,与报告里 QuantStats 计算的年化波动不是同一套实现。两者数值接近但不保证相等,跨口径对比前请先各算一遍,以官方实现为准。

为什么换个时间段权重就完全变了?

因为预期收益与协方差都由区间内数据估计,区间变了输入就变了。这也是均值方差类优化的共识问题:样本噪声被当作真实信号。缓解手段是收缩估计(ledoit_wolf)、加权重约束、或改用不依赖预期收益的 HRP

自定义优化器函数要注意什么?

函数必须返回与标的顺序一一对应的权重列表;源码会把返回值直接当作权重使用,因此长度不符会在后续取数阶段报错,顺序不对则不会报错但结果完全错误。建议在函数内部加断言,以官方实现为准。

优化一定会提高收益吗?

不一定。优化的是目标函数,不是未来收益。最大夏普通常提高历史风险调整收益,最小波动优化通常会降低收益水平;两者都只对历史区间成立。把优化结果当作「未来更赚钱」的证据是典型误读。

可以拿优化权重直接下单吗?

不建议。库不处理交易成本、最小交易单位、涨跌停与流动性,且权重经过取整且和为 1 的约束并不严格。实际下单需要自己再做一轮约束转换与风控校验,本页内容仅供研究与技术评估。

权重定了,下一个难题是「调仓怎么排」

周期字符串和自定义日期表是两种完全不同的写法,还有一种写法在源码里会直接报错。