Fonctions de gestion monétaire dans un Expert Advisor
Introduction
Le langage MQL5 permet d'obtenir une grande quantité d'informations sur les conditions du terminal actuelles, du programme mql5, ainsi que sur l'instrument financier et le compte de trading. Afin d’organiser les fonctions de gestion du capital, nous devrons étudier les propriétés des deux dernières sections énumérées, ainsi que nous familiariser avec les fonctions suivantes:
- SymbolInfoInteger()
- SymbolInfoDouble()
- SymbolInfoString()
- AccountInfoInteger()
- AccountInfoDouble()
- AccountInfoString()
Obtention d’informations sur le solde de votre compte
Les deux premières caractéristiques importantes d’un compte de trading - le solde et les capitaux propres. Pour obtenir ces valeurs, utilisez la fonction AccountInfoDouble() :
double balance=AccountInfoDouble(ACCOUNT_BALANCE); double equity=AccountInfoDouble(ACCOUNT_EQUITY);
La prochaine chose qui nous intéresse, c’est la taille des fonds de dépôt pour les positions ouvertes, et le total des profits ou pertes flottants sur le compte, pour toutes les positions ouvertes.
double margin=AccountInfoDouble(ACCOUNT_MARGIN); double float_profit=AccountInfoDouble(ACCOUNT_PROFIT);
Afin de pouvoir ouvrir de nouvelles positions ou renforcer celles existantes, nous avons besoin de ressources gratuites, ne participant pas au dépôt.
double free_margin=AccountInfoDouble(ACCOUNT_FREEMARGIN);
Ici, il convient de noter que les valeurs ci-dessus sont exprimées en termes monétaires.
Les valeurs monétaires, renvoyées par la fonction AccountInfoDouble(), sont exprimées en monnaie scripturale. Pour connaître la monnaie scripturale, utilisez la fonction AccountInfoString().
string account_currency=AccountInfoString(ACCOUNT_CURRENCY);
Le niveau des fonds personnels
Le compte a une autre caractéristique importante - le niveau auquel l’événement Stop Out se produit (une fermeture obligatoire d’une position en raison d’un manque de fonds personnels nécessaires au maintien des positions ouvertes). Pour obtenir cette valeur, réutilisez la fonction AccountInfoDouble() :
double stopout_level=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO);
La fonction renvoie uniquement la valeur elle-même, mais elle n’explique pas dans quel type d’unités cette valeur est exprimée. Il existe deux modes de spécification de niveau pour Stop Out : en pourcentage et en devise. Pour le savoir, utilisez la fonction AccountInfoInteger() :
//--- Get account currency string account_currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Stop Out level double stopout_level=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); //--- Stop Out mode ENUM_ACCOUNT_STOPOUT_MODE so_mode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); if(so_mode==ACCOUNT_STOPOUT_MODE_PERCENT) PrintFormat("Stop Out level in percents %.2f%%",stopout_level); else PrintFormat("Stop Out level in currency %.2f %s",stopout_level,account_currency);
Informations supplémentaires sur le compte
Souvent, dans les calculs, il fallait connaître la taille de l’effet de levier fourni sur le compte de trading. Vous pouvez obtenir ces informations à l’aide de la fonction AccountInfoInteger() :
int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE);Afin d’éviter d’exécuter accidentellement l’Expert Advisor non réglementé sur un compte réel, vous devez connaître le type de compte.
ENUM_ACCOUNT_TRADE_MODE mode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE); switch(mode) { case ACCOUNT_TRADE_MODE_DEMO: Comment("Account demo"); break; case ACCOUNT_TRADE_MODE_CONTEST: Comment(com,"Account Contest"); break; case ACCOUNT_TRADE_MODE_REAL: Comment(com,"Account Real"); break; default: Comment(com,"Account unknown type"); }Le trading n’est pas possible sur tous les comptes, par exemple, sur des comptes concurrents, les opérations de trading ne peuvent être effectuées qu’après le début de la compétition. Ces informations peuvent également être obtenues par la fonction AccountInfoInteger() :
bool trade_allowed=(bool)AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); if(trade_allowed) Print("Trade is allowed"); else Print(com,"Trade is not allowed");
Même si le trading sur ce compte est autorisé, cela ne signifie pas que l’Expert Advisor a le droit de trader. Pour vérifier si l’Expert Advisor est autorisé à trader, écrivez :
if(trade_allowed) { bool trade_expert=(bool)AccountInfoInteger(ACCOUNT_TRADE_EXPERT); if(trade_expert) Print("Experts are allowed to trade"); else Print("Experts are not allowed to trade");
Ces exemples se trouvent dans l’Expert Advisor ci-joint Account_Info.mq5. Ils peuvent être utilisés dans n’importe quels programmes MQL5 complexes.
Informations sur l’instrument
Chaque instrument financier a ses propres descriptions et est placé sur un chemin, que cet instrument caractérise. Si nous ouvrons la fenêtre des propriétés EURUSD dans le terminal, nous verrons quelque chose comme ceci:
Dans ce cas, la description de EURUSD est - « EURUSD, Euro vs US Dollar ». Pour obtenir ces informations, nous utilisons la fonction SymbolInfoString() :
string symbol=SymbolInfoString(_Symbol,SYMBOL_DESCRIPTION); Print("Symbol: "+symbol); string symbol_path=SymbolInfoString(_Symbol,SYMBOL_PATH); Print("Path: "+symbol_path);
Pour connaître la taille d’un contrat standard, utilisez symbolInfoDouble() :
double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE); Print("Standard contract: "+DoubleToString(lot_size,2));
C’est une caractéristique des instruments FOREX de vendre une devise tout en achetant une autre. Le contrat est indiqué dans la devise, ce qui est nécessaire pour effectuer l’achat. Il s’agit d’une devise de base, qui peut être obtenue à l’aide de la fonction SymbolInfoString() :
string base_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE); Print("Base currency: "+base_currency);
Les variations de prix de l’instrument entraînent une variation du prix d’un actif acheté et, par conséquent, une variation du bénéfice pour une position ouverte (le profit peut être négatif si la position est perdante). Ainsi, le changement de prix entraîne des changements de revenu, exprimés dans une devise particulière. Cette devise est appelée la devise de cotation. Pour une paire de devises EURUSD, la devise de base est généralement l’euro et la devise de cotation est le dollar américain. Pour obtenir la devise de cotation, vous pouvez également utiliser la fonction SymbolInfoString() :
string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT); Print("Currency quotes: "+profit_currency);
Pour ouvrir une position sur l’instrument, vous avez besoin de fonds, et ces fonds sont également exprimés dans une devise particulière. Cette devise est appelée marge de change ou dépôt. Pour les instruments FOREX, la marge et les devises de base sont généralement les mêmes. Pour obtenir la valeur de la monnaie scripturale, utilisez la fonction SymbolInfoString() :
string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN); Print("Currency deposit: "+margin_currency);
Toutes les fonctions décrites sont données dans le code de l’Expert Advisor Symbol_Info.mq5. La figure ci-dessous illustre la sortie d’informations sur le symbole EURUSD, à l’aide de la fonction Comment().
Calcul du montant du dépôt
Les informations sur les instruments financiers, les plus nécessaires pour les traders, sont la taille des fonds, nécessaires pour ouvrir une position sur celui-ci. Sans savoir combien d’argent est nécessaire pour acheter ou vendre un nombre spécifié de lots, nous ne pouvons pas mettre en œuvre le système de gestion du capital de l’Expert Advisor. En outre, le contrôle du solde du compte devient également difficile.
Si vous avez des difficultés à comprendre la suite de la discussion, je vous recommande de lire l’article Forex Trading ABC. Les explications qui y sont décrites sont également applicables à cet article.
Nous devons calculer la taille de la marge dans le dépôt en devises, c’est-à-dire recalculer le dépôt de la devise hypothécaire à la devise de dépôt, en divisant la valeur obtenue par le montant de l’effet de levier du compte donné. Pour ce faire, nous écrivons la fonction GetMarginForOpening()://+------------------------------------------------------------------+ //| Return amount of equity needed to open position | //+------------------------------------------------------------------+ double GetMarginForOpening(double lot,string symbol,ENUM_POSITION_TYPE direction) { double answer=0; //--- ... //--- Return result - amount of equity in account currency, required to open position in specified volume return(answer); }
Où :
- lot - le volume de la position ouverte ;
- symbol - nom de l'instrument financier
- la direction de position prétendue.
- monnaie scripturale
- devise hypothécaire
- Cotations de devises (peuvent être nécessaires pour les paires de devises croisées)
- Taille de contrat
Écrivez ceci dans le langage MQL5 :
//--- Get contract size double lot_size=SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE); //--- Get account currency string account_currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Margin currency string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN); //--- Profit currency string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT); //--- Calculation currency string calc_currency=""; //--- Reverse quote - true, Direct quote - false bool mode;
La variable de mode affecte la façon dont nous calculerons la taille du contrat dans la monnaie scripturale. Considérez cela sur la base d’exemples, dans tous les autres cas, supposons que la monnaie scripturale est le dollar américain.
Les paires de devises sont généralement divisées en trois catégories :
- Paires de devises directes - le taux de change du dollar américain à une devise particulière. Exemples : USDCHF, USDCAD, USDJPY, USDSEK ;
- Reverse Currency Pair - le taux de change d’une devise particulière par rapport au dollar américain. Exemples : EURUSD, GBPUSD, AUDUSD, NZDUSD ;
- Cross Currency Pairs - une paire de devises, qui n’implique pas le dollar américain. Exemples : AUDCAD, EURJPY, EURCAD.
1. EURUSD - la paire de devises inversée
Nous appellerons les paires de devises, dans lesquelles la devise de cotation est la devise du compte, paires de devises inversées. Dans nos exemples, la devise du compte est représentée par le dollar américain, de sorte que notre classification des paires de devises coïncidera avec la classification généralement acceptée. Mais si votre compte de trading utilise une devise différente (pas USD), cela ne coïncidera pas. Dans ce cas, prenez en considération la devise du compte, afin de comprendre toute explication supplémentaire.
La taille du contrat pour EURUSD - 100 000 euros. Nous devons exprimer 100 000 euros dans la devise du dépôt - dollars américains. Pour ce faire, vous devez connaître le taux de change, selon lequel l’euro peut être compté en dollars. Nous introduisons le concept de monnaie de calcul, c’est-à-dire la devise nécessaire à la conversion de la devise hypothécaire en monnaie scripturale.
//--- Calculation currency string calc_currency="";
Heureusement, la paire de devises EURUSD affiche le taux de change de l’euro par rapport au dollar, et donc, dans ce cas, le symbole de l’EURUSD, pour lequel vous devez calculer la taille de l’hypothèque, est précisément le taux de change:
//--- If profit currency and account currency are equal if(profit_currency==account_currency) { calc_currency=symbol; mode=true; }
Nous avons établi la valeur du mode comme vrai, ce qui signifie que pour transférer des euros en dollars (la monnaie hypothéquée est convertible en monnaie scripturale), nous multiplierons le taux de change actuel de l’EURUSD par la taille du contrat. Si mode = false, alors nous divisons la taille du contrat par le taux de change de la devise de calcul. Pour obtenir les prix actuels sur l’instrument, utilisez la fonction SymbolInfoTick().
//--- We know calculation currency, let's get its last prices MqlTick tick; SymbolInfoTick(calc_currency,tick);
Cette fonction place le prix actuel et l’heure de la dernière mise à jour des prix dans la variable du type MqlTick -cette structure a été spécialement conçue à cet effet.
Il suffit donc d’obtenir le dernier prix sur ce symbole, de le multiplier par la taille du contrat puis par le nombre de lots. Mais quel prix de calcul devrions-nous prendre, étant donné qu’il existe un prix d’achat et un prix de vente pour cet instrument ? donc logiquement : si nous achetons, le prix pour les calculs est égal au prix Ask, et si nous vendons, nous devrons prendre le prix Bid.
//--- Now we have everything for calculation double calc_price; //--- Calculate for Buy if(direction==POSITION_TYPE_BUY) { //--- Reverse quote if(mode) { //--- Calculate using Buy price for reverse quote calc_price=tick.ask; answer=lot*lot_size*calc_price; } } //--- calculate for Sell if(direction==POSITION_TYPE_SELL) { //--- Reverse quote if(mode) { //--- Calculate using Sell price for reverse quote calc_price=tick.bid; answer=lot*lot_size*calc_price; } }
Ainsi, dans notre exemple, pour le symbole EURUSD, la devise de dépôt est l’euro, la taille du contrat est de 100 000 et le dernier prix Ask = 1,2500. Devise du compte - Dollar américain, et la devise de calcul est la même paire de devises EURUSD. Multipliez 100 000 par 1,2500 et obtenez 125 000 dollars américains - c’est exactement le montant d’un contrat standard pour l’achat de 1 lot EURUSD, si le prix Ask = 1,2500.
Nous pouvons conclure que si la devise de cotation est égale à la devise du compte, alors pour obtenir la valeur d’un lot de la devise du compte, nous multiplions simplement la taille du contrat par le prix approprié, Bid ou Ask, en fonction de la direction prévue de la position.
margin=lots*lot_size*rate/leverage;
2. USDCHF - paire de devises directes
La devise hypothécaire et la devise du compte pour USDCHF correspondent - le dollar américain. Les paires de devises, dans lesquelles la devise hypothécaire et la devise du compte sont les mêmes, nous les appellerons paires de devises directes. Taille du contrat - 100 000. C’est la situation la plus simple, il suffit de retourner le produit.
//--- if the base currency symbol and the deposit currency are the same if(margin_currency==account_currency) { calc_currency=symbol; //--- Just return the contract value, multiplied by the number of lots return(lot*lot_size); }
Si la monnaie scripturale coïncide avec la devise du compte, la valeur du dépôt dans la devise du compte est égale au produit du contrat standard multiplié par le nombre de lots (contrats) divisé par la taille de l’effet de levier.
margin=lots*lot_size/leverage;
3. CADCHF - paire de devises croisées
La paire de devises CADCHF est prise à des fins d’illustration, et toute autre paire, dans laquelle la devise de dépôt et la devise de cotation coïncident avec la devise du compte, peut être utilisée. Ces paires de devises sont appelées croisées, car pour calculer la marge et le profit sur elles, nous devons connaître le taux de change d’une autre paire de devises, qui se croise avec celle sur l’une des devises.
Habituellement, les paires de devises croisées sont les paires dont les cotations n’utilisent pas le dollar américain. Mais nous appellerons toutes les paires, qui n’incluent pas la devise du compte dans ses cotations, paires de devises croisées. Ainsi, si la devise du compte est en euro, la paire GBPUSD sera une paire de devises croisées, car la monnaie scripturale est en livres sterling et les cotations des devises sont en dollars américains. Dans ce cas, pour calculer la marge, nous devrons exprimer la livre (GBP) en Euro (EUR).
Mais nous continuerons à considérer un exemple dans lequel le symbole est la paire de devises CADCHF. La monnaie scripturale est en dollars canadiens (CAD) et ne coïncide pas avec le dollar américain (USD). La devise de cotation est en francs suisses et ne coïncide pas non plus avec le dollar américain.
On peut seulement dire que le dépôt pour l’ouverture d’une position en 1 lot équivaut à 100 000 dollars canadiens. Notre tâche consiste à recalculer le dépôt dans la devise du compte, en dollars américains. Pour ce faire, nous devons trouver la paire de devises, dont le taux de change contient le dollar américain et la monnaie scripturale - CAD. Il y a un total de deux options potentielles :
- CADUSD
- USDCAD
Nous avons les données de sortie pour le CADCHF :
margin_currency=CAD (Canadian dollar) profit_currency=CHF (Swiss frank)
Nous ne savons pas à l’avance laquelle des paires de devises existe dans le terminal, et en termes de langage MQL5, aucune des deux options n’est préférable. Par conséquent, nous écrivons la fonction GetSymbolByCurrencies(), qui pour l’ensemble donné de devises nous donnera la première correspondance de paire de devises pour les calculs.
//+------------------------------------------------------------------+ //| Return symbol with specified margin currency and profit currency | //+------------------------------------------------------------------+ string GetSymbolByCurrencies(string margin_currency,string profit_currency) { //--- In loop process all symbols, that are shown in Market Watch window for(int s=0;s<SymbolsTotal(true);s++) { //--- Get symbol name by number in Market Watch window string symbolname=SymbolName(s,true); //--- Get margin currency string m_cur=SymbolInfoString(symbolname,SYMBOL_CURRENCY_MARGIN); //--- Get profit currency (profit on price change) string p_cur=SymbolInfoString(symbolname,SYMBOL_CURRENCY_PROFIT); //--- if If symbol matches both currencies, return symbol name if(m_cur==margin_currency && p_cur==profit_currency) return(symbolname); } return(NULL); }
Comme on peut le voir dans le code, nous commençons l’énumération de tous les symboles, disponibles dans la fenêtre « Market View » (la fonctionSymbolsTotal() avec le paramètre « true » nous donnera ce montant). Afin d’obtenir le nom de chaque symbole par le numéro dans la liste de la « Market View », nous utilisons la fonction SymbolName() avec le paramètre true ! Si nous définissons le paramètre sur « false », nous énumérerons tous les symboles présentés sur le serveur de trading, et c’est généralement beaucoup plus que ce qui est sélectionné dans le terminal.
Ensuite, nous utilisons le nom du symbole pour obtenir la monnaie scripturale et les cotations, et pour les comparer avec celles qui ont été transmises à la fonction GetSymbolByCurrencies(). En cas de succès, nous retournons le nom du symbole et le travail de la fonction est terminé avec succès et en avance sur le calendrier. Si la boucle est terminée et que nous atteignons la dernière ligne de la fonction, rien ne correspond et le symbole n’a pas été trouvé, - renvoyez NULL.
Maintenant que nous pouvons obtenir la devise de calcul pour la paire de devises croisées, en utilisant la fonction GetSymbolByCurrencies(), nous allons essayer deux tentatives : dans la première tentative, nous allons rechercher le symbole, dont la devise de dépôt est la margin_currency (devise de dépôt CADCHF - CAD), et la devise de cotation est la devise du compte (USD). En d’autres termes, nous recherchons quelque chose de similaire à la paire de CADUSD.
//--- If calculation currency is still not determined //--- then we have cross currency if(calc_currency="") { calc_currency=GetSymbolByCurrencies(margin_currency,account_currency); mode=true; //--- If obtained value is equal to NULL, then this symbol is not found if(calc_currency==NULL) { //--- Lets try to do it reverse calc_currency=GetSymbolByCurrencies(account_currency,margin_currency); mode=false; } }
Si la tentative échoue, essayez de trouver une autre option: recherchez un symbole dont la monnaie scripturale est account_currency (USD) et la devise de cotation est margin_currency (devise de dépôt pour CADCHF - CAD). Nous recherchons quelque chose de similaire à l’USDCAD.
Maintenant que nous avons trouvé la paire de devises de calcul, il peut s’agir de l’une des deux options - directe ou inversée. La variable mode suppose la valeur « true » pour la paire de devises inverse. Si nous avons une paire de devises directes, la valeur est égale à « false ». Pour la « vraie » valeur, nous la multiplions par le taux de change de la paire de devises, pour la fausse valeur - nous la divisons par la valeur de dépôt d’un contrat standard dans la devise du compte.
Voici le calcul final de la taille du dépôt dans la devise du compte pour la devise de calcul trouvée. Il convient aux deux options - les paires de devises directes et inversées.
//--- We know calculation currency, let's get its last prices MqlTick tick; SymbolInfoTick(calc_currency,tick); //--- Now we have everything for calculation double calc_price; //--- Calculate for Buy if(direction==POSITION_TYPE_BUY) { //--- Reverse quote if(mode) { //--- Calculate using Buy price for reverse quote calc_price=tick.ask; answer=lot*lot_size*calc_price; } //--- Direct quote else { //--- Calculate using Sell price for direct quote calc_price=tick.bid; answer=lot*lot_size/calc_price; } } //--- Calculate for Sell if(direction==POSITION_TYPE_SELL) { //--- Reverse quote if(mode) { //--- Calculate using Sell price for reverse quote calc_price=tick.bid; answer=lot*lot_size*calc_price; } //--- Direct quote else { //--- Calculate using Buy price for direct quote calc_price=tick.ask; answer=lot*lot_size/calc_price; } }
Retour au résultat obtenu
//--- Return result - amount of equity in account currency, required to open position in specified volume return (Answer);
La fonction GetMarginForOpening() termine son travail à ce stade. La dernière chose à faire est de diviser la valeur obtenue par la taille de l’effet de levier fourni - et ensuite nous obtiendrons la valeur de la marge pour les positions ouvertes avec le volume spécifié dans la direction supposée. Gardez à l’esprit que pour les symboles, représentant l’inverse ou la paire de devises croisées, la valeur de la marge variera à chaque trait.
Voici une partie du code expert Advisor SymbolInfo_Advanced.mq5. Le code complet est joint sous forme de fichier.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- String variable for comment string com="\r\n"; StringAdd(com,Symbol()); StringAdd(com,"\r\n"); //--- Size of standard contract double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE); //--- Margin currency string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN); StringAdd(com,StringFormat("Standard contract: %.2f %s",lot_size,margin_currency)); StringAdd(com,"\r\n"); //--- Leverage int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE); StringAdd(com,StringFormat("Leverage: 1/%d",leverage)); StringAdd(com,"\r\n"); //--- Calculate value of contract in account currency StringAdd(com,"Deposit for opening positions in 1 lot consists "); //--- Calculate margin using leverage double margin=GetMarginForOpening(1,Symbol(),POSITION_TYPE_BUY)/leverage; StringAdd(com,DoubleToString(margin,2)); StringAdd(com," "+AccountInfoString(ACCOUNT_CURRENCY)); Comment(com); }
et le résultat de son travail sur le graphique.
Conclusion
Les exemples fournis montrent à quel point il est facile et simple d’obtenir des informations sur les caractéristiques les plus importantes du compte de trading et sur les propriétés des instruments financiers.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/113
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation