Die Übertragung der Trading-Signale in einem universalen Expert Advisor.

Igor Kim | 13 Februar, 2012


Einführung


Vor einiger Zeit habe ich versucht, den Entwicklungsprozess des Expert Advisors im Thema "Die Entwicklung eines universellen Expert Advisors" zu verallgemeinern und zu vereinheitlichen. Dies bedeutete die Ausarbeitung eines gewissen Standards, die Haupteinheit-Ziegel zu entwickeln. Von denen man später den Expert Advisor konstruieren könnte, wie von Teilen eines Baukastens. Teilweise habe ich diese Aufgabe realisiert, ich bot eine Struktur eines universellen EAs und ein Bild von einer universellen Verwendung an, in der Signale von verschiedenen Indikatoren waren. In diesem Artikel werde ich diese Arbeit fortsetzen - Ich werde versuchen, den Prozess der Bildung und der Übertragung der Trading-Signale mit Positionsmanagement im Expert Advisors zu verallgemeinern. In diesem Zusammenhang werde ich direkt klarstellen, dass ich unter Positionen alle Operationen BUY und SELL meine und dass alle unter erwähnten Positionen nur damit zu tun haben. Dieser Artikel beschreibt noch keine Pending Orders BUYLIMIT, BUYSTOP, SELLLIMIT und SELLSTOP, aber am Ende des Artikels zeige ich, dass meine Methode leicht auf sie angewendet werden kann.

Klassifizierung der Handelssignale


Es gibt mehrere Arten von Trading-Signalen:
  1. Kaufen;
  2. Verkaufen;
  3. Zusätzlicher Kauf (Averaging,Mittelwertbildung);
  4. Zusätzlicher Verkauf (Averaging,Mittelwertbildung);
  5. Kauf voll schließen;
  6. Verkauf voll schließen;
  7. Kauf teilweise schließen;
  8. Verkauf teilweise schließen.

Wenn wir die Entscheidung bezüglich Averaging, Mittelwertbildung und teilweise Schließung von der Einheit der Handelssignalen-Formation in die Steuerungseinheit der Positionen umsetzen, kann diese Liste folgendermaßen reduziert werden:

  1. Kaufen;
  2. Verkaufen;
  3. Kauf schließen;
  4. Verkauf schließen;
  5. Nichts tun (für eine normale Funktionalität des EAs wird noch ein solches Signal erfordert).

Abgesehen davon wird das folgende Schema des EAs vorgenommen:

  1. Das Signal-Modul bildet ein Handelssignal;
  2. Ein Trading-Signal geht in die Steuerungseinheit der Positionen, die über Neueröffnungen, Averaging/Mittelwertbildung, teilweise oder vollständige Schließung entscheidet und überträgt das verkürzte Handelssignal in die Ausführungseinheit der Handelssignale;
  3. Die Ausführungseinheit der Handelssignale führt direkt die Handelsoperationen aus.
In diesem Artikel möchte ich verschiedene Weise der Bildung von Handelssignalen betrachten und die Möglichkeiten ihrer Übertragung in die Steuerungseinheit der Positionen, das heißt, in die Interface zwischen den Einheiten, aus den Punkten 1 und 2.

Swing Trading einer Position


Der Sinn eines solchen Handels besteht darin: dass bevor Sie eine neue Position öffnen, sollte die vorherige geschlossen werden. Die neue Position wird mit dem vorherigen gegenüber sein. Wenn ein Kauf war, wird auch ein Verkauf geöffnet und umgekehrt. Von daher, dass die Momente von Öffnungen und Schließungen der Positionen gleichzeitig sind, können die Schließungssignale reduziert werden. Nach dieser Weise reicht es den Swing-Trading zu realisieren, wenn die Übertragung von drei Handelssignalen wird: kaufen, verkaufen und nichts tun. Diese Signale können nur durch eine int-Variable übertragen werden. Zum Beispiel:

    1 - Kaufen;
    0 - nichts tun;
   -1 - Verkaufen.

Dann wird der Analyse-Block der Marktsituation und der Block der Handelssignalebildung in einer Funktion geschrieben, zum Beispiel GetTradeSignal(),
//+----------------------------------------------------------------------------+
//|  Liefert das  Handelsignal zurück:                                               |
//|     1 - Kaufen                                                             |
//|     0 - nichts tun                                                    |
//|    -1 - Verkaufen                                                           |
//|  Parameter:                                                                |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
int GetTradeSignal(string sym="", int tf=0) 
  {
   int bs=0;
   if (sym=="") sym=Symbol();
 
   // Der Analyse-Block mit einem Wert von der Variable bs
 
   return(bs);
  }
