Caractéristiques du langage mql5, subtilités et techniques - page 201

 
Lorsque vous appelez une macro, vous pouvez ne spécifier aucun paramètre (l'omettre). Parfois, vous souhaitez autoriser spécifiquement une macro à fonctionner avec un paramètre non spécifié.


Pour de tels cas, voici quelques macros auxiliaires.

1. Parfois, vous voulez déterminer dans votre macro si un paramètre a été défini ou non. IS_PARAMETER_SET(p) définit une expression, qui renvoie vrai si p est défini (même si la variable string ==NULL).

Attention : l'expression est évaluée après prétraitement au moment de la compilation !!!, c'est-à-dire qu'elle ne peut pas être utilisée pour implémenter quelque chose comme #ifdef IS_PARAMETER_SET(p) #else (ceci s'applique également aux autres macros ci-dessous)

2. Si vous avez besoin de convertir explicitement la valeur d'un paramètre en une chaîne de caractères, pour éviter une erreur de compilation avec un paramètre non spécifié, vous pouvez utiliser __EVAL_STR(p). Si p n'est pas spécifié ou explicitement défini avec un littéral NULL, il retourne "". Non applicable aux tableaux, structures et classes.

La conversion explicite d'un paramètre en un nombre est __EVAL_NON_STR(p). Si p n'est pas défini, retourne 0. Ne fonctionne pas si p est une chaîne de caractères !

Code et exemples d'utilisation :

//Expression returns true if macro's parameter is specified.
#define  IS_PARAMETER_SET(p) ("" != #p || __hlp_macro_func(p))
bool __hlp_macro_func(const string p = NULL) {return "" == p;}
template<typename T> bool __hlp_macro_func(T p)    {return true;}
template<typename T> bool __hlp_macro_func(T& p)   {return true;}
template<typename T> bool __hlp_macro_func(T& p[]) {return true;}


//Expression returns parameter p; if parameter is not specified returns NULL; if p is string returns p
//Error for arrays and objects
#define __EVAL(p) (""==#p?NULL:p+NULL)


//Explicit conversion to string. If parameter is not specified or is constant NULL returns ""
//Error for arrays and objects
#define __EVAL_STR(p) (""==#p || "NULL"==#p? "" :(string)(p+NULL))


//Explicit conversion to number. If parameter is not specified returns 0. Works incorrect if p is string!
//Error for arrays and objects
#define __EVAL_NON_STR(p) ("" == #p? 0 : p+0)


struct S1
  {   int               a; };
class C1
  { int               a; };

void OnStart()
  {
//---
   Print(IS_PARAMETER_SET());                //false
   Print(IS_PARAMETER_SET(""));              //true
   Print(IS_PARAMETER_SET("test"));          //true
   Print(IS_PARAMETER_SET(NULL));            //true
   Print(IS_PARAMETER_SET(0));               //true
   Print(IS_PARAMETER_SET(1));               //true
   string str;
   Print(IS_PARAMETER_SET(str));             //true

   int arr[1];
   Print(IS_PARAMETER_SET(arr));             //true
   S1 _struct;
   Print(IS_PARAMETER_SET(_struct));         //true
   C1 _class;
   Print(IS_PARAMETER_SET(_class));          //true

#define   MACRO1_(a,b)  (IS_PARAMETER_SET(b)?a:-a)
   Print(MACRO1_(1, 0));                     //1
   Print(MACRO1_(1,));                       //-1

#define   MACRO2_(a,b,c)  Print(a," = ",b + c)
#define   MACRO3_(a,b,c)  Print(__EVAL_STR(a)," = ",__EVAL_NON_STR(b) + __EVAL_NON_STR(c))

 //MACRO2_(, 2,);                            // ',' - syntax error, parameter missed
   MACRO3_(, 2,);                            // = 2
   MACRO3_("a", 2, 3);                       // a = 5
  }


 
fxsaber:

Le code suivant sur le compte de démonstrationRannForex-Server permet de reproduire immédiatement cette situation en exécutant ce conseiller.


Résultat.


A propos, le script montre (pas toujours la première fois) un bug dans l'exécution synchrone de OrderSend.

Après l'exécution d'OrderSend pendant quelques dizaines ou centaines de millisecondes, le prix de l'ordre est l'ancien prix, et non celui qui a été placé avec succès par OrderSend.


Pour en revenir au sujet des billets identiques, nous pouvons tirer quelques conclusions.

  1. Si un ordre à cours limité partiel est suspendu, l'onglet "Ordres et transactions" n'affichera pas la transaction générée.
  2. Sur une couverture, un seul ordre peut générer plusieurs transactions IN avec des prix différents. Le résultat sera un prix d'ouverture fractionné (par rapport aux pips) de la position.
  3. Vous pouvez fermer la position générée sans supprimer le Put partiel. Mais si après cela l'ordre en attente est déclenché, alors une transaction sera ouverte avec le ticket, égal au ticket de la position, qui a été fermée avant. Autrement dit, il peut arriver que vous fermiez une position avec un certain ticket. Et puis une position réapparaît avec le même ticker.
  4. L'exécution partielle peut être mise en œuvre différemment, selon le logiciel du courtier. Ce qui précède est une mise en œuvre standard de MT5.

