MACD,Moving Average Convergence / Divergence,中文译名“指数平滑异同平均线”。
Moving Average 很好理解,一个区间内的价格平均数,由于区间随时间平移,因此有了一个形象的名字“Moving Average”(移动平均线)。
关于算均值的方法有若干个。
其他的平均线就暂且不提
这个名字不是很好理解,Convergence是聚合度,Divergence是散度。
用”/”这个符号可以解释成“或”
Convergence or Divergence。
聚合或离散,比起“异同”这样一个状态词,Convergence与Divergence更应该是表示变化的过程。
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的金叉死叉是类似的事情。主要还是看习惯。
快慢均线之差 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.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;
}
//+------------------------------------------------------------------+