avatar

Z Space

You Gotta Move

  • 首页
  • Halo
  • 关于
Home 量化之macd的计算
文章

量化之macd的计算

Posted 2024-12-18 Updated 2024-12- 18
By 冬天的海
8~10 min read

股市从9月底开始,似乎开始活过来了,于是又开始研究了一下量化。想试试macd相关策略的回测,结果发现,用talib算出来的macd和券商的通达信软件的数据差别挺大的,于是对这个算法做了点“深入”研究。

在知乎上搜到了一篇不错的文章:

指标之王MACD(一)-原理

具体看原文,这里主要记录自己的应用。

递归式

macd计算中的关键就是EMA的计算,而根据EMA的算法定义可以推出一个递归的公式,借图如下:

这个公式很好理解,计算起来也很方便,问题在于我们需要一个Xn-1的初始值。

原理式

原文作者为了讲解对其原理的理解,推导出一个新的公式,正好可以用于计算初始值:

EMA = (1*X1 + 2*X2 + ... + n*Xn)/(1+2+...+n)

所以EMA的原理其实就是每个参数值依据所在位置,权重不同,再计算出平均值。

上面的“递归式”和“原理式”是我自己编的一个名词,便于后文叙述。

算法实现

有了上面两个公式,用代码实现macd就很简单了,具体思路就是,在初始值没出现前,使用原理式计算出初始值,有了初始值之后,用递归式计算后续数据。

计算结果测试

简单测试计算结果后,看到的效果是:

  • 在数据量较小时,本算法的计算结果与通达信的偏差相对talib的macd函数要小一点

  • 在数据量较多(约300个数值)时,本算法和talib的macd公式的结果都很接近通达信数据,偏差不超过0.02%

关于算法的应用

既然数据量较大时,talib的结果完全可用,我何必造个新轮子呢,主要在于两点考虑:

  • 出于多年开发工作的习惯,喜欢节省计算资源,talib由于是个黑箱,每次计算必须给它足够多的数据来计算,而自己写的函数,可以在初次算好一批数据后,新的数据只需要拿前一天的数据代入即可算出新的macd值(但量化平台似乎并不在乎这点计算资源)。

  • 由于对python不那么熟练,在量化平台上写代码,出错在所难免,出了错有时候报错信息并不那么清晰,我想要在自己的python环境里把大部分代码调通了,再上量化平台写点取数据的代码就能通,但talib本地安装的依赖还挺多的,有点不想折腾安装。

  • 我知道有些量化平台支持本地安装,但一般都是需要付费的,我目前还在对策略的学习研究阶段,等到能靠它赚钱再付费不迟。

小结

虽然自己搞macd的计算似乎不是非常必要,但在特定情况下多少还有点用,并且加深了一点数学知识的理解,因此小记一篇。

附 - 代码

# close: a list
def macd(close, short=12, long=26, signal=9):
    ema_short, ema_long, dif, dea, bar = [], [], [], [], []
    for index, item in enumerate(close):
        if index < short - 1:
            ema_short.append(np.nan)
        if index == short - 1:
            ema_short.append(ema1(close, index, short))
        if index > short - 1:
            ema_short.append(ema2(item, ema_short[index-1], short))
        if index < long - 1:
            ema_long.append(np.nan)
            dif.append(np.nan)
        if index == long - 1:
            ema_long.append(ema1(close, index, long))
            dif.append(ema_short[index] - ema_long[index])
        if index > long - 1:
            ema_long.append(ema2(item, ema_long[index-1], long))
            dif.append(ema_short[index] - ema_long[index])
        if index < long + signal - 2:
            dea.append(np.nan)
            bar.append(np.nan)
        if index == long + signal - 2:
            dea.append(ema1(dif, index, signal))
            bar.append((dif[index] - dea[index]) * 2)
        if index > long + signal - 2:
            dea.append(ema2(dif[index], dea[index-1], signal))
            bar.append((dif[index] - dea[index]) * 2)
    return ema_short, ema_long, dif, dea, bar

def ema1(close, last_index, n):
    #分子 分母
    accn, accm = 0, 0
    for i in range(n):
        val = close[last_index - i]
        accn = accn + val * (n - i)
        accm = accm + i + 1
#         print(i, val, accn, accm)
    return accn / accm

def ema2(val, last_ema, n):
    return (2 * val + (n - 1) * last_ema) / (n + 1)

money
License:  CC BY 4.0
Share

Further Reading

OLDER

股票投资的24堂必修课 - 读后

NEWER

关于播客

Recently Updated

  • 在debian 13(testing)上安装nvidia驱动
  • 记一次docker desktop的更新故障
  • 关于播客
  • 量化之macd的计算
  • 股票投资的24堂必修课 - 读后

Trending Tags

Halo money 日常 docker pve

Contents

©2025 Z Space. Some rights reserved.

Using the Halo theme Chirpy