首页 > 上网技巧 > 电脑小技巧 > 用Python分析股票的收益和风险

用Python分析股票的收益和风险

时间:2019-12-08 10:00 作者:QQ地带 我要评论

本文将用Python编程,带你了解股票投资收益和风险的基本知识。
 
一、股票的收益
1.1 导入CSV时序数据
本文将分析微软2000年以来的股票交易数据(点我下载哦),它是一个 csv 格式的时间序列数据。你将使用 pandas 读取 csv 数据,并存储为DataFrame格式。
 
# 导入pandas包
import pandas as pd
 
# 读取csv文件,并将‘Date’列解析为日期时间格式,并设为索引
StockPrices = pd.read_csv('MSFTPrices.csv', parse_dates=['Date'], index_col='Date')
 
# 将数据按日期这一列排序(保证后续计算收益率的正确性)
StockPrices = StockPrices.sort_values(by='Date')
 
# 打印数据的前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
该股票数据包括了交易日期、开盘价、最高价、最低价、收盘价、调整后的收盘价以及成交量。其中调整后的收盘价最为重要,它对股票分割、股息和其他公司行为进行了标准化,能真实地反映股票随时间的回报。所以本文后续的计算都是基于调整后的收盘价(Adjusted)这一列数据。
 
1.2 计算收益率
收益率的计算公式如下:
 
 
 
这里可理解为两天的价格差除以前一天的价格。在 pandas 中,使用 .pct_change() 方法来计算收益率。
 
# 增加一列'Returns', 存储每日的收益率
StockPrices['Returns'] = StockPrices['Adjusted'].pct_change()
 
# 检查前5行数据
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
数据框增加了 Returns 一列,即股票的收益。注意第一天的收益率是缺失值 NaN,因为没有前一天的数据用于计算。
为了后续计算方便,我们选取 Returns 这一列,并将缺失值丢弃,存储在新的变量 clean_returns 中。使用 .dropna() 方法来删除缺失值。
 
clean_returns = StockPrices['Returns'].dropna()
绘制每日收益随时间变化的图。
 
# 导入matplotlib绘图包中的pyplot模块
import matplotlib.pyplot as plt
 
#绘图
clean_returns.plot()
plt.show()
 
1.3 收益的均值
均值是最常用的统计量,它将一串数据平均后浓缩为一个数值,但同时也丢失了数据波动性的信息。
 
可使用 numpy 包中的 mean() 函数计算股票历史收益的均值。
 
# 导入numpy包
import numpy as np
 
# 计算股票的日平均收益
mean_return_daily = np.mean(clean_returns)
print("日平均收益:", mean_return_daily)
日平均收益: 0.00037777546435757725
通过以下公式,将日收益率转换为年化收益率(一般假设一年252个交易日),其中  是日平均收益率。
 
 
 
# 计算平均年化收益
mean_return_annualized = ((1 + mean_return_daily)**252) - 1
print("平均年化收益:", mean_return_annualized)
平均年化收益: 0.09985839482858783
1.4 收益的分布
绘制收益的直方图可了解其分布情况,同时也能观察到收益中的异常值。一般在收益分布的两侧有两条长长的尾巴,在投资时一般会尽量避免左侧尾巴上的异常值,因为他们代表了较大的亏损;而分布在右侧尾巴上的异常值通常是件好事,它代表较大的盈利。
 
使用 matplotlib 绘图包中的 hist()函数绘制直方图。
 
# 绘制直方图
plt.hist(clean_returns, bins=75)
plt.show()
 
上图所示的收益是个怎样的分布呢?是正态分布吗?我们将在后续揭晓答案。
 
二、风险的衡量
金融市场的风险是对不确定性的度量,反应在收益的波动上。一般可用以下统计量来表示:
 
方差或标准差
偏度
峰度
接下来我们将逐个计算它们。
 
2.1 方差
方差是对数据离散程度的度量。下图中蓝色分布比红色分布的方差大得多,其数据也更加分散。
 
图片来源:https://en.wikipedia.org/wiki/Standard_deviation
标准差又称均方差,是方差的算数平方根。投资回报中较高的标准差意味着较高的风险,因为数据分布离均值更远了,收益的波动幅度更大。
 
可使用 numpy 包中的 std() 函数计算标准差 ,方差则是标准差的平方 .
 
# 计算标准差
sigma_daily = np.std(clean_returns)
print("标准差: ", sigma_daily)
 
# 计算方差
variance_daily = sigma_daily ** 2
print("方差: ", variance_daily)
标准差:  0.019341100408708328
方差:  0.0003740781650197374
以上计算的是每日的方差,我们可以将之转化成年化方差。将标准差乘以交易日数目的平方根,得到年化标准差。将年化标准差平方,就得到年化方差。
 
# 计算年化标准差
sigma_annualized = sigma_daily*np.sqrt(252)
print("年化标准差:", sigma_annualized)
 
# 计算年化方差
variance_annualized = sigma_annualized ** 2
print("年化方差:", variance_annualized)
年化标准差: 0.3070304505826317
年化方差: 0.09426769758497383
2.2 偏度
偏度是数据分布偏斜方向和程度的度量,反应分布的非对称性。
 
下图所示的曲线分别代表了负偏态和正偏态。在金融领域,人们更倾向于正的偏度,因为这意味着高盈利的概率更大。
 
图片来源:https://en.wikipedia.org/wiki/Skewness
可使用 scipy.stats 提供的 skew() 函数计算收益分布的偏度。
 
# 从 scipy.stats 导入skew函数
from scipy.stats import skew
 
# 计算收益分布的偏度
returns_skewness = skew(clean_returns)
print("偏度:", returns_skewness)
偏度: 0.21935459193067852
回顾之前绘制的收益分布图,乍看之下似乎是对称分布,但经过偏度的计算,我们知道它具有稍许的正偏度。
 
2.3 峰度
峰度表征概率密度分布曲线在平均值处峰值高低的特征数,反映了峰部的尖度。通常将样本的峰度和正态分布相比较,因为正态分布的峰度是3,所以将超出3的部分称为超值峰度。大部分金融收益都具有正的超值峰度。
 
kurtosis.png
使用scipy.stats提供的 kurtosis() 函数计算分布的超值峰度。
 
# 从 scipy.stats 导入 kurtosis 函数
from scipy.stats import kurtosis
 
# 计算收益分布的超值峰度
excess_kurtosis = kurtosis(clean_returns)
print("超值峰度:", excess_kurtosis)
 
# 计算峰度
fourth_moment = excess_kurtosis + 3
print("峰度:", fourth_moment)
超值峰度: 10.31457261802553
峰度: 13.31457261802553
上述峰度的计算结果表明,该股票收益的峰比正态分布高得多。我们也可通过下图概率密度分布的比较看出来,图中橙色代表收益的分布,而蓝色表正态分布。
 
# 模拟正态分布数据,其均值和标准差与文中的股票收益相同。
mu = mean_return_daily
sigma = sigma_daily
norm = np.random.normal(mu, sigma, size=10000)
# 绘制正态分布的概率密度分布图
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')
 
# 增加图例说明
plt.legend()
# 绘图
plt.show()
 
三、收益分布正态性检验
现在让我们回到第一部分结尾提出的问题:该股票的收益分布是正态分布吗?
 
我们知道正态分布是对称的,其偏度为0,而该股票收益具有正的偏度0.219。正态分布的峰度是3,而该股票收益的峰度高达13.31。从这两个统计量看出,该股票收益并不是正态分布,它稍微向右偏斜,并且具有比较尖的峰。
 
但是这就能让我们自信的下结论吗?为了判断股票收益分布的正态性,我们需要使用真正的统计检验方法,而不是简单地检查峰度或偏度。
 
这里使用 scipy.stats 提供的 shapiro() 函数,对股票收益分布进行 Shapiro-Wilk 检验。该函数有两个返回值,一个是检验的t统计量,另一个是p值。现在你并不需要知道 Shapiro-Wilk 检验到底是个什么鬼,只要知道如何使用p值判断数据的正态性:如果p值小于等于0.05,就拒绝正态性假设,得出数据非正态分布的结论。
 
# 从 scipy.stats 导入shapiro
from scipy.stats import shapiro
 
# 对股票收益进行Shapiro-Wilk检验
shapiro_results = shapiro(clean_returns)
print("Shapiro-Wilk检验结果: ", shapiro_results)
 
# 提取P值
p_value = shapiro_results[1]
print("P值: ", p_value)
Shapiro-Wilk检验结果:  (0.9003633260726929, 0.0)
P值:  0.0
计算得到的p值非常小,在目前的精度下等于0,所以我们可以肯定地说该收益分布不是正态分布。
 
小结
本文用Python计算了股票的收益和风险,我们首先查看了股票的收益率及其分布,接着计算指示风险的统计量:方差、偏度和峰度,最后检验了收益分布的正态性。
 
另外我们还学到了以下统计函数:
 
 
import numpy as np
np.mean()   # 均值
np.std()    # 标准差
 
from scipy.stats import skew, kurtosis, shapiro
skew()      # 偏度
kurtosis()  # 超值峰度
shapiro()   # Shapiro-Wilk检验正态性
 
 

标签: Python 股票
顶一下
(0)
0%
踩一下
(0)
0%

Google提供的广告