Générateur de signaux de trading basé sur un indicateur personnalisé
Introduction
Dans cet article, je vais vous expliquer comment créer un générateur de signaux de trading basé sur un indicateur personnalisé. Vous verrez comment vous pouvez écrire votre propre modèle de trading pour un indicateur personnalisé. J'expliquerai également le but du modèle 0 et pourquoi les structures de type IS_PATTERN_USAGE(0) sont utilisées dans le module de signal de trading.
L'article utilisera deux types de code : le code que nous allons modifier et le code que nous avons déjà modifié. Le code modifié sera mis en évidence comme suit :
//+------------------------------------------------------------------+
//| MySignal.mqh |
//| Copyright © 2012, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
Le code modifié est le code à copier et coller dans le générateur de signaux de trading. J'espère que vous comprendrez mieux le code grâce à la mise en évidence.
1. Indicateur personnalisé
Je suis sûr qu'il doit y avoir un indicateur non inclus dans la livraison standard que vous souhaitez utiliser depuis longtemps. Et c'est l'indicateur sur lequel vous voulez construire un module de signal de trading. J'utiliserai l'indicateur MACD de la livraison standard en tant qu'indicateur. L'emplacement de l'indicateur est le suivant : ...MQL5\Indicators\Examples\MACD.mq5
Chaque indicateur peut décrire un ou plusieurs modèles de marché. Un modèle de marché est une certaine combinaison de la valeur de l'indicateur et de la valeur du prix. Les modèles disponibles pour l'indicateur MACD sont l'inversion, le croisement de la ligne principale et de la ligne de signal, le croisement du niveau zéro, la divergence et la double divergence.
1.1 Nouveau modèle d'indicateur.
Supposons que nous ne sommes pas satisfaits des modèles de marché disponibles pour l'indicateur et que nous souhaitons introduire notre propre modèle d'indicateur. La description du nouveau modèle d'indicateur : si l'indicateur MACD est en dessous de la ligne zéro et que ses valeurs augmentent, nous pouvons nous attendre à une nouvelle croissance et ouvrir une position longue :
Figure 1. Modèle de croissance des indicateurs prospectifs
si l'indicateur MACD est au-dessus de la ligne zéro et que ses valeurs diminuent, nous pouvons nous attendre à une nouvelle baisse et ouvrir une position courte :
Figure 2 : Modèle de chute des indicateurs prospectifs
Nous avons donc choisi l'indicateur personnalisé et proposé le nouveau modèle de trading pour l'indicateur et sa description. Procédons à l'écriture du code.
2. Rédaction du générateur de signaux de trading basé sur notre indicateur personnalisé
Notre générateur est le descendant de la classe de base CExpertSignal. La classe de base CExpertSignal est une classe permettant de créer des générateurs de signaux de trading. La classe CExpertSignal contient un ensemble de méthodes publiques (c'est-à-dire accessibles de l'extérieur) qui permettent à un Expert Advisor de voir l'indication du générateur de signaux de trading concernant la direction d'entrée sur le marché.
Puisque nous travaillons sur notre propre générateur de signaux de trading, il devrait être hérité de la classe CExpertSignal, avec les méthodes virtuelles pertinentes redéfinies (remplies avec le code correspondant).
3. Création de la classe du générateur de signaux de trading
Le générateur de signaux de trading doit par défaut se trouver dans le dossier ...MQL5\Include\Expert\Signal. Pour ne pas surcharger le dossier ...\Signal de la bibliothèque standard avec trop d'informations, nous allons créer un nouveau dossier sous le dossier ...\Expert et l'appeler\MySignals:
Figure 3. Création du nouveau dossier MySignals
Ensuite, nous allons créer un fichier include en utilisant l'assistant MQL5. Dans MetaEditor, sélectionnez « Nouveau » dans le menu Fichier, puis sélectionnez "Inclure le fichier (*.mqh)".
Figure 4. Assistant MQL5. Création d'un fichier d'inclusion
Le nom de la classe de générateur de signaux sera MySignal. Il sera situé sous Include\Expert\MySignals\MySignal. Précisons-le :
Figure 5. Assistant MQL5. Emplacement du fichier d'inclusion
Après avoir cliqué sur « Terminer », l'assistant MQL5 générera un modèle vide. A partir de ce moment, nous allons tout faire manuellement et copier/coller les données. Je voudrais attirer votre attention sur le fait qu'en interne, tous les signaux de la bibliothèque standard sont presque identiques. Ils ne diffèrent que par les algorithmes utilisés pour déterminer les modèles de trading.
Par conséquent, vous pouvez prendre n'importe quel fichier du dossier \Include\Expert\Signal, copier son contenu et le coller dans votre modèle. Vous pouvez ensuite commencer à éditer le fichier résultant du générateur de signaux de trading.
4. Description de la classe du générateur de signaux de trading
Comme modèle, j'ai pris le fichier \Include\Expert\Signal\SignalEnvelopes.mqh à partir duquel j'ai tout copié sauf l'en-tête ://+------------------------------------------------------------------+ //| SignalEnvelopes.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+
et collé le tout dans notre modèle MySignal.mqh presque vide. Voilà ce que j'ai obtenu :
//+------------------------------------------------------------------+ //| MySignal.mqh | //| Copyright © 2012, Vladimir Karputov | //| http://wmua.ru/slesar/ | //+------------------------------------------------------------------+ #include <Expert\ExpertSignal.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of indicator 'Envelopes' | //| Type=SignalAdvanced | //| Name=Envelopes | //| ShortName=Envelopes | //| Class=CSignalEnvelopes | //| Page=signal_envelopes | //| Parameter=PeriodMA,int,45,Period of averaging | //| Parameter=Shift,int,0,Time shift | //| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | //| Parameter=Deviation,double,0.15,Deviation | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSignalEnvelopes. | //| Purpose: Class of generator of trade signals based on | //| the 'Envelopes' indicator. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalEnvelopes : public CExpertSignal { protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator double m_limit_in; // threshold sensitivity of the 'rollback zone' double m_limit_out; // threshold sensitivity of the 'break through zone' //--- "weights" of market models (0-100) int m_pattern_0; // model 0 "price is near the necessary border of the envelope" int m_pattern_1; // model 1 "price crossed a border of the envelope" public: CSignalEnvelopes(void); ~CSignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } void LimitIn(double value) { m_limit_in=value; } void LimitOut(double value) { m_limit_out=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } void Pattern_1(int value) { m_pattern_1=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and time series virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(0.15), m_limit_in(0.2), m_limit_out(0.2), m_pattern_0(90), m_pattern_1(70) { //--- initialization of protected data m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSignalEnvelopes::~CSignalEnvelopes(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertSignal::ValidationSettings()) return(false); //--- initial data checks if(m_ma_period<=0) { printf(__FUNCTION__+": period MA must be greater than 0"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and time series of additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- create and initialize MA indicator if(!InitMA(indicators)) return(false); //--- ok return(true); } //+------------------------------------------------------------------+ //| Initialize MA indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitMA(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- add object to collection if(!indicators.Add(GetPointer(m_env))) { printf(__FUNCTION__+": error adding object"); return(false); } //--- initialize object if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation)) { printf(__FUNCTION__+": error initializing object"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| "Voting" that the price will grow. | //+------------------------------------------------------------------+ int CSignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+ //| "Voting" that the price will fall. | //+------------------------------------------------------------------+ int CSignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+
Remarque ligne 6 :
#include <Expert\ExpertSignal.mqh>
Ici, nous donnons l'ordre au préprocesseur d'inclure la classe de base CExpertSignal pour créer des générateurs de signaux de trading dans notre modèle.
Nous allons continuer à éditer le modèle. Pour que notre modèle soit visible ultérieurement par l'assistant MQL5, nous devons modifier la description de notre classe :
//+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of indicator 'Envelopes' | //| Type=SignalAdvanced | //| Name=Envelopes | //| ShortName=Envelopes | //| Class=CSignalEnvelopes | //| Page=signal_envelopes | //| Parameter=PeriodMA,int,45,Period of averaging | //| Parameter=Shift,int,0,Time shift | //| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | //| Parameter=Deviation,double,0.15,Deviation | //+------------------------------------------------------------------+
Alors, voyons. La ligne
//| Title=Signals of indicator 'Envelopes' |
indique le nom de notre classe de signaux sous lequel elle sera affichée dans l'assistant MQL5. Nous allons changer ce nom en quelque chose comme ceci :
//| Title=Signal of the 'Custom Indicator' indicator |
La ligne suivante :
//| Name=Envelopes |
indique le nom pour décrire les variables de notre classe de signaux de trading. Cette description sera utilisée par l'assistant MQL5. Modifions cette ligne comme suit :
//| Name=MyCustomIndicator |
La ligne suivante :
//| ShortName=Envelopes |
Nous donnerons le même nom à ce paramètre :
//| ShortName=MyCustomIndicator |
La ligne suivante définit le nom de la classe :
//| Class=CSignalEnvelopes |
Renommons ce paramètre :
//| Class=CSignalMyCustInd |
Laissez le paramètre suivant tel quel.
//| Page=signal_envelopes |
Le groupe de paramètres suivant est responsable de la description des paramètres de l'indicateur sous-jacent au générateur de signaux de trading. Comme je l'ai mentionné plus tôt, j'utiliserai ...MQL5\Indicators\Examples\MACD.mq5 comme indicateur personnalisé. Il possède les paramètres suivants :
//--- input parameters input int InpFastEMA=12; // Fast EMA period input int InpSlowEMA=26; // Slow EMA period input int InpSignalSMA=9; // Signal SMA period input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE; // Applied price
4.1 Paramètre Description Bloc
Veuillez noter que les paramètres donnés ci-dessus s'appliquent uniquement à MACD.mq5. Votre indicateur personnalisé peut avoir des paramètres complètement différents. L'essentiel ici est de faire correspondre les paramètres de l'indicateur avec leurs descriptions dans la classe de signal de trading. Le bloc de description de paramètre dans la classe de signal de trading pour l'indicateur personnalisé considéré, MACD.mq5 , sera le suivant :
//| Parameter=PeriodFast,int,12,Period of fast EMA |
//| Parameter=PeriodSlow,int,24,Period of slow EMA |
//| Parameter=PeriodSignal,int,9,Period of averaging of difference |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series |
Regardez comment les paramètres de l'indicateur correspondent désormais aux descriptions du bloc de description de classe. Suite à toutes les modifications, le bloc description de notre classe sera le suivant :
//+------------------------------------------------------------------+ //| Description of the class | //| Title=Signal of the 'Custom Indicator' indicator | //| Type=SignalAdvanced | //| Name=MyCustomIndicator | //| ShortName=MyCustomIndicator | //| Class=CSignalMyCustInd | //| Page=signal_envelopes | //| Parameter=PeriodFast,int,12,Period of fast EMA | //| Parameter=PeriodSlow,int,24,Period of slow EMA | //| Parameter=PeriodSignal,int,9,Period of averaging of difference | //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | //+------------------------------------------------------------------+
En programmation, il est considéré comme une bonne pratique de fournir des commentaires à son code, ce qui facilite la compréhension du code, lorsqu'on y revient après un certain temps. Nous allons donc modifier le bloc suivant :
//+------------------------------------------------------------------+ //| Class CSignalEnvelopes. | //| Purpose: Class of generator of trade signals based on | //| the 'Envelopes' indicator. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+
pour correspondre à la description de notre classe :
//+------------------------------------------------------------------+
//| Class CSignalMyCustInd. |
//| Purpose: Class of the trading signal generator based on |
//| the custom indicator. |
//| It is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
Pour éviter toute confusion, nous devons remplacer toutes les valeurs « CSignalEnvelopes » par « CSignalMyCustInd »
Figure 6. Remplacement de CSignalEnvelopes par CSignalMyCustInd
Examinons maintenant quelques aspects théoriques.
5. La classe CiCustom
Nous aurons besoin de la classe CiCustom pour continuer à travailler sur le code de la classe des indicateurs de trading de l'indicateur personnalisé. La classe CiCustom a été créée spécifiquement pour travailler avec des indicateurs personnalisés. La classe CiCustom permet de créer, de paramétrer et d'accéder aux données des indicateurs personnalisés.
6. La classe CIndicators.
CIndicators est la classe permettant de rassembler les instances des classes de séries chronologiques et d'indicateurs techniques. La classe CIndicators assure la création, le stockage et la gestion (synchronisation des données, gestion des handles et de la mémoire) des instances de la classe des indicateurs techniques.
Nous sommes particulièrement intéressés par la classe CIndicators à cause de la méthode Create. Cette méthode crée un indicateur d'un type spécifié avec des paramètres spécifiés.
7. Continuez à écrire notre classe de signaux de trading
Le prochain bloc de code que nous allons modifier (lignes 28-42) est le suivant :class CSignalMyCustInd : public CExpertSignal { protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator double m_limit_in; // threshold sensitivity of the 'rollback zone' double m_limit_out; // threshold sensitivity of the 'break through zone' //--- "weights" of market models (0-100) int m_pattern_0; // model 0 "price is near the necessary border of the envelope" int m_pattern_1; // model 1 "price crossed a border of the envelope"
8. Création de l'indicateur personnalisé dans le générateur de signaux de trading
Jetez un œil au bloc de code fourni ci-dessus. La ligne
CiEnvelopes m_env; // object-indicator
déclare un objet - l'indicateur de classe CiEnvelopes. CiEnvelopes est la classe pour travailler avec l'indicateur technique de la bibliothèque standard. La classe CiEnvelopes a été créée sur la base de l'indicateur technique de la bibliothèque standard. Cependant, nous écrivons le code du générateur basé sur notre indicateur personnalisé. Par conséquent, il n'existe pas de classe prête à l'emploi pour notre ou votre indicateur personnalisé dans la bibliothèque standard. Ce que nous pouvons faire, c'est utiliser la classe CiCustom.
Déclarons notre indicateur comme la classe CiCustom :
CiCustom m_mci; // indicator object "MyCustomIndicator"
8.1 Quatre variables
Vous souvenez-vous du bloc de description des paramètres dans la classe ? Il y avait trois paramètres dans cette description. Dans la zone protégée de notre classe de générateur, nous allons maintenant déclarer quatre variables pour transmettre les valeurs de nos quatre paramètres :
//--- adjustable parameters
int m_period_fast; // "fast EMA period"
int m_period_slow; // "slow EMA period"
int m_period_signal; // "difference averaging period"
ENUM_APPLIED_PRICE m_applied; // "price type"
Le bloc de code suivant :
//--- "weights" of market models (0-100) int m_pattern_0; // model 0 "price is near the necessary border of the envelope" int m_pattern_1; // model 1 "price crossed a border of the envelope"
Ce code déclare des variables qui donnent du « poids » aux modèles de trading de notre générateur de signaux de trading. Remplaçons le bloc de « poids » par le code suivant :
//--- "weights" of the market models (0-100)
int m_pattern_0; // model 0 "the oscillator has required direction"
int m_pattern_1; // model 1 "the indicator is gaining momentum - buy; the indicator is falling - sell"
9. Modèle 0
Comme vous vous en souvenez, au début de l'article, il a été décidé de décrire un seul nouveau modèle qui sera généré par notre générateur de signaux de trading. Cependant, dans le code ci-dessus, j'ai spécifié deux modèles de marché (modèle 0 et modèle 1). Ici, le modèle 0 est un modèle auxiliaire important. Il est nécessaire lorsque vous tradez avec des ordres en attente. Lorsqu'il est appliqué, le modèle 0 garantit que les ordres en attente évoluent en même temps que le prix. Jetons un coup d'œil à notre générateur de signaux de trading et aux conditions suivantes :
- l'indicateur personnalisé MACD est en dessous de la ligne zéro,
- et ses valeurs augmentent,
- nous faisons du trading avec des ordres en attente fixés à 50 points du prix d'ouverture de la barre (valeur de prix à quatre chiffres).
Ces conditions décrivent parfaitement notre modèle de trading. Voici comment les choses vont évoluer : Les conditions de notre modèle de trading seront vérifiées lors de l'apparition de la barre n°. 1. Ce que nous avons : MACD est en dessous de la ligne zéro, mais il prend de l'ampleur. Cela correspond au signal d'achat. Par conséquent, nous plaçons un ordre Buy Stop en attente :
Figure 7. Placer un ordre d'achat stop en attente
Lors de l'apparition de la barre suivante n°. 2, le contrôle de condition constate que le MACD est inférieur à zéro et est en baisse. Selon notre modèle de trading, il n'existe actuellement aucune condition d'achat ou de vente. Cependant, notez : selon la logique de la classe CExpertSignal, puisqu'il n'y a aucune condition d'achat ou de vente, tous les ordres en attente doivent être SUPPRIMÉS. Dans ce cas, si le prix augmente soudainement et de façon spectaculaire, nous manquerons l'occasion d'entrer sur le marché long à notre avantage car il n'y aura pas d'ordre en attente.
C'est là que le modèle auxiliaire 0 apparaît très utile. Le modèle auxiliaire 0 s'appliquera, à condition que :
- l'indicateur personnalisé MACD est en dessous de la ligne zéro.
Nous pouvons donc passer un ordre Buy Stop en attente. Puisque nous passons un ordre à 50 points du prix d'ouverture de la barre, nous déplaçons simplement l'ordre Buy Stop en attente en fonction du mouvement du prix :
Figure 8. Déplacer l'ordre Buy Stop vers le bas
Ainsi, en utilisant le modèle auxiliaire 0, nous avons la possibilité de déplacer un ordre en attente en fonction du mouvement du prix.
10. Autres modifications du code de modèle
Le prochain bloc de code à modifier est le suivant :public: CSignalMyCustInd(void); ~CSignalMyCustInd(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } void LimitIn(double value) { m_limit_in=value; } void LimitOut(double value) { m_limit_out=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } void Pattern_1(int value) { m_pattern_1=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and time series virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void);
Dans ce bloc, nous déclarons des méthodes de définition des paramètres ajustables, des méthodes d'ajustement des poids des modèles de trading, une méthode de vérification des paramètres, une méthode d'initialisation des indicateurs et des méthodes pour vérifier si les modèles de marché sont générés.
Compte tenu du fait que nous avons déclaré quatre variables dans les paramètres réglables, le bloc de méthodes de réglage des paramètres sera le suivant :
//--- methods of setting adjustable parameters
void PeriodFast(int value) { m_period_fast=value; }
void PeriodSlow(int value) { m_period_slow=value; }
void PeriodSignal(int value) { m_period_signal=value; }
void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; }
Le prochain fragment de code restera inchangé :
//--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } void Pattern_1(int value) { m_pattern_1=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and time series virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are generated virtual int LongCondition(void); virtual int ShortCondition(void);
Le prochain bloc de code à modifier est le suivant :
protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } };
Ce bloc sera fortement modifié. Veuillez noter que j'utilise la méthode GetData de la classe CIndicator. Les noms des méthodes appelées seront fournis directement dans le code :
protected:
//--- indicator initialization method
bool InitMyCustomIndicator(CIndicators *indicators);
//--- methods for getting data
//- getting the indicator value
double Main(int ind) { return(m_mci.GetData(0,ind)); }
//- getting the signal line value
double Signal(int ind) { return(m_mci.GetData(1,ind)); }
//- difference between two successive indicator values
double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); }
int StateMain(int ind);
double State(int ind) { return(Main(ind)-Signal(ind)); }
//- preparing data for the search
bool ExtState(int ind);
//- searching the market model with the specified parameters
bool CompareMaps(int map,int count,bool minimax=false,int start=0);
};
Le bloc de code suivant est le constructeur.
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalMyCustInd::CSignalMyCustInd(void) : m_ma_period(45), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(0.15), m_limit_in(0.2), m_limit_out(0.2), m_pattern_0(90), m_pattern_1(70) { //--- initialization of protected data m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; }
Dans le constructeur, nous allons changer les noms des variables. De plus, nous n'utiliserons que deux séries : USE_SERIES_HIGH+USE_SERIES_LOW
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CSignalMyCustInd::CSignalMyCustInd(void) : m_period_fast(12),
m_period_slow(24),
m_period_signal(9),
m_applied(PRICE_CLOSE),
m_pattern_0(10),
m_pattern_1(50)
{
//--- initialization of protected data
m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
}
Modifions la méthode ValidationSettings de notre classe.
//+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CSignalMyCustInd::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertSignal::ValidationSettings()) return(false); //--- initial data checks if(m_ma_period<=0) { printf(__FUNCTION__+": period MA must be greater than 0"); return(false); } //--- ok return(true); }
Dans le bloc de vérification, nous vérifions la condition principale pour l'indicateur personnalisé donné : m_period_fast>=m_period_slow
//+------------------------------------------------------------------+
//| Checking parameters of protected data |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::ValidationSettings(void)
{
//--- validation settings of additional filters
if(!CExpertSignal::ValidationSettings())
return(false);
//--- initial data checks
if(m_period_fast>=m_period_slow)
{
printf(__FUNCTION__+": slow period must be greater than fast period");
return(false);
}
//--- ok
return(true);
}
Le bloc suivant traite de la création d'indicateurs :
//+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalMyCustInd::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and time series of additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- create and initialize MA indicator if(!InitMA(indicators)) return(false); //--- ok return(true); }
Comme appliqué à notre indicateur personnalisé :
//+------------------------------------------------------------------+
//| Creation of indicators. |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitIndicators(CIndicators *indicators)
{
//--- check of pointer is performed in the method of the parent class
//---
//--- initialization of indicators and time series of additional filters
if(!CExpertSignal::InitIndicators(indicators))
return(false);
//--- creation and initialization of the custom indicator
if(!InitMyCustomIndicator(indicators))
return(false);
//--- ok
return(true);
}
Le bloc suivant est le bloc d'initialisation de l'indicateur :
//+------------------------------------------------------------------+ //| Initialize MA indicators. | //+------------------------------------------------------------------+ bool CSignalMyCustInd::InitMA(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- add object to collection if(!indicators.Add(GetPointer(m_env))) { printf(__FUNCTION__+": error adding object"); return(false); } //--- initialize object if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation)) { printf(__FUNCTION__+": error initializing object"); return(false); } //--- ok return(true); }
Tout d'abord, nous ajoutons un objet à la collection. Nous définissons ensuite les paramètres de notre indicateur et créons l'indicateur personnalisé à l'aide de la méthode Create de la classe CIndicators :
//+------------------------------------------------------------------+
//| Initialization of indicators. |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitMyCustomIndicator(CIndicators *indicators)
{
//--- add an object to the collection
if(!indicators.Add(GetPointer(m_mci)))
{
printf(__FUNCTION__+": error adding object");
return(false);
}
//--- set parameters of the indicator
MqlParam parameters[4];
//---
parameters[0].type=TYPE_STRING;
parameters[0].string_value="Examples\\MACD.ex5";
parameters[1].type=TYPE_INT;
parameters[1].integer_value=m_period_fast;
parameters[2].type=TYPE_INT;
parameters[2].integer_value=m_period_slow;
parameters[3].type=TYPE_INT;
parameters[3].integer_value=m_period_signal;
//--- object initialization
if(!m_mci.Create(m_symbol.Name(),0,IND_CUSTOM,4,parameters))
{
printf(__FUNCTION__+": error initializing object");
return(false);
}
//--- number of buffers
if(!m_mci.NumBuffers(4)) return(false);
//--- ok
return(true);
}
Le bloc suivant vérifie les conditions d'achat :
//+------------------------------------------------------------------+ //| "Voting" that the price will grow. | //+------------------------------------------------------------------+ int CSignalMyCustInd::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
Selon notre implémentation du modèle 0, deux modèles sont vérifiés :
//+------------------------------------------------------------------+
//| "Voting" that the price will grow. |
//+------------------------------------------------------------------+
int CSignalMyCustInd::LongCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffMain(idx)>0.0)
{
//--- the main line goes upwards, which confirms the possibility of the price growth
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, look for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0)
result=m_pattern_1; // signal number 1
}
//--- return the result
return(result);
}
Le bloc suivant vérifie les conditions de vente :
//+------------------------------------------------------------------+ //| "Voting" that the price will fall. | //+------------------------------------------------------------------+ int CSignalMyCustInd::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
Selon notre implémentation du modèle 0, deux modèles sont vérifiés :
//+------------------------------------------------------------------+
//| "Voting" that the price will fall. |
//+------------------------------------------------------------------+
int CSignalMyCustInd::ShortCondition(void)
{
int result=0;
int idx =StartIndex();
//--- check direction of the main line
if(DiffMain(idx)<0.0)
{
//--- the main line gown downwards, which confirms the possibility of the price fall
if(IS_PATTERN_USAGE(0))
result=m_pattern_0; // "confirming" signal number 0
//--- if the model 1 is used, look for a reverse of the main line
if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0)
result=m_pattern_1; // signal number 1
}
//--- return the result
return(result);
}
Conclusion
J'espère que cet article vous a aidé à comprendre comment vous pouvez créer un générateur de signaux de trading basé sur votre indicateur personnalisé.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/691
- 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