Python量化教程:量化風(fēng)險(xiǎn)

今天,我們將介紹非常重要的一部分:風(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)呢今野?我解釋一下方差的原理你就知道了葡公。

\sigma^2(R) = E((R-E(R))^2)

這里R是指所有的收益率序列(真實(shí)或預(yù)估),E(R)是指收益率的期望条霜。有些朋友可能對期望不太熟悉催什,所以我們換個(gè)表達(dá)方式。假如我們有一組已知的長度為n的收益率數(shù)據(jù)R宰睡,那么它們的方差為:

S^2(R) = \frac{1}{n-1} \sum^{n}_{i-1}{(R_i - \overline{R})^2}

相當(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ì)算方差步清,這里我們用numpypandas來示范一下如何計(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ì)算方式為:

\delta(R,MARR) = \sqrt{\frac{1}{n} \sum^{n}_{i=1}{(min(R - MARR, 0))^2}}

也就是說廓推,收益率大于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()
image

然后藤肢,分別計(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)
image

看起來萬科的下行風(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á)為:

Pr(X_t < -Var(\alpha, \Delta{t})) = \alpha \%

其中茂翔,隨機(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)的收益率。

z=\frac{x-\mu}{\sigma}\\ Z_{\alpha} = \frac{\frac{-VaR}{W} - \mu}{\sigma}\\ VaR = -(Z_{\alpha} + \mu)

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)
image

image

可以看到械拍,兩種方法都表明萬科的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)
image

可以看到鄙币,期望虧空是比風(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%惠勒。

image

但是有些時(shí)候我們拿到的數(shù)據(jù)并不是資產(chǎn)價(jià)值的數(shù)據(jù)序列爬坑,而是收益率的序列盾计,那我們應(yīng)該如何計(jì)算最大回撤呢?

從時(shí)刻0到時(shí)刻T的回撤值(這里的回撤值類似基金凈值的回撤值)為:

D(T) = max \left\lbrace 0, \mathop{max}_{t\in{(0,T)}} \prod_{k=1}^{t}{(1 + R_k)} - \prod_{k=1}^{T}{(1+R_k)} \right\rbrace

相應(yīng)的回撤率為:

d(T) = \frac{D(T)}{max_{t \in (0,T)} \prod_{k=1}^{t}(1+R_k)}

用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()
image

在這里我們將交易日期轉(zhuǎn)換為了時(shí)間序列數(shù)據(jù)巍棱,并且作為了我們DataFrame的索引拉盾。然后我們開始求18年以來的收益趨勢:

value = (index_sh.pct_chg / 100 + 1).cumprod()
value.plot();
image

可以看到豁状,幾乎從頭跌到尾……

然后我們開始計(jì)算最大回撤率:

MDD = (value.cummax() - value).max()
print('最大回撤:', MDD)

mdd = ((value.cummax() - value) / value.cummax()).max()
print('最大回撤率:', mdd)
image

可以看到,這里我們計(jì)算的最大回撤率是30.77%霞掺,與剛才我們手動計(jì)算的31.95%并不一致讹躯,為什么呢?

這是因?yàn)槠睿@里我們是使用的收益率數(shù)據(jù)秉馏,而收益率數(shù)據(jù)都是以收盤價(jià)計(jì)算的萝究,這里我們損耗了最高價(jià)、最低價(jià)的信息绕娘,所以我們看到的最大回撤率比實(shí)際情況稍低栽连。不過對于基金凈值、組合資產(chǎn)等舷暮,我們一般也更關(guān)注收盤價(jià)數(shù)據(jù)噩茄,對于盤中的波動相對來說沒有那么重視。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凿菩,隨后出現(xiàn)的幾起案子衅谷,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異堵未,居然都是意外死亡渗蟹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門授艰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來世落,“玉大人岛心,你說我怎么就攤上這事篮灼。” “怎么了髓堪?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵干旁,是天一觀的道長炮沐。 經(jīng)常有香客問我,道長换薄,這世上最難降的妖魔是什么翔试? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任垦缅,我火速辦了婚禮,結(jié)果婚禮上凡恍,老公的妹妹穿的比我還像新娘。我一直安慰自己洽损,他們只是感情好革半,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布又官。 她就那樣靜靜地躺著,像睡著了一般碘赖。 火紅的嫁衣襯著肌膚如雪外构。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天撼班,我揣著相機(jī)與錄音砰嘁,去河邊找鬼勘究。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缅阳,可吹牛的內(nèi)容都是我干的景描。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼说搅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起适肠,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤侯养,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后柠傍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辩稽,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逞泄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年喷众,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘲碧。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖望抽,靈堂內(nèi)的尸體忽然破棺而出煤篙,到底是詐尸還是另有隱情,我是刑警寧澤苛茂,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布鸠窗,位于F島的核電站稍计,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剥哑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一株婴、第九天 我趴在偏房一處隱蔽的房頂上張望暑认。 院中可真熱鬧,春花似錦逻翁、人聲如沸捡鱼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽管引。三九已至闯两,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間重慢,已是汗流浹背逊躁。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工稽煤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轧简。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓吉懊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親借嗽。 傳聞我的和親對象是個(gè)殘疾皇子恶导,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容