Особенности языка mql5, тонкости и приёмы работы - страница 231

 

Извините за вопросы новичка... так на какой из них мне стоит сосредоточиться для разработки кода? 4 или 5? Может быть, я не понимаю - стоит ли выбирать 5 только из-за торговой функциональности? Она лучше, чем MQL4s?

 
@rrb1002 #: Извините за вопросы новичка... так на какой из них мне стоит сосредоточиться для разработки кода? 4 или 5? Может быть, я не понимаю - стоит ли выбирать 5 только из-за торговой функциональности? Она лучше, чем MQL4s?

Выбор за вами, но если бы мне сказали, что более старая версия больше не разрабатывается, а все последние разработки ведутся на более новой, я бы подумал, что мой выбор будет очевиден (если только на него не влияют другие обстоятельства).

EDIT: Однако, учитывая, что в вашем профиле указано, что вы находитесь в США, это также может зависеть от того, каких брокеров вы планируете использовать и какие платформы они предлагают.
 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2023.01.07 23:01

Есть два типа брокеров, которые переводят время по США/Европе. Из-за этого, в частности, сдвигается время ролловера.

Тип брокера можно определять автоматически.

// Вычисление типа брокера (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"));
}


Результаты запуска на некоторых брокерах.

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

В данный момент скрипт выдает совсем иные результаты. Не рекомендую использовать MT5-календарь до полного понимания его особенностей.

 

Очень простой прием в MQL5 позволяет бесплатно ускорить бэктесты - запоминание индексов позиций/ордеров по типам.


Пример ускорения ранее опубликованного быстрого кода.

#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 - 1e4*_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);  
}

Имеет смысл разбивать позиции/ордера по типам.

 
Как конвертировать MQL4 EA в MQL5?
 
Если нужен мнимый ноль для любых double.
void OnStart()
{
  double d = 1;
  
  Print(d + d * 1e-17 == d); // true
  Print(d * 1e-17);
}
 
fxsaber #:
Если нужен мнимый ноль для любых double.

DBL_EPSILON

Наименьшее число для которого выполняется условие 1.0+DBL_EPSILON != 1.0

2.2204460492503131e-016

 
Slava #:

DBL_EPSILON

Наименьшее число для которого выполняется условие 1.0+DBL_EPSILON != 1.0

2.2204460492503131e-016

Спасибо!

 

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 gets true for the exact (binary) comparison ==
 
Slava #:

DBL_EPSILON

Наименьшее число для которого выполняется условие 1.0+DBL_EPSILON != 1.0

2.2204460492503131e-016

Это плохое объяснение, т.к.

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