English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
MQL5 Wizard: Come insegnare a un EA ad aprire ordini pendenti a qualsiasi prezzo

MQL5 Wizard: Come insegnare a un EA ad aprire ordini pendenti a qualsiasi prezzo

MetaTrader 5Esempi | 11 gennaio 2022, 17:05
482 0
Vladimir Karputov
Vladimir Karputov

Introduzione

Un Expert Advisor generato utilizzando la procedura guidata MQL5 può aprire gli ordini pendenti solo ad una distanza fissa dal prezzo corrente. Ciò significa che se la situazione del mercato cambia (ad esempio un cambiamento nella volatilità del mercato), l'Expert Advisor dovrà essere nuovamente eseguito con nuovi parametri.

Questo non sarebbe adatto per molti sistemi di trading. Nella maggior parte dei casi, il livello di prezzo per gli ordini pendenti è determinato dinamicamente da un sistema di trading. E la distanza dal prezzo corrente è in continua evoluzione. In questo articolo, discuteremo come modificare un Expert Advisor generato utilizzando la procedura guidata MQL5 in modo che possa aprire ordini pendenti a distanze variabili dal prezzo corrente.


1. Meccanismo di apertura degli ordini pendenti nell'Expert Advisor generato utilizzando la procedura guidata MQL5

Un Expert Advisor generato avrebbe approssimativamente lo stesso codice nella sua intestazione come fornito di seguito:

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string             Expert_Title="ExpertMySignalEnvelopes.mq5";      // Document name
ulong                    Expert_MagicNumber        =3915;        // 
bool                     Expert_EveryTick          =false;       // 
//--- inputs for main signal
input int                Signal_ThresholdOpen      =10;          // Signal threshold value to open [0...100]
input int                Signal_ThresholdClose     =10;          // Signal threshold value to close [0...100]
input double             Signal_PriceLevel         =0.0;         // Price level to execute a deal
input double             Signal_StopLevel          =85.0;        // Stop Loss level (in points)
input double             Signal_TakeLevel          =195.0;       // Take Profit level (in points)
input int                Signal_Expiration         =0;           // Expiration of pending orders (in bars)
input int                Signal_Envelopes_PeriodMA =13;          // Envelopes(13,0,MODE_SMA,...) Period of averaging
input int                Signal_Envelopes_Shift    =0;           // Envelopes(13,0,MODE_SMA,...) Time shift
input ENUM_MA_METHOD     Signal_Envelopes_Method   =MODE_SMA;    // Envelopes(13,0,MODE_SMA,...) Method of averaging
input ENUM_APPLIED_PRICE Signal_Envelopes_Applied  =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series
input double             Signal_Envelopes_Deviation=0.2;         // Envelopes(13,0,MODE_SMA,...) Deviation
input double             Signal_Envelopes_Weight   =1.0;         // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0]
//--- inputs for money
input double             Money_FixLot_Percent      =10.0;        // Percent
input double             Money_FixLot_Lots         =0.1;         // Fixed volume
//+------------------------------------------------------------------+

Si prega di notare il parametro Signal_PriceLevel. Per impostazione predefinita, Expert Advisor viene generato con Signal_PriceLevel=0. Questo parametro definisce la distanza dal prezzo corrente. Se è uguale a zero, verrà aperto un ordine al prezzo corrente di mercato. Per aprire un ordine pendente, è necessario impostare un valore diverso da zero per il parametro Signal_PriceLevel, ovvero Signal_PriceLevel può essere sia negativo che positivo.

Il valore di Signal_PriceLevel è di solito un numero abbastanza grande. La differenza tra valori negativi e positivi è mostrata di seguito:

Signal_PriceLevel=-50:

Fig. 1. Signal_PriceLevel=-50

Fig. 1. Signal_PriceLevel=-50

Signal_PriceLevel=50:

Fig. 2. Signal_PriceLevel=50

Fig. 2. Signal_PriceLevel=50

Pertanto, se Signal_PriceLevel = -50, un ordine pendente verrà aperto al prezzo meno favorevole del prezzo corrente, mentre se Signal_PriceLevel = 50, un ordine pendente verrà aperto al prezzo migliore del prezzo corrente.

Questa versione di Expert Advisor apre gli ordini Sell Stop e Buy Stop.


2. Dove memorizziamo i dati sulla distanza dal prezzo per l'apertura di un ordine pendente?

Diamo prima un'occhiata alla figura qui sotto e poi procediamo ai commenti:

Fig. 3. Memorizzazione dei dati sulla distanza dal prezzo corrente

Fig. 3. Memorizzazione dei dati sulla distanza dal prezzo corrente

Interpretazione della figura di cui sopra.

Expert Advisor è l'Expert Advisor generato utilizzando la procedura guidata MQL5.

  • L'oggetto ExtExpert della classe CExpert viene dichiarato in Expert Advisor a livello globale. 
  • Quindi, nella funzione OnInit() di Expert Advisor, dichiariamo un puntatore all'oggetto segnale della classe CExpertSignal e l'oggetto segnaleviene immediatamente creato utilizzando il nuovo operatore.
  • Pur essendo nella funzione OnInit(), chiamiamo la funzione InitSignal dell'oggetto ExtExpert e inizializziamo l'oggetto segnale.
  • Pur essendo nella funzione OnInit(), chiamiamo la funzione PriceLevel dell'oggetto segnale che ottiene il parametro Signal_PriceLevel.

Pertanto, il parametro Signal_PriceLevel in cui viene memorizzata la distanza dal prezzo corrente e che è stato dichiarato nell'Expert Advisor viene passato all'oggetto segnale della classe CExpertSignal.

La classe CExpertSignal memorizza il valore della distanza dal prezzo corrente nella variabile m_price_level dichiarata con l'ambito della classe protetta:

class CExpertSignal : public CExpertBase
  {
protected:
   //--- variables
   double            m_base_price;     // base price for detection of level of entering (and/or exit?)
   //--- variables for working with additional filters
   CArrayObj         m_filters;        // array of additional filters (maximum number of fileter is 64)
   //--- Adjusted parameters
   double            m_weight;         // "weight" of a signal in a combined filter
   int               m_patterns_usage; // bit mask of  using of the market models of signals
   int               m_general;        // index of the "main" signal (-1 - no)
   long              m_ignore;         // bit mask of "ignoring" the additional filter
   long              m_invert;         // bit mask of "inverting" the additional filter
   int               m_threshold_open; // threshold value for opening
   int               m_threshold_close;// threshold level for closing
   double            m_price_level;    // level of placing a pending orders relatively to the base price
   double            m_stop_level;     // level of placing of the "stop loss" order relatively to the open price
   double            m_take_level;     // level of placing of the "take profit" order relatively to the open price
   int               m_expiration;     // time of expiration of a pending order in bars


3. Struttura di Expert Advisor generata utilizzando la procedura guidata MQL5

L'Expert Advisor è composto da diversi blocchi con diverse funzionalità.


Fig. 4. Struttura dell'Expert Advisor 

Fig. 4. Struttura dell'Expert Advisor

Interpretazione della figura di cui sopra:

  • Expert Advisor è l'Expert Advisor generato utilizzando la procedura guidata MQL5.
  • CExpert è la classe base per l'implementazione di strategie di trading.
  • CExpertSignal è la classe base per la creazione di generatori di segnali di trading.
  • filtro0 ... filtron sono generatori di segnali di trading, i discendenti della classe CExpertSignal. Va notato che il nostro sistema di trading si basa sul generatore di segnali di trading dell'indicatore Envelopes, ma i segnali all'interno del generatore sono stati modificati. Parleremo di questi cambiamenti nella sezione 7.


4. Blocchi di Expert Advisor consigliabili per la modifica

Come si può vedere dalla struttura di Expert Advisor generata utilizzando la procedura guidata MQL5, ci sono blocchi di classe base. Le classi base fanno parte della libreria standard.

Le classi di per sé sono discendenti di altre classi base e a loro volta sono costituite da una o più classi base. Di seguito puoi trovare le prime righe del codice di due classi - CExpert e CExpertSignal:

//+------------------------------------------------------------------+
//|                                                       Expert.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
#include "ExpertTrade.mqh"
#include "ExpertSignal.mqh"
#include "ExpertMoney.mqh"
#include "ExpertTrailing.mqh"
//+------------------------------------------------------------------+
.
.
.
class CExpert : public CExpertBase

e

//+------------------------------------------------------------------+
//|                                                 ExpertSignal.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
.
.
.
class CExpertSignal : public CExpertBase

Sono fortemente contrario a qualsiasi modifica delle classi base:

  1. Quando MetaEditor viene aggiornato, tutte le modifiche apportate alle classi base vengono ignorate e le classi base vengono ripristinate allo stato iniziale.
  2. L'eredità sarebbe più appropriata in questo caso. Ma poi dovrai modificare l'INTERA libreria standard.

Invece, sarebbe meglio modificare il blocco dei moduli Expert Advisor e generatore di segnali di trading, soprattutto perché il nostro sistema di trading avrà già un modulo modificato in uso - il generatore di segnali di trading dell'indicatore Envelopes.

Quindi, questo è risolto:apporteremo modifiche ai blocchi dell'Expert Advisor e al blocco del generatore di segnali di trading.


5. La logica di implementazione

Il puntatore verrà passato dall'Expert Advisor al generatore di segnali di trading.

A tale scopo, è inoltre necessario dichiarare una variabile con l'ambito protetto e scrivere un metodo che memorizza il puntatore di Expert Advisor nella variabile interna:


  Fig. 5. La logica di implementazione

Fig. 5. La logica di implementazione


6. Sistema di trading

L'intervallo di tempo del grafico è D1. L'indicatore da utilizzare è Buste con il periodo medio di 13 e metodo di media esponenziale. I tipi di ordini che l'Expert Advisor può aprire sono Sell Stop e Buy Stop.

Se la barra precedente era rialzista, impostiamo un ordine Sell Stop. Se la barra precedente era ribassista, impostiamo un ordine Buy Stop. In altre parole, speriamo nel pullback:

Fig. 6. Sistema di trading

Fig. 6. Sistema di trading

Per generare segnali di trading come richiesto dal sistema di trading, il modulo standard del generatore di segnali di trading SignalEnvelopes.mqh è stato modificato.

Si noti che qui è possibile utilizzare qualsiasi generatore di segnali di trading dalla libreria standard.


7. Modifica del generatore di segnali di trading. Ottenere il prezzo della barra

Quindi, iniziamo. Devo dire che preferisco salvare i miei programmi in MQL5 Storage.

La prima cosa che dovremmo fare per iniziare a modificare il generatore di segnali di trading è creare un file di include vuoto, eliminare tutto da esso e incollare l'intero contenuto del generatore di segnali di trading standard dell'indicatore Envelopes.

Per impostazione predefinita, il generatore di segnali di trading deve trovarsi sotto ...MQL5\Include\Expert\Signal. Per non sovraccaricare il ...\Cartella segnale della libreria standard con troppe informazioni, creiamo una nuova cartella sotto il ...\Expert cartella e chiamarlo \MySignals:

Fig. 7. Creazione della cartella MySignals

Fig. 7. Creazione della cartella MySignals

Successivamente, creeremo un file di inclusione utilizzando la procedura guidata MQL5.

In MetaEditor, seleziona "Nuovo" nel menu File, quindi seleziona "Includi file (*.mqh)".

Fig. 8. Procedura guidata MQL5. Creazione di un file di inclusione

Fig. 8. MQL5 Wizard. Creare un file include

Il nome della nostra classe di generatori di segnali sarà MySignalEnvelopes.

E si troverà sotto: Include\Expert\MySignals\MySignalEnvelopes. Specifichiamolo:

Fig. 9. Procedura guidata MQL5. Posizione del file di include

Fig. 9. MQL5 Wizard. Percorso del file di include

Dopo aver fatto clic su "Fine", la procedura guidata MQL5 genererà un modello vuoto.

Il file MySignalEnvelopes.mqh generato deve quindi essere aggiunto all'archiviazione MQL5:

Fig. 10. Archiviazione MQL5. Aggiunta del file

Fig. 10. MQL5 Storage. Aggiunta del file

Una volta aggiunto il file, è necessario eseguire il commit delle modifiche a MQL5 Storage:

Fig. 11. Archiviazione MQL5. Committing delle modifiche

Fig. 11. MQL5 Storage. Impegnare le modifiche

Dopo aver completato i passaggi precedenti, possiamo procedere alla modifica del nostro generatore di segnali di trading.

Poiché il generatore è basato sul file \Include\Expert\Signal\SignalEnvelopes.mqh, copiamo l'intero contenuto del file e lo incolliamo nel file generatore, lasciando solo l'intestazione originale:

//+------------------------------------------------------------------+
//|                                            MySignalEnvelopes.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2013, Vladimir Karputov"
#property link      "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.                              |
//| 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 timeseries
   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 timeseries 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 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 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);
  }
