MACandlestick Indicator for MT5

Author: Roberto Jacobs (3rjfx)

Get the MACandlestick indicator for MT5. A powerful MQL5 tool for seamless trend analysis, momentum detection, and customizable trading notifications.

Introduction

Welcome to Forex Home Expert. As active MQL5 programmers and dedicated market analysts since 2012, we understand the constant challenges traders face when trying to filter out market noise.
Today, we are proud to introduce and explain one of our most reliable custom creations: the MACandlestick Indicator for MT5.
We designed this tool to provide crystal-clear visual representation of market trends, transforming traditional price action into a smoothed, moving average-based candlestick format.
Whether you are a seasoned professional or a newcomer looking for robust Trading Tools, this indicator is built to enhance your Forex Analysis and streamline your decision-making process.

Moving Average Candlestick Indicator for MT5
Figure 1: Moving Average Candlestick Indicator for MT5

1. What is the MACandlestick Indicator?

The MACandlestick Indicator is a custom technical analysis tool developed specifically for the MetaTrader 5 (MT5) platform. Unlike standard candlestick charts that plot the raw open, high, low, and close prices of an asset, our indicator calculates and plots candlesticks based on Moving Average (MA) values.
By applying a Moving Average to the open, high, low, and close prices individually, we effectively smooth out the erratic price fluctuations that often lead to false signals.

This unique approach to Momentum Detection allows traders to see the underlying trend with remarkable clarity. When the moving average-based close is higher than the moving average-based open, the indicator paints a bullish candlestick (defaulted to WhiteSmoke). Conversely, when the moving average-based close is lower than the open, it paints a bearish candlestick (defaulted to Red).
This visual simplicity makes it an invaluable component of any comprehensive Forex Strategy, helping you identify the dominant market direction without getting distracted by minor, insignificant price spikes.

2. Key Features and Benefits

  • Smoothed Price Action: By utilizing Moving Averages for candlestick construction, we eliminate the "noise" of volatile markets, providing a cleaner chart for better Forex Analysis.
  • Customizable Parameters: We have included flexible input settings, allowing you to adjust the MA period and the MA method (e.g., Exponential, Simple, Smoothed, or Linear Weighted) to perfectly match your preferred Trading strategy.
  • Advanced Alert System: We know that staring at charts all day is not always feasible. That is why we integrated a comprehensive alert system. You can enable pop-up alerts, MT5 Email Alerts, and mobile Trading Notifications to ensure you never miss a potential market shift.
  • Reliable Buy Sell Signals: The color transition of the MACandlestick bars serves as a foundational element for generating high-probability trading signals, giving you confidence in your entry and exit points.

3. A Deep Dive into the MQL5 Source Code

For our technically inclined readers and fellow developers, we believe in transparency and education. Understanding how a tool works under the hood empowers you to use it more effectively. Below, we break down the core architecture of the MACandlestick.mq5 source code, explaining the logic we implemented to ensure optimal performance and reliability.

1. Global Scope and Input Properties

At the very beginning of the source code, we define the global properties and input parameters. This section is crucial because it dictates how the indicator behaves and how users can interact with it. We use the #property directives to specify that the indicator draws in the main chart window, utilizes six data buffers, and creates five distinct plots. The primary plot uses the DRAW_COLOR_CANDLES style, which allows us to dynamically change the candlestick colors based on trend direction.

