|
Programmierung MQL4 Hier gehts rund ums Programmieren in MQL4. |
|
Themen-Optionen | Thema durchsuchen | Ansicht |
|
|||
Probleme mit OCO-Funktion
Hallo zusammen,
nachdem ich für meinen ersten EA in diesem Forum bereits eine Menge Ideen und Hinweise finden konnte, bin ich bei der Entwicklung inzwischen auf ein Problem gestoßen, dass ich nicht lösen kann. Der EA soll als News-EA fungieren und zu einer bestimmten Zeit zwei Pending-Orders (BuyStop und SellStop) setzen. Das klappt bisher einwandfrei. Dann soll die klassische OCO-Funktion ins Spiel kommen und die nicht eröffnete Position schließen. Dazu verwende ich folgenden Code: //+------------------------------------------------------------------+ //| Benutzer-Input | //+------------------------------------------------------------------+ extern int News_Tag = 5; extern int News_Stunde = 20; extern int News_Minute = 30; extern double Lots = 0.1; extern int StopLoss = 30; extern int TakeProfit = 400; extern int TrailingStop = 30; extern int Pip_Differenz = 50; //+------------------------------------------------------------------+ //| Variablen-Definitionen | //+------------------------------------------------------------------+ int Zaehler = 0; int ticket1, ticket2; void OnTick() { //===Tag & Uhrzeit prüfen=== static bool Erster_Tick = true; if(Day() == News_Tag && Hour() == News_Stunde && Minute() == News_Minute) { if(Erster_Tick == true) { Alert("Order startet"); Erster_Tick = false; //===Programmkern=== //===Orderaufgabe START=== //Buy-Order if (Zaehler < 1) { ticket1 = OrderSend(Symbol(), OP_BUYSTOP, Lots, Close[0] + Pip_Differenz*Point, 10, Close[0] - StopLoss*Point, Close[0] + TakeProfit*Point, "Set by News-Advisor"); if (ticket1 < 0) { Alert ("Error sending Buy-Order!Fehlercode:", GetLastError()); } //Sell-Order ticket2 = OrderSend(Symbol(), OP_SELLSTOP, Lots, Close[0] - Pip_Differenz*Point, 10, Close[0] + StopLoss*Point, Close[0] - TakeProfit*Point, "Set by News-Advisor"); if (ticket2 < 0) { Alert ("Error sending Sell-Order!Fehlercode:", GetLastError()); } } //===Orderaufgabe ENDE=== //===OCO-Funktion START=== for (int i = 0; i < OrdersTotal(); i++) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_BUY) { OrderDelete(ticket2); if(Bid-OrderOpenPrice()>Point*TrailingStop) { if(OrderStopLoss()<Bid-Point*TrailingStop) { OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green); } } } if (OrderType() == OP_SELL) { OrderDelete(ticket1); if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) { if(OrderStopLoss()>(Ask+Point*TrailingStop)) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Poi nt*TrailingStop,OrderTakeProfit(),0,Red); } } } } //===OCO-Funktion ENDE=== } //===Programmkern ENDE=== } else { Erster_Tick = true; } } //+------------------------------------------------------------------+ Das Programm zeigt mir im StrategyTester eine Dauerschleife aus Fehlermedlungen (4108 : Invalid Ticket) an die ich nicht beheben kann. Wo liegt mein Fehler? Danke für eure Hilfe, mfG Bucardo |
|
|||
Zitat:
Code:
for(int i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { if(OrderSymbol()==Symbol()) { if(OrderType()>1) { int ticket=OrderTicket(); OrderDelete(ticket); } } } } |
|
|||
Wow das ging schnell
Danke pako! (Ich habe wohlzu kompliziert gedacht) VG Bucardo |
|
|||
Neues Problem
Hallo zusammen,
nachdem mir pako mit meinem ersten OCO-Problem geholfen hat, bin ich nach einiger Zeit auf das nächste Problem bzgl. der OCO-Funktion gestoßen. Das Ziel ist wie immer das gleiche: Sollte eine der beiden Pending-Orders erfüllt werden, soll die noch offene PO gelöscht werden. Dazu verwende ich den COde unter "/// OCO-Funktion". Könnt ihr mir sagen wo mein Fehler liegt? Im Strategy-Tester schwanken die Ergebnisse zwischen "keine Order wird gelöscht" und "FehlerCOde 4108 / falsches Ticket". In der aktuellen Konfiguration passiert einfach nichts und ich finde den Fehler einfach nicht. :/ P.S. zur Vereinfachung des COdes habe ich diverse VOrbedingungen zur Orderaufgabe weggelassen, weil diese (inkl. der Orderaufgabe einwandfrei funktionieren) Pp.S. pako's Lösung sorgt im aktuellen Fall dafür, dass immer wieder Orders eröffnet und geschlossen werden. Danke & Gruß Bucardo void OnTick() { int ticket_b; int ticket_s; // Programmkern START //// Prüfung ob keine Order offen ist, bevor neue Order eröffnet wird bool res; res=OrderSelect(ticket,SELECT_BY_TICKET); if(res == true) { if(OrderCloseTime() == 0) { bool res2; res2=OrderClose(ticket,Lots,OrderClosePrice(),10); if(res2 == false) { Alert("Error Closing Nr.",ticket); } } } //// Orderaufgabe ticket_b = OrderSend(Symbol(),OP_BUYSTOP,Lots,Buy_Price,20,Bu y_SL,Buy_TP,"Set by London-Breakout-Advisor"); ticket_s = OrderSend(Symbol(),OP_SELLSTOP,Lots,Sell_Price,20, Sell_SL,Sell_TP,"Set by London-Breakout-Advisor"); // Programmkern ENDE } ////Risikomanagement //// OCO-Funktion for(int i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(ticket_b,SELECT_BY_TICKET,MODE_TRAD ES)) { if(OrderSymbol()==Symbol()) { if(OrderType()==OP_BUY) { OrderDelete(ticket_s); } } } if(OrderSelect(ticket_s,SELECT_BY_TICKET,MODE_TRAD ES)) { if(OrderSymbol()==Symbol()) { if(OrderType()==OP_SELL) { OrderDelete(ticket_b); } } } } //// Schließung aller Orders um 21:30 Uhr if (Hour() == 21 && Minute() > 30) { if (OrdersTotal() > 0) { for (int j=OrdersTotal()-1;j>=0;j--) { ph1=OrderSelect(j, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_BUY) { ph2=OrderClose(OrderTicket(),OrderLots(), Bid, 10); } if (OrderType() == OP_SELL) { ph3=OrderClose(OrderTicket(),OrderLots(), Ask, 10); } if (OrderType() == OP_BUYSTOP) { ph4=OrderDelete(OrderTicket()); } if (OrderType() == OP_SELLSTOP) { ph5=OrderDelete(OrderTicket()); } } } } } |
|
|||
So beim Rüberfliegen fällt auf:
for(int i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(ticket_b,SELECT_BY_TICKET,MODE_TRAD ES)) bzw. if(OrderSelect(ticket_s,SELECT_BY_TICKET,MODE_TRAD ES)) Da ticket_b bzw. ticket_s hier übergeben werden, ist die for-Schleife überflüssig. Die Schreibweise MODE_TRAD ES mit dem Freizeichen ist eigentlich nicht tolerabel. Und dann würde ich schreiben: bool del = OrderDelete(ticket_s); if (del) return; um sicher zu gehen, dass der Bub nicht in die nächste Abfrage geht, was durchaus passieren kann aber nicht sollte, weil die Order gelöscht wurde. Zeitverzögerungen, alles schon erlebt, können aber dazu führen, dass dann doch ticket_s existiert. traderdoc
__________________
Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierungswünsche auf Honorarbasis. |
|
|||
falsche logik
und hier wenn OP_BUY oder OP_SELL dann OrderClose wenn Pending dann OrderDelete if(OrderType()==OP_BUY) { OrderDelete(ticket_s); } |
|
|||
@pako:
Ich habe das so verstanden: Wenn der Buy-Stop zum Market-Buy wird, dann muss der Sell-Stop (mit der Ticket-Nr. ticket_s) gelöscht werden (und nicht geschlossen). Pending-Order wird gelöscht, Market-Order wird geschlossen. |
|
|||
Zitat:
Code:
int CountMarketPos=0; for(int i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { if(OrderSymbol()==Symbol()) { if(OrderType()<2)// market { CountMarketPos++;//market buy oder sell } } } } if (CountMarketPos > 0 ) // market buy oder sell { for(int i=OrdersTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { if(OrderSymbol()==Symbol()) { if(OrderType()>1) // pending { OrderDelete(OrderTicket()); } } } } } Geändert von pako (09.02.15 um 18:32 Uhr) |
|
|||
Da wäre ich nie drauf gekommen...
Vielen Dank pako! |
Lesezeichen |
Stichworte |
mql4, news, news ea, news expert advisor, oco, oco funktion, one-close-other, pending-order, problem, programmierung, programmierung metatrader |
|
|