Librerías: OnTickMulti

 

OnTickMulti:

Multisímbolo OnTick.

OnTickMulti

Author: fxsaber

 
Мультисимвольное виртуальное окружение.
Мультисимвольное виртуальное окружение.
  • www.mql5.com
Данный пост посвящен дополнительному функционалу библиотеки виртуального окружения Virtual : Мультисимвольность. Теперь можно торговать в VIrtual не по одному символу, а по любым в одном виртуальном
 
   if (prev_calculated)
    EventChartCustom(Chart, 0, Index, 0, NULL);
Es posible que se salten los ticks si el evento no se ha puesto en cola. A veces ocurre (sobre todo en un VPS o en un ordenador lento).
 
Alain Verleyen en un VPS o en un ordenador lento).

Por desgracia, incluso los asesores sencillos que solo cuentan con la función OnTick se saltan ticks. Para los asesores de trading, se utilizan funciones CopyTicks y otros trucos para que funcionen sin saltarse ticks.

Esta biblioteca garantiza que no se pierdan ticks únicamente en el simulador. Todo funciona exactamente igual que con OnTick.

 
A continuación se muestra el código de un asesor sencillo creado por otra persona, en el que se ha ofrecido mostrar cómo se utiliza OnTickMulti.
/*
// https://www.mql5.com/ru/blogs/post/755348
#define VIRTUAL_TESTER_MULTI // Ejecución en el entorno de trading virtual OnTickMulti
#define VIRTUAL_LIMITS_TP_SLIPPAGE // Los órdenes de límite y TP se ejecutan al primer precio aceptado: deslizamiento positivo
#define VIRTUAL_CLOSEALL_BYEND // Cierra de forma forzada todas las órdenes al final de la simulación
// #define VIRTUAL_ALTERNATIVE // Velocidad alternativa de liquidación
*/

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

