Monday, December 2, 2024

In this article, I'll explain how to create a standard and simple Expert Advisor (EA) or forex robot by applying Buy or Sell signals from the FiboPivotCandleBar indicator for MetaTrader 4.

First, let me explain that the FiboPivotCandleBar indicator for MetaTrader 4 is an indicator I created and have been sharing for free in the MQL5 Library since 2015. However, I have never applied the signals inan Expert Advisor or forex robot until now. This article won't delve into the Fibonacci and Pivot Point strategies, as they require a dedicated and lengthy discussion.

To create this Expert Advisor, I used the latest Event Handling Functions from MQL4 and several key properties and attributes that adhere to good MQL4 programming standards.

FiboPivotCandleBar Expert Advisor for MetaTrader 4

Now, I'll explain each function, the use of variables, and the algorithm's logic one by one.

Standard Include Files.

For creating this Expert Advisor, I used the standard include files (mqh files):

  • 1.- #include MovingAverages.mqh: Used for writing the MovingAverage indicator signal.
  • 2.- #include stderror.mqh: Contains standard errors returned from the trade server.
  • 3.- #include stdlib.mqh: Contains the Error Description from standard library.

You can find these three include files in the MQL4/Include folder.

Custom Enumerations.

YN Enum Function: I use this for Yes or No options. Most programmers prefer boolean variables (True or False), but I prefer using Yes or No for clarity.

MMT Enum Function: This function is used for determining the Lot Size (Money Management).

  • If FixedLot is selected, the expert advisor will use the value of the Lots variable entered by the user. By default, the Lots size variable is set to 0.01.
  • If AutoLot is selected, the expert advisor will calculate the Lot size according to the specified money management requirements.

//---
input string           grs0 = "=== Global Strategy EA Parameters ==="; // Global Strategy EA Parameter
input ENUM_TIMEFRAMES  ExTF = PERIOD_H1;      // Select Expert TimeFrame, default PERIOD_H1
input YN            SrictTF = Yes;            // Strict to Change TimeFrame (Yes) or (No)
//---
input string           grs1 = "=== Money Management Lot Size Parameters ==="; // Money Management Lot Size Parameter
input mmt             mmlot = AutoLot;        // Money Management Type
input double           Risk = 5.0;            // Percent Equity Risk to Trade (Min=1.0% / Max=50.0%)
input double           Lots = 0.01;           // If Money Management Type FixedLot, input Fixed Lot Size
//---
input string           grs2 = "=== Close Order Option ==="; // Close Order Option
input YN      Close_by_Opps = Yes;            // Close Trade By Opposite Signal (Yes) or (No)
input YN             CSexit = Yes;            // Use Close In Signal Exit (Yes) or (No)
//---
input string           grs3 = "=== Stop Loss & Take Profit Parameters ==="; // Stop Loss  && Take Profit Parameter
input YN             Use_SL = No;             // Use Order SL (Yes) or (No)
input YN             Use_TP = No;             // Use Order TP (Yes) or (No)
//---
input string           grs4 = "=== Trailing Stop Loss / Take Profit Parameters ==="; // Trailing SL / TP Parameter
input YN          use_trail = Yes;            // Use Trailing Stop / Trailing Profit (Yes) or (No)
input int            trstrt = 1;              // Input Start value for Trailing Stop in Pips
input int            trstop = 6;              // Input Trailing Stop value in Pips
//---
input string           grs5 = "=== Others Expert Advisor Parameters ==="; // Others EA Parameter
input YN             alerts = Yes;            // Display Alerts on Chart (Yes) or (No)
input YN      UseEmailAlert = No;             // Email Alert (Yes) or (No)
input YN      UseSendnotify = No;             // Send Notification (Yes) or (No)
input YN       Usechartcomm = Yes;            // Display Setting on Chart (Yes) or (No)
input int           magicEA = 20241202;        // Expert ID (Magic Number)
//---

Select Expert TimeFrame (default: PERIOD_H1): This parameter defines the Expert Timeframe for signal calculation. It prevents the EA from recalculating signals based on the chart's last changed timeframe by user, which could lead to premature order closures.

Strict to Change Timeframe (Yes or No): By default, this is set to Yes, preventing traders from changing timeframe charts directly in the MetaTrader 4 terminal. Timeframe changes can only be made through the Select Expert Timeframe input property. Set to No if the user wants to change the timeframe manually.

Money Management Lot Size Parameters.

Money Management Type: By default, this is set to AutoLot. The EA calculates the Lot Size based on the Percent Equity Risk to Trade, which is set at 5% by default (min 1.0%, max 50.0%). For trading on 20 pairs or more, consider increasing the risk to 20% or 30%. If FixedLot is selected, input the desired FixedLot Size.

Close Order Options.

