Errori, bug, domande - pagina 2963

 
fxsaber:

Indicatore1 e Indicatore2 devono poi essere sincronizzati in qualche modo in modo che entrambi i numeri possano essere scritti sulla stessa linea comune.

Questa è una soluzione molto complessa.

Perché dovrebbero essere sincronizzati? user32.dll lo farà per loro.
La cosa principale è numerarli correttamente, in modo che ogni numero abbia un numero unico e questo numero sarà un indice dell'array di dati.
Questo può, come ultima risorsa, essere fatto manualmente. Oppure potete farlo automaticamente. A proposito, recentemente ho pubblicato qualcosa di simile in KB(Indicator Cases).
Cosa c'è che non va nelle risorse? Penso che sia ottimale entro i confini di un terminale. La variante che suggerisco, usando user32.dll (ho implementato questa variante circa 10 anni fa, quando ero giovane e mi dilettavo nell'arbitraggio), il tempo di accesso e il parsing dei dati sono circa 50 microsecondi (penso che possa essere accelerato in 1,5-2 volte). È più lento con le risorse?

 
Nikolai Semko:

Perché dovrebbero avere bisogno di sincronizzarsi? user32.dll lo farà per loro.

Prova a scriverlo. Forse non si capisce bene il compito.

Perché non ti piacciono le risorse? Penso che sia ottimale entro i confini di un singolo terminale. La variante che ho suggerito usando user32.dll (ho implementato questa variante circa 10 anni fa, quando mi dilettavo nell'arbitraggio quando ero giovane) ha un tempo di accesso e parsing di circa 50 microsecondi (penso che possa essere accelerato 1,5-2 volte). È più lento con le risorse?

Ci vogliono 100 microsecondi per leggere su una macchina domestica in condizioni ideali. Un Expert Advisor su un singolo tick può causare la lettura di cento volte. È lento.

In condizioni ideali, GlobalVariableGet sarà eseguito in 10 microsecondi. Ma questo non è un indicatore, perché è un freno orribile in condizioni di combattimento nuove per me.

 
fxsaber:

Questo è HistoryTicks - che cattura tutti i tick per gli EA. Pertanto, EventChartCustom non è adatto, ha la sua propria coda. È lo stesso con il buffer.

Lo faccio funzionare su EventChartCustom. Il 99,8% dei tic vengono ricevuti entro 0,15 ms.

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

EventChartCustom => l'indicatore è troppo lento

Andrey Khatimlianskii, 2019.12.12 09:27

Ecco le statistiche per 9 ore di lavoro con 5 simboli:

Windows 8.1 (build 9600) x64, IE 11, UAC, Intel Core i5-3570  @ 3.40 GHz, Memory: 6979 / 16346 Mb, Disk: 341 / 499 Gb, GMT+2
[USDCHF]: 22784 of 22833 (99.8 %) ticks were processed (0.14 ms delay in average), 49 (0.2 %) ticks were skipped (103.4 ms delay in average)
[EURUSD]: 22944 of 22974 (99.9 %) ticks were processed (0.16 ms delay in average), 30 (0.1 %) ticks were skipped (115.6 ms delay in average)
[USDCAD]: 15331 of 15347 (99.9 %) ticks were processed (0.13 ms delay in average), 16 (0.1 %) ticks were skipped (104.6 ms delay in average)
[EURCHF]: 22516 of 22571 (99.8 %) ticks were processed (0.13 ms delay in average), 55 (0.2 %) ticks were skipped (127.8 ms delay in average)
[EURAUD]: 66842 of 66924 (99.9 %) ticks were processed (0.13 ms delay in average), 82 (0.1 %) ticks were skipped (117.8 ms delay in average)
[GBPUSD]: 41393 of 41393 (100.0 %) ticks were processed (0.00 ms delay in average)
Total trade requests time: 4.280 sec

L'Expert Advisor era su GBPUSD, quindi l'OnTick nativo ha funzionato per esso.

Non ci sono stati errori "l'indicatore è troppo lento".


Al contrario, la percentuale di tick mancati e la latenza media è molto più alta sul VPS di MQ (posterò le statistiche più tardi).
E ci sono un sacco di errori "l'indicatore è troppo lento".

Non capisco la natura dell'overflow della coda, perché l'Expert Advisor elabora gli eventi accumulati immediatamente (ritorna semplicemente).
Qualcun altro lo elabora?


 
Andrey Khatimlianskii:

Lo faccio funzionare suEventChartCustom. Il 99,8% dei tic vengono ricevuti entro 0,15 ms.

Mando i tick dall'indicatore tramite questo: sparam contiene MqlTick, lparam - numero di tick.

L'Expert Advisor in OnChartEvent cattura questi tick. E deve capire se il tick attuale è quello più attuale o no? Cioè, c'è una coda di zecche o è vuota?

Per questo, legge il numero (il compito è leggere questo numero) dell'ultimo tick inviato dall'indicatore. Se il tick ha lo stesso numero - la coda è vuota, ed è possibile iniziare a lavorare con i tick.


E durante il funzionamento di OnTick, dopo OrderSend è necessario controllare se l'indicatore ha inviato altri tick. Per questo, abbiamo di nuovo bisogno di leggere il numero dall'indicatore. E ci possono essere più di cento di questi controlli durante un OnTick. Ecco perché dobbiamo leggere velocemente.

 

Entro 1 terminale, la winapi più veloce sarà l'allocazione della memoria (globale all'interno di un processo) e le funzioni interbloccate come https://docs.microsoft.com/ru-ru/windows/win32/api/winnt/nf-winnt-interlockedexchange.

