English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
Handelssignal-Generator auf Grundlage eines angepassten Indikators

Handelssignal-Generator auf Grundlage eines angepassten Indikators

MetaTrader 5Beispiele | 4 Mai 2016, 16:26
1 102 0
Vladimir Karputov
Vladimir Karputov

Einleitung

Dieser Beitrag erklärt Ihnen, wie man einen Handelssignal-Generator auf Grundlage eines angepassten Indikators erzeugt. Sie erfahren hier, wie Sie Ihr eigenes Handelsmodell für einen angepassten Indikator schreiben können. Des Weiteren erkläre ich Ihnen auch den Zweck des Modell 0 und warum die Strukturen vom Typ IS_PATTERN_USAGE(0) im Handelssignal-Modul verwendet werden.

Dieser Beitrag verwendet zwei Arten von Code: denjenigen, den wir verändern werden und denjenigen, den wir bereits verändert haben. Der veränderte Code wird folgendermaßen hervorgehoben:

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

Dieser Code muss kopiert und in den Handelssignal-Generator eingefügt werden. Ich hoffe das die farbliche Hervorhebung Ihnen beim Verständnis des Codes hilft. 

 

1. Angepasster Indikator

Ich bin sicher, dass in dem Standardpaket, mit dem Sie schon so lange endlich einmal arbeiten wollten, irgendeiner Indikator nicht dabei ist. Und das ist der Indikator auf dessen Grundlage Sie ein Handelssignal-Modul bauen möchten. Ich verwende den MACD-Indikator aus dem Standardpaket als diesen Indikator. Dieser Indikator findet sich hier: ...MQL5\Indicators\Examples\MACD.mq5

Jeder Indikator kann eines oder mehrere Marktmodelle beschreiben. Ein Marktmodell ist eine gewisse Kombination des Indikatorwerts und des Kurswerts. Die für den MACD-Indikator verfügbaren Modelle sind Umkehrung, Kreuzen der Haupt- und Signallinie, Kreuzen der Null-Ebene, Abweichung und doppelte Abweichung.

1.1 Neues Indikator-Modell.

Gehen wir mal davon aus, dass wir mit den gegebenen Marktmodelle, die für den Indikator zur Verfügung stehen, nicht zufrieden sind, und daher unser eigenes Indikator-Modell einführen möchten. Beschreibung des neuen Indikatormodells: ist der MACD-Indikator unter der Nulllinie und nehmen seine Werte zu, können wir mit weiterem Wachstum rechnen und eine Long Position eröffnen:

Abb. 1 Modell des voraussichtlichen Indikatorwachstums 

Abb. 1 Modell des voraussichtlichen Indikatorwachstums

ist der MACD-Indikator über der Nulllinie und nehmen seine Werte ab, können wir mit weiterer Abnahme rechnen und eine Short Position eröffnen:

 Abb. 2 Modell des voraussichtlichen Indikatorabnahme

Abb. 2 Modell des voraussichtlichen Indikatorabnahme 

Also haben wir uns für den angepassten Indikator entschieden und für den Indikator und seine Beschreibung das neue Handelsmodell entwickelt. Sehen wir uns nun an, wie man seinen Code schreibt.

 

2. Den Handelssignal-Generator auf Grundlage unseres angepassten Indikators schreiben

Unser Generator ist ein Nachkomme der CExpertSignal Basisklasse. Die CExpertSignal Basisklasse ist eine Klasse zur Erzeugung von Handelssignal-Generatoren. Die CExpertSignal Klasse enthält ein Set public (d.h. extern zugänglicher) Methoden mit denen ein Expert Advisor den Anhaltspunkt des Handelssignal-Generators im Hinblick auf die Richtung des Eintritts in den Markt sehen kann.

Da wir ja mit unserem eigenen Handelssignal-Generator arbeiten, sollt er aus der CExpertSignal Klasse geerbt sein, zusammen mit den neu definierten, relevanten virtuellen Methoden (also mit dem entsprechenden Code befüllt).

 

3. Die Klasse des Handelssignal-Generators erzeugen

Standardmäßig sollte sich der Handelssignal-Generator im Ordner ...MQL5\Include\Expert\Signal befinden. Um den ...\Signal Ordner der Standard-Library nicht mit zu viel Information zu überladen, legen wir einen neuen Ordner im ...\Expert Ordner an und nennen diesen \MySignals:

