English Русский 中文 Español 日本語 Português
Visuelles Testen der Rentabilität von Indikatoren und Benachrichtigungen

Visuelles Testen der Rentabilität von Indikatoren und Benachrichtigungen

MetaTrader 4Beispiele | 28 März 2016, 09:48
483 0
Sergey Kravchuk
Sergey Kravchuk

Welchen Indikator für Handelsbenachrichtigungen oder nur die Methoden zu ihrer Berechnung man verwendet, wird in der Regel beim Testen von EAs mit diesen Handelsbenachrichtigungen entschieden Es ist allerdings nicht immer möglich/erforderlich/sinnvoll einen EA für jeden Indikator zu schreiben. Sie können die Rentabilität des Trading auf die Handelsbenachrichtigungen von anderen Indikatoren sofort berechnen, unter Verwendung eines speziellen Indikators, der deren Handelsbenachrichtigungen sammelt und ein Bild des idealen Trading ihnen zeichnet. Er kann Ihnen sowohl dabei helfen eine visuelle Einschätzung der zu erzielenden Ergebnisse zu machen, als auch dabei schnell die optimalsten Parameter zu wählen.

Erinnern Sie sich daran, wie viele Male Sie nach einem zufällig gefundenen Indikator gesucht haben, oder ein lange gesuchter und endlich gefundener Indikator, und sie wollten sofort wissen wie die Handelsergebnisse mit seinen Handelsbenachrichtigungen sein würde. Die gleiche Situation tritt auf, wenn Ihnen ein neues Handelssystem angeboten wird, für das es noch keine EAs oder Indikatoren gibt. Bevor Sie anfangen ernsthaft damit zu arbeiten und einen funktionierenden EA schreiben, möchten Sie einschätzen, ob denn ein gesundes Korn in den angebotenen Materialien steckt.

Oder Sie haben die folgende Situation: Es gibt einen Indikator mit guten Handelsbenachrichtigungen, aber Sie haben das Gefühl, dass seine Parameter nicht optimal sind und Sie ihn aufräumen sollten, und Sie wissen auch wie Sie das können. Wie können Sie Ihre Idee schnell und ohne lange an das komplizierte Schreiben von Code gebunden zu sein testen?



Problemstellung

Denken wir nach was wir haben und was wir haben wollen. Nehmen wir den bekannten ZigZag aus der Standard-Auslieferung von MetaTrader 4 als Beispiel. Hängen Sie ihm an irgendein Währungspaar-Chart auf irgendeinem Zeitrahmen: Wolle Sie wirklich mit ihm handeln? Alles ist soweit klar: Sie sollten verkaufen auf dem oberen Knick und Ihre Position schließen und kaufen an dem unteren.

Hier ist jetzt die Frage: Wie viel Geld würde dieser Trade für Sie verdienen? Es ist ziemlich einfach eine Antwort auf diese Frage zu erhalten. Summieren Sie alle Hochs der Segmente und berechnen Sie neu unter Berücksichtigung des Volumens der Position in Lots und dem Kurs von einem Punkt in der Kontowährung. Sie können auf den Puffer der ZigZag Werte zugreifen durch Aufruf der Funktion iCustom:

P=iCustom(NULL,0,"ZigZag",0,i);

wobei i die Nummer des Balkens ist, für den Sie einen Wert erhalten wollen.

Alles was Sie tun müssen, ist alle Werte des Puffers zu durchsuchen und alle Punkte mit nicht-Null Werten zu finden - dies sind die Punkte um den ZigZag aufzubauen. Nun, Sie müssen außerdem alle Hochs der Segmente summieren. Aus beschreibenden gründen können sie sogar diese Linie Zeichnen und entsprechend der Trades und ihrer Rentabilität farbig machen. Diese Aufgabe ist ziemlich einfach und kann erfolgreich einem Indikator zugewiesen werden.



Eine Universelle Lösung

Damit ein solcher Indikator in der Lage ist jeden anderen Indikator zu testen, müssen Sie sicherstellen, dass er universell ist. Da jeder Indikator oder jedes Handelssystem, in einem allgemeinen Fall, annimmt, das nur 4 Operationen ausgeführt werden: BUY, SELL, BUY CLOSE, und SELL CLOSE, sollten wir ein spezielles Array für jeden von ihnen haben. Es muss möglich sein das Array aus jeder Quelle zu füllen. Es ist die einzige Sache, die Sie selber bearbeiten müssen, durch Hinzufügen des Codes zum Füllen des Allert Arrays (nun, Sie sollten wahrscheinlich auch ein paar Parameter in externen Variablen platzieren).

