pythonでValue at Risk (VaR) を計算してみた


この記事はfinancial modeling という本のVaRの章の計算を実際にpythonでおこなったものです。

VaRとは???

VaRとは、"Value at Risk(バリュー・アット・リスク)"の略であり、日本語では「予想最大損失額」と訳されます。元は、金融機関が保有している資産のリスクを評価するために考案されたものです。今現在持っている資産を、今後も一定期間保有(保有期間)し続けたとして、株価や金利などの変動(リスクファクター)にさらされることで、どれくらい損失を被る可能性があるか(信頼水準)を、過去のデータを基に統計的に計測する手法です。なお、「過去のデータ」とは、過去の一定期間(観測期間)に遡って、その間に起きた価格推移のことを指します

例をとって説明します。たとえば今現在あなたが100万円という資産を持っていたとします。このとき「この100万円という資産を、今後5年間保有し続けたとして、株価や金利変動によって失う可能性のある最大金額はいくらか?」といった問いに対する一つの答えを導き出すものがVaRです。その算定の根拠を過去20年なら20年、50年なら50年の統計データに求めるのです。たとえば、「保有期間1年に対してVaRは15万円である」という結果が得られた場合、それは「今後1年間の損失は最大でも15万円以内に収まる可能性がある」という意味になります。このときたとえば「その信頼水準は99%である」という場合、「今後1年以内に損失を被ったとしても、それは99%の確率で15万円以内に収まる」という意味です。逆に言えば、1%の確率で15万以上の損失を被る可能性がある、という意味でもあります。

まとめるとVaRは事前に決めた一定期間においてx%の確率でいくら損失が生じるかという疑問に答えてくれるものである。

資産が一種だけの簡単な例をpythonで計算してみよう

1つの資産からなるポートフォリオを保有しているマネージャーを考えましょう。
大前提として、資産のリターンは平均20%で標準偏差が30%の正規分布に従うとする。
現在のポートフォリオの価値は100百万ドルである。
年末時点のポートフォリオの価値の分布に関して、以下のような種々の簡単な問いに答えたい。

Q1. 年末までに20百万ドルを超える損失が発生する確率は何パーセントか?
Q2. 1%の確率で発生する、年末の最大損失はいくらか?

0.準備(というか問題解くだけならいらない)

この場合、まずは
平均値:100(百万ドル)×1.2(平均収益率が20%なので)=120(百万ドル)
標準偏差:100(百万ドル)×0.3=30(百万ドル)
の正規分布を考える
※正規分布とは

で表される。

%matplotlib inline 
import numpy as np
from scipy.stats import norm
import math
import matplotlib.pyplot as plt
plt.figure(figsize=(10,5))


X = np.arange(0,250,0.1)
#確率密度関数にX,平均50、標準偏差20を代入
Y = norm.pdf(X,120,30)

plt.plot(X,Y,color='r')
plt.show()

<実行結果>
下図は資産のリターンが正規分布に従うとした時の、年末のポートフォリオ価値の確率密度関数を表している。

続いて先ほど求めた確率密度関数に対する累積分布関数を描画してみる

#累積分布関数

x = np.arange(0,250,0.1)
y = []
for i in x:
    y.append(norm.cdf(i, 120, 30))

plt.plot(x, y)
plt.show()

<実行結果>

1. Q1

それでは問題を解いていく。Q1年末までに20(百万ドル)を超える損失が発生する確率は?
これは言い換えれば、年末のポートフォリオ価値が80(百万ドル)未満になる確率を求めればよい。
先ほど描画した累積分布関数をfとするとf(80)を求めればよい

def f(x):
    z = norm.cdf(x, 120, 30) 
    return z
f(80)

0.09121121972586788

よってQ1に対する答えは9.12%である。
言い換えると、ある決まった期間(この場合年末までの)9.12%水準でのポートフォリオのVaRが20(百万ドル)である

2. Q2

1パーセントの確率で発生する最大の損失は幾らかを求める問題だが、これは年末までの1%のVaRを求めることである。前問は年末のポートフォリオが80(百万ドル)を下回る確率を求めたが、今回はX(百万ドル)を下回る確率がちょうど1%であるxを求めよという問題である。
先ほど求めた累積分布関数の逆関数をgとする。

def g(x):
    w = norm.ppf(q=x, loc=120, scale=30)
    return w
g(0.01)

50.20956377877478

よってQ2に対する答えは
120 - 50.21 = 49.79
となる。
この結果は言い換えれば1%水準でのポートフォリオのVaRが49.79であることを意味している。

Excelでやるより楽チン

資産が3種類ある場合

先ほどの例では資産が一種類だけの場合を考えたが、次は資産の種類が複数(3種類)の場合を考える。

3つのリスク資産(X,Y,Z)があると仮定する。資産リターンの分布に関するパラメータは既知であるとして、
リターンの平均は順にUx, Uy, Uz として、
リターンの分散共分散行列Sは

とおく。Sは対称行列である。Sxx ,Syy, Szz はそれぞれX, Y, Z の分散を表しており、
他の成分は、例えばSxy はXとYの共分散を表している。

現在のポートフォリオはXYZ合わせて100(百万ドル)でこの内訳は
X:30百万ドル
Y:45百万ドル
Z:25百万ドル
とする。

このポートフォリオの全資産のリターン分布の平均と分散は
全資産のリターンの平均Ua=x Ux + y Uy + z Uz
全資産のリターンの分散Sa={x, y, z}.S.({x, y, z}.T)
であらわされる。ただし、{x, y, z} は三資産のそれぞれの投資割合を示すベクトルである。
(ここでは= {0.3, 0.25, 0.45})

今回も各資産のリターンが正規分布に従うと仮定する。
各資産のリターンの平均は
Ux = 0.10
Uy = 0.12
Uz = 0.13

分散共分散行列S

$$
\begin{bmatrix}
0.10 & 0.04 & 0.03 \\
0.04 & 0.20& -0.04 \\
0.03 & -0.04 & 0.60
\end{bmatrix}
$$

とする。

全資産のリターン平均

#全資産のリターンの平均Ua
Ua = 0.3*0.10 + 0.25*0.12 + 0.45 * 0.13
Ua

0.1185

全資産のリターンの標準偏差Sa

#3種類の分散共分散行列行列S
S = np.array([[0.10, 0.04, 0.03], 
              [0.04, 0.20, -0.04], 
              [0.03, -0.04, 0.60]])
#ベクトル{x, y ,z}
v = np.array([[0.30], 
              [0.25],
              [0.45]])
#全資産のリターンの標準偏差Sa

Sa = math.sqrt(np.dot(np.dot(v.T,S),v))

0.38483762809787714

よりポートフォリオの価値の平均、ポートフォリオの価値の標準偏差はそれぞれ
100 × (1+ 0.1185)= 111.8500
100 × 0.3848 = 38.4838
である。

各資産のリターンが正規分布に従うことと正規分布の加法性より、資産全体のリターンも正規分布に従う。

累積分布関数を用いて

def g(x):
    w = norm.ppf(q=x, loc=111.85, scale=38.4838)
    return w

g(0.01)

22.323293684987078

より1%水準でのポートフォリオ全体でのVaRは、
100 - 22.3234 = 77.6766

と求まる。

対数正規分布

対数正規分布

多くの資産価格に関して正規分布より合理的な分布である。これまでの例では資産のリターンが正規分布に従うとしましたけど、対数正規分布に従うとして方が現実的な結果が得られるかもしれない。