创建具有图形控制选项的指标·综合运用
🎛️

创建具有图形控制选项的指标·综合运用

(3/3)·把传统、Elder、三色OSMA等五种MACD变型塞进一个带图形开关的指标里

案例拆解新手友好 第 3/3 篇
很多人在MT5里改MACD只是换换参数,却从没想过把五种变型做成下拉切换。手动切图表模板既慢又容易看错信号,其实用向导加图形控件就能一次搞定。

在指标里塞两个图表开关按钮

这段逻辑演示了如何不依赖外部脚本,直接在自定义指标里画出两个右上角按钮,用来切换 MACD 主图线的显示状态。按钮坐标用 CORNER_RIGHT_UPPER 锚定,X 距离 75 像素、Y 距离分别 5 和 30,尺寸 70×20,字号 8,且设成不可选中,避免误拖。 核心判定在尾部:若名为 ShowMACD 的按钮 OBJPROP_STATE 不等于 1,就把 PlotIndex 0 和 1 的绘制类型设为 DRAW_NONE,主线与信号线直接从图表消失;否则走 else 分支恢复绘制。 外汇与贵金属波动剧烈、杠杆风险高,这类显示开关仅改变视觉呈现,不改变任何信号计算逻辑,实盘使用前建议在 MT5 策略测试器里先验证按钮状态读取是否如预期。

MQL5 / C++
const class="type">long &volume[],
const class="type">int &spread[])
  {
  ArraySetAsSeries(HistogramBuffer,false);
  ArraySetAsSeries(HistogramColors,false);
  class="type">int MACDhadling=iMACD(NULL,class="num">0,Fast,Slow,Signal,PRICE_CLOSE);
  CopyBuffer(MACDhadling,class="num">0,class="num">0,rates_total,MACDlineBuffer);
  CopyBuffer(MACDhadling,class="num">1,class="num">0,rates_total,SignallineBuffer);
  for(class="type">int i=class="num">0;i<rates_total;i++) { HistogramBuffer[i]=MACDlineBuffer[i]-SignallineBuffer[i];HistogramColors[i]=class="num">1; }
  ObjectCreate(class="num">0,"ShowMACD",OBJ_BUTTON,ChartWindowFind(),class="num">100,class="num">100);
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_XDISTANCE,class="num">75);
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_YDISTANCE,class="num">5);
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetString(class="num">0,"ShowMACD",OBJPROP_TEXT,"ShowMACD");
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_FONTSIZE,class="num">8);
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_XSIZE,class="num">70);
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_YSIZE,class="num">20);
  ObjectSetInteger(class="num">0,"ShowMACD",OBJPROP_SELECTABLE,false);
  ObjectCreate(class="num">0,"ShowOsMA",OBJ_BUTTON,ChartWindowFind(),class="num">100,class="num">100);
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_XDISTANCE,class="num">75);
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_YDISTANCE,class="num">30);
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
  ObjectSetString(class="num">0,"ShowOsMA",OBJPROP_TEXT,"Show OsMA");
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_FONTSIZE,class="num">8);
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_XSIZE,class="num">70);
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_YSIZE,class="num">20);
  ObjectSetInteger(class="num">0,"ShowOsMA",OBJPROP_SELECTABLE,false);
  if(ObjectGetInteger(class="num">0,"ShowMACD",OBJPROP_STATE)!=class="num">1)
     {
       PlotIndexSetInteger(class="num">0,PLOT_DRAW_TYPE,DRAW_NONE);
       PlotIndexSetInteger(class="num">1,PLOT_DRAW_TYPE,DRAW_NONE);

}
  else
     {

「用按钮切换 MACD 绘制样式」

在指标初始化尾部,先用 PlotIndexSetInteger 把前两条线强制设为 DRAW_LINE,保证快线慢线永远以线性呈现,不会因外部设置丢失画法。 OsMA 柱体的显隐由名为 ShowOsMA 的图表对象状态控制:若其 OBJPROP_STATE 不等于 1,第 2 号绘图索引改为 DRAW_NONE 直接隐藏;否则切到 DRAW_COLOR_HISTOGRAM 画彩色柱。 随后在右下角(CORNER_RIGHT_LOWER)创建两个不可选按钮:2color 距右 75 像素、距底 50 像素,尺寸 70×20,字号 8;Impulse 距底 25 像素,其余几何参数一致。按钮文字初值分别为 MultiColor 与 Impulse。 如果 2color 按钮处于按下状态(OBJPROP_STATE 为真),就把它的标签改写成 2ColorMACD,否则维持 MultiColor——这给了交易者在 MT5 上不重编译就切换配色方案的直接入口。外汇与贵金属波动剧烈,这类视觉开关只辅助读图,不构成方向判断。

MQL5 / C++
  PlotIndexSetInteger(class="num">0,PLOT_DRAW_TYPE,DRAW_LINE);
  PlotIndexSetInteger(class="num">1,PLOT_DRAW_TYPE,DRAW_LINE);

}
  if(ObjectGetInteger(class="num">0,"ShowOsMA",OBJPROP_STATE)!=class="num">1)
   {
     PlotIndexSetInteger(class="num">2,PLOT_DRAW_TYPE,DRAW_NONE);

}
  else
   {
     PlotIndexSetInteger(class="num">2,PLOT_DRAW_TYPE,DRAW_COLOR_HISTOGRAM);

}
  ObjectCreate(class="num">0,"2color",OBJ_BUTTON,ChartWindowFind(),class="num">100,class="num">100);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_XDISTANCE,class="num">75);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_YDISTANCE,class="num">50);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_CORNER,CORNER_RIGHT_LOWER);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_FONTSIZE,class="num">8);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_XSIZE,class="num">70);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_YSIZE,class="num">20);
  ObjectSetInteger(class="num">0,"2color",OBJPROP_SELECTABLE,false);
  ObjectSetString(class="num">0,"2color",OBJPROP_TEXT,"MultiColor");
  ObjectCreate(class="num">0,"Impulse",OBJ_BUTTON,ChartWindowFind(),class="num">100,class="num">100);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_XDISTANCE,class="num">75);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_YDISTANCE,class="num">25);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_CORNER,CORNER_RIGHT_LOWER);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_FONTSIZE,class="num">8);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_XSIZE,class="num">70);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_YSIZE,class="num">20);
  ObjectSetInteger(class="num">0,"Impulse",OBJPROP_SELECTABLE,false);
  ObjectSetString(class="num">0,"Impulse",OBJPROP_TEXT,"Impulse");
  if(ObjectGetInteger(class="num">0,"2color",OBJPROP_STATE)) ObjectSetString(class="num">0,"2color",OBJPROP_TEXT,"2ColorMACD");
  else ObjectSetString(class="num">0,"2color",OBJPROP_TEXT,"MultiColor");

◍ 双色与三色脉冲的着色分支

这段逻辑决定了直方图上色到底看几层确认。先根据界面开关切换标签文字:若名为 Impulse 的物件处于激活态,文本写 Impulse,否则写 Elder's;同时用 iMA 取周期 EldersEMA、模式 MODE_EMA、价格 PRICE_CLOSE 的均线句柄,经 CopyBuffer 把数据塞进 EldersiEMA 数组,供后续比较。 若 2color 开关打开,只比直方图自身前后根:HistogramBuffer[i] 大于前一根则颜色索引 0,小于则 1,不判方向强度。这种画法在震荡市里可能更敏感,但也更容易被毛刺刷色。 2color 关闭时才进真正的脉冲确认。Impulse 开时,要求直方图与 MACDlineBuffer 同向上行才给色 0,同向下行给色 1,其余情况归为色 2(犹豫区);Impulse 关时把 MACD 线换成 EldersiEMA 均线做同样比对。外汇与贵金属波动大,色 2 占比高时往往意味趋势动能未共振,入场概率倾向偏弱。 最后 return(rates_total) 把已处理柱数交还系统,下一 tick 从缓存接续,避免重复算整段历史。

MQL5 / C++
if(ObjectGetInteger(class="num">0,"Impulse",OBJPROP_STATE)) ObjectSetString(class="num">0,"Impulse",OBJPROP_TEXT,"Impulse");
  else ObjectSetString(class="num">0,"Impulse",OBJPROP_TEXT,"Elder&class="macro">#x27;s");
  CopyBuffer(iMA(NULL,class="num">0,EldersEMA,class="num">0,MODE_EMA,PRICE_CLOSE),class="num">0,class="num">0,rates_total,EldersiEMA);
  if(ObjectGetInteger(class="num">0,"2color",OBJPROP_STATE))
    {
      for(class="type">int i=class="num">1;i<rates_total;i++)
        {
         if(HistogramBuffer[i] > HistogramBuffer[i-class="num">1]) HistogramColors[i]=class="num">0;
         if(HistogramBuffer[i] < HistogramBuffer[i-class="num">1]) HistogramColors[i]=class="num">1;
        }
    }
  else
    {
      if(ObjectGetInteger(class="num">0,"Impulse",OBJPROP_STATE))
        {
         for(class="type">int i=class="num">1;i<rates_total;i++)
           {
            if((HistogramBuffer[i]>HistogramBuffer[i-class="num">1]) && (MACDlineBuffer[i]>MACDlineBuffer[i-class="num">1])) HistogramColors[i]=class="num">0;
            else
              {
               if((HistogramBuffer[i]<HistogramBuffer[i-class="num">1]) && (MACDlineBuffer[i]<MACDlineBuffer[i-class="num">1])) HistogramColors[i]=class="num">1;
               else HistogramColors[i]=class="num">2;
              }
           }
        }
      else
        {
         for(class="type">int i=class="num">1;i<rates_total;i++)
           {
            if((HistogramBuffer[i]>HistogramBuffer[i-class="num">1]) && (EldersiEMA[i]>EldersiEMA[i-class="num">1])) HistogramColors[i]=class="num">0;
            else
              {
               if((HistogramBuffer[i]<HistogramBuffer[i-class="num">1]) && (EldersiEMA[i]<EldersiEMA[i-class="num">1])) HistogramColors[i]=class="num">1;
               else HistogramColors[i]=class="num">2;
              }
           }
        }
    }
class=class="str">"cmt">//--- 返回prev_calculated的值用于下一次调用
  class="kw">return(rates_total);
}

记住这一条就够了

图形控件这套思路在 MT5 里落地的关键,是把交互从鼠标点击转成全局变量状态驱动。原文评论区里 Mykola Demko 想在 MT4 跑同款指标被劝退,根因是 MQL4 缺 OBJ_BUTTON 这类对象,只能拿挂热键的脚本改全局变量凑合。 外汇与贵金属市场高波动、高杠杆,任何控件方案都只是辅助你看清盘口,不替你下注。真要验证,开 MT5 新建指标把下面这行对象类型丢进 OnChartEvent,按一次键看按钮是否实时响应,比读十篇文都实在。 [OBJ_BUTTON] 是 MT5 图表里可点击控件的底层类型,缺了它 MT4 那套按钮逻辑直接废掉。

MQL5 / C++
OBJ_BUTTON
交给小布盯盘看多形态切换
这些变型的诊断小布盯盘的AIGC已内置,打开对应品种页即可看到不同MACD形态的概率分布,你只管决定用哪套。

常见问题

句柄只在第一次创建时有效,若参数动态变化需先释放旧句柄再重新获取,避免内存泄漏与数据错位。
直接复用两条已复制缓冲区相减可保证索引一致,减少额外计算并避免时序方向不同导致的错位。
小布盯盘内置了常见MACD变型的诊断视图,若你自定义了ex5文件也可在品种页手动挂载观察,不必重复写面板逻辑。
变型少于五个时用下拉框更省空间,按钮适合频繁切换;本例五种变型用下拉能降低图表遮挡概率。