Showing posts with label Forex indicator alerts. Show all posts
Showing posts with label Forex indicator alerts. Show all posts

Thursday, August 7, 2025

Introduction

The Average Directional Movement Index Multi-Timeframe (ADX MTF) Indicator for MetaTrader 5 provides directional signals from all 21 standard timeframes, ranging from M1 to MN1.

For each timeframe, it displays a directional arrow object (`OBJ_ARROW`) using Wingdings character 108:

🟢 Green arrow = upward ADX signal
🔴 Red arrow = downward ADX signal

After gathering these signals, the indicator calculates a consensus summary using a unique logic:
If the number of **up** signals is greater than **down + 1**, the indicator plots a larger **Wingdings 217** upward arrow * If the number of **down** signals is greater than **up + 1**, it plots a larger **Wingdings 218** downward arrow

This enables traders to view a high-confidence trend direction based on multi-timeframe ADX analysis directly on the main chart.

🔁 Note: All multi-timeframe indicators developed by Forex Home Expert use this exact signal logic structure.

The Average Directional Movement Index Multi-Timeframe indicator for MT5 (ADX_MTF) utilizes a template and displays a panel on the chart. Its function, operation, and usage are identical to the Strength of Price Movement Multi Timeframe indicator (SPM_MTF) as detailed in the previous article. For a comprehensive guide on creating a multi-timeframe indicator, you can refer to the following resources: Strength of Price Movement Multi Timeframe indicator for MT5

Average Directional Movement Index Multi-Timeframe indicator for MT5

Key Features:

✅ 21-Timeframe Directional ADX Scanning
✅ Wingdings Arrows Overlay (per timeframe)
✅ Summary Arrow with Up/Down Consensus Calculation
✅ Color Customization for Each Signal
✅ Built-in Alerts (pop-up, email, mobile)
✅ Graphical Interface Panel for Timeframe Switching (via `OnChartEvent`)

Inputs and Parameters

| Input | Description | | --------------- | ------------------------------------------ |
| `BarCalc` | Bars used for ADX signal scan |
| `ArrowUp` | Color of up signal arrow |
| `ArrowDn` | Color of down signal arrow |
| `NTArrow` | Color of neutral arrow (default) |
| `f_model` | Font type for arrows (usually "Wingdings") |
| `alerts` | Enable/disable alert popups |
| `UseEmailAlert` | Enable email alerts |
| `UseSendnotify` | Enable push notification alerts |

Why Multi-Timeframe ADX Matters?

The ADX is powerful for identifying **trend strength** but lacks insight into **trend consistency** across timeframes. This custom ADX_MTF indicator solves that:

📈 Confirm short-term trades with long-term trend backing
⚠️ Avoid sideways or weak markets using visual confirmation
🚨 Detect powerful breakouts supported by multiple timeframe trends

Using **all 21 timeframes** (from M1 to MN1) ensures broad trend consistency in your decision-making process.

Technical Overview: How the Indicator Works

Timeframe Management

The indicator prepares and manages handles for all standard MT5 timeframes:


ENUM_TIMEFRAMES TFId[] = {PERIOD_M1, PERIOD_M2, ..., PERIOD_MN1};
int tfxar = ArraySize(TFId);  // total 21 timeframes
/* Handles for all timeframe-specific ADX indicators are stored in `hADXp[]` and initialized inside `OnInit()` using `iADX()` for each timeframe. */

Signal Extraction Logic

Each timeframe is scanned using:


   //---
   int ADXDirectionScan(const ENUM_TIMEFRAMES stf,int shift) // Scan ADX Direction
     {
      //--
      int ret=0;
      int rise=1,
          down=-1;
      //--
      int br=shift+2;
      double res=0.0;
      UpdatePrice(stf);
      //--
      double ADXp[];
      ArrayResize(ADXp,br,br);
      ArraySetAsSeries(ADXp,true);
      //--
      int xx=TFIndexArray(stf);
      CopyBuffer(hADXp[xx],1,0,br,ADXp); // We will use ADX indicator buffer for DI+
      //--
      if(ADXp[shift]>ADXp[shift+1]) ret=rise;
      if(ADXp[shift]<ADXp[shift+1]) ret=down;
      //--
      return(ret);
      //---
     } //-end ADXDirectionScan()
   //---
   