//+----------------------------------------------------------------------------+

welche die oben ganzzahligen Werte zurückliefert. Am einfachsten kann diese Funktion in der Steurungseinheit der Positionen aufgerufen werden.
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
   double sl=0, tp=0;
   int    bs=GetTradeSignal();
 
   if(bs>0) 
     {
      if(ExistPositions("", OP_SELL)) 
          ClosePositions("", OP_SELL);
      if(!ExistPositions("", OP_BUY)) 
        {
          if(StopLoss!=0) 
              sl=Ask-StopLoss*Point;
          if(TakeProfit!=0) 
              tp=Ask+TakeProfit*Point;
          OpenPosition("", OP_BUY, sl, tp);
        }
     }
   if(bs<0) 
     {
       if(ExistPositions("", OP_BUY)) 
           ClosePositions("", OP_BUY);
       if(!ExistPositions("", OP_SELL)) 
         {
           if(StopLoss!=0) 
               sl=Bid+StopLoss*Point;
           if(TakeProfit!=0) 
               tp=Bid-TakeProfit*Point;
           OpenPosition("", OP_SELL, sl, tp);
         }
     }
  }
//+----------------------------------------------------------------------------+

In diesem Fall ist eine einzige lokale Variable bs mit dem Integer-Typ, wirkt wie ein Linker zwischen zwei Programmeinheiten. Der vollständige Text der Beispiel-Quellcode des EAs für den Swing-Trading einer Position kann man in der Datei e-SampleSwing.mq4 finden.

Ein einfaches Handeln einer Position


Dieser Fall ist ein wenig schwieriger. Obwohl auf dem Markt in jedem Moment nur eine Position gibt, aber dessen Schließung ist nicht mit der Eröffnung einer anderen verbunden. Deshalb werden nach der erfolgreichen Steuerung der Positionen alle fünf Signale gebraucht: Kauf, Verkauf, Kauf schließen, Verkauf schließen, und nichts tun. Sie können mit dem folgenden Wert in einer Integer-Typ Variable übertragen werden:

     2 - Verkauf schließen;
     1 - Kaufen;
     0 - nichts tun;
   -1 - Verkaufen;
   -2 - Kauf schließen.

Die Steuerungseinheit der Positionen kann in einer Funktion geschrieben werden:
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=GetTradeSignal();
 
    if(ExistPositions()) 
      {
        if(bs==2) 
            ClosePositions("", OP_SELL);
        if(bs==-2) 
            ClosePositions("", OP_BUY);
      } 
    else 
      {
        if(bs==1) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(bs==-1) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+
Der vollständige Text des Beispiel-Quellcodes des EAs für ein einfaches Handeln mit einer Position finden Sie in der Datei e-SampleSimple.mq4.

Der Hauptnachteil der Übertragung eines Handelssignals in eine Variable ist das, dass man mehrere Signale nicht gleichzeitig übertragen kann (Nachteile eines seriellen Interfaces). Zum Beispiel, man kann nicht in beide Richtungen Positionen öffnen, oder eine vorhandene Position mit einer gleichzeitigen Schließung öffnen oder alle Positionen schließen. Teilweise kann dieser Nachteil durch Einteilung der Signale in zwei Variablen beseitigt werden.


Es gibt drei Möglichkeiten, dies zu tun:

  1. Öffnung in einer Variable, und Schließung in einer anderen. Sie können die Öffnung und Schließung kombinieren, das heißt, einen Swing-Trading zu organisieren, aber man kann nicht dabei in beide Richtungen öffnen oder gegenseitig eingerichtete Positionen schließen;
  2. Die Positionen kaufen (öffnen und schließen) in einer Variable, Positionen verkaufen (öffnen und schließen) in einer anderen. Sie können Positionen in beide Richtungen öffnen und alle Positionen  auf einmal schließen, aber man kann nicht gleichzeitig öffnen und schließen, zum Beispiel, Positionen kaufen und verkaufen, Sie können es dann nicht wieder öffnen;
  3. Die Öffnung eines Kaufs und die Schließung eines Verkaufs in einer Variable, und die Öffnung eines Verkaufs und die Schließung eines Kaufs in einer anderen Variable. Sie können auch in beide Richtungen öffnen und alle Positionen schließen, aber dann kann man nicht einen Swing-Trading organisieren.
Lassen Sie uns bitte versuchen, die zweite Variante zu realisieren, denn die Wiedereröffnung ist eher selten. Niemand will Geld beim Spread verlieren. Die zweite Variante kann nach verschiedenen Weisen realisiert werden.

     1. Zwei Funktionen liefern Werte in zwei lokalen Variablen zurück. Eine Funktion bildet Signale für den Kauf, die zweite - für den Verkauf.
//+----------------------------------------------------------------------------+
//|  Liefert das  Handelsignal für die Long-Positionen zurück:                           |
//|     1 - Kaufen                                                             |
//|     0 - nichts tun                                                  |
//|    -1 - Kauf schließen                                                   |
//|  Parameter:                                                                |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
int GetTradeSignalBuy(string sym="", int tf=0) 
  {
    int bs=0;
    if(sym=="") 
        sym=Symbol();
 
    // Der Analyse-Block mit einem Wert von der Variable bs
 
    return(bs);
  }
 
//+----------------------------------------------------------------------------+
//|  Liefert das Handelsignal für die Short-Positionen zurück:                          |
//|     1 - Verkaufen                                                           |
//|     0 - nichts tun                                                  |
//|    -1 - Verkauf schließen                                                   |
//|  Parameter:                                                                |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
int GetTradeSignalSell(string sym="", int tf=0) 
  {
    int bs=0;
    if(sym=="") 
        sym=Symbol();
 
    // Der Analyse-Block mit einem Wert von der Variable bs
 
    return(bs);
  }
 
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=GetTradeSignalBuy();
    int    ss=GetTradeSignalSell();
 
    if(ExistPositions()) 
      {
        if(bs<0) 
            ClosePositions("", OP_BUY);
        if(ss<0) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(bs>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ss>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+
Das ist eine einfache und bequeme Weise, ein Trading-Signal zu bilden und zu übertragen, aber das Signal-Modul ist auf zwei Funktionen geteilt, was wahrscheinlich ihre Funktionalität verlangsamen  wird.

     2. Zwei globalen Variablen bekommen ihre Werte in einer Funktion.

//+----------------------------------------------------------------------------+
BuySignal=0;
SellSignal=0;
 
//+----------------------------------------------------------------------------+
//|  Es bildet  Handelssignale.                                               |
//|  Parameter:                                                                |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
void FormTradeSignals(string sym="", int tf=0) 
  {
    if(sym=="") sym=Symbol();
 
    // Der Analyse-Block mit der Zuordnung der Werte für die Variablen BuySignal und SellSignal
  }
 
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
 
    FormTradeSignals();
    if(ExistPositions()) 
      {
        if(BuySignal<0) 
            ClosePositions("", OP_BUY);
        if(SellSignal<0) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(BuySignal>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(SellSignal>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

Es ist aus diesem Quelle-Code klar, dass die Realisierung mit globalen Variablen sich von dem ersten Verfahren nicht wesentlich unterscheidet. Der scheinbare Vorteil ist, dass  das Signal-Modul in einer Funktion ist.

     3. Zwei lokaler Variablen werden durch einen Link auf eine Funktion übergeben.

//+----------------------------------------------------------------------------+
//|  Liefert die Handelsignale zurück.                                              |
//|  Parameter:                                                                |
//|    bs  - das Handelsignal für den Kauf                                                |
//|    ss  - das Handelsignal für den Verkauf                                                 |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
void GetTradeSignals(int& bs, int& ss, string sym="", int tf=0) 
  {
    if(sym=="") 
        sym=Symbol();
 
    // Der Analyse-Block mit der Zuordnung der Werte für die Variablen bs und ss
  }
 
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=0, ss=0;
 
    GetTradeSignals(bs, ss);
    if(ExistPositions()) 
      {
        if(bs<0) 
            ClosePositions("", OP_BUY);
        if(ss<0) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(bs>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ss>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

     4. Ein Array aus zwei Elementen. Wenn es global ist, dann wird es innerhalb der Funktion initialisiert. Wenn es lokal ist, dann wird es über den Link übergeben. Es ist hier alles einfach. Statt zwei Variablen wird ein Array. Die globalen Variable wurden betrachtet und die lokalen Variable wurden bereits auch über den Link betrachtet. Nichts Neues.


Und schließlich können wir ein vollwertiges paralleles Interface für die Übertragung der Trading-Signale organisieren, die in vier Variablen aufgeteilt werden. Für die Steuerung der Positionen hat jedes Signal zwei Zustände: existiert oder nicht. Deshalb ist es bequemer, die Variablen logisch auszuwählen. Sie können Signale mit dem Übergeben durch vier Variable kombinieren, das kann man endlos machen. Hier ist ein Beispiel eines Codes für die Art mit einem Array von vier Elementen des logischen Typs.
//+----------------------------------------------------------------------------+
//|  Liefert die Handelsignale zurück.                                              |
//|  Parameter:                                                                |
//|    ms  - das Array von Signalen                                                   |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
void GetTradeSignals(bool& ms[], string sym="", int tf=0) 
  {
    if(sym=="") 
        sym=Symbol();
 
    // Der Analyse-Block mit der Erfüllung des ms Arrays:
    // ms[0]=True;   // Buy
    // ms[1]=True;   // Sell
    // ms[2]=True;   // Close Buy
    // ms[3]=True;   // Close Sell
  }
 
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    bool   ms[4]={False, False, False, False};
    double sl=0, tp=0;
 
    GetTradeSignals(ms);
    if(ExistPositions()) 
      {
        if(ms[2]) 
            ClosePositions("", OP_BUY);
        if(ms[3]) 
            ClosePositions("", OP_SELL);
      }
    if(!ExistPositions()) 
      {
        if(ms[0]) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ms[1]) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
//+----------------------------------------------------------------------------+

Die Realisierung mit lokalen Variablen, die unter einem Link auf eine Funktion übergeben werden, und mit globalen Variablen, die innerhalb einer Funktion initialisiert werden, sollte auch keine Probleme verursachen. Allerdings, die Initialisierung von vier lokalen Variablen durch Werte, die von vier verschiedenen Funktionen zurückgeliefert werden, macht wenig Sinn.

Die Unterstützung der Hauptposition


Wenn ein Signal kommt, wird eine Position eröffnet, die direkt die Hauptposition sein wird. Alle anderen Eingangs-Signale auf die Hauptposition werden ignoriert. Und auf weiteren Signalen, die mit der Hauptposition entsprechen, werden zusätzliche Positionen geöffnet. Bei der Schließung der Hauptposition werden alle zusätzlichen Positionen ebenfalls geschlossen.


Man kann die Übertragung der Handelssignale für eine solche Taktik sowohl durch eine Variable realisieren, als auch durch zwei oder vier Variablen. All das wurde bereits beschrieben. Die Schwierigkeit dabei wird die Bereitstellung der Verbindung sein: ein Signal - eine Position. Bei der Handelstaktik mit einer Position wurde das Problem einfach durch die Überprüfung der Funktion ExistPositions() auf einen Position-Existenz gelöst. Wenn es eine Position gibt, wird das Signal zum Eingang rein gelassen, falls es keine Position gibt - wird das Signal durchgeführt.

Also, die Lösungsarten:

  1. Die Bereitstellung einer Pause zwischen den Eingängen. Die einfachste Realisierung;
  2. Ein Bar - ein Eingang. Eine Vielzahl der ersten Art. Die Realisierung ist auch einfach;
  3. Die Nummerierung der Signale und die Eingabe der Arrays von Signalen und Orders-Tickets. Das ist die schwierigste Realisierung mit einer zweifelhaften Zuverlässigkeit.
Das ist das Beispiel eines Codes für das erste Verfahren.
//+----------------------------------------------------------------------------+
extern int PauseBetweenEntrys=3600;    // Die Pause zwischen Eingängen in Sekunden
 
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    bool   ms[4]={False, False, False, False};
    double sl=0, tp=0;
 
    GetTradeSignals(ms);
    if(ExistPositions()) 
      {
        if(ms[2]) 
            ClosePositions("", OP_BUY);
        if(ms[3]) 
            ClosePositions("", OP_SELL);
      }
    if(SecondsAfterOpenLastPos()>=PauseBetweenEntrys) 
      {
        if(ms[0]) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
        if(ms[1]) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
 
//+----------------------------------------------------------------------------+
//|  Liefert die Anzahl der Sekunden nach der Eröffnung der letzten Position zurück.            |
//|  Parameter:                                                                |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    op  - Die Operation                 (-1 - eine Position)                     |
//|    mn  - MagicNumber              (-1 - ein Magic)                       |
//+----------------------------------------------------------------------------+
datetime SecondsAfterOpenLastPos(string sym="", int op=-1, int mn=-1) 
  {
    datetime oot;
    int      i, k=OrdersTotal();
 
    if(sym=="") sym=Symbol();
        for(i=0; ik; i++) 
          {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
              {
                if(OrderSymbol()==sym) 
                  {
                    if(OrderType()==OP_BUY || OrderType()==OP_SELL) 
                      {
                        if(op0 || OrderType()==op) 
                          {
                            if(mn0 || OrderMagicNumber()==mn) 
                              {
                                if(ootOrderOpenTime()) 
                                    oot=OrderOpenTime();
                              }
                          }
                      }
                 }
             }
        }
      return(CurTime()-oot);
  }
//+----------------------------------------------------------------------------+

Der vollständige Text des Beispiel-Quellcodes des EAs für die Taktik mit der Unterstützung der Haupt-Position wird in der Datei e-SampleMain.mq4 sein.

Swing Trading mit Averaging


Wenn ein Eingangssignal kommt, wird eine Position eröffnet. Auf Basis aller weiteren Signale in Richtung der ersten Position werden neue zusätzliche Positionen geöffnet. Wenn ein Signal gegen die bestehenden Positionen kommt, werden alle Positionen geschlossen und eine Position wird in der Richtung des Signals geöffnet. Die Trading-Loop wird wiederholt.

Die Übertragung und Ausführung der Handelssignale für Swing-Trading auf einer Position wurden schon betrachtet. Lassen Sie uns bitte dieses Beispiel für die Realisierung der zusätzlichen Positionseröffnungen anwenden. Und zur Bereitstellung der Verbindung "ein Signal - eine Position", lassen Sie uns bitte die Beschränkung der Eingangsmöglichkeit durch eine Zeitdauer von einem Bar nutzen. Ein Bar - ein Eingang.
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    double sl=0, tp=0;
    int    bs=GetTradeSignal();
 
    if(bs>0) 
      {
        if(ExistPositions("", OP_SELL)) 
            ClosePositions("", OP_SELL);
        if(NumberOfBarLastPos()>0) 
          {
            if(StopLoss!=0) 
                sl=Ask-StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Ask+TakeProfit*Point;
            OpenPosition("", OP_BUY, sl, tp);
          }
      }
    if(bs<0) 
      {
        if(ExistPositions("", OP_BUY)) 
            ClosePositions("", OP_BUY);
        if(NumberOfBarLastPos()>0) 
          {
            if(StopLoss!=0) 
                sl=Bid+StopLoss*Point;
            if(TakeProfit!=0) 
                tp=Bid-TakeProfit*Point;
            OpenPosition("", OP_SELL, sl, tp);
          }
      }
  }
 
//+----------------------------------------------------------------------------+
//|  Liefert die Nummer des Bars nach der Eröffnung der letzten Position zurück oder -1.                  |
//|  Parameter:                                                                |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//|    op  - Die Operation                 (-1 - eine Position)                     |
//|    mn  - MagicNumber              (-1 - ein Magic)                       |
//+----------------------------------------------------------------------------+
int NumberOfBarLastPos(string sym="", int tf=0, int op=-1, int mn=-1) 
  {
    datetime oot;
    int      i, k=OrdersTotal();
 
    if(sym=="") 
        sym=Symbol();
    for(i=0; ik; i++) 
      {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
          {
            if(OrderSymbol()==sym) 
              {
                if(OrderType()==OP_BUY || OrderType()==OP_SELL) 
                  {
                    if(op0 || OrderType()==op) 
                      {
                        if(mn0 || OrderMagicNumber()==mn) 
                          {
                            if(ootOrderOpenTime()) oot=OrderOpenTime();
                          }
                      }
                  }
             }
         }
     }
   return(iBarShift(sym, tf, oot, True));
  }
//+----------------------------------------------------------------------------+

Der vollständige Text des Beispiel-Quellcodes des EAs für den Swing-Trading mit Averaging finden Sie in der Datei e-SampleSwingAdd.mq4.

Portfolio Taktik


Für jedes Trading-Signal wird eine Position geöffnet und es wird unabhängig von anderen unterstützt.


Auf den ersten Blick ist es die komplizierteste Ausführungsvariante der Handelssignale in Bezug auf die Software-Realisierung. Hier außer der Übertragung der Handelssignale, müssen Sie die Zugehörigkeit eines Signals zu jenem oder zu einem anderen Portfolio übertragen. Aber wenn man die Signale in Gruppen teilt, die ein Portfolio bilden, werden Sie sehen, dass jede einzelne Gruppe ein einfaches Handeln einer Position ist. Die Art ist, die Gruppen in einem Portfolio zu bilden, scheint klar: Es wird zu jeder Gruppe eine eindeutige Nummer zugeordnet und es muss in der Loop die Sortierung aller Gruppen durchgeführt werden. Hier ist ein Beispiel für vier Signalgruppen.
//+----------------------------------------------------------------------------+
//|  Liefert die Handelsignale zurück.                                              |
//|  Parameter:                                                                |
//|    ms  - das Array von Signalen                                                   |
//|    ns  - Die Nummer des Signals                                                     |
//|    sym - Der Name des Werkzeugs ("" - das aktuelle Symbol)                    |
//|    tf  - die Timeframe                ( 0 - die aktuelle Timeframe)                 |
//+----------------------------------------------------------------------------+
void GetTradeSignals(bool& ms[], int ns, string sym="", int tf=0) 
  {
    if (sym=="") sym=Symbol();
 
    // Switching der Signalgruppen von Operatoren switch oder if
    // Der Analyse-Block mit der Erfüllung des ms Arrays:
    // ms[0]=True;   // Buy
    // ms[1]=True;   // Sell
    // ms[2]=True;   // Close Buy
    // ms[3]=True;   // Close Sell
  }
 
//+----------------------------------------------------------------------------+
//|  Die Positionen steuern                                                      |
//+----------------------------------------------------------------------------+
void ManagePositions() 
  {
    bool   ms[4];
    double sl=0, tp=0;
    int    i;
 
    for(i=0; i4; i++) 
      {
        ArrayInitialize(ms, False);
        GetTradeSignals(ms, i);
        if(ExistPositions("", -1, MAGIC+i)) 
          {
            if(ms[2]) ClosePositions("", OP_BUY, MAGIC+i);
            if(ms[3]) ClosePositions("", OP_SELL, MAGIC+i);
          }
        if(!ExistPositions("", -1, MAGIC+i)) 
          {
            if(ms[0]) 
              {
                if(StopLoss!=0) 
                    sl=Ask-StopLoss*Point;
                if(TakeProfit!=0) 
                    tp=Ask+TakeProfit*Point;
                OpenPosition("", OP_BUY, sl, tp, MAGIC+i);
              }
            if(ms[1]) 
              {
                if(StopLoss!=0) 
                    sl=Bid+StopLoss*Point;
                if(TakeProfit!=0) 
                    tp=Bid-TakeProfit*Point;
                OpenPosition("", OP_SELL, sl, tp, MAGIC+i);
              }
          }
      }
  }
//+----------------------------------------------------------------------------+

Der vollständige Text des Beispiel-Quellcodes des EAs für die Portfolio Taktik wird in der Datei e-SampleCase.mq4 sein.

Die Handelssignale für die Order


Lassen Sie uns bitte die Liste der Handelssignale betrachten, die für die Arbeit mit den Pending Ordern nötig sind.

  1. Setzen Sie BuyLimit;
  2. Setzen Sie SellLimit;
  3. Setzen Sie BuyStop;
  4. Setzen Sie SellStop;
  5. Löschen Sie BuyLimit;
  6. Löschen Sie SellLimit;
  7. Löschen Sie BuyStop;
  8. Löschen Sie SellStop;
  9. Modifizieren Sie BuyLimit;
  10. Modifizieren Sie SellLimit;
  11. Modifizieren Sie BuyStop;
  12. Modifizieren Sie SellStop.
Sie können sich ganz einfach vorstellen, dass eine Notwendigkeit bei Pending Ordern entstehen kann, um vier und noch mehr Handelssignale gleichzeitig zu übertragen. Und was ist, wenn die EA-Logik, die Beschäftigung sowohl mit Positionen, als auch mit Orders erfordert?

Hier ist die vollständige präzisierte Liste aller Handelssignale.
  1. Öffnen Sie Buy;
  2. Öffnen Sie Sell;
  3. Setzen Sie BuyLimit;
  4. Setzen Sie SellLimit;
  5. Setzen Sie BuyStop;
  6. Setzen Sie SellStop;
  7. Schließen Sie Buy;
  8. Schließen Sie Sell;
  9. Löschen Sie BuyLimit;
  10. Löschen Sie SellLimit;
  11. Löschen Sie BuyStop;
  12. Löschen Sie SellStop;
  13. Modifizieren Sie BuyLimit;
  14. Modifizieren Sie SellLimit;
  15. Modifizieren Sie BuyStop;
  16. Modifizieren Sie SellStop.
Sechzehn Handelssignale! Zwei Bytes! Es gab noch eine Idee, Signale als binäre Zahl zu übertragen, aber in einer Zeile. Beispielsweise 00101 ..., in der die Position von null oder eins für ein bestimmtes Signal verantwortlich wäre. Aber es wäre viel kompliziert mit Unterzeilen für die Decodierung der Signale... Also, man sieht, dass die bequemste Lösung ein Array mit der Anzahl von Elementen ist, die mit der Anzahl von Signalen gleich ist. Außerdem für die bessere Bequemlichkeit der Aufrufe der Array-Elemente, können Indexs als Konstanten definiert werden. MQL4 enthält bereits OP_BUY, OP_SELL und so weiter. Man kann es leicht fertig machen:
#define OP_CLOSEBUY         6
#define OP_CLOSESELL        7
#define OP_DELETEBUYLIMIT   8
#define OP_DELETESELLLIMIT  9
#define OP_DELETEBUYSTOP   10
#define OP_DELETESELLSTOP  11
#define OP_MODIFYBUYLIMIT  12
#define OP_MODIFYSELLLIMIT 13
#define OP_MODIFYBUYSTOP   14
#define OP_MODIFYSELLSTOP  15
und die Array-Elemente aufrufen  ms [OP_BUY] oder ms [OP_MODIFYSELLLIMIT] statt ms [0] und ms [13]? Aber das ist schon die Geschmackssache. Ich halte für einen kurzen und einfachen Code, deshalb bevorzuge ich Zahlen.

Also, weiter. Offenbar sieht alles einfach und schön aus! Aber es fehlt noch die Setzung der Preise-Ebene für Orders, genauso wie Stop und Takeprofit für Positionen. Denn jedes Trading-Signal kann die Informationen über eine bestimmte Größe des Stopps und Takeprofits tragen und noch eine gesetzte Preis-Ebene des Orders. Also, was sollen wir tun? Wie können wir diese Information zusammen mit einem Trading-Signal übertragen? Ich biete die folgende Lösung an.

  1. Deklarieren ein zweidimensionales Array mit einer Anzahl von Zeilen, die mit der Anzahl von Signalen gleich ist, und noch drei Spalten;
  2. Die erste Spalte wird durch den Nullwert die Abwesenheit eines Signals signalisieren, und durch den Nicht-Nullwert wird den Existenz eines Signals für eine Position zeigen. Für Orders wird es die Preis-Ebene bedeuten, in der die Order gesetzt wird;
  3. Die zweite Spalte - Stoppe;
  4. Die dritte Spalte - Takeprofits.

Der vollständige Text des Beispiel-Quellcodes für das Handeln mit Orders finden Sie in der Datei e-SampleOrders.mq4.


Und wenn wir mehrere BuyLimit oder mehrere SellStop setzen müssen? Und dazu noch Positionen eröffnen? In diesem Fall werden wir so tun, wie es im Teil "Portfolio-Taktik" dieses Artikels beschrieben ist, das heißt, verwenden eine Portfolio-Taktik mit der Identifizierung der Positionen und der Orders durch Magick-Nummer.

Fazit


Es ist die Zeit, alles zusammenzufassen:

  1. Die Übertragung der Handelssignale durch eine Variable hat einige Nachteile eines seriellen Interfaces - dadurch kann nur ein Signal an einem Moment übertragen werden;
  2. Der Versuch, ein paralleles Interface zu organisieren, führt zu der größeren Anzahl von Variablen und erschwert deren Management, aber das ermöglicht gleichzeitig Dutzende von Signalen zu übertragen.

Also, die Verwendung einer oder anderen Methode für die Übertragung der Handelssignale muss mit der Zweckmäßigkeit bestimmt werden.