2022年 11月 3日

Python金融实战之计算VaR

总的来说,VaR的评估方式有参数法、非参数法、混合法(也叫半参数法)

一、历史模拟法(非参数法)计算VaR

1.VaR 定义:Value at Risk,在一定概率水平(置信度)下,某一金融资产或证券组合价值在未来特定时期内的最大可能损失。一日 5% VaR 可以理解为一天发生损失超过VaR的概率小于等于5%。

2.Python实现过程
先导入包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn
import tushare as ts
%matplotlib inline
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

读取数据:tushare的get_k_data函数,输入股票代码,和数据起始日期。

data = ts.get_k_data('601398','2018-01-01','2019-12-31')
  • 1

在这里插入图片描述

#计算每天的收益率
data['d_return'] = data['close'].pct_change() 
# np.percentile方法计算分位数,前提是不能有空值;
VaR_5 = np.percentile(data.d_return.dropna(), 5)         
VaR_1 = np.percentile(data.d_return.dropna(), 1)
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
然后画图

plt.figure(figsize= (8,6))
data.d_return.hist(bins=50, alpha=0.6, color='steelblue')
plt.axvline(VaR_5, color='r', linewidth=1,label = 'VaR_5')
plt.axvline(VaR_1, color='y', linewidth=1,label = 'VaR_1')
plt.legend()
plt.xlabel('return')
plt.ylabel('count')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

二、参数法计算VaR

1.参数法定义:先用历史数据计算出每天的收益率均值μ和每天的波动率σ,99%的VaR(daily)=μ_(1-day)-2.33*σ_(1-day),2.33是99%VaR单尾检验的Z值。如果求10天99%的VaR,就要先计算这10天的收益率均值和10天的波动率。99%的10-dayVaR = μ_(1-day)10-2.33σ_(1-day)*√10

2.主要代码都跟历史法一样,这里新加计算收益率均值和波动率的方法。

mean_return = data['d_return'].mean()
std = data['d_return'].std()
var1 = mean_return-2.33*std
var5 = mean_return-1.645*std
  • 1
  • 2
  • 3
  • 4

三、重抽样(非参数法)计算VaR

1.重抽样定义:在历史数据中进行又放回的随机抽样,可以随机抽100天,200天的收益率,这里抽取100次,并计算每个样本对应的VaR,对所有样本的VaR结果取平均值作为总体的VaR值。

2.代码如下

# 使用numpy.random.choice()随机抽取300天的收益率
data_pool = data.d_return.dropna()
data_pool[:10]

def sample_para_VaR(data, size):
    """
    从data中抽取size大小的样本,计算样本的5%和1%VaR
    param data: 产生抽样数据的数据池
    param size: 抽取样本数量
    return: 返回模拟路径下的期末收益
    """
    sample = np.random.choice(data, size, replace=True)
    VaR_5 = np.percentile(sample, 5)
    VaR_1 = np.percentile(sample, 1)
    return (VaR_5, VaR_1)

sample_VaR(data_pool, size=300)

# 产生N条收益率路径
samples = [sample_para_VaR(data_pool, 300) for i in range(100)]
samples[:10]
para_VaRs = pd.DataFrame(samples, columns=['para_VaR_5', 'para_VaR_1'])
para_VaR_mean = para_VaRs.mean()
para_VaR_mean
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

四、蒙特卡洛(参数法)模拟计算VaR

1.蒙特卡洛模拟原理:假设股票价格波动符合几何布朗运动,S_t= S_(t-1)+S_(t-1)dt+σε√dt),
S_t是今天股票的价格,S_(t-1)是前一天的股票价格,μ是股票每天的收益率的均值,ε是服从标准正态分布的随机项。dt是模拟的时间间隔,比如每天模拟一次股票价格,dt=1,每天模拟两次,dt=0.5,每十天模拟一次,dt=10。
比如用昨天的股票数据作为起始数据,用历史数据的每天的平均收益率和波动率代入公式模拟一天后的股票价格100次,就能得到100个收益率数据,在对这100个收益率取95%和99%的分位数,得到95%和99%的VaR

2.蒙特卡洛模拟函数的实现:

# 定义一个函数,用于计算一次几何布朗运动的价格数据,single simualtion;
def GBM(s_0, mu, sigma, T ,n):
    """计算几何布朗运动的价格数据
    
    parameters:
        s_0: 开始价格
        mu: 观察期日收益率的均值
        sigma: 观察期日收益率的标准差
        T: 预测价格的周期长度,如预测下一天,T=1,预测后10天,T=10;
        n: 单次模拟的步数,步数越大,模拟得越精确;
    
    """
    # 计算delta_t
    delta_t = T/n
    
    # 创建一个空的列表用于储存价格数据
    simulated_price = [s_0]
    
    # 模拟价格走势
    for i in range(n):
        # 获取期初价格
        start_price = simulated_price[i]
        # 按照标准正态分布产生一个随机数
        epsilon = np.random.normal()
        # 根据几何布朗运动公式计算期末价格
        end_price = start_price + start_price * (mu*delta_t + sigma*epsilon*np.sqrt(delta_t))
        # 价格应大于0
        end_price = max(0, end_price)
        
        # 将算的的结果存入列表
        simulated_price.append(end_price)
    
    return simulated_price


# 产生10000个1天的模拟价格,取出它们的最终价格,并保存在simulated_prices_1空列表中
simulated_prices_1 = []
for i in range(10000):
    # 模拟一次几何布朗运动
    simulated_price = GBM(s_0, mu_1, sigma_1, 1,100)
    # 取出最终价格
    final_price = simulated_price[-1]
    simulated_prices_1.append(final_price)

simulated_return_1 = simulated_prices_1/s_0-1  
VaR_1 = np.percentile(simulated_return_1, 1) 
VaR_10 =  VaR_1 * np.sqrt(10) #平方根法则,用一天的VaR估算十天的VaR
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

另一种方法,模拟十天后的股票价格,计算十天的99%VaR

# 产生10000个10天的模拟价格,取出第10天的最终价格,并保存在simulated_prices_10空列表中
simulated_prices_10 = []
for i in range(10000):
    # 模拟一次几何布朗运动
    simulated_price = GBM(s_0, mu_1, sigma_1, 10,100)
    # 取出最终价格
    final_price = simulated_price[-1]
    simulated_prices_10.append(final_price)

simulated_return_10 = simulated_prices_10/s_0-1
VaR_10 = np.percentile(simulated_return_10, 1)

#还可以先找到99%分位数对应的股票价格,再用该价格计算对应的收益率得到99%的VaR
price_percentile = np.percentile(simulated_prices_10,1)
VaR_10 = price_percentile/s_0-1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15