Assistant MQL5 : Comment Créer un Module de Gestion des Risques et de fonds
Introduction
MetaTrader 5 fournit un outil puissant qui vous permet de vérifier rapidement diverses idées de trading. Il s'agit d'une génération d’Expert Advisors utilisant l'assistantMQL5 Wizard sur la base de stratégies de trading prêtes.
Un Expert Advisor créé avec le MQL5 Wizard, est basé sur quatre piliers-quatre classes de base:
Figure 1. La structure de la classe de base CExpert
- La classeCExpert (ou sa sous-classe) est le "moteur" principal d'un Expert Advisor. Une instance de CExpert comporte une copie de chaque classe : CExpertSignal, CExpertMoney and CExpertTrailing(ou leurs sous-classes) :
- CExpertSignal est la base du générateur de signaux de trading. Une instance de la classe dérivéeCExpertSignal , comprise dansCExpert, fournit à un Expert Advisor des informations sur la possibilité d'entrer sur le marché, les niveaux d'entrée et l’émission d'ordonnances conservatoires, sur la base d'algorithmes intégrés. L'Expert Advisor décide d'entrer ou non sur le marché. Plus de détails sur la classeCExpertSignal et son utilisation sont décrits dans l'article"MQL5 Wizard: Comment créer un module de signaux de trading".
- La classe CExpertMoney est la base du mécanisme de gestion des risques et de fonds. Une instance de la classe dérivéeCExpertMoney , incluse dans CExpert, fournit à un Expert Advisor des informations sur les volumes possibles pour l'ouverture de positions et l’émission de commandes en cours, sur la base d'algorithmes intégrés. L'Expert Advisor prend une décision sur le volume.
- La classeCExpertTrailing est la base du mécanisme de support de position ouverte. Une instance de la classe dérivéeCExpertTrailing , comprise dans CExpert , fournit à un EA des informations sur la possibilité de modifier les ordonnances conservatoires de la position, sur la base d'algorithmes intégrés. L'Expert Advisor prend une décision sur la modification des commandes. Plus de détails sur la classe CExpertTrailing et son utilisation seront décrits dans un article séparé.
De plus, les membres de la classeCExpert sont des instances des classes suivantes :
- CExpertTrade (pour le trading)
- CIndicators (pour contrôler les indicateurs et les séries chronologiques impliqués dans le travail de l'AE).
- CSymbolInfo(pour obtenir des informations sur l'instrument)
- CAccountInfo (pour obtenir des informations sur l'état du compte de trading)
- CPositionInfo (pour obtenir des informations sur les position)
- COrderInfo (pour obtenir des informations sur les commandes en cours)
Ci-après, sous "expert", nous entendons une instance de CExpert ou de sa sous-classe.
Plus de détails sur CExpert et son utilisation seront décrits dans un article séparé.
1. Classe de base CExpertMoney
Comme mentionné ci-dessus, la classe CExpertMoney est la base du mécanisme de gestion des risques et de l'argent. Pour communiquer avec le "monde extérieur", la classe CExpertMoney dispose d'un ensemble de méthode virtuelle publique :
Initialisation | Description |
virtual Init | L'initialisation de l'instance de classe assure la synchronisation des données du module avec les données de l' EA |
Réglage de la valeur du paramètre "Pourcentage de risque" | |
virtuel ValidationSettings | Validation des paramètres réglés |
virtual InitIndicators | Création et initialisation de tous les indicateurs et séries chronologiques nécessaires au fonctionnement du mécanisme de gestion des risques et de l'argent |
Méthodes de vérification de la nécessité d'ouvrir/tourner/clôturer une position |
|
virtual CheckOpenLong | Déterminer le volume pour ouvrir une longue position |
virtual CheckOpenShort | Déterminer le volume pour ouvrir une courte |
virtual CheckReverse | Déterminer le volume pour l'inversion d'une position |
virtual CheckClose | Déterminer la nécessité de clôturer une position |
Description des Méthodes
1.1. Méthodes d'initialisation
1.1.1 Init
La méthodeInit() est appelée automatiquement après que l’instance de classe aie été ajouté à l’expert. Le dépassement de méthode n'est pas requis..
virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);
1.1.2 Pourcentage
La méthodePercent() est appelée pour configurer le paramètre approprié. Sa valeur peut être comprise entre 0,0 et 100,0 inclus. La valeur par défaut est 100.0. Le dépassement de méthode n'est pas requis..
void Percent(double percent);
1.1.3 ValidationSettings
La méthodeValidationSettings() est directement appelée par l'expert une fois tous les paramètres définis. Vous devez dépasser la méthode s'il existe des paramètres de configuration supplémentaires.
virtual bool ValidationSettings();
La méthode dépassée doit renvoyer true, si toutes les options sont valides (utilisables). Si au moins un des paramètres est incorrect, il doit renvoyer false (la poursuite du travail est impossible). La méthode dépassée doit appeler la méthode de la classe de base avec la vérification du résultat.
1.1.4 InitIndicators
La méthodeInitIndicators() implémente la création et l'initialisation de tous les indicateurs et séries chronologiques nécessaires. Il est appelé par l'expert une fois tous les paramètres définis et leur exactitude vérifiée avec succès. La méthode doit être dépassée si le mécanisme de gestion des risques et de l'argent utilise au moins un indicateur ou une série chronologique.
virtual bool InitIndicators(CIndicators* indicators);
Les indicateurs et/ou les séries chronologiques doivent être utilisés dans les classes appropriées de laBibliothèque Standard Les pointeurs de tous les indicateurs et/ou séries chronologiques doivent être ajoutés à la collection d'indicateurs d'un expert (un pointeur à travers duquel est transmis en paramètre).
La méthode dépassée doit renvoyer true, si toutes les manipulations avec les indicateurs et/ou les séries chronologiques ont réussi (ils sont prêts à l’emploi). Si au moins une opération avec les indicateurs et/ou les séries chronologiques a échoué, la méthode doit renvoyer false (la poursuite du travail est impossible).
1.2. Méthodes pour déterminer le volume d'une position
1.2.1 CheckOpenLong
La méthodeCheckOpenLong() calcule le volume d'ouverture d'une longue position. Il est appelé par un expert pour déterminer le volume d'ouverture d'une longue position. La méthode doit être dépassée si vous prévoyez de calculer le volume d'ouverture d’une longue position en utilisant l'algorithme qui diffère de celui implémenté dans la classe de base.
\virtual double CheckOpenLong(double price, double sl);
La méthode doit implémenter l'algorithme de calcul du volume d'ouverture d'une longue position. La méthode doit renvoyer le volume calculé.
1.2.2 CheckOpenShort
La méthodeCheckOpenShort() calcule le volume d'ouverture d'une position courte. Il est appelé par un expert pour déterminer le volume d'ouverture d'une position courte. La méthode doit être dépassée si vous prévoyez de calculer le volume d'ouverture des courtes positions à l'aide d'un algorithme différent de celui implémenté dans la classe de base.
virtual double CheckOpenShort(double price, double sl);
La méthode doit implémenter l'algorithme de calcul du volume d'ouverture d'une position courte. La méthode doit renvoyer le volume calculé.
1.2.3 CheckReverse
La méthodeCheckReverse() calcule le volume d'inversion d'une position. Il est appelé par un expert pour déterminer le volume d'une opération de commerce pour renverser une position. La méthode doit être dépassée, si vous prévoyez de calculer le volume d'inversion de position en utilisant l'algorithme qui diffère de celui implémenté dans la classe de base (par exemple, inversion avec un double volume).
virtual double CheckReverse(CPositionInfo* position, double sl);
La méthode doit implémenter l'algorithme de calcul du volume pour inverser une position, dont l'information peut être obtenue par le pointeur deposition La méthode doit renvoyer le volume calculé pour l'inversion de position.
1.2.4 CheckClose
Les méthodesCheckClose() vérifient s'il est nécessaire de clôturer une position (en termes de gestion d’argent et de gestion des risques). Il est appelé par un expert pour déterminer s'il est nécessaire de clôturer une position. La méthode doit être dépassée si vous prévoyez de fermer une position en utilisant un algorithme différent de celui implémenté dans la classe de base (par exemple, fermeture partielle).
virtual double CheckClose(CPositionInfo* position);
La méthode doit implémenter l'algorithme de définition de la nécessité de clôturer une position, dont l'information peut être obtenue par le pointeur de position. La méthode doit renvoyer le volume calculé pour la clôture de la position.
2. Créer un Mécanisme de Gestion de l'Argent et des Risques
Maintenant, après avoir examiné la structure de la classe de baseCExpertMoney , vous pouvez commencer à créer votre propre mécanisme de gestion des risques et de fonds. Ci-après, le mécanisme de gestion des risques et de fonds sera dénommé « gestionnaire de fonds ».
Comme mentionné ci-dessus, la classe CExpertMoneyest un ensemble de "cordes" virtuelles publiques - des méthodes, à l'aide desquelles l'expert peut connaître l'opinion du gestionnaire de fonds sur le volume de marché entrant dans un sens ou dans un autre.
Par conséquent, notre objectif principal est de créer notre propre classe de gestionnaire d'argent, en la dérivant de la classeCExpertMoney et en remplaçant les méthodes virtuelles appropriées, en implémentant les algorithmes requis.
Notre deuxième problème (qui n'est pas moins important) - rendre notre classe "visible" àMQL5 Wizard. Mais, tout d'abord.
2.1. Création de la classe du générateur de signaux de trading
Commençons.
Tout d'abord, nous créons (par exemple, en utilisant le mêmeMQL5 Wizard) un fichier d'inclusion avec l'extension mqh.
Dans le menu Fichier sélectionnez "Créer" (ou appuyez sur la combinaison de touches Ctrl+N) et indiquez la création d'un fichier inclus :
Figure 2. Créez un fichier d'inclusion à l'aide de l'assistant MQL5
A noter que pour que le fichier soit ensuite "détecté" parMQL5 Wizard en tant que gestionnaire de fonds, il doit être créé dans le dossier Inclure\Expert.
Afin de ne pas jeter la corbeille dans laBibliothèque Standard,créez notre propre dossier Include\Expert\Money\MyMoneys, dans lequel nous créons le fichier SampleMoney.mqh, en indiquant ces paramètres dans l'assistant MQL5 :
Figure 3. Définition de l'emplacement du fichier d'inclusion
À la suite de l'opération de l'assistantMQL5, nous avons le modèle suivant :
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ // #define MacrosHello "Hello, world!" // #define MacrosYear 2010 //+------------------------------------------------------------------+ //| DLL imports | //+------------------------------------------------------------------+ // #import "user32.dll" // int SendMessageA(int hWnd,int Msg,int wParam,int lParam); // #import "my_expert.dll" // int ExpertRecalculate(int wParam,int lParam); // #import //+------------------------------------------------------------------+ //| EX5 imports | //+------------------------------------------------------------------+ // #import "stdlib.ex5" // string ErrorDescription(int error_code); // #import //+------------------------------------------------------------------+
Ce qui suit n'est qu'un travail "manuel". Supprimez les parties inutiles et ajoutez ce qui est requis - le fichier d'inclusion ExpertMoney.mqh de la Bibliothèque Standard avec une description de classe vide.
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { }; //+------------------------------------------------------------------+
Il faut maintenant choisir les algorithmes.
Comme base pour notre gestionnaire de fonds, nous prenons l'algorithme suivant : Dans les conditions "normales", il est proposé d'utiliser un volume du deal fixe et prédéterminé. Mais si la position précédente a été clôturée avec une perte, il est proposé d'ouvrir une position avec un volume doublé.
Reflétez cela dans notre fichier.
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { }; //+------------------------------------------------------------------+
Définissez une liste de paramètres pour notre gestionnaire de fonds. En fait, il n'y aura pas de liste. Tous les paramètres sont compris dans un seul paramètre qui déterminera le volume d'une transaction dans des conditions "normales".
Le paramètre sera stocké dans une donnée membre protégée de la classe. L'accès au paramètre sera implémenté par une méthode publique appropriée. Dans le constructeur de classe, le paramètre sera initialisé par une valeur par défaut. Pour vérifier les paramètres, dépassons la méthode virtuelle ValidationSettings en fonction de la description de la classe de base.
Incluons ces modifications dans notre fichier :
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { protected: //--- setup parameters double m_lots; // deal volume for "normal" conditions public: CSampleMoney(); //--- methods to set the parameters void Lots(double lots) { m_lots=lots; } }; //+------------------------------------------------------------------+ //| Constructor CSampleMoney. | //| INPUT: no. | //| OUTPUT: no. | //| REMARK: no. | //+------------------------------------------------------------------+ void CSampleMoney::CSampleMoney() { //--- setting the default values m_lots=0.1; } //+------------------------------------------------------------------+
Séparément, voyons comment implémenter la méthode ValidationSettings(). Le fait est que la classe de base dispose déjà d’un paramètre de configuration, qui nécessite également une vérification.
Implémentation de la méthode ValidationSettings() :
//+------------------------------------------------------------------+ //| Validation of the setup parameters. | //| INPUT: no. | //| OUTPUT: true if the settings are correct, otherwise false. | //| REMARK: no. | //+------------------------------------------------------------------+ bool CSampleMoney::ValidationSettings() { //--- Call the base class method if(!CExpertMoney::ValidationSettings()) return(false); //--- Validation of parameters if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax()) { printf(__FUNCTION__+": the deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10) { printf(__FUNCTION__+": the volume of the deal must be multiple of %f",m_symbol.LotsStep()); return(false); } //--- Successful completion return(true); }
Les paramètres sont prêts, passons maintenant au fonctionnement du gestionnaire d’argent. Nous avons besoin d'une méthode qui permettra de déterminer si le deal précédent était perdant et, si nécessaire, de définir son volume. Déclarez-le dans la description de la classe :
class CSampleMoney : public CExpertMoney { protected: //--- Setup parameters double m_lots; // deal volume for "normal" conditions public: CSampleMoney(); //--- Methods to set parameters void Lots(double lots) { m_lots=lots; } //--- Methods to validate parameters virtual bool ValidationSettings(); protected: double CheckPrevLoss(); };
Implémentation de la méthode :
//+------------------------------------------------------------------+ //| Defines whether the prev. deal was losing. | //| INPUT: no. | //| OUTPUT: volume of the prev. deal if it's losing, otherwise 0.0 | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckPrevLoss() { double lot=0.0; //--- Request the history of deals and orders HistorySelect(0,TimeCurrent()); //--- variables int deals=HistoryDealsTotal(); // Total number of deals in the history CDealInfo deal; //--- Find the previous deal for(int i=deals-1;i>=0;i--) { if(!deal.SelectByIndex(i)) { printf(__FUNCTION__+": Error of deal selection by index"); break; } //--- Check the symbol if(deal.Symbol()!=m_symbol.Name()) continue; //--- Check the profit if(deal.Profit()<0.0) lot=deal.Volume(); break; } //--- Return the volume return(lot); }
Examinons à nouveau nos algorithmes plus en détail (bien qu'il soit déjà détaillé).
Sans entrer dans les nuances, notons que notre gestionnaire de fonds proposera d'augmenter le volume d'une opération dès réception de la perte du deal précédent. S'il n'y a pas eu de perte lors du deal précédent, nous vous proposerons d'ouvrir une position avec un volume fixe, défini par un certain paramètre.
À cette fin, nous dépassons les méthodes virtuelles ,CheckOpenLong et CheckOpenShort en les remplissant des fonctionnalités correspondantes.
Descriptif de la classe :
//+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { protected: //--- Setup parameters double m_lots; // Deal volume for "normal" conditions public: CSampleMoney(); //--- Methods to set the parameters void Lots(double lots) { m_lots=lots; } //--- Methods to validate the parameters virtual bool ValidationSettings(); //--- Methods to define the volume virtual double CheckOpenLong(double price,double sl); virtual double CheckOpenShort(double price,double sl); protected: double CheckPrevLoss(); };
Les implémentations de CheckOpenLong et CheckOpenShort sont pratiquement identiques. Les deux méthodes déterminent la nécessité d'augmenter le volume appelant la méthode CheckPrevLoss précédemment implémentée.
Ensuite, nous devons tenir compte du fait que nous ne pouvons pas augmenter le volume des trades indéfiniment. Il y a deux limitations sur le volume de position :
- Le volume maximal du deal pour le symbole, spécifié dans les paramètres du serveur (SYMBOL_VOLUME_MAX).
- Disponibilité du montant requis de fonds gratuits sur le dépôt.
Implementation des méthodes CheckOpenLong et CheckOpenShort:
//+------------------------------------------------------------------+ //| Defining the volume to open a long position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: not. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenLong(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Ask(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); } //+------------------------------------------------------------------+ //| Defining the volume to open a short position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenShort(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Bid(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); }
Nous avons donc résolu le premier problème. Le code ci-dessus est un "code source" de la classe gestionnaire de fonds qui satisfait notre tâche principale.
2.2. Création d'une description de la classe gestionnaire de fonds générée pour l'assistant MQL5
Passons maintenant à la résolution du deuxième problème. Notre gestionnaire de fonds devrait être "reconnu" par le générateur de stratégies de trading du MQL5 Wizard.
Nous avons fait la première condition nécessaire : nous avons placé le fichier là où il sera « trouvé » par l'assistant MQL5. Mais ce n'est pas assez. L'assistant MQL5 doit non seulement "trouver" le fichier, mais aussi le "reconnaître". Pour se fait, nous devons ajouter le texte original du descripteur de classe pour le MQL5 Wizard.
Examinons ces règles.
1. Le bloc de commentaires doit commencer par les lignes suivantes :
// wizard description start //+------------------------------------------------------------------+ //| Description of the class |
2. La ligne suivante est un descripteur de texte (ce que nous verrons dans l'assistant MQL5 lors du choix du signal) au format "//| Title=<Text> |". Si le texte est trop gros pour une ligne, vous pouvez ajouter une ligne supplémentaire (mais pas plus) après.
Dans notre cas, nous avons les éléments suivants :
//| Title=Trade with a doubling of lot after a loss |
3. Vient ensuite une ligne avec le type de classe spécifié au format "//| Type=<Type> |". Le champ <Type> doit disposer de la valeur Money (en plus des gestionnaires de fonds, l'assistant MQL5 connaît d'autres types de classes).
Écrivez:
//| Type=Money |
4. La ligne suivante au format "//| Name=<Name> |" est le nom court du signal (il est utilisé par l'assistant MQL5 pour générer les noms des variables globales de l'expert).
Nous obtenons ce qui suit :
//| Name=Sample |
5. Le nom d'une classe est un élément important de la description. Dans la ligne au format "//| Class=<ClassNameа> |", le paramètre <ClassName> doit correspondre au nom de notre classe :
//| Class=CSampleMoney |
6. Nous ne remplissons pas cette ligne, mais elle doit être présente (il s'agit d'un lien vers la section de référence de langue ):
//| Page= |
7. De plus, il y a des descriptions des paramètres de configuration du signal.
Il s'agit d'un ensemble de lignes (le nombre de lignes est égal au nombre de paramètres).
Le format de chaque ligne est "//| Parameter=<NameOfMethod>,<TypeOfParameter>,<DefaultValue> |".
Voici notre ensemble de paramètres :
//| Parameter=Lots,double,0.1 | //| Parameter=Percent,double,100.0 |
8. Le bloc de commentaire doit se terminer par les lignes suivantes :
//+------------------------------------------------------------------+ // wizard description end
2-7 Nous devons fournir davantage d'explications aux points 2-7. Les sections du descripteur de classe comportent des mots clés (Titre, Type, Nom, Classe, Page, Paramètre). Malheureusement,MQL5 Wizard ne peut pas interpréter toutes les combinaisons possibles de caractères dans le cadre de la description de la classe.
Par conséquent, pour éviter les erreurs inutiles, écrivez-le comme ceci :<Description> ne peut comprendre des espaces que pour le mot clé Titre. Les paragraphes 1 et 8 doivent être copiés "tels quels".
Ajoutons le descripteur au code source.
//+------------------------------------------------------------------+ //| SampleMoney.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Expert\ExpertMoney.mqh> #include <Trade\DealInfo.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Trading with lot doubling after a loss | //| Type=Money | //| Name=Sample | //| Class=CSampleMoney | //| Page= | //| Parameter=Lots,double,0.1 | //| Parameter=Percent,double,100.0 | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSampleMoney. | //| Purpose: Class for risk and money management | //| doubling the volume after a loss deal. | //| It is derived from the CExpertMoney class. | //+------------------------------------------------------------------+ class CSampleMoney : public CExpertMoney { protected: //--- Setup parameters double m_lots; // Deal volume for "normal" conditions public: CSampleMoney(); //--- Methods to set the parameters void Lots(double lots) { m_lots=lots; } //--- Methods to validate the parameters virtual bool ValidationSettings(); //--- Methods to define the volume virtual double CheckOpenLong(double price,double sl); virtual double CheckOpenShort(double price,double sl); protected: double CheckPrevLoss(); }; //+------------------------------------------------------------------+ //| Constructor CSampleMoney. | //| INPUT: no. | //| OUTPUT: no. | //| REMARK: no. | //+------------------------------------------------------------------+ void CSampleMoney::CSampleMoney() { //--- Setting default values m_lots=0.1; } //+------------------------------------------------------------------+ //| Validation of the setup parameters. | //| INPUT: no. | //| OUTPUT: true if the settings are correct, otherwise false. | //| REMARK: no. | //+------------------------------------------------------------------+ bool CSampleMoney::ValidationSettings() { //--- Call the base class method if(!CExpertMoney::ValidationSettings()) return(false); //--- Validating the parameters if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax()) { printf(__FUNCTION__+": The deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10) { printf(__FUNCTION__+": The deal volume must be multiple of %f",m_symbol.LotsStep()); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Defining the volume to open a long position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenLong(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Ask(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); } //+------------------------------------------------------------------+ //|Defining the volume to open a short position. | //| INPUT: no. | //| OUTPUT: lot-if successful, 0.0 otherwise. | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckOpenShort(double price,double sl) { if(m_symbol==NULL) return(0.0); //--- Select the lot size double lot=2*CheckPrevLoss(); if(lot==0.0) lot=m_lots; //--- Check the limits double maxvol=m_symbol.LotsMax(); if(lot>maxvol) lot=maxvol; //--- Check the margin requirements if(price==0.0) price=m_symbol.Bid(); maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent); if(lot>maxvol) lot=maxvol; //--- Return the trade volume return(lot); } //+------------------------------------------------------------------+ //| Defines whether the prev. deal was losing. | //| INPUT: no. | //| OUTPUT: Volume of the prev. deal if it's losing, otherwise 0.0 | //| REMARK: no. | //+------------------------------------------------------------------+ double CSampleMoney::CheckPrevLoss() { double lot=0.0; //--- Request the history of deals and orders HistorySelect(0,TimeCurrent()); //--- variables int deals=HistoryDealsTotal(); // Total number of deals in the history CDealInfo deal; //--- Find the previous deal for(int i=deals-1;i>=0;i--) { if(!deal.SelectByIndex(i)) { printf(__FUNCTION__+": Error of deal selection by index"); break; } //--- Check the symbol if(deal.Symbol()!=m_symbol.Name()) continue; //---Check the profit if(deal.Profit()<0.0) lot=deal.Volume(); break; } //--- Return the volume return(lot); } //+------------------------------------------------------------------+
Eh bien voilà tout. Le gestionnaire de fonds est prêt à l'emploi.
Pour que legenerator des stratégies de trading du MQL5 Wizard puisse utiliser notre gestionnaire de fonds, nous devons redémarrerMetaEditor (l'assistant MQL5 analyse le dossier Include\Expert uniquement au démarrage).
Après avoir redémarréMetaEditor le module gestionnaire de fonds créé peut être utilisé dans l'assistant MQL5 :
Figure 5. Le gestionnaire de fonds créé dans l'assistant MQL5
Les paramètres d'entrée spécifiés dans la section de description des paramètres gestionnaire de fonds sont désormais disponibles :
Figure 6. Paramètres d'entrée du gestionnaire de fonds créé dans l'assistant MQL5
Les meilleures valeurs des paramètres d'entrée de la stratégie de trading mise en œuvre peuvent être trouvées à l'aide duStrategy Tester duMetaTrader 5 terminal.
La figure 7 montre les résultats des tests de l'Expert Advisor qui négocie selon ce système de gestion de fonds (EURUSD H1, la période de test : 01.01.2010-05.01.2011).
Figure 7. Résultats des tests sur l'historique de la stratégie avec le module de gestion de fonds avec un doublement après une perte
Lors de la création d'un Expert Advisor, nous avons utilisé le module de signaux de trading implémenté dans l'article « Assistant MQL5 : Comment créer un module de signaux de trading". Les paramètres de l'Expert Advisor : (PeriodMA=12, ShiftMA=0, MethodMA=MODE_EMA, AppliedMA=PRICE_CLOSE, Limit=-70, StopLoss=145, TakeProfit=430, Expiration=10, Lots=0.1, Percent=100).
Conclusion
Le générateur de stratégies de trading du MQL5 Wizard simplifie considérablement le test des idées de trading. Le code de l'expert généré est basé sur lesclasses de stratégies de trading bibliothèque standard, qui sont utilisées pour créer certaines implémentations de classes de signaux de trading, de classes de gestion de fonds et des risques et de classes de support de position.
L'article décrit comment élaborer un module de gestion des risques et de fonds personnalisé et l'activer dans l'assistant MQL5. À titre d'exemple, nous avons examiné un algorithme de gestion de fonds, dans lequel la taille du volume de trade est déterminée par les résultats du deal précédent. La structure et le format de description de la classe créée pour l'assistant MQL5 sont également décrits.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/230
- 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