日收益率和累计收益

来源:互联网 发布:淘宝店铺怎么取消推广 编辑:程序博客网 时间:2024/04/26 14:19
在测试数据上计算日收益率和对数收益率,和基于两种收益率的累计收益率,比较了一下两种累计收益率,通过每天日收益率累计计算是在python金融数据分析中看到的,另一种是佐治亚理工公开课cs7646中介绍的一种方法,用当前的价格比上第一天买入的价格,在减去一
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt#import pandas_datareader.data as web (现在不太好用)import tushare as ts
# 结束日期为空的话默认为当前日期sz50 = ts.get_k_data('sz50',start='2004-01-01')#通过网络获取上证指数的历史数据,通过info方法查看数据的基本信息sz50.info()#重新指定索引列sz50 = sz50.set_index('date')sz50[:3]
#画出上证指数的收盘价格的时序图,指定网格和长宽比例%matplotlib inlinesz50['close'].plot(grid = True, figsize=(15,7))
![png](output_2_1.png)![这里写图片描述](http://img.blog.csdn.net/20170620222129364?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI4MTM5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
#实现两个趋势策略,期间指数水平移动平均数,分别是两个月(42天),一年(252天).一年只有252个交易日# pandas可以简单实现移动平均值的计算# np.round(),对序列中的数据按照指定的精度进行四舍五入# pd.rolling_mean() 计算移动平均值,这是老语法# 新操作: Series.rolling(window= 42).mean()sz50['42d'] = np.round(sz50['close'].rolling(window= 42).mean(), 2)sz50['252d'] = np.round(sz50['close'].rolling(window= 252).mean(), 2)sz50.tail()
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; } open close high low volume code 42d 252d date 2017-06-14 2505.06 2477.32 2505.20 2471.62 21841108.0 sz50 2393.60 2287.56 2017-06-15 2474.26 2461.97 2481.80 2453.13 20702545.0 sz50 2395.84 2288.77 2017-06-16 2454.84 2452.79 2466.69 2448.31 16518044.0 sz50 2398.15 2290.02 2017-06-19 2455.03 2484.12 2486.31 2453.35 20594004.0 sz50 2401.17 2291.39 2017-06-20 2489.20 2474.43 2492.22 2467.77 17771153.0 sz50 2404.43 2292.67
%matplotlib inlinesz50[['close','42d','252d']].plot(grid=True, figsize=(15,7))
![png](output_4_1.png)![这里写图片描述](http://img.blog.csdn.net/20170620222259634?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxNDI4MTM5Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
#基于这些数据,可以设计一些规则来生简单的成趋势信号# 卖出信号# 42天平均线第一次高于252天平均线SD(平均值差值的阈值)点# 等待(持币)# 42天平均线在252天平均线的+-SD点范围内# 买入信号#在sz50上添加一个新的列,两个平均数据的差值,'42-252',因为两个均值的区间不同,所以数量上是不相等的,缺失的部分为Nansz50['42-252'] = sz50['42d'] - sz50['252d']sz50[['close','42d','252d','42-252']].head()
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; } close 42d 252d 42-252 date 2004-01-02 1011.35 NaN NaN NaN 2004-01-05 1060.80 NaN NaN NaN 2004-01-06 1075.66 NaN NaN NaN 2004-01-07 1086.30 NaN NaN NaN 2004-01-08 1102.66 NaN NaN NaN
sz50[['close','42d','252d','42-252']].tail()
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; } close 42d 252d 42-252 date 2017-06-14 2477.32 2393.60 2287.56 106.04 2017-06-15 2461.97 2395.84 2288.77 107.07 2017-06-16 2452.79 2398.15 2290.02 108.13 2017-06-19 2484.12 2401.17 2291.39 109.78 2017-06-20 2474.43 2404.43 2292.67 111.76
# 设置信号阈值SD,增加一个新列signal# np.where(condition,x,y)有三个参数,第一个为判断条件,也可为bool,# 条件为真时返回x,否则y# 官方文档中np.where跟详细的介绍:https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.htmlSD = 50sz50['signal'] = np.where(sz50['42-252'] > SD, 1, 0)sz50['signal'] = np.where(sz50['42-252'] < -SD, -1, sz50['signal'])sz50['signal'].value_counts()
-1    1363 1    1201 0     705Name: signal, dtype: int64
# 1363个交易日中,42日平均线比年平均线低50以上# 1201个交易日中,42日平均线比年平均线高50以上# 如果短期平均线和长期平均线交叉,它可能会保持一段时间%matplotlib  inlinesz50['signal'].plot(grid=True,figsize=(10,5))

png这里写图片描述

# 计算市场每天的回报率# np.diff()也可用于计算序列相邻两个数据之间的差值,返回数据类型为数组# 有几种不同的计算方法 (d[t]/d[t-1] -1.0)# 或对数收益         log(d[t]/d[t-1])# 分别计算两种收益率sz50['market'] = (sz50['close']/sz50['close'].shift(1))- 1.0# 对数收益率sz50['log_market'] = np.log(sz50['close']/sz50['close'].shift(1))#------------------------------------------------------------------------------# 计算根据移动平均线指定的简单策略,的收益# 收益率数据少一天,所以.shift(1),后以一天sz50['income'] = sz50['signal'].shift(1) * sz50['market']sz50['log_income'] = sz50['signal'].shift(1) * sz50['log_market']%matplotlib inlinesz50['income'].plot(grid=True, figsize=(10,6))sz50['log_income'].plot(grid=True, figsize=(10,6),alpha=0.5,c='red')

png这里写图片描述

# 基于两种不同收益率的差别很小,基本是完全重合的# 在价格序列变动性很小的情况下,这两个收益率的结果是近似相等的。# 另外就是对于使用“ln”处理一方面是的数据更加平滑,克服数据本身的异方差# 同时“ln”处理能够达到价格上涨下架的对称性,即数据的对称性。# 下面是每天的累计收益%matplotlib inlinesz50[['market','log_market','income','log_income']].cumsum().plot(grid=True, figsize=(15,7))

png这里写图片描述

# 前期两种收益率的基本重合,但是随着差距积累从09年后差距明显,但是基于策略的累计回报基本吻合# 从08到09年做空市场获得很好的收益,09年之后收益开始下降# 累计收益率cum_return(t) = daily_return(t-1)*(1.0+daily_return(t))sz50['accu_returns'] = (sz50['market'][:-1]*(1.0+sz50['market'].shift(1)[1:])%matplotlib inlinesz50[['accu_returns']].plot(grid=True, figsize=(10,6))

png这里写图片描述

# 下面进行更直观的比较acc_market = sz50['market'].cumsum()acc_log_market = sz50['log_market'].cumsum()# 规范化acc_market.plot(label='market accu_returns',figsize=(15,7))acc_log_market.plot(label='log market accu_returns')sz50['accu_returns'].plot(label='accu_reutnrs')plt.grid()plt.legend()plt.show()

png这里写图片描述

# 三者的升降的趋势很明显是一致的# 在07年到08年之间,accu_returns的变化非常巨大,因为这个累计收益是和04年1月02日的收盘价格来计算的(每天的收盘价除以04年的买入价)# market_accu_returns和log_market_accu_returns是把每天的收益累加计算得到
原创粉丝点击