//+------------------------------------------------------------------+

Ora, lavoreremo sulle modifiche di alcune parti del codice.

Per evitare confusione, il codice modificato verrà evidenziato:

//+------------------------------------------------------------------+
//|                                                     MySignal.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+

Il codice modificato è il codice che deve essere copiato e incollato nel generatore di segnali di trading. Spero che tale evidenziazione ti aiuti a capire meglio il codice.

Poiché stiamo scrivendo la nostra classe del generatore di segnali di trading, il suo nome dovrebbe essere diverso dal nome della classe base. Sostituiamo quindi CSignalEnvelopes con CMySignalEnvelopes in tutto il codice:

Fig. 12. Rinominare la classe

Fig. 12. Ridenominazione della classe

Per assicurarsi che la classe del generatore di segnali di trading venga visualizzata nella procedura guidata MQL5 sotto il suo nome, modificare il nome della classe nel blocco di descrizione

//| Title=Signals of indicator 'Envelopes'                           |

a

//| Title=Signals of indicator 'MySignalEnvelopes'                   |

Modificare il valore del periodo MA

//| Parameter=PeriodMA,int,45,Period of averaging                    |

a 13 (questo è solo il mio suggerimento, puoi impostare qualsiasi valore tu preferisca)

//| Parameter=PeriodMA,int,13,Period of averaging                    |

