今天,我們將介紹非常重要的一部分:風(fēng)險(xiǎn)的量化。我們會從原理以及Python實(shí)戰(zhàn)兩個(gè)角度來學(xué)習(xí)盆偿。
我們開始今天的內(nèi)容。
一准浴、方差
1952年,Markowitz發(fā)表了均值-方差投資組合理論捎稚,在這套理論中他正式提出了用方差來描述資產(chǎn)收益不確定性的方法乐横,也就是資產(chǎn)風(fēng)險(xiǎn)的方差度量法。
為什么我們可以用方差來度量風(fēng)險(xiǎn)呢今野?我解釋一下方差的原理你就知道了葡公。
這里R是指所有的收益率序列(真實(shí)或預(yù)估),E(R)是指收益率的期望条霜。有些朋友可能對期望不太熟悉催什,所以我們換個(gè)表達(dá)方式。假如我們有一組已知的長度為n的收益率數(shù)據(jù)R宰睡,那么它們的方差為:
相當(dāng)于每個(gè)收益率數(shù)據(jù)與平均收益率之間距離的平方的均值蒲凶。簡單來說气筋,我們可以理解為收益率相對于均值的波動情況。方差越大旋圆,波動越大宠默,風(fēng)險(xiǎn)也就越大,潛在的收益往往也越高灵巧。
隨著風(fēng)險(xiǎn)理論的實(shí)踐與發(fā)展搀矫,這種方法被發(fā)現(xiàn)了很大的弊端。首先刻肄,這個(gè)定義不能與風(fēng)險(xiǎn)完全等同瓤球,因?yàn)橄蛏系膭×也▌右矔斐煞讲钇撸沁@種波動是我們所希望發(fā)生的敏弃,能使我們獲益卦羡;其次,Markowitz的均值-方差投資組合理論有一個(gè)重要假設(shè)权她,那就是收益率是符合正態(tài)分布的虹茶,但是現(xiàn)實(shí)中的金融產(chǎn)品收益率往往具有明顯的偏度和峰度,僅僅使用方差來度量有可能會產(chǎn)生較大的誤差隅要。
假如我們已經(jīng)獲取到了一組收益率數(shù)據(jù)R蝴罪,在Python中,我們可以很多方法來計(jì)算方差步清,這里我們用numpy
和pandas
來示范一下如何計(jì)算方差和標(biāo)準(zhǔn)差(方差的平方根):
# 使用numpy
import numpy as np
R = [0.01, 0.05, 0.02, -0.03]
var1 = np.var(R)
std1 = np.std(R)
# 使用pandas
import pandas as pd
R = pd.Series([0.01, 0.05, 0.02, -0.03])
var2 = R.var()
std2 = R.std()
二要门、下行風(fēng)險(xiǎn)
同樣是1952年,Roy發(fā)表了用下行偏差來度量風(fēng)險(xiǎn)的方法廓啊。這個(gè)方法解決了前邊我們提到的方差度量法的問題欢搜,它主要關(guān)注向下的波動。計(jì)算下行偏差時(shí)谴轮,一個(gè)最重要的變量就是目標(biāo)收益率炒瘟,通常用可接受的最低收益率代表(MARR,Minimum Acceptable Rate of Return)第步。我們常用無風(fēng)險(xiǎn)收益率疮装、0或者資產(chǎn)收益率的平均值作為MARR。下行偏差描述的就是低于MARR的收益率的發(fā)散程度粘都,其計(jì)算方式為:
也就是說廓推,收益率大于MARR的部分全都會被抹平為0,小于MARR的部分會正常進(jìn)行計(jì)算翩隧。這樣的話樊展,得到的下行偏差中不包含向上波動的成分,僅僅代表了資產(chǎn)價(jià)值下行的風(fēng)險(xiǎn)。包括方差度量法的創(chuàng)始人Markowitz都承認(rèn)下行風(fēng)險(xiǎn)是一個(gè)更好的衡量方式专缠。
那么我們來看一下如何用Python計(jì)算下行風(fēng)險(xiǎn)雷酪,我們先用tushare來獲取萬科和中國平安近兩年的行情數(shù)據(jù)。
import pandas as pd
import tushare as ts
pro = ts.pro_api()
wanke = pro.daily(ts_code='000002.SZ', start_date='20170101')
pingan = pro.daily(ts_code='601318.SH', start_date='20170101')
wanke.head()
然后藤肢,分別計(jì)算萬科和平安的下行風(fēng)險(xiǎn):
def cal_downside_risk(r):
_r = r.map(lambda x: x / 100)
mean = _r.mean()
r_adjust = _r.map(lambda x: min(x-mean, 0))
risk = np.sqrt((r_adjust ** 2).mean())
return risk
wanke_risk = cal_downside_risk(wanke.pct_chg)
pingan_risk = cal_downside_risk(pingan.pct_chg)
print('萬科下行風(fēng)險(xiǎn):', wanke_risk)
print('平安下行風(fēng)險(xiǎn):', pingan_risk)
看起來萬科的下行風(fēng)險(xiǎn)更大一些太闺,因?yàn)樗氖找媛试诰迪路降牟▌痈笠恍T谏线叺拇a中嘁圈,我們先將收益率轉(zhuǎn)換為小數(shù)(tusahre中為了便于觀察省骂,提供了百分點(diǎn)數(shù)據(jù)),然后實(shí)現(xiàn)了我們前邊提供的下行風(fēng)險(xiǎn)計(jì)算公式最住。這部分如果有不能理解的可以留言钞澳。注意,這里函數(shù)的輸入?yún)?shù)是 一個(gè)pandas Series
對象涨缚。
三轧粟、風(fēng)險(xiǎn)價(jià)值
1994年,投行巨頭摩根大通公開發(fā)表了用風(fēng)險(xiǎn)價(jià)值(Value at Risk脓魏,VaR)度量風(fēng)險(xiǎn)的方法兰吟。其定義為:VaR是給定的置信水平和目標(biāo)時(shí)段下預(yù)期的最大損失。用公式表達(dá)為:
其中茂翔,隨機(jī)變量Xt是金融資產(chǎn)或資產(chǎn)組合在時(shí)間段t內(nèi)的價(jià)值變動量混蔼,Pr代表概率,這個(gè)公式的含義是珊燎,在時(shí)間段t內(nèi)惭嚣,我們的損失比VaR(α,t)還大的的概率為α%。也就是說悔政,想要計(jì)算風(fēng)險(xiǎn)價(jià)值晚吞,我們必須要先清楚收益率的概率分布。那么我們?nèi)绾斡?jì)算收益率的概率分布呢谋国?
常見的方法有歷史模擬法槽地、協(xié)方差矩陣法以及蒙特卡洛模擬法。
1. 歷史模擬法
這個(gè)方法最為簡單芦瘾。以單日闷盔、5%置信區(qū)間為例,我們直接取歷史上每天的收益率數(shù)據(jù)旅急,得到其數(shù)據(jù)分布。然后我們找到95%的置信區(qū)間中(在這里取最大的95%即可)最小的那個(gè)收益率牡整,然后乘以我們的初始資產(chǎn)價(jià)值藐吮,就是我們預(yù)估的VaR了。
這種方法假定未來的波動與歷史波動一致,但事實(shí)上金融市場瞬息萬變谣辞,很多風(fēng)險(xiǎn)因素并不能從歷史數(shù)據(jù)中發(fā)掘出來迫摔。歷史模擬法一般需要至少1500個(gè)數(shù)據(jù)樣本,否則會導(dǎo)致VaR不太可靠泥从;另外太過久遠(yuǎn)的數(shù)據(jù)意義也不大句占。
2. 協(xié)方差矩陣法
協(xié)方差矩陣法主要用于投資組合的風(fēng)險(xiǎn)預(yù)估。它假設(shè)各資產(chǎn)的收益率服從正態(tài)分布躯嫉,且各資產(chǎn)的收益率與資產(chǎn)組合的收益率之間呈線性關(guān)系纱烘,這樣投資組合的收益率也服從正態(tài)分布。然后我們通過歷史數(shù)據(jù)中各資產(chǎn)的收益率均值祈餐、方差、協(xié)方差矩陣帆阳,可以估計(jì)出投資組合的均值及方差,這樣就得到了投資組合的收益率分布山宾。
這里由于我們只有投資組合的均值和方差,且我們假設(shè)投資組合的收益率也符合正態(tài)分布鳍徽,所以我們可以通過正態(tài)分布的概率模型來找到VaR。我們對收益率數(shù)據(jù)做過標(biāo)準(zhǔn)化之后可以將其轉(zhuǎn)化為z分?jǐn)?shù)旬盯,z分?jǐn)?shù)是符合標(biāo)準(zhǔn)正態(tài)分布的。然后從分布中找到1-α%的置信區(qū)間內(nèi)的最小值(即α%分位數(shù))胖翰,我們用Zα來表示它接剩,然后將其代入計(jì)算z分?jǐn)?shù)的公式求解出對應(yīng)的收益率。
3. 蒙特卡洛方法
又稱隨機(jī)抽樣或統(tǒng)計(jì)試驗(yàn)方法萨咳,是一種隨機(jī)模擬方法培他。蒙特卡洛方法在模型構(gòu)建合理、參數(shù)選擇正確時(shí)會更加精確可靠舀凛,甚至能處理非線性、收益率非正態(tài)分布的情況猛遍;但是它依賴特定的隨機(jī)過程和所選擇的歷史數(shù)據(jù)号坡,并且產(chǎn)生的隨機(jī)數(shù)據(jù)序列是偽隨機(jī)數(shù)宽堆,可能會導(dǎo)致結(jié)果誤差較大茸习,而且計(jì)算量大、計(jì)算時(shí)間長籽慢。
如果讀者對于自助采樣法(Bootstrap)有所了解的話涕刚,會發(fā)現(xiàn)他們之間有一些關(guān)聯(lián)。蒙特卡洛方法假定了數(shù)據(jù)的分布极景,但是自助法不需要有任何數(shù)據(jù)假設(shè)驾茴,它直接從原始數(shù)據(jù)中進(jìn)行再抽樣。這部分我們暫時(shí)了解即可晨缴,之后會找時(shí)間專門講解峡捡。
那么接下來我們就使用剛才萬科和平安的數(shù)據(jù),用Python來實(shí)戰(zhàn)一下稍途。
# 歷史模擬法
wanke_var = wanke.pct_chg.quantile(0.05) / 100
pingan_var = pingan.pct_chg.quantile(0.05) / 100
print('歷史模擬法')
print('萬科VaR(0.05,1天):', wanke_var)
print('平安VaR(0.05,1天):', pingan_var)
# 協(xié)方差矩陣法
from scipy.stats import norm
wanke_var = norm.ppf(0.05, wanke.pct_chg.mean(),
wanke.pct_chg.std()) / 100
pingan_var = norm.ppf(0.05, pingan.pct_chg.mean(),
pingan.pct_chg.std()) / 100
print('協(xié)方差矩陣法')
print('萬科VaR(0.05,1天):', wanke_var)
print('平安VaR(0.05,1天):', pingan_var)
可以看到械拍,兩種方法都表明萬科的VaR更高装盯,即在95%的置信區(qū)間下埂奈,萬科的最大損失更高。
我們來解釋一下代碼账磺,pandas Series
對象的quantile()
方法會返回分位數(shù),在前邊我們已經(jīng)明確党窜,歷史模擬法計(jì)算VaR直接求0.05分位數(shù)即可幌衣;pandas Series
對象的mean()
方法和std()
方法分別返回其均值和標(biāo)準(zhǔn)差壤玫;scipy.stats.norm
函數(shù)可以根據(jù)我們輸入的置信區(qū)間、均值和標(biāo)準(zhǔn)差來求得對應(yīng)的分位數(shù)楚里。
四猎贴、期望虧空
期望虧空(Expected)是VaR(風(fēng)險(xiǎn)價(jià)值)的變體,是學(xué)術(shù)界提出來用于彌補(bǔ)VaR理論上的缺點(diǎn)达址。前邊我們提到趁耗,風(fēng)險(xiǎn)價(jià)值是1-α%置信區(qū)間內(nèi)最大的虧損苛败,也就是從小到大第α%百分位數(shù)。
那么期望虧空不是第α%位置對應(yīng)的收益率嘀韧,而是最小的α%中所有收益率的均值儡遮。
我們?nèi)匀灰匀f科近兩年的收益率數(shù)據(jù)為例:
VaR_wanke = wanke.pct_chg.quantile(0.05)
ES_wanke = wanke.query('pct_chg <= @VaR_wanke')['pct_chg'].mean()
print('萬科近兩年風(fēng)險(xiǎn)價(jià)值:', VaR_wanke)
print('萬科近兩年期望虧空:', ES_wanke)
可以看到鄙币,期望虧空是比風(fēng)險(xiǎn)價(jià)值更低的。理論上因惭,期望虧空≤風(fēng)險(xiǎn)價(jià)值永遠(yuǎn)成立绩衷。
五激率、最大回撤
最大回撤(Maximum Drawdown勿决,MDD)是非常常用的用來衡量投資(尤其是基金)表現(xiàn)的手段低缩,它代表了投資人可能遇到的最大虧損。最大回撤非常好理解讳推,首先玩般,資產(chǎn)在時(shí)刻t的回撤是指在(0,t)期間的最高峰值到T時(shí)刻的資產(chǎn)價(jià)值Pt之間的回落值究驴;而最大回撤久脯,就是在最高峰值之后一直到T時(shí)刻,中間有一個(gè)最低點(diǎn)跑慕,從峰值到最低點(diǎn)的回落值就是最大回撤摧找〉旁牛回撤值占最高價(jià)值的比例就是回撤率。
比如說惩系,2018年以來A股的最高點(diǎn)是3587.03如筛,上一個(gè)交易日(2019-01-04)的收盤價(jià)為2514.87,那么2019-01-04的回撤率為:(3587.03-2514.87)/3587.03=29.89%晤柄,剛好最低點(diǎn)也出現(xiàn)在2019-01-04妖胀,所以最大回撤率為(3587.03-2440.91)/3587.03=31.95%惠勒。
但是有些時(shí)候我們拿到的數(shù)據(jù)并不是資產(chǎn)價(jià)值的數(shù)據(jù)序列爬坑,而是收益率的序列盾计,那我們應(yīng)該如何計(jì)算最大回撤呢?
從時(shí)刻0到時(shí)刻T的回撤值(這里的回撤值類似基金凈值的回撤值)為:
相應(yīng)的回撤率為:
用LaTeX手打一個(gè)公式太慢了……所以最大回撤即最大回撤率的公式就不給大家展示了,留給大家自己練習(xí)一下涨薪。其算法是找到毛收益率(1+Rt)累乘的最大值炫乓,這里就是峰值了,假設(shè)這一時(shí)刻是k侠姑,那么我們就接著找從k到T之間毛利率累乘的最小值箩做,然后計(jì)算兩者的差異占最高值的比例邦邦,就是最大回撤率了。
多說無益鬼店,我們直接來看代碼實(shí)戰(zhàn)黔龟,還是以上證綜指18年以來的數(shù)據(jù)為例,先獲取數(shù)據(jù):
import pandas as pd
import tushare as ts
pro = ts.pro_api()
index_sh = pro.index_daily(ts_code='000001.SH', start_date='20180101')
index_sh.index = pd.to_datetime(index_sh.trade_date)
index_sh = index_sh.sort_index(ascending=True)
index_sh.head()
在這里我們將交易日期轉(zhuǎn)換為了時(shí)間序列數(shù)據(jù)巍棱,并且作為了我們DataFrame
的索引拉盾。然后我們開始求18年以來的收益趨勢:
value = (index_sh.pct_chg / 100 + 1).cumprod()
value.plot();
可以看到豁状,幾乎從頭跌到尾……
然后我們開始計(jì)算最大回撤率:
MDD = (value.cummax() - value).max()
print('最大回撤:', MDD)
mdd = ((value.cummax() - value) / value.cummax()).max()
print('最大回撤率:', mdd)
可以看到,這里我們計(jì)算的最大回撤率是30.77%霞掺,與剛才我們手動計(jì)算的31.95%并不一致讹躯,為什么呢?
這是因?yàn)槠睿@里我們是使用的收益率數(shù)據(jù)秉馏,而收益率數(shù)據(jù)都是以收盤價(jià)計(jì)算的萝究,這里我們損耗了最高價(jià)、最低價(jià)的信息绕娘,所以我們看到的最大回撤率比實(shí)際情況稍低栽连。不過對于基金凈值、組合資產(chǎn)等舷暮,我們一般也更關(guān)注收盤價(jià)數(shù)據(jù)噩茄,對于盤中的波動相對來說沒有那么重視。