Caractéristiques du langage mql5, subtilités et techniques - page 231

 

Désolé pour ces questions de débutant... Alors, sur lequel dois-je me concentrer pour développer du code ? 4 ou 5 ? je ne comprends peut-être pas - devrais-je choisir 5 pour la fonctionnalité de trading ? est-elle meilleure que MQL4s ?

 
@rrb1002 #: Désolé pour ces questions de débutant... Alors, sur lequel dois-je me concentrer pour développer du code ? 4 ou 5 ? je ne comprends peut-être pas - devrais-je choisir 5 pour la fonctionnalité de trading ? est-elle meilleure que MQL4s ?

Eh bien, c'est à vous de choisir, mais si quelqu'un me disait que l'ancien n'est plus développé et que tous les derniers développements sont sur le nouveau, je penserais que mon choix serait évident (à moins qu'il n'y ait d'autres circonstances qui pèsent sur lui).

EDIT : Cependant, étant donné que votre profil indique que vous êtes aux Etats-Unis, cela peut aussi dépendre des courtiers que vous comptez utiliser et des plateformes qu'ils proposent.
 

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Particularités du langage mql5, subtilités et techniques de travail

fxsaber, 2023.01.07 23:01

Il y a deux types de courtiers, qui traduisent le temps aux USA/Europe. C'est notamment pour cette raison que le temps de roulement est décalé.

Le type de courtier peut être déterminé automatiquement.

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


Les résultats de l'exécution sur certains courtiers.

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

Pour l'instant, le script produit des résultats assez différents. Je ne recommande pas l'utilisation de MT5-calendar tant que vous n'avez pas pleinement compris ses particularités.

 

Une technique très simple dans MQL5 vous permet d'accélérer les backtests gratuitement - la mémorisation des index de position/ordre par type.


Un exemple d'accélération du code rapide publié précédemment.

#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);  
}

Il est logique de diviser les positions/ordres par type.

 
Comment convertir MQL4 EA en MQL5 ?
 
Si vous avez besoin d'un zéro imaginaire pour un double quelconque.
void OnStart()
{
  double d = 1;
  
  Print(d + d * 1 e-17 == d); // true
  Print(d * 1 e-17);
}
 
fxsaber #:
Si vous avez besoin d'un zéro imaginaire pour un double quelconque.

DBL_EPSILON

Le plus petit nombre pour lequel la condition 1,0+DBL_EPSILON != 1,0 est vérifiée.

2.2204460492503131e-016

 
Slava #:

DBL_EPSILON

Le plus petit nombre pour lequel la condition 1,0+DBL_EPSILON != 1,0 est satisfaite.

2.2204460492503131e-016

Nous vous remercions de votre attention.

 

DBL_EPSILON

Le plus petit nombre qui satisfait à la condition 1,0+DBL_EPSILON != 1,0

2.2204460492503131e-016


Veuillez m'excuser de commenter en anglais, je ne parle pas russe.

Cela signifie que :

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

parce que le DBL_EPSILON est le taux d'erreur relatif. relatif signifie relatif à l'ampleur du nombre.

à 1,0, le taux d'erreur = 1 * 2 ,2204460492503131e-016 (DBL_EPSILON)

à d, le taux d'erreur = d * DBL_EPSILON .

L'ordinateur ne peut pas faire la différence entre d et d * (1 + 0,5*DBL_EPSILON), il les code donc tous les deux dans le même binaire.
Vous obtenez donc true pour la comparaison exacte (binaire) ==
 
Slava #:

DBL_EPSILON

Le plus petit nombre pour lequel la condition 1,0+DBL_EPSILON != 1,0 est satisfaite.

2.2204460492503131e-016

Il s'agit d'une mauvaise explication, car.

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