Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools

Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools (http://www.expert-advisor.com/forum/index.php)
-   Programmierung MQL5 (http://www.expert-advisor.com/forum/forumdisplay.php?f=221)
-   -   Nicht alle Orders löschen, sondern nur eine bestimmte... (http://www.expert-advisor.com/forum/showthread.php?t=7397)

murkel 29.03.24 17:35

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. :-)

traderdoc 01.04.24 22:12

Die Variable buyOrderDelete = sl; wird immer wieder überschrieben, wenn eine weitere PendingOrder desselben Typs gesetzt wird. Da diese PendingOrders sicherlich an verschiedenen Kursen ihre SLs haben, kann das so nicht funktionieren.

Ganz einfach fragt man die SL-Werte der PendingOrders über eine Schleife ab.
Dazu wird OrdersTotal() benutzt, in deren Variable die Anzahl der Markt- und! PendingOrders steht. Danach müssen noch die PendingOrders selektiert werden und dann kann der aktuelle Kurs mit den SL-Werten verglichen werden.

traderdoc

murkel 02.04.24 13:36

Vielen Dank traderdoc - du bist mir ein paar Stunden zuvorgekommen, denn mittlerweile konnte ich das Problem lösen ... und zwar genau so, wie du es empfohlen hast.

In der OnTick-Funktion habe ich den Zeitpunkt deklariert:

Code:

//---Close Order
  double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
 
  if(OrderSelect(buyTicket) && bid <= OrderGetDouble(ORDER_SL)){
      closeOrder();
  }
  if(OrderSelect(sellTicket) && bid >= OrderGetDouble(ORDER_SL)){
      closeOrder();
  }

Und weiter unten in der closeOrder-Funktion den Code wie folgt:

Code:

void closeOrder(){
  for(int i = OrdersTotal()-1; i >= 0; i--){
      buyTicket = OrderGetTicket(i);
      if(OrderGetString(ORDER_SYMBOL) != _Symbol && OrderGetInteger(ORDER_MAGIC) != Magic) continue;
      if(OrderSelect(buyTicket) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP){
        if(trade.OrderDelete(buyTicket)){
            Print("  -x-> Buy-Stop-Order #",buyTicket," gelöscht da SL erreicht");
        }
      }
  }
  for(int i = OrdersTotal()-1; i >= 0; i--){
      sellTicket = OrderGetTicket(i);
      if(OrderGetString(ORDER_SYMBOL) != _Symbol && OrderGetInteger(ORDER_MAGIC) != Magic) continue;
      if(OrderSelect(sellTicket) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP){
        if(trade.OrderDelete(sellTicket)){
            Print("  -x-> Sell-Stop-Order #",sellTicket," gelöscht da SL erreicht");
        }
      }
  }
}

Nun klappt es ganau so, wie ich es mir gewünscht habe und ich habe wieder was dazugelernt ... :-)

Nochmals vielen Dank für den Hinweis! :-)


Alle Zeitangaben in WEZ +2. Es ist jetzt 10:16 Uhr.

Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.6.1
Powered by vBCMS® 2.7.0 ©2002 - 2024 vbdesigns.de
Copyright ©2009 - 2023 by Expert-Advisor.com - Das Metatrader Forum