La grande et terrible MT4 pour toujours (ou comment organiser une transition) - page 13

 
JRandomTrader:

Voici un extrait de la documentation :

"l'ordre dans lequel ces transactions arrivent dans le terminal n'est pas garanti. Vous ne pouvez donc pas baser votre algorithme de négociation sur l'attente de l'arrivée de certaines transactions après l'arrivée d'autres. " https://www.mql5.com/ru/docs/event_handlers/ontradetransaction

Et par expérience, les transactions TRADE_TRANSACTION_ORDER_DELETE, TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_HISTORY_ADD peuvent arriver dans n'importe quel ordre.

Nous avons donc des situations où il n'y a pas encore d'accord ou d'ordre dans l'histoire, mais où l'ordre existe déjà. Ou vice versa, l'ordre est toujours là, mais la transaction a déjà été exécutée. Mais la situation où l'ordre est présent dans l'actif, ainsi que dans l'historique, est difficilement envisageable.

Je ne capte pas les événements, je regarde l'image complète sur un nouveau tic.


JRandomTrader:

En fait, c'est la raison pour laquelle j'ai refusé d'utiliser la classe CTrade - elle marche sur tous ces écueils.

J'ai une solution : chaque EA conserve une liste de ses ordres et surveille leur état. Cela inclut les états "non standard" - "commande envoyée mais pas encore présente dans les commandes actives" (c'est là qu'ils peuvent faire double emploi), "commande supprimée mais pas présente dans l'historique". Cela facilite également le travail simultané sur le même symbole lors de la mise au filet.

Jusqu'à récemment, j'utilisais une béquille universelle qui vérifiait les commandes manquantes. Mais à un moment donné, il a commencé à échouer.

J'ai ajouté une béquille personnelle supplémentaire au conseiller expert qui surveille désormais ses propres ordres séparément.

C'est beaucoup de béquilles...

 
Andrey Khatimlianskii:

C'est beaucoup de béquilles...

Étudier la question. Je suis même tombé sur ceci : OrderSend market order true, puis PositionsTotal= 0, OrdersTotal = 0, tableaux historiques inchangés.

Il semble avoir réussi à écrire IsSynchronized(). Le code est un peu lourd. Je n'ai pas encore décidé sous quelle forme le poster.

 
// Демонстрация открытия дубля позиции в MT5.

#include <Trade\Trade.mqh>

void OnStart()
{
  CTrade Trade;
  
  while (!IsStopped() && (PositionsTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (PositionsTotal() == 1)
      Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
    else if (!OrdersTotal())
      Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
}

Exécutez ce code sur un compte de démonstration vide et voyez si deux positions s'ouvrent après quelques secondes.


La même logique sur MT4 ressemble à ceci.

void OnStart()
{
  while (!IsStopped() && (OrdersTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0) // Если есть позиция - закрываем.
    else
      OrderSend(_Symbol, OP_BUY, 0.01, Ask, 0, 0, 0) // Если нет позиции и ордера - открываем позицию.
}

Il est clair qu'un tel code sur MT4 ne provoquera pas d'inversion de position. Mais pas sur MT5.

 
fxsaber:

Exécutez ce code sur un compte de démonstration vide et voyez si deux positions s'ouvrent après quelques secondes.


La même logique sur MT4 ressemble à ceci.

Il est clair qu'un tel code sur MT4 ne provoquera pas d'inversion de position. Mais pas sur MT5.

Enfin, vous venez de le découvrir ? Ce problème est aussi vieux que le terminal lui-même. Mais finalement les utilisateurs de terminaux l'ont remarqué... après une décennie.

Lorsque vous effectuez vous-même des actions commerciales, le problème peut être résolu de manière simple : insérer Sleep() pendant une seconde après l'exécution de l'action. Mais lorsque l'EA utilise le stoploss/stackprofit et la clôture du marché, il y a un risque de rencontrer ce problème, et dans ce cas il n'y a pas de solution.

 
Dmitry Fedoseev:

Enfin ! Vous venez de le découvrir ? Ce problème est aussi vieux que le terminal lui-même. Mais les utilisateurs de terminaux l'ont finalement remarqué... après une décennie.

Le problème est discuté depuis longtemps. Presque tout le monde l'a rencontré. C'est la première fois qu'un code aussi régulier le reproduit.

Lorsque vous effectuez vous-même des actions commerciales, vous pouvez résoudre le problème de manière simple : insérez Sleep() pendant une seconde après l'exécution de l'action. Mais lorsque le Stop Loss/StackProfit et la clôture du marché sont utilisés dans un EA, il y a un risque de rencontrer le problème, et il n'y a pas de solution dans ce cas.

La solution a été trouvée.

 
fxsaber:

Exécutez ce code sur un compte de démonstration vide et voyez si deux positions s'ouvrent après quelques secondes.

Étrange. Il ne se reproduit pas. Vérifié sur la démo de MQ, build 2900, EURUSD, zéro spread. J'ai attendu environ cinq minutes.

Peut-être dois-je utiliser un serveur spécifique d'un vrai DC/broker et non le serveur MQ ?

 
Ihor Herasko:

Étrange. Il ne se reproduit pas. Vérifié sur la démo de MQ, build 2900, EURUSD, zéro spread. J'ai attendu environ cinq minutes.

Peut-être dois-je utiliser un serveur spécifique d'un vrai DC/broker et non le serveur MQ ?

ForexTimeFXTM-Demo01

 
fxsaber:

ForexTimeFXTM-Demo01

Oui, maintenant le script s'arrête. Mais il reste encore un poste à pourvoir. Je suppose que le second a le temps de fermer ?

 
Ihor Herasko:

Oui, maintenant le script s'arrête. Mais il reste encore un poste à pourvoir. Le second doit avoir le temps de se fermer ?

Il m'en reste toujours deux. S'il en reste un, c'est encore plus un bug :

  1. PositionsTotal = 1 - envoie un ordre de clôture.
  2. Alors PositionsTotal = 2 et l'ordre du point 1 est clôturé.
 
fxsaber:

Il m'en reste toujours deux. S'il en reste un, c'est un bug encore plus grand :

  1. PositionsTotal = 1 - envoie un ordre de clôture.
  2. Alors PositionsTotal = 2 et l'ordre du point 1 est clôturé.

Oui, c'est ce que je veux dire. Il s'avère que le script parvient à fermer une des positions alors qu'il y en a en fait deux, mais PositionsTotal() renvoie 1. Et ensuite, après la fermeture, la condition de la fin de la boucle est remplie, c'est-à-dire que PositionsTotal() renvoie 2.

Raison: