通常在金融行业会用日回报率来计算贝塔值,以衡量一家公司的市场风险。我们可以通过价格数据来计算回报率(也称作收益率),有时会需要将日收益每周或者每月收益率,所以接下来主要介绍的就是收益率的计算。计算回报率最重要的就是要明白这些价格的排序。
| import pandas as pd |
| import tushare as ts |
| |
| data = ts.get_k_data('000001') |
| close = np.array(data.close) |
| 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 |
$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: |
| |
| d0 = dt.strptime(i,'%Y-%m-%d') |
| d1 = d0.date() |
| dd.append(d1) |
| |
| da = np.array(dd) |
| |
| |
| ym = [] |
| for i in range(0,np.size(logret)): |
| ym.append(''.join([da[i].strftime("%Y"),da[i].strftime("%m")])) |
| |
| 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线数据来进行计算
方法类似
| |
| 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 |
金融领域常用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.
当某只股票今天的价格接近过去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') |
| wk_data = np.array(wk_data) |
| 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周最高价和最低价的交易策略