MQL指标:MACD

MACD 简介

MACD,Moving Average Convergence / Divergence,中文译名“指数平滑异同平均线”。

Moving Average 很好理解,一个区间内的价格平均数,由于区间随时间平移,因此有了一个形象的名字“Moving Average”(移动平均线)。

关于算均值的方法有若干个。

  • Simple Moving Average(简单移动平均):即算术平均数
  • Exponential Moving Average (指数平均数)
    指数平均数公式 Avgt=αPricet+(1α)Avgt1
    α 是“平滑指数”,一般取 2N+1
    本质上是一种加权平均,最新的价格的权值为 2N+1

其他的平均线就暂且不提

这个名字不是很好理解,Convergence是聚合度,Divergence是散度。

用”/”这个符号可以解释成“或”

Convergence or Divergence。

聚合或离散,比起“异同”这样一个状态词,Convergence与Divergence更应该是表示变化的过程。

MACD 算法

MACD要依次计算五个时间序列:
+ 短周期指数均线 FMA (快线,一般周期取12)
+ 长周期指数均线 SMA (慢线,一般周期取26)
+ 快慢均线之差DIFF(DIFF = FMA - SMA)
+ DIFF的指数平均线DMA(一般周期取9)
+ DIF与DEA之差MACD

网上有所谓“双线MACD”的说法,其实就是将DIFF、DEMA画成线,MACD画成柱的做法。

MT5中自带一个“(单线)MACD”的指标,其做法与大众做法不一致,它将DIFF画成柱状图,DIFF使用简单算术平均处理成DMA。尽管走了非主流的路线,但思想是没有问题的:首先,DIFF是柱状图还是连线图并没有本质区别;其次,指数平均线与算术平均线没有绝对的正误之分,都是移动平均线;最后,将MACD显式计算为两者之差 与描述DIF与DMA的金叉死叉是类似的事情。主要还是看习惯

浅析 MACD

快慢均线之差 DIFF 是为了代替快慢均线的金叉死叉分析。

因为两线的金叉死叉有时候是不符合直觉的,不是那么自然。

通常有一种方法:计算两线之差DIFF,将FMA、SMA金叉死叉转化为DIFF是正是负的问题。

快均线FMA对价格的变化比SMA更敏感。

当价格上行时,FMA的上升幅度大于SMA,当FMA自下而上击穿SMA(金叉)时,表示上升趋势的开始,此时,DIFF=FMA-SMA为正。

反之,当价格下行时,FMA的下降幅度大于SMA,当FMA自上而下击穿SMA(死叉)时,表示下降趋势的开始,此时,DIFF=FMA-SMA为负。

所以,DIFF是可以描述金叉死叉的,本质上是价格的变化率。

有趣的是,数学中微分(Differential)与差(DIFF)同源,意思是一样的。微分一开始还是描述一些物理概念的,如速度、加速度等。 MA作为价格的均值,其量纲与价格相同;则DIFF则一定程度上描述了价格的变化率。因此,总体呈上行态时,DIFF为正;总体呈下形态时,DIFF为负。理论上来说,SMA、FMA的周期越小,DIFF越接近“瞬时速度”,对于价格变动越是敏感,可以达到无限接近、无限敏感。然而现实是,因为相对论因果律的作用,均线总是滞后于价格,所以无论怎么接近真实价格的变动速度,也不可能超越价格变动。

DMA是DIFF的均线,本质上是价格变化率的均值,结合其固定的周期,代表的意义是“实际变化的价格”,即在周期区间内,价格变化的量。当价格在周期内总体上升时,DMA为正;反之为负。

从量纲上看 DMA与DIFF是一致的,性质是一致的,DMA的值域一定是DIFF值域的子集。DMA与DIFF共同扮演“速度”这一概念。

DIFF与DMA的差MACD是价格变化率的变化率,代表的意义是“驱动价格变化的因素”,是一种“势”。

继续沿用动力学的概念,MACD即是“加速度”,其值可直接与“力”正比。MACD在图上的图例是,力在时间上的积累为动量,即MACD岛的面积,动量与速度可正比,因此通过MACD岛的面积可以推出DIFF的变化情况,进而预测价格的走势。

MACD岛的面积越大,其对DIFF的影响越大。
MACD岛为正,则DIFF、DMA上升。
MACD岛为负,则DIFF、DMA下降。

附:双线MACD代码

//+------------------------------------------------------------------+
//| MACD.mq5 |
//| Copyright 2016, Izumo Riki |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Izumo Riki"
#property link "https://www.mql5.com"
#property version "1.00"

#include <MovingAverages.mqh>

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 3
//--- plot DIFF
#property indicator_label1 "DIFF"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot DMA
#property indicator_label2 "DMA"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrYellow
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot MACD
#property indicator_label3 "MACD"
#property indicator_type3 DRAW_HISTOGRAM
#property indicator_color3 clrChartreuse
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- input parameters
input int                InpFastEMA = 12;               // Fast EMA period
input int                InpSlowEMA = 26;               // Slow EMA period
input int                InpDiffEMA = 9;                // DIFF EMA period
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied price

//--- indicator buffers
double         DIFFBuffer[];
double         DMABuffer[];
double         MACDBuffer[];
double         ExtFastMaBuffer[];
double         ExtSlowMaBuffer[];
//--- MA handles
int            ExtFastMaHandle;
int            ExtSlowMaHandle;

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, DIFFBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, DMABuffer, INDICATOR_DATA);
   SetIndexBuffer(2, MACDBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, ExtFastMaBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(4, ExtSlowMaBuffer, INDICATOR_CALCULATIONS);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpDiffEMA-1);
//--- name for Dindicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME, "MACD(" + string(InpFastEMA) + "," + string(InpSlowEMA) + "," + string(InpDiffEMA) + ")");
//--- get MA handles
   ExtFastMaHandle=iMA(NULL, 0, InpFastEMA, 0, MODE_EMA, InpAppliedPrice);
   ExtSlowMaHandle=iMA(NULL, 0, InpSlowEMA, 0, MODE_EMA, InpAppliedPrice);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]) {
//--- we can copy not all data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated < 0) to_copy = rates_total;
   else {
      to_copy = rates_total - prev_calculated;
      if(prev_calculated > 0) to_copy++;
   }
//--- get Fast EMA buffer
   CopyBuffer(ExtFastMaHandle, 0, 0, to_copy, ExtFastMaBuffer);
//--- get SlowEMA buffer
   CopyBuffer(ExtSlowMaHandle, 0, 0, to_copy, ExtSlowMaBuffer);
//--- calculate domain
   int from, to;
   if(prev_calculated == 0) from = 0;
   else from = prev_calculated - 1;
   to = rates_total;
//--- calculate DIFF
   for(int i = from; i < to; i++){
      DIFFBuffer[i] = ExtFastMaBuffer[i - from] - ExtSlowMaBuffer[i - from];
   }
//--- calculate DMA 
   ExponentialMAOnBuffer(rates_total, prev_calculated, 0, InpDiffEMA, DIFFBuffer, DMABuffer);
//--- calculate MACD
   for(int i = from; i < to; i++)
      MACDBuffer[i] = (DIFFBuffer[i] - DMABuffer[i]);
//--- OnCalculate done. Return new prev_calculated.
   return to;
  }
//+------------------------------------------------------------------+
相关文章
相关标签/搜索