MT5 e la velocità in azione - pagina 48

 
fxsaber:

Print e Alert non sono asincroni?

Volevo rendere queste funzioni asincrone. Provato un'implementazione attraverso ChartEvent - funziona. Ma è molto lento. Avevo tirato fuori questo.

#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.


Ha rinunciato a una funzione così costosa in luoghi critici.


A proposito di Alert.

Finora possiamo dire con certezza che Alert in luoghi critici non è possibile. L'asincronia è necessaria.

 

Riprodotto i freni di SymbolInfoTick. E nessun test di stress. La necessità pratica ti fa scrivere così.

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


Seguite queste istruzioni per un replay veloce.

Forum sul trading, sistemi di trading automatico e test di strategie di trading

L'OrderSend sincrono riporta un'esecuzione riuscita più velocemente del ping al server commerciale

fxsaber, 2020.09.30 20:36

  1. Apri un conto demo sulRannForex-Server.
  2. Aprire i simboli Forex nella panoramica del mercato e permettere l'autotrading.
  3. Su un singolo grafico avvia questo EA.
  4. Lancia questo script sullo stesso grafico - clonerà l'EA su altri simboli. Eseguitelo con inAmount = 15.
  5. Aspettate questi messaggi e guardate il registro.


Su una macchina veloce il risultato con 30 caratteri in 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.


Spero di non essere l'unico che si sta riproducendo. Naturalmente, il ritardo non è così grande come mostrato in precedenza. Ma qui sarà possibile andare a fondo delle cause molto più rapidamente.


ZZY TimeCurrentMsc non viene inserito in MQL5 per qualche motivo, nonostante le ripetute richieste.

 
fxsaber:

Ha rinunciato a una funzione così costosa in luoghi critici.

Questo è uno svantaggio significativo. Perché il modello di eventi MQL è incompleto - non c'è un evento zero, cioè l'evento che viene chiamato quando non ci sono altri eventi nella coda. Può essere emulato attraverso un evento personalizzato. Ma con questo inconveniente in mente, il modello basato sugli eventi non ha senso per coloro che sono interessati alla velocità

 
fxsaber:

EventChartCustom è costoso.

E senzaChartFirst()?

 
Andrey Khatimlianskii:

E senza 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.

È più costoso inviare alla cartella di qualcun altro che alla propria.

 
A100:

Questo è un difetto significativo. Perché il modello di eventi MQL è incompleto - non c'è un evento nullo, cioè un evento che viene chiamato quando non ci sono altri eventi nella coda. Può essere emulato attraverso un evento personalizzato. Ma con questo inconveniente in mente, il modello basato sugli eventi non ha senso per coloro che sono interessati alla velocità

OnTimer permette di effettuare chiamate in background fino a 16 ms.
 
Renat Fatkhullin:
OnTimer permette di effettuare chiamate in background con una frequenza fino a 16 ms.

Corretto, cioè perdiamo almeno16ms a zero (possiamo tornare al più presto).E non potremmo perderne nessuno se ci fosse un evento nullo gratuito o eventi personalizzati gratuiti. E ora il modello di evento nel caso qui sotto funziona in modo limitato:

Forum sul trading, sistemi di trading automatico e test di strategie di trading

MT5 e la velocità in azione

fxsaber, 2020.10.06 01:27

Sei completamente fuori dal giro. Diciamo che avete bisogno di aprire due posizioni in OnTick. Il primo OrderSend è di pochi millisecondi. Dopo di che bisogna fare un'istantanea. E poi dovrebbe essere chiamato il secondo OrderSend.

Solo OnTick può essere eseguito per centinaia di millisecondi. E voi suggerite di scattare qualche OnTimer.

E OnTimer è stato liberato per altri scopi
 
E inoltre OnTimer non ci permette di essere sicuri di aver ricevuto un evento nullo perché sembra avere una priorità più alta degli altri gestori, che è probabilmente la principale controargomentazione.
 
fxsaber:

A proposito di Alert.

Per ora, si può dire che Alert non può essere usato in luoghi critici. L'asincronia è necessaria.

Allarme con una stampa, si può provare a sostituirla con una scrittura veloce da qualche parte.
Mi viene in mente sql nativo in memoria

 
Renat Fatkhullin:
Non stavo suggerendo un'istantanea, stavo rispondendo a una domanda diretta sul timer di millisecondi.

C'è, anche se nel tester attuale si attiva ancora con una frequenza di 1 secondo. Nel nuovo tester che stiamo scrivendo, cercheremo di cambiare questo.

Uso spesso il fatto che il Tester ha esattamente un timer di millisecondi, non di secondi. Prova.

// Демонстрация корректной работы миллисекундного таймера в Тестере.
#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();
}


Risultato.

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

Ci sono esattamente 29 ms tra l'apertura e la chiusura della posizione.