跳到主要内容

风险管理基础

风险管理是量化交易的生命线,良好的风险管理能够在不利市场环境中保护资金安全,确保策略长期稳定运行。本章将介绍风险管理的核心概念和实用方法。

风险管理的重要性

在量化交易中,风险管理的地位不亚于策略研发本身。许多优秀的策略最终失败,不是因为策略逻辑有问题,而是因为风险管理不当导致资金链断裂。

风险管理的核心目标不是避免亏损,而是将亏损控制在可承受范围内。任何交易策略都会经历亏损期,关键是在亏损期存活下来,等待盈利期的到来。

风险管理的三大原则

生存优先:在任何情况下都要确保账户不会爆仓,保留继续交易的能力。这意味着要严格控制单笔风险和总风险敞口。

风险可量化:所有风险都应该能够被量化计算,而不是凭感觉估计。只有量化的风险才能被有效管理。

动态调整:风险管理不是一成不变的,需要根据市场环境和策略表现动态调整。

常用风险指标

最大回撤

最大回撤(Maximum Drawdown)衡量策略从峰值到谷底的最大跌幅,是最直观的风险指标。

公式:MDD=maxtVpeakVtVpeakMDD = \max_{t} \frac{V_{peak} - V_t}{V_{peak}}

其中 VpeakV_{peak} 是历史最高净值,VtV_t 是当前净值。

import numpy as np
import pandas as pd

def calculate_max_drawdown(returns):
"""
计算最大回撤

参数:
returns: 收益率序列

返回:
最大回撤值(正数)
"""
# 计算累计净值
cumulative = (1 + returns).cumprod()

# 计算历史最高点
running_max = cumulative.cummax()

# 计算回撤
drawdown = (cumulative - running_max) / running_max

# 返回最大回撤
return abs(drawdown.min())

# 使用示例
returns = pd.Series([0.01, -0.02, 0.03, -0.05, 0.02, -0.03, 0.04])
max_dd = calculate_max_drawdown(returns)
print(f"最大回撤: {max_dd * 100:.2f}%")

最大回撤的缺点是只关注最坏情况,没有考虑回撤发生的频率和持续时间。一个策略可能最大回撤较小,但频繁出现中等幅度的回撤,实际风险并不低。

波动率

波动率(Volatility)衡量收益率的离散程度,是最常用的风险度量指标。通常使用收益率的标准差来表示。

年化波动率公式:σannual=σdaily×252\sigma_{annual} = \sigma_{daily} \times \sqrt{252}

def calculate_volatility(returns, annualize=True, periods=252):
"""
计算波动率

参数:
returns: 收益率序列
annualize: 是否年化
periods: 年化因子(日线数据用252,周线用52)

返回:
波动率
"""
vol = returns.std()

if annualize:
vol = vol * np.sqrt(periods)

return vol

波动率假设收益率服从正态分布,但实际金融收益率往往具有"尖峰厚尾"特征,极端事件发生的概率比正态分布预测的要高。

夏普比率

夏普比率(Sharpe Ratio)衡量风险调整后的收益,是最重要的绩效评估指标之一。

公式:Sharpe=RpRfσpSharpe = \frac{R_p - R_f}{\sigma_p}

其中 RpR_p 是策略收益率,RfR_f 是无风险收益率,σp\sigma_p 是策略波动率。

def calculate_sharpe_ratio(returns, risk_free_rate=0.02, periods=252):
"""
计算夏普比率

参数:
returns: 日收益率序列
risk_free_rate: 年化无风险利率
periods: 年化因子

返回:
夏普比率
"""
# 年化收益率
annual_return = (1 + returns.mean()) ** periods - 1

# 年化波动率
annual_vol = returns.std() * np.sqrt(periods)

# 夏普比率
excess_return = annual_return - risk_free_rate
sharpe = excess_return / annual_vol

return sharpe

夏普比率的解读:

  • 小于1:风险调整后收益较差
  • 1-2:良好
  • 2-3:优秀
  • 大于3:卓越(但也可能存在问题,如数据错误或过拟合)

夏普比率的局限性:

  • 假设收益率正态分布
  • 对上行波动和下行波动一视同仁(投资者只关心下行风险)
  • 可能被操纵(如通过增加尾部风险来平滑收益)

索提诺比率

索提诺比率(Sortino Ratio)是夏普比率的改进版,只考虑下行波动率,更符合投资者的实际感受。

公式:Sortino=RpRfσdownSortino = \frac{R_p - R_f}{\sigma_{down}}

其中 σdown\sigma_{down} 是下行波动率,只计算负收益的标准差。

def calculate_sortino_ratio(returns, risk_free_rate=0.02, periods=252):
"""
计算索提诺比率

参数:
returns: 日收益率序列
risk_free_rate: 年化无风险利率
periods: 年化因子

返回:
索提诺比率
"""
# 年化收益率
annual_return = (1 + returns.mean()) ** periods - 1

# 下行波动率
negative_returns = returns[returns < 0]
downside_vol = negative_returns.std() * np.sqrt(periods)

# 索提诺比率
excess_return = annual_return - risk_free_rate
sortino = excess_return / downside_vol

return sortino

卡玛比率

卡玛比率(Calmar Ratio)是年化收益率与最大回撤的比值,直观反映收益与风险的平衡。

公式:Calmar=RannualMDDCalmar = \frac{R_{annual}}{MDD}

def calculate_calmar_ratio(returns, periods=252):
"""
计算卡玛比率

参数:
returns: 日收益率序列
periods: 年化因子

返回:
卡玛比率
"""
# 年化收益率
annual_return = (1 + returns.mean()) ** periods - 1

# 最大回撤
max_dd = calculate_max_drawdown(returns)

# 卡玛比率
calmar = annual_return / max_dd

return calmar

VaR和CVaR

VaR(Value at Risk,在险价值)是在给定置信水平下的最大可能损失。

例如,95% VaR表示有95%的概率损失不会超过这个值。

def calculate_var(returns, confidence=0.95):
"""
计算VaR(历史模拟法)

参数:
returns: 收益率序列
confidence: 置信水平

返回:
VaR值(正数表示损失)
"""
return abs(np.percentile(returns, (1 - confidence) * 100))

def calculate_cvar(returns, confidence=0.95):
"""
计算CVaR(条件VaR,也称Expected Shortfall)
CVaR是超过VaR的平均损失

参数:
returns: 收益率序列
confidence: 置信水平

返回:
CVaR值(正数表示损失)
"""
var = calculate_var(returns, confidence)
return abs(returns[returns < -var].mean())

CVaR比VaR更能反映尾部风险,因为VaR只告诉我们损失不会超过某个值,但没有告诉我们一旦超过会损失多少。

仓位管理

仓位管理是风险管理的核心,决定了每次交易投入多少资金。

固定金额法

每次交易投入固定金额,最简单但不够灵活。

def fixed_amount_position(total_capital, fixed_amount):
"""固定金额仓位"""
return fixed_amount

固定比例法

每次交易投入总资金的固定比例。

def fixed_fraction_position(total_capital, fraction=0.1):
"""固定比例仓位"""
return total_capital * fraction

凯利公式

凯利公式根据胜率和盈亏比计算最优仓位比例,理论上能最大化长期增长率。

公式:f=p×bqbf^* = \frac{p \times b - q}{b}

其中 pp 是胜率,q=1pq = 1-p 是败率,bb 是盈亏比(平均盈利/平均亏损)。

def kelly_criterion(win_rate, avg_win, avg_loss):
"""
凯利公式计算最优仓位

参数:
win_rate: 胜率
avg_win: 平均盈利
avg_loss: 平均亏损

返回:
最优仓位比例
"""
b = avg_win / abs(avg_loss) # 盈亏比
p = win_rate
q = 1 - p

kelly = (p * b - q) / b

# 限制在0-1之间
kelly = max(0, min(kelly, 1))

return kelly

# 实际应用中通常使用半凯利或四分之一凯利
def half_kelly(win_rate, avg_win, avg_loss):
"""半凯利,更保守"""
return kelly_criterion(win_rate, avg_win, avg_loss) * 0.5

凯利公式的局限性:

  • 假设胜率和盈亏比稳定,但实际市场是变化的
  • 完全凯利仓位波动很大,实际中通常使用半凯利或更保守的比例
  • 没有考虑连续亏损的影响

波动率倒数法

根据资产波动率调整仓位,波动大的资产配置较少,波动小的资产配置较多。

def volatility_scaled_position(total_capital, target_vol, asset_vol):
"""
波动率倒数仓位

参数:
total_capital: 总资金
target_vol: 目标波动率
asset_vol: 资产波动率

返回:
仓位金额
"""
# 仓位比例 = 目标波动率 / 资产波动率
position_ratio = target_vol / asset_vol

# 限制最大比例
position_ratio = min(position_ratio, 1.0)

return total_capital * position_ratio

ATR仓位管理

使用ATR(平均真实波幅)来调整仓位,确保每笔交易的风险金额相同。

def atr_position_sizing(total_capital, risk_per_trade, atr, price):
"""
基于ATR的仓位管理

参数:
total_capital: 总资金
risk_per_trade: 每笔交易风险比例(如0.02表示2%)
atr: 当前ATR值
price: 当前价格

返回:
交易股数
"""
# 风险金额
risk_amount = total_capital * risk_per_trade

# 每股风险(假设止损距离为2倍ATR)
stop_distance = 2 * atr

# 计算股数
shares = int(risk_amount / stop_distance)

return shares

止损止盈

止损止盈是风险管理的具体执行手段。

固定点数止损

def fixed_stop_loss(entry_price, stop_points):
"""固定点数止损"""
return entry_price - stop_points

def fixed_take_profit(entry_price, profit_points):
"""固定点数止盈"""
return entry_price + profit_points

百分比止损

def percentage_stop_loss(entry_price, stop_pct):
"""百分比止损"""
return entry_price * (1 - stop_pct)

def percentage_take_profit(entry_price, profit_pct):
"""百分比止盈"""
return entry_price * (1 + profit_pct)

ATR止损

def atr_stop_loss(entry_price, atr, multiplier=2):
"""ATR止损"""
return entry_price - multiplier * atr

移动止损

移动止损(Trailing Stop)随着价格上涨而上移,但不会下降,可以锁定部分利润。

class TrailingStop:
"""移动止损管理器"""

def __init__(self, initial_price, trail_pct=0.1):
self.highest_price = initial_price
self.trail_pct = trail_pct
self.stop_price = initial_price * (1 - trail_pct)

def update(self, current_price):
"""更新止损价格"""
if current_price > self.highest_price:
self.highest_price = current_price
self.stop_price = current_price * (1 - self.trail_pct)
return self.stop_price

def should_stop(self, current_price):
"""判断是否触发止损"""
return current_price <= self.stop_price

# 使用示例
trailing_stop = TrailingStop(entry_price=100, trail_pct=0.05)

prices = [102, 105, 103, 108, 106, 104, 102]
for price in prices:
stop = trailing_stop.update(price)
print(f"价格: {price}, 止损价: {stop:.2f}, 触发: {trailing_stop.should_stop(price)}")

风险预算

风险预算是将总风险分配到各个策略或资产上。

def risk_parity_allocation(volatilities):
"""
风险平价配置
每个资产贡献相同的风险

参数:
volatilities: 各资产波动率列表

返回:
各资产权重
"""
# 风险倒数
inv_vols = [1 / v for v in volatilities]

# 归一化
total = sum(inv_vols)
weights = [v / total for v in inv_vols]

return weights

# 使用示例
volatilities = [0.15, 0.20, 0.25, 0.30] # 四个资产的波动率
weights = risk_parity_allocation(volatilities)
print(f"风险平价权重: {[f'{w:.2%}' for w in weights]}")

风险监控指标

单笔风险控制

def check_single_trade_risk(position_value, total_capital, max_risk_pct=0.02):
"""检查单笔交易风险"""
risk_pct = position_value / total_capital
if risk_pct > max_risk_pct:
print(f"警告: 单笔风险 {risk_pct:.2%} 超过限制 {max_risk_pct:.2%}")
return False
return True

总风险敞口控制

def check_total_exposure(positions, total_capital, max_exposure=1.0):
"""检查总风险敞口"""
total_exposure = sum(abs(p) for p in positions.values()) / total_capital
if total_exposure > max_exposure:
print(f"警告: 总敞口 {total_exposure:.2%} 超过限制 {max_exposure:.2%}")
return False
return True

回撤预警

class DrawdownMonitor:
"""回撤监控器"""

def __init__(self, warning_level=0.1, critical_level=0.2):
self.warning_level = warning_level # 警告级别
self.critical_level = critical_level # 危险级别
self.peak_value = None

def update(self, current_value):
"""更新并检查回撤"""
if self.peak_value is None or current_value > self.peak_value:
self.peak_value = current_value

drawdown = (self.peak_value - current_value) / self.peak_value

if drawdown >= self.critical_level:
print(f"严重警告: 回撤 {drawdown:.2%} 达到危险级别!")
return 'critical'
elif drawdown >= self.warning_level:
print(f"警告: 回撤 {drawdown:.2%} 达到警告级别")
return 'warning'

return 'normal'

小结

风险管理是量化交易成功的关键因素。本章介绍了常用的风险指标(最大回撤、夏普比率、VaR等)、仓位管理方法(凯利公式、波动率倒数法等)、止损止盈策略和风险监控方法。

风险管理的核心原则是:

  1. 永远不要把所有资金押在单一交易上
  2. 预先设定止损点,严格执行
  3. 根据市场波动动态调整仓位
  4. 持续监控风险指标,及时预警

下一章将学习因子投资的基础知识。