Funktionalität, der Indikator besteht aus den folgenden Blöcken:

  • Initialisierung - hier reservieren wir den Speicher für Alert Arrays und setzen die Zähler zurück,
  • Füllen der Alert Arrays - hier bearbeiten wir den Code durch Hinzufügen verschiedener Algorithmen zur Berechnung von Alerts oder für deren Empfang von anderen Indikatoren,
  • Räumung wiederholter Alerts - dieser Block ist notwendig zum "Ausdünnen" der Alert von Indikatoren die nicht in einem diskreten Modus der einen Alert generiert funktionieren, sondern in einem kontinuierlichen, in dem der Indikator fortlaufend die Verfügbarkeit von Eröffnungsbedingungen anbringt, nicht die erste Erscheinung des Alerts, bei dem, tatsächlich, die Order geöffnet werden muss. in dem Block ist der folgende Mechanismus umgesetzt: wenn zwei identische Alerts in benachbarten Balken erkannt werden, ruht der rechte, da wir nur eine Order zur Verwendung berücksichtigen, die bereits auf dem vorherigen (linken) Balken geöffnet wurde. Alle Alerts außerhalb des in den Parametern angegebenen Datumsbereichs werden hier auch entfernt.
  • Platzieren ÖFFNEN und SCHLIESSEN Markierungen - in diesem Block wird der ZigZag durch die "ausgedünnten" (diskreten) Alerts gezeichnet, vertikale Linbien werden platziert, wenn erforderlich, zur Verfolgung der Synchronisierung von Alerts mit dem Chart von anderen Indikatoren, eingeschlossen der den Alert erzeugende,
  • Berechnen der Ergebnisse durch die platzierte Markierung - die Menge geöffneter Ordern und deren Gewinne werden berechnet, in der Folge der platzierten Markierungen. Dieser Block macht einige zusätzliche Berechnungen und zeigt deren Ergebnisse als Kommentar in dem Haupt-Chartfenster,
  • Hilfsfunktionen - zwei Funktionen befinden sich hier: die zum Platzieren von vertikalen Markierungslinien und die zum Zeichnen von ZigZag


Umsetzung

Im Folgenden ist der Code des Indikator selbst, der ein Beispiel der Einspeisung der Daten von dem Indikator ZigZag enthält..

/*///———————————————————————————————————————————————————————————————————————————————————————————————————————
 
    IndicatorTester.mq4 
  
    Visual Testing the Profitability of Indicators and Alerts
    
    Copyright © 2006, Кравчук Сергей,  http://forextools.com.ua
 
/*///———————————————————————————————————————————————————————————————————————————————————————————————————————
#property copyright "Copyright © 2006-2008, Sergey Kravchuk. http://forextools.com.ua"
#property link      "http://forextools.com.ua"
 
#property indicator_chart_window
#property indicator_buffers 0
 
// parameters for displaying the elements of the chart
extern bool   ShowZZ          = true;           // should the ZZ be drawn?
extern bool   ShowMARKERS     = true;           // should the vertical marking lines be drawn?
 
//dates of drawing the chart
extern datetime DateStart     = D'1.01.1970';
extern datetime DateEnd       = D'31.12.2037';
 
//parameters of profit calculations
extern double LotForCalc      = 0.05;           // the amount of lots for profit calculations
extern int    Optimizm        = 0;              // -1 gives a pessimistic calculation; 0 gives the calculation on bar opening prices;  
                                                //+1 is optimistic
 
// BUY lines colors
extern color  ColorProfitBuy  = Blue;           // line color for profitable BUY trades
extern color  ColorLossBuy    = Red;            // line color for losing BUY trades
extern color  ColorZeroBuy    = Gray;           // line color for BUY trades with zero profits
 
// SELL lines colors
extern color  ColorProfitSell = Blue;           // line color for profitable SELL trades
extern color  ColorLossSell   = Red;            // line color for losing SELL trades
extern color  ColorZeroSell   = Gray;           // line color for SELL trades with zero profits
 
// alert lines colors
extern color  ColorBuy        = CornflowerBlue; // line color for BUY alerts
extern color  ColorSell       = HotPink;        // line color for SELL alerts
extern color  ColorClose      = Gainsboro;      // line color for closing alerts
 
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
double sBuy[],sCloseBuy[],sSell[],sCloseSell[]; // arrays for alerts
int sBuyCnt,sSellCnt,sBuyCloseCnt,sSellCloseCnt;// alerts counters 
int i,DisplayBars;
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// service codes
#define MrakerPrefix "IT_"
#define OP_CLOSE_BUY  444
#define OP_CLOSE_SELL 555
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
int init()   { ClearMarkers(); return(0); }
int deinit() { ClearMarkers(); return(0); }
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
int start() 
{ 
  double Profit=0,P1,P2; int CntProfit=0,CntLoose=0,i1,i2;
 
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // delete all marks, in case the indicator is going to be redrawn
  ClearMarkers(); 
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // prepare alerts counters
  sBuyCnt=0; sSellCnt=0; sBuyCloseCnt=0; sSellCloseCnt=0; 
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // allocate some memory for alerts arrays and zeroize their valuesя
  DisplayBars=Bars; // the amount of bars to be displayed
  ArrayResize(sBuy,DisplayBars);  ArrayInitialize(sBuy,0);
  ArrayResize(sSell,DisplayBars); ArrayInitialize(sSell,0);
  ArrayResize(sCloseBuy,DisplayBars);  ArrayInitialize(sCloseBuy,0);
  ArrayResize(sCloseSell,DisplayBars); ArrayInitialize(sCloseSell,0);
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // find the first point and save its location and price
  for(i1=Bars-1;i1>=0;i1--) { P1=iCustom(NULL,0,"ZigZag",0,i1); if(P1!=0) break; }
  // process the ZigZag points
  for(i2=i1-1;i2>=0;i2--) 
  {
    // find the next point and save its location and price
    for(i2=i2;i2>=0;i2--) { P2=iCustom(NULL,0,"ZigZag",0,i2); if(P2!=0) break; }
    
    if(i2<0) break; // place the last point on the current price 
 
    // the opening conditions are at the same time the conditions of closing an opposite order
    if(P1>P2) { sSell[i1]=1; sBuy[i2]=1; sCloseSell[i2]=1; }
    if(P1<P2) { sBuy[i1]=1; sSell[i2]=1; sCloseBuy[i2]=1; }
 
    P1=P2; i1=i2; // save the bar in which the point has been found
  }
    //——————————————————————————————————————————————————————————————————————————————————————————————————————
  // delete the repeated alerts having saved only the very first ones located to the left on the chart
  for(i=0;i<DisplayBars;i++) 
  {
    if(sBuy[i]==sBuy[i+1]) sBuy[i]=0;
    if(sSell[i]==sSell[i+1]) sSell[i]=0;
    if(sCloseBuy[i]==sCloseBuy[i+1]) sCloseBuy[i]=0;
    if(sCloseSell[i]==sCloseSell[i+1]) sCloseSell[i]=0;
  }
  // delete the alerts outside the specified range of dates
  for(i=0;i<DisplayBars;i++) 
  {
    if(Time[i]<DateStart || DateEnd<Time[i]) { sBuy[i]=0; sSell[i]=0; sCloseBuy[i]=0; sCloseSell[i]=0; }
  }
  // add forcible closing marginal positions
  if(DateEnd<=Time[0]) { i=iBarShift(Symbol(),Period(),DateEnd); sBuy[i]=0; sSell[i]=0; 
                                                             sCloseBuy[i]=1; sCloseSell[i]=1; }
  if(DateEnd >Time[0]) { sCloseBuy[0]=1; sCloseSell[0]=1; }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // count the amount of alerts

  for(i=0;i<DisplayBars;i++) 
  {
    if(sBuy [i]!=0) sBuyCnt++;  if(sCloseBuy [i]!=0) sBuyCloseCnt++;
    if(sSell[i]!=0) sSellCnt++; if(sCloseSell[i]!=0) sSellCloseCnt++;
  }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // place the marks, draw a ZZ and calculate the profits
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // process BUY trades
  for(i=DisplayBars-1;i>=0;i--) // go and collect the points
  {
    // find the next OPEN point and save its location and price
    for(i1=i;i1>=0;i1--) if(sBuy[i1]!=0) break; 
 
    // find the next CLOSE point of a BUY trade and save its location and price
    for(i2=i1-1;i2>=0;i2--) if(sCloseBuy[i2]!=0) break;
    if(i2<0) i2=0; // for the last unclosed position, calculate the CLOSE on the current price
    i=i2; // new bar to continue searching for OPEN points
 
    // define the prices for drawing according to the parameter of optimism, Optimizm
    if(Optimizm<0)  { P1=High[i1]; P2=Low[i2];  } 
    if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } 
    if(Optimizm>0)  { P1=Low[i1];  P2=High[i2]; } 
    
    P1/=Point; P2/=Point; // express prices in points
    
    // find the profit and fill out the corresponding buffer
    if(i1>=0) 
    { 
      Profit=Profit+P2-P1; // collect the summed profit
      if(P2-P1>=0) CntProfit++; else CntLoose++; // count the number of orders
      DrawLine(i1,i2,OP_BUY,Optimizm); // draw the order line
      PlaceMarker(i1,OP_BUY); 
      PlaceMarker(i2,OP_CLOSE_BUY); 
    }
  }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // process the SELL trades
  for(i=DisplayBars-1;i>=0;i--) // go and collect the points
  {
    // find the next OPEN point and save its location and price
    for(i1=i;i1>=0;i1--) if(sSell[i1]!=0) break; 
 
    // find the next CLOSE point of a SELL trade and save its location and price
    for(i2=i1-1;i2>=0;i2--) if(sCloseSell[i2]!=0) break;
    if(i2<0) i2=0; // for the last unclosed position, calculate the CLOSE on the current price
    i=i2; // new bar to continue searching for OPEN points
 
    // define the prices for drawing according to the parameter of optimism, Optimizm
    if(Optimizm<0)  { P1=Low[i1];  P2=High[i2]; } 
    if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } 
    if(Optimizm>0)  { P1=High[i1]; P2=Low[i2];  } 
    
    P1/=Point; P2/=Point; // express prices in points
    
    // if there are both points available, find the profit and fill the corresponding buffer
    if(i1>=0) 
    { 
      Profit=Profit+P1-P2; // collect the summed profit
      if(P1-P2>=0) CntProfit++; else CntLoose++; // count the number of orders
      DrawLine(i1,i2,OP_SELL,Optimizm); // draw the order line
      PlaceMarker(i1,OP_SELL); 
      PlaceMarker(i2,OP_CLOSE_SELL);
    }
  }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // calculating the totals for commenting  
  int Cnt=CntProfit+CntLoose; // total number of operations
  // coefficient to transfer points into the deposit currency
  double ToCurrency = MarketInfo(Symbol(),MODE_TICKVALUE)*LotForCalc;    
  string msg="Период: "+TimeToStr(MathMax(DateStart,Time[Bars-1]))+" - "
                                                      + TimeToStr(MathMin(DateEnd,Time[0]))+"\n\n";
  
  msg=msg+
  sBuyCnt+" BUY trades and "+sBuyCloseCnt+" their closings\n"+
  sSellCnt+" SELL trades and "+sSellCloseCnt+" their closings\n\n";
  
  // total time in days
  int TotalDays = (MathMin(DateEnd,Time[0])-MathMax(DateStart,Time[Bars-1]))/60/60/24; 
                                                                       //translate seconds into days
  if(TotalDays<=0) TotalDays=1; // to avoid zero divide for shorter days
  
  if(Cnt==0) msg=msg+("No operations");
  else msg=msg+
  (
    DoubleToStr(Profit,0)+" point on "+Cnt+" operations for "+TotalDays+" days\n"+
    DoubleToStr(Profit/Cnt,1)+" point for operation ("+
    DoubleToStr(Profit/TotalDays,1)+" within a day)\n\n"+
    "When trading with "+DoubleToStr(LotForCalc,2)+" obtain in "+AccountCurrency()+":\n"+
    DoubleToStr(Profit*ToCurrency,0)+" totally, by "+
    DoubleToStr(Profit/Cnt*ToCurrency,1)+" per trade ("+
    DoubleToStr(Profit/TotalDays*ToCurrency,1)+" within one day)\n\n"+
    CntProfit+" profitable ("+DoubleToStr(((CntProfit)*1.0/Cnt*1.0)*100.0,1)+"%)\n"+
    CntLoose+" losing ("+DoubleToStr(((CntLoose)*1.0/Cnt*1.0)*100.0,1)+"%)"
  );
  Comment(msg);
  
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
 
 
 
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// deleting all objects from our chart
void ClearMarkers() 
{ 
  for(int i=0;i<ObjectsTotal();i++) 
  if(StringFind(ObjectName(i),MrakerPrefix)==0) { ObjectDelete(ObjectName(i)); i--; } 
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// placing a vertical line - marks of the operation of the op_type type
void PlaceMarker(int i, int op_type)
{
  if(!ShowMARKERS) return; // displaying markers disabled
 
  color MarkerColor; string MarkName; 
 
  // __ for the CLOSE line to be drawn below the OPEN line at sorting 
  if(op_type==OP_CLOSE_SELL) { MarkerColor=ColorClose; MarkName=MrakerPrefix+"__SELL_"+i; }
  if(op_type==OP_CLOSE_BUY)  { MarkerColor=ColorClose; MarkName=MrakerPrefix+"__BUY_"+i;  }  
  if(op_type==OP_SELL)       { MarkerColor=ColorSell;  MarkName=MrakerPrefix+"_SELL_"+i;  }
  if(op_type==OP_BUY)        { MarkerColor=ColorBuy;   MarkName=MrakerPrefix+"_BUY_"+i;   }
 
  ObjectCreate(MarkName,OBJ_VLINE,0,Time[i],0); 
  ObjectSet(MarkName,OBJPROP_WIDTH,1); 
  if(op_type==OP_CLOSE_BUY || op_type==OP_CLOSE_SELL) ObjectSet(MarkName,OBJPROP_STYLE,STYLE_SOLID); 
  else ObjectSet(MarkName,OBJPROP_STYLE,STYLE_DOT);
  ObjectSet(MarkName,OBJPROP_BACK,True);  
 
  ObjectSet(MarkName,OBJPROP_COLOR,MarkerColor);
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// placing a line on the chart for the operation of the op_type type at the prices of parameter Optimizm
void DrawLine(int i1,int i2, int op_type, int Optimizm)
{
  if(!ShowZZ) return; // ZZ displaying disabled
  
  color СurColor;
  string MarkName=MrakerPrefix+"_"+i1+"_"+i2;
  double P1,P2;
  
  // define prices for drawing, according to parameter Optimizm
  if(Optimizm<0 && op_type==OP_BUY)  { P1=High[i1]; P2=Low[i2];  } 
  if(Optimizm<0 && op_type==OP_SELL) { P1=Low[i1];  P2=High[i2]; } 
  if(Optimizm==0)                    { P1=Open[i1]; P2=Open[i2]; } 
  if(Optimizm>0 && op_type==OP_BUY)  { P1=Low[i1];  P2=High[i2]; } 
  if(Optimizm>0 && op_type==OP_SELL) { P1=High[i1]; P2=Low[i2];  } 
 
  ObjectCreate(MarkName,OBJ_TREND,0,Time[i1],P1,Time[i2],P2);
  
  ObjectSet(MarkName,OBJPROP_RAY,False); // draw segments, not lines
  ObjectSet(MarkName,OBJPROP_BACK,False);
  ObjectSet(MarkName,OBJPROP_STYLE,STYLE_SOLID);
  ObjectSet(MarkName,OBJPROP_WIDTH,2);
 
  // set line color depending on the profitability of the trade
  if(op_type==OP_BUY) 
  { 
    if(P1 <P2) СurColor = ColorProfitBuy;
    if(P1==P2) СurColor = ColorZeroBuy;
    if(P1 >P2) СurColor = ColorLossBuy;
  }
  if(op_type==OP_SELL) 
  { 
    if(P1 >P2) СurColor = ColorProfitSell;
    if(P1==P2) СurColor = ColorZeroSell;
    if(P1 <P2) СurColor = ColorLossSell;
  }
  ObjectSet(MarkName,OBJPROP_COLOR,СurColor);
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
Die Parameter des Indikators enthalten einen speziellen Parameter, Optimizm. Er bestimmt den gewünschten Grad an Optimierung in Berechnungen. Ist sein Wert unter Null, bedeutet das die Berechnungen werden völlig pessimistisch sein: Für BUY Kurse wird das Hoch des Alert-Balken wählen, für SEL Kurse - Tief. Auf diese Weise werden die schlechtesten möglichen Ergebnisse modelliert, die wie durch diese Alerts erhalten können. Ist der Wert über Null, wird die optimistischste Berechnung modelliert: Kaufen am tiefsten und Verkaufen am höchsten. Wenn der Wert dieses Parameters gleich null ist, wird das neutrale Verhalten gebildet, bei dem wir Ordern zum Öffnungskurs von Balken öffnen und schließen - es ist die Situation, die in der Regel beim Handel mit EAs umgesetzt wird.

Ergebnisse Analysieren

Sehen wir uns die Ergebnisse an. Hier ist das Ergebnis der objektiven Analyse von ZigZag.

Sehen Sie, das Chart zeigt acht verlierende Teile. Nun, der ZigZag "funktioniert" am besten auf Kurse, und um es nochmal zu rekonstruieren, sollten wir den Parameter Optimizm = 1 setzen.

Was das Ergebnis sein wird, wenn wir so schlecht wie möglich Traden, sehe wir wenn der Parameter Optimizm = -1


Eine kleine Abschweifung

Geschätzte Trader,

Geben Sie mir nicht die Schuld, aber dieser Indikator kann eine hübsche Peitsche für Sie sein, wenn er in die geschickten Hände Ihres Management gelangt, das in der Regel nicht an Einzelheiten von Handelstaktiken interessiert ist - sie sind nur an dem Ergebnis interessiert. Hochgeladen in einen Tester, der Algorithmus von ZigZag Alerts und die Einstellung Optimizm = 1, werden Sie Zahlen mit dem maximalen Profit, der jemals auf diesem Teil des Charts erzielt hätte werden können, und den Sie erzielen möchten. Wenn Sie immer weniger als die Hälfte erzielen, wird es sie nachdenklich machen, dass Sie vielleicht zu gleichgültig an Ihr Pflichten herangehen.

Andererseits kann dieses Tool eine gute Verteidigung vor unfairen steilen Forderungen sein. Sie werden begründete Argumente haben, dass die für Sie gesetzten Ziele unrealistisch sind und nicht erreicht werden können, sogar mit den günstigsten Konditionen nicht.

Wir sehen, die Verwendung des einzelnen Optimizm Parameter ermöglicht den Indikator für eine potentielle Einschätzung eines in ihm getesteten Indikators mit Alerts. Uns selbst die optimistischste Berechnung macht keinen Gewinn, der getestete Indikator der Alerts sollte geändert werden: sie sollten andere Parameter für ihn ermitteln oder, im schlimmsten Fall, vergessen Sie es wegen der Hoffnungslosigkeit und sparen Sie die Zeit für die EA Entwicklung und Geld für Ihre Einlage, das verloren gehen könnte, um den Beweis zu erhalten, dass der Indikator nicht funktioniert. Somit spart unser Test-Indikator nicht nur Zeit, sondern auch Geld.



Alerts von Handelssystemen Analysieren

Puffer von anderen Indikatoren sind nicht nur Quelle zum Ausfüllen der Alert Arrays, auf denen unser Test-Indikator arbeitet. Irgendwo in Büchern oder in den Tiefen des Internets finden Sie eine Beschreibung von Alerts eines Handelssystems, für die es keine Indikatoren oder Expert Advisors gibt. Dies ist nur ein Satz Regeln, die durchaus mit MQL4 umgesetzt werden können. Wenn Sie die Berechnung von Alerts für ein solches System schreiben können und Alert Puffer durch sie Ausfüllen, wird der Test-Indikator ihnen die Ergebnisse zeigen, die Sie mit dem System erzielen können.

Wenn es einen fertigen Code für ein System gibt, können Sie Berechnung für Alerts wählen, auf denen der EA operiert, und konstruieren "Ergebnisse seiner Operationen" direkt auf dem Chart. Natürlich kann das gleiche, sogar genauer, in MetaTrader 4 Strategietester erreicht werden, aber der Indikator wird Rekonstruktionen schneller durchführen und sie anschaulicher reflektieren, als die strengen Linien eins Testers.

Ein wichtiger Moment ist in diesem Fall die Möglichkeit das Chart mit den erzielten Ergebnissen mit anderen Indikatoren zu verbinden. Vertikale Linien die zusätzliche Indikatoren kreuzen erzählen Ihnen vielleicht wie sie für die Festlegung von wichtigen Alerts verwendet werden, oder Sie erkennen Stellen seiner unzureichenden Funktion. Letztendlich können wir solche Parameter nur durch Hit-and-Miss Methode solche Parameter mit den Werten auswählen, die wahrscheinlich mehr als die Ergebnisse von Optimierern zu uns passen würden.

Nehmen wir als Beispiel den fertigen Code des Standard MACD. So sollte es aussehen. Block zum Füllen von Alert Arrays, die Inhalte, die kopiert und eingefügt wurden aus dem Indikator-Text:

  // fill out alert arrays with values and count them
  for(i=DisplayBars;i>=0;i--) 
  {
    double MacdCurrent, MacdPrevious, SignalCurrent;
    double SignalPrevious, MaCurrent, MaPrevious;
  
    // to simplify the coding and speed up access
    // data are put into internal variables
    MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+0);
    MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+1);
    SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+0);
    SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+1);
    MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+0);
    MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+1);
    
    // check for long position (BUY) possibility
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious) sBuy[i]=1;
       
    // check for short position (SELL) possibility
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent<MaPrevious) sSell[i]=1;
       
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseBuy[i]=1;
 
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&  MacdPrevious<SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseSell[i]=1;
  }

