统计分析
1、计算回报率
通常在金融行业会用日回报率来计算贝塔值,以衡量一家公司的市场风险。我们可以通过价格数据来计算回报率(也称作收益率),有时会需要将日收益每周或者每月收益率,所以接下来主要介绍的就是收益率的计算。计算回报率最重要的就是要明白这些价格的排序。
import pandas as pd
import tushare as ts
data = ts.get_k_data('000001') # 获取平安的k线数据
close = np.array(data.close) # 转换为ndarray数组,以便做批量计算
ret = (close[1:]-close[:-1])/close[:-1]
ret[0:2]
运行结果:
array([0.00775724, 0.00441476])
# 验证回报率:
> data.date[0:3]
>:
0 2016-08-05
1 2016-08-08
2 2016-08-09
Name: date, dtype: object
> data.close[0:3]
>:
0 8.766
1 8.834
2 8.873
Name: close, dtype: float64
> (8.834-8.766)/8.766
> 0.007757243896874243
1.1、从日回报率计算月回报率
$P_0$为上个月最后一个交易日的收盘价,$P_1$是这个月第一个交易日的收盘价。
月回报率:
$$
R{monthly} = \frac {P{20} – P_0} {P0}
$$
月对数回报率:
$$
logreturn{monthly} = log({\frac {P_{20}}{P_0}})
$$
日对数回报率:
$$
logreturn^{daily}_i = log({\frac{Pi}{P{i-1}}})
$$
百分比回报率和对数回报率之间的关系:
$$
R{monthly} = exp(logreturn) – 1
$$
对数回报率的总和:
$$
logreturn{monthly} = log({\frac{P_{20}}{P0}}) = \displaystyle \sum^{20}{i=1}logreturn^{daily}_i
$$
# 对数回报率
logret = np.log(close[1:]/close[:-1])
# 处理时间格式
dd = []
for dt in data.date:
# 字符串格式的时间对象只有先转换为datetime格式才能进行转换到date格式
d0 = dt.strptime(i,'%Y-%m-%d') # 转换为datetime.datetime格式
d1 = d0.date() # 转换为datetime.date格式
dd.append(d1)
# 将新列表转换为ndarray数组
da = np.array(dd)
# 月回报率
ym = []
for i in range(0,np.size(logret)):
ym.append(''.join([da[i].strftime("%Y"),da[i].strftime("%m")]))
# 通过pandas进行批量计算
y = pd.DataFrame(logret,ym,columns=['ret_monthly'])
ret_monthly = y.groupby(y.index).sum()
ret_monthly
运行结果:
ret_monthly
201608 0.044402
201609 -0.035544
201610 0.002146
201611 0.049096
201612 -0.046842
...
201811 -0.022410
201812 -0.141794
201901 0.197798
201902 0.130401
201903 -0.053110
以上程序依旧通过获取的平安的K线数据来进行计算
1.2、从日回报率计算年回报率
方法类似
# 年回报率
date = []
for i in range(0,np.size(logret)):
date.append(''.join([da[i].strftime("%Y")]))
y = pd.DataFrame(logret,date,columns=['ret_annual'])
ret_annual = np.exp(y.groupby(y.index).sum())-1
运行结果:
ret_annual
2016 0.013347
2017 0.517730
2018 -0.318350
2019 0.316649
2、T-检验
金融领域常用t-统计量来检验某个零假设。当零假设成立时,t-统计量服从t分布。
以下的代码生成1000个服从标准正态分布的随机数,然后进行两个检验。第一个检验的零假设是均值为0.5,第2个检验的零假设是均值为0.
from scipy import stats
import scipy as sp
import tushare as ts
import numpy as np
sp.random.seed(1235)
x = stats.norm.rvs(size=1000)
plt.figure(figsize=(7,4))
# 分别为两条数据添加图例
plt.plot(x,lw=1.0,label='1st')
plt.grid(True) # 网格设置
plt.legend(loc=0) # 图例标签位置设置
plt.axis('tight')
plt.xlabel('index')
plt.ylabel('value')
图例:
print(stats.ttest_1samp(x,0.5))
print(stats.ttest_1samp(x,0))
运行结果:
Ttest_1sampResult(statistic=-16.755214405175575, pvalue=1.0140316700193316e-55)
Ttest_1sampResult(statistic=-1.1953686865174769, pvalue=0.23222669336297136)
测试中国平安的平均日回报率是否为0
data = ts.get_k_data('000001')
pa_data_close = np.array(data.close)
ret = pa_data_close[1:]/pa_data_close[:-1] - 1
print(round(sp.mean(ret),5),stats.ttest_1samp(ret,0))
运行结果:
0.00065 Ttest_1sampResult(statistic=0.9167715496440845, pvalue=0.35960876859507807)
结果显示中国平安的平均日回报率为0.065%,t值是0.92而p值是0.36。所以,统计检验的结果不支持平均日回报率等于0.
3、基于52周最高价和最低价的交易策略
当某只股票今天的价格接近过去52周的最高价格,卖出该股票;当其今天得价格接近过去52周达到的最低价格,买入该股票。
import tushare as ts
from datetime import datetime
import numpy as np
wk_data = ts.get_k_data("000002",start='2018-01-01',end='2018-12-30') # 获取万科地产2018一年的K线数据
wk_data = np.array(wk_data) # 转换为ndarray数组
wk_data_1 = wk_data[-1]
y = np.array(wk_data.tolist())[:,-3] # 最低价
aa = y.astype(np.float)
high = max(aa) # 算出一年中最高的
low = min(aa) # 算出一年中最低的
print("""
today price high low from low
%s %s %s %s %s
"""%(wk_data_1[0],wk_data_1[1],high,low,round((wk_data_1[-3]-low)/(high-low)*100,2)))
运行结果:
today price high low from low
2019-04-19 30.61 38.939 9.964 70.74
根据过去52周最高价和最低价的交易策略