找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

160

积分

0

好友

19

主题
发表于 昨天 02:09 | 查看: 3| 回复: 0

自1952年Harry Markowitz提出现代投资组合理论以来,均值-方差框架一直在投资组合构建中占据主导地位。然而,传统方差作为风险度量存在明显缺陷:它同等惩罚收益和损失,忽视极端尾部事件,且假设收益呈正态分布。本文将介绍如何使用Python实现更先进的风险度量方法,包括半方差(Semivariance)、条件风险价值(CVaR)和最大回撤(Maximum Drawdown),帮助构建能够有效抵御灾难性损失的投资组合。

传统方差的局限性

传统均值-方差优化存在四个核心问题:

  1. 对称性问题:方差同等对待上涨和下跌,10%的下跌和10%的上涨在计算中权重相同,这与投资者的实际风险感受不符

  2. 聚焦中间值:方差衡量的是围绕均值的离散程度,而投资者真正关心的是可能抹去多年收益的尾部风险

  3. 分布假设:方差假设收益呈正态分布,但真实市场收益具有肥尾特征和偏斜性

  4. 路径无关性:方差不关心收益的顺序,但稳步下跌和突然崩盘给投资者的体验截然不同

方法一:下行风险组合优化

下偏矩(Lower Partial Moment,LPM)是下行风险的广义形式,其数学定义为:

LPM_α = E[(τ - R)₊^α]

其中τ是灾难阈值,α是风险态度参数。当α=2时,即为半方差(Semivariance)。

import cvxpy as cp
import numpy as np

def optimize_semivariance_portfolio(returns, tau=0, alpha=2, lambda_risk=1.0):
    """
    使用下行风险度量优化投资组合

    参数说明:
    returns: 历史收益率矩阵,形状为 (T, N),T为时间周期数,N为资产数量
    tau: 灾难阈值(最低可接受收益率)
    alpha: 风险态度参数(1=线性,2=二次,3=三次)
    lambda_risk: 风险厌恶系数

    返回:
    最优投资组合权重
    """
    T, N = returns.shape
    mu = returns.mean(axis=0)  # 计算预期收益率

    # 定义决策变量
    w = cp.Variable(N)  # 投资组合权重
    s = cp.Variable(T)  # 下行偏差的辅助变量

    # 目标函数:最大化收益 - λ * 下行风险
    expected_return = mu @ w
    downside_risk = (1/T) * cp.sum(cp.power(s, alpha))
    objective = cp.Maximize(expected_return - lambda_risk * downside_risk)

    # 约束条件
    constraints = [
        cp.sum(w) == 1,           # 满仓约束
        w >= 0,                   # 仅做多约束
        s >= 0,                   # 非负偏差
        s >= tau - returns @ w    # 捕捉下行偏差
    ]

    # 求解优化问题
    problem = cp.Problem(objective, constraints)
    problem.solve(solver=cp.ECOS)

    return w.value

# 示例:模拟252个交易日、10种资产的收益率数据
np.random.seed(42)
returns = np.random.randn(252, 10) * 0.01 + 0.0003

# 使用不同的α值进行优化
weights_linear = optimize_semivariance_portfolio(returns, alpha=1)  # 线性惩罚
weights_semi = optimize_semivariance_portfolio(returns, alpha=2)    # 半方差
weights_cubic = optimize_semivariance_portfolio(returns, alpha=3)   # 三次惩罚

print("半方差优化权重:")
print(np.round(weights_semi, 4))

方法二:尾部风险组合优化(CVaR)

条件风险价值(CVaR)也称为预期损失(Expected Shortfall),它衡量的是超过VaR阈值后的平均损失。CVaR的优势在于它是凸函数,可以通过优化算法高效求解。

def optimize_cvar_portfolio(returns, alpha=0.95, lambda_risk=1.0):
    """
    使用条件风险价值(CVaR)优化投资组合

    CVaR表示在最差的(1-α)%情况下的平均损失
    例如α=0.95时,我们最小化最差5%情景下的平均损失

    参数说明:
    returns: 历史收益率矩阵,形状为 (T, N)
    alpha: 置信水平(常用0.90、0.95或0.99)
    lambda_risk: 风险厌恶系数

    返回:
    最优权重、VaR值、CVaR值
    """
    T, N = returns.shape
    mu = returns.mean(axis=0)

    # 决策变量
    w = cp.Variable(N)      # 投资组合权重
    tau = cp.Variable()     # VaR阈值
    u = cp.Variable(T)      # 超额损失变量

    # CVaR目标函数
    expected_return = mu @ w
    cvar = tau + (1/(1-alpha)) * (1/T) * cp.sum(u)
    objective = cp.Maximize(expected_return - lambda_risk * cvar)

    # 约束条件
    constraints = [
        cp.sum(w) == 1,              # 预算约束
        w >= 0,                      # 仅做多
        u >= 0,                      # 非负超额
        u >= -returns @ w - tau      # 捕捉超过VaR的损失
    ]

    # 求解
    problem = cp.Problem(objective, constraints)
    problem.solve(solver=cp.ECOS)

    # 提取结果
    optimal_w = w.value
    optimal_tau = tau.value
    optimal_cvar = tau.value + (1/(1-alpha)) * (1/T) * np.sum(u.value)

    return optimal_w, optimal_tau, optimal_cvar

