English Русский 中文 Español 日本語 Português
Wie man einen Zuverlässigen und Sicheren Handelsroboter in MQL4 entwickelt

Wie man einen Zuverlässigen und Sicheren Handelsroboter in MQL4 entwickelt

MetaTrader 4Handelssysteme | 28 Januar 2016, 14:59
1 310 0
Shashev Sergei
Shashev Sergei

Einführung

Bei dem Prozess der Erstellung ernsthaften Programmlösung steht der Entwickler vor der Tatsache, dass sein Programm alle möglichen und unmöglichen Fehler enthalten kann. Die Fehler verursachen viel Ärger in der Stufe der Entwicklung, führen zur Unzuverlässigkeit der Lösung und, wenn es ein Handelsroboter ist, können negative Ergebnisse bei Ihrer Einzahlung zeigen. Analysieren wir die häufigsten Fehler, ihre Herkunft und die Methoden zur Erfassung und Verarbeitung von Programmfehlern. Bei dem Prozess der Entwicklung und Verwendung eines Expert Advisors für das Client Terminal MetaTrader 4 können folgende Fehler auftreten:

  1. Syntax – sie können bei der Kompilierungsstufe gefunden und leicht durch einen Programmierer behoben werden,
  2. logische – sie werden nicht mit einem Compiler erkannt. Die Beispiele sind: ein Durcheinander mit den Namen von Variablen, die falschen Funktionsaufrufe, Verarbeiten von Daten verschiedener Typen, und so weiter,
  3. algorithmische – sie treten auf, wenn Klammern nicht richtig gesetzt sind, bei einem Durcheinander mit den Sprungbefehlen und so weiter,
  4. kritische –dies sind unwahrscheinliche Fehler, Sie müssen sich Mühe geben sie zu wecken. Trotzdem treten sie häufig auf, wenn Sie mit DLL arbeiten,
  5. Trading – das sind die Fehler, wenn Sie mit Ordern arbeiten. Diese Art von Fehlern ist eine empfindliche Stelle bei Handelsrobotern.

Zunächst empfehlen wir Ihnen die Dokumentation über Ausführungsfehler zu studieren. Wenn Sie diesen Vorgang einmal durchgeführt haben, können Sie später viel Zeit sparen. Die durch Handelsoperationen induzierten Fehler sind hier beschrieben.


Syntaxfehler

Die Fehler dieser Art werden durch Falscheingaben von Bedienern, Variablen oder unterschiedlichen Funktionsaufrufen hervorgerufen. Während der Kompilierung des Codes eines Programms wird geprüft, und alle Syntaxfehler werden im "Tools" Fenster des MetaEditor angezeigt. Tatsächlich werden fast alle Fehler entdeckt, und können durch den Programmierer behoben werden.

Die Ausnahme ist ein Durcheinander mit den Klammern, wenn die falsche offene/geschlossene Klammer bei der Kompilierungsstufe erkannt wird, aber die Platzierung des Fehlers falsch angezeigt wird. Dann müssen Sie den Code doppelt prüfen, um in der Lage zu sein den Fehler visuell zu finden. Es kann, leider, nicht erfolgreich sein. Der zweite Ansatz ist die schrittweise Abschaltung der Blöcke, der Code verwendenden Kommentare. In diesem Fall, wenn nach dem Kommentieren eines neuen Blocks ein Fehler erscheint, ist er offensichtlich im diesem kommentierten Block platziert. Es schränkt den Bereich der Suche drastisch ein und hilft die falsche Platzierung von Klammern schnell zu finden.


Logische, Algorithmische und Kritische Fehler

Die häufigsten Fehler dieser Art, sind das Durcheinander bei den Namen und Typen der Variablen und auch die algorithmischen Fehler in den Sprungbefehlen des Expert Advisors. Zum Beispiel, lassen Sie uns diesen Code untersuchen:

bool Some = false;
 
void check()
  {
    // Much code
    Some = true;
  }
// Very much code
int start()
  {
    bool Some = false;
    //
    if(Some)   
      {
        //sending the order
      }
   return(0);
  }

Was können wir jetzt sehen? Die logische Variable "Some", die gemeinsam für das gesamte Programm und ein wichtiger Indikator für das Öffnen der Position ist, wurde versehentlich niedriger gesetzt. Es kann zu falschem Eröffnen der Order Führen und, deshalb, zu Verlusten. Sie können viele Namen für die Variablen festlegen! Aber aus irgendeinem Grund wiederholen sich diese Namen in großen Programmen, und es führt zu den oben genannten Problemen.

