百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

金融分析与风险管理——风险价值(VaR)

toyiye 2024-06-21 12:36 6 浏览 0 评论

1. 风险价值(VaR)简述

风险价值(value at risk,VaR)是指在一定的持有期和给定的置信水平下,利率、汇率、股价等风险因子发生变化时可能对投资组合造成的潜在最大损失。例如:持有期 1 天、置信水平 95% 的情况下,计算得到的 VaR 值为 1000 万元,则表明该投资组合在1天中有 95%的可能性损失不会超过1000万,换句话说,1 天中,有5%的可能性损失会超过 1000 万元。

VaR的大小取决于两个参数:持有期(N)、置信水平(X)。由于 VaR 度量的是投资组合的亏损,其对应于投资组合盈亏分布的左端尾部,为了表述方便,通常 VaR 值用绝对值表示。

VaR 的数学表达式如下:

根据巴塞尔协议的明确规定:银行需要计算持有期10天、置信水平99%的VaR。在实际计算中,通常先计算 N=1 时的VaR,在计算相同置信水平下 N>1 时的 VaR,其表达式如下:

上式成立的条件是:投资组合价值在不同交易日之间的变化是相互独立并服从期望值为0的相同正态分布,其他情况下,该等式只是一个近似值。

1.1 Python可视化风险价值

利用Python对VaR进行可视化,图中阴影部分右侧的临界值就是对应置信水平的VaR,其程序如下:

import numpy as np
import pandas as pd
import scipy.stats as st
'''
st.norm中的子模块
pdf:概率密度函数
cdf:累计概率分布函数
ppf:分位点函数,cdf的反函数
'''

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'] #中文显示问题
plt.rcParams['axes.unicode_minus'] = False #负数显示问题


a = 0.95 #置信水平
z = st.norm.ppf(q=1-a) #返回q对应的分位点
x = np.linspace(-4,4,200) #组合的盈亏数组
y = st.norm.pdf(x) #组合盈亏对应的概率密度数组
x1 = np.linspace(-4,z,100) #组合最小亏损值与返回的分位点构成的盈亏数组
y1 = st.norm.pdf(x1)

plt.figure(figsize=(8,6))
plt.plot(x,y)
plt.fill_between(x1, y1)
plt.grid('True')

2. VaR值的测度方法

2.1 方差-协方差法

数学假定:

1 投资组合的各风险因子服从联合正态分布

2 线性假定,持有期内,投资组合的风险暴露与风险因子之间是线性相关的

其表达式如下:

本文通过一个案例来说明如何运用方差-协方差法计算投资组合的 VaR,该投资组合有 5 个不同的资产构成,投资组合当前的市值为1亿元,其权重权重配比如下表:

