请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3365785 新帖:17

MACD指标对于指数的趋势与择时效应

我们棒棒哒发表于:5 月 9 日 19:19回复(1)
"""导入常用模块"""import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport datetimefrom jqdata import *from environment import * # 导入大树工作室开发的回测模块

MACD计算函数

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)


MACD常用方法一

  1. DIF,DEA均大于0,DIF向上突破DEA,即在0轴上形成金叉的时候,买入;

  2. 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时的回报率最大,整体说来,回撤很大。但本回测是采用单一指标,未添加止损止盈,仓位管理等条件,所以不能太苛刻。

MACD常用方法二

当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柱由绿变红时,买入;当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)

以上几种情况,可以结合使用,有兴趣的朋友可以做更多的推广测试。

全部回复

0/140

量化课程

    移动端课程