Einzelnen Beitrag anzeigen
  #1 (permalink)  
Alt 29.03.24
murkel murkel ist offline
Neues Mitglied
 
Registriert seit: Feb 2024
Beiträge: 8
murkel befindet sich auf einem aufstrebenden Ast
Standard Nicht alle Orders löschen, sondern nur eine bestimmte...

Hallo zusammen,

da ich noch totaler Anfänger bin, habe ich einen "Übungs-EA" geschrieben, um mit diesem das eine oder andere zu lernen. Daher ist der unten anhängende Code keine Strategie, sondern dient in der Tat nur zu lernzwecken.

Durch den EA sollen lediglich bei höherem Hoch / tieferem Tief Buy- oder Sell-Stopp-Orders mit SL und TP in den Markt gesetzt werden. Das klappt schon mal fehlerfrei.

Dann soll, wenn die Order getriggert wurde, die Position mit erreichen des SL oder TP geschlossen werden. Auch das klappt fehlerfrei. Dass das fast nur Verluste bringt, soll hier keine Rolle spielen.

Orders, die im Markt sind und deren eigentlicher SL bereits vor dem Entry erreicht werden, sollen gelöscht werden. Dies klappt - aber nur teilweise.

Somit kommen wir zu meinem Problem:
Ich habe den SL mit der variablen "buyOrderDelete" und "sellOrderDelete" besetzt und wenn der Bid-Kurs <= buy/sellOrderDelete ist, soll die Order gelöscht werden. Macht der EA auch, doch wenn ich nun zwei (oder mehrere) offene Orders (in eine Richtung) habe, löscht er nur die erste Order - die anderen Order, deren SL ebenfalls erreicht wurde, bleiben im Markt.

Wie kann den jeweiligen SL der richtigen Order zuordnen - damit jede Order gelöscht wird, deren SL erreicht ist (nicht aber die Orders, deren SL noch nicht erreicht ist).

Code:
//+------------------------------------------------------------------+
//|                                            lern- und test-EA.mq5 |
//|                                         Copyright 2024, Anfänger |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Anfänger"
#property version   "1.00"

#include       <Trade/Trade.mqh>

enum ENUM_LOT  {LOT_FIX,LOT_AMOUNT,LOT_PERCENT};
enum ENUM_SL   {SL_FIX,SL_CANDLE};

input group    "SIGNAL"
input string   TimeRangeStart          = "11:02";
input string   TimeRangeEnd            = "11:12";

input group    "RISIKO"
input ENUM_LOT Lotcalculation          = LOT_AMOUNT;
input double   RiskInLots              = 0.2;
input double   RiskInAmount            = 10.00;
input double   RiskInPercent           = 0.25;

input group    "HANDEL"
input ENUM_SL  SlVariable              = SL_CANDLE;
input uint     SlInitial               = 1500;
input uint     TpInitial               = 3000;

input group    "DIVERS"
input uint     SymbolBuffer            = 100;
input ulong    Magic                   = 202403271656;

CTrade         trade;
ulong          buyTicket;
ulong          sellTicket;
double         high1;
double         low1;
double         buyOrderDelete;
double         sellOrderDelete;
bool           noSignal;
bool           longSignal;
bool           shortSignal;
datetime       timeRangeStart;
datetime       timeRangeEnd;
datetime       timeSignal;


int OnInit(){
   static bool isInit = false;
   if(!isInit){
      isInit = true;
      Print(__FUNCTION__," > EA (re)start");
   }
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){
   
}

void OnTick(){
   //---TimeRange
   if(timeRangeStart != StringToTime(TimeRangeStart)){
      calcTimes();
   }
   
   //---Signal
   if(TimeCurrent() >= timeRangeStart && TimeCurrent() < timeRangeEnd){
      timeSignal = iTime(_Symbol,PERIOD_CURRENT,0);
      static datetime timestapSignal;
      if(timestapSignal != timeSignal){
         timestapSignal = timeSignal;
         calcSignal();
      }
   }
   
   //---Order
   if(longSignal == true){
      executeBuy();
   }
   longSignal = false;
   
   if(shortSignal == true){
      executeSell();
   }
   shortSignal = false;
   
   //---Close Order
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(bid <= buyOrderDelete && OrderSelect(buyTicket)){
      if(trade.OrderDelete(buyTicket)){
         Print("  -x-> Buy-Stop-Order #",buyTicket," cancelled, SL reached");
      }
   }
   if(bid >= sellOrderDelete && OrderSelect(sellTicket)){
      if(trade.OrderDelete(sellTicket)){
         Print("  -x-> Sell-Stop-Order #",sellTicket," cancelled, SL reached");
      }
   }
}

void calcTimes(){
   timeRangeStart = StringToTime(TimeRangeStart);
   timeRangeEnd   = StringToTime(TimeRangeEnd);
}

void calcSignal(){
   //---Candle 1
   double open1         = iOpen(_Symbol,PERIOD_CURRENT,1);
          high1         = iHigh(_Symbol,PERIOD_CURRENT,1);
          low1          = iLow(_Symbol,PERIOD_CURRENT,1);
   double close1        = iClose(_Symbol,PERIOD_CURRENT,1);
   
   //---Candle 2
   double open2         = iOpen(_Symbol,PERIOD_CURRENT,2);
   double high2         = iHigh(_Symbol,PERIOD_CURRENT,2);
   double low2          = iLow(_Symbol,PERIOD_CURRENT,2);
   double close2        = iClose(_Symbol,PERIOD_CURRENT,2);
   
   //---No Signal
   bool higherLowerBar  = (high1 > high2 && low1 < low2);
   bool insideBar       = (high1 <= high2 && low1 >= low2);
   bool doji            = (open1 == close1);
   
   if(higherLowerBar == true){
      noSignal = true;
      Print("  no signal - higherLowerBar ",higherLowerBar);
      return;
   }
   if(doji == true){
      noSignal = true;
      Print("  no signal - doji ",doji);
      return;
   }
   if(insideBar == true){
      noSignal = true;
      Print("  no signal - insideBar ",insideBar);
      return;
   }
   
   //---Long Signal
   bool lowerLow = (low1 < low2 && high1 <= high2);
   
   if(lowerLow == true){
      longSignal = true;
      Print("!!! LONG SIGNAL");
   }else
      {Print("  no long signal");
   }
   
   //---Short Signal
   bool higherHigh    = (high1 > high2 && low1 >= low2);
   
   if(higherHigh == true){
      shortSignal = true;
      Print("!!! SHORT SIGNAL");
   }else
      {Print("  no short signal");
   }
}

void executeBuy(){
   double ask     = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid     = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double spread  = roundUp(ask - bid);
   double entry   = roundUp(high1 + spread + SymbolBuffer * _Point);
   double sl      = 0;
   
   if(SlVariable == SL_FIX){
      sl = entry - SlInitial * _Point;
   }else  sl = roundUp(low1 - SymbolBuffer * _Point);
   
   double tp = roundUp(entry + TpInitial * _Point);
   Print("  Long: entry ",entry," (spread ",spread,"), sl ",sl,", tp ",tp);
   
   double lots    = calclots(entry - sl);
   double price   = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(price < entry){  
      if(trade.BuyStop(lots,entry,_Symbol,sl,tp,0,0)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            buyTicket = trade.ResultOrder();
            Print("  --> Buy-Stop-Order #",buyTicket," was sent");
            buyOrderDelete = sl;
         }
      }
   }
   if(price >= entry){
      if(trade.Buy(lots,_Symbol,entry,sl,tp)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            buyTicket = trade.ResultOrder();
            Print("  --> Buy-Market-Order #",buyTicket," was sent");
         }
      }
   }
}

void executeSell(){
   double ask     = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double bid     = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double spread  = roundUp(ask - bid);
   double entry   = roundDn(low1 - SymbolBuffer * _Point);
   double sl      = 0;
   
   if(SlVariable == SL_FIX){
      sl = entry + SlInitial * _Point;
   }else  sl = roundDn(high1 + spread + SymbolBuffer * _Point);
   
   double tp    = roundDn(entry - TpInitial * _Point);
   Print("  Short: entry ",entry,", sl ",sl," (spread ",spread,"), tp ",tp);
   
   double lots  = calclots(sl - entry);
   double price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(price > entry){  
      if(trade.SellStop(lots,entry,_Symbol,sl,tp,0,0)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            sellTicket = trade.ResultOrder();
            Print("  --> Sell-Stop-Order #",sellTicket," was sent");
            sellOrderDelete = sl;
         }
      }
   }
   if(price <= entry){
      if(trade.Sell(lots,_Symbol,entry,sl,tp)){
         if(trade.ResultRetcode() == TRADE_RETCODE_DONE){
            sellTicket = trade.ResultOrder();
            Print("  --> Sell-Market-Order #",sellTicket," was sent");
         }
      }
   }
}

double roundUp(double price){
   double ticksize = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),_Digits);
   price = NormalizeDouble(price,_Digits);
   double rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
   rest = NormalizeDouble(rest,_Digits);
   if(rest != 0){
      for (double i = _Point; i <= ticksize; i += _Point){
         price = NormalizeDouble(price + _Point,_Digits);
         rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
         rest = NormalizeDouble(rest,_Digits);
         if(rest == 0) break;
      }
   }
   return price;
}

double roundDn(double price){
   double ticksize = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),_Digits);
   price = NormalizeDouble(price,_Digits);
   double rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
   rest = NormalizeDouble(rest,_Digits);
   if(rest != 0){
      for (double i = _Point; i <= ticksize; i += _Point){
         price = NormalizeDouble(price - _Point,_Digits);
         rest = price - NormalizeDouble(price/ticksize,0) * ticksize;
         rest = NormalizeDouble(rest,_Digits);
         if(rest == 0) break;
      }
   }
   return price;
}

double calclots(double slPoints){
   double lots = 0;
   double ticksize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   double tickvalue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   double lotstep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep;

   if(Lotcalculation == LOT_FIX){
      lots = RiskInLots;
      Print("  fixed lot size: ",lots," lot");
   }
   if(Lotcalculation == LOT_AMOUNT){
      lots = MathFloor(RiskInAmount / moneyPerLotstep) * lotstep;
      Print("  lot size caculated via amount: ",lots," lot");
   }
   if(Lotcalculation == LOT_PERCENT){
      double riskPerTrade = AccountInfoDouble(ACCOUNT_EQUITY) * RiskInPercent / 100;
      lots = MathFloor(riskPerTrade / moneyPerLotstep) * lotstep;
      Print("  lot size calculated as a percentage: ",lots," lot");
   }
   lots = MathMin(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX));
   lots = MathMax(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN));
   return lots;
}
Den Ansatz mit einer Schleife habe ich probiert - bin aber ehrlich gesagt noch "zu blöd" es hinzubekommen. Außerdem bin ich auch der Meinung, dass mit einer Schleife alle Order gelöscht werden - was wiederum ebenfalls nicht gewünscht ist.

Dennoch möchte ich euch zeigen, was ich hierzu geschrieben habe. In OnTick habe ich abgefragt (nur mal für die Buy-Variante):

Code:
   //---Close Order
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   
   if(bid <= buyOrderDelete && OrderSelect(buyTicket)){
      closeOrder();
   }
Und dazu weiter unten folgende Funktion:

Code:
void closeOrder(){
   for(int i = OrdersTotal()-1; i >= 0; i--){
      buyTicket = OrderGetTicket(i);
      if(OrderSelect(buyTicket)){
         if(OrderGetString(ORDER_SYMBOL) != _Symbol) continue;            
         if(OrderGetInteger(ORDER_MAGIC) != Magic) continue;
         if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP){
            if(trade.OrderDelete(buyTicket)){
               Print("  -x-> Buy-Stop-Order #",buyTicket," gelöscht da SL erreicht");
            }
         }
      }
   }
}
Mit dieser Variante löscht er gar keine Buy-Orders.

Wie gesagt, so lange ich nur eine Order in jede Richtung habe, klappt die Löschung, sofern notwendig, problemlos ... aber halt nicht mit mehr als einer Order in eine Richtung.

Schon mal vielen Dank für Lösungsansätze. :-)
Mit Zitat antworten