Erreurs, bugs, questions - page 2963

 
Nikolai Semko:

Pourquoi auraient-ils besoin de se synchroniser ? user32.dll le fera pour eux.

Essayez de l'écrire. Peut-être que vous ne comprenez pas bien la tâche.

Pourquoi n'aimez-vous pas les ressources ? Je pense que c'est optimal dans les limites d'un seul terminal. La variante que j'ai suggérée en utilisant user32.dll (j'ai mis en œuvre cette variante il y a environ 10 ans, lorsque je m'adonnais à l'arbitrage dans ma jeunesse) a un temps d'accès et d'analyse d'environ 50 microsecondes (je pense qu'il peut être accéléré de 1,5 à 2 fois). Est-il plus lent avec les ressources ?

La lecture prend 100 microsecondes sur une machine domestique dans des conditions idéales. Un conseiller expert sur un seul tick peut provoquer la lecture d'une centaine de fois. C'est lent.

Dans des conditions idéales, GlobalVariableGet sera exécuté en 10 microsecondes. Mais ce n'est pas un indicateur, car c'est un frein horrible dans des conditions de combat nouvelles pour moi.

 
fxsaber:

C'est HistoryTicks - la capture de tous les ticks pour les EAs. Par conséquent, EventChartCustom n'est pas adapté, il possède sa propre file d'attente. Il en va de même pour le tampon.

Je l'ai fait fonctionner sur EventChartCustom. 99,8% des ticks sont reçus dans un délai de 0,15 ms.

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

EventChartCustom => l'indicateur est trop lent

Andrey Khatimlianskii, 2019.12.12 09:27

Voici les statistiques pour 9 heures de travail avec 5 symboles :

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

Le conseiller expert était sur GBPUSD, donc le OnTick natif fonctionnait pour lui.

Il n'y a pas eu d'erreur "l'indicateur est trop lent".


En revanche, le pourcentage de ticks manqués et la latence moyenne sont beaucoup plus élevés sur le VPS de MQ (je posterai les statistiques plus tard).
Et il y a beaucoup d'erreurs "l'indicateur est trop lent".

Je ne comprends pas la nature du débordement de la file d'attente, car le conseiller expert traite immédiatement les événements accumulés (il ne fait que revenir).
Est-ce que quelqu'un d'autre le traite ?


 
Andrey Khatimlianskii:

Je l'ai fait fonctionner surEventChartCustom. 99,8% des ticks sont reçus dans un délai de 0,15 ms.

J'envoie les ticks de l'indicateur via ceci : sparam contient MqlTick, lparam - numéro de tick.

Le conseiller expert dans OnChartEvent capte ces ticks. Et il doit comprendre si le tick actuel est le plus actuel ou non ? C'est-à-dire, y a-t-il une file d'attente de ticks ou est-elle vide ?

Pour cela, il lit le numéro (la tâche est de lire ce numéro) du dernier tick envoyé par l'indicateur. Si le tick a le même numéro - la file d'attente est vide, et il est possible de commencer à travailler avec les ticks.


Et pendant l'opération de OnTick, après OrderSend il est nécessaire de vérifier si l'indicateur a envoyé plus de ticks. Pour cela, nous devons à nouveau lire le nombre à partir de l'indicateur. Et il peut y avoir plus d'une centaine de ces vérifications pendant un OnTick. C'est pourquoi nous devons lire rapidement.

 

Dans un terminal, le winapi le plus rapide sera l'allocation de mémoire (globale au sein d'un processus) et les fonctions verrouillées comme https://docs.microsoft.com/ru-ru/windows/win32/api/winnt/nf-winnt-interlockedexchange.

Celles-ci sont non bloquantes, atomiques et essentiellement exécutées en quelques instructions 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:

Dans un terminal, le winapi le plus rapide sera l'allocation de mémoire (globale au sein d'un processus) et les fonctions verrouillées comme https://docs.microsoft.com/ru-ru/windows/win32/api/winnt/nf-winnt-interlockedexchange.

Celles-ci sont non bloquantes, atomiques et essentiellement exécutées en quelques instructions asm.

Pas sans un exemple.

 
fxsaber:

Pour ce faire, il lit le numéro (la tâche est de lire ce numéro) du dernier tick envoyé par l'indicateur. Si le tick reçu a le même numéro - la file d'attente est vide, et vous pouvez commencer à travailler avec un paquet de ticks.

Et pendant l'opération de OnTick, après OrderSend il est nécessaire de vérifier si l'indicateur a envoyé plus de ticks. Pour ce faire, nous devons à nouveau lire le numéro de l'indicateur. Et il peut y avoir plus d'une centaine de ces vérifications pendant un OnTick. Par conséquent, nous devons le lire rapidement.

Initialisation.

1. Dans le premier thread (très probablement, le thread d'écriture), allouez de la mémoire de quelque manière que ce soit pour la variable de la taille requise.

2. Dans les threads nécessaires (threads de lecture), envoyez l'adresse de cette mémoire.

Travail de base.

3. Le fil d'écriture initie InterlockedExchange ou InterlockedExchange64 selon la taille de la variable pour y écrire.

4. Le fil de lecture tire par exemple InterlockedCompareExchange pour lire.

Achèvement.

5. Libérer la mémoire allouée, de préférence dans le même thread qui l'a allouée.


Si nécessaire, elle peut être répétée pour la création de plusieurs compteurs. En revanche, vous aurez besoin de la connexion WinAPI. Des caractéristiques de la mémoire allouée l'adresse devrait être alignée, mais par défaut elle l'est généralement.


Le travail se fera au sein d'un processus, la mémoire est partagée pour les threads d'un processus. Si nécessaire, il existe d'autres fonctions verrouillées comme InterlockedDecrement, InterlockedAdd, etc.

Les fonctions sont non bloquantes, n'attendent rien, automates, elles sont exécutées en quelques instructions asm.


P.S. Autant que je me souvienne, les opérations régulières de lecture et d'écriture via mov en assembleur sont de toute façon atomiques. Et si le compilateur ne fait pas de dégâts (il ne devrait pas en théorie), nous pouvons essayer de lire et d'écrire dans la variable dans la mémoire allouée et ce sera atomique.

Si elle convient à la tâche, il est peu probable qu'elle soit plus rapide en un seul processus. Pour l'interprocessus, le plus rapide sera similaire, mais avec la mémoire partagée, dans ce cas vous ne pouvez pas vous passer de WinAPI.

 
fxsaber:

Ce système ne semble pas fonctionner. Montrez un exemple élémentaire, s'il vous plaît.

Pourquoi pas ? C'est comme ça que je le vois. Le principe du getter setter.
Obtenir la valeur d'une variable cachée par le biais de la fonction.
Si vous passez la structure MqlTick, définissez votre structure avec les champs définis comme MqlTick, et ajoutez votre champ compteur à la structure.
Et renvoyer cette structure à partir de la fonction d'exportation.
Un exemple élémentaire pour l'indicateur. Ne faites pas attention à l'exemple dans le 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;  //свой счётчик  
  
}
//+------------------------------------------------------------------+

Dans Expert Advisor, vous appelez GetTickStruct et obtenez la structure entière avec votre compteur.

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

Dans Expert Advisor vous appelez GetTickStruct, vous obtenez la structure entière, avec son compteur.

Veuillez écrire un transfert élémentaire de numéros de l'indicateur à l'EA.

 
fxsaber:

Un transfert de nombre élémentaire de l'indicateur à l'EA, veuillez écrire.

Remplacer la structure par une variable ))

 
Roman:

Remplacer la structure par une seule variable ;))

Non transférable.