Les erreurs typiques et la façon de les traiter dans l'environnement de négociation - page 2

 

fxsaber:

La fonction qui indique la nécessité d'un emballage est marquée en rouge. Son problème est décrit ici. Certains se souviendront peut-être qu'il s'agit d'un ancien problème de réouverture de position, qui dans les temps anciens était résolu par le Sleep, en attendant que la position s'ouvre après l'OrderSend. Mais en fait, ce problème n'a rien à voir avec OrderSend. Vous devez être capable de lire correctement l'environnement commercial.

Le droit est un exemple simple.

La liste des ordres, comme la liste des positions, n'est pas mise à jour instantanément. Je pense qu'on ne peut pas se passer de Sleep-crutch.

Le plus correct est probablement OnTradeTransaction

 
Aleksey Lebedev:

La liste des ordres, comme la liste des positions, n'est pas mise à jour instantanément. imho, on ne peut pas se passer de Sleep-crutch.

Il serait probablement préférable d'utiliser OnTradeTransaction.

Si un problème se pose en attendant la mise à jour de l'environnement, comment Sleep peut-il aider ? Cela aidera ou pas.

Il faut donc adopter l'approche inverse : après avoir envoyé un ordre d'ouverture de position ou un ordre en attente, il faut attendre le résultat et ne plus envoyer d'autres ordres d'ouverture ou d'ordre. Nous avons donc besoin d'un drapeau que nous gérons nous-mêmes au lieu de faire confiance au sommeil qui ne fait que retarder l'exécution du programme mais ne vérifie pas le résultat d'une demande de transaction envoyée par le programme lui-même qui doit savoir ce qu'il faut faire ensuite - mettre un drapeau et travailler selon la logique des résultats en attente. Après avoir attendu le résultat, le drapeau est retiré.

 
Artyom Trishkin:

Question : Que se passera-t-il si, après avoir envoyé un ordre de transaction jusqu'au prochain tick, l'ordre de marché n'est pas placé par le serveur ?

Ce sera exactement la même chose que sur MT4 - s'il n'y a rien, cela ne sera pas compté.


Il peut y avoir plusieurs raisons pour un tel ordre commercial

  1. OrderSend ou OrderSendAsync de tiers - ne provenant pas du programme dans lequel nous lisons l'environnement commercial. Il peut même ne pas provenir du terminal dans lequel le programme est exécuté. Dans ce cas, rien ne peut être fait. Dans de telles situations, tout est identique à ce qui se passe dans MT4.
  2. OrderSend ou OrderSendAsync - sont lancés à partir du programme dans lequel l'environnement commercial est lu. Dans le cas de OrderSend, tout est clair, car OrderSend terminera son exécution avec un résultat clair. Dans le cas de OrderSendAsync nous pouvons faire deux choses - passer les données aux événements suivants selon le premier paradigme, ou faire OrdersAsyncWait() (je n'ai pas le code), comme cela est fait dans une simulation régulière de transfert de données asynchrones dans MT4 (implémentation de plusieurs threads).
Je devrais probablement dire quelques mots sur OrderSendAsync dans MT4. À n'importe quel stade de l'exécution du programme, il est possible de voir à quel point un thread commercial correspondant est occupé et ce qu'il fait exactement. En ce sens, l'asynchronie personnalisée dans MT4 nous offre beaucoup plus de possibilités que celle de MT5. Mais dans MT4, elle est implémentée en exécutant des "clients" sur chaque graphique, ce qui est coûteux. Dans MT5, il est possible d'écrire la même fonctionnalité et même sans beaucoup de graphiques - en exécutant le script sur un objet OBJ_CHART, mais il y aura toujours un léger retard. C'est-à-dire que OrderSendAsyncCustom sera légèrement plus lent que OrderSendAsync, mais il sera toujours beaucoup plus rapide que OrderSend + tous les avantages de l'implémentation personnalisée.
 
Aleksey Lebedev:

La liste des ordres, comme la liste des positions, n'est pas mise à jour instantanément. imho, on ne peut pas se passer de Sleep-crutch.

Probablement, il serait plus correct d'utiliser OnTradeTransaction

MqlTradeTransaction peut être nécessaire uniquement lors du choix du paradigme approprié pour travailler avec OrderSendAsync. Dans d'autres cas, OnTradeTransaction == OnTrade dans le sens et ne joue pas plus de rôle que OnTick ou OnTimer.


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

Les erreurs typiques et la façon de les corriger lorsqu'on travaille dans un environnement de négociation

fxsaber, 2018.02.19 22:36

Il existe deux paradigmes de travail avec l'environnement de trading, l'écriture d'EAs.

  1. Les entrées d'événements (OnTick, OnTimer, etc.) dépendent les unes des autres. Il y a des informations qui DOIVENT se trouver entre les événements (pas pour la vitesse, comme le cache, mais pour la convivialité). Par exemple, nous devons sauvegarder le résultat de OrderSendAsync et l'utiliser dans OnTradeTransaction. Les caches ne sont PAS des informations obligatoires et ne sont utilisés que pour accélérer le processus. C'est pourquoi nous ne les considérons pas tout de suite.
  2. Les entrées d'événements (OnTick, OnTimer, etc.) ne sont PAS dépendantes les unes des autres. Chaque entrée est faite à partir de zéro. En gros, c'est comme un script que vous exécutez vous-même à chaque événement.

