Viewing the resource: Understanding and Implementing the "2 MA IND DASHBOARD"

Understanding and Implementing the "2 MA IND DASHBOARD"

Allan Munene Mutiiria 2025-06-03 22:08:37 184 Views
The "2 MA IND DASHBOARD" is a beginner-friendly, trend-following trading strategy coded in MQL5 for ...

Introduction

Welcome, new traders, to the "2 MA IND DASHBOARD"! This MQL5 strategy for MetaTrader 5 is perfect for beginners. We use two Simple Moving Averages—a "5-period SMA" (fast) and a "10-period SMA" (slow)—to track trends across 9 timeframes, from 1 minute to 1 month. A visual dashboard appears on your chart, with labels and arrows showing trend directions and a final signal: buy, sell, or neutral. This article walks you through every step, from setup to code, in newbie-friendly detail.

Understanding the Strategy

As a beginner, think of this strategy as a map for trading. We use two lines: the "5-period SMA" averages the last 5 closing prices, moving quickly, and the "10-period SMA" averages 10, moving slower. When the fast "SMA" is above the slow one, it hints at an uptrend—prices may rise. When it’s below, it suggests a downtrend—prices may fall. We check this across 9 timeframes (like 1-minute, 1-hour, daily) to get a big picture. Then, we count: more uptrends mean buy, more downtrends mean sell, or equal means neutral. The dashboard shows this visually with text and arrows, making it easy to follow. See below.

Implementation Code

Below is the MQL5 code for the "2 MA IND DASHBOARD". We’re building an Expert Advisor (EA) for MetaTrader 5, and we’ll explain larger chunks step by step, connecting each part so you, as a newbie, can see how it all works together.

//+------------------------------------------------------------------+
//|                                           2 MA IND DASHBOARD.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#define BTN_MAIN "BTN_MAIN"
#define Desc "Desc "
#define Dir "Dir "
#define LABEL "LABEL"
#define XS1 70
#define YS1 25

ENUM_TIMEFRAMES periods[] = {PERIOD_M1,PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1,PERIOD_W1,PERIOD_MN1};

string truncPrds(ENUM_TIMEFRAMES period){
   string prd = StringSubstr(EnumToString(period),7);
   return prd;
}

int handleMA1_Id;
int handleMA2_Id;
double ma1_Data_Val[];
double ma2_Data_Val[];

Let’s start at the top! The "#property" lines are metadata, like a label on a toy box: "copyright" tells us MetaQuotes Ltd. made this in 2024, "link" points to their site, and "version" says it’s 1.00. We use "#define" to set constants—shortcuts like "BTN_MAIN" for a rectangle name, "Desc" and "Dir" for label prefixes, and "XS1" (70) and "YS1" (25) for positioning spaces. The "periods" array lists 9 timeframes, from "PERIOD_M1" (1 minute) to "PERIOD_MN1" (1 month). The "truncPrds" function takes a timeframe (e.g., "PERIOD_M5"), uses "StringSubstr" to cut the name to “M5”, and returns it for display. Then, we define global variables: "handleMA1_Id" and "handleMA2_Id" store references for our "SMAs", and "ma1_Data_Val" and "ma2_Data_Val" are arrays (lists) to hold "SMA" values.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
//---
   int counts_buy = 0, counts_sell = 0;
   
   createRecLabel(BTN_MAIN,180,70,630,80,clrCornsilk,2,clrBlue);
   for (int i=0; i<ArraySize(periods); i++){
      createLabel(Desc+IntegerToString(i),200+i*XS1,80,truncPrds(periods[i]));
      createLabel(Dir+IntegerToString(i),(200-5)+i*XS1,80+20,CharToString(182),clrBlack,30,"Wingdings");
      
      handleMA1_Id = iMA(_Symbol,periods[i],5,0,MODE_SMA,PRICE_CLOSE);
      handleMA2_Id = iMA(_Symbol,periods[i],10,0,MODE_SMA,PRICE_CLOSE);
      
      Print("\nSelect: ",truncPrds(periods[i]));
      Print("H MA1: ",handleMA1_Id,", H MA2: ",handleMA2_Id);
      
      ArraySetAsSeries(ma1_Data_Val,true);
      ArraySetAsSeries(ma2_Data_Val,true);
      
      CopyBuffer(handleMA1_Id,0,0,3,ma1_Data_Val);
      CopyBuffer(handleMA2_Id,0,0,3,ma2_Data_Val);
      
      Print("MA1->0 ",DoubleToString(ma1_Data_Val[0],_Digits+1));
      Print("MA2->0 ",DoubleToString(ma2_Data_Val[0],_Digits+1));
      
      color text_clr;
      uchar code;
      
      if (ma1_Data_Val[0] > ma2_Data_Val[0]){
         text_clr=clrBlue; code = 217;
         counts_buy += 1;
      }
      else if (ma1_Data_Val[0] < ma2_Data_Val[0]){
         text_clr=clrRed; code = 218;
         counts_sell += 1;
      }
      else {
         text_clr=clrBlack; code = 182;
      }
      update_Label(Dir+IntegerToString(i),CharToString(code),text_clr);
   }
   
   createLabel(LABEL,220,30,"NEUTRAL SIG",clrBlack,30,"Times New Roman bold");
   
   Print("Total Counts = ",counts_buy+counts_sell);
   Print("BUY = ",counts_buy,", SELL = ",counts_sell);
   
   if (counts_buy > counts_sell){
      update_Label(LABEL,"BUY SIGNAL",clrBlue);
   }
   else if (counts_buy < counts_sell){
      update_Label(LABEL,"SELL SIGNAL",clrRed);
   }
   else {
      update_Label(LABEL,"NEUTRAL SIG",clrBlack);
   }
   
