Experts: Programmation MQL5 pour les Traders - Codes Source du livre. Partie 7 - page 2

 
Denis Kirichenko #:

En général, pour un manuel, il est préférable d'écrire entre parenthèses:

Tous les opérateurs de la forme @=, où chien signifie le symbole d'une opération quelconque, sont toujours exécutés sur l'opérande de droite, entièrement compté avant l'exécution de l'opération. Ce point est abordé dans la partie 2, sous la rubrique Opérations de modification.

Le fichier de calcul des marges est décrit dans la sixième partie, où l'on suppose que les parties précédentes ont été maîtrisées. La complexité augmente vers la fin du livre - je n'en disconviens pas, c'est pourquoi j'ai essayé de faire référence aux grands concepts et principes des sections précédentes dans les sections suivantes, où ils ont été utilisés comme éléments de base (pour vous rafraîchir la mémoire), mais pas pour de si petites choses.

 
Stanislav Korotky #:

...La complexité augmente vers la fin du livre, ce qui n'est pas contestable. Pour les grands concepts et principes des sections précédentes, j'ai essayé de faire référence aux sections suivantes où ils étaient utilisés comme éléments constitutifs (pour me rafraîchir la mémoire), mais pas pour de si petites choses.

Stanislav, j'ai un niveau de programmation plus modeste que le vôtre. J'essaie d'écrire le code de manière à ce qu'il soit plus facile de le vérifier dans le débogueur. C'est pourquoi je n'utilise pas souvent l'opérateur ternaire. Et si je le fais, je l'utilise avec des parenthèses... Il existe des personnes habiles qui écrivent plusieurs opérateurs ternaires inclus les uns dans les autres. Cela se rapproche du style de programmation macro de mon collègue fxsaber. Il est probable que chaque approche a droit à la vie. Et c'est déjà une question de goût...

Grand respect et respect pour le tutoriel ! Certaines choses intéressantes sont décrites plus en détail que dans la documentation.

 
Aleksandr Slavskii #:

De toute façon, cela ne sert pas à grand-chose, car en fin de compte, la marge est toujours comptée de manière incorrecte si le volume est supérieur à trois.

Calcul de la marge pour dix contrats.

Veuillez joindre le script pour vérification. Je l'ai maintenant exécuté sur l'ensemble du marché - il coïncide avec la fonction standard, quel que soit le volume.

 
Denis Kirichenko #:

Et le compilateur est furieux :

Quelque chose a probablement changé dans le compilateur. Au moment de la publication du livre, toutes les sources se compilaient sans avertissement ni erreur, sauf dans les cas où il y avait des irrégularités délibérées à des fins de démonstration.

 
Denis Kirichenko #:

J'essaie d'écrire le code de manière à ce qu'il soit plus facile de le vérifier dans le débogueur. C'est pourquoi je n'utilise pas souvent l'opérateur ternaire. Et si je le fais, je l'utilise avec des parenthèses....

Je suis d'accord. Je m'en tiens également à cette règle, sauf dans les cas simples - mais ici, chacun a sa propre barrière de simplicité. La lisibilité du code est traitée individuellement, mais nous cherchons généralement un "juste milieu" entre l'approche "tout sur une seule ligne" et "chaque élément sur une ligne séparée". Avec des crochets - de la même manière. Les éditeurs de logiciels ont généralement un ensemble de règles sur la présentation du code source - dans ce cas, il n'y en avait pas.

 
D'autres corrections de bogues et améliorations pour la lecture du calendrier économique et l'exportation au format CSV ont été publiées dans la base de code. En particulier, l'algorithme de tri est corrigé pour le cas des grands tableaux triés (qui sont généralement reçus de l'API de calendrier MQL5), de sorte que les ralentissements et les dépassements de pile sont éliminés.
Economic Calendar CSV
Economic Calendar CSV
  • www.mql5.com
This script saves a predefined set of economic events from the MetaTrader's built-in economic calendar into CSV file.
 
Stanislav Korotky #:

Veuillez joindre le script pour vérification. Je l'ai maintenant exécuté sur l'ensemble du marché - il coïncide avec la fonction standard, quel que soit le volume.

Oh, mon Dieu. Je n'arrive pas à croire que je n'ai pas vu ce message. C'est vrai.

En fait, rien n'a changé pour moi.

Serveur Metaquot, terminal version 4420.

Le code est le suivant

