MetaTrader 5 herunterladen

Methode zur Fehlerbestimmung im Code durch Kommentieren

28 März 2016, 10:50
Eryomin Sergey
0
157

Einführung

Dieser Artikel beschreibt einen einfachen Algorithmus zur Suche nach Fehlern in einem MQL4 Code. Die Probleme während der Kompilierung, durch Fehler in dem Code, treten häufig erst nach dem Schreiben eines Programms auf. Dies können alle Arten von Fehlern sein, aber trotzdem ist es notwendig den Code-Block, mitdem der Fehler zusammenhängt, schnell zu erkennen.

Höchstwahrscheinlich verbringen viele Menschen eine Mege Zeit und Nerven mit der Suche nach einer fehlenden Klammer. Es gibt jedoch eine Methode für das schnelle Auffinden der Fehler, die auf der Verwendung von Kommentaren baesiert. So ist es diese Mehtode, über die ic in diesem Artikel sprechen werde.



Konzeption

Einen großen Code ohne Fehler zu schreiben ist ziemlich angenehme. Aber leider ist das nicht immer der Fall. Es gibt sogar einen Witz, dass noch nie ein Programm ohne Fehler geschrieben wurde.Ich berücksichtige hier nicht die Feehler, die zu einer falschen Ausführung des Codes führen. Hier ist die Frage nach den Fehlern, die das Kompilieren unmöglich machen.

Die weitest verbreiteten Fehler sind: Einfügen ein unpassenden Klammer in einer komplexen Bedingung, Fehlen einer Klammer, nicht gesetzter Doppelpunkt, ein Komma (während der Deklaration von Variablen), usw. Häufig sehen wir welcher Eintrag den Fehler während der Kompilierung enthält sofort. Es gibt aber Fälle, in denen das Ermitteln von Fehlern dieser Art nicht so einfach ist. Weder der Compiler, noch einscharfes Auge kann uns helfen den Fehler sofort zu finden. In diesem Fall fängt, in der Regel, der lerndende (und nicht-) Programmierer an den gesamten Code durchzugehen, und versuchen den Fehler optisch zu erkennen. Wieder und wieder, bis die Nerven reißen und gesagt wird: "Es ist leichter es neu zu schreiben"!

Allerdings, MQL bietet, genau wie alle anderen Programmiersprachen, ein unglaubliches Werkzeug - Kommentieren. Sie können einige Teile des Codes mit seiner Verwendung "entfernen", "deaktivieren". In der Regel wird die Kommentierung im WOrtsinn verwendet, oder für die Deaktivierung von nicht genutzten Teilen des Codes. Die Kommentiereung kann außerdem erfolgreich für die Fehlersuche verwendet werden.



Algorithmus zur Fehlersuche

Die Suche nach fehlern führt in der Regel zu dem Teil des Codes, in dem der Fehler gemacht wurde, und wo dann optisch nach ihm gesucht wird. Ich denke, niemand wird daran zweifeln, dass es viel einfacher und schneller ist 5-10 Code-Einträge "mit dem Auge" zu untersuchen, als 100-150 Einträge.

Das Problem scheint sich einfach lösen zu lassen, wen Kommentieren verwendet wird. Zunächst ist es erforderlich einige unterschiedliche Teile des Codes (manchmal fast der ganze Code) zu kommentieren, um ihn zu "deaktivieren". Dann wird die Kommentierung von diesen Teilen des Codes wieder entfernt. Nach der normalen Beseitigung der Kommentierung, wird ein Versuch den Code zu Kompilieren durchgeführt. Ist die Kompilierung erfolgreich, ist der Fehler nicht in diesem Teil des Codes. Ist die Kompilierung erfolgreich, ist der Fehler nicht in diesem Teil des Codes. Danach wir der nächste Teil geöffnet, und so weiter. Ist der Problematische Teil mit dem Fehler gefunden, wird der Fehler optisch gesucht und behoben. Danach wid ein Versuch gemacht wieder eine Kompilierung durchzufühenren. Wenn alles erfolgreich durchläuft, ist der Fehler beseitigt.

für den Fall, dass neue Fehler auftreten, wird die Prozedur wieder holt bis diese beseitigt sind. Der Ansatz ist sehr nützlich, wenn große Porgamme geschrieben werden, und nicht selten funktioniert es beim Schreiben relativ kleiner Codes.

Es ist sehr wichtig den Block zum Komentieren richtig zu bestimmen. Wenn es eine Bedingung ist8 oder eine andere logische Konstruktion), dann sollte sie vollständig kommentiert werden. Wenn Sie einen Block kommentieren, in dem die Variablen deklariert sind, dann ist es wichtig keine Bläcke auszulassen in denen diese Variablen angezeigt werden. Dazu muss gersagt werden, dass die Kommentierung nach der Logik des Progrtammierens genutzt werden sollte. Das Handeln gegen diesen Grundsatz wird dazu führen, dass neue, desinformierende Fehler während der Kompilierung auftreten.



Beispiel

Ich werde die praktische Suche nach einem Fehler im Code veranschaulichen. Angenommen wir haben einen Code:

#property copyright ""
#property link      ""
 
extern int Level1=6;
extern int Level2=2;
 
extern double Lots=0.1;
extern int TP=7;
extern int SL=5000;
extern int Profit_stop=10;
 
int start()
  {
//+--------------------------------------------------------------------------------------------------+
//|                                        search for opened orders by symbol
   int pos_sell=0;
 for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
 { 
  if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL)
                                                                &&(OrderComment()=="sar_ao"))
  {
   pos_sell=1;  break;   
  } 
 }
    
   int pos_buy=0;
 for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
 { 
  if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY)
                                                                &&(OrderComment()=="sar_ao"))
  {
   pos_buy=1;  break;   
  } 
 }
     
//|                                        search for opened orders by symbol                       |
//+-------------------------------------------------------------------------------------------------+  
 
//+-------------------------------------------------------------------------------------------------+
//|                                                stop for break-even
  double stop_open; 
  for (int ia=OrdersTotal()-1; ia>=0; ia--) 
  { 
   if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; 
   if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(),
                                                                        OrderExpiration(),CLR_NONE);  
   } 
 if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(),
                                                                        OrderExpiration(),CLR_NONE);       
   } 
  }   
//|                                                stop for break-even                              |
//+-------------------------------------------------------------------------------------------------+ 
   int i;   
   bool trend_UP=true,trend_DOWN=true;   
//+-------------------------------------------------------------------------------   
if(!pos_buy)
 {  
  for(i=Level1; i>=0; i--)
   {
   
    if(Open[i]<iSAR(NULL,0,0.02,0.1,i))
    {
     trend_UP=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   {    
   
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_UP=false; break;
     }
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_UP=false; break;
     }
    }          
   
   } 
 }
 else
 {
  trend_UP=false; 
 }
//***************************************************************************
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }  
 
 
  if(Open[0]>iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("sell"); 
  }
  
  if(Open[0]<iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("buy"); 
  } 
   
double MA_1;
MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);  
   if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0)
   {   
     OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); 
      
     ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid);
     ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen);
   }
   
   if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) 
   {   
      OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red);   
      
      ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid);
      ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT);
      ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
      ObjectSet("sell", OBJPROP_COLOR, Red);  
   }
   
 
//+-------------------------------------------------------------------------------
//----
   return(0);
  }
//+------------------------------------------------------------------+

WIr sehen die folgende Fehlermeldung während der Kompilierung:


Es ist unmöglich den Block, in dem der Fehler gemacht wurde, schnell zu erkennen. Wir greifen zurück auf die Kommentierung. Kommentieren Sie alle logischen Konstruktionen:

#property copyright ""
#property link      ""
 
extern int Level1=6;
extern int Level2=2;
 
extern double Lots=0.1;
extern int TP=7;
extern int SL=5000;
extern int Profit_stop=10;
 
int start()
  {
  /*
//+-----------------------------------------------------------------------------------------------+
//|                                        search for opened orders by symbol                     |
   int pos_sell=0;
 for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
 { 
  if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL)
                                                                &&(OrderComment()=="sar_ao"))
  {
   pos_sell=1;  break;   
  } 
 }
    
   int pos_buy=0;
 for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
 { 
  if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY)
                                                                        &&(OrderComment()=="sar_ao"))
  {
   pos_buy=1;  break;   
  } 
 }
     
//|                                        search for opened orders by symbol                    |
//+----------------------------------------------------------------------------------------------+  
*/
 
/*
//+----------------------------------------------------------------------------------------------+
//|                                                stop for break-even                           |
  double stop_open; 
  for (int ia=OrdersTotal()-1; ia>=0; ia--) 
  { 
   if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; 
   if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(),
                                                                OrderExpiration(),CLR_NONE);  
   } 
 if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(),
                                                                OrderExpiration(),CLR_NONE);       
   } 
  }   
//|                                                stop for break-even                          |
//+---------------------------------------------------------------------------------------------+ 
*/
 
 
/*
   int i;   
   bool trend_UP=true,trend_DOWN=true;   
//+-------------------------------------------------------------------------------   
if(!pos_buy)
 {  
  for(i=Level1; i>=0; i--)
   {
   
    if(Open[i]<iSAR(NULL,0,0.02,0.1,i))
    {
     trend_UP=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   {    
   
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_UP=false; break;
     }
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_UP=false; break;
     }
    }          
   
   } 
 }
 else
 {
  trend_UP=false; 
 }
 */
//***************************************************************************
 
/*
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }  
 
 */
 
 /*
  if(Open[0]>iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("sell"); 
  }
  
  if(Open[0]<iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("buy"); 
  } 
  */ 
double MA_1;
MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); 
 
/* 
   if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0)
   {   
     OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); 
      
     ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid);
     ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen);
   }
  */
  
  /* 
   if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) 
   {   
      OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red);   
      
      ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid);
      ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT);
      ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
      ObjectSet("sell", OBJPROP_COLOR, Red);  
   }
   
*/
//+-------------------------------------------------------------------------------
//----
   return(0);
  }
//+------------------------------------------------------------------+

Sie können einfac sicherstellen, dass dieser Code ohne Probleme kompiliert werden kann. Das bedeutet, dass der Teil des Codes, in dem der Fehler gemacht wurde "versteckt" ist. Öffnen Sie Teile des Codes /* ... */ schrittweise und versuchen Sie ihn zu kompilieren.

Die Kompilierung wird erfolgreich sein, bis wir den folgenden Block des Codes erreichen:

//***************************************************************************
 
 
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }

Deshalb ist der Fehler eine logische Konstruktion. Wir können sehen, dass sich dort eine unangebrachte runde Klammer in der Konstruktion ist, während der der eingehenden Untersuchung von diesem Teil des Codes:

   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }

Wenn wir sie entfernen, wird der Code erfolgreich kompiliert.

Wir werden sicherstellen, dass es keine weiteren Fehler in dem Code gibt, indem wir die verbleibenden Kommentare entfernen. Das bedeutet, dass wir unser Ziel erreicht haben - der Fehler im Code wurde schnell erfolgreich gefunden.



Fazit

Es wurde an einem praktischen Beispiel gezeigt, wie dieser Algorithmus für die Fehlersuche verwendet wird. Es wurde kein kleiner Code (194 Einträge) in diesem Beispiel verwendet, also könnte seine "Untersuchung" viel Zeit in Anspruch nehmen. Die Möglichkeit der Kommentierung selbst spart ausreichend Zeit, für Programmierer, die auf das Problem der Fehlersuche stoßen.

Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/1547

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.

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.

Faulheit ist der Reiz zum Fortschritt, oder Wie man mit Grafiken Interaktiv Arbeitet Faulheit ist der Reiz zum Fortschritt, oder Wie man mit Grafiken Interaktiv Arbeitet

Ein Indikator für interaktive Arbeit mit Trendlinien, Fibo-Ebenen, Symbole manuell auf ein Chart gelegt. Er ermöglicht Ihnen die farbigen Zonen der Fibo-Ebenen zu zeichnen, zeigt die Momente in denen der Kurs die Trendlinie kreuzt, verwaltet das "Kurs Label" Objekt.

Wie man Schnelle Nicht-Nachzeichnende ZigZags Schreibt Wie man Schnelle Nicht-Nachzeichnende ZigZags Schreibt

Ein eher universeller Ansatz zum Schreiben von Indikatoren des ZigZag Typs wird vorgeschlagen. Die Methode beinhaltet einen wesentlichen Teil bereits beschriebener ZigZags und ermöglicht Ihnen relativ leicht neue zu erzeugen.