//---
   return(INIT_SUCCEEDED);
}

Now, we tackle the "OnInit" function, which runs once when you load the EA in MetaTrader 5—think of it as setting up your game board. We start with "counts_buy" and "counts_sell" at 0 to track buy and sell signals. Using "createRecLabel", we draw a rectangle ("BTN_MAIN") at position (180,70) with size 630x80, a cornsilk background, and a blue border—our dashboard’s base. Then, we loop through the "periods" array with "ArraySize" to get its length (9). For each timeframe, we:

  1. Use "createLabel" to show the timeframe name (e.g., “M5”) via "truncPrds", positioned at 200+i*"XS1",80.
  2. Add a direction label (e.g., "Dir 0") with "createLabel", showing a neutral arrow ("CharToString(182)") in "Wingdings" font at 195+i*"XS1",100.
  3. Set "handleMA1_Id" and "handleMA2_Id" with "iMA" for a "5-period SMA" and "10-period SMA" on closing prices ("PRICE_CLOSE") for each timeframe.
  4. Log these handles and timeframe with "Print" for checking.
  5. Sort "ma1_Data_Val" and "ma2_Data_Val" with "ArraySetAsSeries" so the newest value is at index 0.
  6. Use "CopyBuffer" to grab the last 3 values of each "SMA" into the arrays, and "Print" the current values with "DoubleToString" for precision.
  7. Compare "ma1_Data_Val[0]" (fast "SMA") to "ma2_Data_Val[0]" (slow "SMA"): if higher, set blue color and arrow 217, add to "counts_buy"; if lower, red and arrow 218, add to "counts_sell"; else, black and arrow 182.
  8. Update the direction label with "update_Label" to show the arrow and color. Finally, we add a "LABEL" at 220,30 saying "NEUTRAL SIG", log counts with "Print", and update "LABEL" to "BUY SIGNAL" (blue) if buys win, "SELL SIGNAL" (red) if sells win, or "NEUTRAL SIG" (black) if tied. We end with "return(INIT_SUCCEEDED)" to confirm setup.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){
//---
   int counts_buy = 0, counts_sell = 0;
   
   for (int i=0; i<ArraySize(periods); i++){
      handleMA1_Id = iMA(_Symbol,periods[i],5,0,MODE_SMA,PRICE_CLOSE);
      handleMA2_Id = iMA(_Symbol,periods[i],10,0,MODE_SMA,PRICE_CLOSE);
      
      Print("\nSelect: ",truncPrds(periods[i]));
      Print("H MA1: ",handleMA1_Id,", H MA2: ",handleMA2_Id);
      
      ArraySetAsSeries(ma1_Data_Val,true);
      ArraySetAsSeries(ma2_Data_Val,true);
      
      CopyBuffer(handleMA1_Id,0,0,3,ma1_Data_Val);
      CopyBuffer(handleMA2_Id,0,0,3,ma2_Data_Val);
      
      Print("MA1->0 ",DoubleToString(ma1_Data_Val[0],_Digits+1));
      Print("MA2->0 ",DoubleToString(ma2_Data_Val[0],_Digits+1));
      
      color text_clr;
      uchar code;
      
      if (ma1_Data_Val[0] > ma2_Data_Val[0]){
         text_clr=clrBlue; code = 217;
         counts_buy += 1;
      }
      else if (ma1_Data_Val[0] < ma2_Data_Val[0]){
         text_clr=clrRed; code = 218;
         counts_sell += 1;
      }
      else {
         text_clr=clrBlack; code = 182;
      }
      update_Label(Dir+IntegerToString(i),CharToString(code),text_clr);
   }
   
   Print("Total Counts = ",counts_buy+counts_sell);
   Print("BUY = ",counts_buy,", SELL = ",counts_sell);
   
   if (counts_buy > counts_sell){
      update_Label(LABEL,"BUY SIGNAL",clrBlue);
   }
   else if (counts_buy < counts_sell){
      update_Label(LABEL,"SELL SIGNAL",clrRed);
   }
   else {
      update_Label(LABEL,"NEUTRAL SIG",clrBlack);
   }   
}

