"""导入常用模块"""import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport datetimefrom jqdata import *from environment import * # 导入大树工作室开发的回测模块
import talib as tl# MACD 公用函数def MACD(close, fastperiod, slowperiod, signalperiod):macdDIFF, macdDEA, macd = tl.MACDEXT(close, fastperiod=fastperiod, fastmatype=1, slowperiod=slowperiod, slowmatype=1, signalperiod=signalperiod, signalmatype=1) macd = macd * 2return macdDIFF, macdDEA, macd # 查寻一个时间段内某标的的macd信息def get_macd(stock, count, end_date, unit):data = get_bars(security=stock, count=count, unit=unit,include_now=False, end_dt=end_date, fq_ref_date=None) close = data['close'] open = data['open'] high = data['high'] low = data['low']return MACD(close, 12, 26, 9)
DIF,DEA均大于0,DIF向上突破DEA,即在0轴上形成金叉的时候,买入;
DIF,DEA均小于0,DIF向下突破DEA,即在0轴下形成死叉的时候,卖出;
在形成金叉或死叉时,需要用前后两个时间点所对应的DIF与DEA的值进行比较,在日回测中,最短的是当天与昨天进行比较,但时间太短,容易发生虚假信号,因此,将这个前后比较的时间做为一个可变参数。设这个时间段为N,N的取值为1到9,接下回来对方法一进行回测,并生成比较结果。
trade_list = [] N = range(1, 10)for n in N:"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2005-05-01'context.end_date = '2019-02-22'context.universe = ['000300.XSHG'] context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0] current_date = trade.context.current_dt macd_day = get_macd(stock, 100, current_date, '1d') dif1 = macd_day[0][-1] dea1 = macd_day[1][-1] macd1 = macd_day[2][-1] dif2 = macd_day[0][-n-1] dea2 = macd_day[1][-n-1] macd2 = macd_day[2][-n-1] close = get_price(security=stock, end_date=context.current_dt, frequency='daily', fields=None, skip_paused=False, fq='pre', count=5)['close']if dif1 > 0 and dea1 > 0 and dif2 < dea2 and dif1 > dea2:if stock in context.position.keys():returnorder.buy(stock, close[-1], context.cash // close[-1])elif dif1 < 0 and dea1 < 0 and dif2 > dea2 and dif1 < dea2:if stock not in context.position.keys():returnorder.sell(stock, close[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle, show=False, log=False) trade_list.append(trade)# 展示Trade.show_ratio_compare('n', N, trade_list, 3, 3)
Trade.show_result('n', N, trade_list)
回测结果显示,在n等于9时的回报率最大,整体说来,回撤很大。但本回测是采用单一指标,未添加止损止盈,仓位管理等条件,所以不能太苛刻。
当DEA与价格趋势发生背离时,即当股价不断走低,而DEA不断走高时,进行买入操作;当股价不断走高,而DEA值不断走低时,进行卖出操作。背离值需要一个时间段来进行比较,我们将这个时间段设N,取值1~9,然后对方法二进行回测。
trade_list = [] N = range(1, 10)for n in N:"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2005-05-01'context.end_date = '2019-02-22'context.universe = ['000300.XSHG'] context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0] current_date = trade.context.current_dt macd_day = get_macd(stock, 100, current_date, '1d') close = get_price(security=stock, end_date=context.current_dt, frequency='daily', fields=None, skip_paused=False, fq='pre', count=n 1)['close'] dif1 = macd_day[0][-1] dea1 = macd_day[1][-1] macd1 = macd_day[2][-1] dif2 = macd_day[0][-n-1] dea2 = macd_day[1][-n-1] macd2 = macd_day[2][-n-1] close1 = close[-1] close2 = close[-n-1]if close1 < close2 and dea1 > dea2:if stock in context.position.keys():returnorder.buy(stock, close[-1], context.cash // close[-1])elif close1 > close2 and dea1 < dea2:if stock not in context.position.keys():returnorder.sell(stock, close[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle, show=False, log=False) trade_list.append(trade)# 展示Trade.show_ratio_compare('n', N, trade_list, 3, 3)
Trade.show_result('n', N, trade_list)
从回测看来,n取值等于4时,效果最好,但整体回测的效果并不理想。原因可以有以下,MACD本身具有延迟性,而如果想在底背离与顶背离时买卖,延迟的时间则更长,而大多数情况下,合适的买卖点不一定都会发生背离情况。因此,方法二回测的情况是符合逻辑的。
当MACD柱由绿变红时,买入;当MACD由红变绿时,卖出。这里同样为本方法设定一个时间段,N的取值是1~9.来看下面的回测。
trade_list = [] N = range(1, 10)for n in N:"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2005-05-01'context.end_date = '2019-02-22'context.universe = ['000300.XSHG'] context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0] current_date = trade.context.current_dt macd_day = get_macd(stock, 100, current_date, '1d') close = get_price(security=stock, end_date=context.current_dt, frequency='daily', fields=None, skip_paused=False, fq='pre', count=n 1)['close'] dif1 = macd_day[0][-1] dea1 = macd_day[1][-1] macd1 = macd_day[2][-1] dif2 = macd_day[0][-n-1] dea2 = macd_day[1][-n-1] macd2 = macd_day[2][-n-1] close1 = close[-1] close2 = close[-n-1]if macd2 < 0 and macd1 > 0:if stock in context.position.keys():returnorder.buy(stock, close[-1], context.cash // close[-1])elif macd2 > 0 and macd1 < 0: if stock not in context.position.keys():returnorder.sell(stock, close[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle, show=False, log=False) trade_list.append(trade)# 展示Trade.show_ratio_compare('n', N, trade_list, 3, 3)
Trade.show_result('n', N, trade_list)
通过回测来看,当n等于1时,效果最好。macd值由红转绿或由绿转红的时候,其实也正是死叉或金叉形成的时候。
通过比较,发现方法一的情况下,N=9时,回测效果最好。如下图:
"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2005-05-01'context.end_date = '2019-02-22'context.universe = ['000300.XSHG'] context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0] current_date = trade.context.current_dt macd_day = get_macd(stock, 100, current_date, '1d') dif1 = macd_day[0][-1] dea1 = macd_day[1][-1] macd1 = macd_day[2][-1] dif2 = macd_day[0][-9] dea2 = macd_day[1][-9] macd2 = macd_day[2][-9] close = get_price(security=stock, end_date=context.current_dt, frequency='daily', fields=None, skip_paused=False, fq='pre', count=5)['close']if dif1 > 0 and dea1 > 0 and dif2 < dea2 and dif1 > dea2:if stock in context.position.keys():returnorder.buy(stock, close[-1], context.cash // close[-1])elif dif1 < 0 and dea1 < 0 and dif2 > dea2 and dif1 < dea2:if stock not in context.position.keys():returnorder.sell(stock, close[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle, log=False)
以上几种情况,可以结合使用,有兴趣的朋友可以做更多的推广测试。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程