We also define an enumeration (enum YN) for simple "Yes" or "No" selections, making the user interface clean and intuitive. The input parameters include inpMaPeriod (defaulting to 5) and inpMethod (defaulting to MODE_EMA), which control the smoothing calculation. Furthermore, we have dedicated inputs for our MQL5 Alerts system: alerts for on-screen pop-ups, UseEmailAlert for MT5 Email Alerts, UseSendnotify for push Trading Notifications, and AlertOnBar to specify exactly which completed candle should trigger the alert, preventing premature or false signals.

  
//+------------------------------------------------------------------+
//|                                               MACandlesticks.mq5 |
//|        Copyright 2022, Roberto Jacobs (3rjfx) ~ Date: 2022-08-10 |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, Roberto Jacobs (3rjfx) ~ Date: 2022-08-10"
#property link      "https://www.mql5.com/en/users/3rjfx"
#property version   "1.00"
#property description "Moving Average-based Candlestick Bar Indicator with alert features for MT5"
//--
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   5
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrWhiteSmoke,clrRed
#property indicator_label1  "MA-Lo;MA-Hi;MA-Op;MA-Cl;Trend"
//---
//-- Enumeration
enum YN
 {
   No,  
   Yes
 };
//--
//---Input parameters for MA
input int            inpMaPeriod = 5;              // Input MA Period
input ENUM_MA_METHOD   inpMethod = MODE_EMA;       // Input MA Method
//--- Input parameters for alerts
input YN                  alerts = Yes;           // Display Alerts Pop-up on Chart (Yes) or (No)
input YN           UseEmailAlert = No;            // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;            // Send Notification (Yes) or (No)
input int             AlertOnBar = 1;             // Input Alert On Bar (default bar 1)
//---
//-- buffers
double 
   MABuffer1[],
   MABuffer2[],
   MABuffer3[],
   MABuffer4[],
   MATrend[],
   MAColor[];
double
  MAOPEN[],
  MAHIGH[],
  MALOW[],
  MACLOSE[];
int 
  hMAO,
  hMAH,
  hMAL,
  hMAC;
int BRC;
int aob;
//--
//--- variable for storing alert
datetime
    altime;
int posalert,
    prevalert;
string Albase,AlSubj;    
//--- name of the indicator on a chart 
string _pname;
string indiname;
//--- we will keep the number of values in the ATR indicator 
int calculated,
    bars_calculated=0;   
//---------//  
***Copyright © 2026 3rjfx ~ For educational purposes only.***

2. The OnInit() Function

The OnInit() function is the initialization engine of our indicator. When you attach the MACandlestick to your MT5 chart, this function executes first. Here, we map the indicator buffers to their respective dynamic arrays using SetIndexBuffer. We assign specific roles to each buffer: some hold the calculated Open, High, Low, and Close values of the Moving Average, while others manage the color indexing and trend direction.

Following the buffer mapping, we call a custom helper function, SetIndicatorHandle(). This is where we request the actual Moving Average data from the MT5 terminal by calling the iMA() function four separate times—once for PRICE_OPEN, PRICE_HIGH, PRICE_LOW, and PRICE_CLOSE. Storing these handles allows us to efficiently retrieve the smoothed data later. Finally, we set the indicator's short name, which appears in the top-left corner of the chart, displaying the current timeframe, MA period, and MA method for quick reference.

  
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,MABuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,MABuffer3,INDICATOR_DATA);
   SetIndexBuffer(3,MABuffer4,INDICATOR_DATA);
   SetIndexBuffer(4,MAColor,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(5,MATrend,INDICATOR_DATA);
   //--
   SetIndicatorHandle();
   ResizeArrays();
   aob=AlertOnBar;
   //--
   _pname=MQLInfoString(MQL_PROGRAM_NAME);
   indiname="MACandlestick"+"("+strTF(Period())+","+string(inpMaPeriod)+","+EnumToString(inpMethod)+")";
   IndicatorSetString(INDICATOR_SHORTNAME,indiname);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   //--
   return(INIT_SUCCEEDED);
//---
  } //-end OnInit()
//---------//  
***Copyright © 2026 3rjfx ~ For educational purposes only.***

3. The OnCalculate() Function and Core Logic

The OnCalculate() function is the beating heart of the MACandlestick indicator. It runs every time a new tick arrives or a new bar forms. Our first step inside this function is to ensure that the Moving Average handles have calculated enough data bars by using the CalculatedHandle() and CountCopyBurrefs() helper functions. If the data is not ready, the function safely exits to prevent errors.

