掘金社区

talib包计算MACD值和行情软件有差异的解决方法Pinned highlighted

四两 发表在策略研究 2020-10-23 09:38:42

策略研究
265
0
0

talib包是计算许多行情指标必备的第三方库,但在计算过程中发现,计算出来的数值和行情软件的计算方法存在很大的差异,可能会导致策略出现错误。为此,专门写了一个函数解决这个问题。欢迎大家一起交流讨论。

MACD的计算

MACD的计算很简单,主要包括DIF、DEA和BAR三个参数。计算方式如下:
0_1603416493225_861ffe33-a5ec-4278-a46f-32d62a8194fb-image.png
(图片来源百度百科)

注: 在计算过程中,需要注意数据的初始化。上市首日,DIF、DEA、BAR默认为0.但次日计算中EMA12和EMA26是按照上市首日的收盘价来计算的,所以这里面涉及一个初始化的问题。在计算上市以来第二个交易日的MACD时要先将EMA12和EMA26都替换为上市首日收盘价。

函数编写思路

  • 首先,需要自上市以来的收盘价数据。这里利用掘金的history接口,将开始日期设置为一个较早的日期以确保将标的自上市以来的全部收盘价都涵盖(这里设定为1997年)。

  • 其次,根据上图中的公式计算出各项指标,存为dataframe。

  • 最后,由于不需要上市以来全部的MACD指标,只需要其中的一段时间。所以,设定一个时间筛选条件,能够满足只要设定开始时间和结束时间即可提取到所需数据的函数。

基于以上思路,可以编写出函数如下:

def get_macd(symbol,start_time,end_time):
    # 取历史数据
    data = history(symbol = symbol,frequency = '1d',start_time = '1997-01-20',end_time = end_time,fields = 'symbol,bob,close',df = True)
    index = data['bob'].apply(lambda x: x.strftime('%Y-%m-%d')).tolist()

    # 编写计算函数
    # 上市首日,DIFF、DEA、MACD = 0
    # 用来装变量的list
    EMA12 = []
    EMA26 = []
    DIFF = []
    DEA = []
    BAR = []
    # 如果是上市首日
    if len(data) == 1:
        # 则DIFF、DEA、MACD均为0
        DIFF = [0]
        DEA = [0]
        BAR = [0]

    # 如果不是首日
    else:
        # 第一日的EMA要用收盘价代替
        EMA12.append(data['close'].iloc[0])
        EMA26.append(data['close'].iloc[0])
        DIFF.append(0)
        DEA.append(0)
        BAR.append(0)

        # 计算接下来的EMA
        # 搜集收盘价
        close = list(data['close'].iloc[1:])    # 从第二天开始计算,去掉第一天
        for i in close:
            ema12 = EMA12[-1] * (11/13) + i * (2/13)
            ema26 = EMA26[-1] * (25/27) + i * (2/27)
            diff = ema12 - ema26
            dea = DEA[-1] * (8/10) + diff * (2/10)
            bar = 2 * (diff - dea)

            # 将计算结果写进list中
            EMA12.append(ema12)
            EMA26.append(ema26)
            DIFF.append(diff)
            DEA.append(dea)
            BAR.append(bar)

    # 返回全部的macd
    MACD = pd.DataFrame({'DIFF':DIFF,'DEA':DEA,'BAR':BAR, 'time':index},index = index)

   # 按照时间筛选子集
    MACD = MACD[(MACD['time'] >= start_time) & (MACD['time'] <= end_time)]

    return MACD

利用数据验证一下。我用的是大商所的豆油(DCE.y2011合约),结果和东方财富显示的相符。

a = get_macd(symbol = 'DCE.y2011',start_time = '2020-01-01',end_time = '2020-10-22')

Tips:
虽然这样能够解决talib计算MACD和行情软件有差异的问题,但这样计算也会衍生出新的问题。

  1. 将该函数放到循环中,每循环一次就要重新提取一次数据,无形之中增加了策略运行的时间和工作量。
  2. 如果利用其他频率的数据计算macd(比如用60s的数据计算MACD),没有能够追溯到上市当天的历史数据,这样计算出来的结果仍然是不准确的。

自己写函数 or 用talib包?

由于talib包没有详细的计算方法解释,所以暂时无法得知该包是怎样计算macd的,但不可否认的是,在事件驱动的高频交易中,用talib包的确更方便一些。

基于以上,选择哪种方法还需自行斟酌。

暂无评论

Looks like your connection to 掘金量化社区 - 量化交易者的策略交流学习社区 was lost, please wait while we try to reconnect.