Equity curve trading help

 

Good morning,

I would like to implement an EA that runs two EAs in one.

The first that send only virtual orders and deserves only to check that the equity curve is above or below its moving average.

The second identic to the virtual one that send real order to the broker and is active only when the equity curve calculated in the "first EA" is above its moving average.

I have no idea where begin because I'm almost a newbie and this is a rather complex topic.

I attach the code of the EA I have copied, modified and adapted from an old post.

#property copyright "Riccardo"
#property link      ""
#property version   "1"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Expert\Money\MoneyFixedMargin.mqh>
CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
CMoneyFixedMargin m_money;
//---
input bool     OpenBUY           = true;     // Buy positions
input bool     OpenSELL          = true;     // Sell positions
input bool     CloseBySignal     = true;     // CloseBySignal
input ushort   InpStopLoss       = 0.0;      // StopLoss
input ushort   InpTakeProfit     = 0.0;      // TakeProfit
input ushort   InpTrailingStop   = 0;        // TrailingStop
input int      BBperiod          = 24;       // Bollinger Bands period
input double   BBstdev            = 0.5;      //Bollinger Bands standard deviation
input int      RSILowerLevel     = 35;       //RSI index lower level
input int      RSIUpperLevel     = 65;       //RSI index upper level
input int      RSIPeriod         = 14;       //RSI Period
input bool     AutoLot           = true;     // AutoLot (percent from a free margin)
input double   Risk              = 10;       // Risk percent from a free margin
input double   ManualLots        = 0.1;      // ManualLots
input ulong    m_magic           = 123;      // Magic number
input string   TradeComment      = "RSI EA"; // TradeComment
input ulong    InpSlippage       = 1;        // Slippage
//---
int LotDigits;
//---
double         ExtStopLoss=0.0;
double         ExtTakeProfit=0.0;
double         ExtTrailingStop=0.0;
ulong          ExtSlippage=0;
ENUM_ACCOUNT_MARGIN_MODE m_margin_mode;
double         m_adjusted_point;             // point value adjusted for 3 or 5 points
int            handle_iBB;                  // variable for storing the handle of the Bollinger Bands indicator
int            handle_iRSI;                  // variable for storing the handle of th RSI indicator
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetMarginMode();
   if(!IsHedging())
     {
      Print("Hedging only!");
      return(INIT_FAILED);
     }
//---
   m_symbol.Name(Symbol());                  // sets symbol name
   if(!RefreshRates())
     {
      Print("Error RefreshRates. Bid=",DoubleToString(m_symbol.Bid(),Digits()),
            ", Ask=",DoubleToString(m_symbol.Ask(),Digits()));
      return(INIT_FAILED);
     }
   m_symbol.Refresh();
//---
   m_trade.SetExpertMagicNumber(m_magic);    // sets magic number

//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;

   ExtStopLoss       = InpStopLoss     * m_adjusted_point;
   ExtTakeProfit     = InpTakeProfit   * m_adjusted_point;
   ExtTrailingStop   = InpTrailingStop * m_adjusted_point;
   ExtSlippage       = InpSlippage     * digits_adjust;

   m_trade.SetDeviationInPoints(ExtSlippage);
//---
   if(!m_money.Init(GetPointer(m_symbol),Period(),m_adjusted_point))
      return(INIT_FAILED);
   m_money.Percent(10); // 10% risk
//--- create handle of the indicator iRSI
   handle_iBB=iBands(Symbol(),Period(),BBperiod,0,BBstdev,PRICE_CLOSE);
//--- if the handle is not created 
   if(handle_iBB==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//---
//--- create handle of the indicator iRSI
   handle_iRSI=iRSI(Symbol(),Period(),RSIPeriod,PRICE_OPEN);
//--- if the handle is not created 
   if(handle_iRSI==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
  //--- Do we have enough bars to work with?
   if(Bars(_Symbol,_Period)<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }  

// We will use the static Old_Time variable to serve the bar time.
// At each OnTick execution we will check the current bar time with the saved one.
// If the bar time isn't equal to the saved time, it indicates that we have a new tick.

   static datetime Old_Time;
   datetime New_Time[1];
   bool IsNewBar=false;

// copying the last bar time to the element New_Time[0]
   int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0) // ok, the data has been copied successfully
     {
      if(Old_Time!=New_Time[0]) // if old time isn't equal to new bar time
        {
         IsNewBar=true;   // if it isn't a first call, the new bar has appeared
         if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here ",New_Time[0]," old time was ",Old_Time);
         Old_Time=New_Time[0];            // saving bar time
        }
     }
   else
     {
      Alert("Error in copying historical times data, error =",GetLastError());
      ResetLastError();
      return;
     }

//--- EA should only check for new trade if we have a new bar
   if(IsNewBar==false)
     {
      return;
     }
 
//--- Do we have enough bars to work with
   int Mybars=Bars(_Symbol,_Period);
   if(Mybars<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }
  //--- Define some MQL5 Structures we will use for our trade
   MqlTick latest_price;      // To be used for getting recent/latest price quotes
   MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
   MqlDateTime now_time;
   
   // the rates arrays
   ArraySetAsSeries(mrate,true);
   //--- Get the last price quote using the MQL5 MqlTick Structure
   if(!SymbolInfoTick(_Symbol,latest_price))
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }

//--- Get the details of the latest 5 bars
   if(CopyRates(_Symbol,_Period,0,5,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      ResetLastError();
      return;
     }
     
// Copy the bar high prices of the last six bars 
   double arrayhigh[4];
   arrayhigh[0]=NormalizeDouble(mrate[1].high,_Digits);
   arrayhigh[1]=NormalizeDouble(mrate[2].high,_Digits);
   arrayhigh[2]=NormalizeDouble(mrate[3].high,_Digits);
   arrayhigh[3]=NormalizeDouble(mrate[4].high,_Digits);
   double max = arrayhigh[ArrayMaximum(arrayhigh)];
   
//Copy the bar low prices of the last six bars
  double arraylow[4];
  arraylow[0]=NormalizeDouble(mrate[1].low,_Digits);
  arraylow[1]=NormalizeDouble(mrate[2].low,_Digits);
  arraylow[2]=NormalizeDouble(mrate[3].low,_Digits);
  arraylow[3]=NormalizeDouble(mrate[4].low,_Digits);
  
  double min = arraylow[ArrayMinimum(arraylow)];

  
//---
   int total_buy=0;
   int total_sell=0;
//-count Buy and Sell positions, and also modify (if specified in the input parameters)
   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            if(m_position.PositionType()==POSITION_TYPE_BUY)
              {
               total_buy++;
               if(ExtTrailingStop>0)
                 {
                  if(m_position.PriceCurrent()>m_position.PriceOpen())
                     if(m_position.PriceCurrent()-2*ExtTrailingStop>m_position.StopLoss())
                       {
                        double sl=NormalizeDouble(m_position.PriceCurrent()-ExtTrailingStop,m_symbol.Digits());
                        m_trade.PositionModify(m_position.Ticket(),sl,m_position.TakeProfit());
                       }
                 }
              }

            if(m_position.PositionType()==POSITION_TYPE_SELL)
              {
               total_sell++;
               if(ExtTrailingStop>0)
                 {
                  if(m_position.PriceCurrent()<m_position.PriceOpen())
                     if(m_position.PriceCurrent()+2*ExtTrailingStop<m_position.StopLoss())
                       {
                        double sl=NormalizeDouble(m_position.PriceCurrent()+ExtTrailingStop,m_symbol.Digits());
                        m_trade.PositionModify(m_position.Ticket(),sl,m_position.TakeProfit());
                       }
                 }
              }
           }
//---
   double BBUpper_0=iBBGetUpper(0);
   double BBUpper_1=iBBGetUpper(1);
   double BBUpper_2=iBBGetUpper(2);
   double BBLower_0=iBBGetLower(0);
   double BBLower_1=iBBGetLower(1);
   double BBLower_2=iBBGetLower(2);
   double BBMiddle_0=iBBGetMiddle(0);
   double BBMiddle_1=iBBGetMiddle(1);
   double BBMiddle_2=iBBGetMiddle(2);
   double RSI_0 =iRSIGet(0);
   double RSI_1 =iRSIGet(1);
   
   //--- Declare bool type variables to hold our Buy Conditions & Sell Conditions
   
   bool Buy_Condition_2=(mrate[1].close>BBUpper_1);
   bool Buy_Condition_3=(mrate[2].close>BBUpper_2);
   bool Buy_Condition_4=(mrate[1].open<BBUpper_1);
   bool Buy_Condition_5=(mrate[2].open<BBUpper_2);
   bool Sell_Condition_2=(mrate[1].close<BBLower_1);
   bool Sell_Condition_3=(mrate[2].close<BBLower_2);
   bool Sell_Condition_4=(mrate[1].open>BBLower_1);
   bool Sell_Condition_5=(mrate[2].open>BBLower_2);
   
    if((MathAbs(mrate[1].open-mrate[1].close)>0.0045)||(MathAbs(mrate[2].open-mrate[2].close)>0.0045))
          {
          return;
          }
          
//--- close position by signal
   if(CloseBySignal)
     {
      if(total_buy>0 && m_position.PriceCurrent()<BBLower_0)
         ClosePositions(POSITION_TYPE_BUY);
      if(total_sell>0 && m_position.PriceCurrent()>BBUpper_0)
         ClosePositions(POSITION_TYPE_SELL);
     }
     
//--- open position
   if(OpenSELL && total_sell<1 && ((Sell_Condition_2||Sell_Condition_3)&&(Sell_Condition_4||Sell_Condition_5)))
      OPSELL();
   if(OpenBUY && total_buy<1 && ((Buy_Condition_2||Buy_Condition_3)&&(Buy_Condition_4||Buy_Condition_5)))
      OPBUY();
      
   
//---
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OPBUY()
  {
   if(!RefreshRates())
      return;

   double StopLossLevel=0.0;
   double TakeProfitLevel=0.0;

   if(ExtStopLoss>0)
      StopLossLevel=m_symbol.NormalizePrice(m_symbol.Ask()-ExtStopLoss);
   if(ExtTakeProfit>0)
      TakeProfitLevel=m_symbol.NormalizePrice(m_symbol.Ask()+ExtTakeProfit);

   double volume=LOT();
   if(volume!=0.0)
      m_trade.Buy(volume,NULL,m_symbol.Ask(),StopLossLevel,TakeProfitLevel,TradeComment);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OPSELL()
  {
   if(!RefreshRates())
      return;

   double StopLossLevel=0.0;
   double TakeProfitLevel=0.0;

   if(ExtStopLoss>0)
      StopLossLevel=m_symbol.NormalizePrice(m_symbol.Bid()+ExtStopLoss);
   if(ExtTakeProfit>0)
      TakeProfitLevel=m_symbol.NormalizePrice(m_symbol.Bid()-ExtTakeProfit);
//---
   double volume=LOT();
   if(volume!=0.0)
      m_trade.Sell(volume,NULL,m_symbol.Bid(),StopLossLevel,TakeProfitLevel,TradeComment);
  }
//+------------------------------------------------------------------+
//| Close Positions                                                  |
//+------------------------------------------------------------------+
void ClosePositions(ENUM_POSITION_TYPE pos_type)
  {
   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==Symbol() && m_position.Magic()==m_magic)
            if(m_position.PositionType()==pos_type)
               m_trade.PositionClose(m_position.Ticket());
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double LOT()
  {
   double lots=0.0;
//---
   if(AutoLot)
     {
      lots=0.0;
      //--- getting lot size for open long position (CMoneyFixedMargin)
      double sl=0.0;
      double check_open_long_lot=m_money.CheckOpenLong(m_symbol.Ask(),sl);

      if(check_open_long_lot==0.0)
         return(0.0);

      //--- check volume before OrderSend to avoid "not enough money" error (CTrade)
      double chek_volime_lot=m_trade.CheckVolume(m_symbol.Name(),check_open_long_lot,m_symbol.Ask(),ORDER_TYPE_BUY);

      if(chek_volime_lot!=0.0)
         if(chek_volime_lot>=check_open_long_lot)
            lots=check_open_long_lot;
     }
   else
      lots=ManualLots;
//---
   return(LotCheck(lots));
  }
//+------------------------------------------------------------------+
//| Lot Check                                                        |
//+------------------------------------------------------------------+
double LotCheck(double lots)
  {
//--- calculate maximum volume
   double volume=NormalizeDouble(lots,2);
   double stepvol=m_symbol.LotsStep();
   if(stepvol>0.0)
      volume=stepvol*MathFloor(volume/stepvol);
//---
   double minvol=m_symbol.LotsMin();
   if(volume<minvol)
      volume=0.0;
//---
   double maxvol=m_symbol.LotsMax();
   if(volume>maxvol)
      volume=maxvol;
   return(volume);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetMarginMode(void)
  {
   m_margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsHedging(void)
  {
   return(m_margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Get value of buffers for the iBands                               |
//+------------------------------------------------------------------+
double iBBGetUpper(const int index)
  {
   double BBUpper[1];
//--- reset error code 
   ResetLastError();
//--- fill a part of the iRSI array with values from the indicator buffer that has 0 index 
   if(CopyBuffer(handle_iBB,1,index,1,BBUpper)<0)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the iRSI indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(0.0);
     }
   return(BBUpper[0]);
  }
//+------------------------------------------------------------------+
double iBBGetLower(const int index)
  {
   double BBLower[1];
//--- reset error code 
   ResetLastError();
//--- fill a part of the iRSI array with values from the indicator buffer that has 0 index 
   if(CopyBuffer(handle_iBB,2,index,1,BBLower)<0)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the Lower BB indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(0.0);
     }
   return(BBLower[0]);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
double iBBGetMiddle(const int index)
  {
   double BBMiddle[1];
//--- reset error code 
   ResetLastError();
//--- fill a part of the iRSI array with values from the indicator buffer that has 0 index 
   if(CopyBuffer(handle_iBB,0,index,1,BBMiddle)<0)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the Middle BB indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(0.0);
     }
   return(BBMiddle[0]);
  }
//+------------------------------------------------------------------+
double iRSIGet(const int index)
  {
   double RSI[1];
//--- reset error code 
   ResetLastError();
//--- fill a part of the iRSI array with values from the indicator buffer that has 0 index 
   if(CopyBuffer(handle_iRSI,0,index,1,RSI)<0)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the RSI indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(0.0);
     }
   return(RSI[0]);
  }
//+------------------------------------------------------------------+