Diese Art von Fehler tritt auf, wenn die Variablen vermischt sind oder der Ausdruck eines Typs dem Ausdruck eines anderen Typs zugewiesen ist. Zum Beispiel in dieser Zeile

int profit = NormalizeDouble(SomeValue*point*2 / 3, digit);

versuchen wir den Wertausdruck des "double" Typ der Variable des "int" Typ zuzuweisen, was in einem Null-Wert resultiert. Und wir berechnen das Take Profit Niveau! Diese Art von Fehler führt zu falschem Trading.

Der algorithmische Fehler in den Sprungbefehlen eines Expert Advisor bedeutet, dass die Klammern nicht entsprechend des Algorithmus platziert sind, oder die falsche Abdeckung von 'if' Operatoren durch die 'else' Operatoren auftritt. Als Ergebnis haben wir einen Expert Advisor, der nicht nach den technischen Anforderungen arbeitet.

Einige Fehler sind so schlecht wahrnehmbar, dass Sie Stunden damit verbringen "auf den Code zu meditieren", um sie zu finden. Leider gibt es keine Möglichkeit die Variablenwert im MetaEditor zu verfolgen, im Gegensatz zu den Umgebungen der C++ Familie. So ist die einzige Möglichkeit die Fehler zu verfolgen, die Ausgabe der Meldung durch die Print() Funktion.

Die Funktion GetLastError() gibt den Code des Fehlers zurück. Es wird empfohlen den letzten Wert nach jeder potentiell verwundbaren Stelle des Programm zu prüfen. Unter Verwendung des Fehlercodes können Sie seine Beschreibung einfach in der Dokumentation finden, und für einige Fehler finden sie auch Methoden der Behandlung.

Wir sollten sagen, dass die oben genannten Fehler höchstwahrscheinlich in der Phase des Testens, vor der Verwendung eines Demokontos, erkannt werden, so dass durch sie hervorgerufene Verluste unwahrscheinlich sind.

Das Hauptmerkmal der kritischen Fehler ist, dass, wenn sie auftreten, die Ausführung des Programms sofort beendet wird. Trotzdem bleibt der Code des Fehlers in der vordefinierten Variable "last error" unverändert. Mit der Funktion GetLastError() erhalten wir die Möglichkeit den Code des Fehlers zu erfahren.


Tradingfehler

Diese Fehler führen häufig zu Verlusten und fehlender Betriebsfähigkeit des Expert Advisor auf dem Demo-, und darüber hinaus, auf dem Live-Konto. Sie treten auf, wenn Sie mit dem Senden und Modifizieren von Ordern arbeiten, mit anderen Worten, während der Interaktion mit dem Trading-Server.

Die einfache Verarbeitung wie diese:

ticket = OrderSend(Symbol(), OP_SELL, LotsOptimized(), Bid, 3,
         Bid + StopLoss*Point, Bid - TakeProfit*Point, 0, MAGICMA, 
         0, Red);
if(ticket > 0) 
  {
    err = GetLastError();
    Print("While opening the order the error #  occured", err);
  }

wird nicht helfen. Wir haben darauf geachtet, dass die Order noch an den Server gesendet wurde und haben den Fehlercode erfahren. Was bedeutet das? Wir haben einen wichtigen Eintritt in den Markt verpasst, wenn wir einen gewinnbringenden Expert Advisor haben.

Die Variante mit der Endlosschleife:

while (true)
  {
    ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, slippage,
             Bid + StopLoss*Point, Bid - TakeProfit*Point, 0, 
             MAGICMA, 0, Red);
    if(ticket > 0) 
      {
        err = GetLastError();
        Print("While opening the order the error #  occured", err);
        break;      
      }
    Sleep(1000);
    RefleshRates();
  }

hilft ein wenig. Die Order wird wahrscheinlicher den Server erreichen. Aber wir können einigen Problemen gegenüber stehen:

  1. Der Broker mag keine häufigen Anfragen,
  2. Der Fehler kann tödlich sein, in diesem Fall wird die Anfrage den Server sowieso nicht erreichen,
  3. Der Expert Advisor wird über eine lange Zeit nicht reagieren,
  4. Der Server akzeptiert überhaupt keine Tradinganfragen - es kann ein Wochenende, Feiertag oder Serverwartung sein, und so weiter.

Fast jeder Fehler ist einzigartig und benötigt seine eigene Behandlung. Also lassen Sie uns über die Variante mit dem Switch-Operator sprechen und jeden Fehler mehr oder weniger einzeln betrachten. Der Standard-Fehler #146 - "Trade flow is busy" wird durch die in der TradeContext.mqh Bibliothek realisierten Semaphore verarbeitet. Sie finden die Bibliothek und ihre detaillierte Beschreibung in diesem Artikel.

//The library for differentiation of work with the trading flow
//written by komposter
#include <TradeContext.mqh>
 
//parameters for the signals
extern double MACDOpenLevel=3;
extern double MACDCloseLevel=2;
extern double MATrendPeriod=26;
 
// maximum acceptable slippage
int       slippage = 3;
//total number of transactions
int deals = 0;
//time for the pause after transaction
int TimeForSleep = 10;
//period of request
int time_for_action = 1;
//number of tries of opening/closing the position
int count = 5;
//indicator of operability of the EA
bool Trade = true;
//indicator of availability of funds for opening the position
bool NoOpen = false;
//+------------------------------------------------------------------+
//| Do not ask the server for quotes on weekends                    |
//+------------------------------------------------------------------+
bool ServerWork()
  {     
   if(DayOfWeek() == 0 || DayOfWeek() == 6)
       return(false);
   return(true);      
  }
//+------------------------------------------------------------------+
//| Generation of magik                                                  |
//+------------------------------------------------------------------+ 
int GenericMagik()
  {
   return(deals);
  }
//+------------------------------------------------------------------+   
//| Closing of transactions                                                  |
//+------------------------------------------------------------------+
bool CloseOrder(int magik)
  {
   int ticket,i;
   double Price_close;
   int err;
   int N;
//Function tries to shut the server at count attempts, if it fails,
//it gives an error message to the logfile
   while(N < count)
     {          
       for(i = OrdersTotal() - 1; i >= 0; i--) 
         {
           if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
               if(OrderSymbol() == Symbol()) 
                   if(OrderMagicNumber() == magik)
                     {
                       if(OrderType() == OP_BUY)        
                           Price_close = NormalizeDouble(Bid, Digits);
                       if(OrderType() == OP_SELL)        
                           Price_close = NormalizeDouble(Ask, Digits);
                       if(OrderClose(OrderTicket(), OrderLots(),
                          Price_close,slippage))
                         { 
                           //reduce the number of transactions for the EA
                           deals--;
                           //the piece of the margin became available - you can open again
                           NoOpen = false;                           
                           return(true);
                         }
                         //we have reached this place, it means that the order has not been sent
                       N++;
                       //processing of possible errors
                       err = ErrorBlock();
                       //if the error is seriuos
                       if(err > 1)
                         {
                           Print("Manual closing of the order #  needed",
                                 OrderTicket());
                           return(false);
                         }
                     }                                          
         }
        // taking a pause of 5 seconds and trying to close the transaction again
       Sleep(5000);
       RefreshRates();
     }
    //if we have reached this place, the transaction was not closed at count attempts 
   Print("Manual closing of the order #  needed",OrderTicket());
   return(false);
  }
//+------------------------------------------------------------------+
//|Tranaction for act 1-buy, 2-sell, the second parameter - the number of lots      |
//+------------------------------------------------------------------+ 
int Deal(int act, double Lot)
  {
   int N = 0;
   int ticket;
   int err;
   double Price_open;
   double Lots;
   int cmd;
   int magik;
   magik = GenericMagik();
   Lots = NormalizeDouble(Lot,1);
   if(act == 1)
     {
       Price_open = NormalizeDouble(Ask, Digits);
       cmd = OP_BUY;
     }
   if(act == 2)
     {
       Price_open = NormalizeDouble(Bid, Digits);
       cmd = OP_SELL;
     }
   //checking the margin for opening the position
   AccountFreeMarginCheck(Symbol(), cmd,Lots);
   err = GetLastError();
   if(err>0)
     {
       Print("No money for new position");
       NoOpen = true;
       return(0);
     }      
//Sending the order                  
   ticket = OrderSend(Symbol(), cmd, Lots, Price_open, slippage, 
                      0, 0, 0, magik);
   if(ticket > 0)
     {
       deals++;
       return(ticket);
     }
//If the order has not been sent, we will try to open it 5 times again      
   else
     {
       while(N < count)
         {
           N++;
           err = ErrorBlock();
           if(err == 1)
             {
               Sleep(5000);
               RefreshRates();
               if(act == 1)
                   Price_open = NormalizeDouble(Ask, Digits);
               if(act == 2)
                   Price_open = NormalizeDouble(Bid, Digits);              
               ticket = OrderSend(Symbol(), cmd, Lots, Price_open,
                                  slippage, 0, 0, 0, magik);
               if(ticket > 0)
                 {
                   deals++;
                   return(ticket);
                 }
             }
           // we have got a serious error  
           if(err > 1)            
               return(0);               
         }                                                       
     }    
   return(0);
  }
//+------------------------------------------------------------------+
//| // 0-no error, 1-need to wait and refresh, 2-transaction rejected,   |
//|    3-fatal error                                            |
//+------------------------------------------------------------------+
//Block of the error control 
int ErrorBlock()
  {
   int err = GetLastError();
   switch(err)
     {
       case 0: return(0);
       case 2:
         {
           Print("System failure. Reboot the computer/check the server");
           Trade = false;
           return(3);  
         }
       case 3:
         {
           Print("Error of the logic of the EA");
           Trade = false;
           return(3);   
         }
       case 4:
         {
           Print("Trading server is busy. Wait for 2 minutes.");
           Sleep(120000);
           return(2);   
         }
       case 6:
         { 
           bool connect = false;
           int iteration = 0;
           Print("Disconnect ");
           while((!connect) || (iteration > 60))
             {
               Sleep(10000);
               Print("Connection not restored", iteration*10,
                     "  seconds passed");
               connect = IsConnected();
               if(connect)
                 {
                   Print("Connection restored");
                   return(2);
                 }
               iteration++;
             }
           Trade = false; 
           Print("Connection problems");
           return(3);
         }
       case 8:
         {
           Print("Frequent requests");
           Trade = false; 
           return(3);
         }
       case 64:
         {
           Print("Account is blocked!");
           Trade = false; 
           return(3);            
         }
       case 65:
         {
           Print("Wrong account number???");
           Trade = false; 
           return(3);            
         }
       case 128:
         {
           Print("Waiting of transaction timed out");
           return(2);
         }
       case 129:
         {
           Print("Wrong price");
           return(1);            
         }
       case 130:
         {
           Print("Wrong stop");
           return(1);
         }
       case 131:
         {
           Print("Wrong calculation of trade volume");
           Trade = false;            
           return(3);
         }
       case 132:
         {
           Print("Market closed");
           Trade = false; 
           return(2);
         }
       case 134:
         {
           Print("Lack of margin for performing operation");
           Trade = false;             
           return(2);
         }
       case 135:
         {
           Print("Prices changed");
           return (1);
         }
       case 136:
         {
           Print("No price!");
           return(2);
         }
       case 138:
         {
           Print("Requote again!");
           return(1);
         }
       case 139:
         {
           Print("The order is in process. Program glitch");
           return(2);
         }
       case 141:
         {
           Print("Too many requests");
           Trade = false; 
           return(2);            
         }
       case 148:
         {
           Print("Transaction volume too large");
           Trade = false; 
           return(2);            
         }                                          
     }
   return (0);
  }
//+------------------------------------------------------------------+
//| generation of signals for opening/closing position on Macd       |
//+------------------------------------------------------------------+
int GetAction(int &action, double &lot, int &magik)
   {
   double MacdCurrent, MacdPrevious, SignalCurrent;
   double SignalPrevious, MaCurrent, MaPrevious;
   int cnt,total;
   
   MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
   MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
   SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
   SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
   MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
   MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
   
  if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
         MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
      {
         action=1;
         lot=1;
         return (0);
      }
  if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
         MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
      {
         action=2;
         lot=1;
         return (0);               
      }
   total=OrdersTotal();
   for(cnt=0;cnt<total;cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderType()<=OP_SELL &&   // check for opened position 
         OrderSymbol()==Symbol())  // check for symbol
        {
         if(OrderType()==OP_BUY)   // long position is opened
           {
            // should it be closed?
            if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
               MacdCurrent>(MACDCloseLevel*Point))
                {
                 action=3;
                 magik=OrderMagicNumber();
                 return(0); // exit
                }
           }
         else // go to short position
           {
            // should it be closed?
            if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&
               MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point))
              {
               action=3;
               magik=OrderMagicNumber();
               return(0); 
              }
           }
        }
     }
   }
