Problem: Crossing Bedingung funktioniert beim Livetrading nicht - obwohl in der Simulation alles sauber läuft

 

Hallo,


ich hoffe Ihr könnt mir weiterhelfen, denn ich habe ein seltsames Problem.Meine Idee ist, immer dann eine Buy Order zu eröffnen, wenn der ADX Wert größer als ein voreingestellter ADX Wert ist und weiterhin beim ADX der D+ Wert den D- Wert kreuzt. In der Simulation funktioniert dies einwandfrei, jedoch nicht im Livekonto. Ich erhalte noch nicht einmal eine Fehlermeldung. Interessant ist aber, wenn ich die Einstiegsbedingung umändere und zwar so, das D+ (die grüne Kurve) über der D- (rote) Kurve liegt, dann klappt die Buy Trade Order in Verbindung mit dem voreingestellten ADX Wert einwandfrei.

Wo liegt das Problem?

Ich poste mal meinen Quellcode:

   //+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

// Eingaben und Array- und Variablendefinitionen
   // Stop Loss
   input int      StopLoss=30;     
   // Take Profit
   input int      TakeProfit=20;  
   //  ADX Setting for Crossing between D+ and D-
   input int setADX = 10; 

   // für ADX-Wert
   double ArrayADX[];
   // für D+-Wert
   double ArrayDpl[];
   // für D- -Wert
   double ArrayDmi[]; 
  
   // To be used for Stop Loss & Take Profit values
   int SL, TP;  
  
    // handle for our ADX indicator
   int adx;
   
   

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Get handle for ADX indicator
   adx=iADX(Symbol(),_Period,14);
   
   //--- What if handle returns Invalid Handle
   if(adx<0)
     {
      Alert("Error Creating Handles for indicators - error: ",GetLastError(),"!!");
      return(-1);
     }
     
   //--- Let us handle currency pairs with 5 or 3 digit prices instead of 4
   SL = StopLoss;
   TP = TakeProfit;
   if(_Digits==5 || _Digits==3)
     {
      SL = SL*10;
      TP = TP*10;
     }
     
        return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
      //--- Release our indicator handles
   IndicatorRelease(adx);
  }
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- Do we have enough bars to work with
   if(Bars(_Symbol,_Period)<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }  
   
   // We will use the static Old_Time variable to serve the bar time.
   // At each OnTick execution we will check the current bar time with the saved one.
   // If the bar time isn't equal to the saved time, it indicates that we have a new tick.

   static datetime Old_Time;
   datetime New_Time[1];
   bool IsNewBar=false;

// copying the last bar time to the element New_Time[0]
   int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0) // ok, the data has been copied successfully
     {
      if(Old_Time!=New_Time[0]) // if old time isn't equal to new bar time
        {
         IsNewBar=true;   // if it isn't a first call, the new bar has appeared
         if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here ",New_Time[0]," old time was ",Old_Time);
         Old_Time=New_Time[0];            // saving bar time
        }
     }
   else
     {
      Alert("Error in copying historical times data, error =",GetLastError());
      ResetLastError();
      return;
     }

//--- EA should only check for new trade if we have a new bar
   if(IsNewBar==false)
     {
      return;
     }
 
//--- Do we have enough bars to work with
   int Mybars=Bars(_Symbol,_Period);
   if(Mybars<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }

//--- Define some MQL5 Structures we will use for our trade
   MqlTick latest_price;      // To be used for getting recent/latest price quotes
   MqlTradeRequest mrequest = {0};  // To be used for sending our trade requests
   MqlTradeResult mresult ={0};    // To be used to get our trade results
   // Initialization of mrequest structure
   ZeroMemory(mrequest);      
   
   //Anfang ADX-Handelsstrategie Umsetzung 
      
   // sortiere die Preise abwärts von der aktuellen Kerze
   ArraySetAsSeries(ArrayADX,true);  
   ArraySetAsSeries(ArrayDpl,true);
   ArraySetAsSeries(ArrayDmi,true);

   //--- Get the last price quote using the MQL5 MqlTick Structure
   if(!SymbolInfoTick(_Symbol,latest_price))
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }
   
   // Definierter EA, erste Indikatorlinie (ADX) = (erste 0) die 1 liefert den Wert für die zweite Indikatorlinie D+ usw., aktuelle Kerze (zweite Index 0), 3 Kerzen (Kopieren der Daten für 3 Kerzen), speichere Resultat in meinPreisArray  // Mit der Funktion Copybuffer füllen wir unser Preisarray aufgrund der ADX Definition
   CopyBuffer(adx,0,0,3,ArrayADX);   // ADX-Wert
   CopyBuffer(adx,1,0,3,ArrayDpl);         // Dplus
   CopyBuffer(adx,2,0,3,ArrayDmi);   // D-Minus
  
