MT5 y la velocidad en acción - página 48

 
fxsaber:

¿Impresión y Alerta no son asíncronas?

Quería que estas funciones fueran asíncronas. Probé una implementación a través de ChartEvent - funciona. Pero es muy lento. Había desenterrado esto.

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

void OnTick()
{
  _B(EventChartCustom(ChartFirst(), 123, 0, 0, NULL), 1);
}


2020.10.07 12:38:04.579 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 100 mсs.
2020.10.07 12:38:06.842 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 170 mсs.
2020.10.07 12:38:07.924 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 765 mсs.
2020.10.07 12:38:08.359 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 377 mсs.
2020.10.07 12:38:09.246 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 66 mсs.
2020.10.07 12:38:14.645 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 692 mсs.
2020.10.07 12:38:14.729 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 6427 mсs.
2020.10.07 12:38:15.140 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 479 mсs.
2020.10.07 12:38:15.222 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 125 mсs.
2020.10.07 12:38:15.373 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 606 mсs.


Renunció a una función tan cara en lugares críticos.


Sobre el tema de la Alerta.

Hasta ahora, podemos decir con seguridad que la alerta no es posible en los lugares críticos. La asincronía es necesaria.

 

Reproducción de los frenos SymbolInfoTick. Y no hay prueba de esfuerzo. La necesidad práctica te hace escribirlo así.

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

// Возвращает время Обзора рынка в миллисекундах.
long TimeCurrentMsc()
{
  long Res = 0;
  
  MqlTick Tick;
  
  for (int i = SymbolsTotal(true); i >= 0; i--) 
  {
    const string Symb = SymbolName(i, true);
    
    if (_B(SymbolInfoTick(Symb, Tick), 10) && (Tick.time_msc > Res))
      Res = Tick.time_msc;
  }

  return(Res);
}

void OnTick()
{ 
  TimeCurrentMsc();
}


Siga estas instrucciones para una reproducción rápida.

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

El envío sincrónico de órdenes informa de la ejecución satisfactoria más rápidamente que el ping al servidor de operaciones

fxsaber, 2020.09.30 20:36

  1. Abra una cuenta de demostración enel servidor de RannForex.
  2. Abrir los símbolos de Forex en la visión general del mercado y permitir el autotrading.
  3. En un solo gráfico inicie este EA.
  4. Lanza este script en el mismo gráfico - clonará el EA en otros símbolos. Ejecútalo con inAmount = 15.
  5. Espere a que aparezcan estos mensajes y observe el registro.


En una máquina rápida el resultado con 30 caracteres en Market Watch.

