MT5 et la vitesse en action - page 23

 
Renat Fatkhullin:

Au cas où quelqu'un ne comprendrait pas, c'est la bibliothèque fxsaber qui provoque le freinage lorsqu'elle est appliquée dans le code de quelqu'un d'autre.

Au lieu de le signaler explicitement, il a commencé à jouer le jeu des exemples suicidaires de freinage et de glissement de plate-forme. Et lorsqu'il a eu l'occasion de s'attaquer à la vraie cause et d'aplanir le problème, il ne l'a pas saisie.

Pour des raisons d'optimisation locale, il empoisonnait le cache de l'historique de l'application principale.

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

MT5 et la vitesse en action

fxsaber, 2020.09.02 00:02

Il y avait un code MQL5 propre et reproductible par beaucoup. La chronologie du fil de discussion étudie d'abord, au lieu de jouer à la théorie du complot, que quelqu'un a tellement besoin de vous qu'il est prêt à passer son temps sur vous pour faire du mudsling.

Tu fais un excellent travail en tant que dinde. Il n'y a pas eu de discussion sur les bibliothèques ici spécifiquement dans le fil de discussion car ce n'est pas constructif.

Le fait est que si quelqu'un s'aventure à utiliser des bibliothèques partagées où le paramètre from-input ne coïncide pas, il sera freiné. Il n'en est fait mention nulle part dans la documentation. Au moins quelque chose sur ce sujet a été extrait de vous avec des pinces. Et quand c'était fait, ils ont commencé à vous accuser de tricher.


Cette fonctionnalité de MQL devrait être écrite dans la branche Documentation et dans la branche Fonctionnalités. Exécutez les scripts MQL5 propres de cette branche sur les builds correspondant aux dates de leur création. Apparemment, tant de corrections ont été faites à l'aveuglette, juste au cas où.

 
fxsaber:

Vous faites un excellent travail en tant qu'indépendant. Aucune bibliothèque n'a été spécifiquement mentionnée ici dans le fil de discussion, car ce n'est pas constructif.

Parce que vous avez fait de votre mieux pour ne pas parler de vos bibliothèques. En présence de ces bibliothèques. Avec l'opposition constante de "le mien est plus rapide". Vous avez donc habilement masqué l'autodafé en mettant en avant "regardez comme c'est lent".


Le fait est que si l'on ose utiliser ensemble des bibliothèques où le paramètre d'entrée n'est pas le même, on obtiendra des décalages. Il n'en est fait mention nulle part dans la documentation. Au moins quelque chose sur ce sujet a été extrait de vous avec des pinces. Et quand c'était fait, ils ont commencé à vous accuser de tricher.


Cette fonctionnalité de MQL devrait être écrite dans la branche Documentation et dans la branche Fonctionnalités. Exécutez les scripts MQL5 propres de cette branche sur les builds correspondant aux dates de leur création. Apparemment, tant de corrections ont été faites à l'aveuglette, juste au cas où.

La documentation de HistorySelect indique clairement :

La fonction HistorySelect() crée une liste d'ordres et une liste de transactions dans le programme mql5 pour une référence ultérieure aux éléments de la liste au moyen des fonctions correspondantes. La taille de la liste des transactions peut être obtenue à l'aide de la fonction HistoryDealsTotal(), et la taille de la liste des commandes dans l'historique peut être obtenue à l'aide de la fonction HistoryOrdersTotal(). L'énumération des éléments de la liste des commandes est mieux réalisée en utilisant la fonction HistoryOrderGetTicket(), pour les éléments de la liste des transactions, la fonction HistoryDealGetTicket() est appropriée.

Après l'utilisation de la fonction HistoryOrderSelect(), la liste des commandes dans l'historique, disponible pour mql5-program, est réinitialisée et remplie à nouveau avec la commande, si la recherche de la commande par ticket a été effectuée avec succès. Il en va de même pour la liste des offres disponibles pour le programme mql5 - elle est réinitialisée à l'aide de la fonction HistoryDealSelect() et remplie à nouveau si une offre est obtenue avec succès par le numéro de ticket.


Lorsque vous travaillez avec d'énormes volumes (et ce n'est pas pour rien que vous avez montré des milliers et des dizaines de milliers de transactions dans l'historique), qui nécessitent un accès atomique/snapshot, vous devez comprendre leur coût.

D'autant plus que j'ai expliqué les détails techniques de ces caches de manière très détaillée dans ce fil de discussion.


Avez-vous essayé pour rien de randomiser chaque échantillon et d'empoisonner le cache autant que possible ? Pour le bien de votre position, une autodestruction est de mise ?

 
Renat Fatkhullin:

Parce que vous avez fait tout ce que vous pouviez pour que vos bibliothèques restent discrètes. C'est pourquoi vous avez habilement masqué les bugs auto-infligés en affichant "regardez comme il est lent".

99% des bugs sont trouvés de cette façon. Le comportement étrange se trouve d'abord dans le gros code. La localisation permet alors de trouver la cause. J'étais plus préoccupé par les freins.

fonction commerciale. Les problèmes sont presque partout.

KD      0       16:00:33.382    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 34: HistoryOrderSelect(0)] = 25 ms.
PE      0       16:00:44.913    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 17: CopyTicks(Symb,Ticks,COPY_TICKS_ALL,0,1)] = 24 ms.
DP      0       16:00:44.888    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 46 ms.
FI      0       16:00:49.579    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 28: HistoryDealSelect(0)] = 22 ms.
EE      0       16:01:03.287    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 33: HistoryOrderGetDouble(0,ORDER_PRICE_CURRENT)] = 1 ms.
KE      0       16:01:07.013    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 50: OrderGetDouble(ORDER_PRICE_CURRENT)] = 1 ms.
JM      0       16:01:12.189    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 44: TimeCurrent()] = 39 ms.
MD      0       16:01:13.067    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 81: ResourceFree(NULL)] = 1 ms.
RS      0       16:01:13.572    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 41: SymbolInfoDouble(Symb,SYMBOL_POINT)] = 7 ms.
GL      0       16:01:27.816    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 79: GlobalVariableGet(NULL)] = 22 ms.
PD      0       16:01:33.892    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 58: PositionGetInteger(POSITION_MAGIC)] = 1 ms.
KP      0       16:01:39.864    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 67: OrderCheck(Request,CheckResult)] = 3 ms.
ML      0       16:01:39.970    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 62: AccountInfoInteger(ACCOUNT_MARGIN_MODE)] = 1 ms.
KM      0       16:01:41.045    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 55: PositionSelect(Symb)] = 2 ms.
NS      0       16:01:46.832    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 78: GlobalVariableCheck(NULL)] = 1 ms.
JP      0       16:01:49.211    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 75: SymbolName(0,true)] = 1 ms.
EL      0       16:01:59.101    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 19: CopyTicksRange(Symb,Ticks,COPY_TICKS_ALL,Tick.time_msc)] = 32 ms.
IM      0       16:02:07.462    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 70: AccountInfoInteger(ACCOUNT_TRADE_EXPERT)] = 7 ms.
PJ      0       16:02:11.735    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 37: IsStopped()] = 4 ms.
OG      0       16:03:08.178    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 32: HistoryOrderGetInteger(0,ORDER_MAGIC)] = 14 ms.
JH      0       16:03:16.385    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 40: SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE)] = 5 ms.
FM      0       16:03:16.601    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 59: PositionGetString(POSITION_SYMBOL)] = 1 ms.
GH      0       16:03:21.841    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 72: TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)] = 1 ms.
FJ      0       16:03:25.782    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 46: TimeTradeServer()] = 1 ms.
EO      0       16:03:26.772    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 45: TimeLocal()] = 10 ms.
HD      0       16:03:36.595    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 13: SymbolInfoTick(Symb,Tick)] = 13 ms.
...
L'homme a décidé d'aider et a exécuté un code MQL5 propre sur sa machine. Un petit échantillon ci-dessus. Lisez les noms des fonctions ci-dessus.


La documentation de HistorySelect indique explicitement :

La fonction HistorySelect() crée une liste d'ordres et une liste de transactions dans le programme mql5 pour une référence ultérieure aux éléments de la liste via les fonctions appropriées. La taille de la liste des transactions peut être obtenue à l'aide de la fonction HistoryDealsTotal(), et la taille de la liste des commandes dans l'historique peut être obtenue à l'aide de la fonction HistoryOrdersTotal(). L'énumération des éléments de la liste des commandes est mieux réalisée en utilisant la fonction HistoryOrderGetTicket(), pour les éléments de la liste des transactions, la fonction HistoryDealGetTicket() est appropriée.

Après l'utilisation de la fonction HistoryOrderSelect(), la liste des commandes dans l'historique, disponible pour mql5-program, est réinitialisée et remplie à nouveau avec la commande, si la recherche de la commande par ticket a été effectuée avec succès. Il en va de même pour la liste des offres disponibles pour le programme mql5 - elle est réinitialisée à l'aide de la fonction HistoryDealSelect() et remplie à nouveau si une offre est obtenue avec succès par le numéro de ticket.