// Kann für die Anzeige der Indikatorwerte in Verbindung mit der comment Funktion verwendet werden 
   
   // Berechne den EA für für die aktuelle Kerze (ADX)
   double ADXWert=NormalizeDouble(ArrayADX[0],2);  // ADX
   double DplWert=NormalizeDouble(ArrayDpl[0],2);  // D+
   double DminWert=NormalizeDouble(ArrayDmi[0],2);  // D-

// Ende der ADX-Handelsstrategie Umsetzung 
   
   // Testkommentar
   //Comment ("The current ADX signal is: ",ADXWert);
   //Comment ("The current Dpl signal is: ",DplWert);
   //Comment ("The current Dmin signal is: ",DminWert);
    Comment ("The current Dpl is: ",DplWert);
   //--- Do we have positions opened already?
   bool Buy_opened=false;  // variable to hold the result of Buy opened position
   bool Sell_opened=false; // variables to hold the result of Sell opened position
   
   if(PositionSelect(_Symbol)==true) // we have an opened position
     {
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
        {
         Buy_opened=true;  //It is a Buy
        }
      else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
        {
         Sell_opened=true; // It is a Sell
        }
     } // Ende if PositionSelect

//   bool Buy_Condition_1 = (ArrayDpl[0] > ArrayDmi[0]); /*&& (ArrayDpl[1] < ArrayDmi[1]);  */     // +DI greater than -DI - für die aktuelle Kerze - Crossing
   
   if( (ADXWert>=setADX)  && ((ArrayDpl[0] > ArrayDmi[0]) && (ArrayDpl[1] < ArrayDmi[1])))   //Crossing condition is commented out
   {
    // any opened Buy position?
   if(Buy_opened)
   {
   Alert("We already have a Buy Position!!!");
   return;    // Don't open a new Buy Position
   } // Ende Buy_opened
           
   ZeroMemory(mrequest);
   mrequest.action = TRADE_ACTION_DEAL;                                                        // Typ der Transaktion
   mrequest.symbol =Symbol();                                                                             // Symbol
   mrequest.volume = 0.01;                                                                                     // Volumen von 0.1 Lot
   mrequest.type = ORDER_TYPE_BUY;                                                               // Ordertyp
   mrequest.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK);                             // Eröffnungspreis
   mrequest.deviation=5;                                                                                     // zulässige Abweichung vom Kurs
   mrequest.magic = 12345;                                                                              // MagicNumber der Order
 
   mrequest.sl = NormalizeDouble(latest_price.ask - SL*_Point,_Digits); // Stop Loss
   mrequest.tp = NormalizeDouble(latest_price.ask + TP*_Point,_Digits); // Take Profit
  
   mrequest.type_filling = ORDER_FILLING_IOC;                             // Order execution type
     
   //--- send order - ab hier kommt der return value of "Order send" should be checked Fehler 4756 The buy order request could not be completed - und invalid stops im journal
   
   //--- Send Buy order
   int trade_order_1 = OrderSend(mrequest, mresult);
   
   
   //--- Get the result code
   if ( mresult.retcode == 10009 || mresult.retcode == 10008 ) 
   {          
      Alert("A buy order has been successfully placed with Ticket #", mresult.order, "!");
   } else {
               Alert("The buy order request could not be completed - error: ", GetLastError(), "!");
               ResetLastError();
               return;
        } // Ende else
     } // Ende if Buy Condition   
  } // Ende on Tick




Ich bin wirklich für jede Hilfe sehr dankbar.


Beste Grüße

Paul

 
PS-WW-Trader:

Hallo,


ich hoffe Ihr könnt mir weiterhelfen, denn ich habe ein seltsames Problem.Meine Idee ist, immer dann eine Buy Order zu eröffnen, wenn der ADX Wert größer als ein voreingestellter ADX Wert ist und weiterhin beim ADX der D+ Wert den D- Wert kreuzt. In der Simulation funktioniert dies einwandfrei, jedoch nicht im Livekonto. Ich erhalte noch nicht einmal eine Fehlermeldung. Interessant ist aber, wenn ich die Einstiegsbedingung umändere und zwar so, das D+ (die grüne Kurve) über der D- (rote) Kurve liegt, dann klappt die Buy Trade Order in Verbindung mit dem voreingestellten ADX Wert einwandfrei.

Wo liegt das Problem?

Ich poste mal meinen Quellcode:


Ich bin wirklich für jede Hilfe sehr dankbar.


Beste Grüße

Paul

Hallo,


also ich würde zuerst mal den gesamten Code auf vordermann bringen, dann finden sich fehler auch leichter


der Teil gehört mal in die OnInit

   // sortiere die Preise abwärts von der aktuellen Kerze
   ArraySetAsSeries(ArrayADX,true);  
   ArraySetAsSeries(ArrayDpl,true);
   ArraySetAsSeries(ArrayDmi,true);

dieser Code gehört eigentlich in eine eigene bool Variable die dann true oder false zurückgibt, das macht den Code wesentlich übersichtlicher

int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0) // ok, the data has been copied successfully
     {
      if(Old_Time!=New_Time[0]) // if old time isn't equal to new bar time
        {
         IsNewBar=true;   // if it isn't a first call, the new bar has appeared
         if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here ",New_Time[0]," old time was ",Old_Time);
         Old_Time=New_Time[0];            // saving bar time
        }
     }
   else
     {
      Alert("Error in copying historical times data, error =",GetLastError());
      ResetLastError();
      return;
     }

dann kann ich dir nur die CTrade Klasse nahelegen,

das spart die OrderSend jedes mal zu definieren und neu in den EA zu schreiben. CTrade Klasse ist ein Bestandteil der von MQL5 mitgeliefert wird.

https://www.mql5.com/de/docs/standardlibrary/tradeclasses/ctrade


für diese zeile gibts bessere Experten als mich, aber in meinen Augen ist die völlig Sinnlos

   if(IsNewBar==false)
     {
      return;
     }

vernünftiger wäre es, zu sagen isNewBar == true --> und dann das reinschreiben was passieren soll wenn die variable auf true ist


da kann ich den zuständigen Code nicht finden

 if(Buy_opened)
   {
   Alert("We already have a Buy Position!!!");
   return;    // Don't open a new Buy Position
   } // Ende Buy_opened

was definiert ob eine Buy open ist oder nicht?


ich persönlich mache das genau umgekehrt

sage wenn buyopen == false, dann mache etwas, da spare ich mir den ganze block


um ganz ehrlich zu sein, ich hab in den letzten 15 Jahren nie einen Chart mit weniger als 60 Bars gesehen, also das wird dir immer das richtige ergebnis liefern, den Teil kannst kübeln (da gibts sicher auch andere Meinungen dazu)

 if(Bars(_Symbol,_Period)<60) // if total bars is less than 60 bars
     {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }  


und wenn du die Ctrade Klasse verwendest, brauchst Du diesen Teil nicht, weil das macht die automatisch

   //--- Get the result code
   if ( mresult.retcode == 10009 || mresult.retcode == 10008 ) 
   {          
      Alert("A buy order has been successfully placed with Ticket #", mresult.order, "!");
   } else {
               Alert("The buy order request could not be completed - error: ", GetLastError(), "!");
               ResetLastError();
               return;
        } // Ende else
     } // Ende if Buy Condition   
Dokumentation zu MQL5: Standardbibliothek / Handelsklassen / CTrade
Dokumentation zu MQL5: Standardbibliothek / Handelsklassen / CTrade
  • www.mql5.com
Standardbibliothek / Handelsklassen / CTrade - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
 
amando:

Hallo,


also ich würde zuerst mal den gesamten Code auf vordermann bringen, dann finden sich fehler auch leichter


der Teil gehört mal in die OnInit

dieser Code gehört eigentlich in eine eigene bool Variable die dann true oder false zurückgibt, das macht den Code wesentlich übersichtlicher

dann kann ich dir nur die CTrade Klasse nahelegen,

das spart die OrderSend jedes mal zu definieren und neu in den EA zu schreiben. CTrade Klasse ist ein Bestandteil der von MQL5 mitgeliefert wird.

https://www.mql5.com/de/docs/standardlibrary/tradeclasses/ctrade


für diese zeile gibts bessere Experten als mich, aber in meinen Augen ist die völlig Sinnlos

vernünftiger wäre es, zu sagen isNewBar == true --> und dann das reinschreiben was passieren soll wenn die variable auf true ist


da kann ich den zuständigen Code nicht finden

was definiert ob eine Buy open ist oder nicht?


ich persönlich mache das genau umgekehrt

sage wenn buyopen == false, dann mache etwas, da spare ich mir den ganze block


um ganz ehrlich zu sein, ich hab in den letzten 15 Jahren nie einen Chart mit weniger als 60 Bars gesehen, also das wird dir immer das richtige ergebnis liefern, den Teil kannst kübeln (da gibts sicher auch andere Meinungen dazu)


und wenn du die Ctrade Klasse verwendest, brauchst Du diesen Teil nicht, weil das macht die automatisch

Hallo amando,


vielen Dank für Deine schnelle Antwort und deine Codeanalyse bzw. Tipps. Ich habe diese alle weitestgehend berücksichtigt und auch die Ctrade Klasse verwendet und nun gehts!!!


Besten Dank für Deine tolle Hilfe.


Viele Grüße

Paul

Grund der Beschwerde: