计算VaR的历史模拟法的Python实现代码


前言

以下是使用历史模拟法计算 VaR(Value at Risk)的 Python 实现。历史模拟法是一种非参数方法,直接基于历史数据的分布来估计风险,无需假设收益率服从特定分布。


python3.13 环境配置

python3.13下载安装教程:https://blog.csdn.net/2501_91538706/article/details/147315428

核心代码实现

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import norm

def calculate_var(returns, confidence_level=0.95, horizon=1, method='historical', 
                  portfolio_value=None, distribution=None, mu=None, sigma=None):
    """
    计算投资组合的VaR(Value at Risk)
    
    参数:
    returns (pd.Series或pd.DataFrame): 资产或投资组合的历史收益率
    confidence_level (float): 置信水平,默认为0.95
    horizon (int): 预测的时间范围(天数),默认为1method (str): 计算方法,支持'historical'(历史模拟法)、'parametric'(参数法)
    portfolio_value (float): 投资组合价值,若为None则返回百分比VaR
    distribution (str): 参数法中使用的分布,支持'normal'(正态分布)
    mu (float): 参数法中的均值
    sigma (float): 参数法中的标准差
    
    返回:
    float: VaR值(若portfolio_value不为None,则返回绝对金额;否则返回百分比)
    """
    # 历史模拟法
    if method == 'historical':
        # 计算时间范围内的累积收益率
        if horizon > 1:
            returns = returns.rolling(window=horizon).apply(lambda x: (1+x).prod() - 1).dropna()
        
        # 计算VaR(负号表示损失)
        var_percentile = np.percentile(returns, (1 - confidence_level) * 100)
        
        # 转换为绝对金额(如果提供了投资组合价值)
        if portfolio_value is not None:
            return -portfolio_value * var_percentile
        else:
            return -var_percentile
    
    # 参数法(正态分布假设)
    elif method == 'parametric':
        if distribution == 'normal':
            if mu is None:
                mu = returns.mean()
            if sigma is None:
                sigma = returns.std()
            
            # 调整时间范围
            mu_horizon = mu * horizon
            sigma_horizon = sigma * np.sqrt(horizon)
            
            # 计算VaR
            z_score = norm.ppf(1 - confidence_level)
            var_percentile = mu_horizon + z_score * sigma_horizon
            
            # 转换为绝对金额(如果提供了投资组合价值)
            if portfolio_value is not None:
                return -portfolio_value * var_percentile
            else:
                return -var_percentile
    else:
        raise ValueError("不支持的计算方法,请选择'historical'或'parametric'")

def calculate_cvar(returns, confidence_level=0.95, horizon=1, portfolio_value=None):
    """
    计算条件VaR(CVaR)或预期尾部损失(ES)
    
    参数:
    returns (pd.Series或pd.DataFrame): 资产或投资组合的历史收益率
    confidence_level (float): 置信水平,默认为0.95
    horizon (int): 预测的时间范围(天数),默认为1portfolio_value (float): 投资组合价值,若为None则返回百分比CVaR
    
    返回:
    float: CVaR值
    """
    # 计算时间范围内的累积收益率
    if horizon > 1:
        returns = returns.rolling(window=horizon).apply(lambda x: (1+x).prod() - 1).dropna()
    
    # 计算VaR阈值
    var_threshold = np.percentile(returns, (1 - confidence_level) * 100)
    
    # 计算CVaR(条件平均损失)
    tail_returns = returns[returns <= var_threshold]
    cvar_percentile = tail_returns.mean()
    
    # 转换为绝对金额(如果提供了投资组合价值)
    if portfolio_value is not None:
        return -portfolio_value * cvar_percentile
    else:
        return -cvar_percentile