Le surlignage indique que le même code commercial est exécuté dans chaque fonction On. Le code non commercial correspondant complète le reste.

 
fxsaber:

Ce sera exactement la même chose que sur MT4 - s'il n'y a rien, cela ne sera pas compté.

C'est-à-dire qu'au prochain tic, le programme envoie une nouvelle demande d'ouverture. Par conséquent, nous avons le même problème - des ouvertures multiples.

Le conseiller expert doit avoir la logique suivante :

  1. Nous recevons un signal pour ouvrir une position ou définir un ordre en attente.
  2. Vérifiez le nombre d'ordres/positions, s'il n'y a pas de signal pour ouvrir une nouvelle position - sortez (au point 1).
  3. Vérifier le drapeau d'attente de réponse du serveur :
    1. Le drapeau est levé - sortie (à l'étape 1)
    2. Drapeau omis - continuer
  4. Si le drapeau est omis, envoyez un ordre de transaction (le nombre de tentatives est limité) et vérifiez le code de retour.
    1. L'ordre a été exécuté - activez le drapeau d'attente.
    2. Ordre échoué - appelez la fonction de correction de l'ordre et passez au point 4
  5. Le drapeau d'attente est levé - vérifiez le changement d'environnement commercial.
    1. L'environnement commercial n'a pas changé - quittez (à l'étape 1).
    2. L'environnement a changé - un ordre en attente est placé ou une position est ouverte - supprimez le drapeau d'attente et sortez (à l'étape 1).
 
Artyom Trishkin:

C'est-à-dire qu'au prochain tick, le logiciel envoie une nouvelle demande d'ouverture. Par conséquent, nous avons le même problème - des ouvertures multiples.

Il serait bon de lire l'intégralité du message.

L'EE doit avoir la logique suivante :

  1. Nous avons reçu un signal pour ouvrir une position ou définir un ordre en suspens.
  2. Vérifiez le nombre d'ordres/positions, s'il n'y a pas de signal pour ouvrir une nouvelle position - sortez (au point 1).
  3. Vérifier le drapeau d'attente de réponse du serveur:
    1. Le drapeau est levé - sortie (à l'étape 1)
    2. Drapeau omis - continuer
  4. Si le drapeau est omis, envoyez un ordre de transaction (le nombre de tentatives est limité) et vérifiez le code de retour.
    1. L'ordre a été exécuté - activez le drapeau d'attente.
    2. Ordre non exécuté - appeler la fonction corriger l'ordre commercial et passer au point 4
  5. Le drapeau d'attente est levé - vérifiez le changement d'environnement commercial.
    1. L'environnement commercial n'a pas changé - quittez (à l'étape 1).
    2. L'environnement a changé - un ordre en attente est placé ou une position est ouverte - supprimez le drapeau d'attente et sortez (à l'étape 1).

L'indicateur d'attente n'est disponible que pour le deuxième cas et OrderSendAsync. Pour OrderSend, le drapeau d'attente n'est pas du tout nécessaire. OrderSendAsync sans drapeau d'attente est OrdersAsyncWait().

Vous pouvez vérifier toute théorie dans la pratique.

Guidé par des résultats pratiques.
 
fxsaber:

Il est bon de lire le post dans son intégralité.

Le drapeau d'attente n'est possible que pour le deuxième cas et OrderSendAsync. Pour OrderSend, le drapeau d'attente n'est pas du tout nécessaire. OrderSendAsync sans drapeau d'attente est OrdersAsyncWait().

Toute théorie peut être testée en pratique

Je suis guidé par les résultats pratiques.

Eh bien, j'ai écrit pour le mode asynchrone. Avec le mode synchrone, vous n'avez pas besoin d'attendre - le résultat est déjà là dans la réponse à la requête.

 
Artyom Trishkin:

J'ai écrit pour le mode asynchrone.

Une réponse détaillée a été donnée dès le début.

 
fxsaber:

Une réponse étendue a été donnée dès le début.

Je dois l'avoir mal lu :)

Je n'ai vu aucune étape pour contourner l'erreur de découverte multiple. Seulement des "paradigmes" généraux ;)

C'est pourquoi j'ai décrit la logique approximative, qui est redondante - le drapeau est vérifié dans une fonction (wrapper) qui ouvre des positions / définit des ordres en attente. Ou peut-être aussi dans la fonction de suivi du signal.

Vous devez réfléchir à la meilleure façon de procéder.

 
Artyom Trishkin:

le drapeau est vérifié dans la fonction (wrapper) d'ouverture des positions/placement des ordres en attente. Ou peut-être aussi dans la fonction de suivi du signal.

Je préfère de loin la solution via OrdersAsyncWait(), lorsque la sortie de la fonction On est toujours effectuée sans suspendre l'état. La prochaine lecture de l'environnement commercial avec une ardoise propre est alors aussi pertinente que possible.

L'utilisation de OrderSendAsync devrait toujours être appropriée. La seule situation où il serait approprié d'envoyer plusieurs (> 1) ordres de transaction, indépendants les uns des autres, sur un seul signal. Par conséquent, le truc OrderSendAsync n'a jamais de sens dans tous les autres cas.


SZZY Il y a un sujet distinct où OrderSendAsync est très pertinent - multi-conseillers : plusieurs TS indépendants dans un conseiller expert. L'OrderSend y est rarement adapté et même l'OrderAsyncWait( const string Symb) n'est pas bon puisque aucun Sleep n'est en principe autorisé.

Raison: