Anpassungen an meinem Pending-Order-EA

 

Hallo, ich versuche nun schon seit knapp 2 Wochen einige Anpassungen an meinem EA vorzunehmen, schaffe es aber leider nicht so, wie ich mir das Vorstelle.

Dachte mir ich frag erst mal hier nach bevor ich einen Freelancer beauftrage. Vielleicht hat ja hier jemand eine Idee bzw. Vorschlag, mit dem ich weiter komme.

Mein EA platziert bei einer neuen Kerze eine Buy_Stop_Order und eine Sell_Stop_Order. Die Anzahl kann ich limitieren, damit nicht bei jeder Kerze neue Order platziert werden. Auch die Anzahl der offenen Positionen hab ich limitiert, sodass erst dann wieder neue Order platziert werden, wenn weniger offene Positionen im Konto sind, als ich eingestellt habe.

Erstes Problem: Wenn nun eine Order ausgeführt und dann geschlossen wird, platziert er wieder eine Buy_Stop_Order und eine Sell_Stop_Order. Eigentlich möchte ich nur diese Order wieder platzieren die nach dem Ausführen geschlossen wurde.

     -Die Funktion ganz unten im Code die zur Zählung offener Positionen dienen soll, löst das Problem nicht.

Das zweite Problem habe ich mit der "for" Schleife zur Aktivierung der Stop-Loss Linie. Hier möchte ich erst dann eine Stop Loss aktivieren, wenn ein gewisser Schwellenwert überschritten ist. Das funktioniert eigentlich auch nicht wirklich, es wird zwar irgendwann die Stop Loss Linie auf den Schwellenwert angehoben, jedoch wird diese nicht automatisch nachgezogen, sondern bleibt immer bei diesem Wert stehen. Habe diese unten auskommentiert, da ich noch eine zweite "for" Schleife darunter, für den Trailing-Stop habe. Dieser funktioniert grundsätzlich. Wenn ich beide Schleifen aktiviere, wird aber die Stop-Loss Linie in beide Richtungen verschoben, was natürlich keinen Sinn macht. Außerdem fängt der visuelle Tester an irgeneinem Punkt zu spinnen an und wird extrem langsam.

Die dritte und letzte Anpassung die mir vorschwebt wäre, dass ich die Stop-Loss und Take-Profit Linien bei den Order-Typen als boolsche Variable zum ein-und ausschalten mache. Trades wüden dann immer über die Stop-Loss geschlossen sofern der Schwellenwert erreicht wird.

Mir ist klar dass das auch ein gewaltiges Risiko mitsichbringt, da es sein kann, dass er eine Order ausführt, den Schwellenwert nicht erreicht und ewig in die falsche Richtung laufen kann. In diesem Fall würd ich mir nen fetten Minus-Trade im Konto mitziehen. Testen würd ich das aber trotzdem gerne.

Ich würde mich sehr freuen wenn mir jemand helfen kann.

Hier mein aktueller Code den ich zur Zeit auf BRN und im Zeitraum von 26.12.2022 bis heute teste. (Timeframe = 1 Minute)

#include <Trade/Trade.mqh>

//+------------------------------------------------------------------+
//| Eingabe Variablen                                                      |
//+------------------------------------------------------------------+
static input long  MeinRobi = 678;// Nummer vom EA

input group "<===========Index der Kerze===========>";
input int Shift = 0;

input group "<===========Einsatz Parameter===========>";
//input double LotSize = 0.03;// Einsatz in Lotgröße
input double Einsatz = 5;// Einsatz in Prozent
input double StopLossDistanz = 3;// StopLoss Distanz (Symbolabhängig --> Prüfen durch testen)
input double StartkapitalProzentsatz = 75.0; // Prozentsatz für das KapitalLimit zu Beginn

input group "<====Maximale Anzahl an Order und Positionen====>";
input int AnzahlOrder = 2;
input int AnzahlPositionen = 1;

input group "<==============Parameter BUY Order===============>";
input bool BuyStopOrder = true;//BuyStopOrder aktivieren/deaktivieren
input int PunkteBuyStopOrder = 230;//Setze BuyStopOrder x Punkte über Eröffnung
input int BuyTrailingpoints = 170;//BuyStopOrder im Abstand von x Punkten nachziehen

input group "<==============Parameter SELL Order===============>";;
input bool SellStopOrder = true;//SellStopOrder aktivieren/deaktivieren
input int PunkteSellStopOrder = 190;//Setze SellOrder x Punkte unter Eröffnung
input int SellTrailingpoints = 220;//SellStopOrder im Abstand von x Punkten nachziehen

input group "<===Schwellenwert für Stop Loss wenn Order ausgeführt wurde===>";
input double StopLossSchwellwert = 50;

input group "<===========Traling Parameter BUY Position===========>";
input int BuyStopLoss = 250;//Stop Loss in Punkten
input int BuyTakeProfit = 500;//Take Profit in Punkten
input int BuyTrailingStop = 260;//Trailingstop in Punkten

input group "<===========Traling Parameter SELL Position===========>";
input int SellStopLoss = 640;//Stop Loss in Punkten
input int SellTakeProfit = 130;//Take Profit in Punkten
input int SellTrailingStop = 610;//Trailingstop in Punkten

input group "<=================================================>";
input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;
input ENUM_ORDER_TYPE_TIME SchlussZeit = ORDER_TIME_GTC;

//+------------------------------------------------------------------+
//| Globale Variablen                                                       |
//+------------------------------------------------------------------+
//datetime timestamp;
double openBar;
ulong orderTicket;

double KapitalLimit = AccountInfoDouble(ACCOUNT_BALANCE) * StartkapitalProzentsatz / 100.0; // KapitalLimit wird auf den Prozentsatz des Startkapitals festgelegt
double VorherigerKontostand = AccountInfoDouble(ACCOUNT_BALANCE); // Variable zur Speicherung des vorherigen Kontostands

CTrade opentrade;

//+------------------------------------------------------------------+
//| Expert initialization function                                    |
//+------------------------------------------------------------------+
int OnInit(){

      opentrade.SetExpertMagicNumber(MeinRobi);
   
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
 
}
//+------------------------------------------------------------------+
//| Expert tick function                                                  |
//+------------------------------------------------------------------+
void OnTick(){

   // Aufrufen der Funktion zur Berechnung des Einsatz (Lots)
   double Lots = BerechneEinsatz(Einsatz, StopLossDistanz);
   
   // Aufrufen der Funktion zur Aktualisierung des Kapitallimits
   double aktualisiertesKapitalLimit = AktualisiereKapitalLimit();

   double open = iOpen(_Symbol, TimeFrame,Shift);
   open = NormalizeDouble(open, _Digits);
   if(openBar != open){
      openBar = open;
         
      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   
   // Aufrufen der Funktion zur Zählung offener Positionen   
      int cntbuy, cntsell;
      if(!CountOpenPositions(cntbuy, cntsell)){
            return;
      }
           
      if(PositionsTotal() < AnzahlPositionen){
         if(OrdersTotal() < AnzahlOrder){          
            if(orderTicket >= 0){
               if(cntbuy <= 1){
                  if(AccountInfoDouble(ACCOUNT_BALANCE) >= aktualisiertesKapitalLimit){
                     if(BuyStopOrder == true){
                        double priceb   = open + PunkteBuyStopOrder * SymbolInfoDouble(_Symbol, SYMBOL_POINT);      
                        double slb   = priceb - BuyStopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
                        double tpb   = priceb + BuyTakeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
                                       
                        opentrade.BuyStop(Lots, priceb, _Symbol, slb, tpb, SchlussZeit, 0, "");
                     }
                  }
               }
            }
            if(orderTicket >= 0){
               if(cntsell <= 0){
                  if(AccountInfoDouble(ACCOUNT_BALANCE) >= aktualisiertesKapitalLimit){
                     if(SellStopOrder == true){
                        double prices   = open - PunkteSellStopOrder * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
                        double sls   = prices + SellStopLoss * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
                        double tps   = prices - SellTakeProfit * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
                                                                             
                        opentrade.SellStop(Lots,prices, _Symbol, sls, tps, SchlussZeit, 0,"");
                     }
                  }
               }
            }                                  
         }
      }                  
   }  

// Schleife zur Aktivierung der Stop Loss Linie, wenn Schwellenwert überschritten wird
/*for(int i = PositionsTotal() - 1; i >= 0; i--){
   ulong posTicket = PositionGetTicket(i);
   long robi = PositionGetInteger(POSITION_MAGIC);
   CPositionInfo pos;
   
   if(posTicket > 0 && PositionGetTicket(i)){
      if(PositionGetInteger(POSITION_MAGIC) == MeinRobi){
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
            double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            //double newSl = entryPrice + StopLossSchwellwert * _Point;
            double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);

            //double positionSl = PositionGetDouble(POSITION_SL);
            double positionTp = PositionGetDouble(POSITION_TP);

            if(currentPrice > entryPrice + StopLossSchwellwert * _Point){
              double newSl = entryPrice + StopLossSchwellwert * _Point;
              opentrade.PositionModify(posTicket, newSl, positionTp);
            }
         }else{
            double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            //double newSl = entryPrice + StopLossSchwellwert * _Point;
            double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

            //double positionSl = PositionGetDouble(POSITION_SL);
            double positionTp = PositionGetDouble(POSITION_TP);

            if(currentPrice < entryPrice+ StopLossSchwellwert * _Point){
              double newSl = entryPrice - StopLossSchwellwert * _Point;
              opentrade.PositionModify(posTicket, newSl, positionTp);
            }
         }         
      }
   }      
}*/

// Schleife für Trailing-Stop
for(int i = PositionsTotal()-1; i >= 0; i--){
   
   ulong posTicket = PositionGetTicket(i);
   long robi = PositionGetInteger(POSITION_MAGIC);
   CPositionInfo pos;
            
   if(posTicket > 0 && PositionGetTicket(i)){
      if(PositionGetInteger(POSITION_MAGIC) == MeinRobi){
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
            double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            double newSl = ask - BuyTrailingStop * _Point;
                              
            double positionSl = PositionGetDouble(POSITION_SL);
            double positionTp = PositionGetDouble(POSITION_TP);
                              
            if(newSl > positionSl){
               opentrade.PositionModify(posTicket, newSl, positionTp);
            }
         }else{
            double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            double newSl = bid + SellTrailingStop * _Point;
                              
            double positionSl = PositionGetDouble(POSITION_SL);
            double positionTp = PositionGetDouble(POSITION_TP);
                              
            if(newSl < positionSl || positionSl == 0){
               opentrade.PositionModify(posTicket, newSl, positionTp);
            }
         }         
      }
   }      
}

// Schleife für das Nachziehen der Pending Order
for(int a = OrdersTotal()-1; a >= 0; a--){
   orderTicket = OrderGetTicket(a);
            
   if(OrderSelect(orderTicket) && OrderGetString(ORDER_SYMBOL) == _Symbol){
   
      ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
      
      double orderPrice = OrderGetDouble(ORDER_PRICE_OPEN);
      double orderTp = OrderGetDouble(ORDER_TP);
      double orderSl = OrderGetDouble(ORDER_SL);
                  
      if(orderType == ORDER_TYPE_BUY_STOP){
         double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + BuyTrailingpoints * _Point;
         price = NormalizeDouble(price, _Digits);
                           
         double trailing = price - orderPrice;
                           
         if(orderTp > 0){
            orderTp += trailing;
            orderTp = NormalizeDouble(orderTp, _Digits);
         }
                           
         if(orderSl > 0){
            orderSl += trailing;
            orderSl = NormalizeDouble(orderSl, _Digits);
         }
                           
         if(price < orderPrice){
           opentrade.OrderModify(orderTicket, price, orderSl, orderTp, SchlussZeit, 0);
         }
                     
      }else if(orderType == ORDER_TYPE_SELL_STOP){
         double price = SymbolInfoDouble(_Symbol, SYMBOL_BID) - SellTrailingpoints * _Point;
         price = NormalizeDouble(price, _Digits);
                           
         double trailing = price - orderPrice;
                           
         if(orderTp > 0){
            orderTp += trailing;
            orderTp = NormalizeDouble(orderTp, _Digits);
         }
                           
         if(orderSl > 0){
            orderSl += trailing;
            orderSl = NormalizeDouble(orderSl, _Digits);
         }
                           
         if(price > orderPrice){
            opentrade.OrderModify(orderTicket, price, orderSl, orderTp, SchlussZeit, 0);
         }                     
      }        
      }     
   }         
}
 