def plot_var(returns, var, confidence_level=0.95, title="收益率分布与VaR"):
    """可视化VaR"""
    plt.figure(figsize=(10, 6))
    plt.hist(returns, bins=50, density=True, alpha=0.7, color='skyblue')
    
    # 绘制VaR线
    var_percentile = np.percentile(returns, (1 - confidence_level) * 100)
    plt.axvline(x=-var, color='r', linestyle='--', label=f'VaR({confidence_level*100}%) = {var:.4f}')
    
    # 填充尾部区域
    x = np.linspace(returns.min(), -var, 100)
    plt.fill_between(x, norm.pdf(x, returns.mean(), returns.std()), color='red', alpha=0.3)
    
    plt.title(title)
    plt.xlabel('收益率')
    plt.ylabel('密度')
    plt.legend()
    plt.grid(True)
    plt.show()

使用示例

下面是一个使用真实股票数据计算 VaR 的完整示例:

# 导入必要的库
import yfinance as yf

# 获取股票数据
def get_stock_data(ticker, start_date, end_date):
    """获取股票历史数据"""
    stock = yf.download(ticker, start=start_date, end=end_date)
    return stock

# 计算投资组合收益率
def calculate_portfolio_returns(stock_data, weights=None):
    """计算投资组合收益率"""
    # 计算每日收益率
    returns = stock_data['Adj Close'].pct_change().dropna()
    
    # 如果是单只股票,直接返回收益率
    if isinstance(returns, pd.Series) or weights is None:
        return returns
    
    # 计算投资组合收益率
    portfolio_returns = returns.dot(weights)
    return portfolio_returns

# 主函数:演示VaR计算
def main():
    # 获取股票数据
    tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN']
    start_date = '2020-01-01'
    end_date = '2023-01-01'
    
    # 创建等权重投资组合
    weights = np.array([0.25, 0.25, 0.25, 0.25])
    
    # 存储各股票的收益率
    all_returns = pd.DataFrame()
    
    for ticker in tickers:
        stock_data = get_stock_data(ticker, start_date, end_date)
        returns = stock_data['Adj Close'].pct_change().dropna()
        all_returns[ticker] = returns
    
    # 计算投资组合收益率
    portfolio_returns = calculate_portfolio_returns(all_returns, weights)
    
    # 计算VaR(95%置信水平,1天)
    var_95 = calculate_var(portfolio_returns, confidence_level=0.95)
    var_99 = calculate_var(portfolio_returns, confidence_level=0.99)
    
    # 计算CVaR
    cvar_95 = calculate_cvar(portfolio_returns, confidence_level=0.95)
    
    print(f"投资组合每日95% VaR: {var_95:.4%}")
    print(f"投资组合每日99% VaR: {var_99:.4%}")
    print(f"投资组合每日95% CVaR: {cvar_95:.4%}")
    
    # 计算10天VaR(时间缩放)
    var_95_10day = calculate_var(portfolio_returns, confidence_level=0.95, horizon=10)
    print(f"投资组合10天95% VaR: {var_95_10day:.4%}")
    
    # 使用参数法(正态分布)计算VaR
    var_parametric = calculate_var(
        portfolio_returns, 
        confidence_level=0.95, 
        method='parametric', 
        distribution='normal'
    )
    print(f"基于正态分布假设的95% VaR: {var_parametric:.4%}")
    
    # 可视化VaR
    plot_var(portfolio_returns, var_95, confidence_level=0.95, title="投资组合收益率分布与VaR")
    
    # 假设投资组合价值为100万美元,计算绝对VaR
    portfolio_value = 1000000
    var_dollar = calculate_var(portfolio_returns, confidence_level=0.95, portfolio_value=portfolio_value)
    print(f"投资组合价值 ${portfolio_value:,} 的95% VaR: ${var_dollar:,.2f}")

if __name__ == "__main__":
    main()

代码解释

  1. 历史模拟法计算 VaR:直接基于历史收益率的分布,通过百分位数计算 VaR。例如,95% 置信水平下的 VaR 是收益率分布的第 5百分位数。
  2. 条件 VaR(CVaR)计算:计算超过 VaR 阈值的平均损失,提供了更保守的风险度量。
  3. 时间范围调整:通过滚动窗口计算多日累积收益率,实现时间范围的扩展。 参数法对比:支持基于正态分布假设的参数法 VaR计算,便于对比不同方法的结果。
  4. 可视化功能:绘制收益率分布直方图,并标记 VaR 阈值和尾部风险区域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值