Inoltre, modifichiamo anche il parametro Deviazione

//| Parameter=Deviation,double,0.15,Deviation                        |

impostando un valore maggiore

//| Parameter=Deviation,double,1.15,Deviation                        |

Secondo la nostra logica di implementazione, dobbiamo dichiarare una variabile interna che memorizzerà il puntatore al segnale principale.

Poiché questa deve essere una variabile interna (solo nell'ambito della classe del generatore di segnali di trading), verrà aggiunta al seguente blocco di codice:

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
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0
   CExpertSignal    *m_signal;         // storing the pointer to the main signal

Si prega inoltre di notare che ho eliminato le variabili non necessarie dal codice. 

Il metodo per memorizzare il puntatore al segnale principale verrà dichiarato in un altro blocco di codice - il "metodo di impostazione del puntatore sul segnale principale". Qui, ho anche eliminato alcuni metodi irrilevanti.

public:
                     CMySignalEnvelopes(void);
                    ~CMySignalEnvelopes(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;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);
   //--- method of setting the pointer to the main signal
   virtual bool      InitSignal(CExpertSignal *signal=NULL);

Specifichiamo ora alcuni parametri modificati nel costruttore ed eliminiamo le variabili che non sono più necessarie:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13),
                                               m_ma_shift(0),
                                               m_ma_method(MODE_SMA),
                                               m_ma_applied(PRICE_CLOSE),
                                               m_deviation(1.15),
                                               m_pattern_0(50)  

A questo punto, possiamo procedere a modificare la logica di generazione del segnale di trading in base al nostro sistema di trading.

Il blocco di codice responsabile di un segnale di acquisto:

int CMySignalEnvelopes::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);
  }

sarà come mostrato di seguito, a seguito delle modifiche necessarie:

int CMySignalEnvelopes::LongCondition(void) //---buy
  {
   int result=0;
   int idx   =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close<open)
        {
         prlevel=GetPriceLevelStopp(open,Open(0));
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }

Il blocco di codice responsabile di un segnale di vendita:

int CMySignalEnvelopes::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);
  }

sarà come mostrato di seguito, a seguito delle modifiche necessarie:

int CMySignalEnvelopes::ShortCondition(void) //---sell
  {
   int result  =0;
   int idx     =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close>open)
        {
         prlevel=GetPriceLevelStopp(Open(0),open);
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }


8. Alcuni commenti sul blocco del codice del segnale

Se viene soddisfatta la condizione richiesta per un determinato segnale, chiamiamo il metodo GetPriceLevelStopp che restituisce un numero come "20" o "15" - il valore della distanza dal prezzo corrente.

Questo è seguito dalla chiamata al metodo PriceLevel dell'oggetto m_signal (che imposta la distanza per determinare il prezzo a livello di ordine pendente). Va ricordato che m_signal è l'oggetto classe CExpertSignal che memorizza il puntatore al segnale principale.

Il codice del metodo GetPriceLevelStopp è fornito di seguito:

double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
  {
   double level;
   double temp;
   temp-=(price_0-min)/PriceLevelUnit();
   level=NormalizeDouble(temp,0);
   return(level);
  }

Dobbiamo dichiarare questo metodo nell'intestazione della classe:

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)); }
   double            GetPriceLevelStopp(double price,double min);
  };

Un altro metodo di cui avremo bisogno è il metodo di passaggio del puntatore al segnale principale alla variabile interna:

bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
  {
   m_signal=signal;
   return(true);
  }

 Dopodiché dovremmo creare un Expert Advisor nella procedura guidata MQL5 e includere in esso il modulo di segnale 'MySignalEnvelopes'.

È inoltre necessario aggiungere la chiamata al metodo InitSignal al codice di Expert Advisor generato utilizzando la procedura guidata MQL5:

//--- Set filter parameters
   filter0.PeriodMA(Signal_Envelopes_PeriodMA);
   filter0.Shift(Signal_Envelopes_Shift);
   filter0.Method(Signal_Envelopes_Method);
   filter0.Applied(Signal_Envelopes_Applied);
   filter0.Deviation(Signal_Envelopes_Deviation);
   filter0.Weight(Signal_Envelopes_Weight);
   filter0.InitSignal(signal);
//...

Per una migliore visualizzazione del funzionamento dell'Expert Advisor, ho fornito un breve video:

Il codice di Expert Advisor generato utilizzando la procedura guidata MQL5, così come il codice del modulo di segnale, è allegato all'articolo.

Di seguito puoi vedere i risultati dei test dell'Expert Advisor. È stato testato per EURUSD e USDJPY con i seguenti parametri: periodo di test 2013.01.01 - 2013.09.01, intervallo di tempo - D1, livello di Stop Loss = 85, livello di Take Profit = 195.

Fig. 13. Test per EURUSD su D1

Fig. 13. Test per EURUSD su D1

Fig. 14. Test per USDJPY su D1

Fig. 14. Test per USDJPY su D1


Conclusione

Abbiamo appena visto come possiamo modificare il codice del modulo del segnale di trading per l'implementazione della funzionalità che ci consente di impostare gli ordini pendenti a qualsiasi distanza dal prezzo corrente: può essere il prezzo di chiusura o apertura della barra precedente o il valore della media mobile. Ci sono molte opzioni. Importante è che è possibile impostare qualsiasi prezzo di apertura per un ordine pendente.

L'articolo ha dimostrato come possiamo accedere al puntatore al segnale principale, e quindi ai metodi della classe CExpertSignal.   Credo che l'articolo si rivelerà utile per i trader che commerciano con ordini pendenti.


Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/723

Stupisci i tuoi clienti MQL5 con un cocktail di tecnologie! Stupisci i tuoi clienti MQL5 con un cocktail di tecnologie!
MQL5 fornisce ai programmatori un set molto completo di funzioni e API orientate agli oggetti grazie alle quali possono fare tutto ciò che vogliono all'interno dell'ambiente MetaTrader. Tuttavia, la tecnologia Web è uno strumento estremamente versatile al giorno d'oggi. Essa può venire in soccorso in alcune situazioni in cui è necessario fare qualcosa di molto specifico, oppure quando vuoi stupire i tuoi clienti con qualcosa di diverso o semplicemente quando non si ha abbastanza tempo per padroneggiare una parte specifica della libreria standard MT5. L'esercizio di oggi ti guida attraverso un esempio pratico su come puoi gestire il tuo tempo di sviluppo allo stesso tempo in cui crei anche un fantastico cocktail tecnologico.
Costruire un trader automatico di notizie Costruire un trader automatico di notizie
Questa è la continuazione di un altro articolo sulla classe OOP MQL5 che ha mostrato come costruire un semplice EA OO da zero, dando alcuni suggerimenti sulla programmazione orientata agli oggetti. Oggi vi mostro le basi tecniche necessarie per sviluppare un EA in grado di scambiare le notizie. Il mio obiettivo è quello di continuare a darti idee su OOP e anche coprire un nuovo argomento in questa serie di articoli, lavorando con il file system.
Aumenta all’ennesima potenza i tuoi sistemi di trading lineare Aumenta all’ennesima potenza i tuoi sistemi di trading lineare
L'articolo di oggi mostra ai programmatori MQL5 di livello intermedio come possono ottenere maggiori profitti dai loro sistemi di trading lineare (Fixed Lot) implementando facilmente la cosiddetta tecnica di esponenziazione. Questo perché la crescita della curva azionaria risultante è quindi geometrica, o esponenziale, assumendo la forma di una parabola. Nello specifico, implementeremo una pratica variante MQL5 del dimensionamento a posizione frazionaria fissa sviluppato da Ralph Vince.
Creazione di EA di reti neurali utilizzando MQL5 Wizard e Hlaiman EA Generator Creazione di EA di reti neurali utilizzando MQL5 Wizard e Hlaiman EA Generator
L'articolo descrive un metodo di creazione automatizzata di EA di reti neurali utilizzando MQL5 Wizard e Hlaiman EA Generator. Ti mostra come puoi facilmente iniziare a lavorare con le reti neurali, senza dover imparare l'intero corpo di informazioni teoriche e ti mostra come scrivere il tuo codice.