/*
#define REPORT_TESTER             // Los informes se guardarán automáticamente en el tester
#define REPORT_BROWSER            // Creación de un informe al iniciar el navegador: requiere autorización de la DLL.
#include <Report.mqh> // https://www.mql5.com/es/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 multicarácter.
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);
   }
}


Configuración del simulador.



Aceleración.

Se puede acelerar si se descomentan las primeras líneas.


Mediciones.

Configuración Resultado
Sin Virtual.mqh. paso más corto 0:00:13,184, paso más largo 0:00:15,031, paso medio 0:00:13,633
Con Virtual.mqh, inVirtualTester = false. paso más corto 0:00:14,735, paso más largo 0:00:16,384, paso medio 0:00:15,081
Con Virtual.mqh, inVirtualTester = true. recorrido más corto 0:00:05,872, recorrido más largo 0:00:05,964, recorrido medio 0:00:05,919
Con Virtual.mqh, inVirtualTester = true + VIRTUAL_ALTERNATIVE. recorrido más corto 0:00:06,172, recorrido más largo 0:00:07,791, recorrido medio 0:00:06,524

El asesor es extremadamente sencillo (0-2 posiciones abiertas por cada símbolo con SL/TP fijos, sin órdenes pendientes), por lo que, en esta variante, solo se puede lograr una aceleración de 2,5 veces.


TickValue+Swap+Commission.

Las pruebas anteriores se realizaron en modo por pips (véase la captura de pantalla de la configuración), para no tener que recalcular el TickValue en cada tick, conectando para ello otros símbolos. En este modo, los resultados son idénticos.

Si se necesita una aceleración a toda máquina, hay que utilizar esta solución.

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

Foro sobre trading, sistemas de trading automáticos y pruebas de estrategias de trading

Bibliotecas: OnTickMulti

fxsaber, 18 de marzo de 2024, 18:36

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

Configuración Resultado
Sin Virtual.mqh. paso más corto 0:00:13,184, paso más largo 0:00:15,031, paso medio 0:00:13,633

Arriba he destacado en el código una forma sencilla de acelerar un asesor multimoneda sin necesidad de bibliotecas Virtual.

Configuración Resultado
Sin Virtual.mqh +MagicNumberOrderSymbol paso más corto 0:00:08,608, paso más largo 0:00:10,236, paso medio 0:00:08,942

¡Una aceleración gratuita de 1,5 veces!

 

He comprobado la ralentización del Tester al pasar del modo monosimbólico al multisimbólico. No lo he hecho de forma del todo perfecta: el asesor es ficticio.


Un asesor de un solo símbolo.

#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++;
}
Configuración (OnTick) Duración (mcs) Número de ticks Rendimiento (ticks/mcs)
EURUSD 1079331 9 927 153 9,19
GBPUSD 1 229 032 11 309 740 9,20
USDJPY 1 307 322 11986756 9,16
USDCHF 1 121 541 10359511 9,23
AUDUSD 1 175 578 10758136 9,15

Se aprecia claramente que el rendimiento del Tester, expresado en número de ticks por unidad de tiempo, no depende del símbolo (modo por pips).


Asesor multisímbolo.

#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/es/code/47647

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

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

// OnTick multicarácter.
void OnTickMulti( const string &Symb, const int &Index )
{
  AmountTicks++;
}
Configuración (OnTickMulti) Duración (OnTickMulti) Duración (OnTick) Número de ticks Rendimiento (OnTickMulti) Rendimiento (OnTick)
EURUSD
3455901 1 079 331 9 927 153 2,87 9,19
EUR/USD, GBP/USD
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 4 737 226 43.583.160 3,78 9,20
EURUSD, GBPUSD, USDJPY, USDCHF, AUDUSD
16058223 5912804 54 341 296 3,38 9,19

El rendimiento depende ligeramente del número de caracteres, pero es tres veces menor.


Conclusión.

Si tu asesor multimoneda es una mezcla de sub-TS independientes de una sola moneda, será (como mínimo) tres veces más rápido optimizar cada uno de los sub-TS por separado (y luego combinarlos mediante Validate en una sola pasada) que optimizarlos todos juntos en un único asesor multimoneda.

 
Se ha añadido el modo «Apart».
Мультивалютный Apart-режим.
Мультивалютный Apart-режим.
  • www.mql5.com
Большинство мультивалютных советников представляют из себя портфель независимых (по логике торговых сигналов) друг от друга ТС, где если связь и есть, то за счет ММ - все ТС оказывают влияние на общие
 
La firma de OnTickMulti ha cambiado ligeramente.
// OnTick multicarácter.
void OnTickMulti( const string &Symb, const u int &Index )
 

Hola,

Parece que en las últimas versiones (5200+) el código ya no se compila:

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // OnTick multicaracter.

int TicksCounter[]; // Contador de los ticks recibidos de cada carácter especificado.

void OnInit()
{
  // Inicializamos el contador de ticks recibidos.
  ArrayResize(TicksCounter, ArraySize(OnTickMulti.Symbols));
  ArrayInitialize(TicksCounter, 0);
}

double OnTester()
{
  // Mostramos el número de ticks recibidos para cada carácter especificado.
  for (uint i = ArraySize(TicksCounter); (bool)i--;)
    Print(OnTickMulti.Symbols[i] + " - " + (string)TicksCounter[i] + " ticks.");

  ArrayPrint(OnTickMulti.Symbols); // Lista de caracteres de OnTickMulti.

  return(0);
}

// OnTick multicaracter.
void OnTickMulti( const string &Symb, const uint &Index )
{
  TicksCounter[Index]++; // Se ha incrementado el contador de ticks recibidos para el símbolo especificado.
}
 
Marat Sultanov #:

Parece que en las últimas versiones (5200+) el código ya no se compila.

La biblioteca se ha actualizado para adaptarse a los cambios deMQL5_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 решает уравнение Сильвестра для вещественных квазитреугольных или комплексных треугольных матриц верхнетреугольные матрицы