/*
This compares DI+ values (buffer 1) to detect rising or falling strength.
*/

Consensus Calculation Logic.


   //---
   void ADXMovementCalculation(int barCnt) // Scan the direction of iADX on each timeframe
     {
      //--
      ArrayResize(PowerMove,barCnt,barCnt);
      ArraySetAsSeries(PowerMove,true);
      //--
      for(int i=barCnt-1; i>=0; i--)
        {
         up=0;
         dw=0;
         //--
         for(int x=0; x<tfxar; x++)
           {
            Arwcolor[x]=NTArrow;
            PowerMove[i]=0.0;
            int PPM=ADXDirectionScan(TFId[x],0);
            if(PPM>0)
              {
               up++;
               Arwcolor[x]=ArrowUp;
              }
            if(PPM<0)
              {
               dw++;
               Arwcolor[x]=ArrowDn;
              }
            if(x==tfxar-1)
              {
               if(up>dw+1)
                 {
                  PowerMove[i]=1.0;
                  TColor=ArrowUp;
                  curAlert=1;
                 }
               if(dw>up+1)
                 {
                  PowerMove[i]=-1.0;
                  TColor=ArrowDn;
                  curAlert=-1;
                 }
              }
           }
        }
      //--
      return;
      //---
     } //-end ADXMovementCalculation()
   //---

/*
This logic ensures that only dominant directional consensus (not slight differences) triggers a clear summary signal.
*/

Dynamic Timeframe Panel (OnChartEvent)

The indicator creates a clickable panel on the chart containing labels for all 21 timeframes. When a label (e.g., "H4") is clicked, the internal reference timeframe for analysis is updated.

This makes it easy for the user to interact with the indicator dynamically.


void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
   ResetLastError();
