English Русский 中文 Español 日本語 Português
Die Rezepte MQL5 - die Handelssignale der Pivots

Die Rezepte MQL5 - die Handelssignale der Pivots

MetaTrader 5Beispiele | 15 Mai 2017, 12:48
887 0
Denis Kirichenko
Denis Kirichenko

Einführung

Der aktuelle Artikel setzt eine Reihe fort, in der die Indikatoren und Setups beschrieben werden, welche die Handelssignale generieren. Diesmal betrachten wir Pivots — die Wendeebenen (die Punkte). Es wird wieder die Standardbibliothek eingesetzt. Erstens werden wir mit dem Indikator der Wendeebenen arbeiten, und dann auf seiner Grundlage werden wir die grundlegende Strategie erstellen, die wir ausarbeiten werden.

Es wäre wünschenswert, wenn der Leser das Zeichen bereits kannte, die grundlegende Klasse für die Bildung der Generatoren der Handelssignale CExpertSignal.

1. Der Indikator Pivots — die Wendeebenen

Für die Strategie wird der Indikator verwendet, der die Ebenen der potentiellen Wende zeichnet. Dabei findet die Zeichnung nur mittels des graphischen Aufbaus ohne Verwendung der graphischen Objekte. Der Hauptvorteil einer solchen Art — ist die Möglichkeit, den Indikator im Optimierungsmodus aufzurufen. Der Nachteil besteht darin, dass die graphischen Konstruktionen die Grenzen der Indikator-Puffer nicht verlassen können, und das heißt, die Linien auf den Bars werden in der Zukunft nicht existieren.

Die Ebenen können nach verschiedenen Weisen berechnet werden. Mehr dazu können Sie aus dem Artikel "Handelsstrategie basierend auf Pivot Punkte Analyse" erfahren.

Wir werden erstmal eine klassische Art benutzen, wo die Ebenen nach solchen Formeln herausberechnet werden:

RES — ist eine i-s Ebene des Widerstands, und SUP — ist eine i-s Ebene der Unterstützung. Insgesamt wird es: Eine Hauptwendeebene(PP), 6 Ebenen des Widerstands (RES) und 6 Ebenen der Unterstützung (SUP).

Also, optisch sieht der Indikator wie ein Satz aus horizontalen Ebenen aus, die nach verschiedenen Preisen gebaut werden. Der erste Start des Indikators auf dem Chart wird die Ebenen nur für den laufenden Tag (die Abb.1) aufbauen.

Abb.1 Der Indikator Pivots: die Zeichnung für den aktuellen Tag

in Abb. 1. Der Indikator Pivots: die Zeichnung für den aktuellen Tag

Wir betrachten einen Code des Indikators blockmäßig, wir beginnen mit dem Teil der Berechnung.

Also, wenn einen neuen Tag beginnt, man muss alle Wendeebenen neu berechnen.

//--- wenn es einen neuen Tag gibt
   if(gNewDay.isNewBar(today))
     {
      PrintFormat("ein neuer Tag: %s",TimeToString(today));
      //--- Die Normalisierung der Preise
      double d_high=NormalizeDouble(daily_rates[0].high,_Digits);
      double d_low=NormalizeDouble(daily_rates[0].low,_Digits);
      double d_close=NormalizeDouble(daily_rates[0].close,_Digits);
      //--- die Preise speichern
      gYesterdayHigh=d_high;
      gYesterdayLow=d_low;
      gYesterdayClose=d_close;
      //--- 1) Pivot: PP = (HIGH + LOW + CLOSE) / 3        
      gPivotVal=NormalizeDouble((gYesterdayHigh+gYesterdayLow+gYesterdayClose)/3.,_Digits);
      //--- 4) RES1.0 = 2*PP - LOW
      gResVal_1_0=NormalizeDouble(2.*gPivotVal-gYesterdayLow,_Digits);
      //--- 5) SUP1.0 = 2*PP – HIGH
      gSupVal_1_0=NormalizeDouble(2.*gPivotVal-gYesterdayHigh,_Digits);
      //--- 8) RES2.0 = PP + (HIGH -LOW)
      gResVal_2_0=NormalizeDouble(gPivotVal+(gYesterdayHigh-gYesterdayLow),_Digits);
      //--- 9) SUP2.0 = PP - (HIGH – LOW)
      gSupVal_2_0=NormalizeDouble(gPivotVal-(gYesterdayHigh-gYesterdayLow),_Digits);
      //--- 12) RES3.0 = 2*PP + (HIGH – 2*LOW)
      gResVal_3_0=NormalizeDouble(2.*gPivotVal+(gYesterdayHigh-2.*gYesterdayLow),_Digits);
      //--- 13) SUP3.0 = 2*PP - (2*HIGH – LOW)
      gSupVal_3_0=NormalizeDouble(2.*gPivotVal-(2.*gYesterdayHigh-gYesterdayLow),_Digits);
      //--- 2) RES0.5 = (PP + RES1.0) / 2
      gResVal_0_5=NormalizeDouble((gPivotVal+gResVal_1_0)/2.,_Digits);
      //--- 3) SUP0.5 = (PP + SUP1.0) / 2
      gSupVal_0_5=NormalizeDouble((gPivotVal+gSupVal_1_0)/2.,_Digits);
      //--- 6) RES1.5 = (RES1.0 + RES2.0) / 2
      gResVal_1_5=NormalizeDouble((gResVal_1_0+gResVal_2_0)/2.,_Digits);
      //--- 7) SUP1.5 = (SUP1.0 + SUP2.0) / 2
      gSupVal_1_5=NormalizeDouble((gSupVal_1_0+gSupVal_2_0)/2.,_Digits);
      //--- 10) RES2.5 = (RES2.0 + RES3.0) / 2
      gResVal_2_5=NormalizeDouble((gResVal_2_0+gResVal_3_0)/2.,_Digits);
      //--- 11) SUP2.5 = (SUP2.0 + SUP3.0) / 2
      gSupVal_2_5=NormalizeDouble((gSupVal_2_0+gSupVal_3_0)/2.,_Digits);
      //--- Die Anfangsbar des aktuellen Tages
      gDayStart=today;
      //--- Die Startbar der aktiven Timeframe
      //--- wie eine Time-Serie
      for(int bar=0;bar<rates_total;bar++)
        {
         //--- Die Zeit der gewählten Bar
         datetime curr_bar_time=time[bar];
         user_date.DateTime(curr_bar_time);
         //--- Der Tag der gewählten Bar
         datetime curr_bar_time_of_day=user_date.DateOfDay();
         //--- wenn die laufende Bar ein Tag früher wäre
         if(curr_bar_time_of_day<gDayStart)
           {
            //--- die Startbar festlegen
            gBarStart=bar-1;
            break;
           }
        }
      //--- den lokalen Zähler zurücksetzten
      prev_calc=0;
         }

