Bibliothèque: OnTickMulti

 

OnTickMulti:

Multisymbol OnTick.

OnTickMulti

Author: fxsaber

 
Мультисимвольное виртуальное окружение.
Мультисимвольное виртуальное окружение.
  • www.mql5.com
Данный пост посвящен дополнительному функционалу библиотеки виртуального окружения Virtual : Мультисимвольность. Теперь можно торговать в VIrtual не по одному символу, а по любым в одном виртуальном
 
   if (prev_calculated)
    EventChartCustom(Chart, 0, Index, 0, NULL);
Il peut arriver que vous manquiez des ticks si l'événement n'est pas mis en file d'attente. Cela arrive parfois (surtout sur un VPS ou un ordinateur lent).
 
Alain Verleyen sur un VPS ou un ordinateur lent).

Malheureusement, même les experts conseillers simples dotés uniquement de la fonction OnTick peuvent manquer des ticks. Pour les experts conseillers de trading, on utilise les fonctions CopyTicks et d’autres astuces afin qu’ils fonctionnent sans manquer de ticks.

Cette bibliothèque garantit de ne pas manquer de ticks uniquement dans le Testeur. Tout fonctionne exactement comme avec OnTick.

 
Vous trouverez ci-dessous le code d'un expert simple créé par quelqu'un d'autre, qui a bien voulu montrer comment utiliser OnTickMulti.
/*
// https://www.mql5.com/ru/blogs/post/755348
#define VIRTUAL_TESTER_MULTI // Lancement dans l'environnement de trading virtuel OnTickMulti
#define VIRTUAL_LIMITS_TP_SLIPPAGE // Les ordres stop et TP sont exécutés au premier cours accepté - slippage positif
#define VIRTUAL_CLOSEALL_BYEND // Ferme de force tous les ordres à la fin du test
// #define VIRTUAL_ALTERNATIVE // Vitesse de calcul alternative
*/

#include <MT4Orders.mqh> // https://www.mql5.com/fr/code/16006
#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // https://www.mql5.com/fr/code/47647

/*
#define REPORT_TESTER             // Les rapports seront automatiquement enregistrés dans le testeur
#define REPORT_BROWSER            // Création d'un rapport avec le lancement du navigateur - nécessite l'autorisation de la DLL.
#include <Report.mqh> // https://www.mql5.com/fr/code/18801
*/

input group "Trading"
input double             LotSize=0.01;
input double             TPdist=0.1;                        // TP (%)
input double             SLdist=0.2;                        // SL (%)
input long               MyMagic=123;

input group "Benchmark: https://www.mql5.com/ru/forum/282062/page49#comment_50801337"
input int inRange = 0;

// OnTick multi-caractères.
void OnTickMulti( const string &Symb, const int &Index )
{
  TradeStep(Symb, Index);
}

double OnTester()
{
   return AccountInfoDouble(ACCOUNT_BALANCE);
}

int GetHour( const datetime time )
{
  return((int)(time / 3600) % 24);
}

void TradeStep( const string &symbol, const int &Index )
{
   if(GetHour(TimeTradeServer()) < 2)
      return;

   DoTrade(symbol, Index);
}

bool IsMySymbol( const string &Symb, const int &Index )
{
  return(OnTickMulti.IsOnlySymbolBase ||
         (
        #ifdef __VIRTUAL__
          VIRTUAL::GetHandle() ? (OrderSymbolID() == Index) : // https://www.mql5.com/ru/forum/282062/page52#comment_51051261
        #endif // #ifdef __VIRTUAL__
          (OrderSymbol() == Symb)));
}

void DoTrade(const string &symbol, const int &Index )
{
   int total=OrdersTotal();
   bool haveBuy=false;
   bool haveSell=false;
   for(int i=0; i<total; i++)
   {
      if(OrderSelect(i, SELECT_BY_POS) &&
         OrderMagicNumber()==MyMagic &&
         IsMySymbol(symbol, Index))
      {
         int type=OrderType();
         if(type==OP_BUY)
            haveBuy=true;
         if(type==OP_SELL)
            haveSell=true;
      }
   }
   
   if(!haveBuy)
   {
      double price=SymbolInfoDouble(symbol,SYMBOL_ASK);
      int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
      double tp=NormalizeDouble(price*(1.0+TPdist/100.0), digits);
      double sl=NormalizeDouble(price*(1.0-SLdist/100.0), digits);
      OrderSend(
         symbol,
         OP_BUY,
         LotSize,
         price,
         0,
         sl,
         tp,
         NULL,
         MyMagic);
   }

   if(!haveSell)
   {
      double price=SymbolInfoDouble(symbol,SYMBOL_BID);
      int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
      double tp=NormalizeDouble(price*(1.0-TPdist/100.0), digits);
      double sl=NormalizeDouble(price*(1.0+SLdist/100.0), digits);
      OrderSend(
         symbol,
         OP_SELL,
         LotSize,
         price,
         0,
         sl,
         tp,
         NULL,
         MyMagic);
   }
}


Paramètres du Tester.



Accélération.

Il est possible d'accélérer le code en décommentant quelques lignes au début.


Mesures.

Configuration Résultat
Sans Virtual.mqh. temps de passage le plus court : 0:00:13,184, temps de passage le plus long : 0:00:15,031, temps de passage moyen : 0:00:13,633
Avec Virtual.mqh, inVirtualTester = false. passage le plus court 0:00:14,735, passage le plus long 0:00:16,384, passage moyen 0:00:15,081
Avec Virtual.mqh, inVirtualTester = true. meilleur temps: 0:00:05,872, temps le plus long : 0:00:05,964, temps moyen : 0:00:05,919
Avec Virtual.mqh, inVirtualTester = true + VIRTUAL_ALTERNATIVE. meilleur temps 0:00:06,172, pire temps 0:00:07,791, temps moyen 0:00:06,524

Le robot est extrêmement simple (0 à 2 positions ouvertes par symbole avec des SL/TP fixes, sans ordres différés) ; c'est pourquoi, dans cette configuration, il n'est possible d'obtenir qu'un gain de vitesse de 2,5 fois.


TickValue+Swap+Commission.

Les tests ci-dessus ont été effectués en mode « par pips » (voir la capture d'écran des paramètres), afin de ne pas avoir à recalculer la TickValue à chaque tick en connectant d'autres instruments pour cela. Dans ce mode, les résultats sont identiques.

Si vous recherchez une accélération maximale, c'est cette solution qu'il vous faut.

OnTickMulti - с добавленными пересчетом прибыли в валюту депозита, свопами, комисссией в % за лот.
OnTickMulti - с добавленными пересчетом прибыли в валюту депозита, свопами, комисссией в % за лот.
  • 2023.12.25
  • www.mql5.com
Текущий вариант OnTickMulti https://www.mql5.com/ru/code/47647 считает прибыль в валюте каждого символа или можно получить в пипсах. Но на общий баланс они влияют в другой пропорции, согласно текущему
 

Forum consacré au trading, aux systèmes de trading automatisés et au test des stratégies de trading

Bibliothèques : OnTickMulti

fxsaber, 18/03/2024 18h36

void DoTrade(const string &symbol, const int &Index )
{
   int total=OrdersTotal();
   bool haveBuy=false;
   bool haveSell=false;
   for(int i=0; i<total; i++)
   {
      if(OrderSelect(i, SELECT_BY_POS) &&
         (OrderMagicNumber()==Index))
      {
         int type=OrderType();
         if(type==OP_BUY)
            haveBuy=true;
         if(type==OP_SELL)
            haveSell=true;
      }
   }
   
   if(!haveBuy)
   {
      double price=SymbolInfoDouble(symbol,SYMBOL_ASK);
      int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
      double tp=NormalizeDouble(price*(1.0+TPdist/100.0), digits);
      double sl=NormalizeDouble(price*(1.0-SLdist/100.0), digits);
      OrderSend(
         symbol,
         OP_BUY,
         LotSize,
         price,
         0,
         sl,
         tp,
         NULL,
         Index);
   }

   if(!haveSell)
   {
      double price=SymbolInfoDouble(symbol,SYMBOL_BID);
      int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
      double tp=NormalizeDouble(price*(1.0-TPdist/100.0), digits);
      double sl=NormalizeDouble(price*(1.0+SLdist/100.0), digits);
      OrderSend(
         symbol,
         OP_SELL,
         LotSize,
         price,
         0,
         sl,
         tp,
         NULL,
         Index);
   }
}

Configuration Résultat
Sans Virtual.mqh. passage le plus court 0:00:13.184, passage le plus long 0:00:15.031, passage moyen 0:00:13.633

J'ai mis en évidence ci-dessus dans le code une méthode simple pour accélérer un expert multidevises sans aucune bibliothèque Virtual.

Configuration Résultat
Sans Virtual.mqh +MagicNumberOrderSymbol passage le plus court 0:00:08,608, passage le plus long 0:00:10,236, durée moyenne d'un passage 0:00:08,942

Un gain de vitesse gratuit de 1,5 fois !

 

J'ai vérifié le ralentissement du Tester lors du passage du mode mono-symbole au mode multi-symboles. Je ne l'ai pas fait de manière tout à fait optimale : le conseiller est factice.


Expert advisor monosymbole.

#property tester_no_cache

input group "Benchmark: https://www.mql5.com/ru/forum/282062/page49#comment_50801337"
input int inRange = 0;

const ulong StartTime = GetMicrosecondCount();
int AmountTicks = 0;

double OnTester()
{
  return((double)(GetMicrosecondCount() - StartTime));
//  return(AmountTicks) ;
//  return((double)AmountTicks / (GetMicrosecondCount() - StartTime));
}

void OnTick()
{
  AmountTicks++;
}
Configuration (OnTick) Durée (mcs) Nombre de ticks Performance (ticks/mcs)
EURUSD 1079331 9 927 153 9,19
GBPUSD 1 229 032 11 309 740 9,20
USDJPY 1 307 322 11 986 756 9,16
USDCHF 1 121 541 10359511 9,23
AUDUSD 1 175 578 10758136 9,15

On constate clairement que les performances du Testeur, exprimées en nombre de ticks par unité de temps, ne dépendent pas du symbole (mode par pips).


Expert multisinaux.

#property tester_no_cache

input group "Benchmark: https://www.mql5.com/ru/forum/282062/page49#comment_50801337"
input int inRange = 0;

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // https://www.mql5.com/fr/code/47647

const ulong StartTime = GetMicrosecondCount();
int AmountTicks = 0;

double OnTester()
{
  return((double)(GetMicrosecondCount() - StartTime));
//  return(AmountTicks) ;
//  return((double)AmountTicks / (GetMicrosecondCount() - StartTime));
}

// OnTick multi-caractères.
void OnTickMulti( const string &Symb, const int &Index )
{
  AmountTicks++;
}
Configuration (OnTickMulti) Durée (OnTickMulti) Durée (OnTick) Nombre de ticks Performance (OnTickMulti) Performance (OnTick)
EURUSD
3455901 1 079 331 9 927 153 2,87 9,19
EURUSD, GBPUSD
6617085 2 308 363
21 236 893 3,20 9,19
EURUSD, GBPUSD, USDJPY
9188781 3615685 33 223 649 3,61 9,18
EURUSD, GBPUSD, USDJPY, USDCHF
11517804 4737226 43 583 160 3,78 9,20
EURUSD, GBPUSD, USDJPY, USDCHF, AUDUSD
16058223 5912804 54 341 296 3,38 9,19

La performance dépend peu du nombre de caractères, mais elle est trois fois inférieure.


Conclusion.

Si votre expert multidevises est constitué d’un mélange de sous-stratégies monodevises indépendantes, il sera (au moins) trois fois plus rapide d'optimiser chacune des sous-stratégies (puis de les regrouper via Validate en un seul passage) séparément, plutôt que de les optimiser toutes ensemble au sein d'un seul expert multidevises.

 
Le mode « Apart » a été ajouté.
Мультивалютный Apart-режим.
Мультивалютный Apart-режим.
  • www.mql5.com
Большинство мультивалютных советников представляют из себя портфель независимых (по логике торговых сигналов) друг от друга ТС, где если связь и есть, то за счет ММ - все ТС оказывают влияние на общие
 
La signature de la fonction OnTickMulti a légèrement changé.
// OnTick multi-caractères.
void OnTickMulti( const string &Symb, const u int &Index )
 

Bonjour,

Il semblerait que, sur les dernières versions (5200+), le code ne se compile plus :

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // OnTick multicharactère.

int TicksCounter[]; // Compteur du nombre de ticks reçus pour chaque caractère spécifié.

void OnInit()
{
  // Initialisation du compteur de ticks reçus.
  ArrayResize(TicksCounter, ArraySize(OnTickMulti.Symbols));
  ArrayInitialize(TicksCounter, 0);
}

double OnTester()
{
  // Nous affichons le nombre de ticks reçus pour chaque caractère spécifié.
  for (uint i = ArraySize(TicksCounter); (bool)i--;)
    Print(OnTickMulti.Symbols[i] + " - " + (string)TicksCounter[i] + " ticks.");

  ArrayPrint(OnTickMulti.Symbols); // Liste des caractères OnTickMulti.

  return(0);
}

// OnTick multicharactère.
void OnTickMulti( const string &Symb, const uint &Index )
{
  TicksCounter[Index]++; // On a incrémenté le compteur des ticks reçus pour le caractère spécifié.
}
 
Marat Sultanov #:

Il semblerait que, sur les dernières versions (5200+), le code ne se compile plus

La bibliothèque a été mise à jour pour prendre en charge les modifications apportées àMQL5_b5200+.

Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5 - Версия MetaTrader 5 расширила поддержку библиотеки линейной алгебры OpenBLAS.
Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5 - Версия MetaTrader 5 расширила поддержку библиотеки линейной алгебры OpenBLAS.
  • 2025.07.31
  • www.mql5.com
SylvesterEquationTriangular решает уравнение Сильвестра для вещественных квазитреугольных или комплексных треугольных матриц верхнетреугольные. SylvesterEquationTriangularBlocked решает уравнение Сильвестра для вещественных квазитреугольных или комплексных треугольных матриц верхнетреугольные матрицы