//--
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- if "X" button is click
      if(sparam=="X")
        {
         mi.DeletedADXObject();
         //--- unpress the button
         ObjectSetInteger(mi.CI,"X",OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,"X",OBJPROP_ZORDER,0);
         //--
         mi.display=false;
         ObjectDelete(mi.CI,"X");
         mi.DisplayPanelButton();
        }
      //--- if "cstar" button is click
      if(sparam==mi.cstar)
        {
         mi.DeletedADXObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         if(mi.corpos==mi.posbot) ObjectDelete(mi.CI,mi.arbot);
         if(mi.corpos==mi.postop) ObjectDelete(mi.CI,mi.artop);
         mi.DrawADXObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if "artop" button is click
      if(sparam==mi.artop)
        {
         mi.DeletedADXObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.artop,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.artop,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         ObjectDelete(mi.CI,mi.artop);
         mi.PanelPosChange(mi.postop);
         //--
         ObjectDelete(mi.CI,"X");
         mi.DisplayButtonClick("arbot");
         mi.DrawADXObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if "arbot" button is click
      if(sparam==mi.arbot)
        {
         mi.DeletedADXObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         ObjectDelete(mi.CI,mi.arbot);
         mi.PanelPosChange(mi.posbot);
         //--
         ObjectDelete(mi.CI,"X");
         mi.DisplayButtonClick("artop");
         mi.DrawADXObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if TF button is click
      //--
      if(sparam==mi.TFSc[0])
        {
         mi.ChangeChartSymbol(mi.TFSc[0],mi.TFId[0]);
        }
      //--
      if(sparam==mi.TFSc[1])
        {
         mi.ChangeChartSymbol(mi.TFSc[1],mi.TFId[1]);
        }
      //--
      if(sparam==mi.TFSc[2])
        {
         mi.ChangeChartSymbol(mi.TFSc[2],mi.TFId[2]);
        }
      //--
      if(sparam==mi.TFSc[3])
        {
         mi.ChangeChartSymbol(mi.TFSc[3],mi.TFId[3]);
        }
      //--
      if(sparam==mi.TFSc[4])
        {
         mi.ChangeChartSymbol(mi.TFSc[4],mi.TFId[4]);
        }
      //--
      if(sparam==mi.TFSc[5])
        {
         mi.ChangeChartSymbol(mi.TFSc[5],mi.TFId[5]);
        }
      //--
      if(sparam==mi.TFSc[6])
        {
         mi.ChangeChartSymbol(mi.TFSc[6],mi.TFId[6]);
        }
      //--
      if(sparam==mi.TFSc[7])
        {
         mi.ChangeChartSymbol(mi.TFSc[7],mi.TFId[7]);
        }
      //--
      if(sparam==mi.TFSc[8])
        {
         mi.ChangeChartSymbol(mi.TFSc[8],mi.TFId[8]);
        }
      //--
      if(sparam==mi.TFSc[9])
        {
         mi.ChangeChartSymbol(mi.TFSc[9],mi.TFId[9]);
        }
      //--
      if(sparam==mi.TFSc[10])
        {
         mi.ChangeChartSymbol(mi.TFSc[10],mi.TFId[10]);
        }
      //--
      if(sparam==mi.TFSc[11])
        {
         mi.ChangeChartSymbol(mi.TFSc[11],mi.TFId[11]);
        }
      //--
      if(sparam==mi.TFSc[12])
        {
         mi.ChangeChartSymbol(mi.TFSc[12],mi.TFId[12]);
        }
      //--
      if(sparam==mi.TFSc[13])
        {
         mi.ChangeChartSymbol(mi.TFSc[13],mi.TFId[13]);
        }
      //--
      if(sparam==mi.TFSc[14])
        {
         mi.ChangeChartSymbol(mi.TFSc[14],mi.TFId[14]);
        }
      //--
      if(sparam==mi.TFSc[15])
        {
         mi.ChangeChartSymbol(mi.TFSc[15],mi.TFId[15]);
        }
      //--
      if(sparam==mi.TFSc[16])
        {
         mi.ChangeChartSymbol(mi.TFSc[16],mi.TFId[16]);
        }
      //--
      if(sparam==mi.TFSc[17])
        {
         mi.ChangeChartSymbol(mi.TFSc[17],mi.TFId[17]);
        }
      //--
      if(sparam==mi.TFSc[18])
        {
         mi.ChangeChartSymbol(mi.TFSc[18],mi.TFId[18]);
        }
      //--
      if(sparam==mi.TFSc[19])
        {
         mi.ChangeChartSymbol(mi.TFSc[19],mi.TFId[19]);
        }
      //--
      if(sparam==mi.TFSc[20])
        {
         mi.ChangeChartSymbol(mi.TFSc[20],mi.TFId[20]);
        }
      //--
     }
//---
  } //-end OnChartEvent()
//---------//

How to Use

1. **Attach to Any Chart** (e.g., EURUSD H1)
2. **Adjust the Inputs**
3. **Observe Directional Arrows** per timeframe on your chart
4. **Watch Summary Signal Arrow** (center chart)
5. **Click Timeframe Labels** to change timeframe view instantly

Frequently Asked Questions (FAQ)

**Q1: What makes this ADX MTF indicator different from the built-in ADX in MetaTrader 5?**
**A1:** The built-in ADX only analyzes the current chart timeframe. This ADX MTF indicator scans and displays directional strength across **21 timeframes**, giving you a full-spectrum view of the market’s trend dynamics. It also features consensus-based summary signals and interactive controls.

**Q2: What do the green and red arrows mean on the chart?**
**A2:**
**Green arrow** (Wingdings 108): Indicates that ADX is rising (positive DI > previous value) on that specific timeframe
**Red arrow** (Wingdings 108): Indicates ADX is falling (trend weakening)
The **large green (217)** or **red (218)** summary arrow shows dominant direction when more than one timeframe agrees

**Q3: How is the final summary signal calculated?**
**A3:** The indicator loops through all timeframes and counts up and down signals.
** If `up > down + 1`, it plots a large **up arrow** (Wingdings 217)
** If `down > up + 1`, it plots a **down arrow** (Wingdings 218)
** If neither, no summary arrow is drawn

**Q4: Can I change the timeframe used for analysis dynamically?**
**A4:** Yes. The indicator includes an interactive panel with all 21 timeframes (M1 to MN1). Just click on any label (like “H4” or “D1”) to switch the analysis source without reattaching the indicator. This is handled via the `OnChartEvent()` function in MQL5.

**Q5: Is this indicator repainting?**
**A5:** No. The indicator uses `CopyBuffer()` with proper indexing and does **not repaint** past signals. All calculations are based on closed candles and historical values.

**Q6: What symbols or assets can I use this on?**
**A6:** This indicator works with all MT5 instruments:
* Forex pairs (e.g., EURUSD, GBPJPY)
* Indices (e.g., DAX, S&P 500)
* Commodities (e.g., gold, oil)
* Crypto (e.g., BTCUSD)

**Q7: Does this indicator send alerts?**
**A7:** Yes. It supports:
* Popup alerts
* Email alerts
* Push notifications
These can be toggled on/off in the input settings.

**Q8: Can this be used inside Expert Advisors (EAs)?**
**A8:** While this is a custom visual indicator, its signal logic can be adapted into EAs. You may extract the consensus signal via `PowerMove[]` or implement a similar formula directly in your EA code.

**Q9: Can I use this for scalping or only for swing trading?**
**A9:** It’s suitable for **both**. Scalpers can confirm short-term moves with higher timeframe trends. Swing traders benefit from trend strength alignment across D1, H4, etc.

**Q10: Do I need to install any external libraries to use it?**
**A10:** No. Just download the `.ex5` file, place it in `MQL5/Indicators`, and run.

Conclusion

The **ADX Multi-Timeframe Indicator for MT5** offers a complete solution for traders who want to understand trend strength across all timeframes simultaneously. Using a unique formula that scans and weighs up/down movement across 21 timeframes, it delivers a summary arrow signal that simplifies complex data into an actionable visual.

With features like dynamic chart interaction, visual arrows, alerts, and a lightweight design, this tool is ideal for discretionary and algorithmic traders alike.

We hope that this article and the ADX_MTF or Average Directional Movement Index Multi-Timeframe Indicator for MT5 program will be useful for traders in learning and generating new ideas for trading, who can ultimately make money from home by trading forex.

Thanks for reading this article.

Please download the ADX_MTF indicator: Average Directional Movement Index Multi-Timeframe Indicator

If you are subscribed to my YouTube Channel, and would like to receive the source program of this article, please send a request via the Contact Us form page, and I will send it to your email, source code: Average Directional Movement Index Multi-Timeframe Indicator for MT5

Don't forget to stop by and subscribe to Forex Home Experts YouTube Channel:

YouTube Channel: @ForexHomeExperts

YouTube Playlist: @ForexHomeExperts YouTube Playlist

Monday, November 25, 2024

Before we start discussing how to create a program to detect whether a new bar has appeared or not on MT5 and MT4, it's a good idea to know the benefits of detecting new bars.

How to detect new bars on Expert Advisors in MT4 and MT5

Detecting new bars in MT4 or MT5 has several important benefits for traders, especially in increasing the efficiency and effectiveness of their trading strategies and the use of automated trading like expert advisor.. Here are some of the main benefits:

  • 1. Faster Decision-Making: Detecting new bars helps you get instant updates on price changes, allowing you to make quick decisions based on the latest data.
  • 2. Less Data Clutter: By focusing on new bars, you avoid unnecessary data and concentrate on the most important information for your strategy.
  • 3. Increased Efficiency: You don't need to manually check charts all the time. This frees you up to focus on deeper analysis or other activities.
  • 4. Automation: Integrate new bar detection with automation tools for sending messages or placing orders automatically when certain conditions are met.
  • 5. Better Monitoring: Keep a closer eye on market trends and detect trend changes faster by watching for new bars.
  • 6. Reduced Stress: You don't have to constantly monitor charts, which helps reduce stress and improves your concentration.
  • 7. Improved Trading Strategies: With quicker and more accurate information, you can develop and optimize your trading strategies more effectively.

Overall, detecting new bars in MT4 or MT5 helps traders be more efficient, make better decisions, and manage their trading activities more effectively. It can be clearly said that detecting new bars is very important in using automatic trading or expert advisors.

Example of a simple program in MQL5


//+------------------------------------------------------------------+
//|                                                   TestNewBar.mq5 |
//|        Copyright 2024, Roberto Jacobs (3rjfx) ~ Date: 2024-11-24 |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Roberto Jacobs (3rjfx) ~ Date: 2024-11-24"
#property link      "https://www.mql5.com/en/users/3rjfx"
#property version   "1.00"
#property strict
//--
//+------------------------------------------------------------------+
//|                             Include                              |
//+------------------------------------------------------------------+
#include <trade rade.mqh="">
#include <trade ositioninfo.mqh="">
#include <trade ymbolinfo.mqh="">
#include <trade ccountinfo.mqh="">
//--
CTrade              mc_trade;
CSymbolInfo         mc_symbol;
CPositionInfo       mc_position; 
CAccountInfo        mc_account;
//---
//--
input ENUM_TIMEFRAMES  Timeframe = PERIOD_H1;     // Select Expert TimeFrame, default PERIOD_H1

//--
datetime         
   PrevbarBuy,
   TimebarBuy,
   PrevbarSell,
   TimebarSell;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
     // Initialization code here
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
   PrintFormat("%s: Deinitialization reason code=%d",__FUNCTION__,reason);
   //--
   return;
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
     //- For Open Order Buy
     if(IFNewBarsB()) { OpenBuy(); PrevbarBuy=TimebarBuy; }
     //--
     //- For Open Order Sell
     if(IFNewBarsB()) { OpenSell(); PrevbarSell=TimebarSell; }
    //--
    return;
//---
  }
//+------------------------------------------------------------------+

bool IFNewBarsB(void) // New bar check buy order
  {
//---
    bool Nb=false;
    //--
    TimebarBuy=iTime(Symbol(),Timeframe,0);
    if(TimebarBuy!=PrevbarBuy) Nb=true;
    //--
    return(Nb);
//---
  } //-end IFNewBarsB()
//---------//

bool IFNewBarsS(void) // New bar check sell order
  {
//---
    bool Nb=false;
    //--
    TimebarSell=iTime(Symbol(),Timeframe,0);
    if(TimebarSell!=PrevbarSell) Nb=true;
    //--
    return(Nb);
//---
  } //-end IFNewBarsS()
//---------//

bool OpenBuy(void) 
  {
//---
    ResetLastError();
    //--
    bool buyopen      = false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    double Lot=0.01;
    double SL=0.0;
    double TP=0.0;
    //--
    buyopen=mc_trade.Buy(Lot,Symbol(),mc_symbol.Ask(),SL,TP,"Your Comment");
    //--
    int error=GetLastError();
    if(buyopen||error==0)
      {
        string bsopen="Open BUY Order for "+Symbol()+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        PrevbarBuy=iTime(Symbol(),Timeframe,0);
      }
    else
      {
        mc_trade.CheckResult(check);
        return(false);   
      }
    //--
    return(buyopen);
    //--
//---
  } //-end OpenBuy
