
Generatore di segnali di trading basato su un indicatore personalizzato
Introduzione
In questo articolo, ti dirò come creare un generatore di segnali di trading basato su un indicatore personalizzato. Vedrai come puoi scrivere il tuo modello di trading per un indicatore personalizzato. Spiegherò anche lo scopo del modello 0 e perché le strutture di tipo IS_PATTERN_USAGE(0) vengono utilizzate nel modulo del segnale di trading.
L'articolo utilizzerà due tipi di codice: il codice che stiamo per modificare e il codice che abbiamo già modificato. Il codice modificato sarà evidenziato come segue:
//+------------------------------------------------------------------+
//| MySignal.mqh |
//| Copyright © 2012, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
Il codice modificato è il codice da copiare e incollare nel generatore di segnali di trading. Spero che capirai meglio il codice attraverso l'uso dell'evidenziazione.
1. Indicatore personalizzato
Sono sicuro che ci deve essere un indicatore non incluso nella consegna standard che desideri utilizzare da molto tempo. E questo è l'indicatore in base al quale vuoi costruire un modulo di segnale di trading. Userò l'indicatore MACD dalla consegna standard come tale indicatore. La posizione dell'indicatore è la seguente: ...MQL5\Indicators\Examples\MACD.mq5.
Ciascun indicatore può descrivere uno o più modelli di mercato. Un modello di mercato è una certa combinazione del valore dell'indicatore e del valore del prezzo. I modelli disponibili per l'indicatore MACD sono inversione, crossover della linea principale e della linea di segnale, crossover del livello zero, divergenza e doppia divergenza.
1.1 Nuovo modello di indicatori.
Supponiamo di non essere soddisfatti dei modelli di mercato disponibili per l'indicatore e di voler introdurre il nostro modello di indicatore. La nuova descrizione del modello di indicatore: se l'indicatore MACD è al di sotto della linea dello zero e i suoi valori sono in aumento, possiamo aspettarci un'ulteriore crescita e aprire una posizione long:
Figura 1. Modello di crescita dell'indicatore prospettico
Se l'indicatore MACD è sopra la linea dello zero e i suoi valori sono in diminuzione, possiamo aspettarci un'ulteriore diminuzione e aprire una posizione short:
Figura 2: Modello di caduta dell'indicatore prospettico
Quindi, abbiamo deciso l'indicatore personalizzato e abbiamo creato il nuovo modello di trading per l'indicatore e la sua descrizione. Procediamo con la scrittura del codice.
2. Scrivere il generatore di segnali di trading in base al nostro indicatore personalizzato
Il nostro generatore è il discendente della classe base CExpertSignal. La classe base CExpertSignal è una classe per la creazione di generatori di segnali di trading. La classe CExpertSignal contiene un insieme di metodi pubblici (ossia accessibili dall'esterno) che consentono ad un Expert Advisor di vedere l'indicazione del generatore di segnali di trading circa la direzione di ingresso nel mercato.
Poiché stiamo lavorando sul nostro generatore di segnali di trading, deve essere ereditato dalla classe CExpertSignal, on i relativi metodi virtuali ridefiniti (compilati con il codice corrispondente).
3. Creazione della classe del generatore di segnali di trading
Il generatore di segnali di trading deve trovarsi per impostazione predefinita nella cartella ...MQL5\Include\Expert\Signal. Per non sovraccaricare la cartella ...\Signal della libreria standard con troppe informazioni, creiamo una nuova cartella nella cartella ...\Expert e chiamiamola \MySignals:
Figura 3. Creazione della nuova cartella MySignals
Successivamente, creeremo un file include utilizzando il Wizard MQL5. Su MetaEditor, seleziona "Nuovo" nel menu File e quindi seleziona "File include (*.mqh)".
Figura 4. Wizard MQL5. Creare un file include
Il nome della classe del generatore di segnale sarà MySignal. Si troverà in Include\Expert\MySignals\MySignal. Specifichiamolo:
Figura 5. Wizard MQL5. Posizione del file include
Dopo aver cliccato su "Fine", il Wizard MQL5 genererà un modello vuoto. Da questo momento in poi, faremo tutto manualmente e copieremo/incolleremo i dati. Vorrei attirare la vostra attenzione sul fatto che internamente tutti i segnali della libreria standard sono quasi identici. Differiscono solo negli algoritmi utilizzati per determinare i modelli di trading.
Pertanto, puoi prendere qualsiasi file dalla cartella \Include\Expert\Signal, copiarne il contenuto e incollarlo nel tuo modello. Puoi quindi iniziare a modificare il file risultante del generatore di segnali di trading.
4. Descrizione della classe del generatore di segnali di trading
Come modello ho preso il file \Include\Expert\Signal\SignalEnvelopes.mqh da cui ho copiato tutto tranne l'intestazione://+------------------------------------------------------------------+ //| SignalEnvelopes.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+
e ho incollato tutto nel nostro modello MySignal.mqh quasi vuoto. Questo è quello che ho ottenuto:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Nota la riga 6:
#include <Expert\ExpertSignal.mqh>
Qui diamo un ordine al preprocessore di includere la classe base CExpertSignal per la creazione di generatori di segnali di trading nel nostro modello.
Continueremo a modificare il modello. Per garantire che il nostro modello sia visibile in seguito al Wizard MQL5, dobbiamo modificare la descrizione della nostra 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 | //+------------------------------------------------------------------+
Quindi, vediamo. La linea
//| Title=Signals of indicator 'Envelopes' |
mostra il nome della nostra classe di segnale sotto la quale verrà visualizzato nel Wizard MQL5. Cambieremo questo nome in qualcosa del genere:
//| Title=Signal of the 'Custom Indicator' indicator |
La riga successiva:
//| Name=Envelopes |
indica il nome per descrivere le variabili della nostra classe di segnali di trading. Questa descrizione verrà utilizzata dal Wizard MQL5. Modifichiamo questa riga come segue:
//| Name=MyCustomIndicator |
La riga successiva:
//| ShortName=Envelopes |
Daremo lo stesso nome a questo parametro:
//| ShortName=MyCustomIndicator |
La riga seguente imposta il nome della classe:
//| Class=CSignalEnvelopes |
Rinominiamo questo parametro:
//| Class=CSignalMyCustInd |
Lascia il parametro successivo così com'è.
//| Page=signal_envelopes |
Il seguente gruppo di parametri è responsabile della descrizione dei parametri dell'indicatore sottostante il generatore di segnali di trading. Come accennato in precedenza, utilizzerò ...MQL5\Indicators\Examples\MACD.mq5 come indicatore personalizzato. L'oggetto ha i seguenti parametri:
//--- 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 Parametro Descrizione Blocco
Da notare che i parametri sopra indicati si applicano solo a MACD.mq5. Il tuo indicatore personalizzato potrebbe avere parametri completamente diversi. La cosa principale qui è abbinare i parametri dell'indicatore con le loro descrizioni nella classe del segnale di trading. Il parametro descrizione blocco nella classe del segnale di trading per l'indicatore personalizzato in esame, MACD.mq5 , sarà il seguente:
//| 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 |
Dai un'occhiata a come i parametri nell'indicatore ora corrispondono alle descrizioni nel blocco di descrizione della classe. A seguito di tutte le modifiche, il blocco descrittivo della nostra classe sarà il seguente:
//+------------------------------------------------------------------+ //| 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 | //+------------------------------------------------------------------+
Nella programmazione è considerata buona pratica fornire commenti al proprio codice, facilitando così la comprensione del codice quando vi si torna dopo che è trascorso un po' di tempo. Quindi, modificheremo il seguente blocco:
//+------------------------------------------------------------------+ //| Class CSignalEnvelopes. | //| Purpose: Class of generator of trade signals based on | //| the 'Envelopes' indicator. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+
per abbinare la descrizione della nostra classe:
//+------------------------------------------------------------------+
//| Class CSignalMyCustInd. |
//| Purpose: Class of the trading signal generator based on |
//| the custom indicator. |
//| It is derived from the CExpertSignal class. |
//+------------------------------------------------------------------+
Per evitare confusione, dobbiamo sostituire tutti i valori "CSignalEnvelopes" con "CSignalMyCustInd"
Figura 6. Sostituzione di CSignalEnvelopes con CSignalMyCustInd
Vediamo ora alcuni aspetti teorici.
5. La classe CiCustom
Avremo bisogno della classe CiCustom per continuare a lavorare sul codice della classe degli indicatori di trading dell'indicatore personalizzato. La classe CiCustom è stata creata appositamente per lavorare con indicatori personalizzati. La classe CiCustom fornisce la creazione, l'impostazione e l'accesso ai dati degli indicatori personalizzati.
6. La classe degli indicatori C.
CIndicators è la classe per la raccolta di istanze di serie temporali e classi di indicatori tecnici. La classe CIndicators fornisce la creazione, l'archiviazione e la gestione (sincronizzazione dei dati, handle e gestione della memoria) di istanze di classi di indicatori tecnici.
Siamo particolarmente interessati alla classe CIndicators a causa del metodo Create. Questo metodo crea un indicatore di un tipo specificato con parametri specificati.
7. Continua a scrivere la nostra classe di segnali di trading
Il prossimo blocco di codice che andremo a modificare (righe 28-42) è il seguente: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. Creazione dell'indicatore personalizzato nel generatore di segnali di trading
Dai un'occhiata al blocco di codice fornito sopra. La linea
CiEnvelopes m_env; // object-indicator
dichiara un oggetto: l'indicatore di classe CiEnvelopes. CiEnvelopes è la classe per lavorare con l'indicatore tecnico della libreria standard. La classe CiEnvelopes è stata creata sulla base dell'indicatore tecnico della libreria standard. Tuttavia, stiamo scrivendo il codice del generatore in base al nostro indicatore personalizzato. Pertanto, non esiste una classe già pronta per il nostro o il tuo indicatore personalizzato nella libreria standard. Quello che possiamo fare è usare la classe CiCustom.
Dichiariamo il nostro indicatore come classe CiCustom:
CiCustom m_mci; // indicator object "MyCustomIndicator"
8.1 Quattro variabili
Ricordi il parametro descrizione blocco nella classe? C'erano tre parametri in quella descrizione. Nell'area protetta della nostra classe generator dichiareremo ora quattro variabili per passare i valori ai nostri quattro parametri:
//--- 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"
Il seguente blocco di codice:
//--- "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"
Questo codice dichiara le variabili che danno "peso" ai modelli di trading del nostro generatore di segnali di trading. Sostituiamo il blocco dei "pesi" con il seguente codice:
//--- "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. Modello 0
Come ricorderete, all'inizio dell'articolo si è deciso di descrivere solo un nuovo modello, il quale verrà generato dal nostro generatore di segnali di trading. Tuttavia, nel codice sopra ho specificato due modelli di mercato (modello 0 e modello 1). Qui, il modello 0 è un importante modello ausiliario. È richiesto quando si fa trading con ordini in sospeso. Quando applicato, il modello 0 garantisce che gli ordini in sospeso si muovano insieme al prezzo. Diamo un'occhiata al nostro generatore di segnali di trading e alle seguenti condizioni:
- l'indicatore personalizzato MACD è sotto la linea dello zero
- e i suoi valori stanno aumentando.
- Stiamo facendo trading con ordini in sospeso fissati a 50 punti dal prezzo di apertura della barra (valore del prezzo a quattro cifre).
Queste condizioni descrivono perfettamente il nostro modello di trading. Ecco come si muoveranno le cose: Le condizioni del nostro modello di trading verranno verificate alla comparsa della barra n. 1. Cosa abbiamo: Il MACD è al di sotto della linea dello zero, ma sta guadagnando slancio. Questo corrisponde al segnale di acquisto. Pertanto, effettuiamo un ordine Buy Stop in sospeso:
Figura 7. Inserimento di un ordine Buy Stop in sospeso
Alla comparsa della successiva battuta n. 2, il controllo delle condizioni rileva che il MACD è inferiore a zero e sta diminuendo. Secondo il nostro modello di trading, al momento non ci sono condizioni per l'acquisto o la vendita. Attenzione però: secondo la logica della classe CExpertSignal, non essendoci condizioni né per l'acquisto né per la vendita, tutti gli ordini in sospeso devono essere ELIMINATI. In questo caso, se il prezzo sale improvvisamente e drammaticamente, perderemo l'opportunità di entrare nel mercato long a nostro vantaggio poiché non ci saranno ordini in sospeso.
È qui che il modello ausiliario 0 sembra essere molto utile. Si applica il modello ausiliario 0 a condizione che:
- l'indicatore personalizzato MACD sia sotto la linea dello zero.
Quindi possiamo inserire un ordine Buy Stop in sospeso. Poiché effettuiamo un ordine a 50 punti dal prezzo di apertura della barra, spostiamo semplicemente l'ordine Buy Stop in sospeso in base al movimento del prezzo:
Figura 8. Spostare l'ordine Buy Stop verso il basso
Pertanto, utilizzando il modello ausiliario 0, abbiamo l'opportunità di spostare un ordine in sospeso in base al movimento del prezzo.
10. Ulteriori modifiche del codice modello
Il prossimo blocco di codice da modificare è il seguente: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);
In questo blocco dichiariamo i metodi per impostare i parametri regolabili, i metodi per regolare i pesi dei modelli di trading, il metodo di verifica delle impostazioni, il metodo di inizializzazione dell'indicatore e i metodi per verificare se i modelli di mercato sono generati.
Considerando che abbiamo dichiarato quattro variabili nei parametri regolabili, il blocco di metodi per l'impostazione dei parametri sarà il seguente:
//--- 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; }
Il prossimo frammento di codice rimarrà invariato:
//--- 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);
Il prossimo blocco di codice da modificare è il seguente:
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)); } };
Questo blocco sarà pesantemente modificato. Da notare che sto utilizzando il metodo GetData della classe CIndicator. I nomi dei metodi chiamati saranno forniti direttamente nel codice:
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);
};
Il prossimo blocco di codice è il costruttore.
//+------------------------------------------------------------------+ //| 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; }
Nel costruttore, cambieremo i nomi delle variabili. Inoltre, useremo solo due serie: 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;
}
Modifichiamo il metodo ValidationSettings della nostra 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); }
Nel blocco di controllo, controlliamo la condizione principale per l'indicatore personalizzato dato: 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);
}
Il blocco successivo riguarda la creazione di indicatori:
//+------------------------------------------------------------------+ //| 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); }
Come applicato al nostro indicatore personalizzato:
//+------------------------------------------------------------------+
//| 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);
}
Il blocco seguente è il blocco di inizializzazione dell'indicatore:
//+------------------------------------------------------------------+ //| 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); }
Innanzitutto, aggiungiamo un oggetto alla raccolta. Impostiamo quindi i parametri del nostro indicatore e creiamo l'indicatore personalizzato utilizzando il metodo Create della 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);
}
Il blocco successivo controlla le condizioni di acquisto:
//+------------------------------------------------------------------+ //| "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); }
Secondo la nostra implementazione del modello 0, vengono verificati due modelli:
//+------------------------------------------------------------------+
//| "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);
}
Il seguente blocco controlla le condizioni di vendita:
//+------------------------------------------------------------------+ //| "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); }
Secondo la nostra implementazione del modello 0, vengono verificati due modelli:
//+------------------------------------------------------------------+
//| "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);
}
Conclusione
Spero che questo articolo ti abbia aiutato a capire come creare un generatore di segnali di trading basato sul tuo indicatore personalizzato.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/691





- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso