VaR模型 - 用历史模拟法计算VaR#

前言#

VaR模型有多种的计算方法,比较常见的有历史模拟法、方差-协方差法 和 蒙特.卡洛模拟法 ,本文将介绍历史模拟法并计算VaR。

其实用历史模拟法计算VaR的整体思路是,先计算出某只股票某段时间的整体回报率和波动, 然后根据置信区间的百分比,如10%、5%或 1% 来确定最大损失值。

import tushare as ts
import pandas as pd
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
plt.rcParams['font.sans-serif'] = ['SimHei'] 
plt.rcParams['axes.unicode_minus'] = False  

pro = ts.pro_api('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') #这里需要填写你注册好的Tushare的TOKEN凭证
/tmp/ipykernel_2216/3543896033.py:6: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead.
  plt.style.use('seaborn-white')

通过调用tushare获取股票600377(宁沪高速)的股票数据,这里不设置日期,那么默认获取Tushare提供的历史数据。

ticker_data = pro.daily(ts_code='600377.SH')
print('数据量:',len(ticker_data))
ticker_data.head(5)
数据量: 5278
ts_code trade_date open high low close pre_close change pct_chg vol amount
0 600377.SH 20230216 8.10 8.15 8.05 8.07 8.11 -0.04 -0.4932 40840.64 33117.312
1 600377.SH 20230215 8.14 8.15 8.09 8.11 8.13 -0.02 -0.2460 31751.18 25757.239
2 600377.SH 20230214 8.17 8.18 8.12 8.13 8.14 -0.01 -0.1229 45641.97 37190.139
3 600377.SH 20230213 8.18 8.20 8.10 8.14 8.17 -0.03 -0.3672 61499.73 50133.679
4 600377.SH 20230210 8.20 8.21 8.15 8.17 8.22 -0.05 -0.6083 36648.00 29940.740

从上面可以看出,序号并不是以时间作为单位的。那么我们首先需要将trade_date转为datetime格式,然后设置为序号以便于画图。

ticker_data['trade_date'] = pd.to_datetime(ticker_data['trade_date'],format='%Y%m%d')
ticker_data.set_index('trade_date', inplace=True)
returns = ticker_data["close"].pct_change().dropna()

plt.figure(figsize=(15, 5))
plt.title("股票代码:600377 - 宁沪高速", weight='bold')
ticker_data['close'].plot()
<Axes: title={'center': '股票代码:600377 - 宁沪高速'}, xlabel='trade_date'>
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 32929 (\N{CJK UNIFIED IDEOGRAPH-80A1}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 31080 (\N{CJK UNIFIED IDEOGRAPH-7968}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 20195 (\N{CJK UNIFIED IDEOGRAPH-4EE3}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 30721 (\N{CJK UNIFIED IDEOGRAPH-7801}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 23425 (\N{CJK UNIFIED IDEOGRAPH-5B81}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 27818 (\N{CJK UNIFIED IDEOGRAPH-6CAA}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 39640 (\N{CJK UNIFIED IDEOGRAPH-9AD8}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 36895 (\N{CJK UNIFIED IDEOGRAPH-901F}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 32929 (\N{CJK UNIFIED IDEOGRAPH-80A1}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 31080 (\N{CJK UNIFIED IDEOGRAPH-7968}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 20195 (\N{CJK UNIFIED IDEOGRAPH-4EE3}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 30721 (\N{CJK UNIFIED IDEOGRAPH-7801}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 23425 (\N{CJK UNIFIED IDEOGRAPH-5B81}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 27818 (\N{CJK UNIFIED IDEOGRAPH-6CAA}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 39640 (\N{CJK UNIFIED IDEOGRAPH-9AD8}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 36895 (\N{CJK UNIFIED IDEOGRAPH-901F}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
../_images/historical-VaR_6_2.png

下面将画出每日收盘价的百分比变化图:

plt.figure(figsize=(15, 5))
ticker_data["close"].pct_change().plot()
plt.title("股票代码:600377 - 宁沪高速", weight='bold');
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 32929 (\N{CJK UNIFIED IDEOGRAPH-80A1}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 31080 (\N{CJK UNIFIED IDEOGRAPH-7968}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 20195 (\N{CJK UNIFIED IDEOGRAPH-4EE3}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 30721 (\N{CJK UNIFIED IDEOGRAPH-7801}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 23425 (\N{CJK UNIFIED IDEOGRAPH-5B81}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 27818 (\N{CJK UNIFIED IDEOGRAPH-6CAA}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 39640 (\N{CJK UNIFIED IDEOGRAPH-9AD8}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/events.py:89: UserWarning: Glyph 36895 (\N{CJK UNIFIED IDEOGRAPH-901F}) missing from current font.
  func(*args, **kwargs)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 32929 (\N{CJK UNIFIED IDEOGRAPH-80A1}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 31080 (\N{CJK UNIFIED IDEOGRAPH-7968}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 20195 (\N{CJK UNIFIED IDEOGRAPH-4EE3}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 30721 (\N{CJK UNIFIED IDEOGRAPH-7801}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 23425 (\N{CJK UNIFIED IDEOGRAPH-5B81}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 27818 (\N{CJK UNIFIED IDEOGRAPH-6CAA}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 39640 (\N{CJK UNIFIED IDEOGRAPH-9AD8}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 36895 (\N{CJK UNIFIED IDEOGRAPH-901F}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
../_images/historical-VaR_8_1.png

从上面可以看出,由于A股市场的每日涨跌幅限制,可以看到宁沪高速最大的涨跌幅为10%, 但其中有一个数据是超出10%(介于2016年至2017年坐标轴之间),估计是高开涨停。上图也可以理解为股票收益的波动图.

历史模拟法计算VaR#

在险百分比#

#### 计算百分比VaR对应的在险百分比
VaR_90 = returns.quantile(0.1)
VaR_95 = returns.quantile(0.05)
VaR_99 = returns.quantile(0.01)
VaR_9999 = returns.quantile(0.001)

h_VaR = {'90%':VaR_90, '95%':VaR_95,'99%':VaR_99,'99.99%':VaR_9999}
pd.DataFrame.from_dict(h_VaR, orient='index',columns=['在险损失(VaR)'])
在险损失(VaR)
90% -0.018353
95% -0.026685
99% -0.051169
99.99% -0.090775

在险绝对金额#

假设你的投资金额为100万,那么用绝对值来算,那么:

invest =100
VaR_90 = returns.quantile(0.1)*invest
VaR_95 = returns.quantile(0.05)*invest
VaR_99 = returns.quantile(0.01)*invest
VaR_9999 = returns.quantile(0.001)*invest

h_VaR = {'90%':VaR_90, '95%':VaR_95,'99%':VaR_99,'99.99%':VaR_9999}
pd.DataFrame.from_dict(h_VaR, orient='index',columns=['在险损失(金额)'])
在险损失(金额)
90% -1.835259
95% -2.668450
99% -5.116866
99.99% -9.077542

解释

假设你投资了100万股票600377(宁沪高速),你单日的投资损失有90%的机率会少于1.85万;你单日的投资损失有95%的机率会少于2.70万;你单日的投资损失有99%的机率会少于5.13万;你单日的投资损失有99.99%的机率会少于9.08万。

# 假设置信区间为95%
varg = np.percentile(returns, 5)

#柱状图
plt.figure(figsize=(15, 5))
plt.hist(returns,bins=50, density=True)
plt.xlabel('回报率')
plt.ylabel('频率')
plt.title(r'收益柱状图', fontsize=18, fontweight='bold')
plt.axvline(x=varg, color='r', linestyle='--', label='95% 置信区间 VaR: ' + "{0:.2f}%".format(varg * 100))
plt.legend(loc='upper right')
plt.show()  

print ("你单日的最大投资损失有95%的机率会少于" + "{0:.2f}%".format(np.percentile(returns, 5) * 100))
print(" 占" + str(len(returns)) + " 天中的" + "{0:.2f}".format(.05*len(returns)) + "天")
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 39057 (\N{CJK UNIFIED IDEOGRAPH-9891}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 26609 (\N{CJK UNIFIED IDEOGRAPH-67F1}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 29366 (\N{CJK UNIFIED IDEOGRAPH-72B6}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 22270 (\N{CJK UNIFIED IDEOGRAPH-56FE}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 22238 (\N{CJK UNIFIED IDEOGRAPH-56DE}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 25253 (\N{CJK UNIFIED IDEOGRAPH-62A5}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 32622 (\N{CJK UNIFIED IDEOGRAPH-7F6E}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 20449 (\N{CJK UNIFIED IDEOGRAPH-4FE1}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 21306 (\N{CJK UNIFIED IDEOGRAPH-533A}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
/opt/hostedtoolcache/Python/3.8.16/x64/lib/python3.8/site-packages/IPython/core/pylabtools.py:152: UserWarning: Glyph 38388 (\N{CJK UNIFIED IDEOGRAPH-95F4}) missing from current font.
  fig.canvas.print_figure(bytes_io, **kw)
../_images/historical-VaR_17_1.png
你单日的最大投资损失有95%的机率会少于-2.67%
 占5277 天中的263.85天