Jump to content
Tom Next - Daytrading Community

Recommended Posts

Posted (edited)
Was ist mit totals wenn eine Limitorder noch nicht ausgeführt wurde?

Fall totals dann = 1, wie kriege ich denn heraus, wieviele ausgeführte Orders und damit geöffnete Positionen ich habe?

 

Folgendes nutz ich, um offene Positionen und Pending Orders zu unterscheiden:

 

#define OT_BUY		1
#define OT_SELL	   2
#define OT_BUYLIMIT   4
#define OT_SELLLIMIT  8
#define OT_BUYSTOP   16
#define OT_SELLSTOP  32

#define OT_TRADES	 3
#define OT_PENDING   60

int OrdersTotalByType(int type)
{
 int result = 0;

 for (int i = OrdersTotal() - 1; i >= 0; i--)
 {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
  if (0 != OrderType() & type) result++;
}
 }

 return (result);
}

 

Die Verwendung ist denkbar einfach:

 

// Prüfen, ob es Pending Orders gibt
if (0 == OrdersTotalByType(OT_PENDING)) {
 Print("Keine pending Orders gefunden");
}

// Anzahl der offenen Positionen ausgeben
Print("Offene Positionen: ", OrdersTotalByType(OT_TRADES));

// Anzahl aller Long Trades/Orders ausgeben
Print("Long Positionen/Orders: ", OrdersTotalbyType(OT_BUY | OT_BUYLIMIT | OT_BUYSTOP));

Edited by Buthus
Posted
Was ist mit totals wenn eine Limitorder noch nicht ausgeführt wurde?

Falls totals dann = 1, wie kriege ich denn heraus, wieviele ausgeführte Orders und damit geöffnete Positionen ich habe?

 

OrdersTotal gibt dir die Anzahl der "noch nicht geschlossenen und nicht gecancelten" ORders an, also alle offenen Orders (inkl. der Pending Orders).

 

Da jede Order selber noch den OrderType weiß, (und da du mit einem EA sowieso nicht nur auf OrdersTotal zurückgreifen solltest) empfiehlt sich eine Schleife der folgenden Art:

for(index=0;index < OrdersTotal(); index++)
{
   if(OrderSelect(index,SELECT_BY_POS,MODE_TRADES)==false)        break;
   if(OrderMagicNumber()!=magic_number || OrderSymbol()!=Symbol()) continue;
   //---- check order type 
  if(OrderType()==OP_BUY) //offene LONG Position
  [...]
  
  if(OrderType()==OP_SELL) //offene SHORT Position
  [...]
  
  etc.
}

wobei in den if abfragen dann jeweils ein counter stehen kann der die offenen positionen etc. zählt, oder die Order direkt bearbeitet (stop nachzieht etc).

Damit greifst du mit dem EA auch nur auf die Orders zu, die du "selber" erzeugt hast (magic_number) und auch zu deinem Symbol passen (vorrausgesetzt der EA arbeitet nur mit einem Symbol, ansonsten musst du den Part halt ändern).

 

hth

Posted

Habe ein paar Tage nicht gepostet, weil ich erstmal selbst ein wenig weiterkommen wollte.

Um eure beiden letzten Antworten zu verstehen, mußte ich ja die for-Schleife verstehen.

Das ist mir gelungen. For-Schleifen hab ich verstanden und die while-Schleifen hab ich mir dabei auch gleich reingezogen.

 

Was mir nicht gelingt, ist zu kapieren, was der zweite und dritte Parameter der OrderSelect Funktion macht.

 

Meine aktuelle Vermutung:

Es gibt zwei verschiedene Listen.

Wenn der erste Parameter "index" die Ticketnummer ist, muß der zweite Parameter Select by Ticket heißen, damit in der Liste nachgeschaut wird, in der die Ticketnummern stehen.

Aber was ist dann mit dem dritten Parameter?

Und:

Wenn der erste Parameter nicht die Ticketnummer ist, sondern Order index, was ist das? Da der zweite Parameter dann SELECT_BY_POS heißen muß,

vermute ich daß der erste also so etwas wie eine Positionsnummer ist, kann mir aber nicht erklären, was das sein soll. Bekommen alle Orders noch eine Pos nummer?

Wenn Ihr mir das erklärt, kann ich weitermachen mit "die letzten beiden Antworten verstehen"

Posted
Meine aktuelle Vermutung:

Es gibt zwei verschiedene Listen.

Wenn der erste Parameter "index" die Ticketnummer ist, muß der zweite Parameter Select by Ticket heißen, damit in der Liste nachgeschaut wird, in der die Ticketnummern stehen.

 

Genau.

 

Aber was ist dann mit dem dritten Parameter?

 

Entweder MODE_TRADES oder MODE_HISTORY. Die Angabe ist optional (ohne Angabe wird MODE_TRADES genommen). Hier wird entschieden, in welchem Pool intern gesucht wird - entweder in den Trades (offene Positionen/Orders) oder in der History (geschlossene/gelöschte/abgebrochene Positionen/Orders).

 

Wenn der erste Parameter nicht die Ticketnummer ist, sondern Order index, was ist das? Da der zweite Parameter dann SELECT_BY_POS heißen muß,

vermute ich daß der erste also so etwas wie eine Positionsnummer ist, kann mir aber nicht erklären, was das sein soll. Bekommen alle Orders noch eine Pos nummer?

 

So in etwa. Durch die Positionsnummer kann eine Order nicht eindeutig identifiziert werden, diese sollte man nur für den aktuellen Schleifendurchlauf als gültig ansehen. Es ist einfach nur eine fortlaufende Nummer (von 0 - n), um auf die Positionen im jeweiligen Pool zugreifen zu können.

 

for (int i = OrdersTotal() - 1; i >= 0; i--)
{
   if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && OP_BUY == OrderType() && 0 < OrderProfit()) {
       OrderClose(OrderTicket(), OrderLots(), Bid, 2);  // close all profitable long positions
   }
}

 

In dem Beispiel wird auch klar, warum gerade der Trade-Pool immer rückwärts durchlaufen werden sollte. In dem Moment, wo eine Position geschlossen wird, rückt die nächste nach und bekommt somit die (fortlaufende) Positionsnummer der geschlossenen Position.

Posted (edited)

Wo wir schon beim Thema sind. Ich habe mir einen kleinen EA gebastelt, welcher an jedem neuen Tag Limit Orders im Markt platziert, aber vorher alle pending Orders löscht. Klappt in der Theorie auch ganz gut, nur in der Praxis schafft er es nicht, wirklich alle ihn betreffenden alten pending Orders zu löschen. Hat da jemand eine Idee, woran das liegen könnte bzw. was zu verbessern wäre?

 

Und so siehts aus:

//Pending Orders löschen
for (i = 0; i < OrdersTotal(); i ++) {
  OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
  if((OrderType()==OP_SELLLIMIT || OrderType()==OP_BUYLIMIT) &&  OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
 if (CancelOld) OrderDelete(OrderTicket(),CLR_NONE);
  }
}

 

Update

Evtl. liegt es am vom Buthus erwähnten Pool - ich werde es also mal anders rum probieren :secret:.

 

Update2

Hatte es nun fix umgebaut und es macht das System schlechter. Muss ich nun mal im Detail durchgehen, was wann wie wo passiert.

 

Update3

Nun heißt es wieder 40h rechnen - dann wird sich zeigen, ob die "richtige" oder die "falsche" Logik die bessere ist. Dass richtig nicht immer unbedingt besser sein muss, weiß ich ja mittlerweile...

Edited by conglom-o
Posted
Update

Evtl. liegt es am vom Buthus erwähnten Pool - ich werde es also mal anders rum probieren.

Genau daran liegt es ;). Stell Dir einfach vor, Du sitzt auf nem Ast und sägst ihn unter Dir stückchenweise ab.

Posted

@conglom-o - wenn's um einen Mini-EA als eigenständiges kleines Werkzeug geht, können wir die Beiträge in einem extra Topic auslagern.

 

Einfach Bescheid geben, falls hierzu eine Aktion gewünscht wird.

Posted

@whipsaw