Je me demande qui a vu quelque chose entre les lignes dans ce texte ? Personnellement, j'ai compris (avant cette branche), que HistoryDealSelect et HistoryOrderSelect doivent être écrits comme ceci.

  static bool HistorySelectOrder( const ulong Ticket )
  {
    return((::HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket) || ::HistoryOrderSelect(Ticket));
  }

  static bool HistorySelectDeal( const ulong &Ticket )
  {
    return((::HistoryDealGetInteger(Ticket, DEAL_TICKET) == Ticket) || ::HistoryDealSelect(Ticket));
  }

Sinon, vous êtes assuré de rencontrer des décalages.

Lorsque vous travaillez avec d'énormes volumes, nécessitant un accès atomique/snapshot, vous devez comprendre leur coût.

D'autant plus que j'ai expliqué les détails techniques de ces caches de manière très détaillée dans ce fil de discussion.

J'ai recueilli les informations nécessaires dans ce fil.

 
Renat Fatkhullin:

Avez-vous essayé pour rien de randomiser chaque échantillon et d'empoisonner le cache autant que possible ? Pour le bien de votre position, une autodestruction est de mise ?

Vous pouvez tout voir par ordre chronologique dans ce fil. Le problème a été montré à l'origine sans aucun aléa.

Ce fil est un grand testament de la façon dont vous pouvez déformer les mots de votre adversaire. Toutes les sources et leurs résultats sont enregistrés ici.

 

Pourquoi le terminal ne peut-il pas simplement augmenter le cache lorsque l'historique complet est à nouveau demandé, récupérer et mettre en cache la plage manquante ? Cela semble résoudre le problème. Après tout, lors de la demande de bars/tickets, des paquets de données manquants sont renvoyés, il existe donc un mécanisme pour cela.

 
Aleksey Vyazmikin:

Pourquoi le terminal ne peut-il pas simplement augmenter le cache lorsque l'historique complet est à nouveau demandé, récupérer et mettre en cache la plage manquante ?

Cela a déjà été fait.

Mais si entre HistorySelect( 0, INT_MAX ) appelleHistorySelect( autre_temps, ... ), le cache sera reconstruit à partir d' autre_temps et la prochaine requêteHistorySelect( 0, ... ) entraînera une nouvelle construction du cache (sera plus lente).

 
Andrey Khatimlianskii:

Cela a déjà été fait.

Mais si entre les appels de HistorySelect( 0, INT_MAX ) nous appelonsHistorySelect( autre_temps, ... ), le cache sera reconstruit à partir d' autre_temps et la prochaine requêteHistorySelect( 0, ... ) entraînera une nouvelle construction du cache (ce sera plus lent).

Si vous l'avez fait, c'est bien, la seule question est alors celle de la commodité du travail avec les données reçues, à condition que le cache soit constitué.

Je n'ai pas compris les opérations de trading aussi profondément, mais si la plage de requête change, il n'y a pas de possibilité de rechercher rapidement des données dans l'historique sans force brute totale ?

 
Aleksey Vyazmikin:

Je ne suis pas très au fait des échanges, mais si l'étendue de la requête change, il n'y a aucun moyen de rechercher rapidement des données dans l'histoire sans une énumération complète ?

Quel est l'intérêt de ces connaissances si vous ne les utilisez pas ?

Pas de problème pratique = pas de question.

 
Renat Fatkhullin:

OrderExist et PositionExist sont des fonctions spéciales optimisées qui évitent de boucler stupidement sur tous les ordres ou positions à la recherche d'entrées par symbole, type de transaction et medzhik.

Le résultat est un ensemble de billets.


Les programmes peuvent économiser beaucoup d'argent en utilisant ces fonctions. Surtout lorsqu'on appelle des positions ouvertes et des ordres en masse, de manière constante et répétée dans des boucles de dépassement.

Nous mettrons en œuvre des fonctions plus efficaces pour accéder à des données commerciales massives à l'avenir.

La langue sera également considérablement renforcée et simplifiée grâce à des fonctionnalités plus puissantes.

"OrderExist et PositionExist" - introuvables dans la documentation, où puis-je trouver des informations à leur sujet ?
 
HimOrik:
"OrderExist et PositionExist" - non trouvé dans la documentation, où lire à leur sujet ?

Très probablement après la prochaine version (actuellement en version bêta).