English 日本語
preview
Wie man ein volatilitätsbasiertes Handelssystem (Chaikin Volatility - CHV) aufbaut und optimiert

Wie man ein volatilitätsbasiertes Handelssystem (Chaikin Volatility - CHV) aufbaut und optimiert

MetaTrader 5Handel | 6 Juni 2024, 12:03
172 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Einführung

Im Bereich des Handels ist die Volatilität sehr wichtig. Das ist bekannt. Daher gibt es viele verwendbare Werkzeuge, um diesen Faktor zu messen. Wir können unsere Handelsentscheidungen also verbessern, wenn wir die Volatilität als Teil unseres Handelssystems berücksichtigen.

In diesem Artikel befassen wir uns mit einem dieser technischen Volatilitätsindikatoren, der Chaikin-Volatilität (CHV). In diesem Artikel erfahren Sie, was die Chaikin-Volatilität ist, was sie bedeutet, wie wir sie berechnen können und wie wir sie zu unseren Gunsten nutzen können, um bessere Handelsergebnisse zu erzielen. Wir werden den Indikator auf der Grundlage einfacher Handelsstrategien verwenden (CHV Crossover und CHV und MA Crossover).

Unser Ansatz besteht darin, zu verstehen, wie wir den Chaikin-Volatilitätsindikator als ein Volatilitätsinstrument betrachten können, um bessere Handelsergebnisse zu erzielen, die in Bezug auf die Volatilitätsmessung als Teil unseres Handelssystems zuverlässig sein können. Wir werden also lernen, wie man Handelssysteme auf der Grundlage von volatilitätsbasierten Strategien erstellt, und wir werden ein Beispiel dafür geben, wie wir unser Handelssystem optimieren können, indem wir einfache Strategien hinzufügen oder andere Tools kombinieren, um bessere Ergebnisse zu erzielen als ohne diese Optimierung. Wir werden auch lernen, wie wir unseren eigenen CHV-Indikator erstellen, der als Teil unseres Handelssystems verwendet werden kann.

Wie Sie wissen, ist es für jedes Handelssystem sehr wichtig, in verschiedenen Umgebungen getestet zu werden, bevor es für den realen Handel verwendet wird, um sicherzustellen, dass es nützlich und für Ihren Handel geeignet ist, da es keine Strategie gibt, die für jeden passt. Wir werden also einige einfache Tests für unser Handelssystem auf der Grundlage dieser beiden erwähnten Handelsstrategien durchführen, und ich möchte Sie ermutigen, Ihre Tests mit anderen Aspekten durchzuführen, als ich sie in diesem Artikel verwendet habe, um zu sehen, wie Sie Ihr System verbessern können, um bessere Ergebnisse zu erzielen als ich, oder sogar herauszufinden, dass dieses Tool für Ihr Handelssystem überhaupt nicht geeignet oder anwendbar ist.

Wir werden all dies in den folgenden Themen behandeln:

Es ist auch wichtig zu wissen, dass es sehr wichtig ist, selbst zu üben und Code zu schreiben, wenn man das Programmieren für den Handel oder das Programmieren im Allgemeinen erlernen will. Ich möchte Sie daher ermutigen, das, was Sie lernen, zu programmieren, da dies Ihre Programmierkenntnisse und -fähigkeiten verbessern kann.

Haftungsausschluss: Alle Informationen werden in der vorliegenden Form nur zu Informationszwecken bereitgestellt und sind nicht für Handelszwecke oder als Ratschläge gedacht. Die Informationen garantieren keinen Erfolg. Wenn Sie sich dafür entscheiden, diese Materialien auf einem Ihrer Handelskonten zu verwenden, tun Sie dies auf eigenes Risiko und Sie sind allein verantwortlich.


Chaikin-Volatilität

In diesem Teil werden wir den Chaikin-Volatilitätsindikator im Detail identifizieren. Der Chaikin-Volatilitätsindikator wurde von Marc Chaikin entwickelt, der viele technische Indikatoren geschaffen hat, die seinen Namen tragen. Die CHV wird verwendet, um die Volatilität in der Bewegung der Finanzmärkte zu messen und kann hilfreich sein, um potenzielle Marktumkehrungen zu antizipieren. Es kann nützlich sein, den Wertbereich zwischen hohen und niedrigen Preisen über einen bestimmten Zeitraum zu bestimmen, um potenzielle Bewegungen oder Marktschwankungen in beide Richtungen zu messen. Die CHV berücksichtigt Lücken nicht in der gleichen Weise, wie wir bei der Berechnung sehen werden. Es ist sehr wichtig zu beachten, dass eine zunehmende Volatilität ein hohes Risiko oder eine hohe Rendite bedeuten kann.

Der CHV-Indikator kann hohe oder niedrige Werte aufweisen, wobei steigende Werte bedeuten, dass sich die Preise sehr schnell ändern, während niedrige Werte bedeuten, dass die Preise konstant sind und der Basiswert nur wenig schwankt. Ich halte es für sehr wichtig zu erwähnen, dass die Volatilität auf Märkten mit und ohne Trend erfasst werden kann, nicht nur auf Märkten mit Trend, da wir die Volatilität und nicht den Trend oder die Richtung der Preise messen. Bei der Verwendung von anderen technischen Werkzeugen, die als eine Bestätigung auf die generierte es wird bessere Ergebnisse, und das ist, was wir tun, wie erwähnt, wie wir versuchen, unsere Entscheidungen mit dem gleitenden Durchschnitt technischen Indikator, um die Richtung des Marktes und nehmen trending Trades so viel wie möglich.