//+------------------------------------------------------------------+
//| Aktualisierung des KapitalLimits                                |
//+------------------------------------------------------------------+
double AktualisiereKapitalLimit(){
   double aktuellerKontostand = AccountInfoDouble(ACCOUNT_BALANCE);
    
   // Überprüfen, ob der Kontostand gestiegen ist
   if(aktuellerKontostand > VorherigerKontostand) {
      KapitalLimit = aktuellerKontostand * StartkapitalProzentsatz / 100.0; // berechne das neue KapitalLimit auf den Prozentsatz des aktuellen Kontostands
      VorherigerKontostand = aktuellerKontostand; // Aktualisiere den vorherigen Kontostand
      
      return KapitalLimit; // Den aktualisierten Wert des KapitalLimits zurückgeben
   }
   return KapitalLimit; // Den alten Wert des KapitalLimits zurückgeben
}

//+------------------------------------------------------------------+
//| Berechnung für Einsatz in Prozent                            |
//+------------------------------------------------------------------+
double BerechneEinsatz(double Risk, double sldistance){
   
   double TickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double TickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double LotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   
   
   double Lot = AccountInfoDouble(ACCOUNT_BALANCE) * Risk / 100;
   double MoneyStep = (sldistance / TickSize) * TickValue * LotStep;
   
   double Lots = MathFloor(Lot / MoneyStep) * LotStep;
   
   Print(Lot, " eins " , MoneyStep, " zwei " , Lots, " drei ", KapitalLimit);

      return Lots;
}

//+------------------------------------------------------------------+
//| Zähle offene Buy und Sell Positionen                             |
//+------------------------------------------------------------------+
bool CountOpenPositions(int &cntBuy, int &cntSell){

   cntBuy = 0;
   cntSell = 0;
   
   int total = PositionsTotal();
      for(int i = total -10; i >= 0; i--){
         ulong ticket = PositionGetTicket(i);
         
         if(ticket <= 0){
            Print("Keine Positionseröffnung");
            return false;
         }
         if(PositionSelectByTicket(ticket)){
            Print("Keine Position ausgewählt");
            return false;
         }
         long magic;
            if(!PositionGetInteger(POSITION_MAGIC, magic)){
               Print("Keine EA-Nummer");
               return false;                  
         }          
         if(magic == MeinRobi){
            long type;
            if(!PositionGetInteger(POSITION_TYPE, type)){
               Print("Kein Positions-Type");
               return false;                                  
         }
         if(type == POSITION_TYPE_BUY){
            cntBuy++;
         }
         if(type == POSITION_TYPE_SELL){
            cntSell++;
         }     
      }
   }
      return true;
}

Falsch formatierter Code vom Moderator entfernt.

Die Ereignisverarbeitungsroutine "Neuer Balken"
Die Ereignisverarbeitungsroutine "Neuer Balken"
  • www.mql5.com
Die Programmiersprache MQL5 kann helfen, Probleme auf einer ganz neuen Ebene zu lösen. Selbst Aufgaben, für die es bereits eine Lösung gibt, können dank der objektorientierten Programmierung auf ein höheres Niveau gebracht werden. In diesem Beitrag geht es um ein besonders einfaches Beispiel für die Überprüfung des Auftretens eines neuen Balkens in einem Diagramm, das in ein leistungsfähiges und vielseitiges Hilfsmittel verwandelt wurde. Was ist das für ein Hilfsmittel? Das verrät dieser Artikel.
 

Bitte editiere Deinen EA und poste den Code als Code mit Alt+S oder !