//---------//

bool OpenSell(void) 
  {
//---
    ResetLastError();
    //--
    bool selopen      = false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    double Lot=0.0;
    double SL=0.0;
    double TP=0.0;
    //--
    selopen=mc_trade.Sell(Lot,Symbol(),mc_symbol.Bid(),SL,TP,"Your Comment");
    //--
    int error=GetLastError();
    if(selopen||error==0)
      {
        string bsopen="Open SELL Order for "+Symbol()+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        PrevbarSell=iTime(Symbol(),Timeframe,0);
      }
    else
      {
        mc_trade.CheckResult(check);
        return(false);   
      }
    //--
    return(selopen);
    //--
//---
  } //-end OpenSell
//---------//

Includes and Declarations.


#include <trade rade.mqh="">
#include <trade ositioninfo.mqh="">
#include <trade ymbolinfo.mqh="">
#include <trade ccountinfo.mqh="">

CTrade              mc_trade;
CSymbolInfo         mc_symbol;
CPositionInfo       mc_position; 
CAccountInfo        mc_account;

input ENUM_TIMEFRAMES  Timeframe = PERIOD_H1;     // Select Expert TimeFrame, default PERIOD_H1

datetime         
   PrevbarBuy,
   TimebarBuy,
   PrevbarSell,
   TimebarSell;
  • Includes: Importing trade, position, symbol, and account information classes.
  • Declarations: Creating instances of trade, symbol, position, and account classes. Defining the input parameter for selecting the timeframe and datetime variables for buy and sell bars.