Next, we move to cleanup and real-time updates. The "OnDeinit" function runs when you remove the EA—think of it as packing up your tools. It takes a "reason" (why it’s stopping), but we leave it empty as no cleanup is needed yet. Then, the "OnTick" function runs on every price tick—a tiny price change. This keeps our dashboard live! We reset "counts_buy" and "counts_sell" to 0, then loop through "periods" again. For each timeframe, we:

  1. Recreate "handleMA1_Id" and "handleMA2_Id" with "iMA" for fresh "5-period" and "10-period SMA" values.
  2. Log the timeframe and handles with "Print" for tracking.
  3. Sort "ma1_Data_Val" and "ma2_Data_Val" with "ArraySetAsSeries" for newest-first order.
  4. Fill arrays with "CopyBuffer" for the latest 3 "SMA" values, and "Print" current values.
  5. Check if "ma1_Data_Val[0]" is above "ma2_Data_Val[0]" (blue, arrow 217, add to "counts_buy"), below (red, arrow 218, add to "counts_sell"), or equal (black, arrow 182).
  6. Update direction labels with "update_Label". We log total counts, buys, and sells with "Print", then update "LABEL" to "BUY SIGNAL" (blue), "SELL SIGNAL" (red), or "NEUTRAL SIG" (black) based on counts, keeping your dashboard current.

//+------------------------------------------------------------------+
//|     Function to create rectangle label                           |
//+------------------------------------------------------------------+
bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {
    ResetLastError();
    
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false);
    }
    
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD);
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD);
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS);
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS);
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg);
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType);
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle);
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder);
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder);
    ObjectSetInteger(0, objName, OBJPROP_BACK, false);
    ObjectSetInteger(0, objName, OBJPROP_STATE, false);
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false);
    
    ChartRedraw(0);
    
    return (true);
}

//+------------------------------------------------------------------+
//|     Function to create text label                                |
//+------------------------------------------------------------------+
bool createLabel(string objName, int xD, int yD,
                 string txt, color clrTxt = clrBlack, int fontSize = 12,
                 string font = "Arial Rounded MT Bold") {
    ResetLastError();

    if (!ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError);
        return (false);
    }

    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD);
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD);
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
    ObjectSetString(0, objName, OBJPROP_TEXT, txt);
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt);
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize);
    ObjectSetString(0, objName, OBJPROP_FONT, font);
    ObjectSetInteger(0, objName, OBJPROP_BACK, false);
    ObjectSetInteger(0, objName, OBJPROP_STATE, false);
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false);

    ChartRedraw(0);

    return (true);
}

bool update_Label(string objName, string txt, color clrTxt = clrBlack) {
   int found = ObjectFind(0,objName);
   if (found < 0){
      ResetLastError();
      Print("UNABLE TO FIND THE OBJ: ",objName," ERR CODE: ",_LastError);
      return (false);
   }
   else {
      ObjectSetString(0, objName, OBJPROP_TEXT, txt);
      ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt);
      ChartRedraw(0);
      
      return (true);
   }
}

To wrap up, we build helper functions to draw our dashboard. The "createRecLabel" function makes a rectangle: we pass a name, position ("xD","yD"), size ("xS","yS"), colors, and border style. We clear errors with "ResetLastError", create an "OBJ_RECTANGLE_LABEL" with "ObjectCreate", and set properties like "OBJPROP_XDISTANCE" (x position), "OBJPROP_YSIZE" (height), "OBJPROP_BGCOLOR" (background), and more. If it fails, we "Print" an error and return false; else, we redraw the chart with "ChartRedraw" and return true. Next, "createLabel" makes text labels: we pass a name, position, text, color, and font size. We create an "OBJ_LABEL", set "OBJPROP_TEXT" for content, "OBJPROP_COLOR" for color, and "OBJPROP_FONT" (default "Arial Rounded MT Bold"), then redraw. Finally, "update_Label" updates labels: we check if the object exists with "ObjectFind", and if found, update "OBJPROP_TEXT" and "OBJPROP_COLOR", redraw, and return true; if not, we log an error. These build and refresh your visual dashboard!

Conclusion

The "2 MA IND DASHBOARD" is a simple, visual strategy for new traders. We’ve set variables, built a dashboard in "OnInit", updated it in "OnTick", and drawn it with helper functions. Test this in MetaTrader 5!

Disclaimer: For education only. Trading is risky—test on a demo account first.

Disclaimer: The ideas and strategies presented in this resource are solely those of the author and are intended for informational and educational purposes only. They do not constitute financial advice, and past performance is not indicative of future results. All materials, including but not limited to text, images, files, and any downloadable content, are protected by copyright and intellectual property laws and are the exclusive property of Forex Algo-Trader or its licensors. Reproduction, distribution, modification, or commercial use of these materials without prior written consent from Forex Algo-Trader is strictly prohibited and may result in legal action. Users are advised to exercise extreme caution, perform thorough independent research, and consult with qualified financial professionals before implementing any trading strategies or decisions based on this resource, as trading in financial markets involves significant risk of loss.

Recent Comments

Go to discussion to Comment or View other Comments

No comments yet. Be the first to comment!