|
Startseite | Registrieren | Hilfe | Benutzerliste | Kalender | Suchen | Heutige Beiträge | Alle Foren als gelesen markieren |
Programmierung MQL5 Hier gehts rund ums Programmieren in MQL5. |
|
Themen-Optionen | Thema durchsuchen | Ansicht |
|
|||
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; } 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(); } 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"); } } } } } 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. :-) |
|
|||
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
__________________
Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierungswünsche auf Honorarbasis. |
|
|||
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(); } 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"); } } } } Nochmals vielen Dank für den Hinweis! :-) |
Lesezeichen |
Themen-Optionen | Thema durchsuchen |
Ansicht | |
|
|