Bibliotecas: OnTickMulti

 

OnTickMulti:

OnTick de vários símbolos.

OnTickMulti

Author: fxsaber

 
Мультисимвольное виртуальное окружение.
Мультисимвольное виртуальное окружение.
  • www.mql5.com
Данный пост посвящен дополнительному функционалу библиотеки виртуального окружения Virtual : Мультисимвольность. Теперь можно торговать в VIrtual не по одному символу, а по любым в одном виртуальном
 
   if (prev_calculated)
    EventChartCustom(Chart, 0, Index, 0, NULL);
Você pode perder os ticks se o evento não for colocado na fila. Isso acontece (principalmente em VPS ou em computadores lentos).
 
Alain Verleyen em VPS ou em computadores lentos).

Infelizmente, mesmo os consultores simples que possuem apenas a função OnTick deixam de receber os ticks. Para consultores de negociação, utilizam-se as funções CopyTicks e outros recursos para que funcionem sem perder ticks.

Esta biblioteca garante que não há perda de ticks apenas no Testador. Tudo funciona exatamente da mesma forma que com a função OnTick.

 
Abaixo está o código de um consultor simples criado por outra pessoa, no qual ele se propôs a demonstrar a aplicação do OnTickMulti.
/*
// https://www.mql5.com/ru/blogs/post/755348
#define VIRTUAL_TESTER_MULTI // Execução no ambiente de negociação virtual OnTickMulti
#define VIRTUAL_LIMITS_TP_SLIPPAGE // Os ordens de limite e TP são executadas ao primeiro preço de aceitação — slippage positivo
#define VIRTUAL_CLOSEALL_BYEND // Fechamento forçado de todas as ordens ao final do teste
// #define VIRTUAL_ALTERNATIVE // Velocidade alternativa de cálculos
*/

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

/*
#define REPORT_TESTER             // Os relatórios serão gravados automaticamente no testador
#define REPORT_BROWSER            // Criação de relatório com abertura do navegador — requer permissão da DLL.
#include <Report.mqh> // https://www.mql5.com/pt/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 com vários caracteres.
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);
   }
}


Configurações do Testador.



Aceleração.

É possível acelerar o código se você descomentar algumas linhas no início.


Medidas.

Configuração Resultado
Sem o Virtual.mqh. passagem mais curta 0:00:13,184, passagem mais longa 0:00:15,031, média das passagens 0:00:13,633
Com o Virtual.mqh, inVirtualTester = false. passagem mais curta 0:00:14,735, passagem mais longa 0:00:16,384, média das passagens 0:00:15,081
Com Virtual.mqh, inVirtualTester = true. passagem mais curta 0:00:05,872, passagem mais longa 0:00:05,964, média das passagens 0:00:05,919
Com Virtual.mqh, inVirtualTester = true + VIRTUAL_ALTERNATIVE. passagem mais curta 0:00:06,172, passagem mais longa 0:00:07,791, média das passagens 0:00:06,524

O consultor é extremamente simples (0 a 2 posições abertas por cada instrumento, com SL/TP fixos, sem ordens pendentes); portanto, nessa variante, é possível obter apenas uma aceleração de 2,5 vezes.


TickValue+Swap+Commission.

Os testes acima foram realizados no modo por pips (veja a captura de tela das configurações), para não precisar recalcular o TickValue a cada tick, conectando outros símbolos para isso. Nesse modo, os resultados são idênticos.

Se for necessário um aumento de velocidade com todas as opções ativadas, deve-se usar esta solução.

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

Fórum sobre trading, sistemas de negociação automatizados e testes de estratégias de trading

Bibliotecas: OnTickMulti

fxsaber, 18/03/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);
   }
}

Configuração Resultado
Sem o Virtual.mqh. passagem mais curta 0:00:13,184, passagem mais longa 0:00:15,031, média das passagens 0:00:13,633

Acima, destaquei no código uma maneira simples de acelerar um robô multimoeda sem o uso de nenhuma biblioteca Virtual.

Configuração Resultado
Sem o Virtual.mqh +MagicNumberOrderSymbol passagem mais curta 0:00:08,608, passagem mais longa 0:00:10,236, passagem média 0:00:08,942

Aceleração gratuita em 1,5 vez!

 

Verifiquei a lentidão do Tester ao passar do modo monossimbólico para o multissimbólico. Não fiz isso de maneira totalmente ideal — o consultor é fictício.


Consultor de um único 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++;
}
Configuração (OnTick) TimeLength (mcs) Quantidade de Ticks Desempenho (ticks/mcs)
EURUSD 1.079.331 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 10.359.511 9,23
AUDUSD 1.175.578 10758136 9,15

Fica bem claro que o desempenho do Testador, medido pelo número de ticks por unidade de tempo, não depende do símbolo (modo por pips).


Eximador multissí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/pt/code/47647

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

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

// OnTick com vários caracteres.
void OnTickMulti( const string &Symb, const int &Index )
{
  AmountTicks++;
}
Configuração (OnTickMulti) TimeLength (OnTickMulti) TimeLength (OnTick) Quantidade de Ticks Desempenho (OnTickMulti) Desempenho (OnTick)
EURUSD
3.455.901 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
EUR/USD, GBP/USD, USD/JPY
9188781 3615685 33.223.649 3,61 9,18
EUR/USD, GBP/USD, USD/JPY, USD/CHF
11517804 4.737.226 43.583.160 3,78 9,20
EUR/USD, GBP/USD, USD/JPY, USD/CHF, AUD/USD
16.058.223 5912804 54.341.296 3,38 9,19

O desempenho depende pouco do número de caracteres, mas é três vezes menor.


Conclusão.

Se o seu consultor multimoeda for uma mistura de sub-TS independentes de uma única moeda, será (no mínimo) três vezes mais rápido otimizar cada um dos sub-TS (e depois uni-los por meio do Validate em uma única execução) separadamente do que otimizar todos juntos em um único consultor multimoeda.

 
Foi adicionado o modo Apart.
Мультивалютный Apart-режим.
Мультивалютный Apart-режим.
  • www.mql5.com
Большинство мультивалютных советников представляют из себя портфель независимых (по логике торговых сигналов) друг от друга ТС, где если связь и есть, то за счет ММ - все ТС оказывают влияние на общие
 
A assinatura da função OnTickMulti sofreu algumas pequenas alterações.
// OnTick com vários caracteres.
void OnTickMulti( const string &Symb, const u int &Index )
 

Olá,

Parece que, nas versões mais recentes (5200+), o código não compila mais:

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // OnTick com vários caracteres.

int TicksCounter[]; // Contador de ticks recebidos para cada caractere definido.

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

double OnTester()
{
  // Exibimos o número de ticks recebidos para cada símbolo especificado.
  for (uint i = ArraySize(TicksCounter); (bool)i--;)
    Print(OnTickMulti.Symbols[i] + " - " + (string)TicksCounter[i] + " ticks.");

  ArrayPrint(OnTickMulti.Symbols); // Lista de símbolos do OnTickMulti.

  return(0);
}

// OnTick com vários caracteres.
void OnTickMulti( const string &Symb, const uint &Index )
{
  TicksCounter[Index]++; // Aumentamos o contador de ticks recebidos para o símbolo especificado.
}
 
Marat Sultanov #:

Parece que, nas versões mais recentes (5200+), o código não compila mais

A biblioteca foi atualizada para se adequar às alteraçõesdo 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 решает уравнение Сильвестра для вещественных квазитреугольных или комплексных треугольных матриц верхнетреугольные матрицы