Vielen Dank, aber das ist nicht nötig. Ich bastel mir halt im Moment nur immer kleine EAs zusammen, um die Funktionsweise des MT4 näher zu verstehen. Man will sich ja doch irgendwie weiterentwickeln...

Die praktischen Beispielmodule dienen eher dazu, mögliche Differenzen zwischen Logik im Kopf und Handlungsweise des EA aufzuzeigen. Die "Fehler" zeigen sich eben (leider) erst in der Praxis. Denke das passt ganz gut hier in den Einstiegsthread rein und kann folglich hier verbleiben. Für meinen etwas wichtigeren EA habe ich ja schon einen eigenen Thread :secret:.

Posted
Nun heißt es wieder 40h rechnen - dann wird sich zeigen, ob die "richtige" oder die "falsche" Logik die bessere ist. Dass richtig nicht immer unbedingt besser sein muss, weiß ich ja mittlerweile...

 

Hei Micha...

 

Diese Vorgehensweise höre ich leider immer häufiger von dir... :secret:

Es kommt nicht drauf an, ob mit "Irgendwas" bessere oder schlechtere Ergebnisse rauskommen, sondern daß die Logik/der Code GENAU!!! das macht, was er soll...

 

Erst kommt die Logik, dann der Code. Und der soll machen, was die Logik sagt.

Kommt Mist raus, muß die Logik überprüft werden und neu gecodet werden... bis es das gewünschte Ergebnis liefert.

 

Sonst weiß man weder WAS, noch WIE WAS gemacht wird.

Posted
Hei Micha...

 

Diese Vorgehensweise höre ich leider immer häufiger von dir... :alarm:

Es kommt nicht drauf an, ob mit "Irgendwas" bessere oder schlechtere Ergebnisse rauskommen, sondern daß die Logik/der Code GENAU!!! das macht, was er soll...

 

Erst kommt die Logik, dann der Code. Und der soll machen, was die Logik sagt.

Kommt Mist raus, muß die Logik überprüft werden und neu gecodet werden... bis es das gewünschte Ergebnis liefert.

 

Sonst weiß man weder WAS, noch WIE WAS gemacht wird.

 

Dem stimme ich ja weitestgehend zu. Nur wenn eine "falsche" bzw. andere Logik besser ist, sollte man sie nicht gleich verwerfen. Dann muss man halt den umgekehrten Weg gehen und verstehen, was an Stelle der angedachten Logik nun eigentlich passiert. Wenn es dann besser ist und (wichtig!) sich auch in der Praxis bewährt, werde ich mich nicht dagegen sträuben. Aber blind einem System vertrauen, welches ich nicht verstehe, würde ich auch nicht :secret:.

Posted
Aber blind einem System vertrauen, welches ich nicht verstehe, würde ich auch nicht :secret:.

 

OK, dann sind wir ja der selben Meinung. :alarm:

Das ""ob die "richtige" oder die "falsche" Logik die bessere ist"" hatte mich irritiert.

 

 

Zum Code, versuch mal:

 

if(OrderType()!=OP_SELL && OrderType()!=OP_BUY && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)

 

dann werden auch die STOP, nicht nur die LIMITS aus den Pendings mit einbezogen.

Posted

@GoSPvC

Yo, da hast Du wohl Recht und man sollte es auch so machen, wenn man wirklich alle Pending Orders killen will. In meinem Fall gibt es da aber nur Limit Orders. Deswegen die von mir gepostete Abfrage. Dass er nicht alle gelöscht hat, schiebe ich nun mal auf den abgesägten Ast :secret:. Morgen weiß ich mehr...

Posted
if((OrderType()==OP_SELLLIMIT || OrderType()==OP_BUYLIMIT) && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)

 

Diese Zeile von conglom-o bringt mich zu der Frage, wie die Reihenfolge bei meheren logischen Abfragen funktioniert.

 

if (A oder B und C)

 

Bezieht sich das "und C" nur auf "B" oder auch auf "A"

Wird einfach von links nach rechts durchgegangen, oder hat das "und" Vorrang, oder...

