【量化投资】三大经典策略
三大经典策略三大经典策略前导知识1. tushare使用2. python包的使用3. 收益率计算方式双均线策略1. 策略思想2. 策略实现3. 策略评估4. 策略优化动量策略1. 策略思想2. 策略实现3. 策略优化均值回归策略1. 策略思想2. 策略实现三大经典策略前导知识1. tushare使用tushare是一个免费的、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、
三大经典策略
三大经典策略
前导知识
1. tushare使用
tushare是一个免费的、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。考虑到Python pandas包在金融量化分析中体现出的优势,Tushare返回的绝大部分的数据格式都是pandas DataFrame类型,非常便于用pandas/NumPy/Matplotlib进行数据分析和可视化。当然也可以使用tushare的数据存储功能将数据存储到excel。目前老版tushare不再维护,即将停止更新,可以使用Pro版接口,如果想要获取更多、更详细的数据,需要注册成为tushare社区用户,凭积分获取数据。
下面简单介绍tushare的安装与应用。在命令提示符下输入:
pip install tushare
下面演示如何通过tushare调取数据,我们这里对tushare pro进行演示。
我们获取股票基础数据,包括股票代码、名称、上市日期等,如下所示:
初始化pro接口:
>>> pro = ts.pro_api()
查询当前正常交易上市的股票信息:
>>> data = pro.stock_basic(exchange='', list_status='L',\
fields='ts_code,symbol,name,area,industry,list_date')
>>> data.head()
ts_code symbol name area industry list_date
0 000001.SZ 000001 平安银行 深圳 银行 19910403
1 000002.SZ 000002 万科A 深圳 全国地产 19910129
2 000004.SZ 000004 国华网安 深圳 互联网 19910114
3 000005.SZ 000005 世纪星源 深圳 环境保护 19901210
4 000006.SZ 000006 深振业A 深圳 区域地产 19920427
我们还可以获取股票日线行情数据,如下所示:
获取平安银行2020年12月至2021年1月的前复权数据:
>>> df = ts.pro_bar(ts_code='000001.SZ', adj='qfq', start_date='20201201', end_date='20210131')
>>> df.head()
ts_code trade_date open high ... change pct_chg vol amount
0 000001.SZ 20210129 22.81 23.54 ... 0.28 1.2275 1240258.41 2864101.419
1 000001.SZ 20210128 22.78 23.18 ... -0.27 -1.1698 857476.96 1948881.146
2 000001.SZ 20210127 22.31 23.47 ... 0.71 3.1739 1294152.72 2976800.955
3 000001.SZ 20210126 22.30 23.32 ... -0.12 -0.5336 1126720.55 2558575.511
4 000001.SZ 20210125 21.72 22.60 ... 0.46 2.0881 1028365.27 2269032.820
[5 rows x 11 columns]
我们可以获取平安银行均线数据:
>>> df = ts.pro_bar(ts_code='000001.SZ', start_date='20201201', end_date='20210131', ma=[5, 10])
>>> df.head()
ts_code trade_date open high ... ma5 ma_v_5 ma10 ma_v_10
0 000001.SZ 20210129 22.81 23.54 ... 22.768 1109394.782 22.561 1209637.021
1 000001.SZ 20210128 22.78 23.18 ... 22.556 1046229.984 22.352 1333680.078
2 000001.SZ 20210127 22.31 23.47 ... 22.440 1063690.312 22.088 1360947.944
3 000001.SZ 20210126 22.30 23.32 ... 22.318 1061018.400 21.850 1336444.645
4 000001.SZ 20210125 21.72 22.60 ... 22.312 1084091.958 21.713 1352589.140
[5 rows x 15 columns]
当然有些数据需要一定的积分才能够调取,所以为了获取足够的积分,调取更多数据,可以积极注册称为tushare社区用户,多多参与社区活动,获取更多平台的权益。
tushare pro的网址:https://tushare.pro/
在下面策略中我们使用老版tushare接口调取沪深300日线数据用于策略的实现。
2. python包的使用
在量化投资领域,最流行的语言为python,其原因在于python语法简单、易上手,有许多数据分析、可视化和统计建模的包可供使用,在下面的策略中,我们使用如下的包:
import matplotlib.pyplot as plt
import matplotlib as mpl #matplotlib是绘图时最常用的包
plt.style.use('seaborn') #seaborn也是可视化的包,这里为了让绘制的图如seaborn那般美观
mpl.rcParams['font.family'] = 'serif' #设置字体防止乱码
import warnings; warnings.simplefilter('ignore')#由于版本的原因,会出现警告信息,这里忽略
import pandas as pd
import numpy as np
import tushare as ts
3. 收益率计算方式
收益率的计算方式有两种:离散型和连续型。设当期股票价格为 P t P_t Pt,则离散型股票收益率计算方式为: P t P t − 1 − 1 \frac{P_t}{P_{t-1}}-1 Pt−1Pt−1;连续型收益率计算方式为: log ( P t / P t − 1 ) \log(P_t/P_{t-1}) log(Pt/Pt−1),两种计算方式都相差不大,在下面的策略实现时,两种收益率计算方式都有使用。
双均线策略
1. 策略思想
均线:对每一个交易日,可以计算出前 N N N日股票收盘价的平均值,这个平均值叫做移动平均,将每一个交易日的前 N N N日移动平均值连在一起就构成了均线。
双均线:双均线的意思即为有两条这样的均线,一条是用前 N N N日收盘价计算所得,另一条使用前 M M M日收盘价计算所得。
金叉(Golden cross)和死叉(Death cross):时间短的均线在下方向上穿过时间长的均线,称为金叉,这时认为,股票强势,可以买入该股票。时间短的均线在上方向下穿过时间长的均线,称为死叉,这时股票弱势,应该卖出该股票。如下图所示,图中橘色的线为20日均线,黄色的线为45日均线。
思想:当 x x x天均线上升并且交叉穿过 y y y天的均线时股票多头;当 x x x天均线下降并且交叉穿过 y y y天的均线时股票空头。在A股市场,虽然有着融资融券业务的存在,但是目前想要做空股票,投资者就得从券商那里借入股票并卖出。通常情况下,投资者是不容易借入股票的。本文为了演示策略,引入了股票空头,读者请知悉。
2. 策略实现
使用老版tushare获取沪深300k线数据:
df = ts.get_k_data('hs300',start='2010-01-01',end='2021-07-02')
df = df[['date','close']]
df.set_index('date',inplace=True)
计算10日均线和60日均线:(当然10日和60日是参数,你可以调整为你想要的值)
df['SMA_10'] = df['close'].rolling(10).mean()
df['SMA_60'] = df['close'].rolling(60).mean()
df[['close','SMA_10','SMA_60']].plot(title='hs300 stock price and SMAs of 10 and 60 days',figsize=(10,6))
沪深300日线、10日均线和60日均线如下图所示:
建立头寸,1表示多头,-1表示空头,头寸如下图所示。
df['position'] = np.where(df['SMA_10']>df['SMA_60'],1,-1)
df.dropna(inplace=True)
df['position'].plot(ylim=[-1.1,1.1],title='market position')
计算沪深300的收益率以及双均线策略的收益率:使用的是连续型收益率
df['return'] = np.log(df['close']/df['close'].shift(1))
df['strategy'] = df['position'].shift(1) * df['return']
df[['return','strategy']].cumsum().apply(np.exp).plot(figsize=(10,6))
累计收益率如下图所示:
3. 策略评估
年化收益率:一年也就252个交易日
df[['return','strategy']].mean() * 252
result:return 0.03682 strategy 0.072253
也就是说如果你在2010-01-01买入沪深300并持有至2021-07-02,你的年化收益为3.6%,如果你使用双均线策略,你的年化收益为7.2%。当然,我们在这里并没有考虑到实盘时的手续费、滑点等。
年化风险:
df[['return','strategy']].mean() * 252 ** 0.5
result:return 0.002320 strategy 0.004552
最大回撤:最大回撤表示的是累计收益从最大的点到之后最低点的距离,如下图所示。
df['cumreturn'] = df['strategy'].cumsum().apply(np.exp)
df['cummax'] = df['cumreturn'].cummax()
df[['cummax','cumreturn']].plot(figsize=(10,6))
drawdown = df['cummax'] - df['cumreturn']
drawdown.max()
累计最大收益和累计收益如下图所示:
最大回测为:1.5747052701854531
4. 策略优化
试想像:如果双均线频繁的交叉而导致频繁的买卖,会不会造成成本增加呢?
所以策略优化的思路就是基于此进行优化,即不要频繁的操作。即我们可以设置一个阈值 c c c:当一个均线穿过另一个均线并且大于阈值 c c c或者小于 − c -c −c时,才开仓,否者平仓。
df['SMA_diff'] = df['SMA_10'] - df['SMA_60']
c = 20
df['position'] = np.where(df['SMA_diff'] > c,1,0)
df['position'] = np.where(df['SMA_diff'] < -c,-1,df['position'])
df.dropna(inplace=True)
df['return'] = np.log(df['close']/df['close'].shift(1))
df['strategy'] = df['position'].shift(1) * df['return']
df[['return','strategy']].cumsum().apply(np.exp).plot(figsize=(10,6))
累计收益如下图所示:(好像和没优化时没多大区别,但是在实盘时考虑到交易费用等时区别应当明显)
动量策略
1. 策略思想
动量效应:在一定时期内,如果某股票或者某股票投资组合在前一段时期表现较好(差),那么,在下一段时期该股票或股票投资组合仍然将有良好(较差)的表现。
思路:
- 当前一期收益率为正时,当期采取股票多头;当前一期收益率为负时,下一期采取股票空头。
- 当前几期收益率的移动平均为正时,当期采取股票多头;当前几期收益率的移动平均为负时,当期采取股票空头。
2. 策略实现
df = ts.get_k_data('hs300',start='2010-01-01',end='2021-07-02')
df = df[['date','close']]
df.set_index('date',inplace=True)
df['return'] = np.log(df['close']/df['close'].shift(1))
df['position'] = np.sign(df['return'])
df['strategy'] = df['position'].shift(1) * df['return']
df.dropna(inplace=True)
df[['return','strategy']].cumsum().apply(np.exp).plot(figsize=(12,6))
累计收益如下图所示:
3. 策略优化
前面的策略实现过程中,当前一期收益率为正,采取股票多头,反之采取股票空头。但是我们可以用前面5期、10期、20期等的收益率平均值来作为建立头寸的依据。优化的思路即是参数寻优,一个简单的枚举法如下所示:
df2 = ts.get_k_data('hs300',start='2010-01-01',end='2021-07-02')
df2 = df2[['date','close']]
df2.set_index('date',inplace=True)
df2['return'] = df2['close'] / df2['close'].shift(1) - 1
df2['return_cum'] = (df2['return']+1).cumprod()
df2['position'] = np.sign(df2['return'])
df2['strategy'] = df2['position'].shift(1) * df2['return']
df2['strategy_cum'] = (df2['strategy']+1).cumprod()
table_title = ['return_cum']
for day in [5,10,20,30,60]:
table_title.append('strategy_%dd_cum' % day)
df2['position_%dd' % day] = np.sign(df2['return'].rolling(day).mean())
df2['strategy_%dd' % day] = df2['position_%dd' % day].shift(1) * df2['return']
df2['strategy_%dd_cum' % day] = (df2['strategy_%dd' % day] + 1).cumprod()
df2[table_title].dropna().plot(title='hs300 multi parameters momuntum strategy',figsize=(12,6),style=['--']*6)
各种参数的累计收益率如下图所示:
均值回归策略
1. 策略思想
均值回归是在价格震荡中寻求反弹的交易思路,即:涨上去的迟早要跌回来,跌下去的迟早要涨回来。均值回归策略应用了股市投资中经典的高抛低吸思想,该类型策略一般在震荡市中表现优异; 但是在单边趋势行情中一般表现糟糕,往往会大幅跑输市场。
distance:收盘价和均线的差值,如distance=close-SMA(50)
threshold:阈值,是对仓位调整的信号
思路:
- 当distance > threshold时,下一步做空;
- 当distance < -threshold时,下一步做多;
- 当连续两天的distance出现一正一负时,说明distance回归均值,平仓
2. 策略实现
df = ts.get_k_data('hs300',start='2010-01-01',end='2021-07-02')
df = df[['date','close']]
df.set_index('date',inplace=True)
df['return'] = np.log(df['close']/df['close'].shift(1))
SMA = 60
df['SMA'] = df['close'].rolling(SMA).mean()
df['distance'] = df['close'] - df['SMA']
threshold = 250 #阈值参数,可以调整
df.dropna(inplace=True)
df['distance'].plot(figsize=(10,6),legend=True)
plt.axhline(threshold,color='y')
plt.axhline(-threshold,color='y')
plt.axhline(0,color='y')
distance和阈值如下图所示:
下面建立股票头寸:
df['position'] = np.where(df['distance'] > threshold,-1,np.nan)
df['position'] = np.where(df['distance'] < - threshold,1,df['position'])
df['position'] = np.where(df['distance']*df['distance'].shift(1)<0,0,df['position'])
df['position'] = df['position'].ffill().fillna(0)
df['position'].plot(figsize=(10,6))
头寸如下图所示:
计算收益并可视化:
df['strategy'] = df['position'].shift(1) * df['return']
df[['return','strategy']].cumsum().apply(np.exp).plot(figsize=(10,6))
累计收益如下图所示:
可以发现,在14-15年那波大牛市中,均值回测策略表现糟糕,大幅跑输市场。
更多推荐
所有评论(0)