int OnInit()
{
   // Initialization code here
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   Comment("");
   PrintFormat("%s: Deinitialization reason code=%d",__FUNCTION__,reason);
   return;
}
  • OnInit: Runs once when the expert advisor is initialized. It returns INIT_SUCCEEDED to indicate successful initialization.
  • OnDeinit: Runs once when the expert advisor is removed or the terminal is shut down. It clears any comments and prints the deinitialization reason.

void OnTick()
{
   // For Open Order Buy
   if(IFNewBarsB()) { OpenBuy(); PrevbarBuy = TimebarBuy; }
   
   // For Open Order Sell
   if(IFNewBarsB()) { OpenSell(); PrevbarSell = TimebarSell; }
   
   return;
}
  • OnTick: Runs on every tick (price update). It checks for new buy and sell bars and opens orders accordingly.

bool IFNewBarsB(void) // New bar check buy order
  {
//---
    bool Nb=false;
    //--
    TimebarBuy=iTime(Symbol(),Timeframe,0);
    if(TimebarBuy!=PrevbarBuy) Nb=true;
    //--
    return(Nb);
//---
  } //-end IFNewBarsB()
//---------//

bool IFNewBarsS(void) // New bar check sell order
  {
//---
    bool Nb=false;
    //--
    TimebarSell=iTime(Symbol(),Timeframe,0);
    if(TimebarSell!=PrevbarSell) Nb=true;
    //--
    return(Nb);
//---
  } //-end IFNewBarsS()
//---------//
  • IFNewBarsB and IFNewBarsS: Check if a new buy or sell bar has appeared by comparing the current bar time with the previous bar time. If they are different, a new bar is detected, and the function returns true.

bool OpenBuy(void) 
  {
//---
    ResetLastError();
    //--
    bool buyopen      = false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    double Lot=0.01;
    double SL=0.0;
    double TP=0.0;
    //--
    buyopen=mc_trade.Buy(Lot,Symbol(),mc_symbol.Ask(),SL,TP,"Your Comment");
    //--
    int error=GetLastError();
    if(buyopen||error==0)
      {
        string bsopen="Open BUY Order for "+Symbol()+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        PrevbarBuy=iTime(Symbol(),Timeframe,0);
      }
    else
      {
        mc_trade.CheckResult(check);
        return(false);   
      }
    //--
    return(buyopen);
    //--
//---
  } //-end OpenBuy
//---------//

bool OpenSell(void) 
  {
//---
    ResetLastError();
    //--
    bool selopen      = false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    double Lot=0.0;
    double SL=0.0;
    double TP=0.0;
    //--
    selopen=mc_trade.Sell(Lot,Symbol(),mc_symbol.Bid(),SL,TP,"Your Comment");
    //--
    int error=GetLastError();
    if(selopen||error==0)
      {
        string bsopen="Open SELL Order for "+Symbol()+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        PrevbarSell=iTime(Symbol(),Timeframe,0);
      }
    else
      {
        mc_trade.CheckResult(check);
        return(false);   
      }
    //--
    return(selopen);
    //--
//---
  } //-end OpenSell
//---------//
  • OpenBuy and OpenSell: These functions handle opening buy and sell orders. They use the CTrade class to place orders with specified lot sizes, stop loss, and take profit levels. If an order is successfully placed, the functions return true; otherwise, they return false.

Summary:

The improved script detects new bars on the selected timeframe and opens buy or sell orders accordingly. It includes functions to check for new bars and open orders while utilizing the powerful MQL5 trading library.

Many programmers create new bar detection functions with less than ideal considerations. They often rely on the logic: "If the opening time of the current bar is not the same as the previous bar time, then the 'New Bar' condition becomes 'TRUE'. Subsequently, the previous bar time is immediately updated to match the current bar time."

Limitations of the Conventional Logic.

This approach, while straightforward, has significant drawbacks:

  • Transient Condition: The EA (Expert Advisor) will only register the 'New Bar' condition as 'TRUE' at the exact moment the new bar opens. A few seconds later, upon rechecking, the 'New Bar' condition will revert to 'FALSE'.
  • Indicator Signals: This logic fails when EAs rely on indicators to generate signals. Indicators might not produce a signal precisely at the new bar's opening. Consequently, if the new bar condition quickly turns 'FALSE', the EA might miss potential trading opportunities.

Enhanced Algorithm Logic.

To address these issues, I propose a more robust algorithm:

  • 1. New Bar Detection: Check if the new bar condition is 'TRUE'.
  • 2. Order Function Check: Ensure that the open order function (OpenBuy() or OpenSell()) also returns 'TRUE'.
  • 3. Update Time Variables: Only if both checks are 'TRUE', update the previous bar time variable (PrevbarBuy for Buy orders or PrevbarSell for Sell orders) to match the current bar time variable (TimebarBuy or TimebarSell).

This approach guarantees that the previous bar time is updated only after a successful order placement. Thus, when the EA rechecks for a new bar, the function returns 'FALSE', preventing multiple orders from being placed within the same bar.

Handling Reversed Indicator Signals.

In my example program, I use separate time variables for Buy and Sell conditions:

  • Buy Orders: Utilize PrevbarBuy and TimebarBuy.
  • Sell Orders: Utilize PrevbarSell and TimebarSell.

This separation accounts for scenarios where indicator signals might reverse within the same bar. If both signals share a single time check variable, the EA could miss opportunities to open opposite orders due to the 'New Bar' condition being 'FALSE'.

Conclusion.

By refining the new bar detection logic, we can enhance the reliability of EAs, ensuring they act upon indicator signals accurately and timely. This approach leads to more precise trading actions and potentially better trading outcomes.

This article ends here, hopefully it can help and be useful for fellow traders.

Notes:

This code provides a basic framework for new bar detection in an EA. However, for a robust and reliable trading strategy, it needs further development to incorporate additional factors such as price movements, indicators, and risk management techniques.

Please download the Expert Advisor: TestNewBar

Don't forget to stop by and subscribe to Forex Home Experts YouTube Channel:

YouTube Channel: @ForexHomeExperts

YouTube Playlist: @ForexHomeExperts YouTube Playlist

Featured Post

How to create a simple Multi-Currency Expert Advisor using MQL5 with Zigzag and RSI Indicators Signal

Introduction The Expert Advisor discussed in this article is a multi-currency trading robot that uses the Zigzag and RSI indicators. It fol...