- www.mql5.com
if (prev_calculated) EventChartCustom(Chart, 0, Index, 0, NULL);È possibile che i tick vengano saltati se l'evento non viene inserito nella coda. A volte capita (soprattutto su un VPS o su un computer lento).
Purtroppo, anche i semplici expert advisor dotati solo della funzione OnTick saltano i tick. Per gli expert advisor di trading si utilizzano le funzioni CopyTicks e altri accorgimenti per garantire il funzionamento senza saltare i tick.
Questa libreria garantisce che i tick non vengano saltati solo nel Tester. Funziona esattamente come con OnTick.
/* // https://www.mql5.com/ru/blogs/post/755348 #define VIRTUAL_TESTER_MULTI // Avvio nell'ambiente di trading virtuale OnTickMulti #define VIRTUAL_LIMITS_TP_SLIPPAGE // Gli ordini stop e i TP vengono eseguiti al primo prezzo di accettazione - slippage positivo #define VIRTUAL_CLOSEALL_BYEND // Chiude forzatamente tutti gli ordini al termine del test // #define VIRTUAL_ALTERNATIVE // Velocità di calcolo alternativa */ #include <MT4Orders.mqh> // https://www.mql5.com/it/code/16006 #include <fxsaber\OnTickMulti\OnTickMulti.mqh> // https://www.mql5.com/it/code/47647 /* #define REPORT_TESTER // I report verranno salvati automaticamente nel tester #define REPORT_BROWSER // Creazione di un report con l'avvio del browser - richiede l'autorizzazione della DLL. #include <Report.mqh> // https://www.mql5.com/it/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 multicarattere. 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); } }
Impostazioni del Tester.
Accelerazione.
È possibile velocizzare il codice rimuovendo i commenti da alcune righe all'inizio.
| Configurazione | Risultato |
|---|---|
| Senza Virtual.mqh. | passaggio più breve 0:00:13.184, passaggio più lungo 0:00:15.031, passaggio medio 0:00:13.633 |
| Con Virtual.mqh, inVirtualTester = false. | passaggio più breve 0:00:14.735, passaggio più lungo 0:00:16.384, passaggio medio 0:00:15.081 |
| Con Virtual.mqh, inVirtualTester = true. | passaggio più breve 0:00:05.872, passaggio più lungo 0:00:05.964, passaggio medio 0:00:05.919 |
| Con Virtual.mqh, inVirtualTester = true + VIRTUAL_ALTERNATIVE. | passaggio più breve 0:00:06.172, passaggio più lungo 0:00:07.791, passaggio medio 0:00:06.524 |
Il sistema è estremamente semplice (0-2 posizioni aperte per ogni strumento con SL/TP fissi, senza ordini pendenti), pertanto in questa configurazione è possibile ottenere un'accelerazione solo di 2,5 volte.
TickValue+Swap+Commission.
I test sopra riportati sono stati effettuati in modalità «per pip» (vedi screenshot delle impostazioni), per evitare di ricalcolare il TickValue ad ogni tick, collegando altri simboli a tale scopo. In questa modalità i risultati sono identici.
Se serve la massima velocità, allora bisogna utilizzare questa soluzione.
- 2023.12.25
- www.mql5.com
Forum sul trading, sui sistemi di trading automatici e sul test delle strategie di trading
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); } }
| Configurazione | Risultato |
|---|---|
| Senza Virtual.mqh. | passaggio più breve 0:00:13.184, passaggio più lungo 0:00:15.031, passaggio medio 0:00:13.633 |
Ho evidenziato sopra nel codice un modo semplice per velocizzare un expert advisor multivaluta senza alcuna libreria Virtual.
| Configurazione | Risultato |
|---|---|
| Senza Virtual.mqh +MagicNumberOrderSymbol | passaggio più breve 0:00:08.608, passaggio più lungo 0:00:10.236, passaggio medio 0:00:08.942 |
Un'accelerazione gratuita di 1,5 volte!
Ho verificato il rallentamento del Tester nel passaggio dalla modalità monocarattere a quella multicarattere. Non l'ho fatto in modo del tutto perfetto: il sistema automatico è un semplice prototipo.
Expert Advisor monosimbolo.
#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++; }
| Configurazione (OnTick) | Durata (mcs) | Numero di tick | Prestazioni (tick/mcs) |
|---|---|---|---|
| EURUSD | 1079331 | 9927153 | 9,19 |
| GBPUSD | 1229032 | 11309740 | 9,20 |
| USDJPY | 1307322 | 11986756 | 9,16 |
| USDCHF | 1121541 | 10359511 | 9,23 |
| AUDUSD | 1175578 | 10758136 | 9,15 |
È chiaramente visibile che la produttività del Tester, espressa in numero di tick per unità di tempo, non dipende dal simbolo (modalità in pip).
Expert Advisor multisimbolo.
#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/it/code/47647 const ulong StartTime = GetMicrosecondCount(); int AmountTicks = 0; double OnTester() { return((double)(GetMicrosecondCount() - StartTime)); // return(AmountTicks); // return((double)AmountTicks / (GetMicrosecondCount() - StartTime)); } // OnTick multicarattere. void OnTickMulti( const string &Symb, const int &Index ) { AmountTicks++; }
| Configurazione (OnTickMulti) | Durata (OnTickMulti) | Durata (OnTick) | Numero di tick | Performance (OnTickMulti) | Rendimento (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 | 33223649 | 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 produttività dipende in misura minima dal numero di caratteri, ma è comunque tre volte inferiore.
Conclusione.
Se il vostro expert advisor multivaluta è costituito da un insieme eterogeneo di sub-TS monovalutari indipendenti, sarà (come minimo) tre volte più veloce ottimizzare ciascuna delle sub-TS (per poi unirle tramite Validate in un unico passaggio) separatamente, piuttosto che ottimizzarle tutte insieme in un unico sistema multivaluta.
- www.mql5.com
// OnTick multisimbolo. void OnTickMulti( const string &Symb, const u int &Index )
Salve,
Sembra che nelle ultime build (5200+) il codice non venga più compilato:
#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // OnTick per più simboli. int TicksCounter[]; // Contatore dei tick ricevuti per ciascun carattere specificato. void OnInit() { // Inizializziamo il contatore dei tick ricevuti. ArrayResize(TicksCounter, ArraySize(OnTickMulti.Symbols)); ArrayInitialize(TicksCounter, 0); } double OnTester() { // Visualizziamo il numero di tick ricevuti per ogni carattere specificato. for (uint i = ArraySize(TicksCounter); (bool)i--;) Print(OnTickMulti.Symbols[i] + " - " + (string)TicksCounter[i] + " ticks."); ArrayPrint(OnTickMulti.Symbols); // Elenco dei simboli OnTickMulti. return(0); } // OnTick per più simboli. void OnTickMulti( const string &Symb, const uint &Index ) { TicksCounter[Index]++; // È stato incrementato il contatore dei tick ricevuti per il simbolo specificato. }
La libreria è stata aggiornata in base alle modifichedi MQL5_b5200+.
- 2025.07.31
- www.mql5.com
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso


SuTickMulti:
Multisimbolo OnTick.
Author: fxsaber