#include "MarginProfitMeter.mqh"
//+------------------------------------------------------------------+
int OnInit(void)
  {
   EventSetTimer(1);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
void OnTimer()
  {
   double margin = 0;
   double volume = 10;
   ENUM_ORDER_TYPE type = ORDER_TYPE_BUY;
   double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   if(_OrderCalcMargin(type, _Symbol, volume, price, margin))
      Print("Symbol ", _Symbol, "; volume ", volume, "; MarginProfitMeter margin = ", margin);

   margin = 0;
   if(OrderCalcMargin(type, _Symbol, volume, price, margin))
      Print("Symbol ", _Symbol, "; volume ", volume, "; OrderCalcMargin margin = ", margin);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();
  }
//+------------------------------------------------------------------+

Le résultat est le suivant.

18:53:40.877    11 (EURUSD,H1)  Symbol EURUSD; volume 10.0; MarginProfitMeter margin = 10421.6
18:53:40.877    11 (EURUSD,H1)  Symbol EURUSD; volume 10.0; OrderCalcMargin margin = 23264.8

Quelqu'un compte mal.


Je ne sais pas ce que c'est et pourquoi c'est nécessaire, mais cela ne m'a pas permis de compiler l'EA.

En fait, j'ai juste supprimé la ligne namespace MPM, les accolades après et renommé OrderCalcMargin, en ajoutant le trait de soulignement.

En général, le fichier a été compilé sous cette forme. Est-il possible que l'erreur vienne de là ?

//+------------------------------------------------------------------+
//|MarginProfitMeter.mqh |
//|Copyright (c) 2018-2022, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//|| Un ensemble de fonctions permettant de calculer la marge, le bénéfice/la perte potentiel(le), la valeur de l'investissement, etc.
//| La valeur des points et les taux de couverture.|
//+------------------------------------------------------------------+
// Analogue de la marge intégrée OrderCalcMargin qui n'est pas autorisée dans les indicateurs
bool _OrderCalcMargin(const ENUM_ORDER_TYPE action, const string symbol,
                     double volume, double price, double &margin)
  {
   double marginInit, marginMain;
   MqlTick ticks;

// vérifie les paramètres donnés
   if((action != ORDER_TYPE_BUY && action != ORDER_TYPE_SELL) || volume < 0 || price < 0)
      return false;

// demande toutes les propriétés utilisées dans les formules
   if(!SymbolInfoTick(symbol, ticks))
      return false;
   if(!SymbolInfoMarginRate(symbol, action, marginInit, marginMain))
      return false;
   const double contract = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   long leverage = AccountInfoInteger(ACCOUNT_LEVERAGE);
   if(volume == 0)
      volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   if(price == 0)
      price = action == ORDER_TYPE_BUY ? ticks.ask : ticks.bid;

   if(margin == DBL_MAX)
      marginInit = marginMain;
   margin = 0;

   const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);

   switch(m)
     {
      case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
         leverage = 1;

      case SYMBOL_CALC_MODE_FOREX:
         margin = volume * contract / leverage * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFD:
         margin = volume * contract * price * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFDINDEX:
         margin = volume * contract * price * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)
                  / SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE) * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFDLEVERAGE:
         margin = volume * contract * price / leverage * marginInit;
         break;

      case SYMBOL_CALC_MODE_EXCH_STOCKS:
      case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
         if(price == 0)
            price = ticks.last;
         margin = volume * contract * price * marginInit;
         break;

      case SYMBOL_CALC_MODE_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
         margin = volume * SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL) * marginInit;
         break;
      default:
         PrintFormat("Unsupported symbol %s trade mode: %s", symbol, EnumToString(m));
     }

   string account = AccountInfoString(ACCOUNT_CURRENCY);
   string current = SymbolInfoString(symbol, SYMBOL_CURRENCY_MARGIN);
   if(current != account)
     {
      if(!_Convert(current, account, action == ORDER_TYPE_SELL, margin))
         return false;
     }

   return true;
  }

// Recherche des symboles disponibles pour un seul construit des devises "courant" et "compte".
int _FindExchangeRate(const string current, const string account, string &result)
  {
   for(int i = 0; i < SymbolsTotal(true); i++)
     {
      const string symbol = SymbolName(i, true);
      const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
      if(m == SYMBOL_CALC_MODE_FOREX || m == SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE)
        {
         string base = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE);
         string profit = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
         if(base == current && profit == account)
           {
            result = symbol;
            return +1;
           }
         else
            if(base == account && profit == current)
              {
               result = symbol;
               return -1;
              }
        }
     }
   return 0;
  }

