第 4 章 · 05 二次效用


文档摘要

第 4 章 · 05 二次效用 本节摘要:本节详解 的第五个目标—— 。它最大化一个二次效用函数 ,用单一参数 δ(风险厌恶系数) 平衡收益与风险:δ 越大越厌恶风险(趋向最小方差组合),δ 越小越追求收益(趋向最大收益组合)。这种「用一个连续参数扫描整条前沿」的方式比 / 的「离散目标」更优雅,且不需要预先指定目标值——你只需表达「我有多怕风险」。本节拆解效用函数的数学形式、 参数的语义、源码实现、δ 的实务取值范围,以及 Black-Litterman 模块给出的「市场隐含 δ」如何给 δ 一个客观参考。最后指出它支持 且与额外目标兼容。 内容来源:原项目源码 、 、文档 ,汉化并套用体系化模板。 学习目标 阅读完本节,你应当能够: 写出二次效用函数 。

第 4 章 · 05 二次效用

本节摘要:本节详解 EfficientFrontier 的第五个目标——max_quadratic_utility。它最大化一个二次效用函数 U = wᵀ μ - ½ δ wᵀ Σ w,用单一参数 δ(风险厌恶系数) 平衡收益与风险:δ 越大越厌恶风险(趋向最小方差组合),δ 越小越追求收益(趋向最大收益组合)。这种「用一个连续参数扫描整条前沿」的方式比 efficient_risk/efficient_return 的「离散目标」更优雅,且不需要预先指定目标值——你只需表达「我有多怕风险」。本节拆解效用函数的数学形式、risk_aversion 参数的语义、源码实现、δ 的实务取值范围,以及 Black-Litterman 模块给出的「市场隐含 δ」如何给 δ 一个客观参考。最后指出它支持 market_neutral 且与额外目标兼容。

内容来源:原项目源码 pypfopt/efficient_frontier/efficient_frontier.pypypfopt/objective_functions.py、文档 docs/MeanVariance.rst,汉化并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 写出二次效用函数 U = wᵀ μ - ½ δ wᵀ Σ w
  2. 解释 δ(风险厌恶系数) 的语义与对权重的方向性影响。
  3. max_quadratic_utility(risk_aversion=...) 求最优组合。
  4. 知道 δ 的实务取值范围与「市场隐含 δ」的参考。
  5. 理解它与额外目标兼容支持市场中性

一、效用函数的直觉

经济学里「效用」是对偏好程度的数学刻画。二次效用是金融里最常用的一种:

U(w) = wᵀ μ - ½ · δ · wᵀ Σ w
  • wᵀ μ:组合期望收益(越多越好)。
  • wᵀ Σ w:组合方差(风险,越少越好)。
  • δ:风险厌恶系数(risk aversion),衡量「方差每增加 1 单位,要扣多少效用」。
  • ½:数学惯例(让 δ 直接等于相对风险厌恶系数,与一阶条件对应)。

💡 核心心法:效用函数把「收益」与「风险」统一到一个标量里,用一个参数 δ 表达「你多怕风险」。δ 大 = 宁可少赚也不要波动;δ 小 = 只要能赚,波动无所谓。这比 efficient_risk 的「我要 20% 波动」更贴近真实偏好——很少有人能精确说出「我能承受的波动是 20.3%」,但多数人能回答「我比较保守 / 比较激进」。

二、δ 的语义与方向

δ 是个正实数,它把优化结果在「最小方差」与「最大收益」之间拉:

δ 取值 行为 极限
δ → 0 几乎忽略风险,只追收益 趋向「最大收益组合」(权重全押最高 μ 的资产)
δ = 1(默认) 中等平衡 在前沿中间某点
δ → ∞ 极度厌恶风险 趋向「全局最小方差组合」(GMV)

源码里 if risk_aversion <= 0: raise ValueError,δ 必须为正——因为负 δ 意味着「喜欢风险」,会无界增大方差,数学上发散。

三、源码逐行解析

打开 efficient_frontier.py,定位 max_quadratic_utility(源码 317-357 行):

def max_quadratic_utility(self, risk_aversion=1, market_neutral=False): if risk_aversion <= 0: raise ValueError("risk aversion coefficient must be greater than zero") update_existing_parameter = self.is_parameter_defined("risk_aversion") if update_existing_parameter: self._validate_market_neutral(market_neutral) self.update_parameter_value("risk_aversion", risk_aversion) else: self._objective = objective_functions.quadratic_utility( self._w, self.expected_returns, self.cov_matrix, risk_aversion=risk_aversion, ) for obj in self._additional_objectives: self._objective += obj self._make_weight_sum_constraint(market_neutral) return self._solve_cvxpy_opt_problem()

关键点:

  1. 正数校验:risk_aversion <= 0 抛错。
  2. 参数化重解:用 is_parameter_defined("risk_aversion") 检查是否已建过 risk_aversion 参数。若是,直接 update_parameter_value 改值重解——这让「扫不同 δ」更高效(不重建实例)。若否,首次构造完整目标。
  3. 目标:objective_functions.quadratic_utility(w, μ, Σ, risk_aversion)(详见下节)。
  4. 累加额外目标:与 min_volatility 一样,+= 到主目标——与额外目标完全兼容(对比 max_sharpe 的警告)。
  5. 权重和约束:_make_weight_sum_constraint(market_neutral),与 efficient_risk/efficient_return 一致——支持市场中性

四、quadratic_utility 目标函数

打开 objective_functions.py,定位 quadratic_utility(源码 165-195 行):

