美文网首页
MACD指标对于指数的趋势与择时效应

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

作者: 东南有大树 | 来源:发表于2019-03-03 15:23 被阅读8次
"""导入常用模块"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
from 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 * 2
    return 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 的计算与使用,可参考 https://www.joinquant.com/view/community/detail/16472

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():
                return
            order.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():
                return
            order.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():
                return
            order.buy(stock, close[-1], context.cash // close[-1])
        elif close1 > close2 and dea1 < dea2:
            if stock not in context.position.keys():
                return
            order.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():
                return
            order.buy(stock, close[-1], context.cash // close[-1])
        elif macd2 > 0 and macd1 < 0: 
            if stock not in context.position.keys():
                return
            order.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():
            return
        order.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():
            return
        order.sell(stock, close[-1], context.position[stock]['count'])

"""执行策略"""
trade.trade(handle, log=False)

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

相关文章

网友评论

      本文标题:MACD指标对于指数的趋势与择时效应

      本文链接:https://www.haomeiwen.com/subject/vxipuqtx.html