Mit Rot habe ich die Zeilen gewählt, wo die Ebenen neuberechnet werden. Dann muss man die Nummer der Bar für die laufende Timeframe finden, welche der Anfang für die Zeichnung der Ebenen sein wird. Für seinen Wert ist die Variable gBarStart verantwortlich. Bei der Suche wird die benutzerdefinierte Struktur SUserDateTime für die Arbeit mit den Daten und Zeit eingesetzt — die Folge der Struktur CDateTime.

Jetzt einige Wörter über den Block, wo die Auffüllung der Pufferwerte für die Bars der laufenden Timeframe stattfindet.

//--- wenn eine neue Bar auf der aktiven Timeframe
   if(gNewMinute.isNewBar(time[0]))
     {
      //--- nach welcher Bar berechnet werden soll 
      int bar_limit=gBarStart;
      //--- wenn es nicht der erste Start ist
      if(prev_calc>0)
         bar_limit=rates_total-prev_calc;
      //--- die Aufzählung der Puffer 
      for(int bar=0;bar<=bar_limit;bar++)
        {
         //--- 1) Pivot
         gBuffers[0].data[bar]=gPivotVal;
         //--- 2) RES0.5
         if(gToPlotBuffer[1])
            gBuffers[1].data[bar]=gResVal_0_5;
         //--- 3) SUP0.5
         if(gToPlotBuffer[2])
            gBuffers[2].data[bar]=gSupVal_0_5;
         //--- 4) RES1.0
         if(gToPlotBuffer[3])
            gBuffers[3].data[bar]=gResVal_1_0;
         //--- 5) SUP1.0
         if(gToPlotBuffer[4])
            gBuffers[4].data[bar]=gSupVal_1_0;
         //--- 6) RES1.5
         if(gToPlotBuffer[5])
            gBuffers[5].data[bar]=gResVal_1_5;
         //--- 7) SUP1.5
         if(gToPlotBuffer[6])
            gBuffers[6].data[bar]=gSupVal_1_5;
         //--- 8) RES2.0
         if(gToPlotBuffer[7])
            gBuffers[7].data[bar]=gResVal_2_0;
         //--- 9) SUP2.0
         if(gToPlotBuffer[8])
            gBuffers[8].data[bar]=gSupVal_2_0;
         //--- 10) RES2.5
         if(gToPlotBuffer[9])
            gBuffers[9].data[bar]=gResVal_2_5;
         //--- 11) SUP2.5
         if(gToPlotBuffer[10])
            gBuffers[10].data[bar]=gSupVal_2_5;
         //--- 12) RES3.0
         if(gToPlotBuffer[11])
            gBuffers[11].data[bar]=gResVal_3_0;
         //--- 13) SUP3.0
         if(gToPlotBuffer[12])
            gBuffers[12].data[bar]=gSupVal_3_0;
        }
         }

Die Aufzählung der Puffer fängt beim Erscheinen einer neuen Bar auf dem Chart an, auf dem der Indikator gestartet ist. MitGelb wurde die Bestimmung der Bar-Nummer gewählt, nach der wir Puffer aufzählen werden. Für diese Ziele wird der lokale Zähler der berechneten Bars verwendet. Wir haben ihn gebraucht, weil der Anfang des neuen Tages die Werte der Konstante prev_calculated nicht auf Null zurücksetzen wird, obwohl ein solches Rücksetzen notwendig ist.

Der vollständige Code des Pivots-Indikators wird unter der Datei Pivots.mq5 zugeordnet.

2. Die grundlegende Strategie

Aufgrund des beschriebenen Indikators werden wir versuchen, eine unkomplizierte grundlegende Strategie zu erstellen. Wenn das Signal zur Eröffnung von der Anordnung des Open-Preises des Tages bezüglich dem zentralen Pivot abhängig sein wird. Als Bestätigung für das Signal wird die Berührung der Pivot-Ebene vom Preis dienen.

So wird auf dem Chart EURUSD, M15 (die Abb.2) die Situation dargestellt, wenn der Tag (am 14. Januar 2015) unter dem zentralen Pivot angefangen hat, und später innerhalb des Tages hat der Preis seine Ebene von unten nach oben erreicht. So ist es das Signal auf den Verkauf erschienen. Wir werden beim Anfang des neuen Tages schließen, wenn weder Stop Loss, noch Take Profit nicht ausgelöst wurden.

In Abb. 2 die Grundlegende Strategie: das Signal auf den Verkauf

in Abb. 2 ist die Grundlegende Strategie: das Signal auf den Verkauf

Die Ebenen Stop Loss und Take Profit werden wir zu den Wendeebenen des Pivotsindikators verankern. Für den Verkauf durch Stop Loss wird die Mittelebene des Widerstands Res0.5 sein, welche auf $1.18153 ist. Als Stop Loss für den Profit wird die Hauptebene der Unterstützung Sup1.0 auf $1.17301 dienen. Ein Bisschen später kommen wir zurück zum Handelstag am 14. Januar. Solange reden wir über den Code, der in der algorithmischen Grundlage der grundlegenden Strategie gelegt wird.

2.1 die Signal-Klasse CSignalPivots

Wir werden die Signal-Klasse erstellen, die die Signale von verschiedenen Modellen generieren wird, die sich aufgrund der Preisdynamik und des Indikators der Wendeebenen bilden.

//+-----------------------------------------------------------------------+
//| Class CSignalPivots                                                   |
//| Purpose: Die Klasse der Handelssignale auf der Grundlage der Pivots.  |
//| Die Folge der Klasse CExpertSignal.                                   |
//+------------------------------------------------------------------+
class CSignalPivots : public CExpertSignal
  {
   //--- === Data members === ---  
protected:
   CiCustom          m_pivots;            // der Objekt-Indikator "Pivots"   
   //--- die einstellbaren Parameter
   bool              m_to_plot_minor;     // die Zeichnung der nebensächlichen Ebenen
   double            m_pnt_near;          // der Zutritt 
   //--- berechneten
   double            m_pivot_val;         // der Werte des Pivots
   double            m_daily_open_pr;     // Der Eröffnungspreis des laufenden Tages    
   CisNewBar         m_day_new_bar;       // die neu Bar der Tages-Timeframe
   //--- die Marktmodelle  
   //--- 1) das Modell 0 "die erste Berührung der Ebene PP" (von oben - buy, von unten - sell)
   int               m_pattern_0;         // вес
   bool              m_pattern_0_done;    // das Merkmal des durchgearbeiteten Modells
   //--- === Methods === ---  
public:
   //--- Konstruktor / Destruktor
   void              CSignalPivots(void);
   void             ~CSignalPivots(void){};
   //--- Die Methoden der Installierung der einstellbaren Parameter 
   void              ToPlotMinor(const bool _to_plot) {m_to_plot_minor=_to_plot;}
   void              PointsNear(const uint _near_pips);
   //--- Die Einstellungsmethoden "der Waage" der Marktmodelle
   void              Pattern_0(int _val) {m_pattern_0=_val;m_pattern_0_done=false;}
   //--- Die Prüfungsmethode der Einstellungen
   virtual bool      ValidationSettings(void);
   //--- Die Erstellungsmethode des Indikators und Timeserie
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- Die Prüfungsmethoden, wenn die Modelle des Marktes gebildet sind
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);
   virtual double    Direction(void);
   //--- Die Bestimmungsmethoden der Eintrittsebenen in den Markt
   virtual bool      OpenLongParams(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      OpenShortParams(double &price,double &sl,double &tp,datetime &expiration);
   //---
protected:
   //--- die Initializationsmethode des Indikators
   bool              InitCustomIndicator(CIndicators *indicators);
   //--- Die Erhaltung des Wertes des Pivots
   double            Pivot(void) {return(m_pivots.GetData(0,0));}
   //--- Die Erhaltung des Wertes der Hauptebene des Widerstands
   double            MajorResistance(uint _ind);
   //--- Die Erhaltung des Wertes der zweitrangigen Ebene des Widerstands
   double            MinorResistance(uint _ind);
   //--- Die Erhaltung des Wertes der Hauptebene der Unterstützung
   double            MajorSupport(uint _ind);
   //--- Die Erhaltung des Wertes der zweitrangigen Ebene der Unterstützung
   double            MinorSupport(uint _ind);
  };
  //+------------------------------------------------------------------+

Im Artikel "Rezepte MQL5 - Handelssignale der gleitenden Kanäle" verwendete ich diese Weise, wenn die Berührung eine irgendwelcher Linie vom Preis fixiert wird, wenn der Preis in der Umgebung dieser Linie gerät. Der Zutritt für die Wendeebene wird die Mitglieder-Daten m_pnt_near eingeben.

Die wichtigste Rolle in der Klasse muss man wohl dem Signalmodell lassen, welches die Klasse bedient. In der grundlegenden Klasse wird ein Modell sein. Außer dem Gewicht (m_pattern_0), sie wird noch das Merkmal der Durcharbeitung im Laufe vom Handelstag (m_pattern_0_done) haben.

Die grundlegende Signalklasse CExpertSignal hat viele virtuelle Methoden. Und dieser Reichtum lässt zu, die feine Einstellung der abgeleiteten Klasse zu realisieren.

Insbesondere habe ich für die Berechnung der Handelsebenen 2 Methoden OpenLongParams() und OpenShortParams() umdefiniert.

Wir schauen auf den Code der ersten Methode — die Bestimmung der Werte für die Handelsebenen beim Kauf.

//+------------------------------------------------------------------+
//| die Bestimmung der Handelsebenen für den Kauf                    |
//+------------------------------------------------------------------+
bool CSignalPivots::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
  {
   bool params_set=false;
   sl=tp=WRONG_VALUE;
//--- wenn das Modell 0 berücksichtigt wird
   if(IS_PATTERN_USAGE(0))
      //--- wenn das Modell 0 nicht durchgearbeitet ist
      if(!m_pattern_0_done)
        {
         //--- Eröffnungspreis - nach dem Markt
         double base_price=m_symbol.Ask();
         price=m_symbol.NormalizePrice(base_price-m_price_level*PriceLevelUnit());
         //--- sl-Preis - die Ebene Sup0.5
         sl=this.MinorSupport(0);
         if(sl==DBL_MAX)
            return false;
         //--- wenn den sl-Preis gibt
         sl=m_symbol.NormalizePrice(sl);
         //--- tp-Preis - die Ebene Res1.0         
         tp=this.MajorResistance(0);
         if(tp==DBL_MAX)
            return false;
         //--- wenn den tp-Preis gibt
         tp=m_symbol.NormalizePrice(tp);
         expiration+=m_expiration*PeriodSeconds(m_period);
         //--- wenn die Preise gegeben wurden
         params_set=true;
         //--- das Modell ist durchgearbeitet 
         m_pattern_0_done=true;
        }
//---
   return params_set;
  }
  //+------------------------------------------------------------------+

Der Preis Stopp-Loss wird wie der Wert der ersten zweitrangigen Ebene der Unterstützung mit Hilfe der Methode MinorSupport() berechnet. Den Profit geben wir nach dem Preis der ersten Hauptebene des Widerstands mit Hilfe der Methode MajorResistance(). Für den Verkauf werden sich diese Methoden entsprechend gewechselt, um MinorResistance() und MajorSupport().

Um die Methoden der Bestimmung der Handelsebenen in der abgeleiteten Klasse wirksam wären, muss man das benutzerdefinierte Signal als das Hauptsignal machen. So sieht die Bestimmungsmethode der Handelsebenen der Elternklasse aus:

//+------------------------------------------------------------------+
//| Detecting the levels for buying                                  |
//+------------------------------------------------------------------+
bool CExpertSignal::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
  {
   CExpertSignal *general=(m_general!=-1) ? m_filters.At(m_general) : NULL;
//---
   if(general==NULL)
     {
      //--- if a base price is not specified explicitly, take the current market price
      double base_price=(m_base_price==0.0) ? m_symbol.Ask() : m_base_price;
      price      =m_symbol.NormalizePrice(base_price-m_price_level*PriceLevelUnit());
      sl         =(m_stop_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price-m_stop_level*PriceLevelUnit());
      tp         =(m_take_level==0.0) ? 0.0 : m_symbol.NormalizePrice(price+m_take_level*PriceLevelUnit());
      expiration+=m_expiration*PeriodSeconds(m_period);
      return(true);
     }
//---
   return(general.OpenLongParams(price,sl,tp,expiration));
  }
  //+------------------------------------------------------------------+

Wenn der Index des Hauptsignals nicht eingegeben wurde, so werden die Ebenen die Werte standardmäßig bekommen. Um eine solche Situation zu vermeiden, kann man im Code des EAs bei der Initialization des Signals das Folgende schreiben:

//--- Der Filter CSignalPivots
   CSignalPivots *filter0=new CSignalPivots;
   if(filter0==NULL)
     {
      //--- Fehler
      PrintFormat(__FUNCTION__+": error creating filter0");
      return INIT_FAILED;
     }
   signal.AddFilter(filter0);
     signal.General(0);  

Die Prüfungsmethode der Bedingung auf den Kauf wurde so vorgestellt:

//+------------------------------------------------------------------+
//| Die Überprüfung der Bedingung auf den Kauf                       |
//+------------------------------------------------------------------+
int CSignalPivots::LongCondition(void)
  {
   int result=0;
//--- wenn das Modell 0 berücksichtigt wird
   if(IS_PATTERN_USAGE(0))
      //--- wenn das Modell 0 nicht durchgearbeitet ist
      if(!m_pattern_0_done)
         //--- wenn der Tag über dem Pivot begann
         if(m_daily_open_pr>m_pivot_val)
           {
            //--- Der minimale Preis auf der laufenden Bar
            double last_low=m_low.GetData(1);
            //--- wenn der Preis bekommen wurde
            if((last_low>WRONG_VALUE) && (last_low<DBL_MAX))
               //--- wenn die Berührung von oben war (unter Berücksichtigung des Zutrittes)
               if(last_low<=(m_pivot_val+m_pnt_near))
                 {
                  result=m_pattern_0;
                  //--- Im Journal
                  Print("\n---== Die Berührung die Pivot-Ebene vom Preis von oben ==---");
                  PrintFormat("Der Preis: %0."+IntegerToString(m_symbol.Digits())+"f",last_low);
                  PrintFormat("Pivot: %0."+IntegerToString(m_symbol.Digits())+"f",m_pivot_val);
                  PrintFormat("Der Zutritt: %0."+IntegerToString(m_symbol.Digits())+"f",m_pnt_near);
                 }
           }
//---
   return result;
  }
  //+------------------------------------------------------------------+

Es ist leicht, zu bemerken, dass die Berührung von oben unter Berücksichtigung des Zutrittes last_low<=(m_pivot_val+m_pnt_near) geprüft wird.

Die Methode der Bestimmung "der abgewogenen" Richtung Direction(), prüft außerdem, noch die Durcharbeitung des grundlegenden Modells.

//+------------------------------------------------------------------+
//| die Bestimmung "der abgewogenen" Richtung                        |
//+------------------------------------------------------------------+
double CSignalPivots::Direction(void)
  {
   double result=0.;
//--- Die Erhaltung der historischen Tagesdaten
   MqlRates daily_rates[];
   if(CopyRates(_Symbol,PERIOD_D1,0,1,daily_rates)<0)
      return 0.;
//--- wenn das Modell 0 durchgearbeitet ist
   if(m_pattern_0_done)
     {
      //--- das Erscheinen des neuen Tages prüfen
      if(m_day_new_bar.isNewBar(daily_rates[0].time))
        {
         //--- die Fahne der Durcharbeitung des Modells zurücksetzen
         m_pattern_0_done=false;
         return 0.;
        }
     }
//--- wenn das Modell 0 nicht durchgearbeitet ist
   else
     {
      //--- Der Eröffnungspreis
      if(m_daily_open_pr!=daily_rates[0].open)
         m_daily_open_pr=daily_rates[0].open;
      //--- Pivot
      double curr_pivot_val=this.Pivot();
      if(curr_pivot_val<DBL_MAX)
         if(m_pivot_val!=curr_pivot_val)
            m_pivot_val=curr_pivot_val;
     }
//--- Das Ergebnis
   result=m_weight*(this.LongCondition()-this.ShortCondition());
//---
   return result;
  }
  //+------------------------------------------------------------------+

Bezüglich der Signale für die Schließung, so werden wir die Methoden der Elternklasse CloseLongParams() und CloseShortParams() umdefinieren. Das Beispiel des Codes für den Kaufsblock:

//+------------------------------------------------------------------+
//| Die Bestimmung der Handelsebene für den Kauf                     |
//+------------------------------------------------------------------+
bool CSignalPivots::CloseLongParams(double &price)
  {
   price=0.;
//--- wenn das Modell 0 berücksichtigt wird
   if(IS_PATTERN_USAGE(0))
      //--- wenn das Modell 0 nicht durchgearbeitet ist
      if(!m_pattern_0_done)
        {
         price=m_symbol.Bid();
         //--- Im Journal
         Print("\n---== Das Signal für die Schließung des Kaufs ==---");
         PrintFormat("Der Marktpreis: %0."+IntegerToString(m_symbol.Digits())+"f",price);
         return true;
        }
//--- return the result
   return false;
  }
  //+------------------------------------------------------------------+

Die Schwelle des Signals für die Schließung muss man auf Null im Code des EAs zurücksetzen.

signal.ThresholdClose(0);

Dann wird in der Elternklasse die Prüfung nach der Richtung nicht stattfinden.

//+------------------------------------------------------------------+
//| Generating a signal for closing of a long position               |
//+------------------------------------------------------------------+
bool CExpertSignal::CheckCloseLong(double &price)
  {
   bool   result   =false;
//--- the "prohibition" signal
   if(m_direction==EMPTY_VALUE)
      return(false);
//--- check of exceeding the threshold value
   if(-m_direction>=m_threshold_close)
     {
      //--- there's a signal
      result=true;
      //--- try to get the level of closing
      if(!CloseLongParams(price))
         result=false;
     }
//--- zeroize the base price
   m_base_price=0.0;
//--- return the result
   return(result);
  }
  //+------------------------------------------------------------------+

Es entsteht die Frage: auf wessen Kosten das Signal auf die Schließung in diesem Fall geprüft werden soll? Er wird in erster Linie geprüft, vom Vorhandensein der Position (in der Methode Processing()), und noch, vom Merkmal m_pattern_0_done (in den umdefinierten Methoden CloseLongParams() und CloseShortParams() ). Im Allgemeinen, solange der Experte das Vorhandensein der Position beim nicht durchgearbeiteten Modell 0 herausfindet, so versucht er sofort, die Position zu schließen. Es findet am Anfang des Handelstages statt.

Wir betrachteten die Grundlagen der benutzerdefinierten Signalklasse CSignalPivots, jetzt werden wir über die Klasse der Strategie reden.

2.2 die Klasse der Handelsstrategie CPivotsExpert

Die abgeleitete Klasse der Strategie ist ähnlich mit den gleichen für die gleitenden Kanäle. Die Unterschiede bestehen erstens darin, dass es keinen tickweisen Handelsmodus verwendet wird, sondern pro minütige. Es ermöglicht die Strategie auf genügend tiefe History zu prüfen. Zweitens, es gibt die Prüfung für die Schließung der Position. Hier oben wurde es bestimmt, warum der EA die Position schließen kann.

Der Methode-Hauptbearbeiter sieht so aus:

//+------------------------------------------------------------------+
//| Das Haupt-Modul                                                  |
//+------------------------------------------------------------------+
bool CPivotsExpert::Processing(void)
  {
//--- Die neue Bar pro Minute
   if(!m_minute_new_bar.isNewBar())
      return false;
//--- Die Berechnung der Richtung
   m_signal.SetDirection();
//--- wenn es keine Positionen gibt

   if(!this.SelectPosition())
     {
      //--- Das Eröffnungsmodul der Positionen
      if(this.CheckOpen())
         return true;
     }
//--- wenn es Positionen gibt 
   else
     {
      //--- Das Schließungsmodul der Positionen
      if(this.CheckClose())
         return true;
     }
//--- wenn es keine Handelsoperationen gibt
   return false;
  }
  //+------------------------------------------------------------------+

Eigentlich war das. Jetzt können wir die grundlegende Strategie starten. Ihr Code wurde in der Datei BasePivotsTrader.mq5 dargestellt.


In Abb.3 die Grundlegende Strategie: Verkauf

in Abb. 3 die Grundlegende Strategie: Kauf

Wir kommen zum Beispiel am 14. Januar 2015 zurück In diesem Fall war das Modell einfach ideal durchgearbeitet. Wir haben nach unten auf Pivot geöffnet, und haben auf der Ebene der Hauptunterstützung Sup1.0 geschlossen.

Es wurde eine Probe im Strategie-Tester vom 07.01.2013 bis 07.01.2017 auf der Timeframe 15 nach dem Symbol EURUSD mit den folgenden Werten der Parameter durchgeführt:

  • Die Grenze des Signals zur Eröffnung, [0...100] = 10;
  • Gewicht, [0...1.0] = 1,0;
  • Der fixierte Volumen= 0,1;
  • Der Zutritt, пп = 15.

Wie es festgestellt wurde, handelt die Strategie mit einem standfesten Ergebnis. Allerdings, ist das Ergebnis negativ (Abb.4).

Abb. 4 EURUSD: die Ergebnisse der ersten grundlegenden Strategie für 2013-2016.

in Abb. 4  EURUSD: die Ergebnisse der ersten grundlegenden Strategie für 2013-2016

Nach dem Chart der Produktivität haben wir alles falsch gemacht. Man hätte kaufen sollen, wenn das Signal auf Verkauf kam, und, - beim Signal auf den Kauf verkaufen. Ist das wirklich so? Wir versuchen es zu prüfen. Dafür erstellen wir die zweite grundlegende Strategie.

Wir fügen zu ihr die Änderungen im Teil der Signale hinzu. Dann wird, zum Beispiel die Bedingung auf den Kauf so aussehen:

//+------------------------------------------------------------------+
//| Die Überprüfung der Bedingungen auf den Verkauf                  |
//+------------------------------------------------------------------+
int CSignalPivots::LongCondition(void)
  {
   int result=0;
//--- wenn das Modell 0 berücksichtigt wird
   if(IS_PATTERN_USAGE(0))
      //--- wenn das Modell 0 nicht durchgearbeitet ist
      if(!m_pattern_0_done)
         //--- wenn der Tag unter dem Pivot begann
         if(m_daily_open_pr<m_pivot_val)
           {
            //--- Der maximale Preis auf der laufenden Bar
            double last_high=m_high.GetData(1);
            //--- wenn der Preis bekommen wurde
            if((last_high>WRONG_VALUE) && (last_high<DBL_MAX))
               //--- wenn die Berührung von unten war (unter Berücksichtigung des Zutrittes)

               if(last_high>=(m_pivot_val-m_pnt_near))
                 {
                  result=m_pattern_0;
                  //--- Im Journal
                  Print("\n---== Die Berührung die Pivot-Ebene vom Preis von unten ==---");
                  PrintFormat("Der Preis: %0."+IntegerToString(m_symbol.Digits())+"f",last_high);
                  PrintFormat("Pivot: %0."+IntegerToString(m_symbol.Digits())+"f",m_pivot_val);
                  PrintFormat("Der Zutritt: %0."+IntegerToString(m_symbol.Digits())+"f",m_pnt_near);
                 }
           }
//---
   return result;
  }
  //+------------------------------------------------------------------+

Wir versuchen wieder die Strategie im Tester zu probieren und bekommen ein solches Ergebnis:

Abb.5 EURUSD: die Ergebnisse der zweiten grundlegenden Strategie für 2013-2016.

in Abb. 5  EURUSD: die Ergebnisse der zweiten grundlegenden Strategie für 2013-2016

Es ist offenbar, dass es keine Kopie der ersten Version geworden ist. Schuld daran, offensichtlich liegt an den Umfang Stop-Loss und Take-Profit. Außerdem wird beim neuen Tages die Positionen geschlossen, nach denen weder Stopp-Loss, auch Profit im Laufe des Handelstages nicht ausgelöst wurden.

Wir versuchen wieder die grundlegende Strategie zu ändern, und zwar — ihre zweite Version. Wir machen es so, damit für den Kauf die Ebenen Stopp-Loss etwas weiter — bis zur Hauptunterstützung Sup1.0 gestellt werden, und der Umfang des Profits wird von der Mittelebenen des Widerstands Res0.5 beschränkt. Für den Verkauf Stop-Loss werden wir es auf die Ebene Res1.0 stellen, und den Profit — auf Sup0.5.

Dann, zum Beispiel, die Handelsebene für den Kauf wird so bestimmt:

//+------------------------------------------------------------------+
//| Die Bestimmung der Handelsebenen für den Kauf                    |
//+------------------------------------------------------------------+
bool CSignalPivots::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
  {
   bool params_set=false;
   sl=tp=WRONG_VALUE;
//--- wenn das Modell 0 berücksichtigt wird
   if(IS_PATTERN_USAGE(0))
      //--- wenn das Modell 0 nicht durchgearbeitet ist
      if(!m_pattern_0_done)
        {
         //--- Der Eröffnungspreis - nach dem Markt
         double base_price=m_symbol.Ask();
         price=m_symbol.NormalizePrice(base_price-m_price_level*PriceLevelUnit());
         //--- sl-Preis - die Ebene Sup1.0
         sl=this.MajorSupport(0);
         if(sl==DBL_MAX)
            return false;
         //--- wenn den sl-Preis gibt
         sl=m_symbol.NormalizePrice(sl);
         //--- tp-Preis - die Ebene Res0.5         
         tp=this.MinorResistance(0);
         if(tp==DBL_MAX)
            return false;
         //--- wenn den tp-Preis gibt
         tp=m_symbol.NormalizePrice(tp);
         expiration+=m_expiration*PeriodSeconds(m_period);
         //--- wenn die Preise gegeben wurden
         params_set=true;
         //--- das Modell ist durchgearbeitet 
         m_pattern_0_done=true;
        }
//---
   return params_set;
  }
  //+------------------------------------------------------------------+

Wir bekommen im Tester ein solches Ergebnis für die dritte Version:

Abb.6  EURUSD: die Ergebnisse der dritten grundlegenden Strategie für 2013-2016.

in Abb. 6 EURUSD: die Ergebnisse der dritten grundlegenden Strategie für 2013-2016

Das Bild hat sich mehr oder weniger ähnlich mit der Kopie für die erste Version ergeben. Auf den ersten Blich scheint es, dass Gral gefunden ist. Aber es gibt noch die versteckten Fälle, über die wir im nächsten Kapitel reden werden.

3. Zur Frage über Robustheit

Wenn man sich genau die Abb.6 anschaut, so ist es leicht, zu bemerken, dass die Kurve der Balance ungleichmäßig wuchs. Es waren die Intervallen, wo die Balance den Gewinn stabil ansammelte. Es waren die Drawdown-Intervallen. Sowie waren auch die Intervallen, wo sich die Kurve der Balance nach rechts bewog, streng nach Osten.

Die Robustheit (robustness) – ist eine Stabilität des Handelssystems, die die relativen Beständigkeit und Effektivität des Systems auf einem langwierigen Zeitraum bestätigt.

Insgesamt, kann man sagen, dass der Strategie die Robustheit fehlt. Kann man sie erhöhen? Wir versuchen es.

3.1 Der Indikator des Trends

Meiner Meinung nach funktionieren die höher beschriebenen Handelsregeln besser, wenn es auf dem Markt die gerichtete Bewegung — den Trend gibt. So zeigte die Strategie das beste Ergebnis auf EURUSD in 2014 — Anfang 2015, wenn das Paar standfest sank.

Es stellt sich heraus, dass ein irgendwelcher Filter gebraucht wird, welcher ermöglicht, die Seitenbewegung zu vermeiden. Zum Thema der Bestimmung des festen Trends existiert eine Menge von Materialien, einschließlich hier, im Kapitel "Artikel" auf mql5.com. Mir hat es persönlich am besten der Artikel "Verschiedene Wege zur Ermittlung eines Trends in MQL5" gefallen. In dem der Autor vorschlägt, eine bequeme und noch was wichtiger eine universelle Weise der Suche des Trends.

Ich habe den ähnlichen Indikator MaTrendCatcher erstellt. In dem Artikel werden zwei Movings genommen — ein schneller und ein langsamer. Wenn den Unterschied zwischen den Werten positiv ist, so denken wir, dass der Trend stierisch ist. Dann werden die kleinen Pfähle des Histogramms im Indikator gleich 1 sein. Wenn der Unterschied negativ sein wird, bedeutet es, es herrscht auf dem Markt der Bärentrend. Die kleinen Pfähle werden gleich -1 sein (Abb.7.).

Abb.7  Der Indikator des Trends MaTrendCatcher

in Abb. 7  Der Indikator des Trends MaTrendCatcher

Außerdem wenn bezüglich der vorherigen Bar den Unterschied zwischen Movings (der Trend steigert sich) wächst, so wird der kleine Pfahl grün, wenn es sinkt — rot.

Und noch eine Möglichkeit, die zum Indikator hinzugefügt ist: da, wo die Verschiedenheit zwischen МА klein ist, die kleinen Pfähle werden nicht dargestellt. Inwiefern die Verschiedenheit klein sein soll, um ihre visuelle Darstellung zu verbergen — es hängt vom einstellbaren Parameter des Indikators "Einmessung, пп" (die Abb.8) ab

Abb.8  Der Indikator des Trends MaTrendCatcher, die Einmessung der kleinen Unterschiede

in Abb. 8  Der Indikator des Trends MaTrendCatcher, die Einmessung der kleinen Unterschiede

Also, zwecks der Filtrierung werden wir den Indikator MaTrendCatcher verwenden.

Um den Indikator einzusetzen, muss man einige Änderungen an dem Dateien-Code des Projektes hinzufügen. Wir sagen sofort, dass die letzte Version des EAs im Ordner Model gespeichert wird.

Zwecks der Strategie hätte man die berechnete Größe "der abgewogenen" Richtung bekommen müssen. Deshalb musste man den benutzerdefinierten Klasse-Nachkommen von der grundlegenden Signalklasse erstellen.

class CExpertUserSignal : public CExpertSignal

Später in der erneuerten Signalklasse der Wendeebenen das neue Modell — das Modell 1 "der Trend-flet-Kontertrend" erschienen.

Eigentlich bereichert sie das Modell 0. Deshalb kann man sie als Submodell nennen. Ein Bisschen später werden wir im Code diesen Moment bemerken.

Jetzt sieht die Prüfungsmethode der Bedingung auf den Kauf so aus:

//+------------------------------------------------------------------+
//| Die Überprüfung der Bedingung auf den Kauf                       |
//+------------------------------------------------------------------+
int CSignalPivots::LongCondition(void)
  {
   int result=0;
//--- wenn das Modell 0 berücksichtigt wird
   if(IS_PATTERN_USAGE(0))
      //--- wenn das Modell 0 nicht durchgearbeitet ist
      if(!m_pattern_0_done)
        {
         m_is_signal=false;
         //--- wenn der Tag unter dem Pivot begann
         if(m_daily_open_pr<m_pivot_val)
           {
            //--- Der maximale Preis auf der letzten Bar
            double last_high=m_high.GetData(1);
            //--- wenn der Preis bekommen wurde
            if(last_high>WRONG_VALUE && last_high<DBL_MAX)
               //--- wenn die Berührung von unten war (unter Berücksichtigung des Zutrittes)

               if(last_high>=(m_pivot_val-m_pnt_near))
                 {
                  result=m_pattern_0;
                  m_is_signal=true;
                  //--- Im Journal
                  this.Print(last_high,ORDER_TYPE_BUY);
                 }
           }
         //--- wenn das Modell 1 berücksichtigt wird

         if(IS_PATTERN_USAGE(1))
           {
            //--- Wenn auf der vorherigen Bar den Stiertrend gab
            if(m_trend_val>0. && m_trend_val!=EMPTY_VALUE)
              {
               //--- wenn es eine Beschleunigung gibt
               if(m_trend_color==0. && m_trend_color!=EMPTY_VALUE)
                  result+=(m_pattern_1+m_speedup_allowance);
               //--- wenn es keine Beschleunigung gibt
               else
                  result+=(m_pattern_1-m_speedup_allowance);
              }
           }
        }
//---
   return result;
      }

Ich habe mit grün den Block gewählt, wo das Submodell eingesetzt wird.

Die Berechnung hat den folgenden Sinn: wenn der Eintritt in den Markt ohne Rücksicht auf das Submodell durchgeführt wurde, so wird das Ergebnis des Signals dem Gewicht des Modells 0 gleich sein. Wenn das Submodell berücksichtigt wird, so sind die folgenden Varianten möglich:

  1. Der Eintritt nach dem Trend mit der Beschleunigung (Bonus für den Trend und Bonus für die Beschleunigung);
  2. Der Eintritt nach dem Trend ohne Beschleunigung (Bonus für den Trend und eine Strafe für die Beschleunigung);
  3. Der Eintritt gegen den Trend mit der Beschleunigung (eine Strafe für den Gegentrend und eine Strafe für die Beschleunigung);
  4. Der Eintritt gegen den Trend ohne Beschleunigung (eine Strafe für den Gegentrend und Bonus für die Beschleunigung).

Ein solches Herangehen ermöglicht auf ein schwaches Signal keine Reaktion zu geben. Und wenn das Gewicht des Signals den Grenzenwert überschreitet, so beeinflusst er auf den Umfang des Handelsvolumens. In der Klasse des EAs nach Pivots gibt es die Methode CPivotsExpert::LotCoefficient():

//+------------------------------------------------------------------+
//| Der Koeffizient des Lots                                         |
//+------------------------------------------------------------------+
double CPivotsExpert::LotCoefficient(void)
  {
   double lot_coeff=1.;
//--- Das allgemeine Signal
   CExpertUserSignal *ptr_signal=this.Signal();
   if(CheckPointer(ptr_signal)==POINTER_DYNAMIC)
     {
      double dir_val=ptr_signal.GetDirection();
      lot_coeff=NormalizeDouble(MathAbs(dir_val/100.),2);
     }
//---
   return lot_coeff;
  }
  //+------------------------------------------------------------------+

So wenn das Signal 120 Punkte hat, so wird der Anfangsvolumen um 1,2 korrigiert, und wenn 70 — um 0,7.

Um den Koeffizient zu verwenden, muss man noch die Methoden OpenLong() und OpenShort() umdefinieren. Insbesondere, die Methode für den Kauf ist so vorgestellt:

//+------------------------------------------------------------------+
//| Long position open or limit/stop order set                       |
//+------------------------------------------------------------------+
bool CPivotsExpert::OpenLong(double price,double sl,double tp)
  {
   if(price==EMPTY_VALUE)
      return(false);
//--- get lot for open
   double lot_coeff=this.LotCoefficient();
   double lot=LotOpenLong(price,sl);
   lot=this.NormalLot(lot_coeff*lot);
//--- check lot for open
   lot=LotCheck(lot,price,ORDER_TYPE_BUY);
   if(lot==0.0)
      return(false);
//---
   return(m_trade.Buy(lot,price,sl,tp));
  }
  //+------------------------------------------------------------------+

Die Idee mit der dynamischen Bildung des Umfanges des Lotes ist ziemlich einfach: je stärker das Signal ist, desto mehr Risiko haben wir.

3.2 Der Umfang des Bereichs

Es ist auch einfach, zu bemerken, dass es keine große Volatilität am Markt gibt, wenn die Wendeebenen (Pivots) nahe voneinander sind. Um das Handeln in solchen Tagen auszuschließen, ist ein solcher Parameter eingeführt, wie "das Limit nach der Breite, пп" . Das Modell 0 ( mit ihm noch das Submodell) wird als durchgearbeitet gelten, wenn die Grenze des Limits nicht überschrittet war. Es wird dieses Limit im Körper der Methode Direction() geprüft. Ich schreibe einen Teil des Codes:

//--- wenn das Limit gegeben ist
   if(m_wid_limit>0.)
     {
      //--- das obere Rechnungslimit 
      double norm_upper_limit=m_symbol.NormalizePrice(m_wid_limit+m_pivot_val);
      //--- das reale obere Limit
      double res1_val=this.MajorResistance(0);
      if(res1_val>WRONG_VALUE && res1_val<DBL_MAX)
        {
         //--- wenn das Limit nicht überschreitet wurde 
         if(res1_val<norm_upper_limit)
           {
            //--- das Modell 0 ist durchgearbeitet 
            m_pattern_0_done=true;
            //--- Im Journal
            Print("\n---== das reale obere Limit ist nicht überschreitet ==---");
            PrintFormat("berechnetes: %0."+IntegerToString(m_symbol.Digits())+"f",norm_upper_limit);
            PrintFormat("reales: %0."+IntegerToString(m_symbol.Digits())+"f",res1_val);
            //---
            return 0.;
           }
        }
      //--- das untere Rechnungslimit 
      double norm_lower_limit=m_symbol.NormalizePrice(m_pivot_val-m_wid_limit);
      //--- das reale untere Limit
      double sup1_val=this.MajorSupport(0);
      if(sup1_val>WRONG_VALUE && sup1_val<DBL_MAX)
        {
         //--- wenn das Limit nicht überschreitet wurde 
         if(norm_lower_limit<sup1_val)
           {
            //--- das Modell 0 ist durchgearbeitet 
            m_pattern_0_done=true;
            //--- Im Journal
            Print("\n---== das reale untere Limit ist nicht überschreitet ==---");
            PrintFormat("berechnetes: %0."+IntegerToString(m_symbol.Digits())+"f",norm_lower_limit);
            PrintFormat("reales: %0."+IntegerToString(m_symbol.Digits())+"f",sup1_val);
            //---
            return 0.;
           }
        }
         }

Und wenn das Signal nach der Breite des Umfangs die Prüfung nicht bestanden ist, so wird im Journal zum Beispiel eine solche Aufzeichnung erscheinen:

2015.08.19 00:01:00   ---== das obere Limit wurde nicht überschreitet ==---
2015.08.19 00:01:00   berechnetes: 1.10745
2015.08.19 00:01:00   reales: 1.10719
D.h. in diesem Fall reichte es nicht 26 Punkte, um das Signal vollwertig zu werden.

Starten wir die Strategie im Tester im Optimierungsmodus. Ich verwendete die folgenden Optimierungsparameter:

  1. "Nach der Breite, пп";
  2. "Der Zutritt, пп";
  3. "das schnelle МА";
  4. "das langsame МА";
  5. "Einmessung, пп".

Die erfolgreichteste Probe aus der Sicht des Gewinnes sieht aus:

Abb.9 EURUSD: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

in Abb. 9 EURUSD: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

Eigentlich hätten man es erwarten können, es wurden einige Signale ausgeschlossen. Die Kurve der Balance ist gleichmäßiger geworden.

Aber man soll auch darüber sagen, was schief gegangen ist. Die Strategie, wie es auf dem Chart zu sehen ist, seit 2015 generiert die Intervalle, auf den die Kurve der Balance sich im engen Umfang ohne offenbares Wachstum des Gewinns schwingt. Die Optimierungsergebnisse sind in der Datei EURUSD_model.xml.

Lassen uns bitte schauen, wie die Ergebnisse auf den anderen Instrumenten sind.

So auf dem Paar USDJPY wurde der beste Durchgang auf der Abb. 10 dargestellt.

Abb.10 USDJPY: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

in Abb. 10 USDJPY: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

Jetzt schauen wir mal auf das Spot Gold . Das beste Ergebnis wurde auf der Abb. 11 dargestellt

Abb.11 XAUUSD: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

in Abb. 11 XAUUSD: die Ergebnisse die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

In der gegebenen Periode wurde das Edelmetall im engen Umfang gehandelt, deshalb hat die Strategie ein positives Ergebnis nicht gebracht.

Bezüglich des britischen Pfunds wurde der beste Durchgang auf der Abb. 12 dargestellt.

Abb.12 GBPUSD: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

in Abb. 12 GBPUSD: die Ergebnisse der Strategie unter Verwendung der Filter für 2013-2016

Das Pfund wurde gut nach dem Trend gehandelt. Aber die Korrektion am Anfang 2015. hat das endgültige Ergebnis schlechter gemacht.

Im Allgemeinen funktioniert die Strategie am besten dann, wenn es auf dem Markt die gerichtete Bewegung gibt.

Fazit

Zum Schluss möchte ich bemerken, dass der Prozess der Bildung der Handelsstrategie aus einigen Stufen besteht. Am Anfang wird die Handelsidee zusammengefasst. In der Regel ist es die Hypothese, die man in Form vom Code formalisieren muss, und später im Tester prüfen Sehr oft muss man irgendwas schon im Laufe der Prüfung korrigieren und ausarbeiten. Darin besteht eben eine gewöhnlich Arbeit des Entwicklers. Auch in diesem Fall für die Kodierung der Strategie Pivots wurde diese Weise verwendet. Dabei erleichtert meiner Meinung nach die Verwendung ООП die Aufgabe des Entwicklers.

Ich werde es bemerken, dass der ganze Test im Optimierungsmodus habe ich in MQL5 Cloud Network durchgeführt. Mit Hilfe der wolkigen Technologie gelang es mir schnell genug und preiswert, die Produktivität der Strategien zu bewerten.


Der Ordner der Dateien

Der Ordner der Dateien

Es ist am bequemsten, die Dateien mit den Strategien in einem Ordner Pivots zu ordnen. Die Dateien der Indikatoren (Pivots.ex5 und MaTrendCatcher.ex5) nach der Kompilation muss man zum Ordner der Indikatoren %MQL5\Indicators eintragen.

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

Beigefügte Dateien |
Pivots.zip (43.18 KB)
Optimization.zip (40.72 KB)
DeMarks Sequential (TD SEQUENTIAL) unter Verwendung künstlicher Intelligenz DeMarks Sequential (TD SEQUENTIAL) unter Verwendung künstlicher Intelligenz
In diesem Artikel werde ich erzählen, wie man durch das Kreuzen einer sehr bekannten Strategie mit einem neuronalen Netz erfolgreich handeln kann. Es wird um die Strategie Thomas Demarks "Sequential" unter Verwendung künstlicher Intelligenz gehen. Wir werden NUR nach dem ersten Teil der Strategie arbeiten, dabei verwenden wir die Signale der "Setzung" und "Kreuzung".
Grafische Interfaces X: Algorithmus für den Zeilenumbruch im mehrzeiligen Textfeld (build 12) Grafische Interfaces X: Algorithmus für den Zeilenumbruch im mehrzeiligen Textfeld (build 12)
Wir fahren fort mit der Entwicklung eines mehrzeiligen Textfeldes. Diesmal ist es unsere Aufgabe einen Algorithmus für den Fall, dass der Text die Breite des Textfeldes überschreitet, zu entwickeln oder, umgekehrt, einen Zeilenumbruch zu entfernen, wenn die möglich ist.
Wolfe Wellen Wolfe Wellen
Die von Bill Wolfe vorgeschlagene Methode hilft nicht nur ein Muster zu erkennen und somit den Moment und die Richtung des Einstiegs zu bestimmen, sondern auch das Ziel vorherzusagen, das der Preis erreichen muss sowie die Zeit des Erreichens. Der Artikel beschreibt die Erstellung eines Indikator für die Erkennung der Wolfe Wellen basierend auf dem ZigZag Indikator sowie einen einfachen Expert Advisor, der nach seinen Signalen handelt.
Das Handelssystem DiNapoli Das Handelssystem DiNapoli
Im Artikel wird gründlich das Handelssystem unter Verwendung der Ebene Fibonatschtschi betrachtet, die Joe DiNapoli entwickelt und beschrieben hat. Es werden die Hauptbegriffe und das Wesen des Systems erklärt, es wird die Illustration auf dem Beispiel des unkomplizierten Indikators gegeben.