Abb. 3 Den neuen MySignals Ordner anlegen  

Abb. 3 Den neuen MySignals Ordner anlegen 

Als nächstes erzeugen wir mit Hilfe des MQL5-Assistenten eine Miteinschliessen Datei. Dazu im MetaEditor, im Dateimenü auf "Neu" gehen und dann "Datei miteinschliessen (*.mqh)" wählen.

Abb. 4 MQL5-Assistent. Eine Miteinschliessen Datei anlegen

Abb. 4 MQL5-Assistent. Eine Miteinschliessen Datei anlegen

Der Name der Klasse des Signal-Generators ist MySignal. Sie findet sich in Include\Expert\MySignals\MySignal. Legen wir sie fest:

Abb. 5 MQL5-Assistent. Standort der Miteinschliessen Datei

Abb. 5 MQL5-Assistent. Standort der Miteinschliessen Datei

Nach Klicken auf "Abschließen" erzeugt der MQL5-Assistent ein leeres Template. Ab jetzt müssen wir alles manuell erledigen und Daten kopieren und einfügen. An dieser Stelle möchte ich darauf hinweisen, dass intern alle Signale aus der Standard Library fast identisch sind. Ihr einziger Unterschied liegt in den zur Feststellung der Handelsmodelle verwendeten Algorithmen.

Daher können Sie jede beliebige Datei aus dem \Include\Expert\Signal Ordner hernehmen, ihren Inhalt kopieren und ihn in Ihr Template einfügen. Die so entstandene Datei des Handelssignal-Generators können Sie dann bearbeiten.

 

4. Beschreibung der Klasse des Handelssignal-Generators

Ich habe die \Include\Expert\Signal\SignalEnvelopes.mqh Datei als Template genommen und von dort alles außer der Kopfzeile:
//+------------------------------------------------------------------+
//|                                              SignalEnvelopes.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+

kopiert und das alles in unser fast leeres MySignal.mqh Template eingefügt. Und das habe ich bekommen: 

//+------------------------------------------------------------------+
//|                                                     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);
  }
//+------------------------------------------------------------------+

Beachten Sie Zeile 6:

#include <Expert\ExpertSignal.mqh>

Hier geben wir dem Präprozessor die Anweisung, die CExpertSignal Basisklasse zur Erzeugung von Handelssignal-Generatoren in unser Template miteinzuschliessen.

Wir bearbeiten das Template gleich weiter. Um sicherzustellen, dass unser Template auch später noch für den MQL5-Assistenten sichtbar ist, müssen wir die Beschreibung unserer Klasse ändern:

//+------------------------------------------------------------------+
//| 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                        |
//+------------------------------------------------------------------+

Schau'n wir mal. Die Zeile:

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

 zeigt den Namen unserer Signal-Klasse unter dem es im MQL5-Assistenten angezeigt wird. Diesen Namen verändern wir ungefähr so:

//| Title=Signal of the 'Custom Indicator' indicator             |

Die nächste Zeile: 

//| Name=Envelopes                                                   |

gibt den Namen zur Beschreibung der Variablen unserer Handelssignal-Klasse an. Der MQL5-Assistent verwendet diese Beschreibung später. Verändern wir diese Zeile in etwa so:

//| Name=MyCustomIndicator                                           |

Die nächste Zeile:

//| ShortName=Envelopes                                              |

Diesem Parameter geben wir den gleichen Namen:

//| ShortName=MyCustomIndicator                                      |

Die folgende Zeile legt den Namen der Klasse fest:

//| Class=CSignalEnvelopes                                           |

Diesen Parameter benennen wir um:

//| Class=CSignalMyCustInd                                           |

Der nächste Parameter bleibt unverändert.

//| Page=signal_envelopes                                            |

Die folgende Gruppe an Parametern ist zuständig für die Beschreibung der Parameter des dem Handelssignal-Generators zugrunde liegenden Indikators. Wie vorhin schon erwähnt, verwende ich ...MQL5\Indicators\Examples\MACD.mq5 als den angepassten Indikator. Er hat die folgenden Parameter:

//--- 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 Parameter-Beschreibungsblock 

Bitte beachten Sie, dass die oben angegebenen Parameter nur für MACD.mq5 gelten. Ihr angepasster Indikator kann daher komplett andere Parameter haben. Die wichtigste Aufgabe hier ist, die Indikator-Parameter auf die Beschreibung in der Handelssignal-Klasse anzugleichen. Der Parameter-Beschreibungsblock in der Handelssignal-Klasse für den angepassten Indikator, den wir wollen, nämlich MACD.mq5, lautet so:

//| 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   |

Betrachten Sie sich kurz wie jetzt die Parameter im Indikator mit den Beschreibungen im Klassen-Beschreibungsblock übereinstimmen. Nach all diesen Veränderungen lautet der Beschreibungsblock unserer Klasse wie folgt:

//+------------------------------------------------------------------+
//| 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   |
//+------------------------------------------------------------------+

Es hat sich beim Programmieren bewährt, seinen Code mit Anmerkungen zu versehen, damit er, wenn man nach einiger Zeit wieder mit ihm arbeitet. leichter verstanden werden kann. Daher verändern wir den folgenden Block: ,

//+------------------------------------------------------------------+
//| Class CSignalEnvelopes.                                          |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Envelopes' indicator.                              |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+

damit er mit unserer Klasse übereinstimmt:

//+------------------------------------------------------------------+
//| Class CSignalMyCustInd.                                          |
//| Purpose: Class of the trading signal generator based on          |
//|          the custom indicator.                                   |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+

Damit keine Verwirrung entsteht, müssen wir alle "CSignalEnvelopes" Werte durch "CSignalMyCustInd" ersetzen

Abb. 6 Ersetzen von CSignalEnvelopes durch CSignalMyCustInd

Abb. 6 Ersetzen von CSignalEnvelopes durch CSignalMyCustInd 

Betrachten wir uns nun einige theoretische Aspekte.

 

5. Die CiCustom Klasse

Die CiCustom Klasse muss weiterhin auf dem Code der Handelsindikatoren-Klasse des angepassten Indikators arbeiten können. Die CiCustom Klasse wurde speziell zur Arbeit mit angepassten Indikatoren erzeugt. Mit der CiCustom Klasse lassen die Daten des angepassten Indikators erzeugen, einrichten und darauf zugreifen.

 

6. Die CIndicators Klasse.

CIndicators ist die Klasse zur Sammlung von Instanzen an Zeitreihen und technischen Indikatorklassen. Mit der CIndicators Klasse lassen sich die Klasseninstanzen technischer Indikatoren erzeugen, ablegen und verwalten (Datensynchronisierung, Handle- und Memoryverwaltung).

Uns interessiert vor allem die CIndikators Klasse wegen der Create Methode. Diese Methode erzeugt einen Indikator eines festgelegten Typs mit spezifizierten Parametern.

 

7. Unsere Handelssignal-Klasse weiter schreiben

Der nächste Codeblock, den wir verändern (Zeilen 28-42), lautet folgendernmaßen:
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. Erzeugen des angepassten Indikators im Handelssignal-Generator

Betrachten Sie sich kurz den oben gezeigten Codeblock. Die Zeile

   CiEnvelopes       m_env;            // object-indicator

deklariert ein Objekt - den CiEnvelopes Klassen-Indikator. CiEnvelopes ist die Klasse zur Arbeit mit dem technischen Indikator aus der Standard-Library. Die CiEnvelopes Klasse wurde auf Grundlage des technischen Indikators aus der Standard Library erzeugt. Wir schreiben jedoch den Generator-Code auf Grundlage unseres des angepassten Indikators. Daher gibt es für unseren oder Ihren angepassten Indikator keine fertige Klasse in der Standard-Library. Wir können allerdings die CiCustom Klasse verwenden und

unseren Indikator als die CiCustom Klasse deklarieren:

   CiCustom          m_mci;            // indicator object "MyCustomIndicator"

8.1 Vier Variablen

Erinnern Sie sich noch an den Parameter-Beschreibungsblock in der Klasse? In dieser Beschreibung kamen drei Parameter vor. Im geschützten Bereich unserer Generator-Klasse deklarieren wuir daher jetzt vier Variablen zur Übertragung der Werte auf unsere vier Parameter:

   //--- 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"

Der folgende Codeblock:

   //--- "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"