Wie bereits erwähnt, kann der CHV-Indikator zur Vorhersage von Marktumkehrungen verwendet werden, denn manchmal, wenn der Indikator relativ hohe Werte verzeichnet, kann dies zur Vorhersage von Umkehrungen und potenziellen Höchst- oder Tiefstständen auf dem Markt genutzt werden. Nun müssen wir verstehen, wie der CHV-Indikator berechnet wird, um das Hauptkonzept hinter dem Indikator zu vertiefen.

H-L (i) = HIGH (i) - LOW (i)

H-L (i - 10) = HIGH (i - 10) - LOW (i - 10)

CHV = (EMA (H-L (i), 10) - EMA (H-L (i - 10), 10)) / EMA (H-L (i - 10), 10) * 100

wobei:

  • HIGH (i) - bezieht sich auf das Hoch der i-ten Kerze.
  • LOW (i) - bezieht sich auf das Tief der i-ten Kerze.
  • HIGH (i - 10) - bezieht sich auf das Hoch der Kerze zehn Kerzen vor der i-ten.
  • LOW (i - 10) - bezieht sich auf das Tief der Kerze zehn Kerzen vor der i-ten.
  • H-L (i) - bezieht sich auf die Differenz zwischen dem Hoch und dem Tief der i-ten Kerze.
  • H-L (i - 10) - bezieht sich auf die Differenz zwischen dem Hoch und dem Tief zehn Kerzen vor der i-ten.
  • EMA - bezieht sich auf den exponentiellen gleitenden Durchschnitt.


Nutzerdefinierter Chaikin-Volatilitätsindikator

In diesem Abschnitt lernen wir, wie man einen nutzerdefinierten Chaikin-Volatilitätsindikator mit MQL5 programmiert, was nützlich sein kann, da wir den Indikator an unsere Ziele anpassen können. Im Folgenden werden die Schritte zur Programmierung unseres nutzerdefinierten Chaikin Volatility (CHV) Indikators beschrieben:

Verwenden Sie den Präprozessor #include, um die Include-Datei der gleitenden Durchschnitte im Programm und in der Berechnung verwenden zu können.

#include <MovingAverages.mqh>

Verwendung des Präprozessors #property zur Angabe zusätzlicher Parameter, die mit den folgenden Bezeichnerwerten identisch sind:

  • description: um einen kurzen Text für das Programm mql5 zu setzen.
  • indicator_separate_window: um den Ort des Indikators in einem separaten Fenster festzulegen.
  • indicator_buffers: zum Festlegen der Anzahl der Puffer für die Indikatorberechnung.
  • indicator_plots: zur Festlegung der Anzahl der grafischen Reihen im Indikator.
  • indicator_type1: zur Angabe der Art der grafischen Darstellung, die durch die Werte von ENUM_DRAW_TYPE bestimmt wird. N ist die Anzahl der grafischen Serien; die Zahlen können bei 1 beginnen.
  • indicator_color1: zur Angabe der Farbe für die Anzeige von Zeile N, N ist die Anzahl der Grafikreihen; die Zahlen können bei 1 beginnen.
  • indicator_width1: zur Angabe der Linienstärke des Indikators, N ist die Anzahl der Grafikreihen; die Zahlen können bei 1 beginnen.
#property description "Chaikin Volatility"
#property indicator_separate_window
#property indicator_buffers 3

#property indicator_plots   1
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  MediumBlue
#property indicator_width1  3

Verwendung des Schlüsselworts enum zur Definition eines Datensatzes für den Glättungsmodus des gleitenden Durchschnitts:

enum smoothMode
  {
   SMA=0,// Simple MA
   EMA=1 // Exponential MA
  };

Setzen von Eingängen für die Indikatoreinstellungen mit dem Schlüsselwort input:

input int          smoothPeriodInp=10;  // Smoothing Period
input int          chvPeriodInp=10;     // Chaikin Volatility Period
input smoothMode InpSmoothType=EMA;   // Smoothing Mode

Deklaration von drei Arrays von chv-, hl- und shl-Puffern:

double             chvBuffer[];
double             hlBuffer[];
double             shlBuffer[];

Deklaration von zwei globalen Variablen für den Glättungszeitraum und den CHV-Zeitraum:

int                smoothPeriod,chvPeriod;

In OnInit() werden wir die Variablen der Eingänge überprüfen und festlegen.

Name des gleitenden Durchschnitts: Nach der Deklaration des maName prüft das Programm, ob es sich bei der Eingabe um einen SMA handelt, in diesem Fall lautet der Name SMA (einfacher gleitender Durchschnitt), oder ob die Eingabe EMA lautet, in diesem Fall lautet der Name EMA (exponentieller gleitender Durchschnitt).

   string maName;
   if(InpSmoothType==SMA)
      maName="SMA";
   else
      maName="EMA";

Glättungszeitraum: Das Programm prüft die Glättungsperiode, wenn sie kleiner oder gleich Null ist, wird der Wert mit einem Standardwert von 10 angegeben und eine Meldung ausgedruckt. Ist der Wert abweichend, d. h. größer als 10, wird er als eingegeben angezeigt.

   if(smoothPeriodInp<=0)
     {
      smoothPeriod=10;
      printf("Incorrect value for Smoothing Period input = %d. Default value = %d.",smoothPeriodInp,smoothPeriod);
     }
   else smoothPeriod=smoothPeriodInp;

Periodenlänge für CHV: Das Programm prüft, ob die Periodenlänge für den CHV kleiner oder gleich Null ist, der Wert wird standardmäßig auf 10 gesetzt und eine Meldung wird gedruckt. Ist sie anders, d. h. größer als 10, so wird sie als eingegebene Zahl angegeben.

   if(chvPeriodInp<=0)
     {
      chvPeriod=10;
      printf("Incorrect value for Chaikin Volatility Period input = %d. Default value = %d.",chvPeriodInp,chvPeriod);
     }
   else chvPeriod=chvPeriodInp;

Definiert deklarierte Puffer, indem das Schlüsselwort SetIndexBuffer verwendet wird, um einen boolschen Wert zurückzugeben. Dessen Parameter sind:

  • index: Nummer des Puffers des Indikators, sie beginnt bei Null und ist kleiner als der Wert des Bezeichners #property of indicator_buffers.
  • buffer[]: zur Angabe des im nutzerdefinierten Indikator deklarierten Arrays.
  • data_type: um anzugeben, was gespeichert wird. Der Standardwert ist INDICATOR_DATA für chvBuffer, und wir werden INDICATOR_CALCULATIONS angeben, um in der Zwischenberechnung und nicht in der Zeichnung verwendet zu werden.
   SetIndexBuffer(0,chvBuffer);
   SetIndexBuffer(1,hlBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,shlBuffer,INDICATOR_CALCULATIONS);

Festlegen der Zeichnungseinstellung:

   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,smoothPeriod+chvPeriod-1);
   PlotIndexSetString(0,PLOT_LABEL,"CHV("+string(smoothPeriod)+","+maName+")");
   IndicatorSetString(INDICATOR_SHORTNAME,"Chaikin Volatility("+string(smoothPeriod)+","+maName+")");
   IndicatorSetInteger(INDICATOR_DIGITS,1);

In OnCalculate werden wir drei Integer-Variablen wie folgt deklarieren:

   int    i,pos,posCHV;

Festlegung, dass die Variable posCHV dem Ergebnis von 2 - chvPeriod und smoothPeriod entspricht:

   posCHV=chvPeriod+smoothPeriod-2;

Um zu prüfen, ob rateTotal kleiner ist als der Wert von posCHV, benötigen wir einen Rückgabewert von Null:

   if(rates_total<posCHV)
      return(0);

Definieren Sie den Wert von pos, nachdem Sie geprüft haben, ob prev_calculated kleiner als 1 ist. Ist die Bedingung nicht erfüllt, so ist pos das Ergebnis von prev_calculated -1.

   if(prev_calculated<1)
      pos=0;
   else pos=prev_calculated-1;

Definition des hlBuffer[i]:

   for(i=pos;i<rates_total && !IsStopped();i++)
     {
      hlBuffer[i]=High[i]-Low[i];
     }

Definition des geglätteten Puffers (shl):

   if(pos<smoothPeriod-1)
     {
      pos=smoothPeriod-1;
      for(i=0;i<pos;i++)
        {
         shlBuffer[i]=0.0;
        }
     }

Definition von einfachen und exponentiellen MAs mit den Funktionen SimpleMAOnBuffer und ExponentialMAOnBuffer:

   if(InpSmoothType==SMA)
     {
      SimpleMAOnBuffer(rates_total,prev_calculated,0,smoothPeriod,hlBuffer,shlBuffer);
     }
   else
      ExponentialMAOnBuffer(rates_total,prev_calculated,0,smoothPeriod,hlBuffer,shlBuffer);

Aktualisierung der Pos nach Prüfung, ob die Pos kleiner als die PosCHV ist:

   if(pos<posCHV)
     {
      pos=posCHV;
     }

Definition des CHV-Puffers:

   for(i=pos;i<rates_total && !IsStopped();i++)
     {
      if(shlBuffer[i-chvPeriod]!=0.0)
         chvBuffer[i]=100.0*(shlBuffer[i]-shlBuffer[i-chvPeriod])/shlBuffer[i-chvPeriod];
      else
         chvBuffer[i]=0.0;
     }

Rückgabe von rates_total:

return(rates_total);

Im Folgenden ist der vollständige Code in einem Block dargestellt:

//+------------------------------------------------------------------+
//|                                           Chaikin Volatility.mq5 |
//+------------------------------------------------------------------+
#include <MovingAverages.mqh>
#property description "Chaikin Volatility"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  MediumBlue
#property indicator_width1  3
enum smoothMode
  {
   SMA=0,// Simple MA
   EMA=1 // Exponential MA
  };
input int          smoothPeriodInp=10;  // Smoothing Period
input int          chvPeriodInp=10;     // Chaikin Volatility Period
input smoothMode InpSmoothType=EMA;   // Smoothing Mode
double             chvBuffer[];
double             hlBuffer[];
double             shlBuffer[];
int                smoothPeriod,chvPeriod;
void OnInit()
  {
   string maName;
   if(InpSmoothType==SMA)
      maName="SMA";
   else
      maName="EMA";
   if(smoothPeriodInp<=0)
     {
      smoothPeriod=10;
      printf("Incorrect value for Smoothing Period input = %d. Default value = %d.",smoothPeriodInp,smoothPeriod);
     }
   else
      smoothPeriod=smoothPeriodInp;
   if(chvPeriodInp<=0)
     {
      chvPeriod=10;
      printf("Incorrect value for Chaikin Volatility Period input = %d. Default value = %d.",chvPeriodInp,chvPeriod);
     }
   else
      chvPeriod=chvPeriodInp;
   SetIndexBuffer(0,chvBuffer);
   SetIndexBuffer(1,hlBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,shlBuffer,INDICATOR_CALCULATIONS);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,smoothPeriod+chvPeriod-1);
   PlotIndexSetString(0,PLOT_LABEL,"CHV("+string(smoothPeriod)+","+maName+")");
   IndicatorSetString(INDICATOR_SHORTNAME,"Chaikin Volatility("+string(smoothPeriod)+","+maName+")");
   IndicatorSetInteger(INDICATOR_DIGITS,1);
  }
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &Time[],
                const double &Open[],
                const double &High[],
                const double &Low[],
                const double &Close[],
                const long &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
   int    i,pos,posCHV;
   posCHV=chvPeriod+smoothPeriod-2;
   if(rates_total<posCHV)
      return(0);
   if(prev_calculated<1)
      pos=0;
   else
      pos=prev_calculated-1;
   for(i=pos;i<rates_total && !IsStopped();i++)
     {
      hlBuffer[i]=High[i]-Low[i];
     }
   if(pos<smoothPeriod-1)
     {
      pos=smoothPeriod-1;
      for(i=0;i<pos;i++)
        {
         shlBuffer[i]=0.0;
        }
     }
   if(InpSmoothType==SMA)
     {
      SimpleMAOnBuffer(rates_total,prev_calculated,0,smoothPeriod,hlBuffer,shlBuffer);
     }
   else
      ExponentialMAOnBuffer(rates_total,prev_calculated,0,smoothPeriod,hlBuffer,shlBuffer);
   if(pos<posCHV)
     {
      pos=posCHV;
     }
   for(i=pos;i<rates_total && !IsStopped();i++)
     {
      if(shlBuffer[i-chvPeriod]!=0.0)
         chvBuffer[i]=100.0*(shlBuffer[i]-shlBuffer[i-chvPeriod])/shlBuffer[i-chvPeriod];
      else
         chvBuffer[i]=0.0;
     }
   return(rates_total);
  }

Nachdem wir diesen Code kompiliert haben, finden wir den gleichen Indikator wie in der folgenden Grafik, wenn wir ihn an das Chart anhängen:

CHVInda

Wie in der vorangegangenen Grafik zu sehen ist, wird der Indikator im unteren Fenster des Charts als Histogramm dargestellt, das oszilliert oder Werte über und unter Null aufzeichnet.


Chaikin-Volatilitätshandelsstrategien

In diesem Teil werden wir sehen, wie wir den Chaikin-Volatilitäts-Indikator zu unseren Gunsten nutzen können und wie er Teil unseres Handelssystems sein kann, um die Volatilität beim Handel zu berücksichtigen. Wir werden nur die CHV verwenden und Handelsentscheidungen auf der Grundlage des Wertes des Indikators treffen, dann werden wir dies testen, um zu sehen, ob die Ergebnisse profitabel sein können oder nicht.

Wir werden eine andere Strategie verwenden und einen anderen Indikator kombinieren, um Entscheidungen auf der Grundlage der Richtung des gleitenden Durchschnitts zu filtern, um zu sehen, ob die Strategie profitabel oder besser ist als die Verwendung von CHV nur oder nicht, basierend auf dem Testen dieser Strategie.

Im Folgenden werden diese Strategien vorgestellt:

Kreuzen von CHV:

Diese Strategie kann automatisch Kauf- und Verkaufssignale erzeugen und Aufträge erteilen. Wenn der Wert von CHV über Null liegt, wird der EA eine Kaufposition platzieren. Wenn der Wert von CHV unter Null liegt, wird der EA eine Verkaufsposition abschicken.

Einfach:

CHV-Wert > 0 => Position kaufen.

CHV-Wert < 0 => Position verkaufen.

Kreuzen von CHV und MA:

Die Strategie generiert Signale und platziert Kauf- und Verkaufspositionen auf der Grundlage des Kreuzens zwischen dem CHV-Wert und dem Nullniveau, wobei die Richtung des gleitenden Durchschnitts berücksichtigt wird. Wenn die CHV über Null liegt und der gleitende Durchschnitt unter dem Schlusskurs liegt, wird eine Kaufposition erstellt und platziert. Liegt die CHV hingegen unter Null und der gleitende Durchschnitt über dem Schlusskurs, wird eine Verkaufsposition generiert und platziert.

Einfach:

CHV > 0 und Schlusskurs > MA => Position kaufen.

CHV < 0 und Schlusskurs < MA => Position verkaufen.


Chaikin-Volatilitätshandelssystem

In diesem Teil werden wir ein Handelssystem mit MQL5 erstellen, das auf den genannten Strategien basiert, und wir werden jede einzelne testen, um zu sehen, wie wir die Strategie optimieren können, um bessere Ergebnisse zu erzielen. Zuerst werden wir einen einfachen EA erstellen, der als Basis für unsere Handelssysteme der beiden Strategien dient. Dieser EA wird die CHV-Werte als Kommentar auf dem Chart anzeigen.

Wir deklarieren die Eingaben des Handelssystems basierend auf dem Indikator:

enum SmoothMethod
  {
   SMA=0,// Simple MA
   EMA=1 // Exponential MA
  };
input int          InpSmoothPeriod=10;  // Smoothing period
input int          InpCHVPeriod=10;     // Chaikin Volatility period
input SmoothMethod InpSmoothType=EMA;   // Smoothing method

Deklarieren Sie eine Integer-Variable für die chv:

int chv;

Im OnInit()-Teil des EA definieren wir die chv-Variable so, dass sie der iCustom-Funktion entspricht, die das Handle des CHV-Indikators zurückgibt. Die Parameter von iCustom sind:

  • symbol: Zur Angabe des Symbolnamens wird (_Symbol) verwendet, das auf das aktuelle Symbol angewendet wird.
  • Zeitrahmen: Zur Angabe des Zeitrahmens wird PERIOD_CURRENT verwendet, das auf den aktuellen Zeitraum angewendet wird.
  • Name: zur Angabe des Namens des Indikators
  • Angabe der Liste der Eingaben (smoothPeriodInp,chvPeriodInp und smoothTypeInp)
chv = iCustom(_Symbol,PERIOD_CURRENT,"Custom_CHV",smoothPeriodInp,chvPeriodInp, smoothTypeInp);

In OnDeinit() wird eine Meldung ausgegeben, wenn der EA entfernt wird:

Print("EA is removed");

In OnTick() wird das Array chvInd deklariert:

double chvInd[];

Abrufen der angegebenen Pufferdaten des CHV-Indikators mit dem Schlüsselwort CopyBuffer. Die Parameter sind:

  • indicator_handle: zur Angabe des Indikator-Handles, der das chv ist 
  • buffer_num: Angabe der Nummer des Anzeigepuffers, die 0 sein wird
  • start_pos: zur Angabe der Startposition, die 0 sein wird
  • count: zur Angabe der zu kopierenden Menge, die 3 beträgt
  • buffer[]: zur Angabe des zu kopierenden Ziel-Arrays, das chvInd sein wird
CopyBuffer(chv,0,0,3,chvInd);

Setzen des AS_SERIES Flags auf das ausgewählte Array mit dem ArraySetAsSeries Schlüsselwort und seinen Parametern:

  • array[]: zur Angabe des Arrays per Referenz, die chvInd sein wird. 
  • flag: auf true gesetzt, wird die umgekehrte Reihenfolge der Indizierung eingerichtet. 
ArraySetAsSeries(chvInd,true);

Deklarieren und definieren von chvVal, um den aktuellen Wert des Indikators zurückzugeben.

double chvVal = NormalizeDouble(chvInd[0], 1);

Kommentieren des aktuellen Wertes im Chart:

Comment("CHV value = ",chvVal);

Wir können also den gesamten Code in einem Block sehen, der wie folgt aussieht:

//+------------------------------------------------------------------+
//|                                                       chvVal.mq5 |
//+------------------------------------------------------------------+
enum SmoothMethod
  {
   SMA=0,// Simple MA
   EMA=1 // Exponential MA
  };
input int          smoothPeriodInp=10;  // Smoothing period
input int          chvPeriodInp=10;     // Chaikin Volatility period
input SmoothMethod smoothTypeInp=EMA;   // Smoothing method
int chv;
int OnInit()
  {
   chv = iCustom(_Symbol,PERIOD_CURRENT,"Custom_CHV",smoothPeriodInp,chvPeriodInp, smoothTypeInp);
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }
void OnTick()
  {
    double chvInd[];
    CopyBuffer(chv,0,0,3,chvInd);
    ArraySetAsSeries(chvInd,true);
    double chvVal = NormalizeDouble(chvInd[0], 1);
    Comment("CHV value = ",chvVal);
  }
//+------------------------------------------------------------------+

Nach dem Kompilieren dieses Codes können wir den Wert des aktuellen Wertes wie in der folgenden Grafik dargestellt sehen:

chvVal

Wir können uns vergewissern, dass der auf dem Chart ausgegebene Wert korrekt ist, indem wir den Indikator in dasselbe Chart einfügen, um zu sehen, ob es einen Unterschied zwischen den beiden Werten gibt oder nicht. Das folgende Chart zeigt dies, um sicherzustellen, dass alles korrekt ist, bevor wir mit der Entwicklung unseres Handelssystems fortfahren:

chvValSame

Wie wir sehen können, ist der gedruckte Wert der aktuellen CHV derselbe wie der Wert des angehängten Indikators. Lassen Sie uns nun unser Handelssystem für die erste Strategie (CHV Crossover) erstellen.

Kreuzen von CHV:

Entsprechend der Strategie der CHV-Crossover-Strategie ist im Folgenden der vollständige Code für diese Strategie aufgeführt:

//+------------------------------------------------------------------+
//|                                                 chvCrossover.mq5 |
//+------------------------------------------------------------------+
#include <trade/trade.mqh>
enum smoothMode
  {
   SMA=0,// Simple MA
   EMA=1 // Exponential MA
  };
input int          smoothPeriodInp=10;  // Smoothing period
input int          chvPeriodInp=10;     // Chaikin Volatility period
input smoothMode smoothTypeInp=EMA;   // Smoothing Mode
input double      lotSize=1;
input double slPips = 300;
input double tpPips = 600;

int chv;
int barsTotal;
CTrade trade;
int OnInit()
  {
   barsTotal=iBars(_Symbol,PERIOD_CURRENT);
   chv = iCustom(_Symbol,PERIOD_CURRENT,"Custom_CHV",smoothPeriodInp,chvPeriodInp, smoothTypeInp, lotSize, slPips, tpPips);
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }
void OnTick()
  {
   int bars=iBars(_Symbol,PERIOD_CURRENT);
   if(barsTotal < bars)
     {
      barsTotal=bars;
      double chvInd[];
      CopyBuffer(chv,0,0,3,chvInd);
      ArraySetAsSeries(chvInd,true);
      double chvVal = NormalizeDouble(chvInd[0], 1);
      double chvValPrev = NormalizeDouble(chvInd[1], 1);
      if(chvVal>0)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal = ask - slPips*_Point;
         double tpVal = ask + tpPips*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }
      if(chvVal<0)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal = bid + slPips*_Point;
         double tpVal = bid - tpPips*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }
     }
  }
//+------------------------------------------------------------------+

Die Unterschiede in diesem Code sind wie folgt:

Einbindung der Datei mit den Handelsfunktionen:

#include <trade/trade.mqh>

Deklarieren der Eingaben für die lotSize, die slPips und die tpPips, die vom Nutzer bearbeitet werden können:

input double      lotSize=1;
input double slPips = 300;
input double tpPips = 600;

Deklaration einer Integer-Variable von barsTotal, die als Code für jeden neuen Takt verwendet wird:

int barsTotal;

Deklaration des Objektes zur Handelsabwicklung:

CTrade trade;

In OnInit() werden wir die Variable barsTotal definieren:

barsTotal=iBars(_Symbol,PERIOD_CURRENT);

Hinzufügen der drei Eingaben von lotSize, slPips und tpPips zum Schlüsselwort iCustom:

chv = iCustom(_Symbol,PERIOD_CURRENT,"Custom_CHV",smoothPeriodInp,chvPeriodInp, smoothTypeInp, lotSize, slPips, tpPips);

Deklaration und Definition der Integer-Variable bar:

int bars=iBars(_Symbol,PERIOD_CURRENT);

Um zu prüfen, ob barsTotal kleiner als bars ist, muss Folgendes ausgeführt werden:

Aktualisieren des Wert von barsTotal so, dass er gleich dem Wert von bars ist:

barsTotal=bars;

Deklaration des Arrays chvInd:

double chvInd[];

Abruf der angegebenen Pufferdaten des CHV-Indikators mit Hilfe des Schlüsselworts CopyBuffer.

CopyBuffer(chv,0,0,3,chvInd);

Setzen Sie das AS_SERIES Flag für das ausgewählte Array mit dem ArraySetAsSeries Schlüsselwort, wie folgt:

ArraySetAsSeries(chvInd,true);

Deklaration und Definition von chvVal für die Rückgabe des aktuellen Wertes und des vorherigen Wertes des aktuellen des Indikators.

      double chvVal = NormalizeDouble(chvInd[0], 1);
      double chvValPrev = NormalizeDouble(chvInd[1], 1);

Wenn wir die Bedingung für die Kaufposition festlegen, muss der EA automatisch eine Kaufposition platzieren, wenn er den CHV-Wert überprüft und feststellt, dass er größer als Null ist.

      if(chvVal>0)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal = ask - slPips*_Point;
         double tpVal = ask + tpPips*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }

Wenn wir die Bedingung für die Verkaufsposition festlegen, muss der EA automatisch eine Verkaufsposition platzieren, wenn er den CHV-Wert überprüft und feststellt, dass er kleiner als Null ist.

      if(chvVal<0)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal = bid + slPips*_Point;
         double tpVal = bid - tpPips*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }

Nach dem Kompilieren dieses Codes können wir sehen, dass die Platzierung der Kaufposition wie folgt aussehen kann:

chvCrossover_buySignal

Wir stellen fest, dass die Verkaufsposition auch auf die gleiche Weise platziert werden kann wie die folgende:

chvCrossover_sellSignal

Wie wir wissen, gibt es keine gute Strategie, ohne sie zu testen und gewinnbringende Ergebnisse zu erzielen. Wir werden uns auf die folgenden Schlüsselmaßnahmen konzentrieren:

  • Reingewinn: Dieser wird berechnet, indem der Bruttoverlust vom Bruttogewinn abgezogen wird. Der höchste Wert ist der beste.
  • Salden-DD relativ: Dies ist der maximale Verlust, den das Konto während des Handels erleidet. Je niedriger, desto besser.
  • Gewinnfaktor: Dies ist das Verhältnis von Bruttogewinn zu Bruttoverlust. Je höher, desto besser.
  • Expected Payoff: Dies ist der durchschnittliche Gewinn oder Verlust eines Handelsgeschäfts. Je höher, desto besser.
  • Erholungsfaktor: Er misst, wie gut sich die getestete Strategie nach Verlusten erholt. Je höher, desto besser.
  • Sharpe Ratio: Sie bestimmt das Risiko und die Stabilität des getesteten Handelssystems, indem sie die Rendite mit der risikofreien Rendite vergleicht. Die höchste Sharpe Ratio ist die beste.

Die folgenden Bilder zeigen die Testergebnisse. Wir testen ein Jahr (1.1.2023 bis 31.12.2023) mit EURUSD und einem Zeitrahmen von 1 Stunde.

chvCrossover_resultat

chvCrossover_result2

chvCrossover_result1

Aus den Testergebnissen lassen sich die folgenden wichtigen Werte für den Test ableiten:

  • Nettogewinn: -35936,34 USD.
  • Salden-DD relative: 48.12%.
  • Gewinnfaktor: 0.94.
  • Erwartete Auszahlung: -6,03.
  • Erholungsfaktor: -0,62.
  • Sharpe Ratio: -1,22.

Anhand der bisherigen Ergebnisse können wir sehen, dass die Ergebnisse nicht gut oder profitabel sind, so dass wir sie optimieren müssen, um bessere Ergebnisse zu erzielen. Im Folgenden soll dies durch die Strategie geschehen.

Kreuzen von CHV und MA:

Bei dieser Strategie verwenden wir den CHV-Indikator, aber wir kombinieren einen anderen technischen Indikator, den gleitenden Durchschnitt, um Trades auf der Grundlage der Richtung des gleitenden Durchschnitts zu filtern. Nachfolgend finden Sie den vollständigen Code für diesen Vorgang:

//+------------------------------------------------------------------+
//|                                             chv_MA_Crossover.mq5 |
//+------------------------------------------------------------------+
#include <trade/trade.mqh>
enum smoothMode
  {
   SMA=0,// Simple MA
   EMA=1 // Exponential MA
  };
input int          InpSmoothPeriod=10;  // Smoothing period
input int          InpCHVPeriod=10;     // Chaikin Volatility period
input smoothMode smoothTypeInp=EMA;   // Smoothing Mode
input int InpMAPeriod=10; //MA Period
input ENUM_MA_METHOD InpMAMode=MODE_EMA; // MA Mode
input double      lotSize=1;
input double slPips = 300;
input double tpPips = 600;
int chv;
int ma;
int barsTotal;
CTrade trade;
int OnInit()
  {
   barsTotal=iBars(_Symbol,PERIOD_CURRENT);
   chv = iCustom(_Symbol,PERIOD_CURRENT,"Custom_CHV",InpSmoothPeriod,InpCHVPeriod, smoothTypeInp, lotSize, slPips, tpPips);
   ma=iMA(_Symbol,PERIOD_CURRENT, InpMAPeriod, 0, InpMAMode, PRICE_CLOSE);
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }
void OnTick()
  {
   int bars=iBars(_Symbol,PERIOD_CURRENT);
   if(barsTotal < bars)
     {
      barsTotal=bars;
      double chvInd[];
      double maInd[];
      CopyBuffer(chv,0,0,3,chvInd);
      ArraySetAsSeries(chvInd,true);
      CopyBuffer(ma,0,0,3,maInd);
      ArraySetAsSeries(maInd,true);
      double chvVal = NormalizeDouble(chvInd[0], 1);
      double chvValPrev = NormalizeDouble(chvInd[1], 1);
      double maVal = NormalizeDouble(maInd[0], 5);
      double maValPrev = NormalizeDouble(maInd[1], 5);
      double lastClose=iClose(_Symbol,PERIOD_CURRENT,1);
      double prevLastClose=iClose(_Symbol,PERIOD_CURRENT,2);

      if(prevLastClose<maValPrev && lastClose>maVal && chvVal>0)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal = ask - slPips*_Point;
         double tpVal = ask + tpPips*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }
      if(prevLastClose>maValPrev && lastClose<maVal && chvVal<0)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal = bid + slPips*_Point;
         double tpVal = bid - tpPips*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }
     }
  }
//+------------------------------------------------------------------+

Die Unterschiede in diesem Code sind wie folgt:

Wir deklarieren eine Integer-Variable für ma:

int ma;

In OnInit() definieren wir den ma, indem wir das Schlüsselwort iMA verwenden, um das Handle des gleitenden Durchschnitts zu erhalten. Die Parameter sind:

  • symbol: um den Namen des Symbols anzugeben, wird _Symbol auf das aktuelle Symbol angewendet. 
  • period: zur Angabe des Zeitrahmens wird PERIOD_CURRENT für den aktuellen Zeitrahmen verwendet.
  • ma_period: zur Angabe der Periode des gleitenden Durchschnitts, es wird MAperiod eingegeben.
  • ma_shift: um anzugeben, ob eine horizontale Verschiebung für die Durchschnittslinie erforderlich ist.
  • ma_method: zur Angabe des Glättungsmodus des gleitenden Durchschnitts, der die Eingabe des MA-Modus ist. 
  • applied_price: zur Angabe des Preistyps, der für die Berechnung verwendet werden soll; wir werden den Schlusskurs verwenden.
ma=iMA(_Symbol,PERIOD_CURRENT, InpMAPeriod, 0, InpMAMode, PRICE_CLOSE);

Nach der Prüfung, ob ein neuer Balken vorhanden ist, wird Folgendes hinzugefügt:

Deklaration des Arrays maInd[]:

double maInd[];

Abrufen der Daten des angegebenen Puffers des gleitenden Durchschnittsindikators mit dem Schlüsselwort CopyBuffer und Setzen des AS_SERIES-Flags auf das ausgewählte Array mit dem Schlüsselwort ArraySetAsSeries:

      CopyBuffer(ma,0,0,3,maInd);
      ArraySetAsSeries(maInd,true);

Festlegung der folgenden Werte:

den aktuellen gleitenden Durchschnitt, den vorhergehenden gleitenden Durchschnitt, den letzten Schlusskurs und den vorhergehenden Kurs des letzten Schlusskurses:

      double maVal = NormalizeDouble(maInd[0], 5);
      double maValPrev = NormalizeDouble(maInd[1], 5);
      double lastClose=iClose(_Symbol,PERIOD_CURRENT,1);
      double prevLastClose=iClose(_Symbol,PERIOD_CURRENT,2);

Wenn der letzte Schlusskurs kleiner als der vorherige gleitende Durchschnittswert ist und gleichzeitig der letzte Schlusskurs größer als der aktuelle gleitende Durchschnitt und der aktuelle Chaikin-Wert größer als Null ist, soll der EA eine Kaufposition platzieren:

      if(prevLastClose<maValPrev && lastClose>maVal && chvVal>0)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal = ask - slPips*_Point;
         double tpVal = ask + tpPips*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }

Wenn der letzte Schlusskurs größer ist als der vorherige gleitende Durchschnitt und gleichzeitig der letzte Schlusskurs kleiner ist als der aktuelle gleitende Durchschnitt und gleichzeitig der aktuelle Chaikin-Wert kleiner als Null ist, soll der EA eine Verkaufsposition einnehmen.

      if(prevLastClose>maValPrev && lastClose<maVal && chvVal<0)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal = bid + slPips*_Point;
         double tpVal = bid - tpPips*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }

Nach dem Kompilieren dieses Codes können wir sehen, dass die Platzierung der Kaufposition wie folgt aussehen kann:

chvMACrossover_buySignal

Wir stellen fest, dass die Verkaufsposition auch auf die gleiche Weise platziert werden kann wie die folgende:

chvMACrossover_sellSignal

Nach einem Test dieser Strategie für ein Jahr (1.1.2023 bis 31.12.2023) auf dem EURUSD und einem Zeitrahmen von 1 Stunde, sind unsere Ergebnisse wie folgt

chvMACrossover_resultat

chvMACrossover_result2

chvMACrossover_result1

Aus den Testergebnissen lassen sich die folgenden wichtigen Werte für den Test ableiten:

  • Reingewinn: 20817,39 USD.
  • Salden-DD relative: 9.62%.
  • Gewinnfaktor: 1.15.
  • Erwartete Auszahlung: 29.28.
  • Erholungsfaktor: 1.69.
  • Sharpe Ratio: 1.71.

Auf der Grundlage der Ergebnisse der vorangegangenen Tests und nach dem Hinzufügen eines anderen technischen Werkzeugs, das der gleitende Durchschnitt ist, können wir die besten Zahlen, die die Strategie getestet von CHV und MA Crossover ein und die 1 Stunde Zeitrahmen die gleichen wie die folgenden entsprechen zu finden:

  • Reingewinn: Der höhere Wert (20817,39 USD) ist besser.
  • Salden-DD relativ: Der niedrigere Wert (9,62 %) ist besser.
  • Profit Factor: Der höhere Wert (1,15) ist besser.
  • Expected Payoff: Der höhere Wert ((29,28) ist besser.
  • Erholungsfaktor: Der höhere Wert (1,69) ist besser.
  • Sharpe Ratio: Der höhere Wert (1,71) ist besser.


Schlussfolgerung

Wir sollten die Bedeutung des Konzepts der Volatilität auf dem Finanzmarkt verstehen, indem wir den technischen Indikator Chaikin-Volatilität kennenlernen, der für das Lesen oder die Vorhersage potenzieller Marktbewegungen nützlich sein kann. Wir gingen davon aus, dass wir verstehen würden, wie der CHV-Indikator funktioniert, wie er berechnet werden kann und wie wir ihn zu unserem Vorteil auf den Handelsmärkten nutzen können.

Wir nehmen mal an, dass wir zwei einfache Strategien verstehbar erklärt haben und jetzt wissen, wie wir unsere Strategie optimieren können, um bessere Ergebnisse zu erzielen, indem wir sie mit einem anderen technischen Instrument wie dem gleitenden Durchschnitt begleiten. Wir haben gelernt, wie wir unseren eigenen CHV-Indikator mit Hilfe von MQL5 erstellen können, um ihm unsere Präferenzen hinzuzufügen. Wir haben gelernt, wie wir diesen nutzerdefinierten CHV-Indikator in einem Handelssystem auf der Grundlage der genannten Strategien verwenden können.

  • Kreuzen von CHV
  • Kreuzen von CHV und MA

Wir haben auch gelernt, wie man ein Handelssystem erstellt, das automatisch auf der Grundlage der genannten Strategien arbeitet und Positionen platziert, indem wir EAs erstellen, sie dann testen und sehen, wie wir bessere Einblicke und Ergebnisse erhalten können, indem wir ein anderes technisches Werkzeug wie den gleitenden Durchschnitt als Optimierung durch Strategy Tester hinzufügen.

Ich möchte Sie ermutigen, andere mögliche Instrumente auszuprobieren und zu testen, um bessere Erkenntnisse zu gewinnen, da Verbesserungen nie enden können und eine unendliche Funktion nicht nur im Handel, sondern auch in unserem Leben darstellen. Ich hoffe, dass Ihnen die Lektüre dieses Artikels gefallen hat und Sie ihn auf Ihrer Handelsreise als nützlich empfunden haben. Wenn Sie weitere Artikel über den Aufbau von Handelssystemen und das Verständnis des dahinter stehenden Konzepts lesen möchten, können Sie meine früheren Artikel zu diesen und anderen Themen im Zusammenhang mit der MQL5-Programmierung lesen.


Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/14775

Beigefügte Dateien |
Custom_CHV.mq5 (3.24 KB)
chvVal.mq5 (0.97 KB)
chvCrossover.mq5 (1.8 KB)
Aufbau eines Modells von Kerzen, Trend und Nebenbedingungen (Teil 2): Zusammenführung integrierter Indikatoren Aufbau eines Modells von Kerzen, Trend und Nebenbedingungen (Teil 2): Zusammenführung integrierter Indikatoren
In diesem Artikel geht es darum, die Vorteile der im MetaTrader 5 integrierten Indikatoren zu nutzen, um Signale abseits eines Trends zu erkennen. In Fortführung des vorherigen Artikels werden wir untersuchen, wie wir unsere Idee mit Hilfe von MQL5-Code in das endgültige Programm übertragen können.
Datenwissenschaft und ML (Teil 22): Nutzung von Autoencodern Neuronaler Netze für intelligentere Trades durch den Übergang vom Rauschen zum Signal Datenwissenschaft und ML (Teil 22): Nutzung von Autoencodern Neuronaler Netze für intelligentere Trades durch den Übergang vom Rauschen zum Signal
In der schnelllebigen Welt der Finanzmärkte ist es für den erfolgreichen Handel entscheidend, aussagekräftige Signale vom Rauschen zu unterscheiden. Durch den Einsatz hochentwickelter neuronaler Netzwerkarchitekturen sind Autocoder hervorragend in der Lage, verborgene Muster in Marktdaten aufzudecken und verrauschte Daten in verwertbare Erkenntnisse umzuwandeln. In diesem Artikel gehen wir der Frage nach, wie Autoencoders die Handelspraktiken revolutionieren und Händlern ein leistungsfähiges Werkzeug an die Hand geben, um die Entscheidungsfindung zu verbessern und sich auf den dynamischen Märkten von heute einen Wettbewerbsvorteil zu verschaffen.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 17): Handel mit mehreren Währungen MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 17): Handel mit mehreren Währungen
Der Handel mit mehreren Währungen ist nicht standardmäßig verfügbar, wenn ein Expertenberater über den Assistenten zusammengestellt wird. Wir untersuchen 2 mögliche Hacks, die Händler machen können, wenn sie ihre Ideen mit mehr als einem Symbol gleichzeitig testen wollen.
MQL5-Assistent-Techniken, die Sie kennen sollten (Teil 16): Hauptkomponentenanalyse mit Eigenvektoren MQL5-Assistent-Techniken, die Sie kennen sollten (Teil 16): Hauptkomponentenanalyse mit Eigenvektoren
Die Hauptkomponentenanalyse, ein Verfahren zur Verringerung der Dimensionalität in der Datenanalyse, wird in diesem Artikel untersucht, und es wird gezeigt, wie sie mit Eigenwerten und Vektoren umgesetzt werden kann. Wie immer streben wir die Entwicklung eines Prototyps einer Experten-Signal-Klasse an, die im MQL5-Assistenten verwendet werden kann.