// Estimer un taux de symbole spécifié à un moment donné dans le passé
double GetHistoricPrice(const string symbol, const datetime moment, const bool ask)
  {
   const int offset = iBarShift(symbol, _Period, moment);
// NB : iClose peut contenir le dernier prix au lieu de l'offre pour les symboles d'échange.
// il n'y a pas de moyen rapide de gérer cela, seule l'analyse de l'historique des ticks est possible
   return iClose(symbol, _Period, offset) +
          (ask ? iSpread(symbol, _Period, offset) * SymbolInfoDouble(symbol, SYMBOL_POINT) : 0);
  }

// _Convertir le montant de l'argent "courant" en argent "compte".
bool _Convert(const string current, const string account,
             const bool ask, double &margin, const datetime moment = 0)
  {
   string rate;
   int dir = _FindExchangeRate(current, account, rate);
   if(dir == +1)
     {
      margin *= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_BID : SYMBOL_ASK) :
                GetHistoricPrice(rate, moment, ask);
     }
   else
      if(dir == -1)
        {
         margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
        }
      else
        {
         static bool once = false;
         if(!once)
           {
            Print("Can't convert ", current, " -> ", account);
            once = true;
           }
        }
   return true;
  }

// Valeur du point de retour (dans la devise du compte) d'un symbole spécifique
double PointValue(const string symbol, const bool ask = false, const datetime moment = 0)
  {
   const double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   const double contract = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
   double result = 0;

   switch(m)
     {
      case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
      case SYMBOL_CALC_MODE_FOREX:
      case SYMBOL_CALC_MODE_CFD:
      case SYMBOL_CALC_MODE_CFDINDEX:
      case SYMBOL_CALC_MODE_CFDLEVERAGE:
      case SYMBOL_CALC_MODE_EXCH_STOCKS:
      case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
         result = point * contract;
         break;

      case SYMBOL_CALC_MODE_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
         result = point * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
         break;
      default:
         PrintFormat("Unsupported symbol %s trade mode: %s", symbol, EnumToString(m));
     }

   string account = AccountInfoString(ACCOUNT_CURRENCY);
   string current = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);

   if(current != account)
     {
      if(!_Convert(current, account, ask, result, moment))
         return 0;
     }

   return result;
  }
//+------------------------------------------------------------------+
 
Aleksandr Slavskii #:

Le code est le suivant

Le résultat est le suivant

Quelqu'un a mal compté.


Voici ce que l'on trouve dans les nouvelles pour le début de 2024 (c'est-à-dire après l'écriture du livre) à propos de la version 4150 - https://www.metatrader5.com/en/releasenotes/terminal/2342.

Marge flottante par volume

Dans les paramètres du serveur et l'interface de spécification des symboles, ils ont ajouté la dépendance de la marge par rapport au volume.

Je n'ai pas trouvé comment accéder à ces propriétés à partir de MQL5.

Dans un courtier/instrument particulier, ce paramètre de marge flottante peut ne pas être activé, c'est pourquoi je n'ai pas vu de différence lorsque je n'ai pas vérifié sur MQ demo.

MetaTrader 5 build 4150: Trading report export and new machine learning methods in MQL5
MetaTrader 5 build 4150: Trading report export and new machine learning methods in MQL5
  • 2024.01.18
  • MetaQuotes
  • www.metatrader5.com
Added export of trading reports to HTML and PDF files. With this option, you can easily share your trading achievements with colleagues and investors. New export commands are available in the File menu and in the report menu. Added ability to save the current state of the Market Watch window to a CSV file. To do this, select Export in the...
 
Stanislav Korotky #:

Ajout de la dépendance de la marge de volume aux paramètres du serveur et à l'interface de spécification des symboles.

Je n'ai pas trouvé comment accéder à ces propriétés à partir de MQL5.

J'ai également cherché et je n'ai pas trouvé non plus)
Je pensais qu'il s'agissait d'un bogue dans ma tête, mais ce n'est pas le cas.
Merci de votre compréhension.
 

@Renat Fatkhullin

Est-il prévu d'ajouter la possibilité d'obtenir ces propriétés depuis MQL5 ?

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

Expert Advisors : MQL5 Programming for Traders - codes sources du livre. Partie 7

Stanislav Korotky, 2024.11.23 20:26

J'ai trouvé dans les nouvelles du début de 2024 (c'est-à-dire après l'écriture du livre) la version 4150 - https://www.metatrader5.com/en/releasenotes/terminal/2342.

Marge flottante par volume

Dans les paramètres du serveur et l'interface de spécification des symboles, ils ont ajouté la dépendance de la marge sur le volume.

Je n'ai pas trouvé comment accéder à ces propriétés à partir de MQL5.

Dans un courtier/instrument particulier, ce paramètre de marge flottante peut ne pas être activé, c'est pourquoi je n'ai pas vu de différence lorsque je n'ai pas vérifié sur MQ demo.