Close Trade By Opposite Signal (Yes or No): By default, this is set to Yes. If there's an open BUY order and the signal reverses to SELL, the EA will close the BUY order and open a SELL order, and vice versa.

Use Close In Signal Exit (Yes or No): By default, this is set to Yes. If the BUY signal weakens but is still profitable, the EA will close the BUY order. If set to No, the EA won't close the order based on signal exit.

Stop Loss and Take Profit Parameters.

Use Order SL (Yes or No): By default, this is set to No. Despite this, the EA will automatically close orders if there's a reverse signal, thanks to the Close Trade By Opposite Signal parameter.

Use Order TP (Yes or No): By default, this is set to No, allowing for greater profits during long trends.

Trailing Stop Loss or Take Profit Parameters.

Use Trailing Stop or Trailing Profit (Yes or No): By default, this is set to Yes. If not preferred, set this parameter to No. The trailing start is set at 1 pip from the Order Open Price, with a trailing stop value of 6 pips. These values can be adjusted as desired.

Other Expert Advisor Parameters.

Display Alerts on Chart (Yes or No): By default, this is set to Yes, activating alerts, email, and push notification functions through the DoAlerts function.

Email Alert (Yes or No): By default, this is set to No. For email alerts, users must configure their email settings in MetaTrader 4:

  • 1. Click the Tools menu.
  • 2. Select Options.
  • 3. Click Email.

Configure the settings with your email identity:

  • SMTP server: e.g., smtp.gmail.com:587 for Gmail.
  • SMTP login: Your email address.
  • SMTP password: Your email password.
  • From: Your email address.
  • To: Recipient's email address (can be the same as the sender).

After configuring, click the Test button and check the Journal Tab for any errors.

Send Notification (Yes or No): By default, this is set to No. For push notifications, users must configure their MetaQuotes ID in MetaTrader 4:

  • 1. Click the Tools menu.
  • 2. Select Options.
  • 3. Click the Notifications tab.
  • 4. Check Enable Push Notification.
  • 5. Enter YOUR MetaQuotes ID.

Class Function.

In this Expert Advisor, I use a class function named "EXP", listing all main variables and functions used. This class serves as the blueprint of the Expert Advisor. However, this article won't delve into the class function's details, assuming readers are familiar with it.


//+------------------------------------------------------------------+
//| Class for working Expert Advisor                                 |
//+------------------------------------------------------------------+
class EXP 
  {
//---
    private:
    //---
    //--
    int           slip,bartotal;
    int           ldig,checkacc,cdb,cds;
    //--
    double        mSL,mTP,mPft;
    double        pip,xpip,trs;
    double        profitb,profits,floatprofit;
    //--
    double        OPEN[],HIGH[],LOW[],CLOSE[];
    double        trval,trstart,trstoptp,aapct;
    double        PvtS,POpen,PLow1,PHigh1,PClose1;
    //--
    bool          posBUY,posSELL;
    //--
    string        expname,
                  exsymbol,
                  trade_mode;
    //-- 
    long          chart_id;
    ENUM_TIMEFRAMES BnC;
    //------------
     
    //------------
    int           LotsDigit(void);
    int           DirectionMove(ENUM_TIMEFRAMES xtf,int shift);
    int           FiboPivotCB(void);
    int           AllowOpen(void);
    int           SignalCondition(void);
    //--
    string        TF2Str(int period);
    string        GetCommentForOrder(void)                  { return(expname); }    
    string        ReturnsOrderType(ENUM_ORDER_TYPE ordtype);
    string        AccountMode(void);
    //--
    double        NonZeroDiv(double val1,double val2);
    double        MLots(void);
    //--   
    void          CopyPrices(void);
    void          RefreshPrice(string symbx,ENUM_TIMEFRAMES xtf,int bars);
    //--
    bool          ModifyStopTP(double mStop,double mProfit) { return(OrderModify(OrderTicket(),OrderOpenPrice(),mStop,mProfit,0,CLR_NONE)); }
    bool          SameAs(double v1,double v2)               { if((double)v1==(double)v2) return(true); return(false); }
    bool          CloseAllOrder(void);
    //------------

    public:
    //---
    //--
    int           utr,ALO,cB,cS,checktml;
    int           oBm,oSm,hBm,hSm,tto;
    //--
    bool          IfTradeAllowed;
    //--
    datetime      PbarB,TbarB,PbarS,TbarS;
    //------------
     
    //------------
    void          FPCB_Config(void);
    void          GetOpenPosition(void);
    void          CheckOpen(void);
    void          CheckClose(void);
    void          TrailingPositionsBuy(void);
    void          TrailingPositionsSell(void);
    void          CloseBuyPositions(void);
    void          CloseSellPositions(void);
    void          Do_Alerts(string msgText);
    void          ChartComm(void);
    void          SignalExit(void);
    //--
    bool          takeBuyPositions(void);
    bool          takeSellPositions(void);
    bool          OpenBuy(void);
    bool          OpenSell(void);
    bool          CloseAllOrdersProfit(void);
    bool          IFNewBarsB(string symb);
    bool          IFNewBarsS(string symb);
    //--
    string        getUninitReasonText(int reasonCode);
    //--
    //------------
//---
  }; //-end class fxt