案例中投资组合2015年—2018年完整的数据可以通过百度网盘(https://pan.baidu.com/share/init?surl=_koktaATAs5wggwO8U2QRQ)获取,提取码:zbbx。

Python程序如下:

data = pd.read_excel(r'C:\Users\Administrator\Desktop\投资组合配置的资产情况.xlsx',header = 0,index_col = 0)

#初始数据的归一化处理
R = np.log(data/data.shift(1))
#处理缺失数据
R = R.dropna() 

R_mean = R.mean() #计算均值
R_cov = R.cov() #计算协方差
R_corr = R.corr() #计算相关系数
R_vol = R.std() #计算标准差

# 方差协方差方法
def VaR_VCM(value,Rp,Vp,X,N):
    '''
    Parameters
    ----------
    value : 投资组合的价值
    Rp : 投资组合的日收益率
    Vp : 投资组合的日波动率
    X : 置信水平
    N : 持有天数

    '''
    import scipy.stats as st
    import numpy as np

    z = np.abs(st.norm.ppf(q=1-X))

    return np.sqrt(N)*value*(z*Vp-Rp)

weights = np.array([0.15,0.20,0.5,0.05,0.1])
#计算投资组合的期望收益率
Rp_daily = np.sum(weights*R_mean)
#计算投资组合的日波动率
Vp_daily = np.sqrt(np.dot(weights,np.dot(R_cov,weights.T)))

print('投资组合日收益率:',Rp_daily)
print('投资组合日波动率:',Vp_daily)

D1 = 1
D2 = 10
X1 = 0.99
X2 = 0.95
value_port = 100000000

VaR99_1day_VCM = VaR_VCM(value=value_port, Rp=Rp_daily, Vp=Vp_daily, X=X1, N=D1)
VaR99_10day_VCM = VaR_VCM(value=value_port, Rp=Rp_daily, Vp=Vp_daily, X=X1, N=D2)
VaR95_1day_VCM = VaR_VCM(value=value_port, Rp=Rp_daily, Vp=Vp_daily, X=X2, N=D1)
VaR95_10day_VCM = VaR_VCM(value=value_port, Rp=Rp_daily, Vp=Vp_daily, X=X2, N=D2)

print('1天、99%的VaR:',VaR99_1day_VCM)
print('10天、99%的VaR:',VaR99_10day_VCM)  
print('1天、95%的VaR:',VaR95_1day_VCM)
print('10天、99%的VaR:',VaR95_10day_VCM)

计算结果表明:持有期10天、置信水平99%的VaR=464.34万;持有期10天、置信水平95%的VaR=325.83万。

2.2 历史模拟法

历史模拟法:从当前回溯一定时期投资组合的历史盈亏,并把历史盈亏按照由大到小的顺序排列,从中找出符合给定置信水平的盈亏值。例如:1天、置信水平95%的VaR,把历史盈亏由大到小排列,VaR为95%的位置对应盈亏值的绝对值,或者由小到大排列,VaR为5%位置对应盈亏值的绝对值。

本文仍然使用上述案例数据进行说明,其Python程序如下:

#各资产配置
value_asset = value_port*weights
#历史交易日投资组合的盈亏值
Return_history = np.dot(R,value_asset)
Return_history = pd.DataFrame(Return_history,index=R.index,columns=['投资组合模拟日收益'])

#盈亏数据描述
Return_history.describe()
Return_history.plot()

#盈亏数据分布直方图
plt.hist(Return_history,bins=30)
plt.grid('True')

#投资组合盈亏值的正态性检验
#KS检验,返回统计量及P值
st.kstest(rvs=Return_history['投资组合模拟日收益'], cdf='norm')   
#AD检验,返回统计量、显著性水平对应的临界值(统计量)、显著性水平
st.anderson(x=Return_history['投资组合模拟日收益'], dist='norm')   
#返回统计量及P值
st.shapiro(Return_history['投资组合模拟日收益'])   
#返回统计量及P值
st.normaltest(Return_history['投资组合模拟日收益'])

由频数分布直方图、正态性检验的P值(P<1%)结果可知,投资组合的日收益数据不服从正态分布,运用方差—协方差方法计算的投资组合VaR值会存在偏差。使用历史模拟法的计算程序如下:

#计算历史模拟的VaR
VaR99_1day_history = np.abs(np.percentile(a=Return_history['投资组合模拟日收益'],q=(1-X1)*100))
VaR95_1day_history = np.abs(np.percentile(a=Return_history['投资组合模拟日收益'],q=(1-X2)*100))

VaR99_10day_history = np.sqrt(10)*VaR99_1day_history
VaR95_10day_history = np.sqrt(10)*VaR95_1day_history

print('1天、99%的VaR:',VaR99_1day_history)
print('10天、99%的VaR:',VaR99_10day_history)  
print('1天、95%的VaR:',VaR95_1day_history)
print('10天、99%的VaR:',VaR95_10day_history)

计算结果表明:持有期10天、置信水平99%的VaR=675.38万;持有期10天、置信水平95%的VaR=274.21万。

2.3 蒙特卡洛模拟法

蒙特卡洛模拟法又称随机抽样或统计试验方法,即从一个给定的分布中,随机抽取随机数并进行计算,该方法能较好地逼近实际分布情况。

在投资组合的模拟抽样步骤如下:

  • 1 利用第 i 个资产的当前价值(最新价值)加总计算投资组合的当前价值
  • 2 在第 i 个资产价值的日百分比变化所服从的分布中进行一次抽样得到
  • 3 利用抽样获取的计算第 i 个资产下一个交易日的收益金额变动
  • 4 计算本次抽样获取的下一交易日投资组合的盈亏
  • 5 重复上述第2-4步,并将获取的按大小顺序排列,从而构建投资组合在下一交易日的盈亏概率分布。
  • 6 计算持有期1 天、置信水平X 的VaR 值,然后计算

本文仍然使用上述案例数据进行说明,在模拟过程中,需要用到金融资产价格服从的随机过程公式,即

上式中的模拟过程中假定服从 t 分布或者正态分布。

其服从 t 分布的 Python 程序如下:

#蒙特卡洛模拟法
import numpy.random as npr 
I = 10000 #模拟次数
#从学生t分布进行I次模拟
epsilon = npr.standard_t(df=len(R),size=I)

#获取最新收盘价
S1 = data.iloc[-1,0]  #第一个资产的最新价格
S2 = data.iloc[-1,1]  
S3 = data.iloc[-1,2]  
S4 = data.iloc[-1,3]  
S5 = data.iloc[-1,4]  

R_mean = R.mean()*252 #投资组合各资产的年化收益
R_vol = R.std()*np.sqrt(252) #投资组合各资产的年化波动率
dt = 1/252 #年化单个交易日

#模拟投资组合下一个交易日各资产的收盘价
S1_new = S1*np.exp((R_mean[0]-0.5*R_vol[0]**2)*dt + R_vol[0]*epsilon*np.sqrt(dt))
S2_new = S2*np.exp((R_mean[1]-0.5*R_vol[1]**2)*dt + R_vol[1]*epsilon*np.sqrt(dt))
S3_new = S3*np.exp((R_mean[2]-0.5*R_vol[2]**2)*dt + R_vol[2]*epsilon*np.sqrt(dt))
S4_new = S4*np.exp((R_mean[3]-0.5*R_vol[3]**2)*dt + R_vol[3]*epsilon*np.sqrt(dt))
S5_new = S5*np.exp((R_mean[4]-0.5*R_vol[4]**2)*dt + R_vol[4]*epsilon*np.sqrt(dt))

#模拟投资组合下一个交易日各资产的盈亏
S1_delta = (S1_new/S1 - 1)*value_port*weights[0]
S2_delta = (S2_new/S2 - 1)*value_port*weights[1]
S3_delta = (S3_new/S3 - 1)*value_port*weights[2]
S4_delta = (S4_new/S4 - 1)*value_port*weights[3]
S5_delta = (S5_new/S5 - 1)*value_port*weights[4]
#计算投资组合下一个交易日的盈亏
Sp_delta = S1_delta + S2_delta + S3_delta + S4_delta + S5_delta

#下一交易日投资组合盈亏的可视化
plt.figure(figsize=(10,8))
plt.hist(Sp_delta,bins=30)
plt.ylabel('频数')
plt.grid(True)

#蒙特卡洛模拟法计算VaR
VaR99_1day_MS = np.abs(np.percentile(a=Sp_delta,q=(1-X1)*100))    
VaR95_1day_MS = np.abs(np.percentile(a=Sp_delta,q=(1-X2)*100))

VaR99_10day_MS = np.sqrt(10)*VaR99_1day_MS
VaR95_10day_MS = np.sqrt(10)*VaR95_1day_MS

#由于抽样随机数的原因,结果可能会有不同
print('1天、99%的VaR:',VaR99_1day_MS)
print('10天、99%的VaR:',VaR99_10day_MS)  
print('1天、95%的VaR:',VaR95_1day_MS)
print('10天、95%的VaR:',VaR95_10day_MS)

计算结果表明:持有期10天、置信水平99%的VaR=640.81万;持有期10天、置信水平95%的 VaR=436.52 万。

其服从正态分布的 Python 程序如下:

#服从正态分布进行模拟
epsilon_norm = npr.standard_normal(I)

S_new = np.zeros(shape=(I,len(R_mean)))

S1_new = S1*np.exp((R_mean[0]-0.5*R_vol[0]**2)*dt + R_vol[0]*epsilon*np.sqrt(dt))

for i in range(len(R_mean)):
    S_new[:,i] = data.iloc[-1,i]*np.exp((R_mean[i]-0.5*R_vol[i]**2)*dt + R_vol[i]*epsilon_norm*np.sqrt(dt))

S = np.array(data.iloc[-1])

Sp_delta_norm = (np.dot(S_new/S-1,weights))*value_port


plt.figure(figsize=(10,8))
plt.hist(Sp_delta_norm,bins=30)
plt.ylabel('频数')
plt.grid(True)

VaR99_1day_MSnorm = np.abs(np.percentile(a=Sp_delta_norm,q=(1-X1)*100))    
VaR95_1day_MSnorm = np.abs(np.percentile(a=Sp_delta_norm,q=(1-X2)*100))

VaR99_10day_MSnorm = np.sqrt(10)*VaR99_1day_MSnorm
VaR95_10day_MSnorm = np.sqrt(10)*VaR95_1day_MSnorm

print('1天、99%的VaR:',VaR99_1day_MSnorm)
print('10天、99%的VaR:',VaR99_10day_MSnorm)  
print('1天、95%的VaR:',VaR95_1day_MSnorm)
print('10天、95%的VaR:',VaR95_10day_MSnorm)

计算结果表明:持有期10天、置信水平99%的VaR=626.17万;持有期10天、置信水平95%的 VaR=451.86 万。

3. 回溯检验

回溯检验又称为后检验,即通过模型获取的VaR与实际发生的损益进行比较,以检验模型的准确性、可靠性,并据此对模型进行改进及优化。

本文仍然使用上述案例进行说明,其Python程序如下:

#回溯检测
Return_2015 = Return_history.loc['2015-01-01':'2015-12-31']
Return_2016 = Return_history.loc['2016-01-01':'2016-12-31']
Return_2017 = Return_history.loc['2017-01-01':'2017-12-31']
Return_2018 = Return_history.loc['2018-01-01':'2018-12-31']

days_2015 = len(Return_2015)
days_2016 = len(Return_2016)
days_2017 = len(Return_2017)
days_2018 = len(Return_2018)

VaR_2015 = pd.DataFrame(-VaR95_1day_VCM*np.ones_like(Return_2015),index=Return_2015.index)
VaR_2016 = pd.DataFrame(-VaR95_1day_VCM*np.ones_like(Return_2016),index=Return_2016.index)
VaR_2017 = pd.DataFrame(-VaR95_1day_VCM*np.ones_like(Return_2017),index=Return_2017.index)
VaR_2018 = pd.DataFrame(-VaR95_1day_VCM*np.ones_like(Return_2018),index=Return_2018.index)


plt.figure(figsize=(9,15))
plt.subplot(4,1,1)
plt.plot(Return_2015)
plt.plot(VaR_2015)
plt.ylabel('频数')
plt.grid(True)

plt.subplot(4,1,2)
plt.plot(Return_2016)
plt.plot(VaR_2016)
plt.ylabel('频数')
plt.grid(True)

plt.subplot(4,1,3)
plt.plot(Return_2017)
plt.plot(VaR_2017)
plt.ylabel('频数')
plt.grid(True)

plt.subplot(4,1,4)
plt.plot(Return_2018)
plt.plot(VaR_2018)
plt.ylabel('频数')
plt.grid(True)

#计算超出VaR的天数
dayexcept_2015 = len(Return_2015[Return_2015['投资组合模拟日收益']<-VaR95_1day_VCM])
dayexcept_2016 = len(Return_2016[Return_2016['投资组合模拟日收益']<-VaR95_1day_VCM])
dayexcept_2017 = len(Return_2017[Return_2017['投资组合模拟日收益']<-VaR95_1day_VCM])
dayexcept_2018 = len(Return_2018[Return_2018['投资组合模拟日收益']<-VaR95_1day_VCM])    

print('2015年超出风险天数:',dayexcept_2015)
print('2015年超出风险天数在全年的占比:',dayexcept_2015/days_2015)

print('2016年超出风险天数:',dayexcept_2016)
print('2016年超出风险天数在全年的占比:',dayexcept_2016/days_2016)

print('2017年超出风险天数:',dayexcept_2017)
print('2017年超出风险天数在全年的占比:',dayexcept_2017/days_2017)

print('2018年超出风险天数:',dayexcept_2018)
print('2018年超出风险天数在全年的占比:',dayexcept_2018/days_2018)

计算结果表明:2015年超出风险天数为22天,全年占比为9.05%,明显高于5%;2016年超出风险天数为9天,全年占比为3.69%;2017年超出风险天数为1天,全年占比为0.4%;2018年超出风险天数为6天,全年占比为2.47%。

4. 压力VaR

压力测试是一种以定量分析为主的风险分析方法,进而测算在小概率事件及极端情况下可能面临的损失。压力情景通常分为如下两种方法:头脑风暴和历史重现法。

压力风险价值具体是指当市场变量在一定压力市场条件下通过历史模拟法计算得到的风险价值,其计算步骤与历史模拟法相同。

本文仍然使用上述案例进行说明,2015年6月持续数月的股灾及2016年1月初的股市熔断可以看做案例数据中的极端情况。其Python程序如下:

#压力测试
return_stress = Return_history.loc['2015-06-15':'2016-01-07']

return_stress.describe()

return_zero = pd.DataFrame(np.zeros_like(return_stress),index = return_stress.index)

#投资组合盈亏与0的可视化比较
plt.figure(figsize=(8,6))
plt.plot(return_stress)
plt.plot(return_zero)
plt.grid(True)


SVaR99_1day = np.abs(np.percentile(a=return_stress,q=(1-X1)*100))    
SVaR95_1day = np.abs(np.percentile(a=return_stress,q=(1-X2)*100)) 

SVaR99_10day = np.sqrt(10)*SVaR99_1day
SVaR95_10day = np.sqrt(10)*SVaR95_1day

print('1天、99%的VaR:',SVaR99_1day)
print('10天、99%的VaR:',SVaR99_10day)  
print('1天、95%的VaR:',SVaR95_1day)
print('10天、95%的VaR:',SVaR95_10day)

计算结果表明:持有期10天、置信水平99%的压力VaR=1102.12万;持有期10天、置信水平95%的压力VaR=670.14万。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码