本文將用Python編程涯贞,帶你了解股票投資收益和風(fēng)險(xiǎn)的基本知識(shí)均践。
一椒袍、股票的收益
1.1 導(dǎo)入CSV時(shí)序數(shù)據(jù)
本文將分析微軟2000年以來(lái)的股票交易數(shù)據(jù)(點(diǎn)我下載哦)藕施,它是一個(gè) csv 格式的時(shí)間序列數(shù)據(jù)寇损。你將使用 pandas 讀取 csv 數(shù)據(jù),并存儲(chǔ)為DataFrame格式裳食。
# 導(dǎo)入pandas包
import pandas as pd
# 讀取csv文件矛市,并將‘Date’列解析為日期時(shí)間格式,并設(shè)為索引
StockPrices = pd.read_csv('MSFTPrices.csv', parse_dates=['Date'], index_col='Date')
# 將數(shù)據(jù)按日期這一列排序(保證后續(xù)計(jì)算收益率的正確性)
StockPrices = StockPrices.sort_values(by='Date')
# 打印數(shù)據(jù)的前5行
print(StockPrices.head())
Open High Low Close Volume Adjusted
Date
2000-01-03 88.777 89.722 84.712 58.28125 53228400 38.527809
2000-01-04 85.893 88.588 84.901 56.31250 54119000 37.226345
2000-01-05 84.050 88.021 82.726 56.90625 64059600 37.618851
2000-01-06 84.853 86.130 81.970 55.00000 54976600 36.358688
2000-01-07 82.159 84.901 81.166 55.71875 62013600 36.833828
該股票數(shù)據(jù)包括了交易日期、開盤價(jià)诲祸、最高價(jià)浊吏、最低價(jià)、收盤價(jià)救氯、調(diào)整后的收盤價(jià)以及成交量找田。其中調(diào)整后的收盤價(jià)最為重要,它對(duì)股票分割着憨、股息和其他公司行為進(jìn)行了標(biāo)準(zhǔn)化墩衙,能真實(shí)地反映股票隨時(shí)間的回報(bào)。所以本文后續(xù)的計(jì)算都是基于調(diào)整后的收盤價(jià)(Adjusted)這一列數(shù)據(jù)。
1.2 計(jì)算收益率
收益率的計(jì)算公式如下:
這里可理解為兩天的價(jià)格差除以前一天的價(jià)格漆改。在 pandas 中心铃,使用 .pct_change()
方法來(lái)計(jì)算收益率。
# 增加一列'Returns', 存儲(chǔ)每日的收益率
StockPrices['Returns'] = StockPrices['Adjusted'].pct_change()
# 檢查前5行數(shù)據(jù)
print(StockPrices.head())
Open High Low Close Volume Adjusted Returns
Date
2000-01-03 88.777 89.722 84.712 58.28125 53228400 38.527809 NaN
2000-01-04 85.893 88.588 84.901 56.31250 54119000 37.226345 -0.033780
2000-01-05 84.050 88.021 82.726 56.90625 64059600 37.618851 0.010544
2000-01-06 84.853 86.130 81.970 55.00000 54976600 36.358688 -0.033498
2000-01-07 82.159 84.901 81.166 55.71875 62013600 36.833828 0.013068
數(shù)據(jù)框增加了 Returns 一列挫剑,即股票的收益去扣。注意第一天的收益率是缺失值 NaN,因?yàn)闆]有前一天的數(shù)據(jù)用于計(jì)算樊破。
為了后續(xù)計(jì)算方便愉棱,我們選取 Returns 這一列,并將缺失值丟棄哲戚,存儲(chǔ)在新的變量 clean_returns 中奔滑。使用 .dropna()
方法來(lái)刪除缺失值。
clean_returns = StockPrices['Returns'].dropna()
繪制每日收益隨時(shí)間變化的圖惫恼。
# 導(dǎo)入matplotlib繪圖包中的pyplot模塊
import matplotlib.pyplot as plt
#繪圖
clean_returns.plot()
plt.show()
1.3 收益的均值
均值是最常用的統(tǒng)計(jì)量,它將一串?dāng)?shù)據(jù)平均后濃縮為一個(gè)數(shù)值澳盐,但同時(shí)也丟失了數(shù)據(jù)波動(dòng)性的信息祈纯。
可使用 numpy 包中的 mean()
函數(shù)計(jì)算股票歷史收益的均值。
# 導(dǎo)入numpy包
import numpy as np
# 計(jì)算股票的日平均收益
mean_return_daily = np.mean(clean_returns)
print("日平均收益:", mean_return_daily)
日平均收益: 0.00037777546435757725
通過(guò)以下公式叼耙,將日收益率轉(zhuǎn)換為年化收益率(一般假設(shè)一年252個(gè)交易日)腕窥,其中 是日平均收益率。
# 計(jì)算平均年化收益
mean_return_annualized = ((1 + mean_return_daily)**252) - 1
print("平均年化收益:", mean_return_annualized)
平均年化收益: 0.09985839482858783
1.4 收益的分布
繪制收益的直方圖可了解其分布情況筛婉,同時(shí)也能觀察到收益中的異常值簇爆。一般在收益分布的兩側(cè)有兩條長(zhǎng)長(zhǎng)的尾巴,在投資時(shí)一般會(huì)盡量避免左側(cè)尾巴上的異常值爽撒,因?yàn)樗麄兇砹溯^大的虧損入蛆;而分布在右側(cè)尾巴上的異常值通常是件好事,它代表較大的盈利硕勿。
使用 matplotlib 繪圖包中的 hist()
函數(shù)繪制直方圖哨毁。
# 繪制直方圖
plt.hist(clean_returns, bins=75)
plt.show()
上圖所示的收益是個(gè)怎樣的分布呢?是正態(tài)分布嗎源武?我們將在后續(xù)揭曉答案扼褪。
二、風(fēng)險(xiǎn)的衡量
金融市場(chǎng)的風(fēng)險(xiǎn)是對(duì)不確定性的度量粱栖,反應(yīng)在收益的波動(dòng)上话浇。一般可用以下統(tǒng)計(jì)量來(lái)表示:
- 方差或標(biāo)準(zhǔn)差
- 偏度
- 峰度
接下來(lái)我們將逐個(gè)計(jì)算它們。
2.1 方差
方差是對(duì)數(shù)據(jù)離散程度的度量闹究。下圖中藍(lán)色分布比紅色分布的方差大得多幔崖,其數(shù)據(jù)也更加分散。
標(biāo)準(zhǔn)差又稱均方差,是方差的算數(shù)平方根岖瑰。投資回報(bào)中較高的標(biāo)準(zhǔn)差意味著較高的風(fēng)險(xiǎn)叛买,因?yàn)閿?shù)據(jù)分布離均值更遠(yuǎn)了,收益的波動(dòng)幅度更大蹋订。
可使用 numpy 包中的 std()
函數(shù)計(jì)算標(biāo)準(zhǔn)差 率挣,方差則是標(biāo)準(zhǔn)差的平方 .
# 計(jì)算標(biāo)準(zhǔn)差
sigma_daily = np.std(clean_returns)
print("標(biāo)準(zhǔn)差: ", sigma_daily)
# 計(jì)算方差
variance_daily = sigma_daily ** 2
print("方差: ", variance_daily)
標(biāo)準(zhǔn)差: 0.019341100408708328
方差: 0.0003740781650197374
以上計(jì)算的是每日的方差,我們可以將之轉(zhuǎn)化成年化方差露戒。將標(biāo)準(zhǔn)差乘以交易日數(shù)目的平方根椒功,得到年化標(biāo)準(zhǔn)差。將年化標(biāo)準(zhǔn)差平方智什,就得到年化方差动漾。
# 計(jì)算年化標(biāo)準(zhǔn)差
sigma_annualized = sigma_daily*np.sqrt(252)
print("年化標(biāo)準(zhǔn)差:", sigma_annualized)
# 計(jì)算年化方差
variance_annualized = sigma_annualized ** 2
print("年化方差:", variance_annualized)
年化標(biāo)準(zhǔn)差: 0.3070304505826317
年化方差: 0.09426769758497383
2.2 偏度
偏度是數(shù)據(jù)分布偏斜方向和程度的度量,反應(yīng)分布的非對(duì)稱性荠锭。
下圖所示的曲線分別代表了負(fù)偏態(tài)和正偏態(tài)旱眯。在金融領(lǐng)域,人們更傾向于正的偏度证九,因?yàn)檫@意味著高盈利的概率更大删豺。
可使用 scipy.stats 提供的 skew()
函數(shù)計(jì)算收益分布的偏度。
# 從 scipy.stats 導(dǎo)入skew函數(shù)
from scipy.stats import skew
# 計(jì)算收益分布的偏度
returns_skewness = skew(clean_returns)
print("偏度:", returns_skewness)
偏度: 0.21935459193067852
回顧之前繪制的收益分布圖愧怜,乍看之下似乎是對(duì)稱分布呀页,但經(jīng)過(guò)偏度的計(jì)算,我們知道它具有稍許的正偏度拥坛。
2.3 峰度
峰度表征概率密度分布曲線在平均值處峰值高低的特征數(shù)蓬蝶,反映了峰部的尖度。通常將樣本的峰度和正態(tài)分布相比較猜惋,因?yàn)檎龖B(tài)分布的峰度是3丸氛,所以將超出3的部分稱為超值峰度。大部分金融收益都具有正的超值峰度著摔。
使用scipy.stats提供的 kurtosis()
函數(shù)計(jì)算分布的超值峰度雪位。
# 從 scipy.stats 導(dǎo)入 kurtosis 函數(shù)
from scipy.stats import kurtosis
# 計(jì)算收益分布的超值峰度
excess_kurtosis = kurtosis(clean_returns)
print("超值峰度:", excess_kurtosis)
# 計(jì)算峰度
fourth_moment = excess_kurtosis + 3
print("峰度:", fourth_moment)
超值峰度: 10.31457261802553
峰度: 13.31457261802553
上述峰度的計(jì)算結(jié)果表明,該股票收益的峰比正態(tài)分布高得多梨撞。我們也可通過(guò)下圖概率密度分布的比較看出來(lái)雹洗,圖中橙色代表收益的分布,而藍(lán)色表正態(tài)分布卧波。
# 模擬正態(tài)分布數(shù)據(jù)时肿,其均值和標(biāo)準(zhǔn)差與文中的股票收益相同。
mu = mean_return_daily
sigma = sigma_daily
norm = np.random.normal(mu, sigma, size=10000)
# 繪制正態(tài)分布的概率密度分布圖
plt. hist(norm, bins=100, alpha=0.8, density=True, label='Normal Distribution')
# 繪制收益的概率密度分布圖
plt.hist(clean_returns, bins=75, alpha=0.7, density=True, label='Returns')
# 增加圖例說(shuō)明
plt.legend()
# 繪圖
plt.show()
三港粱、收益分布正態(tài)性檢驗(yàn)
現(xiàn)在讓我們回到第一部分結(jié)尾提出的問(wèn)題:該股票的收益分布是正態(tài)分布嗎螃成?
我們知道正態(tài)分布是對(duì)稱的旦签,其偏度為0,而該股票收益具有正的偏度0.219寸宏。正態(tài)分布的峰度是3宁炫,而該股票收益的峰度高達(dá)13.31。從這兩個(gè)統(tǒng)計(jì)量看出氮凝,該股票收益并不是正態(tài)分布羔巢,它稍微向右偏斜,并且具有比較尖的峰罩阵。
但是這就能讓我們自信的下結(jié)論嗎竿秆?為了判斷股票收益分布的正態(tài)性,我們需要使用真正的統(tǒng)計(jì)檢驗(yàn)方法稿壁,而不是簡(jiǎn)單地檢查峰度或偏度幽钢。
這里使用 scipy.stats 提供的 shapiro()
函數(shù),對(duì)股票收益分布進(jìn)行 Shapiro-Wilk 檢驗(yàn)傅是。該函數(shù)有兩個(gè)返回值匪燕,一個(gè)是檢驗(yàn)的t統(tǒng)計(jì)量,另一個(gè)是p值⌒剩現(xiàn)在你并不需要知道 Shapiro-Wilk 檢驗(yàn)到底是個(gè)什么鬼帽驯,只要知道如何使用p值判斷數(shù)據(jù)的正態(tài)性:如果p值小于等于0.05,就拒絕正態(tài)性假設(shè)溃斋,得出數(shù)據(jù)非正態(tài)分布的結(jié)論界拦。
# 從 scipy.stats 導(dǎo)入shapiro
from scipy.stats import shapiro
# 對(duì)股票收益進(jìn)行Shapiro-Wilk檢驗(yàn)
shapiro_results = shapiro(clean_returns)
print("Shapiro-Wilk檢驗(yàn)結(jié)果: ", shapiro_results)
# 提取P值
p_value = shapiro_results[1]
print("P值: ", p_value)
Shapiro-Wilk檢驗(yàn)結(jié)果: (0.9003633260726929, 0.0)
P值: 0.0
計(jì)算得到的p值非常小吸申,在目前的精度下等于0梗劫,所以我們可以肯定地說(shuō)該收益分布不是正態(tài)分布。
小結(jié)
本文用Python計(jì)算了股票的收益和風(fēng)險(xiǎn)截碴,我們首先查看了股票的收益率及其分布梳侨,接著計(jì)算指示風(fēng)險(xiǎn)的統(tǒng)計(jì)量:方差、偏度和峰度日丹,最后檢驗(yàn)了收益分布的正態(tài)性走哺。
另外我們還學(xué)到了以下統(tǒng)計(jì)函數(shù):
import numpy as np
np.mean() # 均值
np.std() # 標(biāo)準(zhǔn)差
from scipy.stats import skew, kurtosis, shapiro
skew() # 偏度
kurtosis() # 超值峰度
shapiro() # Shapiro-Wilk檢驗(yàn)正態(tài)性
如果你想自己下載股票數(shù)據(jù)的話,可以參考這篇文章 《如何用Python下載金融數(shù)據(jù)》哲虾。
注:本文是 DataCamp 課程 Intro to Portfolio Risk Management in Python 的學(xué)習(xí)筆記丙躏。