//+------------------------------------------------------------------+
//| The EA initialization function                                   |
//+------------------------------------------------------------------+
int init()
  { 
    if(!IsTradeAllowed())
      {
        Print("Trade not allowed!");
        return(0);     
      }
  }
//+------------------------------------------------------------------+
//| The EA deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//Closing all orders
   for(int k = OrdersTotal() - 1; k >= 0 ; k--)
       if(OrderSymbol() == Symbol()) 
         {
           if(OrderType() == OP_BUY)
              OrderClose(OrderTicket(), OrderLots(), 
                         NormalizeDouble(Bid,Digits), 10);               
           if(OrderType() == OP_SELL)
               OrderClose(OrderTicket(), OrderLots(),
                          NormalizeDouble(Ask, Digits),10);                 
         }
  } 
//+------------------------------------------------------------------+
//| The EA start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   int action =0;
   double lot = 1;
   int magik = 0;     
   while(Trade)
     {
       Sleep(time_for_action*1000);      
       RefreshRates();
       /*Logic of the EA where the we calculate the action, position limit and magik for closing the order
       action 1-buy, 2-sell, 3-close
       for example, take the EA on Macd*/
       GetAction(action,lot,magik);
       if(ServerWork())
         {
           if(((action == 1) || (action == 2)) && (!NoOpen))
             {                                        
               if(TradeIsBusy() < 0) 
                   return(-1); 
               Deal(action, lot);
               Sleep(TimeForSleep*1000);                                
               TradeIsNotBusy();
             }
           if(action == 3)
             {
               if(TradeIsBusy() < 0) 
                 { 
                   return(-1); 
                   if(!CloseOrder(magik))
                       Print("MANUAL CLOSE OF TRANSATION NEEDED");
                   Sleep(TimeForSleep*1000);   
                   TradeIsNotBusy();
                 } 
             }
         }
       else
         {
            Print("Weekends");
            if(TradeIsBusy() < 0) 
                  return(-1); 
            Sleep(1000*3600*48);
            TradeIsNotBusy();
         }
       action = 0;
       lot = 0;
       magik = 0;
     }
   Print("Critical error occured and the work of the EA terminated");  
   return(0);
  }
//+------------------------------------------------------------------+

Diese Version des Handelsroboters arbeitet in einer Endlosschleife. Seine Erfordernis erfolgt, wenn der Mehrwährungs- Scalping Expert Advisor erstellt wird. Der Algorithmus der Arbeitsweise des EA ist der folgende:

  1. Das Signal von dem analytischen Block GetAction() erhalten,
  2. Die notwendige Transaktion in den Funktionen Deal() und CloseOrder() durchführen,
  3. Rückkher zu Punkt 1 nach einer kurzen Pause time_for_action, falls es dort keine schwerwiegenden Fehler gab.

Nach dem Erhalt des Signals (Buy, Sell, Schließen) von dem analysierenden Block, blockiert der Expert Advisor den Handelsfluss (lesen Sie den Artikel) und versucht die Transaktion durchzuführen, danach macht er eine Pause von wenigen Sekunden und gibt den Handelsfluss für andere EAs frei. Der EA versucht die Order nicht öfter als "Anzahl" Mal zu senden. Es sollte ausreichend sein um die Order an einem unsicheren Markt zu übergeben, an dem Sie Requotes erhalten können. Wenn beim Senden der Order ein schwerwiegender Fehler auftritt, stoppt der Expert Advisor seine Funktion. Wenn irgendwelche Probleme auftreten, erscheint eine Fehlermeldung in dem "Expert Advisors" Ordner. Der Expert Advisor wird weiterarbeiten, wenn der Fehler nicht kritisch ist.

