日收益率和累计收益

在测试数据上计算日收益率和对数收益率,和基于两种收益率的累计收益率,比较了一下两种累计收益率,通过每天日收益率累计计算是在python金融数据分析中看到的,另一种是佐治亚理工公开课cs7646中介绍的一种方法,用当前的价格比上第一天买入的价格,在减去一
import numpy as np
import pandas as pd
import 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]
<class 'pandas.core.frame.DataFrame'>
Int64Index: 3269 entries, 0 to 3268
Data columns (total 7 columns):
date      3269 non-null object
open      3269 non-null float64
close     3269 non-null float64
high      3269 non-null float64
low       3269 non-null float64
volume    3269 non-null float64
code      3269 non-null object
dtypes: float64(5), object(2)
memory usage: 204.3+ KB
openclosehighlowvolumecode
date
2004-01-02997.001011.351021.57993.898064650.0sz50
2004-01-051008.281060.801060.901008.2814468200.0sz50
2004-01-061059.141075.661086.691059.0916991300.0sz50
#画出上证指数的收盘价格的时序图,指定网格和长宽比例
%matplotlib inline
sz50['close'].plot(grid = True, figsize=(15,7))

这里写图片描述

#实现两个趋势策略,期间指数水平移动平均数,分别是两个月(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()
openclosehighlowvolumecode42d252d
date
2017-06-142505.062477.322505.202471.6221841108.0sz502393.602287.56
2017-06-152474.262461.972481.802453.1320702545.0sz502395.842288.77
2017-06-162454.842452.792466.692448.3116518044.0sz502398.152290.02
2017-06-192455.032484.122486.312453.3520594004.0sz502401.172291.39
2017-06-202489.202474.432492.222467.7717771153.0sz502404.432292.67
%matplotlib inline
sz50[['close','42d','252d']].plot(grid=True, figsize=(15,7))

这里写图片描述

#基于这些数据,可以设计一些规则来生简单的成趋势信号
# 卖出信号
# 42天平均线第一次高于252天平均线SD(平均值差值的阈值)点
# 等待(持币)
# 42天平均线在252天平均线的+-SD点范围内
# 买入信号
#在sz50上添加一个新的列,两个平均数据的差值,'42-252',因为两个均值的区间不同,所以数量上是不相等的,缺失的部分为Nan
sz50['42-252'] = sz50['42d'] - sz50['252d']

sz50[['close','42d','252d','42-252']].head()

close42d252d42-252
date
2004-01-021011.35NaNNaNNaN
2004-01-051060.80NaNNaNNaN
2004-01-061075.66NaNNaNNaN
2004-01-071086.30NaNNaNNaN
2004-01-081102.66NaNNaNNaN
sz50[['close','42d','252d','42-252']].tail()
close42d252d42-252
date
2017-06-142477.322393.602287.56106.04
2017-06-152461.972395.842288.77107.07
2017-06-162452.792398.152290.02108.13
2017-06-192484.122401.172291.39109.78
2017-06-202474.432404.432292.67111.76
# 设置信号阈值SD,增加一个新列signal
# np.where(condition,x,y)有三个参数,第一个为判断条件,也可为bool,
# 条件为真时返回x,否则y
# 官方文档中np.where跟详细的介绍:https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html
SD = 50
sz50['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     705
Name: signal, dtype: int64
# 1363个交易日中,42日平均线比年平均线低50以上
# 1201个交易日中,42日平均线比年平均线高50以上
# 如果短期平均线和长期平均线交叉,它可能会保持一段时间
%matplotlib  inline
sz50['signal'].plot(grid=True,figsize=(10,5))

这里写图片描述

# 计算市场每天的回报率
# 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 inline
sz50['income'].plot(grid=True, figsize=(10,6))
sz50['log_income'].plot(grid=True, figsize=(10,6),alpha=0.5,c='red')

这里写图片描述

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

这里写图片描述

# 前期两种收益率的基本重合,但是随着差距积累从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 inline
sz50[['accu_returns']].plot(grid=True, figsize=(10,6))

这里写图片描述

# 下面进行更直观的比较
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()

这里写图片描述

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值