updating trading code from MQL4 to MQL5

 

Hi

I have the following MQL4 code:-

   if(CountOrders(0)!=0 || CountOrders(1)!=0)
      {
       for(int b=OrdersTotal()-1; b>=0; b--)
         {
          if(OrderSelect(b,SELECT_BY_POS)==true)
           {
            if(OrderSymbol()==_Symbol && OrderMagicNumber()==OrderMagic)
             {
              if(OrderType()==OP_BUY && TradeSignal>=0.5)
               {
                if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red))
                 {
                  if(TradeSignal==1.0)
                  {
                   lots = LotsOptimized(); 
                   if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){
                     };
                  }
                 }
               }
               if(OrderType()==OP_SELL && TradeSignal<=0.5)
               {
                if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red))
                 {
                  if(TradeSignal==0.0)
                  {
                   lots = LotsOptimized(); 
                   if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
                    };
                  }
                 }
               }
             }
            }
          }
         return;
        }
        
   lots = LotsOptimized(); 
   if(TradeSignal==0.0 && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_BUY))
     { 
      if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
       };
     }
   else if(TradeSignal==1.0 && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_SELL))
     {
      if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){
       };
     }
   return;
     
  }
and I have attempted to update this code to MQL5 as follows:-
   if(totalPositions > 0) {  // i.e. open positions detected
       for(int i = 0; i < totalPositions; i++) {
            string symbol = PositionGetSymbol(i);
            if (Symbol() == symbol) { // Open position found for this symbol
               ENUM_POSITION_TYPE type = PositionGetInteger(POSITION_TYPE); 
               if (type == POSITION_TYPE_BUY) postype = 1;
               if (type == POSITION_TYPE_SELL) postype = -1;
               int posmagic = PositionGetInteger(POSITION_MAGIC);
                 if(posmagic == ourmagic) {
                    if(postype == 1 && TradeSignal >= MinNeutralSignal) {  // a BUY order is selected and the trade signal > left boundary of the neutral signal
                       trade.PositionClose(_Symbol); // that is, there is either a neutral signal or a SELL signal, then close the BUY position 
                       if(TradeSignal>MaxNeutralSignal) { // if the order is closed and a SELL signal exists (exceeds the right boundary of the neutral signal), immediately open a SELL position
                          lots = LotsOptimized(); 
                          trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, lots, SymbolInfoDouble(_Symbol, SYMBOL_ASK), 0, 0);  
                          isTradeOpen = true;
                       }
                    }
                    if(postype == -1 && TradeSignal <= MaxNeutralSignal) { // a SELL order is selected and the trade signal < right boundary of the neutral signal
                       trade.PositionClose(_Symbol); // that is, there is either a neutral signal or a BUY signal, then close the SELL position
                       if(TradeSignal<MinNeutralSignal) { // if the order is closed and a BUY signal exists (less than the left boundary of the neutral signal), immediately open a BUY position
                          lots = LotsOptimized(); 
                          trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, lots, SymbolInfoDouble(_Symbol, SYMBOL_BID), 0, 0);  
                          isTradeOpen = true;
                       }
                    }
                 }
            }
       }
     return;
   }

I have a clean compile but backtesting suggests I have errors in translating..........

Any comments on obvious errors / improvements most welcome

Bob M Dunedin

New Zealand

Testing trading strategies on real ticks
Testing trading strategies on real ticks
  • 2016.08.04
  • www.mql5.com
The article provides the results of testing a simple trading strategy in three modes: "1 minute OHLC", "Every tick" and "Every tick based on real ticks" using actual historical data.
 
Directly use fxsaber's library MT4Orders, these are not a problem, you don't even need to modify the mql4 order-related code
 

yes - I am aware that I do not NEED to update this code

BUT, it would be great to have all code at the MQL5 standard, rather than a mixture of old and new

Bob M

 
Bob Matthews #:

yes - I am aware that I do not NEED to update this code

BUT, it would be great to have all code at the MQL5 standard, rather than a mixture of old and new

Bob M

converting the OrderSend line will unlikely be enuf. If you only convert that line, then you are missing out other things that would usualy go into mql5's OnInit function such as FILLING and DEVIATION. So, I think that you should consider hini's advice again.

 

Thanks for your advice.............

Fernando said it might be a daunting task to convert

FILLING and DEVIATION are new to me..............

I have watched various utube presentations on simply trading code and those two do not feature, so am puzzled

Bob M

 
Bob Matthews #:


without seeing your full code, we can only make guesses as to the code that you need; if you upload the full code, then, maybe we can make more applicable advice depending on the purpose of your full code. As it is, your only snippet does not give any context of what your ea should be doing, therefore your new code may or may not work.

 

Here is the full code..............

