本文主要是利用海龟交易策略进行量化交易策略的构建,同时用均线策略,布林带策略等经典策略构建第二条通道进行策略改善。
数据来源:
https://tushare.pro/register?reg=403436
不知道如何编写代码的也可以直接进入数据工具接口生成即可Tushare数据工具,非常方便。
首先先利用API接口获得沪深300近10年数据,然后进行数据清理,构造布林带策略和均线均线策略的组件。
import math
import tushare as ts
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import talib
matplotlib.rcParams['axes.unicode_minus']=False
plt.rcParams['font.sans-serif']=['SimHei']
ts.set_token('af3...')#这里是token码 获取地址 https://tushare.pro/register?reg=403436(需注册)
pro = ts.pro_api()
df=pro.index_daily(ts_code='399300.SZ', start_date='20100101', end_date='20211010')
df=df.sort_index()
df.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')#设置日期索引
df = df[::-1]
close = df.close
ret = df['close'].pct_change()
close20 = talib.MA(np.array(close),timeperiod=20)
atr1 = talib.ATR(df['high'].values,df['low'].values,df['close'].values,timeperiod=20)
atr = pd.DataFrame(atr1)
atr.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')
atr = atr.fillna(0)
mv = talib.MA(np.array(df.close),timeperiod=20)
close_bup = mv+2*atr1
close_bdw = mv-2*atr1
#实现最大回撤
def MaxDrawdown(return_list):
# 1. find all of the peak of cumlative return
maxcum = np.zeros(len(return_list))
b = return_list[0]
for i in range(0,len((return_list))):
if (return_list[i]>b):
b = return_list[i]
maxcum[i] = b
# 2. then find the max drawndown point
i = np.argmax((maxcum-return_list)/maxcum)
if i == 0:
return 0
j = np.argmax(return_list[:i])
# 3. return the maxdrawndown
return (return_list[j]-return_list[i])/return_list[j]
先构造经典20日,55日海龟长期交易策略
'''
普通短期海龟交易策略图示及框架
'''
def haigui(short,long):
SmaSignal = pd.Series(0,index=close.index)
for i in range(long,len(close)):
if close[i]>max(close[i-long:i]):
SmaSignal[i]=1
elif close[i]<min(close[i-short:i]):
SmaSignal[i]=0
else:
SmaSignal[i]=SmaSignal[i-1]
SmaTrade = SmaSignal.shift(1).dropna()
SmaRet = ret*SmaTrade
SmaRet=SmaRet.dropna()
#策略累积收益率
cumStock = (1+ret[SmaRet.index[0:]]).cumprod()
cumTrade = np.cumprod(1+SmaRet)
plt.plot(cumTrade,label='海龟交易策略净值线',color='r')
plt.plot(cumStock,label='直接持有净值线',color='k')
plt.title('海龟交易策略')
plt.legend()
#总收益率
year_n = len(df)/242
cagr=(1+cumTrade[-1])**(1/year_n)-1
SR=(SmaRet.mean()-0.00135/365)/SmaRet.std()*np.sqrt(242)
benchmark =ret.mean()
IR=(SmaRet.mean()-benchmark)/SmaRet.std()*np.sqrt(242)
MH=MaxDrawdown(cumTrade)
print('策略累计收益率:'+ str(cumTrade[-1]))
print('策略年化收益率:'+ str(cagr))
print('夏普比率:'+ str(SR))
print('信息比率:'+ str(IR))
print('最大回撤:'+ str(MH))
'''
长期:20,55
'''
haigui(20,55)
策略累计收益率:1.7992776730184188
策略年化收益率:0.09110535656105423
夏普比率:0.45756551980402194
信息比率:0.031684543775977014
最大回撤:0.32839036842157054
海龟交易策略整体情况是不错的,但是还不够好,年化9%不够高。
优化系统 均线策略X海龟双通道策略
构造20日均线 上穿20日均线或海龟线任意一个就买入 下穿20日均线且碰到海龟线才卖出
def haiguiXjunxian(short,long):
SmaSignal = pd.Series(0,index=close.index)
s=0
k=0
for i in range(long,len(close)):
if close[i]>max(close[i-long:i]) or all([close[i]>close20[i],close[i-1]<close20[i-1]]):
SmaSignal[i]=1
k+=1
elif close[i]<min(close[i-short:i]) and all([close[i]<close20[i],close[i-1]>close20[i-1]]):
SmaSignal[i]=0
k+=1
else:
SmaSignal[i]=SmaSignal[i-1]
s=s+SmaSignal[i]
ds = len(close)-s
SmaTrade = SmaSignal.shift(1).dropna()
SmaRet = ret*SmaTrade
SmaRet=SmaRet.dropna()
#策略累积收益率
cumStock = (1+ret[SmaRet.index[0:]]).cumprod()
cumTrade = np.cumprod(1+SmaRet)
plt.plot(cumTrade,label='海龟交易策略净值线',color='r')
plt.plot(cumStock,label='直接持有净值线',color='k')
plt.title('海龟交易策略')
plt.legend()
#总收益率
year_n = len(df)/242
cagr=(1+cumTrade[-1])**(1/year_n)-1
SR=(SmaRet.mean()-0.00135/365)/SmaRet.std()*np.sqrt(242)
benchmark =ret.mean()
IR=(SmaRet.mean()-benchmark)/SmaRet.std()*np.sqrt(242)
MH=MaxDrawdown(cumTrade)
print('策略累计收益率:'+ str(cumTrade[-1]))
print('策略年化收益率:'+ str(cagr))
print('夏普比率:'+ str(SR))
print('信息比率:'+ str(IR))
print('最大回撤:'+ str(MH))
haiguiXjunxian(20,55)
策略累计收益率:1.8879248200168226
策略年化收益率:0.09399056122632032
夏普比率:0.35310434487607206
信息比率:0.11052841469154707
最大回撤:0.46696138837984724
成功跑赢原始海龟策略,但是最大回撤过大,而且没计算交易成本,所以继续改进。
构造布林带上下轨,限制交易频率,在满足海龟交易策略且位于布林带上轨才买入,而在满足海龟交易策略且刺穿布林带下轨才卖出。
def haiguiXbulin(short,long):
SmaSignal = pd.Series(0,index=close.index)
s=0
k=0
for i in range(long,len(close)):
if close[i]>max(close[i-long:i]) and close[i]>close_bup[i]:
SmaSignal[i]=1
k+=1
elif close[i]<min(close[i-short:i]) and all([close[i]<close_bdw[i],close[i-1]>close_bdw[i-1]]):
SmaSignal[i]=0
k+=1
else:
SmaSignal[i]=SmaSignal[i-1]
s=s+SmaSignal[i]
ds = len(close)-s
SmaTrade = SmaSignal.shift(1).dropna()
SmaRet = ret*SmaTrade
SmaRet=SmaRet.dropna()
#策略累积收益率
cumStock = (1+ret[SmaRet.index[0:]]).cumprod()
cumTrade = np.cumprod(1+SmaRet)
plt.plot(cumTrade,label='海龟交易策略净值线',color='r')
plt.plot(cumStock,label='直接持有净值线',color='k')
plt.title('海龟交易策略')
plt.legend()
#总收益率
year_n = len(df)/242
cagr=(1+cumTrade[-1])**(1/year_n)-1
SR=(SmaRet.mean()-0.00135/365)/SmaRet.std()*np.sqrt(242)
benchmark =ret.mean()
IR=(SmaRet.mean()-benchmark)/SmaRet.std()*np.sqrt(242)
MH=MaxDrawdown(cumTrade)
print('策略累计收益率:'+ str(cumTrade[-1]))
print('策略年化收益率:'+ str(cagr))
print('夏普比率:'+ str(SR))
print('信息比率:'+ str(IR))
print('最大回撤:'+ str(MH))
haiguiXbulin(20,55)
策略累计收益率:2.2329523717630524
策略年化收益率:0.10449872667110616
夏普比率:0.5754578953903876
信息比率:0.17648503084869085
最大回撤:0.27539806074090606
跑赢上一个均线+海龟的组合模型,且最大回测大幅度降低,夏普比率上到0.7。