Dieser Code deklariert Variablen, die den Handelsmodellen unseres Handelssignal-Generator eine "Gewichtung" geben. Ersetzen wir den "Gewichtungs"-Block mit folgendem Code:

   //--- "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. Modell 0

Vielleicht wissen Sie noch, dass zu Beginn dieses Beitrags beschlossen wurde, nur ein neues Modell zu beschreiben, dass von unserem Handelssignal-Generator generiert wird. Im obigen Code habe ich jedoch zwei Marktmodelle festgelegt (Modell 0 und Modell 1). Modell 0 ist in unserem Fall ein wichtiges Hilfs-Modell, da es beim Handel mit pending Orders erforderlich ist. Modell 0, wenn es angewendet wird, stellt sicher, dass sich pending Order zusammen mit dem Kurs bewegen. Sehen wir uns unseren Handelssignal-Generator und die folgenden Bedingungen kurz an:

  • der MACD angepasste Indikator befindet sich unterhalb der Nulllinie,
  • und seine Werte steigen an,
  • wir handeln mit pending Orders, die 50 Punkte vom Bar-Eröffnungskurs gesetzt sind (vierstelliger Kurswert).

Diese Bedingungen beschreiben perfekt unser Handelsmodell. Und so bewegt sich dann alles: Die Bedingungen unseres Handelsmodells werden bei Auftreten des Bar Nr. 1 geprüft. Wir haben: MACD befindet sich unter der Nulllinie, nimmt jedoch an Fahrt zu. Das entspricht dem Buy-Signal. Also platzieren wir eine pending Buy Stop Order:

Abb. 7 Eine pending Buy Stop Order platzieren
 Abb. 7 Eine pending Buy Stop Order platzieren 

Bei Auftreten des nächsten Bars, Nr. 2, ergibt die Prüfung der Bedingung, dass sich MACD unterhalb von Null befindet und abnimmt. Gemäß unseres Handelsmodell sind aktuelle keine Bedingungen für Kaufen oder Verkaufen vorhanden. Beachten Sie jedoch bitte: nach der Logik der CExpertSignal-Klasse sollten, da es ja weder Bedingungen für Kaufen noch Verkaufen gibt, allen pending Orders GELÖSCHT werden. In diesem Fall verpassen wir, sollte der Kurs plötzlich und deutlich ansteigen, die Chance, in den Markt lang zu unserem Vorteil einzusteigen, da es ja keine pending Order mehr gibt.

Und hier kommt das Hilfs-Modell 0 als extrem hilfreich ins Spiel. Das Hilfs-Modell 0 greift ein, wenn:

  • sich der MACD angepasste Indikator unterhalb der Nulllinie befindet.

Daher können wir eine pending Buy Stop Order platzieren. Da wir eine Order 50 Punkte vom Bar-Eröffnungskurs platzieren, verschieben wir tatsächlich die pending Buy Stop Order in Übereinstimmung mit der Kursbewegung:

Abb. 8 Verschieben der Buy Stop Order nach unten
  Abb. 8 Verschieben der Buy Stop Order nach unten 

Wenn wir uns also des Hilfsmodells 0 bedienen, erhalten wir die Möglichkeit, eine pending Order je nach Kursbewegung verschieben zu können.

 

10. Weitere Veränderungen des Template-Codes

Der nächste Codeblock, der verändert werden muss, ist folgender: 
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 diesem Block deklarieren wir Methoden zur Einrichtung anpassbarer Parameter, Methoden zur Anpassung der Gewichtungen der Handelsmodelle, Methode zur Überprüfung der Einstellungen, die Methode zur Indikator-Initialisierung und Methoden zur Prüfung, ob Marktmodelle generiert worden sind.

Unter Berücksichtigung, dass wir in den anpassbaren Parametern vier Variablen deklariert haben, sieht der Block der Methoden zur Einrichtung der Parameter folgendermaßen aus:

   //--- 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;               }

Das nächste Codefragment bleibt unverändert:

   //--- 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);

Der nächste Codeblock wird folgendermaßen verändert: 

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)); }
  };

Hier nehmen wir starke Veränderungen vor. Bitte beachten Sie, dass ich mit der GetData Methode der CIndicator Klasse arbeite. Die Namen der aufgerufenen Methoden werden direkt im Code bereitgestellt:

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);
  };

 Der nächste Codeblock ist der Constructor.

