Skip to content

风险管理量化方法

引言

在量化投资中,有一句被反复引用的名言:"投资的第一条规则是不要亏钱,第二条规则是记住第一条。"——沃伦-巴菲特。虽然完全不亏钱在投资中是不可能的,但通过科学的风险管理方法,我们可以将亏损控制在可承受的范围内,确保在市场极端情况下仍能生存。

风险管理不是预测市场会怎样,而是回答"如果最坏的情况发生了,我能承受吗?"。本文将介绍量化风险管理中最核心的方法和工具,包括 VaR、波动率控制、最大回撤控制、风险预算以及黑天鹅应对策略,帮助你在追求收益的同时牢牢守住风险底线。


一、在险价值(Value at Risk,VaR)

1.1 VaR 的定义

VaR(Value at Risk,在险价值) 是衡量投资组合在一定置信水平和一定时间区间内可能遭受的最大损失的统计指标。

简单说,VaR 回答的问题是:"在正常的市场条件下,我有 X% 的把握在接下来的 N 天内亏损不会超过 Y 元。"

例如:"95% 的 VaR 为 10 万元"意味着:在未来一天内,有 95% 的概率亏损不会超过 10 万元,或者说亏损超过 10 万元的概率只有 5%。

1.2 VaR 的三种计算方法

方法一:历史模拟法(Historical Simulation)

最直观的方法,直接使用历史收益率数据来估算 VaR:

python
import numpy as np
import pandas as pd

def historical_var(returns, confidence_level=0.95, portfolio_value=1000000):
    """
    历史模拟法计算 VaR

    参数:
        returns: pd.Series, 日收益率序列
        confidence_level: float, 置信水平(如0.95表示95%)
        portfolio_value: float, 组合市值

    返回:
        float: VaR 值(正数,表示可能的最大亏损)
    """
    # 找到对应置信水平的分位数
    var_percentile = 100 * (1 - confidence_level)
    var_return = np.percentile(returns, var_percentile)

    # 转换为金额
    var_amount = abs(var_return) * portfolio_value

    print(f"历史模拟法 VaR({confidence_level:.0%}置信水平):")
    print(f"  日VaR收益率: {var_return:.4%}")
    print(f"  日VaR金额: {var_amount:,.0f} 元")

    return var_amount

# 示例
np.random.seed(42)
daily_returns = pd.Series(np.random.normal(0.0005, 0.015, 1000))
historical_var(daily_returns, confidence_level=0.95, portfolio_value=1000000)

优点:不需要假设收益率分布,简单直观。 缺点:完全依赖历史数据,无法捕捉历史中未出现过的极端情况。

方法二:参数法(方差-协方差法)

假设收益率服从正态分布,利用均值和标准差来估算 VaR:

python
from scipy import stats

def parametric_var(returns, confidence_level=0.95, portfolio_value=1000000):
    """
    参数法计算 VaR(假设正态分布)

    参数:
        returns: pd.Series, 日收益率序列
        confidence_level: float, 置信水平
        portfolio_value: float, 组合市值

    返回:
        float: VaR 值
    """
    mu = returns.mean()
    sigma = returns.std()

    # 正态分布的分位数
    z_score = stats.norm.ppf(1 - confidence_level)

    # VaR
    var_return = mu + z_score * sigma
    var_amount = abs(var_return) * portfolio_value

    print(f"参数法 VaR({confidence_level:.0%}置信水平):")
    print(f"  日均收益率: {mu:.4%}")
    print(f"  日波动率: {sigma:.4%}")
    print(f"  Z分数: {z_score:.2f}")
    print(f"  日VaR金额: {var_amount:,.0f} 元")

    return var_amount

# 不同置信水平的 Z 分数参考
# 90% → -1.28
# 95% → -1.645
# 99% → -2.326

优点:计算简单,便于解析求解。 缺点:收益率通常不服从正态分布,往往具有"厚尾"特征(极端事件发生的概率高于正态分布预测)。

方法三:蒙特卡洛模拟法

通过模拟大量可能的未来场景来估算 VaR:

python
def monte_carlo_var(returns, confidence_level=0.95, portfolio_value=1000000,
                     n_simulations=100000, holding_days=1):
    """
    蒙特卡洛模拟法计算 VaR

    参数:
        returns: pd.Series, 历史日收益率序列
        confidence_level: float, 置信水平
        portfolio_value: float, 组合市值
        n_simulations: int, 模拟次数
        holding_days: int, 持有天数

    返回:
        float: VaR 值
    """
    mu = returns.mean()
    sigma = returns.std()

    # 模拟未来收益率
    simulated_returns = np.random.normal(
        mu * holding_days,
        sigma * np.sqrt(holding_days),
        n_simulations
    )

    # 计算 VaR
    var_return = np.percentile(simulated_returns,
                                100 * (1 - confidence_level))
    var_amount = abs(var_return) * portfolio_value

    print(f"蒙特卡洛 VaR({confidence_level:.0%}置信水平, "
          f"{holding_days}天持有期):")
    print(f"  模拟次数: {n_simulations}")
    print(f"  VaR收益率: {var_return:.4%}")
    print(f"  VaR金额: {var_amount:,.0f} 元")

    return var_amount

1.3 VaR 的局限性

VaR 虽然是广泛使用的风险指标,但有几个重要局限:

  • 不告诉你在 VaR 之外会亏多少:95% VaR 为 10 万,但剩下 5% 的情况下可能亏 20 万、50 万甚至更多,VaR 无法告诉你。
  • 不满足次可加性:两个组合各自的 VaR 之和,可能小于合并后的 VaR。这在数学上意味着"分散投资反而增加风险",显然不合理。
  • 依赖历史数据:无论用哪种方法,VaR 都在一定程度上依赖历史数据,而"过去不代表未来"。

1.4 条件 VaR(CVaR / ES)

为了弥补 VaR 的不足,业界引入了 CVaR(Conditional VaR),也叫 ES(Expected Shortfall,预期亏损)。它衡量的是在损失超过 VaR 的情况下的平均亏损

python
def conditional_var(returns, confidence_level=0.95, portfolio_value=1000000):
    """
    计算 CVaR(条件 VaR / Expected Shortfall)

    参数:
        returns: pd.Series, 日收益率序列
        confidence_level: float, 置信水平
        portfolio_value: float, 组合市值

    返回:
        float: CVaR 值
    """
    var_percentile = 100 * (1 - confidence_level)
    var_return = np.percentile(returns, var_percentile)

    # 取所有超过 VaR 的损失(即比 VaR 更差的收益率)
    tail_returns = returns[returns <= var_return]

    # 计算尾部损失的平均值
    cvar_return = tail_returns.mean()
    cvar_amount = abs(cvar_return) * portfolio_value

    print(f"CVaR({confidence_level:.0%}置信水平):")
    print(f"  VaR: {abs(var_return):.4%}")
    print(f"  CVaR: {abs(cvar_return):.4%}")
    print(f"  CVaR / VaR: {abs(cvar_return) / abs(var_return):.2f}x")
    print(f"  CVaR金额: {cvar_amount:,.0f} 元")

    return cvar_amount

# 示例
conditional_var(daily_returns, confidence_level=0.95, portfolio_value=1000000)

CVaR 始终大于等于 VaR,它告诉我们:当极端情况发生时,平均会亏多少。 CVaR 比 VaR 更保守、也更完整地描述了尾部风险。


二、波动率控制

2.1 为什么关注波动率

波动率(Volatility)是衡量收益率不确定性的最基本指标。高波动率意味着收益的不确定性大,价格可能在短期内剧烈波动,增加投资者的心理压力和强制平仓风险。

波动率控制的核心思想是:通过动态调整仓位,使组合的波动率保持在目标水平。

2.2 波动率估算方法

python
import numpy as np
import pandas as pd

def realized_volatility(returns, window=20):
    """
    计算滚动已实现波动率(年化)

    参数:
        returns: pd.Series, 日收益率
        window: int, 滚动窗口(交易日数)

    返回:
        pd.Series: 年化波动率序列
    """
    rolling_vol = returns.rolling(window).std() * np.sqrt(252)
    return rolling_vol

def ewma_volatility(returns, span=60):
    """
    指数加权移动平均波动率(年化)

    EWMA 对近期数据赋予更高权重,对波动率变化的响应更快

    参数:
        returns: pd.Series, 日收益率
        span: int, 衰减因子对应的跨度

    返回:
        pd.Series: 年化 EWMA 波动率序列
    """
    ewma_std = returns.ewm(span=span).std() * np.sqrt(252)
    return ewma_std

def parkinson_volatility(high, low, window=20):
    """
    Parkinson 波动率估计(使用日内最高价和最低价)

    相比收盘价计算的波动率,利用了更多价格信息

    参数:
        high: pd.Series, 日最高价
        low: pd.Series, 日最低价
        window: int, 滚动窗口

    返回:
        pd.Series: 年化 Parkinson 波动率
    """
    hl_ratio = np.log(high / low)
    factor = 1 / (4 * np.log(2))
    parkinson_var = factor * (hl_ratio ** 2)
    rolling_var = parkinson_var.rolling(window).mean()
    annualized = np.sqrt(rolling_var * 252)
    return annualized

2.3 波动率调仓策略

波动率调仓的核心公式:

目标仓位 = 目标波动率 / 预测波动率 × 基础仓位
python
def volatility_targeting_position(predicted_vol, target_vol=0.15,
                                    max_position=1.5, min_position=0.1):
    """
    基于波动率目标的仓位调整

    参数:
        predicted_vol: float, 预测的年化波动率
        target_vol: float, 目标年化波动率
        max_position: float, 最大仓位限制
        min_position: float, 最小仓位限制

    返回:
        float: 调整后的仓位比例
    """
    raw_position = target_vol / predicted_vol

    # 限制仓位范围
    position = np.clip(raw_position, min_position, max_position)

    return position

# 示例:不同预测波动率下的仓位调整
print("预测波动率 | 目标仓位")
print("-" * 25)
for vol in [0.10, 0.15, 0.20, 0.25, 0.30, 0.40, 0.50]:
    pos = volatility_targeting_position(vol, target_vol=0.15)
    print(f"  {vol:.0%}      |  {pos:.2f}")

输出:

预测波动率 | 目标仓位
-------------------------
  10%      |  1.50(上限)
  15%      |  1.00
  20%      |  0.75
  25%      |  0.60
  30%      |  0.50
  40%      |  0.375
  50%      |  0.30

波动率调仓的逻辑是:市场波动大时减仓(降低风险暴露),波动小时加仓(充分利用风险预算)。

2.4 A 股波动率特征

A股市场的波动率有一些独特的特征:

  • 波动率聚集效应:高波动期和低波动期交替出现。一旦进入高波动期,通常会持续一段时间。
  • 杠杆效应:A股市场下跌时波动率往往上升,上涨时波动率较低。这意味着最危险的时刻往往伴随着最高的波动率。
  • 事件驱动波动率:政策公告、经济数据发布、节假日前后等时间节点,波动率可能突然跳升。
  • 开盘收盘波动率:开盘和收盘时段的波动率通常高于盘中其他时段。

三、最大回撤控制

3.1 回撤控制的框架

最大回撤控制是一个多层次的过程:

  1. 事前预防:通过仓位管理和止损设置,限制每笔交易和整体组合的最大亏损。
  2. 事中监控:实时跟踪组合回撤水平,在达到预设阈值时触发风险控制措施。
  3. 事后恢复:从回撤中恢复后,分析原因,优化策略。

3.2 回撤控制的具体方法

python
class DrawdownController:
    """回撤控制器"""

    def __init__(self, initial_capital, warning_level=0.10,
                 reduce_level=0.15, stop_level=0.20):
        """
        参数:
            initial_capital: 初始资金
            warning_level: 警告线(回撤比例)
            reduce_level: 减仓线
            stop_level: 止损线
        """
        self.initial_capital = initial_capital
        self.peak_capital = initial_capital
        self.warning_level = warning_level
        self.reduce_level = reduce_level
        self.stop_level = stop_level

    def update(self, current_capital):
        """
        更新资金并检查回撤状态

        返回:
            dict: 回撤信息和操作建议
        """
        # 更新峰值
        if current_capital > self.peak_capital:
            self.peak_capital = current_capital

        # 计算当前回撤
        drawdown = (current_capital - self.peak_capital) / self.peak_capital
        abs_drawdown = abs(drawdown)

        # 判断状态并给出建议
        if abs_drawdown >= self.stop_level:
            action = "全部平仓"
            position_scale = 0.0
        elif abs_drawdown >= self.reduce_level:
            action = "大幅减仓至30%"
            position_scale = 0.3
        elif abs_drawdown >= self.warning_level:
            action = "适度减仓至60%"
            position_scale = 0.6
        else:
            action = "正常交易"
            position_scale = 1.0

        return {
            'current_capital': current_capital,
            'peak_capital': self.peak_capital,
            'drawdown': drawdown,
            'action': action,
            'position_scale': position_scale
        }

# 使用示例
controller = DrawdownController(initial_capital=1000000)
print("资金量     | 回撤   | 操作建议")
print("-" * 50)
for capital in [1000000, 950000, 900000, 850000, 800000]:
    result = controller.update(capital)
    print(f"{capital:>10,.0f} | {result['drawdown']:>6.1%} | "
          f"{result['action']}")

四、风险预算(Risk Budgeting)

4.1 风险预算的概念

传统资产配置是分配资金(如股票 60%、债券 40%),而风险预算是分配风险。核心思想是:每个资产或策略对组合总风险的贡献应该与其预期收益相匹配。

风险预算的步骤:

  1. 确定组合的总风险预算(如年化波动率不超过 12%)。
  2. 将总风险预算分配给各个资产或策略。
  3. 计算每个资产/策略的边际风险贡献(Marginal Risk Contribution)。
  4. 调整权重使各资产的实际风险贡献等于预算。

4.2 风险预算的实现

python
import numpy as np
from scipy.optimize import minimize