Bedenke: Es gibt fast nichts, was nicht schon für MT4/MT5 programmiert wurde!
 
Thomas Aumayr:
opentrade.SellStop(Lots,prices, _Symbol, sls, tps, SchlussZeit, 0,"");

Hallo,

Bei Problem Nummer 1 überprüfen Sie den letzten geschlossenen Order. Hier ist der Code:


static ENUM_POSITION_TYPE tipe_letzte_position=-1;
for(int i=PositionsTotal()-1; i>=0; i--) // Gibt die Anzahl der aktuellen Positionen zurück

 if(tipe_letzte_position==POSITION_TYPE_BUY) {
  // Wenn letzte Order Buy war, BuyStop setzen
}else if(tipe_letzte_position==POSITION_TYPE_SELL) {
  // Wenn letzte Order Sell war, SellStop setzzen
}

Problem 2:

Erklären Sie bitte den Schwellenwert.


Gruß Igor

 
Igor Widiger #:

Hallo,

Bei Problem Nummer 1 überprüfen Sie den letzten geschlossenen Order. Hier ist der Code:


Problem 2:

Erklären Sie bitte den Schwellenwert.


Gruß Igor

Danke für den Tipp, das werd ich heute gleich mal ausprobieren.
Zum Schwellenwert: Ich möchte versuchen, dass erst dann eine Stop Loss Linie eingefügt wird, wenn der Kurs einen bestimmten Wert vom Einstiegspreis über-bzw. unterschritten hat. Je nach dem ob Long oder Short Order ausgeführt wurde. Ich habe aber gestern noch gesehen, dass die erste for-Schleife mehrere Fehler hat und so, wie sie jetzt ist, gar nicht funktionieren kann.
Das werd ich auch heute versuchen auszubessern. 
 
Thomas Aumayr #:
Danke für den Tipp, das werd ich heute gleich mal ausprobieren.
Zum Schwellenwert: Ich möchte versuchen, dass erst dann eine Stop Loss Linie eingefügt wird, wenn der Kurs einen bestimmten Wert vom Einstiegspreis über-bzw. unterschritten hat. Je nach dem ob Long oder Short Order ausgeführt wurde. Ich habe aber gestern noch gesehen, dass die erste for-Schleife mehrere Fehler hat und so, wie sie jetzt ist, gar nicht funktionieren kann.
Das werd ich auch heute versuchen auszubessern. 

Hallo,

jetzt verstehe ich. (Schwellenwert ist der Breakeven).

// Schleife zur Aktivierung der Stop Loss Linie, wenn Schwellenwert überschritten wird

for(int i=PositionsTotal()-1; i>=0; i--) // Gibt die Anzahl der offenen Positionen zurück
      if(m_position.SelectByIndex(i)) {
         double price_current = m_position.PriceCurrent();
         double price_open    = m_position.PriceOpen();
         double stop_loss     = m_position.StopLoss();
         double take_profit   = m_position.TakeProfit();


         //---
         if(m_position.Symbol()== _Symbol && m_position.Magic()==MeinRobi) { // Prüft nach Symbol und Magicnummer
            if(m_position.PositionType()==POSITION_TYPE_BUY) {

               double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); // Define Bid

               if(stop_loss < price_open) {
                  if(Bid > price_open + StopLossSchwellwert * _Point)
                     m_trade.PositionModify(m_position.Ticket(),m_symbol.NormalizePrice(price_open),take_profit);
               }
            } else {

               double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); // Define Ask

               if(stop_loss > price_open) {
                  if(Ask < price_open - StopLossSchwellwert*_Point)
                     m_trade.PositionModify(m_position.Ticket(),m_symbol.NormalizePrice(price_open),take_profit);
               }
            }
         }
      }

Hier ein kleines Beispiel des Breakeven.


Damit Schwellenwert funktioniert, setzen Sie bitte folgendes Code unter 

#include <Trade/Trade.mqh>

#include <Trade/SymbolInfo.mqh>
CTrade m_trade;
CSymbolInfo m_symbol;
CPositionInfo  m_position;
CHistoryOrderInfo m_history;

Gruß Igor