Features of the mql5 language, subtleties and tricks - page 231

 
@rrb1002 #: sorry for the beginner questions ... so, which one should i focus on to develop code? 4 or 5?  maybe not understanding - should i just pick 5 for the trading functionality?  is it better than MQL4s?

Well, the choice is yours, but if someone told me that the older one is no longer being developed and all the latest development is on the newer one, I would think that my choice would be obvious (unless there were other circumstances weighing on it).

EDIT: However, given that your profile indicates that you are in the USA, it may also depend on which brokers you plan to use and which platforms they offer.
 

Forum on trading, automated trading systems and testing trading strategies

Peculiarities of mql5 language, subtleties and techniques of work

fxsaber, 2023.01.07 23:01

There are two types of brokers, which translate the time in the USA/Europe. Because of this, in particular, the rollover time is shifted.

The broker type can be determined automatically.

// Вычисление типа брокера (USA/Europe).

bool IsEuropeBroker()
{
  MqlCalendarValue Value[1];
  
  CalendarValueHistoryByEvent(840030016, Value, D'2022.11.03', D'2022.11.05');
  
  return(Value[0].time == ChartNewsTime(Value[0].time)); // https://www.mql5.com/ru/forum/357793/page5#comment_44225999
}

void OnStart()
{
  Print(AccountInfoString(ACCOUNT_SERVER) + " - " + (IsEuropeBroker() ? "Europe" : "USA"));
}


The results of running on some brokers.

RannForex-Server - Europe
MetaQuotes-Demo - Europe
FXOpen-MT5 - USA
Alpari-MT5 - Europe
Tickmill-Live - USA
ICMarketsSC-MT5-2 - USA
Darwinex-Live - USA

At the moment the script produces quite different results. I do not recommend using MT5-calendar until you fully understand its peculiarities.

 

A very simple technique in MQL5 allows you to speed up backtests for free - memorisation of position/order indexes by type.


An example of speeding up the previously published quick code.

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

input int inAmountMagics = 50; // Сколько ТС эмулировать

// Для каждой ТС открываем позицию и отложку. MT4-код для лаконичности.
void OnInit()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))  
    for (int i = 0; i < inAmountMagics; i++)
    {
      OrderSend(_Symbol, OP_BUY, 1, Tick.ask, 0, 0, 0, NULL, i);
      
      OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - 1 e4*_Point, 0, 0, 0, NULL, i);
    }
}

#define  MAX_ORDERS 100

// Индексы позиций/ордеров по типам.
struct TYPE_INDEXES
{
  int Index[OP_SELLSTOP + 1][MAX_ORDERS];
  int Amount[OP_SELLSTOP + 1];
  
  // Заполнение индексов.
  void Fill( void )
  {
    ::ArrayInitialize(this.Amount, 0);
    
    for (int i = ::PositionsTotal() - 1; i >= 0; i--)
      if (::PositionGetTicket(i))
      {
        const int Type = (int)PositionGetInteger(POSITION_TYPE);
        
        this.Index[Type][this.Amount[Type]++] = i;
      }

    for (int i = ::OrdersTotal(true) - 1; i >= 0; i--)
      if (::OrderGetTicket(i))
      {
        const int Type = (int)OrderGetInteger(ORDER_TYPE);
        
        this.Index[Type][this.Amount[Type]++] = i;
      }
      
    return;          
  }
};

#undef  MAX_ORDERS

// Сбор информации с нужных позиций/ордеров. Максимально быстрый MT5-код.
double CountOrders( const int Type, const int Magic, const TYPE_INDEXES &TypeIndexes )
{
  double Res = 0;
  
  if (Type <= OP_SELL)
  {
    for (int i = TypeIndexes.Amount[Type] - 1; i >= 0; i--)
      if (PositionGetTicket(TypeIndexes.Index[Type][i]) && PositionGetInteger(POSITION_MAGIC) == Magic)
        Res += PositionGetDouble(POSITION_PRICE_OPEN) + PositionGetDouble(POSITION_PRICE_CURRENT) +
               PositionGetDouble(POSITION_TP) + PositionGetDouble(POSITION_SL);
  }
  else
    for (int i = TypeIndexes.Amount[Type] - 1; i >= 0; i--)
      if (OrderGetTicket(TypeIndexes.Index[Type][i]) && OrderGetInteger(ORDER_MAGIC) == Magic)
        Res += OrderGetDouble(ORDER_PRICE_OPEN) + OrderGetDouble(ORDER_PRICE_CURRENT) +
               OrderGetDouble(ORDER_TP) + OrderGetDouble(ORDER_SL);
        
  return(Res);
}

// Число для контроля корректности альтернативных реализаций.
double OnTesterValue = 0;
double OnTester() { return(OnTesterValue); }

void OnTick()
{
  TYPE_INDEXES TypeIndexes; // Индексы позиций/ордеров по типам.
  
  TypeIndexes.Fill(); // Заполнение индексов.
  
  // Симулируем работу по всем ТС.
  for (int i = 0; i < inAmountMagics; i++)
    OnTesterValue += CountOrders(POSITION_TYPE_BUY, i, TypeIndexes) + 
                     CountOrders(POSITION_TYPE_SELL, i, TypeIndexes) +
                     CountOrders(ORDER_TYPE_BUY_LIMIT, i, TypeIndexes) +
                     CountOrders(ORDER_TYPE_SELL_LIMIT, i, TypeIndexes);  
}

It makes sense to split positions/orders by types.

 
How to convert MQL4 EA to MQL5?
 
If you need an imaginary zero for any double.
void OnStart()
{
  double d = 1;
  
  Print(d + d * 1 e-17 == d); // true
  Print(d * 1 e-17);
}
 
fxsaber #:
If you need an imaginary zero for any double.

DBL_EPSILON

The smallest number for which the condition 1.0+DBL_EPSILON != 1.0 holds.

2.2204460492503131e-016

 
Slava #:

DBL_EPSILON

The smallest number for which the condition 1.0+DBL_EPSILON != 1.0 is satisfied.

2.2204460492503131e-016

Thank you!

 

DBL_EPSILON

The smallest number that satisfies the condition 1.0+DBL_EPSILON != 1.0

2.2204460492503131e-016


Please excuse me for commenting in English, I do not speak Russian.

This means:

d * (1 + DBL_EPSILON) != d
d * (1 + 0.5 * DBL_EPSILON) == d

because the DBL_EPSILON is the relative error rate. relative means relative to the magnitude of the number.

at 1.0, the error rate = 1 * 2 .2204460492503131e-016 (DBL_EPSILON)

at d, the error rate = d * DBL_EPSILON .

The computer cannot differentiate between d and d * (1 + 0.5*DBL_EPSILON), so it encodes both of them to the same binary.
So, you get true for the exact (binary) comparison ==
 
Slava #:

DBL_EPSILON

The smallest number for which the condition 1.0+DBL_EPSILON != 1.0 is satisfied.

2.2204460492503131e-016

This is a bad explanation, because.

void OnStart()
{
  double d = 1 e5;
  
  Print(d + d * 0.1 == d * (1 + 0.1)); // false
}
 

Explanation of the definition of DBL_EPSILON:

void OnStart()
  {
   double epsilon = 1.0;
   while(1.0 + epsilon != 1.0)
      epsilon /= 2;
   epsilon *= 2;

   Print(epsilon);  // 2.220446049250313e-16
  }