English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Generatore di segnali di trading basato su un indicatore personalizzato

Generatore di segnali di trading basato su un indicatore personalizzato

MetaTrader 5Esempi | 11 gennaio 2022, 16:07
218 0
Vladimir Karputov
Vladimir Karputov

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 prospettica dell'indicatore 

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

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 

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. Creazione di un file include

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

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

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
 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. Ribasso dell'ordine Buy Stop
  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

File allegati |
mysignal.mqh (9.38 KB)
Risultati del Market MQL5 per il secondo trimestre 2013 Risultati del Market MQL5 per il secondo trimestre 2013
Operando con successo per 1,5 anni, il Market MQL5 è diventato il più grande negozio di trader di strategie di trading e indicatori tecnici. Offre circa 800 applicazioni di trading fornite da 350 sviluppatori di tutto il mondo. Oltre 100.000 programmi di trading sono già stati acquistati e scaricati dai trader sui loro terminali MetaTrader 5.
Risultati del Market MQL5 per il primo trimestre 2013 Risultati del Market MQL5 per il primo trimestre 2013
Dalla sua fondazione, il negozio di robot di trading e indicatori tecnici del Market MQL5 ha già attratto più di 250 sviluppatori che hanno pubblicato 580 prodotti. Il primo trimestre del 2013 si è rivelato un discreto successo per alcuni venditori del Market MQL5 che sono riusciti a realizzare un bel profitto vendendo i loro prodotti.
Social Trading con le piattaforme di trading MetaTrader 4 e MetaTrader 5 Social Trading con le piattaforme di trading MetaTrader 4 e MetaTrader 5
Cos'è il social trading? È una cooperazione reciprocamente vantaggiosa di trader e investitori in cui i trader di successo consentono il monitoraggio del loro trading e i potenziali investitori sfruttano l'opportunità di monitorare le loro prestazioni e copiare le negoziazioni di coloro che sembrano più promettenti.
Jeremy Scott: venditore di successo sul Market MQL5 Jeremy Scott: venditore di successo sul Market MQL5
Jeremy Scott, meglio conosciuto con il soprannome di Johnnypasado sulla MQL5.community, è diventato famoso offrendo prodotti nel nostro servizio Market MQL5. Jeremy ha già guadagnato diverse migliaia di dollari nel Market e non finisce qui. Abbiamo deciso di dare un'occhiata più da vicino al futuro milionario e ricevere alcuni consigli per i venditori del Market MQL5.