Posted
Diese Zeile von conglom-o bringt mich zu der Frage, wie die Reihenfolge bei meheren logischen Abfragen funktioniert.

 

if (A oder B und C)

 

Bezieht sich das "und C" nur auf "B" oder auch auf "A"

Wird einfach von links nach rechts durchgegangen, oder hat das "und" Vorrang, oder...

 

Das weiß ich auch nicht so genau - deswegen habe ich extra um die oder-Bedingung eine Klammer gesetzt. Sicher ist sicher :laugh:.

Posted
if (A oder B und C)

Bezieht sich das "und C" nur auf "B" oder auch auf "A"

Das C bezieht sich nur auf sich selbst.

Diese Art ist sehr verwirrend gerade auch für Anfänger.

 

Wenn ihr es so zusammen schreibt ist es bestimmt einfacher zu verstehen.

if( 
  OrderType()==OP_SELLLIMIT||OrderType()==OP_BUYLIMIT  
  &&OrderSymbol()==Symbol()				
  &&OrderMagicNumber()==MagicNumber		 
	   )

 

Wenn hier IF Anweisungen in Schleifen(for oder while) benutzt

könnt ihr die zur verfügung stehenden Befehle in einer Schleife als Hilfe benutzten.

das wären

continue Stop hier und arbeite wieder von oben aber zähle den nächsten Wert in der Schleife.

break Stop hier die Schleife und Arbeite diese nicht weiter ab.

 

 

dann würde dieser Code...

//Pending Orders löschen
for (i = 0; i < OrdersTotal(); i ++) {
  OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
  if((OrderType()==OP_SELLLIMIT || OrderType()==OP_BUYLIMIT) &&  OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
 if (CancelOld) OrderDelete(OrderTicket(),CLR_NONE);
  }
}

 

so aussehen...

//Pending Orders löschen
for (int i=0; i<OrdersTotal(); i++) {
if (!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue;

if (OrderSymbol() != Symbol()) continue;		
if (OrderMagicNumber() != MagicNumber) continue;
if (OrderType() != OP_SELLLIMIT) continue;
if (OrderType() != OP_BUYLIMIT) continue;

if (CancelOld) OrderDelete(OrderTicket(),CLR_NONE);
}

 

 

Da die Order Typen in MQL4 konstante Zahlenwerte haben könntet ihr auch mit diesen arbeiten

um den Code noch einfacher zu schreiben

Da

OP_BUY =0

OP_SELL =1

OP_BUYLIMIT =2

OP_SELLLIMIT =3

OP_BUYSTOP =4

OP_SELLSTOP =5

würde der Code so aussehen...

//Pending Orders löschen
for (int i=0; i<OrdersTotal(); i++) {
if (!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue;

if (OrderSymbol() != Symbol()) continue;		
if (OrderMagicNumber() != MagicNumber) continue;
if (OrderType() < 2 && OrderType() > 3  ) continue;

if (CancelOld) OrderDelete(OrderTicket(),CLR_NONE);
}

 

 

 

Verstanden?

...
if (OrderSymbol() != Symbol()) continue;
//wenn das Zutrifft also das Symbol nicht gleich das Symbol ist, 
//springe wieder zum Anfang der Schleife und nimm die nächste Order.
...

:laugh:

Posted (edited)
if (A oder B und C)

 

Bezieht sich das "und C" nur auf "B" oder auch auf "A"

Wird einfach von links nach rechts durchgegangen, oder hat das "und" Vorrang, oder...

 

Das und hat Vorrang. Sie auch die Tabelle Operator precedence in [1] (Rangfolge von oben nach unten). Aber allein schon wegen der Lesbarkeit sollten Klammern verwendet werden, egal ob notwendig oder nicht.

 

[1] Operators in C and C++

 

--

 

EDIT:

 

Das C bezieht sich nur auf sich selbst.

 

Nicht wirklich; das A bezieht sich auf sich selbst.

Edited by Buthus
Posted (edited)
[...]

Da die Order Typen in MQL4 konstante Zahlenwerte haben könntet ihr auch mit diesen arbeiten

um den Code noch einfacher zu schreiben

[...]

 

Ich habe aber bewusst den Ordertypen hingeschrieben, damit man auch verstehen kann, was da passiert. Ungeübte Leser würden sonst nämlich verwirrt, da sie evtl. nicht wissen, was ein OrderType kleiner 2 ist. Und so habe ich auch immer später nochmal die Möglichkeit, schnell im Quelltext zu sehen, was passieren soll. Zu erweitern wäre eine komplette "Pending Orders löschen" Abfrage natürlich noch um die STOP-Orders und es ist - wie schon beschrieben - die Schleife "umzudrehen".

Edited by conglom-o
Posted
Ungeübte Leser würden sonst nämlich verwirrt, da sie evtl. nicht wissen, was ein OrderType kleiner 2 ist. Und so habe ich auch immer später nochmal die Möglichkeit, schnell im Quelltext zu sehen, was passieren soll.

:laugh:

 

Das Beispiel zeigt gut, dass es nicht DEN einzig richtigen Weg/Art zu Programmieren gibt, sondern in der Regel ne ganze Menge unterschiedlicher Lösungen, die man nach verschiedenen Kriterien bewerten kann. Zum Beispiel:

 

  • Codelesbarkeit - dafür zahlt man meist den Preis, dass der Code länger und eventuell weniger performant wird
  • "Eleganz" - ist wie im wahren Leben: sieht super gut aus, aber keiner außer einem selbst versteht's :sad:. Dafür ist es meist recht schnell in der Ausführung.
  • Keines-Von-Beiden: weder sonderlich verständlich noch elegant, erfüllt aber auch seinen Zeck, wenn auch manchmal recht umständlich.

Mein Favorit ist Codelesbarkeit. Zum einen, wenn man nach mehreren Monaten selbst in die Sourcen wieder reinschauen muss, zum anderen, wenn mal jemand anderes reinschaut oder den Code verstehen soll. Für nen Quickhack für einen selbst, um mal schnell was zu testen, sind solche Abkürzungen ja ok (mach ich auch so). Leider ist nichts so hartnäckig-andauernd wie ein Provisorium (aka Quickhack), welcher dann doch plötzlich weitergereicht wird, obwohl er ursprünglich nicht dafür gedacht war.

Und derjenige, der sich dann den Code antun muss, pflückt meist mühsam alles wieder auseinander oder sitzt zumindest ewig darüber (bzw. nervt den Urheber des Codes) bis er es versteht.

Posted (edited)

Da gab es ja wieder eine Menge zu lernen.

Ich versuche immer alle geposteten Codes komplett zu verstehen und habe zwei Problemchen.

 

Buthus schreibt:

int OrdersTotalByType(int type)

{

int result = 0;

 

for (int i = OrdersTotal() - 1; i >= 0; i--)

{

if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))

{

if (0 != OrderType() & type) result++;

}

}

 

return (result);

}

 

Ist mir alles klar, bis auf diese Zeile:

if (0 != OrderType() & type) result++;

Ich denke, ich weiß, was das machen soll, result wird immer einen weiter gezählt, falls

OrderType ungleich null ist und falls es sich um den Ordertyp handelt, der der Funktion mit der Variable type mitgegeben wurde.

Aber ich verstehe die Syntax dieser Zeile nicht. Kann das jemand erklären?

result++ ist klar, aber das in der Klammer nicht.

 

FinGer schreibt:

if (!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue;

 

Hier verstehe ich nicht, warum da nicht break, sondern continue steht.

Edited by mh21
Posted
Ich denke, ich weiß, was das machen soll, result wird immer einen weiter gezählt, falls

OrderType ungleich null ist und falls es sich um den Ordertyp handelt, der der Funktion mit der Variable type mitgegeben wurde.

Aber ich verstehe die Syntax dieser Zeile nicht. Kann das jemand erklären?

ich versuchs.

Das "&" hier ist kein logisches UND (das wäre &&) sondern ein bitweises (oft auch binäres genannt) UND:

 

Bitwise operation AND of binary-coded x and y representations. The value of the expression contains 1 (TRUE) in all digits where both x and y do not contain zero; and it contains 0 (FALSE) in all other digits.

siehe http://docs.mql4.com/basis/operations/bit

Buthus arbeitet hier mit etwas fortgeschrittenen Programmiertechniken, die man nur anwenden sollte wenn man ein gutes Verständniss von der Binärdarstellung hat. Falls es dich wirklich interessiert einfach fragen, ich will dich nur nicht mit (möglicherweise) kryptischem "Expert-Blabla" zuquatschen ;)

 

Hier verstehe ich nicht, warum da nicht break, sondern continue steht.

mit break würdest du aus der for-Schleife rausspringen, wodurch alle Orders die in der Liste danach kommen würden ignoriert werden.

Mit dieser Zeile verhindert man aber nur das "fremde" Orders von diesem EA überhaupt gelesen werden.

 

"continue" bedeutet "Überspring alles was danach im Schleifenkörper steht und mach mit der nächsten Iteration weiter".

In diesem Fall also: "Ignorier diese Order und mach mit der nächsten Order (i++) weiter".

 

HTH

Posted

Würde man die Zeile von Buthus dann auch so schreiben können:

 

if (0 != OrderType() && type== OrderType() ) result++;

 

oder bin ich da aufm Holzweg?

Aber warum brauch ich überhaupt die Abfrage 0 != OrderType(), denn type ist ja eh ungleich 0.

Posted
Mit dieser Zeile verhindert man aber nur das "fremde" Orders von diesem EA überhaupt gelesen werden.

 

if (!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue

 

Ich dachte, OrderSelect() ist true, wenn eine Order gefunden wird, die die Posnummer hat, die in der for Schleife gerade abgefragt wird. Es ist also false, wenn keine Order gefunden wird. Durch das ! wird das false zu true. Es ist also true, wenn keine Order mit dieser Posnummer in der Liste der Positionen SELECT_BY_POS und den aktuellen Trades MODE_TRADES gefunden wird.

 

Wenn ich bei i keine Order finde, kann ich bei i+1 doch auch keine finden. Dachte ich. Also kann ich doch mit break aufhören.

Irgendwas habe ich ganz gründlich nicht verstanden.

Posted
Würde man die Zeile von Buthus dann auch so schreiben können:

 

if (0 != OrderType() && type== OrderType() ) result++;

 

oder bin ich da aufm Holzweg?

Aber warum brauch ich überhaupt die Abfrage 0 != OrderType(), denn type ist ja eh ungleich 0.

 

Mach wir's doch etwas kryptischer :siscop:

 

Die folgenden Definitionen standen ja in meinem ersten Beitrag dazu:

 

#define OT_BUY        1
#define OT_SELL       2
#define OT_BUYLIMIT   4
#define OT_SELLLIMIT  8
#define OT_BUYSTOP   16
#define OT_SELLSTOP  32

#define OT_TRADES     3
#define OT_PENDING   60

 

Binär sieht das ganze so aus:

 

if (0 != OrderType() & type)

welches eigentlich

if (0 != OperationToType(OrderType()) & type)

heißen sollte (kommt davon, wenn man im Forum alles neu schreibt, statt das vorhandene zu kopieren :door:), sieht das z.B. so aus:

 

Szenario: aktuelle Order ist eine Limit Buy und wir wollen wissen, ob es Pending Orders gibt

int OperationToType(int op)
{
 switch (op)
 {
   case OP_BUY:       return (OT_BUY);
   case OP_SELL:      return (OT_SELL);
   case OP_BUYLIMIT:  return (OT_BUYLIMIT);
   case OP_SELLLIMIT: return (OT_SELLLIMIT);
   case OP_BUYSTOP:   return (OT_BUYSTOP);
   case OP_SELLSTOP:  return (OT_SELLSTOP);
 }
 return (09;
}

 

Um also auf die eigentlich Frage zu antworten: Solange man auf einen bestimmten Ordertypen prüfen will, kann man es so schreiben, wie Du vorgeschlagen hast. Will man aber auf z.B. auf Pending oder Long - also auf irgendwas, was sich nicht durch einen einzigen Ordertypen beschreiben lässt - prüfen, dann ist die Bitvariante die kürzere.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...