//---------//
 
EXP fx;

OnInit: Here, I create an algorithm where if SrictTF enumeration is set to Yes, it utilizes the Strict to Change TimeFrame parameter. This function calls "FPCBConfig" function for setting the default configuration used in the Expert Advisor.


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//----
   Comment("");
   //--
   if(SrictTF==Yes)
     {
       if(!ChartSetSymbolPeriod(ChartID(),Symbol(),ExTF))
         {ChartSetSymbolPeriod(ChartID(),Symbol(),ExTF);}
     }
   //--
   fx.FPCB_Config();
   //--
//--- initialization done
   return(INIT_SUCCEEDED);
  }
//---------//

FPCB_Config() function.


void EXP::FPCB_Config(void)
  {
//---
   expname="@ExpFPCB-MT4";
   exsymbol=Symbol();
   //--
   slip=20;
   checktml=0;
   AccountMode();
   utr=use_trail;
   BnC=ExTF; 
   bartotal=108;
   chart_id=ChartID();
   ALO=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);
   //--
   //-- Checking the Digits Point
   slip=20;
   PbarB=iTime(Symbol(),BnC,1);
   PbarS=iTime(Symbol(),BnC,1);
   double point=SymbolInfoDouble(Symbol(),SYMBOL_POINT);
   mPft=0.5;
   //--
   if(exsymbol=="XAGUSD")
     {
       xpip=4; 
       pip=point*xpip;
       if(Use_SL==Yes) mSL=100*point;
       else mSL=0.0;
       if(Use_TP==Yes) mTP=50*point;
       else mTP=0.0;
       //--
       trstart=NormalizeDouble(trstrt*pip,Digits());
       trstoptp=NormalizeDouble(trstop*pip,Digits());
       trval=NormalizeDouble(trstart+trstoptp,Digits());
     }
   if(exsymbol=="XAUUSD")
     {
       xpip=10; 
       pip=point*xpip;
       if(Use_SL==Yes) mSL=250*point;
       else mSL=0.0;
       if(Use_TP==Yes) mTP=50*point;
       else mTP=0.0;
       //--
       trstart=NormalizeDouble(trstrt*pip,Digits());
       trstoptp=NormalizeDouble(trstop*pip,Digits());
       trval=NormalizeDouble(trstart+trstoptp,Digits());
     }
   if(exsymbol=="XBRUSD")
     {
       xpip=10; 
       pip=point*xpip;
       if(Use_SL==Yes) mSL=250*point;
       else mSL=0.0;
       if(Use_TP==Yes) mTP=50*point;
       else mTP=0.0;
       //--
       trstart=NormalizeDouble(trstrt*pip,Digits());
       trstoptp=NormalizeDouble(trstop*pip,Digits());
       trval=NormalizeDouble(trstart+trstoptp,Digits());
     }
   if(exsymbol=="XTIUSD")
     {
       xpip=10; 
       pip=point*xpip;
       if(Use_SL==Yes) mSL=250*point;
       else mSL=0.0;
       if(Use_TP==Yes) mTP=50*point;
       else mTP=0.0;
       //--
       trstart=NormalizeDouble(trstrt*pip,Digits());
       trstoptp=NormalizeDouble(trstop*pip,Digits());
       trval=NormalizeDouble(trstart+trstoptp,Digits());
     }
   else
     {
       xpip=10; 
       pip=point*xpip;
       if(Use_SL==Yes) mSL=25*pip;
       else mSL=0.0;
       if(Use_TP==Yes) mTP=5*pip;
       else mTP=0.0;
       //--
       trstart=NormalizeDouble(trstrt*pip,Digits());
       trstoptp=NormalizeDouble(trstop*pip,Digits());
       trval=NormalizeDouble(trstart+trstoptp,Digits());
     }
   //--
   IfTradeAllowed=IsTradeAllowed();
   CopyPrices();
   //--
   return;
//---
  } //-end FPCB_Config()
//---------//

OnDeinit: in this function, I call the getUninitReasonText function, which provides the description of the reason Code when the Expert Advisor calls the OnDeinit function.


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
   //--
   PrintFormat("%s: Deinitialization reason code=%d",__FUNCTION__,reason);
   Print(fx.getUninitReasonText(reason));
   //--
   return;
  } //-end OnDeinit()