def risk_budget_portfolio(cov_matrix, risk_budgets):
    """
    风险预算组合

    参数:
        cov_matrix: np.array, 协方差矩阵
        risk_budgets: list, 各资产的风险预算比例(之和为1)

    返回:
        np.array: 最优权重
    """
    n = cov_matrix.shape[0]
    risk_budgets = np.array(risk_budgets)

    def objective(weights):
        # 组合波动率
        port_vol = np.sqrt(weights @ cov_matrix @ weights)
        # 各资产的风险贡献
        marginal_risk = cov_matrix @ weights
        risk_contribution = weights * marginal_risk / port_vol
        # 风险贡献的比例
        rc_ratio = risk_contribution / risk_contribution.sum()
        # 目标:使实际风险贡献比例尽可能接近预算
        return np.sum((rc_ratio - risk_budgets) ** 2)

    constraints = {'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
    bounds = [(0.01, 1) for _ in range(n)]
    initial = np.ones(n) / n

    result = minimize(objective, initial, method='SLSQP',
                      bounds=bounds, constraints=constraints)

    return result.x

# 示例:3个资产,给低波动资产更多风险预算
cov = np.array([
    [0.04, 0.01, 0.005],  # 股票(高波动)
    [0.01, 0.01, 0.003],  # 债券(低波动)
    [0.005, 0.003, 0.02]  # 商品(中波动)
])
budgets = [0.5, 0.2, 0.3]  # 股票50%、债券20%、商品30%的风险预算

weights = risk_budget_portfolio(cov, budgets)
print("风险预算组合权重:")
print(f"  股票: {weights[0]:.1%}")
print(f"  债券: {weights[1]:.1%}")
print(f"  商品: {weights[2]:.1%}")

4.3 多策略的风险预算

风险预算不仅适用于资产配置,也适用于多策略组合:

python
def multi_strategy_risk_budget(strategies_sharpe, strategies_vol,
                                 total_risk_budget=0.12):
    """
    多策略风险预算

    参数:
        strategies_sharpe: list, 各策略的夏普比率
        strategies_vol: list, 各策略的年化波动率
        total_risk_budget: float, 组合的总波动率预算

    返回:
        dict: 各策略的资金分配和风险分配
    """
    n = len(strategies_sharpe)
    sharpes = np.array(strategies_sharpe)
    vols = np.array(strategies_vol)

    # 按夏普比率分配风险预算(夏普高的分配更多风险)
    risk_weights = np.maximum(sharpes, 0)  # 不给负夏普分配风险
    if risk_weights.sum() == 0:
        risk_weights = np.ones(n) / n
    else:
        risk_weights = risk_weights / risk_weights.sum()

    # 根据风险权重和各策略波动率反推资金权重
    # 风险贡献 = 资金权重 × 策略波动率
    # 总风险 = sqrt(sum(风险贡献^2))
    capital_weights = risk_weights * total_risk_budget / vols
    capital_weights = capital_weights / capital_weights.sum()

    print("多策略风险预算分配:")
    for i in range(n):
        print(f"  策略{i+1}: 夏普={sharpes[i]:.2f}, "
              f"波动率={vols[i]:.0%}, "
              f"风险预算={risk_weights[i]:.0%}, "
              f"资金分配={capital_weights[i]:.0%}")

    return {
        'risk_weights': risk_weights,
        'capital_weights': capital_weights
    }

五、黑天鹅应对

5.1 什么是黑天鹅

黑天鹅事件是指极不可能发生、一旦发生却影响巨大的事件。在金融市场中,黑天鹅事件的特征:

  • 极端性:远超正常波动的范围。例如 2008 年金融危机、2020 年新冠疫情暴跌。
  • 不可预测:传统的统计模型(假设正态分布)严重低估了黑天鹅的概率。
  • 影响深远:不仅影响市场,还可能改变市场结构和规则。

从统计角度看,金融市场的收益率分布具有**厚尾(Fat Tail)**特征:极端事件的概率远高于正态分布的预测。

5.2 厚尾的统计证据

python
def analyze_tail_risk(returns):
    """
    分析收益率的尾部特征

    参数:
        returns: pd.Series, 日收益率

    返回:
        dict: 尾部风险指标
    """
    from scipy import stats

    # 偏度和峰度
    skewness = returns.skew()
    kurtosis = returns.kurtosis()  # 超额峰度(正态分布为0)

    # Jarque-Bera 正态性检验
    jb_stat, jb_pvalue = stats.jarque_bera(returns)

    # 极端值统计
    n_sigma_3 = (abs(returns - returns.mean()) > 3 * returns.std()).sum()
    expected_3sigma = len(returns) * 0.0027  # 正态分布下3sigma概率

    print("尾部风险分析:")
    print(f"  偏度: {skewness:.3f}(正态分布为0)")
    print(f"  峰度: {kurtosis:.3f}(正态分布为0,>0表示厚尾)")
    print(f"  Jarque-Bera p值: {jb_pvalue:.4f}(<0.05拒绝正态)")
    print(f"  实际3σ事件: {n_sigma_3}次")
    print(f"  正态预测3σ事件: {expected_3sigma:.1f}次")
    print(f"  厚尾倍数: {n_sigma_3 / expected_3sigma:.1f}x")

    return {
        'skewness': skewness,
        'kurtosis': kurtosis,
        'tail_multiplier': n_sigma_3 / expected_3sigma
    }

在 A 股市场中,厚尾倍数通常在 3-8 倍之间,意味着极端事件发生的频率是正态分布预测的 3-8 倍。

5.3 应对黑天鹅的策略

策略一:预留安全垫

永远不要满仓。保留一定比例的现金(如 10%-20%),在极端情况下可以用来应对赎回或逢低加仓。

python
def safety_cushion_sizing(total_capital, max_drawdown_tolerance=0.20,
                            confidence_buffer=1.5):
    """
    计算安全仓位

    参数:
        total_capital: 总资金
        max_drawdown_tolerance: 最大可承受回撤
        confidence_buffer: 安全缓冲系数

    返回:
        float: 建议的最大投入资金
    """
    # 保守估计:将可承受亏损除以缓冲系数
    max_acceptable_loss = total_capital * max_drawdown_tolerance
    # 假设极端情况下可能亏损达到预期最大回撤的buffer倍
    max_position = total_capital - (max_acceptable_loss * confidence_buffer)

    safe_ratio = max_position / total_capital

    print(f"总资金: {total_capital:,.0f}")
    print(f"最大可承受回撤: {max_drawdown_tolerance:.0%}")
    print(f"安全缓冲系数: {confidence_buffer}")
    print(f"建议最大仓位: {max_position:,.0f}{safe_ratio:.0%})")

    return max_position

策略二:尾部风险对冲

购买看跌期权或波动率产品作为保险:

  • 在组合中配置少量的看跌期权(如沪深300认沽期权),在市场暴跌时期权的收益可以抵消组合的亏损。
  • 虽然期权在正常市场环境下会持续损耗(相当于交保费),但在黑天鹅事件中能起到关键的保护作用。
  • 通常用组合市值的 1%-3% 来购买尾部风险保护。

策略三:分散到非相关资产

黑天鹅事件对不同资产的影响不同。通过配置黄金、国债等避险资产,可以在股票市场暴跌时减少整体损失:

python
def crisis_portfolio_allocation():
    """
    危机时期的资产配置建议(仅供教育参考,不构成投资建议)

    这展示的是一种保守配置思路,实际配置应根据个人情况调整
    """
    allocation = {
        '股票': {'正常时期': 0.60, '危机时期': 0.30},
        '国债': {'正常时期': 0.25, '危机时期': 0.40},
        '黄金': {'正常时期': 0.05, '危机时期': 0.15},
        '现金': {'正常时期': 0.10, '危机时期': 0.15},
    }

    print("资产配置对比:")
    print(f"{'资产':>6} | {'正常时期':>8} | {'危机时期':>8}")
    print("-" * 35)
    for asset, weights in allocation.items():
        print(f"{asset:>6} | {weights['正常时期']:>8.0%} | "
              f"{weights['危机时期']:>8.0%}")

    return allocation

策略四:设置"熔断"机制

当组合亏损达到预设阈值时,自动停止交易,强制冷静期:

python
class CircuitBreaker:
    """策略熔断器"""

    def __init__(self, daily_loss_limit=0.03, weekly_loss_limit=0.05,
                 monthly_loss_limit=0.08):
        self.daily_loss_limit = daily_loss_limit
        self.weekly_loss_limit = weekly_loss_limit
        self.monthly_loss_limit = monthly_loss_limit
        self.is_triggered = False

    def check(self, daily_loss, weekly_loss, monthly_loss):
        """
        检查是否触发熔断

        参数:
            daily_loss: 当日亏损比例(负数)
            weekly_loss: 当周亏损比例(负数)
            monthly_loss: 当月亏损比例(负数)

        返回:
            bool: 是否触发熔断
        """
        triggers = []

        if abs(daily_loss) >= self.daily_loss_limit:
            triggers.append(f"日亏损 {daily_loss:.1%} 超过限制 {self.daily_loss_limit:.0%}")
        if abs(weekly_loss) >= self.weekly_loss_limit:
            triggers.append(f"周亏损 {weekly_loss:.1%} 超过限制 {self.weekly_loss_limit:.0%}")
        if abs(monthly_loss) >= self.monthly_loss_limit:
            triggers.append(f"月亏损 {monthly_loss:.1%} 超过限制 {self.monthly_loss_limit:.0%}")

        if triggers:
            self.is_triggered = True
            print("熔断触发!原因:")
            for t in triggers:
                print(f"  - {t}")
            print("建议:暂停交易,冷静期至少 3 个交易日")
            return True

        self.is_triggered = False
        return False

六、综合风险管理体系

6.1 风险管理的层次

一个完整的风险管理体系应该是多层次的:

第一层:单笔交易风控
    ├── 单笔最大亏损限制(如不超过总资金的 2%)
    ├── 止损设置(固定百分比或 ATR 止损)
    └── 持仓时间限制(避免长期持有亏损头寸)

第二层:组合级风控
    ├── 行业/个股集中度限制(单一行业不超过 25%)
    ├── 组合整体 VaR 监控
    ├── 波动率目标控制
    └── 相关性监控(避免隐性集中)

第三层:策略级风控
    ├── 策略最大回撤监控
    ├── 策略容量控制
    ├── 多策略相关性管理
    └── 熔断机制

第四层:账户级风控
    ├── 总资金回撤限制
    ├── 杠杆控制
    ├── 流动性管理(预留保证金)
    └── 现金储备要求

6.2 风险指标仪表盘

建议构建一个综合的风险监控仪表盘,每日收盘后更新:

python
class RiskDashboard:
    """风险管理仪表盘"""

    def __init__(self, returns, benchmark_returns=None,
                 portfolio_value=1000000):
        self.returns = returns
        self.benchmark = benchmark_returns
        self.portfolio_value = portfolio_value

    def generate_report(self):
        """生成每日风险报告"""
        print("=" * 60)
        print("每日风险管理报告")
        print("=" * 60)

        # 1. 收益指标
        annual_return = (1 + self.returns).prod() ** (252 / len(self.returns)) - 1
        annual_vol = self.returns.std() * np.sqrt(252)
        sharpe = annual_return / annual_vol if annual_vol > 0 else 0

        print(f"\n1. 收益与风险")
        print(f"   年化收益率: {annual_return:.2%}")
        print(f"   年化波动率: {annual_vol:.2%}")
        print(f"   夏普比率:   {sharpe:.2f}")

        # 2. 回撤
        cum_nav = (1 + self.returns).cumprod()
        cum_max = cum_nav.cummax()
        drawdown = (cum_nav - cum_max) / cum_max
        current_dd = drawdown.iloc[-1]
        max_dd = drawdown.min()

        print(f"\n2. 回撤监控")
        print(f"   当前回撤:   {current_dd:.2%}")
        print(f"   历史最大回撤: {max_dd:.2%}")

        # 3. VaR
        var_95 = np.percentile(self.returns, 5)
        cvar_95 = self.returns[self.returns <= var_95].mean()

        print(f"\n3. 尾部风险")
        print(f"   95% VaR:    {var_95:.2%}")
        print(f"   95% CVaR:   {cvar_95:.2%}")
        print(f"   VaR金额:    {abs(var_95) * self.portfolio_value:,.0f} 元")

        # 4. 最近表现
        recent_5d = self.returns.tail(5).sum()
        recent_20d = self.returns.tail(20).sum()

        print(f"\n4. 近期表现")
        print(f"   近5日收益:  {recent_5d:.2%}")
        print(f"   近20日收益: {recent_20d:.2%}")

        # 5. 风险等级评估
        risk_level = self._assess_risk_level(current_dd, annual_vol)
        print(f"\n5. 风险等级: {risk_level}")

        return risk_level

    def _assess_risk_level(self, current_dd, annual_vol):
        """评估当前风险等级"""
        abs_dd = abs(current_dd)

        if abs_dd > 0.20 or annual_vol > 0.30:
            return "高(建议减仓)"
        elif abs_dd > 0.10 or annual_vol > 0.20:
            return "中高(密切关注)"
        elif abs_dd > 0.05 or annual_vol > 0.15:
            return "中等(正常监控)"
        else:
            return "低(正常交易)"

七、总结

量化风险管理是投资成功的基石。记住以下核心原则:

  1. VaR 和 CVaR 是衡量尾部风险的标准工具。VaR 告诉你最坏情况下的亏损底线,CVaR 告诉你超过底线后平均会亏多少。
  2. 波动率控制是最实用的风险管理方法。通过动态调仓保持稳定的波动率,可以在不同市场环境中保持一致的风险暴露。
  3. 最大回撤控制要有明确纪律。设定警告线、减仓线和止损线,严格执行,不要在亏损时抱有侥幸心理。
  4. 风险预算比资金预算更科学。按风险贡献而非资金比例来分配,能更好地利用有限的风险预算。
  5. 黑天鹅无法预测,但可以准备。通过安全垫、尾部对冲、分散配置和熔断机制,在极端事件中保护本金。

风险管理的本质不是消除风险——没有风险就没有收益。风险管理的目标是在承受可控风险的前提下获取收益,确保你在市场最黑暗的时刻仍然存活,等待黎明的到来。

仅供学习交流,不构成任何投资建议