Und hier ist das Ergebnis:

Beachten Sie, dass die Linien der Alert-Markierungen vollständig mit den Schnittpunkten von MACD Charts übereinstimmen. Vielleicht entscheiden Sie beim Betrachten dieses Charts, was genau in Alerts geändert werden soll. Zum Beispiel, dass MaCurrent und MaPrevious keine Prüfung benötigen. Ein weinig korrigierter Code::

  // fill out alert arrays with values and count them
  for(i=DisplayBars;i>=0;i--) 
  {
    double MacdCurrent, MacdPrevious, SignalCurrent;
    double SignalPrevious, MaCurrent, MaPrevious;
  
    // to simplify the coding and speed up access
    // data are put into internal variables
    MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+0);
    MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+1);
    SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+0);
    SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+1);
    MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+0);
    MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+1);
    
    // check for long position (BUY) possibility
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point)) sBuy[i]=1;
       
    // check for short position (SELL) possibility
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point)) sSell[i]=1;
       
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseBuy[i]=1;
 
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&  MacdPrevious<SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseSell[i]=1;
  }

Sie sehen was das Ergebnis ist. Die Anzahl der Operationen hat sich von 19 auf 51 erhöht. Obwohl der Gesamtgewinn in den Verlust gedreht hat, was zeigt, dass dies keine gute Idee zum Verbessern der Alert-Qualität war.



Test-Fantasien

Jeder Entwickler hat sich aufdrängende Gedanken, die nie behandelt werden. Der Tester für Indikatoren hilft sie schnell zu visualisieren und einzuschätzen. Wenn Ideen anfangen konkreter zu werden und die erzielten Ergebnisse positiv sind, kann ein Entwickler darüber nachdenken einen Indikator oder Expert Advisor zu schreiben. In diesem Fall werden die Ergebnisse des Indikator Tester gleichzeitig eine Illustration für die Anforderungsspezifikationen zur Entwicklung sein, und ein abschließendes Beispiel, nach dem das fertige Produkt überprüft wird.

Hier ist ein primitives "System" als Beispiel: Kaufen mit Simple MA Indikator. Kauf-Bedingung - MA wächst, Verkauf-Bedingung - MA fällt. Sehen Sie wie schnell die Rentabilität dieser Ide geprüft wird. Hier ist der Block zum Alert Ausfüllen:

  // fill out alert arrays with values and count them
  for(i=DisplayBars;i>=0;i--) 
  {
    double m1=iMA(NULL,0,MAPeriod,0,MAMode,MAPrice,i+1);
    double m2=iMA(NULL,0,MAPeriod,0,MAMode,MAPrice,i+2);
    
    // open conditions are at the same time close conditions of an opposite order
    if(m2<=m1 && MathAbs(m1-m2)>0.2*Point) { sBuy[i]=1; sCloseSell[i]=1; sBuyCnt++; sSellCloseCnt++; }
    if(m2>=m1 && MathAbs(m1-m2)>0.2*Point) { sSell[i]=1; sCloseBuy[i]=1; sSellCnt++; sBuyCloseCnt++; }
  }

Und hier sind Ergebnisse:

Nicht schlecht, aber nicht das beste Ergebnis - weil wir uns unglaubliche Gewinne eingebildet haben. Versuchen wir nun die MA Periode zu verringern, um die Möglichkeit von Gewinnen auf rentablen Trades zu erhöhen. Verringern der Periode von 15 auf 7 Balken, wir haben es geschafft den durchschnittlichen täglichen Gewinn fast um das Doppelte zu erhöhen:

Was bleibt ist das Herstellen der Korrelation von rentablen und verlierenden Trades gleich zu mindesten 80% zu 20%. Aber das müssen Sie ohne meine Hilfe machen.



Fazit

Jetzt haben Sie ein weiteres Werkzeug zur Express-Analyse von Indikatoren und Trading Alerts oder Handelsbenachrichtigungen. Natürlich ersetzen sie nicht den Tester für reales Trading. Alle mit dem Werkzeug erzielten Daten sind von beschreibendem, schätzendem Charakter. Jedoch lassen die komfortable Bedienung, Visualisierung und die Geschwindigkeit der erzielten Ergebnisse mich daran glauben, dass dieses Tool für jeden Entwickler nützlich sein kann. Es hilft schnell Handelsideen zu prüfen, verschwendet dabei nicht viel Zeit und Mühe. Zu einem gewissen Grad kann es ein Beweis sein, ob eine Idee vielversprechend oder hoffnungslos ist. Und einem denkenden Ermittler oder Experimentalist kann dies ein Werkzeug der empfindlichen Optimierung der Indikator-Parameter sein.

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

Beigefügte Dateien |
Faulheit ist der Reiz zum Fortschritt. Halbautomatische Markierung einer Vorlage Faulheit ist der Reiz zum Fortschritt. Halbautomatische Markierung einer Vorlage
Unter den Dutzenden von Beispielen wie man mit Chart arbeitet, gibt es eine Methode der manuellen Markierung einer Vorlage. Trendlinien, Kanäle, Unterstützung/Widerstandsebenen, usw. werden einem Chart auferlegt. Sicher, es gibt einige spezielle Programme für diese Art von Arbeit. Jeder entscheidet für sich selbst, welche Methode er/sie verwendet. In diesem Artikel biete ich Ihnen für Ihre Betrachtung die Methoden der manuellen Markierung mit nachfolgendem Automatisieren einiger Elemente wiederholter Routine-Aktionen.
Interaktion zwischen MetaTrader 4 und Matlab über DDE Interaktion zwischen MetaTrader 4 und Matlab über DDE
Schritt-für-Schritt Anleitung wie man den Datentransfer von Matlab zu MetaTrader 4 mit DDE organisiert.
Ansicht der Technischen AAnalyse im Rahmen von Automatischen Steuerungssystemen (ACS), oder "Umgekehrte Ansicht" Ansicht der Technischen AAnalyse im Rahmen von Automatischen Steuerungssystemen (ACS), oder "Umgekehrte Ansicht"
Der Artikel demonstriert eine alternative Ansicht der technischen Analyse, die sowohl auf den Grundsätzen der modernen automatischen Steuerungstheorie, als auch auf der technischen Analyse selbst basiert. Es ist ein einführender Artikel, der die Theorie mit einigen praktischen Beispielen von ihr darstellt.
Zweistufige Modifizierung von Offenen Positionen Zweistufige Modifizierung von Offenen Positionen
Der zweistufige Ansatz ermöglicht Ihnen das unnötige Schließen und Neu-Öffnen von Positionen, in Situationen nah am Trend und in Fällen des Auftretens von Divergenz zu vermeiden.