2020.10.07 13:28:01.931 Test9 (NZDCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 65 mсs.
2020.10.07 13:28:02.344 Test9 (EURAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 11 mсs.
2020.10.07 13:28:02.730 Test9 (EURAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 15 mсs.
2020.10.07 13:28:02.800 Test9 (AUDCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 11 mсs.
2020.10.07 13:28:05.471 Test9 (GBPAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 30 mсs.
2020.10.07 13:28:08.675 Test9 (NZDCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 28 mсs.
2020.10.07 13:28:08.675 Test9 (GBPAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 120 mсs.
2020.10.07 13:28:09.697 Test9 (CADCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 13 mсs.
2020.10.07 13:28:10.063 Test9 (EURCAD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 29 mсs.
2020.10.07 13:28:11.741 Test9 (CADJPY,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 32 mсs.
2020.10.07 13:28:12.597 Test9 (EURCAD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 33 mсs.


Espero no ser el único que se reproduce. Por supuesto, el retraso no es tan grande como el mostrado anteriormente. Pero aquí será posible llegar al fondo de las causas mucho más rápido.


ZZY TimeCurrentMsc no se introduce en MQL5 por alguna razón, a pesar de las repetidas solicitudes.

 
fxsaber:

Renunció a una función tan cara en lugares críticos.

Este es un inconveniente importante. Porque el modelo de eventos MQL es incompleto - no hay un evento cero, es decir, el evento que se llama cuando no hay otros eventos en la cola. Se puede emular a través de un evento personalizado. Pero teniendo en cuenta este inconveniente, el modelo basado en eventos carece de sentido para quienes están interesados en la velocidad

 
fxsaber:

EventChartCustom es caro.

¿Y sinChartFirst()?

 
Andrey Khatimlianskii:

¿Qué tal sin ChartFirst()?

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

long GetAnotherChart()
{
  long Chart = ::ChartFirst();
  
  while (Chart == ChartID())
    Chart = ChartNext(Chart);
 
  return(Chart);     
}


void OnTick()
{  
  const long Chart = GetAnotherChart();
  
  if (Chart)
    _B(EventChartCustom(Chart, 123, 0, 0, NULL), 1);
  
  _B(EventChartCustom(0, 123, 0, 0, NULL), 1);
}


2020.10.07 14:49:09.786 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 349 mсs.
2020.10.07 14:49:09.786 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 81 mсs.
2020.10.07 14:49:09.866 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 248 mсs.
2020.10.07 14:49:09.866 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 24 mсs.
2020.10.07 14:49:10.095 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 163 mсs.
2020.10.07 14:49:10.095 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 116 mсs.
2020.10.07 14:49:10.810 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 600 mсs.
2020.10.07 14:49:10.811 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 53 mсs.
2020.10.07 14:49:10.870 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 137 mсs.
2020.10.07 14:49:10.870 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 54 mсs.

Es más caro enviar a la carta de otra persona que a la propia.

 
A100:

Este es un defecto importante. Porque el modelo de eventos MQL es incompleto - no hay ningún evento nulo, es decir, un evento que se llama cuando no hay otros eventos en la cola. Se puede emular a través de un evento personalizado. Pero teniendo en cuenta este inconveniente, el modelo basado en eventos carece de sentido para quienes están interesados en la velocidad

OnTimer te permite hacer llamadas en segundo plano hasta 16 ms.
 
Renat Fatkhullin:
OnTimer le permite realizar llamadas de fondo con una frecuencia de hasta 16 ms.

Correcto, es decir, perdemos al menos16ms para nada (podemos volver como mínimo).Y no podíamos perderlos si había un evento gratuito de cero o eventos personalizados gratuitos. Y ahora el modelo de eventos en el caso de abajo funciona limitadamente:

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

MT5 y la velocidad en acción

fxsaber, 2020.10.06 01:27

Estás completamente fuera de onda. Digamos que necesita abrir dos posiciones en OnTick. El primer OrderSend dura unos pocos milisegundos. Después hay que hacer una foto instantánea. Y luego se debe llamar al segundo OrderSend.

Sólo OnTick puede ejecutarse durante cientos de milisegundos. Y sugieres que se haga un snapshot de OnTimer.

Y OnTimer se ha liberado para otros fines
 
Y además OnTimer no nos permite estar seguros de haber recibido un evento nulo porque parece tener una prioridad más alta que otros manejadores, lo cual es probablemente el principal contraargumento.
 
fxsaber:

Sobre el tema de la Alerta.

Por ahora, es seguro decir que la Alerta no se puede utilizar en lugares críticos. La asincronía es necesaria.

Alerta con una huella, puedes intentar sustituirla por una escritura rápida en algún lugar.
Me viene a la mente el sql nativo en memoria

 
Renat Fatkhullin:
No estaba sugiriendo una instantánea, estaba respondiendo a una pregunta directa sobre el temporizador de milisegundos.

Está ahí, aunque en el probador actual todavía se dispara con una frecuencia de 1 segundo. En el nuevo probador que estamos escribiendo, intentaremos cambiar esto.

A menudo utilizo el hecho de que el Tester tiene exactamente un temporizador de milisegundos, no de segundos. Prueba.

// Демонстрация корректной работы миллисекундного таймера в Тестере.
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006
#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun)
  {
    MqlTick Tick;
    
    if (SymbolInfoTick(_Symbol, Tick) && Tick.bid && Tick.ask)
      FirstRun = !EventSetMillisecondTimer(29); // 29 мс таймер.
  }
}

void OnTimer()
{
  static int Count = 0;
  
  if (Count < 10)
  {
    if ((bool)((++Count) & 1)) // Попеременно
      OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0); // Открываем позицию
    else if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0); // Закрываем позицию
  }
}

void OnDeinit( const int )
{
  // Распечатали историю в конце бэктеста.
  for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
      OrderPrint();
}


Resultado.

2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #11 2020.10.06 00:00:00.320 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.349 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #9 2020.10.06 00:00:00.262 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.291 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #7 2020.10.06 00:00:00.204 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.233 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #5 2020.10.06 00:00:00.146 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.175 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #3 2020.10.06 00:00:00.088 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.117 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #1 2020.10.06 00:00:00.000 balance 0.00 0.00000 0.00000 0.00000 2020.10.06 00:00:00.000 0.00000 0.00 0.00 100000000.00 0

Hay exactamente 29 ms entre el tiempo de apertura y el de cierre de la posición.