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.

pako 09.02.15 18:47

Zitat:

Zitat von traderdoc (Beitrag 28664)
Funktioniert aber nur solange, wie primär nur ein Pendingpärchen pro Chart existiert.

Wenn 100 Pendings pro Chart existieren, funktioniert es auch

traderdoc 09.02.15 18:54

Zitat:

Zitat von pako (Beitrag 28665)
Wenn 100 Pending pro Chart existiert, funktioniert auch

Ja aber nur indem alle!! anderen Pendigs auch gelöscht werden würden.
Das wäre sicherlich nicht im Sinne des Traders, wenn er pro Chart mehrere Pärchen im Markt hat und dann aber immer nur die Pending löschen will, die auch zum anderen Part gehört.
OCO heißt ja One-Cancel-Other und nicht One-Cancel-All, denn dann hieße es ja OCA.:)
Und mit Other ist der Andere gemeint und nicht die Anderen.

traderdoc

pako 09.02.15 19:06

Zitat:

Zitat von traderdoc (Beitrag 28666)
Ja aber nur indem alle!! anderen Pendigs auch gelöscht werden würden.
Das wäre sicherlich nicht im Sinne des Traders, wenn er pro Chart mehrere Pärchen im Markt hat und dann aber immer nur die Pending löschen will, die auch zum anderen Part gehört.
OCO heißt ja One-Cancel-Other und nicht One-Cancel-All, denn dann hieße es ja OCA.:)
Und mit Other ist der Andere gemeint und nicht die Anderen.

traderdoc

laut Topicstarter
Zitat:

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(pending) schließen. Dazu verwende ich folgenden Code:


traderdoc 09.02.15 19:12

Ich habe ja nur dazu eine Bemerkung gemacht, falls der User doch auf die Idee kommt mehrere Pärchen auf dem Chart haben zu wollen.
Aber auch wenn nur ein Pärchen pro Chart gesetzt wird und es existiert mehr als nur 1 Timeframe dieses Währungspaares, wird diese Version nicht mehr eineindeutig arbeiten, sondern die anderen Pärchen der anderen Timeframes ebenfalls löschen.

traderdoc

pako 09.02.15 19:28

Zitat:

Zitat von traderdoc (Beitrag 28670)
Aber auch wenn nur ein Pärchen pro Chart gesetzt wird und es existiert mehr als nur 1 Timeframe dieses Wärhungspaares, wird diese Version nicht mehr eineindeutig arbeiten, sondern die anderen Pärchen der anderen Timeframes ebenfalls löschen.

traderdoc

Wie soll ich das verstehen?:confused:

traderdoc 09.02.15 19:35

Zitat:

Zitat von pako (Beitrag 28671)
Wie soll ich das verstehen?:confused:

@pako, was verstehst Du! daran nicht?
Wenn er z.B. 5 verschiedene Timeframes mit demselben WP offen hat und auf jedem Chart liegt jeweils ein Pärchen, dann werden alle anderen Pärchen dieses WPs mit geschlossen, wenn in einem Chart diese WP eine PendingOrder zur MarketOrder wird, weil eben nur nach OrderSymbol() selektiert wurde.

traderdoc

pako 09.02.15 20:13

Zitat:

Zitat von traderdoc (Beitrag 28672)
@pako, was verstehst Du! daran nicht?
Wenn er z.B. 5 verschiedene Timeframes mit demselben WP offen hat und auf jedem Chart liegt jeweils ein Pärchen, dann werden alle anderen Pärchen dieses WPs mit geschlossen, wenn in einem Chart diese WP eine PendingOrder zur MarketOrder wird, weil eben nur nach OrderSymbol() selektiert wurde.

traderdoc

Ist selbstverständlich aber , Wenn eine ChartID oder ein Timeframe zu einer Magicnummer zugeordnet wird dann kann man es nach dieser Nummer selektieren.

traderdoc 09.02.15 20:21

Zitat:

Zitat von pako (Beitrag 28673)
Ist selbstverständlich aber , Wenn eine ChartID oder ein Timeframe zu einer Magicnummer zugeordnet wird dann kann man es nach dieser Nummer selektieren.

Ja, aber...
Sicherlich kann man das, ist aber nicht.
Wobei eine Magicnumber alleine dazu auch reicht.

traderdoc


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