Once the data is verified, we use FillArrayFromBuffer() to copy the latest Moving Average values into our local arrays (MAOPEN, MAHIGH, MALOW, MACLOSE). The main calculation loop then iterates through the available bars. For each bar, we compare the MACLOSE value to the MAOPEN value. If the close is greater than or equal to the open, we classify the trend as bullish, assign a trend value of 1.0, and set the color index to 0.0 (WhiteSmoke). If the close is lower, we classify it as bearish, assign a trend value of -1.0, and set the color index to 1.0 (Red). This logical comparison is what generates the clear, visual Buy Sell Signals on your chart.

  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
                const int32_t 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 int32_t &spread[])
  {
//---
   CalculatedHandle(rates_total);
   //--
   int values_to_copy=CountCopyBurrefs(rates_total,prev_calculated);
   //--
   //--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(MAOPEN,hMAO,values_to_copy))  return(0);
   if(!FillArrayFromBuffer(MAHIGH,hMAH,values_to_copy))  return(0);
   if(!FillArrayFromBuffer(MALOW,hMAL,values_to_copy))   return(0);
   if(!FillArrayFromBuffer(MACLOSE,hMAC,values_to_copy)) return(0);
   //--
   int start;
   int min_start = 1 + aob;
//--- preliminary calculations
   if(prev_calculated==0)
     {
      MABuffer1[0]=MALOW[0];
      MABuffer2[0]=MAHIGH[0];
      MABuffer3[0]=MAOPEN[0];
      MABuffer4[0]=MACLOSE[0];
      start=2;
      start = fmax(2, min_start);
     }
   else
      start=prev_calculated;
   //--
   //---
   double MAOpen,MAHigh,MALow,MAClose;
   //---
//--- the main loop of calculations
   for(int i=start; i<BRC && !IsStopped(); i++)
     {
       MAClose= MACLOSE[i];
       MAOpen = MAOPEN[i];
       MAHigh = MAHIGH[i];
       MALow  = MALOW[i];
       //--
       if(MACLOSE[i]>=MAOPEN[i])
         {
           MABuffer1[i]=MALOW[i]; 
           MABuffer2[i]=MAHIGH[i];
           MATrend[i]=1.0;
           MAColor[i]=0.0; // set color to WhiteSmoke default
         }
       else
         {
           MABuffer1[i]=MAHIGH[i];
           MABuffer2[i]=MALOW[i];
           MATrend[i]=-1.0;
           MAColor[i]=1.0; // set color to Red default
         }
       MABuffer3[i]=MAOPEN[i];
       MABuffer4[i]=MACLOSE[i];
      //--- set alert
      if(MAColor[i-aob]==0.0 && MAColor[i-(1+aob)]==1.0) { posalert = 1; altime=time[i-aob]; }
      if(MAColor[i-aob]==1.0 && MAColor[i-(1+aob)]==0.0) { posalert =-1; altime=time[i-aob]; }
      //---
     }
   //--
   PosAlerts(posalert,altime);
//--- memorize the number of values in the Average True Range indicator
   bars_calculated=calculated;
   //---
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+  
***Copyright © 2026 3rjfx ~ For educational purposes only.***

4. Alert and Helper Functions

A standout feature of our development is the robust alert mechanism. Within the calculation loop, we monitor for color transitions. If the current bar's color index differs from the previous bar's color index (e.g., shifting from Red to WhiteSmoke), we flag a posalert state. This state is then passed to the PosAlerts() function.

The PosAlerts() function evaluates the alert state and constructs a descriptive message, such as "MACandlestick bar was Up ~ Open Buy". It then passes this message to the Do_Alerts() function. Based on your initial input preferences, Do_Alerts() will execute a combination of actions: printing the event to the MT5 Experts tab, triggering a desktop pop-up, sending an email via MT5 Email Alerts, or dispatching a mobile push message via Trading Notifications. This multi-channel approach to MQL5 trading alerts ensures you are always informed, regardless of where you are.

  
void Do_Alerts(string msgText,datetime altpos)
  {
//---
    //--
    Print(" --- "+Symbol()+": "+msgText+
          "\n --- at: ",TimeToString(altpos,TIME_DATE|TIME_MINUTES));
    //--
    if(alerts==Yes)
      {
        Alert(" --- "+Symbol()+": "+msgText+
              " --- at: ",TimeToString(altpos,TIME_DATE|TIME_MINUTES));
      }
    //--
    if(UseEmailAlert==Yes) 
      SendMail(_pname," --- "+Symbol()+" "+strTF(Period())+": "+msgText+
                       "\n --- at: "+TimeToString(altpos,TIME_DATE|TIME_MINUTES));
    //--
    if(UseSendnotify==Yes) 
      SendNotification(_pname+" --- "+Symbol()+" "+strTF(Period())+": "+msgText+
                      "\n --- at: "+TimeToString(altpos,TIME_DATE|TIME_MINUTES));
    //--
    return;
    //--
//---
  } //-end Do_Alerts()
//---------//

void PosAlerts(int curalerts,datetime altpos) 
   {
//---
    //---
    if((curalerts!=prevalert)&&(curalerts==1))
       {
         Albase=indiname;
         AlSubj=Albase+" MACandlestick bar was Up ~ Open Buy";
         Do_Alerts(AlSubj,altpos);
         prevalert=curalerts;
       }
    //---
    if((curalerts!=prevalert)&&(curalerts==-1))
       {   
         Albase=indiname;  
         AlSubj=" MACandlestick bar was Down ~ Open Sell";
         Do_Alerts(AlSubj,altpos);
         prevalert=curalerts;
       }
    //---
    return;
//---
   } //-end PosAlerts()
//---------//  
***Copyright © 2026 3rjfx ~ For educational purposes only.***

4. How to Use the MACandlestick Indicator in Your Trading Strategy

Integrating the MACandlestick Indicator into your daily routine is straightforward. We recommend using it primarily as a trend-filtering tool rather than a standalone entry mechanism.
For example, if you are employing a breakout Forex Strategy, you can use the MACandlestick to confirm the overall direction. If the MACandlestick is painting WhiteSmoke bars, you might choose to only take long (buy) breakouts, ignoring the short (sell) signals that go against the smoothed momentum.

Additionally, the customizable AlertOnBar parameter is a powerful feature for risk management. By setting this to 1 (the default), you ensure that the MQL5 Alerts only trigger after a candle has fully closed.
This prevents you from jumping into a trade based on a "repainting" or fluctuating intra-bar signal, which is a common pitfall in less sophisticated Trading Tools.
By waiting for the bar close, you validate the Momentum Detection, giving you a higher degree of confidence in your trading signals.

Frequently Asked Questions (FAQ)

Q: Does the MACandlestick Indicator repaint?

A: No, it does not repaint historical bars. Because we calculate the candlestick colors based on finalized Moving Average values and trigger our MQL5 trading alerts only on confirmed, closed bars (as dictated by the AlertOnBar setting), the signals remain fixed once the candle closes. This ensures the integrity of your backtesting and live Forex Analysis.

Q: Can I use this indicator on any timeframe?

A: Absolutely. The MACandlestick Indicator is designed to be timeframe-agnostic. Whether you are scalping on the M1 chart or swing trading on the H4 or D1 charts, the underlying Moving Average logic adapts seamlessly. We encourage you to test different inpMaPeriod settings to find the optimal balance for your specific timeframe and Trading strategy.

Conclusion

At Forex Home Expert, our mission is to equip traders with sophisticated, reliable, and easy-to-use software.
The MACandlestick Indicator for MT5 is a testament to that commitment. By transforming raw, noisy price data into smooth, easy-to-read Moving Average candlesticks, we provide you with a clearer perspective on market momentum. Combined with our highly customizable MQL5 Alerts, including MT5 Email Alerts and Trading Notifications, this indicator ensures you stay ahead of market shifts without being chained to your screen. We invite you to take, test, and integrate this powerful tool into your trading arsenal, and we look forward to supporting your journey toward consistent market success.

Vital Records

We hope that this article and the MACandlestick - Indicator for MT5 program will be useful for traders in learning and generating new ideas, thereby will be able improving your trading performance.

We hope you find our content useful and thank you for visiting the Forex Home Expert.

See you in the next article on Expert Advisor programs or indicators for MetaTrader 4, MetaTrader 5 or Python program and trading psychology.

Explore more algorithmic trading resources:

Note: This program is shared under a Copyleft/Creative Commons License (CCL) for educational purposes. There is no direct download link available. Before obtaining the source code, if you wish to support our algorithmic trading operations, you can check out something interesting for you. Then, please follow the detailed steps below to manually install it in your MQL4/MQL5 MetaEditor.

πŸ“‹ How to Install This Program (Manual Copy-Paste Guide)

Step-by-Step Instructions:

  1. Open your MQL5 MetaEditor (press F4 in MT5).
  2. Click "New" (or File > New) to create a new document.
  3. Select the program type:
    • Choose Expert Advisor (template) if this is an EA.
    • Choose Custom Indicator if this is an indicator.
  4. Enter the Name (e.g., ECN) and click "Next" twice.
  5. Click "Finish". A blank template page will be created.
  6. Scroll down and click the "Full Source Code Preview (CCL)" button below.
  7. Highlight the entire code in the preview box, right-click, and select Copy.
  8. Return to the blank MetaEditor page, Paste the code (Ctrl+V), replacing any default text.
  9. Click "Compile" (F7). Check the Toolbox panel: if there are 0 errors, your program is ready!

Summary: This section provides a manual copy-paste installation guide for MQL4/MQL5 Expert Advisors and Custom Indicators shared under CCL license. Users must open MetaEditor, create a new file, copy the source code from the preview section below, paste it into the editor, and compile the program to use it on MetaTrader 4/5 charts.

☕ Support the Developer: Click here to view something interesting for you..


//+------------------------------------------------------------------+
//|                                               MACandlesticks.mq5 |
//|        Copyright 2022, Roberto Jacobs (3rjfx) ~ Date: 2022-08-10 |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, Roberto Jacobs (3rjfx) ~ Date: 2022-08-10"
#property link      "https://www.mql5.com/en/users/3rjfx"
#property version   "1.00"
#property description "Moving Average-based Candlestick Bar Indicator with alert features for MT5"
//--
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   5
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrWhiteSmoke,clrRed
#property indicator_label1  "MA-Lo;MA-Hi;MA-Op;MA-Cl;Trend"
//---
//-- Enumeration
enum YN
 {
   No,  
   Yes
 };
//--
//---Input parameters for MA
input int            inpMaPeriod = 5;              // Input MA Period
input ENUM_MA_METHOD   inpMethod = MODE_EMA;       // Input MA Method
//--- Input parameters for alerts
input YN                  alerts = Yes;           // Display Alerts Pop-up on Chart (Yes) or (No)
input YN           UseEmailAlert = No;            // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;            // Send Notification (Yes) or (No)
input int             AlertOnBar = 1;             // Input Alert On Bar (default bar 1)
//---
//-- buffers
double 
   MABuffer1[],
   MABuffer2[],
   MABuffer3[],
   MABuffer4[],
   MATrend[],
   MAColor[];
double
  MAOPEN[],
  MAHIGH[],
  MALOW[],
  MACLOSE[];
int 
  hMAO,
  hMAH,
  hMAL,
  hMAC;
int BRC;
int aob;
//--
//--- variable for storing alert
datetime
    altime;
int posalert,
    prevalert;
string Albase,AlSubj;    
//--- name of the indicator on a chart 
string _pname;
string indiname;
//--- we will keep the number of values in the ATR indicator 
int calculated,
    bars_calculated=0;   
//---------//
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,MABuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,MABuffer3,INDICATOR_DATA);
   SetIndexBuffer(3,MABuffer4,INDICATOR_DATA);
   SetIndexBuffer(4,MAColor,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(5,MATrend,INDICATOR_DATA);
   //--
   SetIndicatorHandle();
   ResizeArrays();
   aob=AlertOnBar;
   //--
   _pname=MQLInfoString(MQL_PROGRAM_NAME);
   indiname="MACandlestick"+"("+strTF(Period())+","+string(inpMaPeriod)+","+EnumToString(inpMethod)+")";
   IndicatorSetString(INDICATOR_SHORTNAME,indiname);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   //--
   return(INIT_SUCCEEDED);
//---
  } //-end OnInit()