Si quelqu'un a réussi à le reproduire sur un autre serveur de trading, merci de partager le nom.

Nom de recherche: Oshibka 010.

On en revient encore à la question de l'exécution partielle.

1. Veuillez clarifier le point 3 : "Vous pouvez fermer la position que vous avez formée sans supprimer l'exécution partielle. Mais si l'ordre est ensuite déclenché, une transaction s'ouvrira avec un ticket égal à celui de la position que vous avez fermée auparavant. Autrement dit, il peut arriver que vous fermiez une position avec un certain ticket. Et ensuite, une position réapparaît avec le même ticket."
Dans ce cas, POSITION_IDENTIFIER était-il égal à POSITION_TICKET ou non ?

2. Plus tôt dans le fil de discussion "POSITION_TICKET != POSITION_IDENTIFIER", vous avez démontré une logique MT5 différente.

https://www.mql5.com/ru/forum/227423/page2#comment_6543129

fxsaber:

Conclusions

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'existe pas dans les ordres historiques.
  • Les ordres qui sont 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'ancien ordre en direct a 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.

D'après votre expérience, y a-t-il un schéma général dans les cas/modes de travail que MT5 utilise ?

3. En définitive, y a-t-il déjà eu des situations réelles où "POSITION_TICKET != POSITION_IDENTIFIER" ?

POSITION_TICKET != POSITION_IDENTIFIER
POSITION_TICKET != POSITION_IDENTIFIER
  • 2018.02.12
  • www.mql5.com
зная id позиции можно ли без перебора узнать тикет позиции...
 
mktr8591:
Lors de l'appel d'une macro, il est possible d'omettre un paramètre (de ne pas le prendre en compte). Parfois, vous souhaitez autoriser spécifiquement une macro à fonctionner avec un paramètre non spécifié.
Il s'avère qu'un paramètre non spécifié dans une macro est traité par le compilateur comme une chaîne vide ?
 
fxsaber:
Il s'avère donc qu'un paramètre non spécifié dans une macro est traité par le compilateur comme une chaîne vide ?

D'une certaine manière, oui, bien que "comme un espace vide" soit un meilleur terme. Difficile de s'exprimer clairement :-(.

Mais #p se transforme définitivement en chaîne ==""

 
mktr8591:

D'une certaine manière, oui, bien que "comme un espace vide" soit un meilleur terme. Difficile de s'exprimer clairement :-(.

Mais #p se transforme définitivement en chaîne ==""

Merci, nuance intéressante.

 
Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2021.04.03
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 
mktr8591:

On en revient encore à la question de la performance partielle.

1. Veuillez clarifier le point 3 : " Vous pouvez clôturer une position formée sans supprimer l'option de vente partielle. Mais si l'ordre est ensuite déclenché, une transaction s'ouvrira avec un ticket égal à celui de la position que vous avez fermée auparavant. Autrement dit, il peut arriver que vous fermiez une position avec un certain ticket. Et puis une position réapparaît avec le même ticket."
Dans ce cas, POSITION_IDENTIFIER était-il égal à POSITION_TICKET ou non ?

2. Plus tôt, dans la branche "POSITION_TICKET != POSITION_IDENTIFIER", vous avez démontré une logique différente de MT5.

https://www.mql5.com/ru/forum/227423/page2#comment_6543129

Dans votre expérience, avez-vous constaté un schéma général dans quels cas/modes d'opération le schéma MT5 s'applique ?

3. En définitive, y a-t-il déjà eu des situations réelles où "POSITION_TICKET != POSITION_IDENTIFIER" ?

Les deux liens parlent de différentes implémentations de l'exécution partielle. Ceci est déterminé par le logiciel du courtier, et non par MT5.

Aucune incompatibilité entre le ticket et l'identification n'a jamais été rencontrée.

 
Merci.
 

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

Bibliothèques : Utilisation

fxsaber, 2021.05.01 14:17

GetMicrosecondCount peut produire une valeur inférieure à celle de l'appel précédent (sans dépassement de l'ULONG). Exemples de telles situations.
2021.04.29 06:43:31.915   Alert: NewValue = 296000074313, PrevValue = 296001329284

2021.04.29 06:43:32.149   Alert: NewValue = 296086250613, PrevValue = 296087264090

2021.04.29 06:43:31.868   Alert: NewValue = 295129291901, PrevValue = 295130576710

2021.04.29 06:43:32.180   Alert: NewValue = 295955613012, PrevValue = 295956589070

2021.04.29 06:43:32.180   Alert: NewValue = 295146223171, PrevValue = 295147199454

2021.04.29 06:43:32.149   Alert: NewValue = 295065995432, PrevValue = 295067005968

2021.04.29 06:43:32.149   Alert: NewValue = 295078776581, PrevValue = 295079787357

Chaque ligne est obtenue par différents EAs sur trois terminaux MT4.

Et sur MT5, ce genre de chose arrive, mais beaucoup moins fréquemment sur MT4.

Faites attention.

 
Les commentaires non liés à ce sujet ont été déplacés vers "Questions des débutants de MQL5 MT5 MetaTrader 5".