//+------------------------------------------------------------------+
//|                                         Expert without fuzzy.mq5 |
//|                                Copyright 2017, Dmitrievskiy Max. |
//|                        https://www.mql5.com/ru/users/dmitrievsky |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Dmitrievskiy Max."
#property link      "https://www.mql5.com/ru/users/dmitrievsky"
#property version   "1.00"

#include <Trade\AccountInfo.mqh>
#include <MT4Orders.mqh>

int hnd1, hnd2, hnd3;
double arr1[], arr2[], arr3[];

input double   MaximumRisk=0.01;
input double   CustomLot=0;    
input int      OrderMagic=666;

double   lots;
static datetime last_time=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
   hnd1 = iRSI(_Symbol,0,9,PRICE_CLOSE);
   hnd2 = iRSI(_Symbol,0,14,PRICE_CLOSE);
   hnd3 = iRSI(_Symbol,0,21,PRICE_CLOSE);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(!isNewBar())
     {  
      return;
     }
     
   double TradeSignal=CalculateSignal(); 
   
   if(CountOrders(0)!=0 || CountOrders(1)!=0)
      {
       for(int b=OrdersTotal()-1; b>=0; b--)
         {
          if(OrderSelect(b,SELECT_BY_POS)==true)
           {
            if(OrderSymbol()==_Symbol && OrderMagicNumber()==OrderMagic)
             {
              if(OrderType()==OP_BUY && TradeSignal>=0.5)
               {
                if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red))
                 {
                  if(TradeSignal==1.0)
                  {
                   lots = LotsOptimized(); 
                   if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){
                     };
                  }
                 }
               }
               if(OrderType()==OP_SELL && TradeSignal<=0.5)
               {
                if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red))
                 {
                  if(TradeSignal==0.0)
                  {
                   lots = LotsOptimized(); 
                   if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
                    };
                  }
                 }
               }
             }
            }
          }
         return;
        }
        
   lots = LotsOptimized(); 
   if(TradeSignal==0.0 && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_BUY))
     { 
      if(OrderSend(Symbol(),OP_BUY,lots,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,Green)){
       };
     }
   else if(TradeSignal==1.0 && CheckMoneyForTrade(_Symbol,lots,ORDER_TYPE_SELL))
     {
      if(OrderSend(Symbol(),OP_SELL,lots,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,Red)){
       };
     }
   return;
     
  }
//+------------------------------------------------------------------+

double CalculateSignal()
{
 double res =0.5;
 CopyBuffer(hnd1,0,0,1,arr1);
 CopyBuffer(hnd2,0,0,1,arr2);
 CopyBuffer(hnd3,0,0,1,arr3);
 
 if(arr1[0]>70 && arr2[0]>70 && arr3[0]>70) res=1.0;
 if(arr1[0]<30 && arr2[0]<30 && arr3[0]<30) res=0.0;
 
 if(arr1[0]<30 && arr2[0]<30 && arr3[0]>70) res=0.5;
 if(arr1[0]<30 && arr2[0]>70 && arr3[0]<30) res=0.5;
 if(arr1[0]>70 && arr2[0]<30 && arr3[0]<30) res=0.5;
 
 if(arr1[0]>70 && arr2[0]>70 && arr3[0]<30) res=0.5;
 if(arr1[0]>70 && arr2[0]<30 && arr3[0]>70) res=0.5;
 if(arr1[0]<30 && arr2[0]>70 && arr3[0]>70) res=0.5;
 
 if(arr1[0]<30 && arr2[0]<30 && (arr3[0]>40 && arr3[0]<60)) res=0.0;
 if(arr1[0]<30 && (arr2[0]>40 && arr2[0]<60) && arr3[0]<30) res=0.0;
 if((arr1[0]>40 && arr1[0]<60) && arr2[0]<30 && arr3[0]<30) res=0.0;
 
 if(arr1[0]>70 && arr2[0]>70 && (arr3[0]>40 && arr3[0]<60)) res=1.0;
 if(arr1[0]>70 && (arr2[0]>40 && arr2[0]<60) && arr3[0]>70) res=1.0;
 if((arr1[0]>40 && arr1[0]<60) && arr2[0]>70 && arr3[0]>70) res=1.0;
 
 return(res);
}

int CountOrders(int a)
  {
   int result=0;
   for(int k=0; k<OrdersTotal(); k++)
     {
      if(OrderSelect(k,SELECT_BY_POS,MODE_TRADES)==true)
        {
         if(OrderType()==a && OrderMagicNumber()==OrderMagic && OrderSymbol()==_Symbol)
           {result++;}
        }
     }
   return(result);
  }
  
double LotsOptimized()
  {
   CAccountInfo myaccount; SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
   double lot;
   
   lot=NormalizeDouble(myaccount.FreeMargin()*MaximumRisk/1000.0,2);
   if(CustomLot!=0.0) lot=CustomLot;
   
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
   int ratio=(int)MathRound(lot/volume_step);
   if(MathAbs(ratio*volume_step-lot)>0.0000001)
     {
      lot = ratio*volume_step;
     }
   if(lot<SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN)) lot=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(lot>SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX)) lot=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   return(lot);
  }
  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool isNewBar()
  {
   datetime lastbar_time=datetime(SeriesInfoInteger(Symbol(),_Period,SERIES_LASTBAR_DATE));
   if(last_time==0)
     {
      last_time=lastbar_time;
      return(false);
     }
   if(last_time!=lastbar_time)
     {
      last_time=lastbar_time;
      return(true);
     }
   return(false);
  
  }
//+------------------------------------------------------------------+

bool CheckMoneyForTrade(string symb,double lot,ENUM_ORDER_TYPE type)
  {
//--- Getting the opening price
   MqlTick mqltick;
   SymbolInfoTick(symb,mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- values of the required and free margin
   double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   //--- call of the checking function
   if(!OrderCalcMargin(type,symb,lots,price,margin))
     {
      //--- something went wrong, report and return false
      Print("Error in ",__FUNCTION__," code=",GetLastError());
      return(false);
     }
   //--- if there are insufficient funds to perform the operation
   if(margin>free_margin)
     {
      //--- report the error and return false
      Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
      return(false);
     }
//--- checking successful
   return(true);
  }
 
Bob Matthews #:

Here is the full code..............

you need some ArraySetAsSeries in your CalculateSignal() function; but that is just for starters. i suggest you download a few eas on codebase to see how to use them.

i would also create a single variable in place of arr1[0], arr2[0], arr3[0].

You also need to tell the ea to check the CopyBuffer is a real value, otherwise you will get many false signals.

You also have to recode the CountOrders() -- OrderSelect function for mt5.

and so on and so on... and so on and so on... ... ...

other examples of what needs to recoded is all the lines with OrderType OrderMagic and such will be several extra lines such as PositionGetDouble(NULL,POSITION_TYPE_BUY/SELL).

if you dont know what a rabbit hole is, you most certainly will once you start down this route!

 
Bob Matthews #:

Here is the full code..............

Here's an article regarding handles, arraysetasSeries etc etc.

https://www.mql5.com/en/articles/43

 
// Variables
input int OrderMagic = 12345;
input double TradeSignal;

// Others
double lots;
int ticket;
long position_type;
long magic;
string symbol_name;

// Check open positions
if(PositionsTotal() > 0)
{
    // Checking open positions by cycle
    for(int b = PositionsTotal() - 1; b >= 0; b--)
    {
        // Get position information
        ticket = PositionGetTicket(b);
        symbol_name = PositionGetString(POSITION_SYMBOL);
        magic = PositionGetInteger(POSITION_MAGIC);
        position_type = PositionGetInteger(POSITION_TYPE);

        if(symbol_name == _Symbol && magic == OrderMagic)
        {
            // Closing a BUY order and opening a new SELL order
            if(position_type == POSITION_TYPE_BUY && TradeSignal >= 0.5)
            {
                if(PositionClose(_Symbol, 0))
                {
                    if(TradeSignal == 1.0)
                    {
                        lots = LotsOptimized();
                        // Send SELL order
                        OrderSend(
                            _Symbol,
                            ORDER_TYPE_SELL,
                            lots,
                            SymbolInfoDouble(_Symbol, SYMBOL_BID),
                            0, 0, 0, NULL, OrderMagic, 0
                        );
                    }
                }
            }
            // Close a SELL order and open a new BUY order
            else if(position_type == POSITION_TYPE_SELL && TradeSignal <= 0.5)
            {
                if(PositionClose(_Symbol, 0))
                {
                    if(TradeSignal == 0.0)
                    {
                        lots = LotsOptimized();
                        // Send BUY order
                        OrderSend(
                            _Symbol,
                            ORDER_TYPE_BUY,
                            lots,
                            SymbolInfoDouble(_Symbol, SYMBOL_ASK),
                            0, 0, 0, NULL, OrderMagic, 0
                        );
                    }
                }
            }
        }
    }
    return;
}

// Opening new orders (if there is no position)
lots = LotsOptimized();

if(TradeSignal == 0.0)
{
    // Send BUY order
    OrderSend(
        _Symbol,
        ORDER_TYPE_BUY,
        lots,
        SymbolInfoDouble(_Symbol, SYMBOL_ASK),
        0, 0, 0, NULL, OrderMagic, 0
    );
}
else if(TradeSignal == 1.0)
{
    //  Send SELLorder
    OrderSend(
        _Symbol,
        ORDER_TYPE_SELL,
        lots,
        SymbolInfoDouble(_Symbol, SYMBOL_BID),
        0, 0, 0, NULL, OrderMagic, 0
    );
}

// LotsOptimized function (you need to add it yourself)
double LotsOptimized()
{
    // Write the logic of this function according to your own strategy.
    return 0.1;
}