Questi sono non bloccanti, atomici ed essenzialmente eseguiti in poche istruzioni asm.

InterlockedExchange function (winnt.h) - Win32 apps
InterlockedExchange function (winnt.h) - Win32 apps
  • 2018.12.05
  • lastnameholiu
  • docs.microsoft.com
Sets a 32-bit variable to the specified value as an atomic operation.
 
traveller00:

Entro 1 terminale, la winapi più veloce sarà l'allocazione della memoria (globale all'interno di un processo) e le funzioni interbloccate come https://docs.microsoft.com/ru-ru/windows/win32/api/winnt/nf-winnt-interlockedexchange.

Questi sono non bloccanti, atomici ed essenzialmente eseguiti in poche istruzioni asm.

Non senza un esempio.

 
fxsaber:

Per farlo, legge il numero (il compito è leggere questo numero) dell'ultimo tick inviato dall'indicatore. Se il tick ricevuto ha lo stesso numero - la coda è vuota, e si può iniziare a lavorare con un pacchetto di tick.

E durante il funzionamento di OnTick, dopo OrderSend è necessario controllare se l'indicatore ha inviato altri tick. Per questo, abbiamo di nuovo bisogno di leggere il numero dall'indicatore. E ci possono essere più di cento di questi controlli durante un OnTick. Pertanto, dobbiamo leggerlo rapidamente.

Inizializzazione.

1. Nel primo thread (molto probabilmente, il thread di scrittura), allocate la memoria in qualsiasi modo per la variabile della dimensione richiesta.

2. Nei thread richiesti (thread di lettura), inviate l'indirizzo di questa memoria.

Lavoro di base.

3. Il thread di scrittura avvia InterlockedExchange o InterlockedExchange64 a seconda della dimensione della variabile per scriverci.

4. Il thread di lettura tira ad esempio InterlockedCompareExchange per leggere.

Completamento.

5. Rilasciare la memoria allocata, preferibilmente nello stesso thread che l'ha allocata.


Se necessario può essere ripetuto per la creazione di diversi contatori. Il lato negativo è che avrete bisogno della connessione WinAPI. Delle caratteristiche dell'indirizzo della memoria allocata dovrebbe essere allineato, ma per impostazione predefinita di solito lo è.


Il lavoro sarà all'interno di 1 processo, la memoria è condivisa per i thread di 1 processo. Se necessario, ci sono altre funzioni interbloccate come InterlockedDecrement, InterlockedAdd, ecc.

Le funzioni sono non bloccanti, non aspettano nulla, automi, vengono eseguite in poche istruzioni asm.


P.S. Per quanto ricordo, le normali operazioni di lettura e scrittura via mov in assembler sono comunque atomiche. E se il compilatore non fa casino (in teoria non dovrebbe), possiamo provare a leggere e scrivere alla variabile nella memoria allocata e sarà atomico.

Se è adatto al compito, è improbabile che sia più veloce in 1 processo. Per l'interprocesso il più veloce sarà simile, ma con la memoria condivisa, in questo caso non si può fare a meno di WinAPI.

 
fxsaber:

Questo schema non sembra funzionare. Mostra un esempio elementare, per favore.

Perché non è fattibile? Solo per come la vedo io. Il principio getter setter.
Ottenere il valore di una variabile nascosta attraverso una funzione.
Se passate la struttura MqlTick, definite la vostra struttura con i campi impostati come MqlTick, e aggiungete il vostro campo contatore alla struttura.
E restituire questa struttura dalla funzione di esportazione.
Un esempio elementare per l'indicatore. Non prestate attenzione all'esempio nello script.

struct myMqlTick 
{ 
   datetime     time;          // Время последнего обновления цен 
   double       bid;           // Текущая цена Bid 
   double       ask;           // Текущая цена Ask 
   double       last;          // Текущая цена последней сделки (Last) 
   ulong        volume;        // Объем для текущей цены Last 
   ulong        count;  //Свой счётчик
   
}myStruct;

//--------------------------------------------------
myMqlTick GetTickStruct() export
{
   
   return(myStruct);
}

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   myStruct.time   = 0.0;
   myStruct.bid    = 0.0;
   myStruct.ask    = 0.0;
   myStruct.last   = 0.0;
   myStruct.volume = 0;
   myStruct.count  = 1;  //свой счётчик  
  
}
//+------------------------------------------------------------------+

In Expert Advisor, si chiama GetTickStruct e si ottiene l'intera struttura con il contatore.

Документация по MQL5: Константы, перечисления и структуры / Структуры данных / Структура для получения текущих цен
Документация по MQL5: Константы, перечисления и структуры / Структуры данных / Структура для получения текущих цен
  • www.mql5.com
Структура для получения текущих цен - Структуры данных - Константы, перечисления и структуры - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Roman:

In Expert Advisor si chiama GetTickStruct, si ottiene l'intera struttura, con il suo contatore.

Si prega di scrivere un trasferimento numerico elementare da indicatore a EA.

 
fxsaber:

Un trasferimento di numeri elementari da indicatore a EA, si prega di scrivere.

Sostituire la struttura con una variabile ))