Universelle Expert Advisor Vorlage

Вадим Андреевич | 24 Februar, 2016

Einführung

Viele Trader stehen vor dem Problem ihren eigenen Expert Advisor zu schreiben. Was kommt als erstes? Wie setzt man in einem EA Code Take Profit, Stop-Loss oder Trailing-Stop ein? Wie prüft man die Funktionalität einer Strategie? In diesem Artikel werden wir bei den wichtigsten Funktionen zum Erstellen eines Expert Advisor. Vielleicht wird jemand den nachlaufenden Code nützlich finden.

Expert Advisor Variablen

Also, welche Variablen sind in jedem Expert Advisor notwendig? Was muss getan werden, damit ein Tester die Parameter durchläuft, festgelegt durch bool Variablen? Erstens, ich zeige einen allgemeinen EA-Code, der auf allen Währungspaaren arbeitet. Für eine bessere Geschwindigkeit wird empfohlen, diese nach Ihrem eigenen Währungstyp anzupassen. Zweitens, 0-deaktiviert, 1-aktiviert (weil wir wollen, dass alle Parameter in einem Optimierer überprüft werden. Wenn ein endgültiger Code selten optimiert, wird empfohlen, diesen Parameter zu ändern). Drittens, Variablen der Ebenen (Stops) werden durch Ganzzahlen (integer) initialisiert, und in einem Code, falls erforderlich, in Bruchzahlen geändert. Da wir im wirklichen Leben mit verschiedenen Währungen handeln, ist hier die Vorlage! Viertens, wenn die Stop Parameter gleich Null sind, funktioniert der Stop nicht.

Variablen definieren

Beginnen wir mit dem Definieren der Variablen. Fangen wir mit denen an, die zur Optimierung geeignet sind - externe Variablen.

extern double MaxLot;
extern double TakeProfit;
extern double TrailingStop;
extern double StopLoss;
extern double MinProfit;
extern double ProfitPoints;
extern int    Slippage=0;
extern int Condition1=1;
extern double LotSpliter=1.0;
extern int CloseByOtherSideCondition;

Die Variable MaxLot bestimmt die maximale Lot-Größe, wenn wir den maximal verwendeten Lots begrenzen wollen (die Anzahl wird auch durch einen Server beschränkt, aber dies werden wir später besprechen).
TakeProfit, StopLoss und TrailingStop arbeiten in unserem Code, wenn sie größer als Null sind.
MinProfit und ProfitPoints arbeiten, wenn ProfitPoints höher als Null sind, nach dem Grundsatz: ein Kurs erreicht ProfitPoints und dreht zurück bis MinProfit.
ConditionX aktiviert die Einstiegsbedingungen.
LotSpliter ist ein Splitter für Lots. Sie verwendet nur einen Teil der verfügbaren Lots, zum Beispiel enthält 0.1 nut Lots, die 10 Mal kleiner sind, als der verfügbare Anteil der gesamten Einlage.
CloseByOtherSideCondition schließt eine Order, wenn eine gegenteilige Bedingung erscheint.

Bestimmen wir die internen Variablen, die zusammen mit der EA-Beschreibung besprochen werden.

double Lot;
double PP=0;
double slu,sld,a,b;
double tp,sl;

Initialisierungscode

Sehen wir und nun an, was nur beim Starten eines Expert Advisors berechnet und weiter im Code verwendet werden kann.

int init()
  {
   tp=TakeProfit;
   sl=StopLoss;
   return(0);
  }

Wir nehmen die Werte dieser Variablen für den Fall der Änderung der Stop-Ebenen. Wir können auch ein Lot berechnen, wenn wir die gesamte Zeit mit dem gleichen Volumen handeln wollen, und den Überschuss anzeigen (später im Artikel wird die Lot-Berechnung analysiert). Wir können außerdem einen darstellbaren Kommentar erstellen, der eine EA-Beschreibung oder das Copyright enthält. Es wird auf die folgende Weise durchgeführt:

Comment("cloud trade \n v2.0.11");

"\n" - means shift to the next display line, "carriage return".


Rahmen-Code

Sehen wir uns enen Code an, wenn es keine Ordern gibt:

if(OrdersTotal()==0)
   {   
      preinit();
      if(U()==1)
      {
         OrderBuy();
         return(0);
      }
      if(U()==2)
      {
         OrderSell();
         return(0);
      }
      return(0);
   }

Ein Teil dieser Funktionen wird später analysiert werden. Hier ist das Prinzip: initialisieren der Parameter, prüfen, ob eine Einstiegsbedingung existier, Einstieg durch eine Bedingung.

Sehen wir uns den Code an, wenn es eine Order gibt:

if(OrderType()==OP_BUY)
        {
         if((slu)>PP)
           {
            PP=slu;
           }
         if(((slu)>0.001) && (OrderStopLoss()<(b-TrailingStop))
          && (OrderOpenPrice()<(b-TrailingStop))
           && (OrderProfit()>MathAbs(OrderSwap())))
           {
            if(TrailingStop!=0)
              {
               OrderModify(OrderTicket(), 0, b-TrailingStop, 0, 0, 0);
              }
           }
        }
      if(OrderType()==OP_SELL)
        {
         if((sld)>PP)
           {
            PP=sld;
           }
         if(((sld)>0.001) && (OrderStopLoss()>(a+TrailingStop))
          && (OrderOpenPrice()>(a+TrailingStop)))
           {
            if(TrailingStop!=0)
              {
               OrderModify(OrderTicket(), 0, a+TrailingStop, 0, 0, 0);
              }
           }
        }
      if(ProfitPoints!=0)
        {
         if(OrderType()==OP_BUY && PP>=ProfitPoints && (slu)<=MinProfit)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
         if(OrderType()==OP_SELL && PP>=ProfitPoints && (sld)<=MinProfit)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
        }
      if(CloseByOtherSideCondition==1)
        {
         if(OrderType()==OP_BUY && U()==2)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
         if(OrderType()==OP_SELL && U()==1)
           {
            CloseOnlyOrder(OrderTicket());
            return(0);
           }
        }

Zuerst wählen wir nur eine Order für weitere Aktionen auf ihr (dieser Code wird in einem separaten Teil des Artikels analysiert). Dann weisen wir Variablen den Kursen zu, damit wir keine Order ändern, zum Beispiel bei einem Trailing-Stop in die falsche Richtung oder bei unrentablen neuen Kursen. Zuerst prüfen wir eine Order auf die Wahrscheinlichkeit eines Trailing-Stop, und gleichzeitig sammeln wir Daten für die nächste Funktion - minProfit, deren Verwendung weiter oben beschrieben wurde. Dann geht die Funktion zum Schließen einer Order bei Erscheinen einer gegenteiligen Bedingung und öffnet eine Order in die entgegengesetzte Richtung.

Im Artikel Analysierte Funktionen

Jetzt wollen wir die Funktionen ansehen, die zum Verkürzen des Codes gedacht sind und in Blöcke der am häufigsten verwendeten Befehle eingearbeitet sind, so dass später die vollen Blöcke aufgerufen werden können. Versuchen wir solche Bedingungen festzulegen und sie zu prüfen:

//+------------------------------------------------------------------+
//|  returns a signal to buy or to sell                              |
//+------------------------------------------------------------------+
int U()
  {
      if((U1()==2 && Condition1==1)
       || (U2()==2 && Condition2==1)){return(2);}
      if((U1()==1 && Condition1==1)
       || (U2()==1 && Condition2==1)){return(1);}
   return(0);
  }
//+------------------------------------------------------------------+
//|  returns a signal based on stochastic values                     |
//+------------------------------------------------------------------+
int U1()
  {
   if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_SIGNAL,1)>=80)
     {
      if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,2)
           <=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_MAIN,2))
        {
         if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,1)
           >=iStochastic(Symbol(),Period(),
              Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,1))
           {
            return(2);
           }
        }
     }
   if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,1)<=20)
     {
      if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_SIGNAL,2)
           >=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,2))
        {
         if(iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing, Method,PriceUsing,MODE_SIGNAL,1)
              <=iStochastic(Symbol(),Period(),Kperiod,Dperiod,Slowing,Method,PriceUsing,MODE_MAIN,1))
           {
            return(1);
           }
        }
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| find trend direction using fractals                              |
//+------------------------------------------------------------------+
int U2()
  {
   double fu=0,fd=0;
   int f=0,shift=2;
   while(f<2)
     {
      if(iFractals(Symbol(),Period(),MODE_UPPER,shift)>0)
        {
         fu=fu+1;
         f=f+1;
        }
      if(iFractals(Symbol(),Period(),MODE_LOWER,shift)>0)
        {
         fd=fd+1;
         f=f+1;
        }
      shift=shift+1;
     }
   if(fu==2){return(2);}
   if(fd==2){return(1);}
   return(0);
  }

Die erste Funktion prüft Bedingungen, die nächsten zwei bestimmen Bedingungen.

Nun sehen wir uns die Funktion an, die Stop-Ebenen berechnet, wenn diese falsch bestimmt sind, und einen Lot-Wert definiert:

//+------------------------------------------------------------------+
//| preliminary initialization of variables                          |
//+------------------------------------------------------------------+
int preinit()
  {
   Lot=NormalizeDouble(MathFloor(LotSpliter*AccountBalance()*AccountLeverage()
      /Ask/MathPow(10,Digits+1)*10)/10,1);
   if(MaxLot>0 && Lot>MaxLot){Lot=MaxLot;}
   if(Lot>MarketInfo(Symbol(),MODE_MAXLOT)){Lot=MarketInfo(Symbol(),MODE_MAXLOT);}
   PP=0;
   StopLoss=sl;
   TakeProfit=tp;
   if(TakeProfit!=0 && TakeProfit<(MarketInfo(Symbol(),MODE_STOPLEVEL)))
     {
      TakeProfit=MarketInfo(Symbol(),MODE_STOPLEVEL);
     }
   if(StopLoss!=0 && StopLoss<(MarketInfo(Symbol(),MODE_STOPLEVEL)))
     {
      StopLoss=MarketInfo(Symbol(),MODE_STOPLEVEL);
     }
   return(0);
  }

Jetzt eingestellte Funktionen öffnen Ordern in Abhängigkeit von den vorgegebenen Stop-Ebenen:

//+------------------------------------------------------------------+
//| returns true in case of a successful opening of Buy              |
//+------------------------------------------------------------------+
bool OrderBuy()
  {
   bool res=false;
   if(StopLoss!=0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage,
       NormalizeDouble(Ask-StopLoss,4),
        NormalizeDouble(Ask+TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage, 0,
       NormalizeDouble(Ask+TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask,
       Slippage, 0, 0, 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss!=0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), 0, NormalizeDouble(Lot,1), Ask, Slippage,
       NormalizeDouble(Ask-StopLoss,4), 0, 0, 0, 0, 0);
      return(res);
     }
   return(res);
  }
//+------------------------------------------------------------------+
//|   returns true in case of a successful opening of Sell           |
//+------------------------------------------------------------------+
bool OrderSell()
  {
   bool res=false;
   if(StopLoss!=0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit!=0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss==0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   if(StopLoss!=0 && TakeProfit==0)
     {
      res=OrderSend(Symbol(), OP_SELL, NormalizeDouble(Lot,1), Bid, Slippage,
       NormalizeDouble(Bid+StopLoss,4),
        NormalizeDouble(Bid-TakeProfit,4), 0, 0, 0, 0);
      return(res);
     }
   return(res);
  }
Die nächste Funktion schließt eine Order mit einem angegebenen Ticket, Volumen und einem angegebenen Kurs:
//+-------------------------------------------------------------------------+
//|  returns true in case of a successful closing of an order with Ticket   |
//+-------------------------------------------------------------------------+
bool CloseOnlyOrder(int Ticket, double Lots ,double priceClose)
  {
   bool res=false;
   res=OrderClose(Ticket, Lots, priceClose, Slippage, 0);
   return(res);

Nun wollen wir uns die Funktion ansehen zur Auswahl einer Order über die Positionsnummer, für weitere Operationen auf diesen:

//+--------------------------------------------------------------------------------+
//| returns true in case of a successful choosing of an order in the position pos  |
//+--------------------------------------------------------------------------------+
bool SelectOnlyOrder(int pos)
  {
   bool res=false;
   res=OrderSelect(pos,SELECT_BY_POS,MODE_TRADES);
   return(res);
  }
//+------------------------------------------------------------------+

Einige Programmier-Empfehlungen

Erstens, legen Sie Optionen fest wie 0 und 1, statt true und false. Das wir Ihnen helfen Ihren Expert Advisor besser zu optimieren. Zweitens, vernachlässigen Sie nicht den Stopp-Loss, zum begrenzen möglicher Verluste, wenn der Markt sic in die Gegenrichtung der Bedingungen bewegt. Drittens, testen Sie Ihren Expert Advisor nicht ohne Stopp-Loss - es wird wahrscheinlich zu einem schnellen Verlust der Einlage führen. Viertens, verwenden Sie Funktionen und Blöcke, die helfen den Code verständlicher zu machen.

Fazit

Es ist einfach einen Expert Advisor zu erstellen. Und um es noch einfacher zu machen, enthält die angehängte Datei den Expert Advisor, der in diesem Artikel analysiert wurde.