//+------------------------------------------------------------------+
//| 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;
  }

Hier verändern wir die Namen der Variablen. In Zukunft werden wir nur zwei Reihen verwenden : 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;
  }

Verändern wir nun auch die ValidationSettings Methode unserer Klasse.

//+------------------------------------------------------------------+
//| 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);
  }

Im Kästchen kreuzen wir die Hauptbedingung für den gegebenen angepassten Indikator an: 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);
  }

Der nächste Block ist für die Erzeugung von Indikatoren zuständig:

//+------------------------------------------------------------------+
//| 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);
  }

Wie auf unseren angepassten Indikator angewendet: 

//+------------------------------------------------------------------+
//| 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);
  }

Der folgende Block ist der Block zur Initialisierung des Indikators:

//+------------------------------------------------------------------+
//| 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);
  }

Zunächst ergänzen wir die Sammlung um ein Objekt. Anschließend richten wir die Parameter unseres Indikators ein und erzeugen mit Hilfe der Create Methode der CIndicators Klasse den angepassten Indikator:

//+------------------------------------------------------------------+
//| 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);
  }

Der nächste Block prüft die Bedingungen für einen Kauf:

//+------------------------------------------------------------------+
//| "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);
  }

Gemäß unserer Implementierung von Modell 0, werden zwei Modelle überprüft:  

//+------------------------------------------------------------------+
//| "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);
  }

Der nächste Block prüft die Bedingungen für einen Verkauf:  

//+------------------------------------------------------------------+
//| "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);
  }

Gemäß unserer Implementierung von Modell 0, werden zwei Modelle überprüft:  

//+------------------------------------------------------------------+
//| "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);
  }

 

Fazit

Ich hoffe, dass Ihnen dieser Beitrag geholfen hat, zu verstehen, wie Sie einen Handelssignal-Generator auf Grundlage Ihres angepassten Indikators erzeugen können.


Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/691

Beigefügte Dateien |
mysignal.mqh (9.38 KB)
MQL5 Market - Ergebnisse für Q2/2013 MQL5 Market - Ergebnisse für Q2/2013
MQL5 Market, bereits seit 18 Monaten erfolgreich, ist zum größten Platz für Handelsstrategien und technische Indikatoren für Händler geworden. Dort findet man ca. 800 Handels-Anwendungen von 350 Entwicklern aus der ganzen Welt. Viele Händler haben bereits mehr als 100.000 Handelsprogramme gekauft und auf ihre MetaTrader 5 Terminals heruntergeladen.
MQL5 Market - Ergebnisse für Q1/2013 MQL5 Market - Ergebnisse für Q1/2013
Seit seiner Eröffnung hat der MQL5 Market, der Platz für Handelsroboter und technische Indikatoren, bereits mehr als 250 Entwickler angezogen, die 580 Produkte veröffentlicht haben. Das 1.Quartal 2013 hat sich für einige MQL5 Market Verkäufer als ziemlich erfolgreich erwiesen, da sie durch den Verkauf ihrer Produkte keine schlechten Gewinne einfahren konnten.
Sozialer Handel mit Hilfe der MetaTrader 4 und MetaTrader 5 Handelsplattformen Sozialer Handel mit Hilfe der MetaTrader 4 und MetaTrader 5 Handelsplattformen
Was ist Sozialer Handel? Sozialer Handel ist eine Kooperation von Händlern und Investoren mit Vorteilen für beide Seiten. Erfolgreiche Händler gestatten Einblicke in ihren Handel und potenzielle Investoren profitieren von diesen Einblicken und kopieren die Handel von denjenigen, die am vielversprechendsten aussehen.
Jeremy Scott - Erfolgreicher Verkäufer auf MQL5 Market Jeremy Scott - Erfolgreicher Verkäufer auf MQL5 Market
Jeremy Scott, in der MQL5.community besser bekannt unter seinem Pseudonym 'Johnnypasado', hat sich in unserem MQL5 Market einen Namen für sein Produktangebot gemacht. Jeremy hat im Market bereits mehrere Tausend Dollar verdient - und ist weiterhin erfolgreich. Daher haben wir uns diesen zukünftigen Millionär genauer angesehen und von ihm einige Tipps für andere Anbieter im MQL5 Market bekommen.