//---------//

OnTick: This is where the Expert Advisor carries out trading activities based on the settings specified in the input properties parameter.


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick(void)
  {  
//---
   //Check Trading Terminal
   if(!fx.IfTradeAllowed && fx.checktml==0)
     {
       fx.Do_Alerts("Trading at "+Symbol()+" are NOT Allowed by Setting.");
       fx.checktml=1;
       return;
     }
   //--
   RefreshRates();
   fx.CheckOpen();
   if(fx.tto==0 && fx.hBm+fx.hSm>0) fx.CheckClose();
   //--
   if(Usechartcomm==Yes) fx.ChartComm();
   //--
   fx.GetOpenPosition();
   //Buy Condition
   if(fx.takeBuyPositions())
     {
       //--
       fx.CheckOpen();
       //--
       if(fx.oBm==0 && fx.IFNewBarsB(Symbol())) {fx.cB=1; fx.OpenBuy(); fx.PbarB=fx.TbarB;}
       else if(fx.oBm==0 && fx.oSm>0) {fx.cB=2; fx.OpenBuy(); fx.PbarB=fx.TbarB;}
       fx.CheckOpen();
       if(fx.oBm>0 && Close_by_Opps==Yes && fx.oSm>0) {fx.CloseSellPositions(); fx.PbarB=fx.TbarB;}
     }
   //--
   //Sell Condition
   if(fx.takeSellPositions())
     {
       //--
       fx.CheckOpen();
       //--
       if(fx.oSm==0 && fx.IFNewBarsS(Symbol())) {fx.cS=1; fx.OpenSell(); fx.PbarS=fx.TbarS;}
       else if(fx.oSm==0 && fx.oBm>0) {fx.cS=2; fx.OpenSell(); fx.PbarS=fx.TbarS;}
       fx.CheckOpen();
       if(fx.oSm>0 && Close_by_Opps==Yes && fx.oBm>0) {fx.CloseBuyPositions(); fx.PbarS=fx.TbarS;}
     }
   //--
   if(CSexit==Yes) fx.SignalExit();
   //--
   if(OrdersTotal()>=fx.ALO) fx.CloseAllOrdersProfit();
   //---
   //Trailing Stop / Take Profit Position
   if(fx.utr==Yes)
     {
       fx.CheckOpen();
       if(fx.oBm>0) fx.TrailingPositionsBuy();
       if(fx.oSm>0) fx.TrailingPositionsSell();
     }
   //--
   return;
//---
  } //-end OnTick()
//---------//

First, the Expert Advisor checks whether automatic trading on symbols and MetaTrader 4 is allowed. If is not, it alerts that "Trading on the symbol is NOT Allowed by Setting."

Especially for novice traders:

  • 1. Check if the "AutoTrading" button is red or green. If red, click it once to turn it green.
  • 2. Check if the Expert Advisor icon in the upper right corner of the chart shows a crying or laughing face. If crying:
    • 1. Click the Tools menu.
    • 2. Select Options.
    • 3. Click the Expert Advisors tab.
    • 4. Check "Allow automated trading." The icon will show a laughing face, and the "AutoTrading" button will turn green.

After that, the Expert Advisor starts trading activities by:

  • 1. Calling the CheckOpen function to check for open orders. If none, it calls the CheckClose function to reset the open buy or sell order count to zero.
  • 2. If Display Setting on Chart is Yes, it calls the ChartComm function to display settings on the chart.

CheckOpen function.

This is a function named CheckOpen in the EXP class, which seems to be used for checking the status of open trades. Here's a step-by-step explanation:

1. Initialization:

  • oBm and oSm are set to 0. These might represent the count of Buy and Sell orders, respectively.
  • profitb and profits are set to 0.0. These variables likely store the profit from Buy and Sell orders.
  • totalorder is set to OrdersTotal(), which retrieves the total number of orders.

2. Order Checking Loop:

  • A loop iterates through all orders (totalorder). The loop runs as long as opn is less than totalorder and the IsStopped() function returns false.
  • Inside the loop, OrderSelect(opn, SELECT_BY_POS, MODE_TRADES) selects the order at position opn.

3. Order Validation:

  • It checks if the selected order's symbol matches the current symbol (OrderSymbol() == Symbol()) and its magic number matches magicEA.
  • If these conditions are met, it proceeds to check the order type.

4. Order Type Checking:

  • If the order is a Buy order (OrderType() == OP_BUY):
    • oBm and hBm are incremented.
    • profitb is calculated as the sum of OrderProfit(), OrderCommission(), and OrderSwap().
  • If the order is a Sell order (OrderType() == OP_SELL):
    • oSm and hSm are incremented.
    • profits is calculated similarly.

5.Profit Calculation:

  • floatprofit is set to the sum of profitb and profits.

6.Total Orders:

  • tto is set to the sum of oBm and oSm, which likely represents the total number of Buy and Sell orders.

7.End of Function::

  • The function ends and returns..

The CheckOpen function essentially counts the number of Buy and Sell orders, calculates their respective profits, and totals them up. It handles trades by ensuring they match specific criteria (symbol and magic number) before processing.


void EXP::CheckOpen(void) //-- function: CheckOpenTrade.
  {
//---
    oBm=0;
    oSm=0;
    profitb=0.0;
    profits=0.0;
    int totalorder=OrdersTotal();
    //--
    for(int opn=0; opn<totalorder && !IsStopped(); opn++)
      {
        if(OrderSelect(opn,SELECT_BY_POS,MODE_TRADES))
          {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==magicEA)
              {
                //--
                if(OrderType()==OP_BUY)  
                  {
                    oBm++; 
                    hBm++;
                    profitb=OrderProfit()+OrderCommission()+OrderSwap();                
                  }
                if(OrderType()==OP_SELL) 
                  {
                    oSm++; 
                    hSm++;
                    profits=OrderProfit()+OrderCommission()+OrderSwap();
                  }
                //--
                floatprofit=profitb+profits;
              }
            //--
          }
      }
    //--
    tto=oBm+oSm;
    //---
    return;
//---
  } //-end CheckOpen()
//---------//

CheckClose function.


void EXP::CheckClose(void) //-- function: CheckOrderClose.
  {
//----
    //--
    CheckOpen();
    datetime octm;
    int hyst=OrdersHistoryTotal();
    //--
    for(int b=hyst-1; b>=0; b--)
      {
        //--
        if(OrderSelect(b,SELECT_BY_POS,MODE_HISTORY))
          {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==magicEA)
              {
                //--
                if(OrderType()==OP_BUY)
                  {
                    octm=OrderCloseTime();
                    if(hBm>0 && oBm==0 && octm>0) hBm=0;                            
                  }
                //--
                if(OrderType()==OP_SELL)
                  {
                    octm=OrderCloseTime();
                    if(hSm>0 && oSm==0 && octm>0)  hSm=0;                              
                  }
              }
          }
        //--
      }
   //--
   //---
   return;
//----
  } //-end CheckClose()
//---------//

ChartComm function.


void EXP::ChartComm() // function: write comments on the chart
  {
//---
   string opnsignal=posBUY ? "BUY" : posSELL ? "SELL" : "Not Trade";
   //--
   Comment("n     :: Server Date Time : ",(string)Year(),".",(string)Month(),".",(string)Day(), "   ",TimeToString(TimeCurrent(),TIME_SECONDS), 
      "n     ------------------------------------------------------------", 
      "n      :: Broker             :  ",TerminalCompany(), 
      "n      :: Acc. Name       :  ",AccountName(), 
      "n      :: Acc, Number    :  ",(string)AccountNumber(),
      "n      :: Acc,TradeMode :  ",AccountMode(),
      "n      :: Acc. Leverage   :  1 : ",(string)AccountLeverage(), 
      "n      :: Acc. Balance     :  ",DoubleToString(AccountBalance(),2),
      "n      :: Acc. Equity       :  ",DoubleToString(AccountEquity(),2),
      "n      :: Timeframe        :  ",TF2Str(BnC),
      "n      :: Magic Number   :  ",string(magicEA),
      "n     --------------------------------------------",
      "n      :: Currency Pair    :  ",Symbol(),
      "n      :: Current Spread  :  ",IntegerToString(SymbolInfoInteger(Symbol(),SYMBOL_SPREAD),0),
      "n      :: Signal          : ",opnsignal,
      "n      :: Position BUY  : ",string(oBm),
      "n      :: Position SELL : ",string(oSm),
      "n      :: Current Profit : ",DoubleToString(floatprofit,2));
   //---
   ChartRedraw();
   return;
//----
  } //-end ChartComm()  
//---------//

Then, the Expert Advisor calls the GetOpenPosition function, which in turn calls the SignalCondition function. This function processes signals through:

  • 1. DirectionMove function: Checks if the Close Price is above (Buy Signal) or below (Sell Signal) the Open Price.
  • 2. AllowOpen function: Checks the Open Price position against the Moving Averages period 2 (LWMA Mode, Price Weighted).
  • 3. FiboPivotCB function: Calculates signal using four Moving Average indicators, standard ZigZag indicators for M30 and H1 Timeframes, and the MACD indicator.

SignalCondition function.


int EXP::SignalCondition(void) 
  {
//---
    int rise=1,
        down=-1;
    int InTRise=3;
    int InTDown=-3;
    int cond=0;
    //--   
    CheckOpen();
    int dmove=DirectionMove(BnC,0);
    int alopn=AllowOpen();
    int fbcb3=FiboPivotCB();
    //--
    int TrendIndi=fbcb3+dmove+alopn;
    //--
    if(TrendIndi==InTRise) {cond=rise; cdb=11;}
    if(TrendIndi==InTDown) {cond=down; cds=11;}
    if(oSm>0 && TrendIndi==InTRise) {cond=rise; cdb=12;}
    if(oBm>0 && TrendIndi==InTDown) {cond=down; cds=12;}
    //--
    return(cond);
//---
  } //-end SignalCondition()
//---------//

The SignalCondition function will call 4 functions:

  • CheckOpen();
  • DirectionMove();
  • AllowOpen();
  • FiboPivotCB();

DirectionMove function.


int EXP::DirectionMove(ENUM_TIMEFRAMES xtf,int shift) // Bar Direction 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int br=shift+1;
    RefreshPrice(Symbol(),xtf,br);
    //--
    double diff=iClose(Symbol(),xtf,shift)-iOpen(Symbol(),xtf,shift);
    if( diff>0.0) ret=rise;
    if (diff<0.0) ret=down;
    //--
    return(ret);
//---
  } //-end DirectionMove()
//---------//

AllowOpen function.


int EXP::AllowOpen(void)
  {
//---
    int res=0;
    int rise=1,
        down=-1;
    //--
    int MAWper02=2;
    double MAFast[];
    //--
    ArrayResize(MAFast,bartotal,bartotal);
    ArraySetAsSeries(MAFast,true);
    //--
    CopyPrices();
    //--
    for(int x=bartotal-1; x>=0; x--)
      MAFast[x]=iMA(Symbol(),BnC,MAWper02,0,MODE_LWMA,PRICE_WEIGHTED,x);
    //--
    bool OpenUp=(OPEN[0]<MAFast[0]);
    bool OpenDn=(OPEN[0]>MAFast[0]);
    //--
    if(OpenUp) res=rise;
    if(OpenDn) res=down;
    //--
    //Print(Symbol()+" : AllowOpen res = "+string(res));
    //--
    return(res);
//---
  } //-end AllowOpen()
//---------//

FiboPivotCB function.


int EXP::FiboPivotCB(void) // Signal BUY / SELL Indicator FiboPivotCandleBar
  {
//---
    int res=0;
    int rise=1,
        down=-1;
    //--
    int zzh1=0;
    int zzl1=0;
    int zhm1=0;
    int zlm1=0;
    bool ArrUp=false;
    bool ArrDn=false;
    bool opsup=false;
    bool opsdn=false;
    bool opsnt=false;
    //--   
    ENUM_TIMEFRAMES
       cprz=PERIOD_M15,
       prhh=PERIOD_M30,
       prh1=PERIOD_H1;
    ENUM_MA_METHOD mmeth1=MODE_EMA;
    ENUM_MA_METHOD mmeth2=MODE_SMA;
    ENUM_APPLIED_PRICE aprice=PRICE_MEDIAN;
    //--
    double ema02m[];
    double sma20m[];
    double maon10[];
    double maon62[];
    //--
    ArrayResize(ema02m,bartotal);
    ArrayResize(sma20m,bartotal);
    ArrayResize(maon10,bartotal);
    ArrayResize(maon62,bartotal);
    ArraySetAsSeries(ema02m,true);
    ArraySetAsSeries(sma20m,true);
    ArraySetAsSeries(maon10,true);
    ArraySetAsSeries(maon62,true);
    //--
    RefreshPrice(Symbol(),cprz,bartotal);
    //--
    for(int j=bartotal-1; j>=0; j--)
      {ema02m[j]=iMA(Symbol(),cprz,2,0,mmeth1,aprice,j);}
    for(int k=bartotal-1; k>=0; k--)
      {sma20m[k]=iMA(Symbol(),cprz,20,0,mmeth2,aprice,k);}
    //--
    SimpleMAOnBuffer(bartotal,0,0,10,sma20m,maon10);
    SimpleMAOnBuffer(bartotal,0,0,62,sma20m,maon62);
    //--
    double ma10620=maon10[0]-maon62[0];
    double ma10621=maon10[1]-maon62[1];
    double ma20100=sma20m[0]-maon10[0];
    double ma20101=sma20m[1]-maon10[1];
    //--
    bool ma5xupn=(ema02m[0]>ema02m[1])&&(sma20m[0]>sma20m[1])&&(ma10620>=ma10621)&&((maon10[2]<maon62[2])&&(maon10[0]>maon62[0]));
    bool ma5xupc=(ema02m[0]>ema02m[1])&&(sma20m[0]>sma20m[1])&&(ma10620>=ma10621)&&(maon10[0]>maon62[0])&&(maon10[0]>maon10[1]);
    bool ma5xupb=(ema02m[0]>ema02m[1])&&(sma20m[0]>sma20m[1])&&(ma20100>ma20101)&&(maon62[0]>maon62[1])&&(sma20m[0]>maon10[0]);
    bool ma5xdnn=(ema02m[0]<ema02m[1])&&(sma20m[0]<sma20m[1])&&(ma10620<=ma10621)&&((maon10[2]>maon62[2])&&(maon10[0]<maon62[0]));
    bool ma5xdnc=(ema02m[0]<ema02m[1])&&(sma20m[0]<sma20m[1])&&(ma10620<=ma10621)&&(maon10[0]<maon62[0])&&(maon10[0]<maon10[1]);
    bool ma5xdna=(ema02m[0]<ema02m[1])&&(sma20m[0]<sma20m[1])&&(ma20100<ma20101)&&(maon62[0]<maon62[1])&&(sma20m[0]<maon10[0]);
    //--
    RefreshPrice(Symbol(),prhh,bartotal);
    for(int zz=bartotal-1; zz>=0; zz--) //- for(zz)
      {
        if(iHigh(Symbol(),prhh,zz)==iCustom(Symbol(),prhh,"ZigZag",12,5,3,1,1,zz))
          {zhm1=zz;}
        if(iLow(Symbol(),prhh,zz)==iCustom(Symbol(),prhh,"ZigZag",12,5,3,1,2,zz))
          {zlm1=zz;}
      } //-end for(zz m30)
    //--
    RefreshPrice(Symbol(),prh1,bartotal);
    for(int zz=bartotal-1; zz>=0; zz--) //- for(zz)
      {
        if(iHigh(Symbol(),prh1,zz)==iCustom(Symbol(),prh1,"ZigZag",12,5,3,1,zz))
          {zzh1=zz;}
        if(iLow(Symbol(),prh1,zz)==iCustom(Symbol(),prh1,"ZigZag",12,5,3,1,2,zz))
          {zzl1=zz;}
      } //-end for(zz h1)
    //--
    double macd0=iMACD(Symbol(),prh1,12,26,9,0,MODE_MAIN,0)-iMACD(Symbol(),prh1,12,26,9,0,MODE_SIGNAL,0);
    double macd1=iMACD(Symbol(),prh1,12,26,9,0,MODE_MAIN,1)-iMACD(Symbol(),prh1,12,26,9,0,MODE_SIGNAL,1);
    double mcdm0=iMACD(Symbol(),prh1,12,26,9,0,MODE_MAIN,0);
    double mcdm1=iMACD(Symbol(),prh1,12,26,9,0,MODE_MAIN,1);
    double mcds0=iMACD(Symbol(),prh1,12,26,9,0,MODE_SIGNAL,0);
    double mcds1=iMACD(Symbol(),prh1,12,26,9,0,MODE_SIGNAL,1);
    //--
    if((((zzl1<zzh1)&&(zzl1>0)&&(zzl1<4)&&(zlm1<zhm1)))||((macd0>macd1)&&(mcdm0>mcdm1))) {ArrUp=true;}
    //--
    if((((zzl1>zzh1)&&(zzh1>0)&&(zzh1<4)&&(zlm1>zhm1)))||((macd0<macd1)&&(mcdm0<mcdm1))) {ArrDn=true;}
    //--
    if(((ArrUp==true)&&(zzl1>4))||((mcdm0<mcdm1)&&(macd0<macd1))) {ArrDn=true; ArrUp=false;}
    if(((ArrDn==true)&&(zzh1>4))||((mcdm0>mcdm1)&&(macd0>macd1))) {ArrUp=true; ArrDn=false;}
    if((mcdm0>=mcdm1)&&(mcdm0>mcds0)&&(mcds0>mcds1)) {ArrUp=true; ArrDn=false;}
    if((mcdm0<=mcdm1)&&(mcdm0<mcds0)&&(mcds0<mcds1)) {ArrDn=true; ArrUp=false;}
    if(ma5xupn||ma5xupc||ma5xupb) {ArrUp=true; ArrDn=false;}
    if(ma5xdnn||ma5xdnc||ma5xdna) {ArrDn=true; ArrUp=false;}
    //--
    double fpCls0=(iHigh(Symbol(),prh1,0)+iLow(Symbol(),prh1,0)+iClose(Symbol(),prh1,0)+iClose(Symbol(),prh1,0))/4;
    double fpCls1=(iHigh(Symbol(),prh1,1)+iLow(Symbol(),prh1,1)+iClose(Symbol(),prh1,1)+iClose(Symbol(),prh1,1))/4;
    double hlcc0=fpCls0-iMA(Symbol(),prh1,20,0,mmeth2,aprice,0);
    double hlcc1=fpCls1-iMA(Symbol(),prh1,20,0,mmeth2,aprice,1);
    //--
    if((ArrUp==true)&&(hlcc0>hlcc1)) {opsup=true; opsdn=false; opsnt=false;}
    //--
    if((ArrDn==true)&&(hlcc0<hlcc1)) {opsdn=true; opsup=false; opsnt=false;}
    //--
    if((!opsup)&&(!opsdn)) {opsnt=true; opsup=false; opsdn=false;}
    //--
    //---
    if(ArrUp && opsup) res=rise;
    //--
    if(ArrDn && opsdn) res=down;
    //--
    //---
    return(res);
//---
  } //-end FiboPivotCB()
//---------//

The FiboPivotCB() that utilizes a combination of technical analysis indicators and Fibonacci Pivot Points to generate buy and sell signals.

1. Variable Declaration:

  • Various integer and boolean variables are declared to store intermediate calculations and signal flags.
  • Timeframe variables cprz, prhh, and prh1 are defined to specify different timeframes for calculations.
  • Arrays ema02m, sma20m, maon10, and maon62 are declared to store calculated moving averages.

2. Calculating Moving Averages:

  • The code calculates several moving averages using the iMA() function.
  • It also calculates differences between moving averages to identify potential trend changes.

3. Fibonacci Pivot Points:

  • The code calculates Fibonacci Pivot Points using the iHigh(), iLow(), and iClose() functions.
  • It identifies potential support and resistance levels based on these pivot points.

4. Trend Identification:

  • The code uses a combination of moving average crossovers and Fibonacci Pivot Points to identify potential uptrends and downtrends.
  • Boolean variables ArrUp and ArrDn are used to indicate upward and downward trends, respectively.

5. Signal Generation:

  • The final if conditions check the values of the trend indicators and Fibonacci Pivot Points to generate buy or sell signals.
  • res variable is set to rise for a buy signal and down for a sell signal.

Key Points to Note:

  • Timeframe Importance: The choice of timeframes (e.g., cprz, prhh, prh1) significantly impacts the sensitivity and accuracy of the signals.
  • Indicator Combination: The code combines multiple indicators to generate more robust signals, reducing the risk of false signals.

Buy Orders condition:

  • takeBuyPositions function is true.
  • No existing Buy order (one order per direction signal).
  • On a new bar (no previous Buy order or Close Buy order on that bar).
  • If a Sell order exists and Close Trade By Opposite Signal is Yes, it opens a Buy order and closes the Sell order.
  • If Close Trade By Opposite Signal is No, it opens a Buy order and leaves the Sell order open.

Sell Orders condition:

  • takeSellPositions function is true.
  • No existing Sell order (one order per direction signal).
  • On a new bar (no previous Sell order or Close Sell order on that bar).
  • If a Buy order exists and Close Trade By Opposite Signal is Yes, it opens a Sell order and closes the Buy order.
  • If Close Trade By Opposite Signal is No, it opens a Sell order and leaves the Buy order open.

If Use Close In Signal Exit is Yes, the Expert Advisor calls the SignalExit function to close orders if the signal is not significant.

If the Orders Total is greater than or equal to the ACCOUNT LIMIT ORDERS set by the broker, the Expert Advisor calls the CloseAllOrdersProfit function to close profitable orders, keeping the total open orders below the broker's limit.

If Use Trailing Stop and Trailing Profit is Yes, the Expert Advisor performs trailing stop and trailing profit using TrailingPositionsBuy for Buy orders and TrailingPositionsSell for Sell orders.

For additional functions, you can explore and learn from the Expert Advisor program it self. If you have any questions, feel free to write in the comments or email me.

I recommend testing this expert advisor directly on the trading terminal using a demo account. While you can use the StrategyTester, keep in mind that its results depend heavily on the complete history of price data in your MetaTrader 4. This expert advisor integrates multiple indicators, including a 6-period Moving Average, ZigZag indicator (two timeframes), and MACD indicator.

I've tested this expert advisor on the MT4 trading terminal using a demo account to evaluate its performance. As you can see, the expert advisor has opened orders according to the FiboPivotCandleBar for the MT4 indicator signal, which indicates that it is functioning well.

Thank you for reading this article.

See you in the next article on Expert Advisor programs or indicators for MetaTrader 4 and MetaTrader 5.

Please download the Expert Advisor: ExpFPCB-MT4 and Indicator: FiboPivotCandleBar

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:

Expert Advisor: ExpFPCB-MT4.mq4

Indicator: FiboPivotCandleBar.mq4

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

YouTube Channel: @ForexHomeExperts

YouTube Playlist: @ForexHomeExperts YouTube Playlist

Tagged: , , , , , , , , ,

0 comments:

Post a Comment

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...