//---------//
//+------------------------------------------------------------------+ 
//| Indicator deinitialization function                              | 
//+------------------------------------------------------------------+ 
void OnDeinit(const int reason) 
  { 
//---
   Comment(""); 
   PrintFormat("%s: Deinitialization reason code=%d",__FUNCTION__,reason);
   Print(getUninitReasonText(reason));
   if(hMAO!=INVALID_HANDLE) IndicatorRelease(hMAO);
   if(hMAH!=INVALID_HANDLE) IndicatorRelease(hMAH);
   if(hMAL!=INVALID_HANDLE) IndicatorRelease(hMAL);
   if(hMAC!=INVALID_HANDLE) IndicatorRelease(hMAC);
   //--
   return;
//---
  } //-end OnDeinit()
//---------//
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
                const int32_t 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 int32_t &spread[])
  {
//---
   CalculatedHandle(rates_total);
   //--
   int values_to_copy=CountCopyBurrefs(rates_total,prev_calculated);
   //--
   //--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(MAOPEN,hMAO,values_to_copy))  return(0);
   if(!FillArrayFromBuffer(MAHIGH,hMAH,values_to_copy))  return(0);
   if(!FillArrayFromBuffer(MALOW,hMAL,values_to_copy))   return(0);
   if(!FillArrayFromBuffer(MACLOSE,hMAC,values_to_copy)) return(0);
   //--
   int start;
   int min_start = 1 + aob;
//--- preliminary calculations
   if(prev_calculated==0)
     {
      MABuffer1[0]=MALOW[0];
      MABuffer2[0]=MAHIGH[0];
      MABuffer3[0]=MAOPEN[0];
      MABuffer4[0]=MACLOSE[0];
      start=2;
      start = fmax(2, min_start);
     }
   else
      start=prev_calculated;
   //--
   //---
   double MAOpen,MAHigh,MALow,MAClose;
   //---
//--- the main loop of calculations
   for(int i=start; i<BRC && !IsStopped(); i++)
     {
       MAClose= MACLOSE[i];
       MAOpen = MAOPEN[i];
       MAHigh = MAHIGH[i];
       MALow  = MALOW[i];
       //--
       if(MACLOSE[i]>=MAOPEN[i])
         {
           MABuffer1[i]=MALOW[i]; 
           MABuffer2[i]=MAHIGH[i];
           MATrend[i]=1.0;
           MAColor[i]=0.0; // set color to WhiteSmoke default
         }
       else
         {
           MABuffer1[i]=MAHIGH[i];
           MABuffer2[i]=MALOW[i];
           MATrend[i]=-1.0;
           MAColor[i]=1.0; // set color to Red default
         }
       MABuffer3[i]=MAOPEN[i];
       MABuffer4[i]=MACLOSE[i];
      //--- set alert
      if(MAColor[i-aob]==0.0 && MAColor[i-(1+aob)]==1.0) { posalert = 1; altime=time[i-aob]; }
      if(MAColor[i-aob]==1.0 && MAColor[i-(1+aob)]==0.0) { posalert =-1; altime=time[i-aob]; }
      //---
     }
   //--
   PosAlerts(posalert,altime);
//--- memorize the number of values in the Average True Range indicator
   bars_calculated=calculated;
   //---
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

void SetIndicatorHandle(void)
  {
//---
   hMAO=iMA(Symbol(),0,inpMaPeriod,0,inpMethod,PRICE_OPEN);
   hMAH=iMA(Symbol(),0,inpMaPeriod,0,inpMethod,PRICE_HIGH);
   hMAL=iMA(Symbol(),0,inpMaPeriod,0,inpMethod,PRICE_LOW);
   hMAC=iMA(Symbol(),0,inpMaPeriod,0,inpMethod,PRICE_CLOSE);
   //--
   return;
//---
  } //-end SetIndicatorHandle()  
//---------//

void ResizeArrays(void)
  {
//---
   BRC=iBars(Symbol(),Period());
   ArrayResize(MABuffer1,BRC,BRC);
   ArrayResize(MABuffer2,BRC,BRC);
   ArrayResize(MABuffer3,BRC,BRC);
   ArrayResize(MABuffer4,BRC,BRC);
   ArrayResize(MATrend,BRC,BRC);
   ArrayResize(MAColor,BRC,BRC);
   //--
   ArrayResize(MAOPEN,BRC,BRC);
   ArrayResize(MAHIGH,BRC,BRC);
   ArrayResize(MALOW,BRC,BRC);
   ArrayResize(MACLOSE,BRC,BRC);
   //--
   return;
//---
  } //-end ResizeArrays()  
//---------//

int CalculatedHandle(int bars)
  {
//---
   calculated=BarsCalculated(hMAO);
   //--
   if(calculated<bars)
     {
      Print("Not all data of MAHandle Price Open is calculated (",calculated," bars). Error ",GetLastError());
      return(0);
     }
   calculated=BarsCalculated(hMAH);
   if(calculated<bars)
     {
      Print("Not all data of MAHandle Price High is calculated (",calculated," bars). Error ",GetLastError());
      return(0);
     }
   calculated=BarsCalculated(hMAL);
   if(calculated<bars)
     {
      Print("Not all data of MAHandle Price Low is calculated (",calculated," bars). Error ",GetLastError());
      return(0);
     }
   calculated=BarsCalculated(hMAC);
   if(calculated<bars)
     {
      Print("Not all data of MAHandle Price Close is calculated (",calculated," bars). Error ",GetLastError());
      return(0);
     }
   //--
   return(calculated);
//---
  } //-end CalculatedHandle()  
//---------//

int CountCopyBurrefs(int barstotal,int prevc)
  {
//---
   int to_copy;
   if(prevc==0 || calculated!=bars_calculated || barstotal>prevc+1)
     {
      //--- if the iMA Buffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything 
      //--- otherwise, we copy less than the size of indicator buffers
      if(calculated>barstotal) to_copy=barstotal;
      else                     to_copy=calculated;
     }
   else
     {
      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate()
      //--- for calculation not more than one bar is added
      to_copy=(barstotal-prevc)+1;
     }
   //--
   return(to_copy);
//---
  } //-end CountCopyBurrefs()  
//---------//

//+------------------------------------------------------------------+
//| Filling indicator buffers from the iMA indicator                 |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(double &values[],  // indicator buffer for MA values
                         int ind_handle,    // handle of the iMA indicator
                         int amount         // number of copied values
                         )
  {
//--- reset error code
   ResetLastError();
//--- fill a part of the iMA Buffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(ind_handle,0,0,amount,values)<0)
     {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
//--- everything is fine
   return(true);
//---
  } //-end FillArrayFromBuffer()  
//---------//

string strTF(ENUM_TIMEFRAMES period)
  {
//---
   switch(period)
     {
       //--
       case PERIOD_M1:   return("M1");
       case PERIOD_M2:   return("M2");
       case PERIOD_M3:   return("M3");
       case PERIOD_M4:   return("M4");
       case PERIOD_M5:   return("M5");
       case PERIOD_M6:   return("M6");
       case PERIOD_M10:  return("M10");
       case PERIOD_M12:  return("M12");
       case PERIOD_M15:  return("M15");
       case PERIOD_M20:  return("M20");
       case PERIOD_M30:  return("M30");
       case PERIOD_H1:   return("H1");
       case PERIOD_H2:   return("H2");
       case PERIOD_H3:   return("H3");
       case PERIOD_H4:   return("H4");
       case PERIOD_H6:   return("H6");
       case PERIOD_H8:   return("H8");
       case PERIOD_H12:  return("H12");
       case PERIOD_D1:   return("D1");
       case PERIOD_W1:   return("W1");
       case PERIOD_MN1:  return("MN1");
       //--
     }
   //--
   return(string(period));
//---
  } //-end strTF()  
//---------//

void Do_Alerts(string msgText,datetime altpos)
  {
//---
    //--
    Print(" --- "+Symbol()+": "+msgText+
          "\n --- at: ",TimeToString(altpos,TIME_DATE|TIME_MINUTES));
    //--
    if(alerts==Yes)
      {
        Alert(" --- "+Symbol()+": "+msgText+
              " --- at: ",TimeToString(altpos,TIME_DATE|TIME_MINUTES));
      }
    //--
    if(UseEmailAlert==Yes) 
      SendMail(_pname," --- "+Symbol()+" "+strTF(Period())+": "+msgText+
                       "\n --- at: "+TimeToString(altpos,TIME_DATE|TIME_MINUTES));
    //--
    if(UseSendnotify==Yes) 
      SendNotification(_pname+" --- "+Symbol()+" "+strTF(Period())+": "+msgText+
                      "\n --- at: "+TimeToString(altpos,TIME_DATE|TIME_MINUTES));
    //--
    return;
    //--
//---
  } //-end Do_Alerts()
//---------//

void PosAlerts(int curalerts,datetime altpos) 
   {
//---
    //---
    if((curalerts!=prevalert)&&(curalerts==1))
       {
         Albase=indiname;
         AlSubj=Albase+" MACandlestick bar was Up ~ Open Buy";
         Do_Alerts(AlSubj,altpos);
         prevalert=curalerts;
       }
    //---
    if((curalerts!=prevalert)&&(curalerts==-1))
       {   
         Albase=indiname;  
         AlSubj=" MACandlestick bar was Down ~ Open Sell";
         Do_Alerts(AlSubj,altpos);
         prevalert=curalerts;
       }
    //---
    return;
//---
   } //-end PosAlerts()
//---------//


string getUninitReasonText(int reasonCode) 
  { 
//---
   string text=""; 
   //--- 
   switch(reasonCode) 
     { 
       case REASON_PROGRAM:
            text="The EA has stopped working calling by remove function."; break;
       case REASON_REMOVE: 
            text="Program "+__FILE__+" was removed from chart"; break;
       case REASON_RECOMPILE:
            text="Program recompiled."; break;    
       case REASON_CHARTCHANGE: 
            text="Symbol or timeframe was changed"; break;
       case REASON_CHARTCLOSE: 
            text="Chart was closed"; break; 
       case REASON_PARAMETERS: 
            text="Input-parameter was changed"; break;            
       case REASON_ACCOUNT: 
            text="Account was changed"; break; 
       case REASON_TEMPLATE: 
            text="New template was applied to chart"; break; 
       case REASON_INITFAILED:
            text="The OnInit() handler returned a non-zero value."; break;
       case REASON_CLOSE: 
            text="Terminal closed."; break;
       default: text="Another reason"; break;
     } 
   //--
   return text;
//---
  } //-end getUninitReasonText()
//---------//
//+------------------------------------------------------------------+
***Copyright © 2026 3rjfx ~ For educational purposes only.***

No comments :

Post a Comment

Leave A Comment...