Le paramètre d'entrée ChartID zéro dans certaines fonctions n'entraîne pas le recalcul des valeurs. Si vous voulez les données réelles du graphique actuel, vous devez utiliser l'ID complet.
Si nous supposons qu'il s'agit d'un comportement normal de MT5 et non d'une particularité du hack du courtier, alors
ORDER_STATE_PARTIAL n'apparaît pas dans les ordres historiques.
Les ordres exécutés ont toujours le statut ORDER_STATE_FILLED.
Lorsqu'un ordre est partiellement exécuté, un nouvel ordre de marché correspondant est créé par le serveur de négociation (ORDER_REASON_CLIENT - même si l'ordre initial est placé automatiquement (EXPERT)).
L'ancien ordre en direct (le ticket n'est pas modifié) reste en attente avec un volume réduit (ORDER_VOLUME_CURRENT).
Dans ce cas, l'ancienne commande en direct reçoit le statut ORDER_STATE_PARTIAL. En fait, cet indicateur est le résultat de la comparaison de ORDER_VOLUME_CURRENT et ORDER_VOLUME_INITIAL.
Toutes les positions ouvertes reçoivent un ID == OrderTicket. Où OrderTicket est le ticket généré par le serveur commercial.
Une transaction a toujours exactement un ordre historique et son statut est ORDER_STATE_FILLED.
Chaque ordre historique exécuté comporte exactement une transaction.
Le ORDER_VOLUME_INITIAL de tout ordre exécuté est égal au volume pour lequel il a été exécuté. C'est-à-dire que même l'ordre initial qui a été annulé a un ORDER_VOLUME_INITITAL qui est égal au volume de la transaction qu'il a engendrée.
L'heure de l'ordre initial (qui a été partiellement exécuté) ne change pas et n'est pas égale à l'heure de sa transaction.
Le tableau historique est trié par heure de commande (ORDER_TIME_SETUP) mais pas par heure de transaction. Ainsi, si nous faisons HistorySelect à partir de DEAL_TIME, nous ne pouvons pas obtenir la commande correspondante dans la table d'historique.
HistorySelectByPosition renvoie toujours l'ensemble des transactions/ordres nécessaires.
Vous pouvez calculer le slippage pour n'importe quelle transaction.
Faiblesses
Les éléments ORDER_REASON_PARTIAL, DEAL_REASON_PARTIAL et POSITION_REASON_PARTIAL sont manquants. Ces indicateurs doivent être placés immédiatement après REASON_EXPERT dans les listes respectives.
Les ordres au marché correspondants, lorsqu'ils exécutent partiellement des ordres à cours limité, peuvent par nature avoir un slippage négatif. Il semble s'agir d'une erreur dans le type d'ordre uniquement et il n'y a pas vraiment d'ordre de marché - il est seulement créé à l'intérieur de MT5 et ne sort pas.
(pas sûr, difficile à vérifier, similaire à la fermeture partielle de la position)
Tout fonctionne comme ceci :
1) ordre en attente déclenché partiellement - une position avec Position_ID = Order_Ticket1 est ouverte
2) le reste de l'ordre est formé en un nouvel ordre Order_Ticket2 et attend son exécution ; le nouvel Order_Ticket2 != Order_Ticket1 car il ne peut y avoir deux ordres dans l'historique avec le même Order_Ticket
3) l'ordre restant a été exécuté - une position avec Position_ID = Order_Ticket2 est ouverte.
il y a deux ordres dans l'historique, deux positions dans le terminal, tout correspond
Ouvrir une position BUY à la main sur deux serveurs de démonstration de trading
RoboForex-MetaTrader 5
2018.02.13 00:02:08.424 '8520459': market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': accepted market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': deal #90389019 buy 1.00 GBPUSD at 1.38387 done (based on order #107426544)
2018.02.13 00:02:10.101 '8520459': order #107426544 buy 1.00 / 1.00 GBPUSD at 1.38387 done in 1683.949 ms
FXOpen-MT5
2018.02.13 00:00:25.780 '18000903': market buy 1.00 GBPUSD
2018.02.13 00:00:25.912 '18000903': accepted market buy 1.00 GBPUSD
2018.02.13 00:00:25.922 '18000903': market buy 1.00 GBPUSD placed for execution
2018.02.13 00:00:25.942 '18000903': order #896454 buy 1.00 / 1.00 GBPUSD at market done in 154.252 ms
2018.02.13 00:00:25.942 '18000903': deal #80559 buy 1.00 GBPUSD at 1.38387 done (based on order #896454)
Les lignes de la même couleur indiquent la même chose. Cependant, on voit clairement qu'ils sont dans un ordre différent. Pour Robo, le message concernant l'exécution de l'ordre arrive après l'exécution de la transaction. En ouvert, il vient AVANT ! Pour cette raison, OrderSend renvoie la chance, mais pas encore de transaction. C'est-à-dire que nous obtenons un OrderSend non synchronisé avec l'historique.
Si un ordre est envoyé à un système de négociation externe, le serveur de négociation MetaTrader 5 n'attend pas de réponse de sa part et renvoie immédiatement le résultat de la demande comme "ordre passé". Pour cette raison, OrderSend retournera toujours deal=0, car il n'y a pas encore d'information sur la transaction exécutée. Attrapez-le dans OnTrade ou OnTradeTransaction.
OrderSend - envoie un ordre pour exécuter une transaction sur le marché.L'ordre est passé- nous devons lire Result.order. Mais personne n'attend la ou les transactions - il peut y en avoir beaucoup et le temps total de leur exécution n'est pas défini.
Cela dépend de l'implémentation spécifique de la sortie du côté du courtier. Dans le cas général, il n'est pas défini.
Je vous recommande donc vivement d'utiliser le compte de démonstration sur FXOpen-MT5 pour tester votre code, car il se distingue des autres démos.
Par exemple, je suggère d'essayer d'écrire un script en MQL5 avec la logique de trading suivante (le style MQL4 n'est utilisé que pour un affichage rapide)
Le poste était important. Je ne m'attendais pas à être supprimé. J'aimerais entendre la raison de la suppression. Parce que c'est masochiste de se faire supprimer à nouveau.
Je vous le dis, ce n'est pas parmi les effacés. Peut-être qu'il y a eu un pépin ?
Tout ne va pas du tout bien dans MT5. Exemple montrant le problème
// Пример неправильного считывания торгового окружения на каждом тике// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.#include <Trade/Trade.mqh>
// Возвращает количество позиций по символуint GetAmountPositions( conststring Symb )
{
int Res = 0;
// Этот MQL5-код с ошибкойfor (int i = PositionsTotal() - 1; i >= 0; i--)
if (PositionGetSymbol(i) == Symb)
Res++;
/*
// В MT4 такой код выполняется без ошибки
for (int i = OrdersTotal() - 1; i >= 0; i--)
if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
Res++;
*/return(Res);
}
// Пример OnTickvoid ExampleOnTick()
{
static CTrade Trade;
// Если нет позиции, открываемif (!GetAmountPositions(_Symbol))
Trade.Buy(1);
}
// Эмуляция прихода двух Tick-событийvoidOnStart()
{
ExampleOnTick();
Sleep(10); // Между двумя тиками ~10 мс.
ExampleOnTick();
}
Pensez-vous que si vous exécutez ce script sur un symbole sans positions, qu'est-ce qui va se passer ?
La réponse correcte est qu'un ou deux postes seront ouverts.
La raison pour laquelle cela se produit. Après le premier envoi d'ordre, un ordre au marché apparaît et si un nouveau tick arrive avant le moment de son exécution, il n'y a pas encore de position et le deuxième envoi d'ordre est effectué.
L'idée apparemment bonne de PositionsTotal est quelque peu éclipsée par la nécessité, dans MT5, d'analyser également OrdersTotal pour les ordres au marché.
Pour cette raison, un modèle MT5 apparemment normalne fonctionnera pas correctement et, par conséquent, la plupart des EA MT5 de la base kodobase.
Comme preuve de cette affirmation, nous pouvons prendre presque tous les conseillers experts de la base de données MT5. Ne choisissons pas n'importe quoi mais prenons le dernier conseiller expert du moment. Il est bon qu'il ait été écrit par un auteur ayant une grande expérience de la publication de MT5 en QB.
Le code source contient les chaînes de caractères suivantes (mes commentaires sont mis en évidence)
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
//....int total=0; // для расчета количества открытых советником позиций//....//--- main cyclefor(int i=PositionsTotal()-1;i>=0;i--)
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its propertiesif(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
{
total++; // расчет количества открытых позиций//....if(total==0) // Если нет открытых советником позиций
{
if(!RefreshRates())
{
PrevBars=iTime(1);
return;
}
//--- open BUY if(MACD_MAIN_2>MACD_SIGNAL_2 && MACD_MAIN_4<MACD_SIGNAL_4) // Сигнал на покупку
{
double sl=(InpStopLoss!=0)?m_symbol.Ask()-ExtStopLoss:0.0;
double tp=(InpTakeProfit!=0)?m_symbol.Ask()+ExtTakeProfit:0.0;
OpenBuy(sl,tp); // Отправка маркет-ордера на покупкуreturn;
}
//--- open SELLif(MACD_MAIN_2<MACD_SIGNAL_2 && MACD_MAIN_4>MACD_SIGNAL_4) // Сигнал на продажу
{
double sl=(InpStopLoss!=0)?m_symbol.Bid()+ExtStopLoss:0.0;
double tp=(InpTakeProfit!=0)?m_symbol.Bid()-ExtTakeProfit:0.0;
OpenSell(sl,tp); // Отправка маркет-ордера на продажу
}
}
return;
}
Nous sommes dans une situation identique à celle décrite ci-dessus.
Après le premier envoi d'ordre, un ordre au marché apparaît et si un nouveau tick arrive avant son exécution, il n'y a pas encore de position et un deuxième envoi d'ordre est effectué.
L'idée apparemment bonne de PositionsTotal est quelque peu éclipsée par la nécessité, dans MT5, d'analyser également OrdersTotal pour les ordres au marché.
Cela signifie que dans le cas général, au lieu d'une position, le conseiller expert en ouvrira deux, trois, etc. En fonction de la fréquence de réception des ticks et de la durée d'exécution des ordres de marché.
Puisque presque tous les EAs MT5 dans kodobase sont écrits avec la même logique que le modèle MT5, ils ont aussi le même bug qui est contenu dans celui-ci. C'est le cas de presque tous les EA de MT5 dans KB, malheureusement.
При поступлении сигнала противоположная позиция закрывается. Также советник может закрывать половину позиции (параметр Profit for closing half of the position), может переводить позицию в безубыток (параметр Breakeven). Размер открываемой позиции может задавать вручную (параметр Lots) или в процентах риска от свободной маржи (параметр Risk in...
Sur un netting, il peut y avoir une position ouverte et plusieurs ordres de marché dans un sens ou dans l'autre sur le même symbole au même moment. Par exemple, une position BUY et un ordre BUY. C'est vrai, je n'ai pas réussi à trouver un tel compte de démonstration, car il y avait une règle avec l'asynchronie partout.
Nous pouvons parfaitement voir à partir de la colonne de temps et des données numériques de l'EA que la durée d'exécution de l'ordre de transaction n'a aucun effet sur la séquence des événements OnTradeTransaction. Toute l'asynchronie part en vrille ! Ils ont réussi à tout gâcher. Construire 1755.
Par exemple, lorsque l'ordre de marché OrderSendAsync est placé dans le Terminal, l'ordre de marché n'apparaîtra même pas un instant. Les développeurs ont peut-être décidé de faire cela pour accélérer un peu les choses.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
Comment identifier un remplacement de carte ?
fxsaber, 2018.02.08 12:39
Le paramètre d'entrée ChartID zéro dans certaines fonctions n'entraîne pas le recalcul des valeurs. Si vous voulez les données réelles du graphique actuel, vous devez utiliser l'ID complet.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie
POSITION_TICKET != POSITION_IDENTIFIER
fxsaber, 2018.02.12 20:14
Conclusions
Si nous supposons qu'il s'agit d'un comportement normal de MT5 et non d'une particularité du hack du courtier, alors
Faiblesses
ZZY Hypothèse entièrement confirmée.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
POSITION_TICKET != POSITION_IDENTIFIER
Pavel Kolchin, 2018.02.12 13:31
(pas sûr, difficile à vérifier, similaire à la fermeture partielle de la position)
Tout fonctionne comme ceci :
1) ordre en attente déclenché partiellement - une position avec Position_ID = Order_Ticket1 est ouverte
2) le reste de l'ordre est formé en un nouvel ordre Order_Ticket2 et attend son exécution ; le nouvel Order_Ticket2 != Order_Ticket1 car il ne peut y avoir deux ordres dans l'historique avec le même Order_Ticket
3) l'ordre restant a été exécuté - une position avec Position_ID = Order_Ticket2 est ouverte.
il y a deux ordres dans l'historique, deux positions dans le terminal, tout correspond
Forum sur le trading, les systèmes de trading automatisés et l'essai de stratégies de trading
Discussion sur "LifeHack for trader : mixer ForEach sur les définitions (#define)"
fxsaber, 2018.02.14 10:54
Mesure de la performance
Résultat
J'avais totalement tort ! SymbolInfoDouble est deux fois plus lent que SymbolInfoTick.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
Discussion sur "LifeHack for trader : mixer ForEach sur les définitions (#define)"
fxsaber, 2018.02.14 11:58
Incompétent. Résultat dans le testeur.
Lorsque la performance est nécessaire (Optimizer), il est préférable d'utiliser SymbolInfoDouble. Dans le monde réel, cela ne fait aucune différence.
La mesure de la vitesse de la fonction ZZY doit être effectuée dans un environnement où les performances sont importantes - Testeur.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
Bugs, bugs, questions
fxsaber, 2018.02.12 23:10
Ouvrir une position BUY à la main sur deux serveurs de démonstration de trading
RoboForex-MetaTrader 5
FXOpen-MT5
Les lignes de la même couleur indiquent la même chose. Cependant, on voit clairement qu'ils sont dans un ordre différent. Pour Robo, le message concernant l'exécution de l'ordre arrive après l'exécution de la transaction. En ouvert, il vient AVANT ! Pour cette raison, OrderSend renvoie la chance, mais pas encore de transaction. C'est-à-dire que nous obtenons un OrderSend non synchronisé avec l'historique.
Code pour FXOpen-MT5
Résultat
Cette situation a l'explication suivante
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie
Bugs, bugs, questions
Rashid Umarov, 2018.02.15 06:25
Si un ordre est envoyé à un système de négociation externe, le serveur de négociation MetaTrader 5 n'attend pas de réponse de sa part et renvoie immédiatement le résultat de la demande comme "ordre passé". Pour cette raison, OrderSend retournera toujours deal=0, car il n'y a pas encore d'information sur la transaction exécutée. Attrapez-le dans OnTrade ou OnTradeTransaction.
Un exemple d'écouteur d'événement de transaction est donné dans l'article Où commencer lors de la création d'un robot de trading pour MOEX - TradeTransactionListener.mq5
OrderSend - envoie un ordre pour exécuter une transaction sur le marché.L'ordre est passé- nous devons lire Result.order. Mais personne n'attend la ou les transactions - il peut y en avoir beaucoup et le temps total de leur exécution n'est pas défini.
Cela dépend de l'implémentation spécifique de la sortie du côté du courtier. Dans le cas général, il n'est pas défini.
Je vous recommande donc vivement d'utiliser le compte de démonstration sur FXOpen-MT5 pour tester votre code, car il se distingue des autres démos.
Par exemple, je suggère d'essayer d'écrire un script en MQL5 avec la logique de trading suivante (le style MQL4 n'est utilisé que pour un affichage rapide)
Ce n'est pas facile du tout. Je recommande également le serveur de démonstration mentionné pour travailler sur l'exécution partielle.
Suppression d'un message qui donnait une explication sur l'une des erreurs les plus courantes sur MT5.
Le poste était important. Je ne m'attendais pas à être supprimé. J'aimerais entendre la raison de la suppression. Parce que c'est masochiste de se faire supprimer à nouveau.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
Organiser une boucle de commande
fxsaber, 2018.02.16 09:40
Tout ne va pas du tout bien dans MT5. Exemple montrant le problème
Pensez-vous que si vous exécutez ce script sur un symbole sans positions, qu'est-ce qui va se passer ?
La réponse correcte est qu'un ou deux postes seront ouverts.
La raison pour laquelle cela se produit. Après le premier envoi d'ordre, un ordre au marché apparaît et si un nouveau tick arrive avant le moment de son exécution, il n'y a pas encore de position et le deuxième envoi d'ordre est effectué.
Pour cette raison, un modèle MT5 apparemment normalne fonctionnera pas correctement et, par conséquent, la plupart des conseillers experts MT5 de codobase. Dans le même temps, le modèle MT4, presque identique, continuera à fonctionner sans aucun problème.
L'idée apparemment bonne de PositionsTotal est quelque peu éclipsée par la nécessité, dans MT5, d'analyser également OrdersTotal pour les ordres au marché.
Faites attention !
Pour cette raison, un modèle MT5 apparemment normalne fonctionnera pas correctement et, par conséquent, la plupart des EA MT5 de la base kodobase.
Comme preuve de cette affirmation, nous pouvons prendre presque tous les conseillers experts de la base de données MT5. Ne choisissons pas n'importe quoi mais prenons le dernier conseiller expert du moment. Il est bon qu'il ait été écrit par un auteur ayant une grande expérience de la publication de MT5 en QB.
Le code source contient les chaînes de caractères suivantes (mes commentaires sont mis en évidence)
Nous sommes dans une situation identique à celle décrite ci-dessus.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie
Particularités du langage mql5, trucs et astuces
fxsaber, 2018.02.16 19:52
Après le premier envoi d'ordre, un ordre au marché apparaît et si un nouveau tick arrive avant son exécution, il n'y a pas encore de position et un deuxième envoi d'ordre est effectué.
L'idée apparemment bonne de PositionsTotal est quelque peu éclipsée par la nécessité, dans MT5, d'analyser également OrdersTotal pour les ordres au marché.
Cela signifie que dans le cas général, au lieu d'une position, le conseiller expert en ouvrira deux, trois, etc. En fonction de la fréquence de réception des ticks et de la durée d'exécution des ordres de marché.
Puisque presque tous les EAs MT5 dans kodobase sont écrits avec la même logique que le modèle MT5, ils ont aussi le même bug qui est contenu dans celui-ci. C'est le cas de presque tous les EA de MT5 dans KB, malheureusement.
Sur un netting, il peut y avoir une position ouverte et plusieurs ordres de marché dans un sens ou dans l'autre sur le même symbole au même moment. Par exemple, une position BUY et un ordre BUY. C'est vrai, je n'ai pas réussi à trouver un tel compte de démonstration, car il y avait une règle avec l'asynchronie partout.
Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading
Bugs, bugs, questions
fxsaber, 2018.02.14 08:58
L'ensemble de la séquence d'événements OnTradeTransaction intervient après l'envoi de l'ordre.
EA
Envoi manuel d'un ordre de transaction.
Journal de bord
2018.02.14 09:41:46.671 '8854170': instant sell 1.00 EURUSD at 1.23673 2018.02.14 09:41:46.853 '8854170': accepted instant sell 1.00 EURUSD at 1.23673 2018.02.14 09:41:46.853 '8854170': deal #192088422 sell 1.00 EURUSD at 1.23673 done (based on order #208541700) 2018.02.14 09:41:46.853 '8854170': order #208541700 sell 1.00 / 1.00 EURUSD at 1.23673 done in 190.608 msRésultat du conseiller expert
Nous pouvons parfaitement voir à partir de la colonne de temps et des données numériques de l'EA que la durée d'exécution de l'ordre de transaction n'a aucun effet sur la séquence des événements OnTradeTransaction. Toute l'asynchronie part en vrille ! Ils ont réussi à tout gâcher. Construire 1755.
Par exemple, lorsque l'ordre de marché OrderSendAsync est placé dans le Terminal, l'ordre de marché n'apparaîtra même pas un instant. Les développeurs ont peut-être décidé de faire cela pour accélérer un peu les choses.
Forum sur le trading, les systèmes de trading automatisé et les tests de stratégies de trading
Discussion de l'article "Visualisation de l'optimisation des stratégies commerciales dans MetaTrader 5".
fxsaber, 2018.02.22 08:39
En mode cadre, OnInit, OnDeinit, OnTick, OnTrade, OnTradeTransaction et OnTimer sont ignorés. Seul OnChartEvent fonctionne.
Bien sûr, en raison de l'exception OnChartEvent, il faut obligatoirement vérifier l'indicateur frame-mode.