Die Fehler werden in der ErrorBlock() Prozedur verarbeitet, nach dem folgenden Schema: die Prozedur erhält den Code des Fehlers und enthält einen kurzen Algorithmus diesen zu verarbeiten. Für die meisten Fehler ist es einfach eine Nachricht in der Protokolldatei. Wenn der Fehler schwerwiegend ist, tauschen die Indikatoren Trade und NoOpen. Wenn es ein Verbindungsfehler ist, ist die Verarbeitung der Situation ein wenig komplizierter. Der Roboter versucht den Server sechzig Mal mit der vordefinierten periodischen Folge zu erreichen. Wird der Server nicht erreicht, dann hat er sehr wahrscheinlich schwerwiegende Probleme und Sie sollten das Trading für einige Zeit aussetzen. Abhängig von dem Einfluss des Fehlers auf das Trading gibt der Verarbeitungsalgorithmus verschiedene Bedeutungen zurück:

  • 0 - kein Fehler,
  • 1 - der Fehler ist mit der Volatilität am Markt verbunden, Sie können versuchen die Order noch einmal zu senden,
  • 2 - ein schwerwiegender Fehler ist aufgetreten während diese Order gesendet wurde, stoppen Sie das Öffnen von Positionen für einige Zeit,
  • 3 - schwerwiegender Fehler des EA, Verbindungsfehler - stoppen Sie das Trading, bis die Umstände geklärt sind.


Fazit

Syntax, algorithmische und logische Fehler treten auf, wenn Sie dem Schreiben des Algorithmus nicht die ausreichende Aufmerksamkeit schenken. Diese Fehler werden durch das Prüfen und Verifizieren der Werte von Variablen in der Protokolldatei behoben. Sie können während der Stufe der Kompilierung und des Testen des Expert Advisor erkannt werden. Fehler dieser Art besehen nicht für lange Zeit, sie werden in der Regel vor der Verwendung eines Demokontos behoben.

Trading-Fehler treten beim Senden der Ordern an den Server auf. Sie sind mit dem echten Handel verbunden, wo Sie auf Requotes, Slippage, Kampf der Dealer mit Scalping und Gerätefehler treffen können. Solche Fehler können nicht vorausgesehen werden, aber sie können und sollten verarbeitet werden. Sie sollten sie einzeln pro Woche verarbeiten, abhängig von der Logik des Expert Advisor, der Häufigkeit der Transaktionen und Änderungen von Ordern.

Die Fehler, die während des Betriebs des Expert Advisor auftreten, müssen verarbeitet werden. Es ist keine einfache Aufgabe. Es hängt von der Komplexität des EA und seinen Eigenschaften ab. In dem Artikel finden Sie das exemplarische Muster des Expert Advisor, der diese Aufgabe erfüllt. Es benötigt viel Zeit, ein sichereres und zuverlässigeres Handelssystem zu erstellen. Aber die Zeit für die Entwicklung eines störungsfreien automatischen Handelssystems wird mehrfach belohnt, durch die Sicherheit Ihrer Einlagen und einen ruhigen Schlaf.

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

Beigefügte Dateien |
AntiError.mq4 (14.86 KB)
TradeContext.mqh (11.54 KB)
Übertragen eines Indikator Code in einen Expert Advisor Code. Abschluss Übertragen eines Indikator Code in einen Expert Advisor Code. Abschluss
Dies ist der abschließende Artikel über das Übertragen eines Indikator Code in einen Expert Advisor Code. Hier verändert der Autor in einem bestimmten Beispiel einen Code eines Expert Advisor so, dass dieser EA in einer einzigen Datei dargestellt wird, ohne den Aufruf benutzerdefinierter Indikatoren.
Ein Expert Advisor auf Bestellung gemacht. Handbuch für einen Trader Ein Expert Advisor auf Bestellung gemacht. Handbuch für einen Trader
Nicht alle Trader sind Programmierer. Und nicht alle Programmierer sind wirklich gut. Also, was sollte getan werden, wenn Sie Ihr System automatisieren müssen und keine Zeit und Lust haben MQL4 zu studieren?
Theoretische Grundlagen zum Aufbau von Cluster Indikatoren für Devisenhandel Theoretische Grundlagen zum Aufbau von Cluster Indikatoren für Devisenhandel
Cluster Indikatoren sind Indikatoren, die Währungspaare in einzelne Währungen aufteilen. Indikatoren ermöglichen das Verfolgen der relativen Währungsfluktuation, bestimmen das Potential der Bildung eines neuen Trends, erhalten Handelssignale und folgen mittelfristigen und langfristigen Positionen.
Terminal Service Client. Wie man einen Pocket PC zu Big Brothers Freund macht Terminal Service Client. Wie man einen Pocket PC zu Big Brothers Freund macht
Der Artikel beschreibt die Art und Weise der Verbindung eines Remote-PCs mit installiertem MT4-Client Terminal über einen PDA.