欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一种基于RSI和K线的择时策略

程序员文章站 2022-07-13 17:15:48
...

该策略为择时策略,是小哥用来练习写量化程序用的

策略:

入场逻辑
多头:当 12 周期 RSI>50 并且当前K线收盘价为 40 周期内的最高点,在下一
K 线的开盘价买入。
ii. 空头:当 12 周期 RSI<50 并且当前K线收盘价为 40 周期内的最低点,在下一
K 线的开盘价卖出

平台:Python

标的:沪深300指数主力连续合约

标的数量:一手

回测时间:2010至今

代码如下:

#%% 导入包
import pandas as pd
import rsi
import matplotlib.pyplot as plt
import numpy as np

#%% 导入数据
IFL8=pd.read_excel('H:/Python/Paper/IFL8.xlsx')
IFL8.dropna()
IFL8=IFL8.iloc[1:,0:5]
IFL8.columns=IFL8.iloc[0,:]
IFL8=IFL8.iloc[2:-1,:]
IFL8.index=IFL8.iloc[:,0]
IFL8=IFL8.iloc[:,1:]
IFL8.columns=['开盘价','最高价','最低价','收盘价']
IFL8.index=pd.to_datetime(IFL8.index)
print(IFL8.head())

#%% 计算收盘价和开盘价
Close=IFL8['收盘价']
Open=IFL8['开盘价']

#%% 计算RSI(12期)
RSI12=rsi.rsi(Close,12)
#%% 画图
Close=Close[RSI12.index]
Open=Open[RSI12.index]
Close.name='Close'
Open.name='Open'
RSI12.name='RSI12'
#第一张图
plt.figure('开盘价、收盘价和RSI')
plt.subplot(211)
plt.plot(Close)
plt.plot(Open)
plt.legend()
#第二张图
plt.subplot(212)
plt.plot(RSI12)
plt.legend()

#%% 构建策略信号
signal=pd.Series(0,index=Close.index)  #信号初始化
signal.name='策略信号'
for i in range(39,len(Close)):
    if all([RSI12[i]>50,Close[i]==max(Close[i-39:i+1])]):  #多头条件
        signal[i]=1    #条件触发则买入多头
    elif all([RSI12[i]<50,Close[i]==min(Close[i-39:i+1])]):  #空头条件
        signal[i]=-1   #条件出发则买入空头

#%% 构建交易信号和仓位变化
tradeSig=pd.Series(0,index=signal.index)  # 交易信号
tradeSig.name='交易信号'
cage=pd.Series(0,index=signal.index)  #持仓情况
cage.name='仓位情况'
for i in range(0,len(signal)-1):
    if all([signal[i]==1,cage[i]<1]):  #当策略信号触发且仓位为空头时,触发多头信号
        tradeSig[i+1]=1
        cage[i+1]=1
    elif all([signal[i]==-1,cage[i]>-1]): #当策略信号触发且多头时,触发空头信号
        tradeSig[i+1]=-1
        cage[i+1]=-1
    else: 
        cage[i+1]=cage[i]  #仓位的保持
cage[-1]=0  #期末平仓 

#%% 绘制策略信号、交易信号和仓位情况图像
plt.figure('策略信号、交易信号和仓位情况')
plt.subplot(311)
plt.plot(signal)
plt.subplot(312)
plt.plot(tradeSig)
plt.subplot(313)
plt.plot(cage)

#%% 计算累计收益率,最大回撤,年化收益率,胜率,持仓时间,
# 计算累计收益率
Return=((Close-Close.shift(1))/Close.shift(1)).dropna()  # 日收益率
cumReturn_capital=np.cumprod(1+Return).dropna()     # 标的累计收益率
cumReturn_capital.name='标的累积收益率'
cumReturn_strategy=np.cumprod(1+cage*Return).dropna()  # 策略累计收益率
cumReturn_strategy.name='策略累积收益率'
plt.figure('累积收益率和回撤率')
plt.subplot(221)
plt.plot(cumReturn_capital)
plt.legend()
plt.subplot(222)
plt.plot(cumReturn_strategy)
plt.legend()

#%% 计算最大回撤
def traceback(Close):
    traceback=pd.Series(0,index=Close.index) #回撤
    for i in range(len(traceback)):
        traceback[i]=(max(Close[0:i+1])-Close[i])/max(Close[0:i+1])*100
    maxtraceback=max(traceback) # 最大回撤
    return maxtraceback,traceback
traceback_capital=traceback(cumReturn_capital)[1]
traceback_capital.name='标的回撤率'
traceback_strategy=traceback(cumReturn_strategy)[1]
traceback_strategy.name='策略回撤率'
plt.subplot(223)
plt.plot(traceback_capital)
plt.legend()
plt.subplot(224)
plt.plot(traceback_strategy)
plt.legend()
print('标的最大回撤率:',traceback(cumReturn_capital)[0],'%\n')
print('策略最大回撤率:',traceback(cumReturn_strategy)[0],'%\n')

#%% 年化收益率
yearReturn_capital=(cumReturn_capital[-1]**(212/len(cumReturn_capital))-1)*100
yearReturn_strategy=(cumReturn_strategy[-1]**(212/len(cumReturn_strategy))-1)*100
print('标的年化收益率:',yearReturn_capital,'%\n')
print('策略年化收益率:',yearReturn_strategy,'%\n')

#%% 计算胜率
returnD_strategy=(cage*Return).dropna()    # 策略的日收益率
victor=len(returnD_strategy[returnD_strategy>0])/len(returnD_strategy) # 胜率 
print('策略的胜率:',victor)

#%% 持仓时间
print('持仓时间:',len(cage[cage!=0]),'天')

计算RSI的函数

#%% 计算RSI
# input:收盘价和期数
# output: RSI
def rsi(price,period=6):
    import numpy as np
    import pandas as pd
    clprcChange=price-price.shift(1)
    clprcChange=clprcChange.dropna()
    
    indexprc=clprcChange.index
    upPrc=pd.Series(0,index=indexprc)
    upPrc[clprcChange>0]=clprcChange[clprcChange>0]
    
    downPrc=pd.Series(0,index=indexprc)
    downPrc[clprcChange<0]=-clprcChange[clprcChange<0]
    rsidata=pd.concat([price,clprcChange,upPrc,downPrc],axis=1)
    rsidata.columns=['price','PrcChange','upPrc','downPrc']
    rsidata=rsidata.dropna()
    
    SMUP=[]
    SMDOWN=[]
    for i in range(period,len(upPrc)+1):
        SMUP.append(np.mean(upPrc.values[(i-period):i],dtype=np.float32))
        SMDOWN.append(np.mean(downPrc.values[(i-period):i],dtype=np.float32))
        rsi=[100*SMUP[i]/(SMUP[i]+SMDOWN[i]) for i in range(0,len(SMUP))]
        
    indexRsi=indexprc[(period-1):]
    rsi=pd.Series(rsi,index=indexRsi)
    return(rsi)

得到收盘价和RSI的时间序列

一种基于RSI和K线的择时策略

接着得到策略信号、交易信号和仓位情况的序列

一种基于RSI和K线的择时策略

之后计算最重要的累计收益率和回撤率

一种基于RSI和K线的择时策略

策略的结果参数为

标的最大回撤率: 48 %
策略最大回撤率: 58 %
标的年化收益率: 2.7500531042845555 %
策略年化收益率: -1.5597819693758175 %
策略的胜率: 0.4923425978445831
持仓时间: 1723 天

结论:可见这个策略连标的都没有跑过,而且回撤是如此之大,以至于这样操作会大亏,所以这个策略并不好。权当小哥写回测程序练手罢了。