def quadratic_utility(w, expected_returns, cov_matrix, risk_aversion, negative=True): sign = -1 if negative else 1 mu = w @ expected_returns variance = cp.quad_form(w, cov_matrix, assume_PSD=True) risk_aversion_par = cp.Parameter( value=risk_aversion, name="risk_aversion", nonneg=True ) utility = mu - 0.5 * risk_aversion_par * variance return _objective_value(w, sign * utility)

关键点:

  1. negative=True(默认):返回负效用。因为 PyPortfolioOpt 的优化器是最小化框架,要「最大化效用」等价于「最小化负效用」——这是库内统一的设计(README 模块注释明确:「明显应最大化的目标(夏普、收益),函数返回负值,因最小化负值 = 最大化正值」)。
  2. mu = w @ μ:组合收益,线性项。
  3. variance = cp.quad_form(w, Σ):组合方差,二次项。
  4. risk_aversion_par:把 δ 包成 cp.Parameter(name="risk_aversion", nonneg=True)——这正是 max_quadratic_utilityis_parameter_defined 检测的那个参数,让 δ 可重解。

效用公式严格对应 μ - 0.5 × δ × variance:

U = wᵀ μ - ½ δ wᵀ Σ w

五、参数速查表

参数 默认 含义 备注
risk_aversion 1 风险厌恶系数 δ 必须 > 0
market_neutral False 是否市场中性(权重和为 0) 需负权重边界

⚠️ δ 不能 ≤ 0:源码 if risk_aversion <= 0: raise ValueError。负 δ 意味「喜欢风险」,数学上无界。

六、δ 的实务取值

δ 该取多少?这是 max_quadratic_utility 最常被问的问题。几个参考:

  1. 默认 δ=1:中等平衡的起点。
  2. δ ∈ [1, 5]:典型机构投资者的范围(偏稳健)。
  3. δ ∈ [0.5, 2]:常见于教科书示例。
  4. 市场隐含 δ(关键参考):docs/MeanVariance.rstnote 提到——Black-Litterman 模块提供了一种计算「市场隐含风险厌恶参数」的方法,在没有其他信息时给出客观估计。

💡 实务建议:先从 δ=1 起步,看权重分布是否合理;若太集中(某资产占 50%+),说明风险约束不够,调大 δ;若太分散(几乎等权),说明风险约束过强,调小 δ。也可扫 δ ∈ [0.5, 5] 看权重如何平滑变化,选一个「直觉舒服」的点。若做严肃配置,用 Black-Litterman 的市场隐含 δ(第 7 章)作为客观锚点。

七、用法示例

7.1 默认 δ=1

ef = EfficientFrontier(mu, S) ef.max_quadratic_utility() ef.clean_weights() ef.portfolio_performance(verbose=True)

7.2 调高 δ(更保守)

ef = EfficientFrontier(mu, S) ef.max_quadratic_utility(risk_aversion=5) ef.portfolio_performance(verbose=True)

波动率会比 δ=1 时更低,收益也相应降低。

7.3 市场中性 + 二次效用

ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1)) ef.max_quadratic_utility(risk_aversion=2, market_neutral=True)

7.4 扫 δ 画「效用前沿」

deltas = [0.5, 1, 2, 3, 5, 10] curve = [] for d in deltas: ef = EfficientFrontier(mu, S) ef.max_quadratic_utility(risk_aversion=d) ret, vol, _ = ef.portfolio_performance() curve.append((vol, ret, d)) # 画 (vol, ret),每点标 δ——这条曲线就是有效前沿的另一种参数化

注意:扫不同 δ 时,如果用 update_parameter_value 重解(而非重建实例),需要保证 market_neutral 不变——源码里 _validate_market_neutral 会检查,改了 market_neutral 必须重建。

7.5 与额外目标兼容

from pypfopt import objective_functions ef = EfficientFrontier(mu, S) ef.add_objective(objective_functions.L2_reg, gamma=1) ef.max_quadratic_utility(risk_aversion=2)

无 max_sharpe 的变量替换问题,L2 正则正常工作。

八、与其他目标的对比

维度 max_sharpe min_volatility efficient_risk/return max_quadratic_utility
需要 μ
需要预设目标 (目标值) (只给 δ)
参数连续性 离散扫目标 δ 连续扫
与额外目标兼容
支持市场中性
直觉 风险调整收益 最保守 精确目标 偏好强度

💡 何时用 quadratic_utility:如果你不想精确指定「目标波动 20%」或「目标收益 25%」,而是想表达「我比较保守/激进」的模糊偏好,max_quadratic_utility 是最自然的选择。δ 是一个连续参数,扫它就能描出整条前沿,且每次结果都是前沿上的有效点(不像 max_sharpe 只给一个点)。

本节要点回顾

  1. 效用公式:U = wᵀ μ - ½ δ wᵀ Σ w,δ 平衡收益与风险。
  2. δ 语义:> 0 必须;小→激进(追收益),大→保守(趋 GMV)。
  3. 源码:目标 quadratic_utility(negative=True 返负效用),与额外目标兼容、支持市场中性。
  4. 参数化重解:δ 包成 cp.Parameter,is_parameter_defined + update_parameter_value 高效扫不同 δ。
  5. δ 取值:默认 1;典型 [1,5];客观锚点用 Black-Litterman 市场隐含 δ(第 7 章)。
  6. 优势:不需预设目标、δ 连续扫前沿、与额外目标兼容、支持市场中性——综合最灵活的目标。

至此,均值-方差优化的五个目标讲完。下一章我们进入进阶——加约束、做市场中性、用 L2 正则、自定义目标,把标准模型推向工程实战。


发布者: 作者: 灏天文库 转发
评论区 (0)
U