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 MQL4 (http://www.expert-advisor.com/forum/forumdisplay.php?f=220)
-   -   Probleme mit OCO-Funktion (http://www.expert-advisor.com/forum/showthread.php?t=3980)

Bucardo 06.12.14 20:04

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

pako 06.12.14 21:03

Zitat:

Zitat von Bucardo (Beitrag 28106)
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

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);
          }
        }
    }
  }


Bucardo 07.12.14 18:27

Wow das ging schnell :)

Danke pako! (Ich habe wohlzu kompliziert gedacht)

VG Bucardo

Bucardo 09.02.15 17:14

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());
}
}
}
}

}

traderdoc 09.02.15 17:48

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

pako 09.02.15 17:49

falsche logik


und hier

wenn OP_BUY oder OP_SELL dann OrderClose
wenn Pending dann OrderDelete


if(OrderType()==OP_BUY)
{
OrderDelete(ticket_s);
}

Bucardo 09.02.15 17:52

@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.

pako 09.02.15 18:18

Zitat:

Zitat von Bucardo (Beitrag 28659)
@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.


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());
                          }
                    }
              }
        }
  }


Bucardo 09.02.15 18:23

Da wäre ich nie drauf gekommen...

Vielen Dank pako!

traderdoc 09.02.15 18:31

Funktioniert aber nur solange, wie primär nur ein Pendingpärchen pro Chart existiert.


Alle Zeitangaben in WEZ +2. Es ist jetzt 06:20 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