# 示例:比较不同置信水平
np.random.seed(42)
returns = np.random.randn(252, 20) * 0.015 + 0.0004

w_90, var_90, cvar_90 = optimize_cvar_portfolio(returns, alpha=0.90)
w_95, var_95, cvar_95 = optimize_cvar_portfolio(returns, alpha=0.95)
w_99, var_99, cvar_99 = optimize_cvar_portfolio(returns, alpha=0.99)

print(f"CVaR 90%: {cvar_90:.4f}")
print(f"CVaR 95%: {cvar_95:.4f}")  # 最常用的置信水平
print(f"CVaR 99%: {cvar_99:.4f}")

方法三:回撤风险组合优化

回撤(Drawdown)捕捉的是投资者真正经历的痛苦:看着财富从峰值下跌。一个关键的心理洞察是:50%的损失需要100%的收益才能恢复。

def optimize_cdar_portfolio(returns, alpha=0.95, lambda_risk=1.0):
    """
    最小化条件回撤风险(CDaR)

    CDaR是最差回撤的平均值,比最大回撤更稳定
    因为它考虑多个糟糕情景,而不仅仅是单一最差情况

    参数说明:
    returns: 历史收益率矩阵
    alpha: 置信水平
    lambda_risk: 风险厌恶系数
    """
    T, N = returns.shape
    mu = returns.mean(axis=0)
    cum_returns = np.cumsum(returns, axis=0)  # 计算累计收益

    # 决策变量
    w = cp.Variable(N)       # 投资组合权重
    u = cp.Variable(T)       # 历史最高水位标记
    tau = cp.Variable()      # 回撤VaR
    z = cp.Variable(T)       # 超额回撤

    # CDaR目标函数
    expected_return = mu @ w
    cdar = tau + (1/(1-alpha)) * (1/T) * cp.sum(z)
    objective = cp.Maximize(expected_return - lambda_risk * cdar)

    # 约束条件
    constraints = [
        cp.sum(w) == 1,
        w >= 0,
        z >= 0,
    ]

    # 回撤计算约束
    for t in range(T):
        drawdown_t = u[t] - cum_returns[t, :] @ w
        constraints.append(u[t] >= cum_returns[t, :] @ w)
        if t > 0:
            constraints.append(u[t] >= u[t-1])  # 单调递增
        constraints.append(z[t] >= drawdown_t - tau)

    problem = cp.Problem(objective, constraints)
    problem.solve(solver=cp.ECOS)

    return w.value, tau.value

# 示例
np.random.seed(42)
returns = np.random.randn(252, 15) * 0.012 + 0.0003

w_cdar, dd_var = optimize_cdar_portfolio(returns, alpha=0.95, lambda_risk=5.0)
print(f"CDaR 95%组合的回撤VaR: {dd_var:.2%}")
print("优化权重:")
print(np.round(w_cdar, 4))

实测对比与选择建议

根据对S&P 500成分股的回测结果(2015-2020年,每月再平衡,1年回望期),不同风险度量的表现如下:

  • 半方差(α=2)组合表现最佳,夏普比率达到1.24,同时最大回撤比传统均值-方差组合降低了近10%
  • 熵风险价值(EVaR)在相同置信水平下持续优于CVaR
  • 极端度量如最大回撤组合表现较差,因为它们由单个数据点决定,导致不稳定

对于量化交易实践,建议采用以下策略:

  1. 将半方差作为均值-方差的默认升级方案
  2. 在核心配置之上叠加CVaR或EVaR作为尾部风险覆盖层
  3. 即使回撤不在优化目标中,也应将其作为健康指标进行监控

选择风险度量时可参考以下决策流程:

  • 如果收益分布对称,使用均值-方差即可
  • 如果主要担心尾部风险,选择CVaR或EVaR
  • 如果需要每日监控投资组合,选择CDaR
  • 其他情况下,半方差是最稳妥的选择

总结

均值-方差优化仍是有用的基准方法,但在肥尾、结构性断裂和杠杆约束主导的市场中,它已不再足够。替代风险度量让你能够表达真正关心的内容:避免深度水下期、在尾部事件中存活、以及提供投资者能够坚持的更平滑的权益曲线。

本文介绍的三类方法——下行风险(半方差)、尾部风险(CVaR/EVaR)和路径相关风险(回撤)——都可以通过凸优化高效求解。如果你已经熟悉凸优化,现在就拥有了替换方差作为默认风险度量的所有要素,将风险管理从事后补救变成首要的设计选择。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-1 14:12 , Processed in 0.054471 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表