参考书目:深入浅出Python量化交易实战
本次带来最经典的交易策略,双均线策略的构建和其回测方法。
双均线一般采用5天均值和10天均值,如果5日均线上穿突破了10日均线,说明股价在最近的涨势很猛,买入信号。若下穿了10日均线,说明最近的跌幅较大,应该卖出。
数据获取和策略构建导入库
#导入必要的库import tushare as tsimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as sns获取数据
#指定下载股票的日期范围start_date = '2020-01-01'end_date = '2020-03-20'#使用ts获取数据#将时间范围作为参数传入zgpa = ts.get_k_data('601318',start_date, end_date)zgpa = zgpa.set_index('date')#检查是否下载成功zgpa.head()#新建一个数据表,命名为strategy(策略),计算交易的信号和下单数量
#序号保持和原始数据一致strategy = pd.DataFrame(index = zgpa.index)#添加一个signal字段,用来存储交易信号strategy['signal'] = 0#将5日均价保存到avg_5这个字段strategy['avg_5'] = zgpa['close'].rolling(5).mean()#同样,将10日均价保存到avg_10strategy['avg_10'] = zgpa['close'].rolling(10).mean()#当5日均价大于10日均价时,标记为1#反之标记为0strategy['signal'] = np.where(strategy['avg_5']>strategy['avg_10'], 1,0)#根据交易信号的变化下单,当交易信号从0变成1时买入#交易信号从1变成0时卖出#交易信号不变时不下单strategy['order'] = strategy['signal'].diff()#查看数据表后10行strategy.tail(10)singal表示买入信号,order表示相应的买入和卖出的操作点。-1表示卖出,1表示买入。
画图查看
#创建尺寸为10*5的画布plt.figure(figsize=(10,5))#使用实线绘制股价plt.plot(zgpa['close'],lw=2,label='price')#使用虚线绘制5日均线plt.plot(strategy['avg_5'],lw=2,ls='--',label='avg5')#使用-.风格绘制10日均线plt.plot(strategy['avg_10'],lw=2,ls='-.',label='avg10')#将买入信号用正三角进行标示plt.scatter(strategy.loc[strategy.order==1].index,zgpa['close'][strategy.order==1],marker = '^', s=80,color='r',label='Buy')#将卖出信号用倒三角进行标示plt.scatter(strategy.loc[strategy.order==-1].index,zgpa['close'][strategy.order==-1],marker = 'v', s=80,color='g',label='Sell')#添加图注plt.legend()plt.xticks([0,12,24,36,48])#添加网格以便于观察plt.grid()#显示图像plt.show()20000的初始资金
initial_cash = 20000#新建一个数据表positions,序号保持和strategy数据表一致#用0将空值进行替换positions = pd.DataFrame(index = strategy.index).fillna(0)#因为A股买卖都是最低100股#因此设置stock字段为交易信号的100倍positions['stock'] = strategy['signal'] * 100#创建投资组合数据表,用持仓的股票数量乘股价得出持仓的股票市值portfolio = pd.DataFrame(index = strategy.index)portfolio['stock value'] = positions.multiply(zgpa['close'], axis=0)#同样仓位的变化就是下单的数量#用初始资金减去下单金额的总和就是剩余的资金portfolio['cash'] = initial_cash - positions['stock'].diff().multiply(zgpa['close'], axis=0).cumsum()#剩余的资金+持仓股票市值即为总资产portfolio['total'] = portfolio['cash'] + portfolio['stock value']#检查一下后10行portfolio.tail(10)这里计算了每一天的市值和现金,总得账户余额。
核心思想也是用仓位的变化就是下单的数量,乘以对应的收盘价然后累计求和就是现金流变化。
画图查看账户变化:
#创建10*5的画布plt.figure(figsize=(10,5))#绘制总资产曲线plt.plot(portfolio['total'], lw=2, label='total')#绘制持仓股票市值曲线plt.plot(portfolio['stock value'],lw=2,ls='--', label='stock value')#添加图注plt.legend()#添加网格plt.grid()plt.xticks([0,12,24,36,48])#展示图像plt.show()
可以看到还是略微亏损,但是整体而言还是很不错了。少亏就是赚