用趋势突破策略回测CTA

以下是小哥用趋势突破策略回测CTA的代码和结果,错误的地方还请大家提出来。

标的是螺纹钢的主力连续合约

#%% 趋势突破策略
# 导入包
import pandas as pd
import matplotlib.pyplot as plt

#%% 导入和清洗数据
RBL=pd.read_excel('H:/RBL8.xlsx')
RBL.index=pd.to_datetime(RBL.iloc[:,0])
RBL=RBL['2014':'2017']
RBL=RBL.iloc[:,1:5]
RBL.columns=('Open','High','Low','Close')

#%% 策略
#输入收盘价
#输出交易信号和仓位
def dt(tsc):
    ma5=pd.Series(0,index=tsc.index[19:])
    ma15=pd.Series(0,index=tsc.index[19:])
    ma20=pd.Series(0,index=tsc.index[19:])
    
    Signal=pd.Series(0,index=tsc.index[19:]) #信号
    Case=pd.Series(0,index=tsc.index[19:])   #仓位
    
    #计算MA
    for i in range(len(tsc)-19):
        ma5[i]=tsc[i+15:i+20].mean()
        ma15[i]=tsc[i+5:i+20].mean()
        ma20[i]=tsc[i:i+20].mean()
    
    #画出MA曲线
    plt.figure('MA曲线')
    plt.plot(tsc[19:],label='Close')
    plt.plot(ma5,label='MA5')
    plt.plot(ma20,label='MA20')
    plt.legend()
    
    #写出策略
    for i in range(len(Signal)-1):
        Case[i+1]=Case[i]
        if ma5[i]>ma20[i] and Case[i]<1:
            Signal[i]=1
            Case[i+1]=1
        elif ma5[i]<ma20[i] and Case[i]>-1:
            Signal[i]=-1
            Case[i+1]=-1
            
    return Signal,Case

#%% 回测
[sig,ca]=dt(RBL['Close'])

#%% 输出收盘价、交易信号、持仓情况
plt.figure('输出收盘价、交易信号、持仓情况')
plt.subplot(3,1,1)
plt.plot(RBL['Close'])
plt.title('收盘价')
plt.subplot(3,1,2)
plt.plot(sig)
plt.title('交易信号')
plt.subplot(3,1,3)
plt.plot(ca)
plt.title('持仓情况')
    
#%% 指标评价
# 累计收益、年化收益率、标的收益率、胜率、持仓时间、交易次数、最大回撤
#累计收益率
def all_re(tsc,Case):
    re=tsc.diff().dropna() #以收盘价衡量的每日收益
    day_profit=pd.Series(index=Case.index) #持仓后每日的收益
    for i in range(len(Case)):
        day_profit[i]=Case.iloc[i]*re[Case.index[i]]*5
    
    #累计收益
    acc_profit=day_profit.cumsum()
    #保证金,以持仓初始日的保证金为本金买入一手
    insur=tsc[Case.index[0]]*0.05+10000
    
    #年化收益:日收益率的平均值做成年化
    day_rate=acc_profit[-1]/(insur*len(acc_profit))
    anual_rate=day_rate*250
    
    #标的收益率
    bid_re=tsc[-1]/(insur*len(tsc))
    
    return acc_profit+insur,anual_rate,bid_re

#%% 交易次数、多头次数、空头次数
def trade_num(sig):
    return len(sig[sig!=0]),len(sig[sig==1]),len(sig[sig==-1])

#%% 持仓时间
def in_case(case):
    return len(case[case!=0])

#%% 回撤、最大回撤
def tradeback(tsc,Case):
    tb=pd.Series(0,index=Case.index)
    re=tsc.diff().dropna() #以收盘价衡量的每日收益
    day_profit=pd.Series(index=Case.index) #持仓后每日的收益
    for i in range(len(Case)):
        day_profit[i]=Case.iloc[i]*re[Case.index[i]]*5
        
    insur=tsc[Case.index[0]]*0.05+10000
    #累计收益
    acc_profit=day_profit.cumsum()+insur
    
    #回撤率
    for i in range(10,len(tb)-1):
        if acc_profit[i]>0:
            tb.iloc[i]=abs((max(acc_profit[:i+1])-acc_profit[i+1])/max(acc_profit[:i+1]))
           
    #返回回撤率、最大回撤率    
    return tb,max(tb)

#%%计算胜率
def victor(tsc,Case):
    ca_re=pd.Series(0,index=Case.index)
    re=tsc.diff().dropna()
    for i in range(len(Case)):
        ca_re.iloc[i]=Case.iloc[i]*re[Case.index[i]]
    
    vi=len(ca_re[ca_re>0])/len(Case) 
    return vi
    
#%% 输出累计收益率,回撤
plt.figure('累计收益、回撤')
plt.subplot(2,1,1)
plt.plot(all_re(RBL['Close'],ca)[0])
plt.title('累计收益')
plt.subplot(2,1,2)
plt.plot(tradeback(RBL['Close'],ca)[0]*100)
plt.title('回撤')

#%% 各项指标
print('年化收益率:',all_re(RBL['Close'],ca)[1]*100,'%')
print('\n标的收益率:',all_re(RBL['Close'],ca)[2]*100,'%')
print('\n交易次数:',trade_num(sig)[0],'\n多头次数:',trade_num(sig)[1],\
      '\n空头次数:',trade_num(sig)[2])
print('\n胜率:',victor(RBL['Close'],ca))
print('\n持仓时间:',in_case(ca))
print('\n最大回撤:',tradeback(RBL['Close'],ca)[1]*100,'%')   

年化收益率: 19.2994218941 %
标的收益率: 0.0382150782476 %
交易次数: 43 
多头次数: 21 
空头次数: 22
胜率: 0.5005224660397074
持仓时间: 956
最大回撤: 38.5974300685 %
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值