Jump to content
Tom Next - Daytrading Community

Wir bauen ein TomNext EA für Metatrader  

60 members have voted

  1. 1. Besteht Interesse zusammen ein EA zu bauen für Metatrader??



Recommended Posts

Posted

Ok weiter gehts.

 

Da es keine Kommentare zur start() gab, würd ich sagen wir gehen weiter im Text ;)

 

Bereits "erledigt" vom Struktogramm wär damit der Teil

Ebene1 (start())

 

- Verarbeitung offener Positionen

? Eröffnung neuer Orders erlaubt?

+ JA: Überprüfe auf Signal

+ NEIN: Nix.

und aus Ebene2:

Eröffnung neuer Orders erlaubt:

? Wurde dieser Bar bereits überprüft?

+ JA: return false;

? Außerhalb der erlaubten Handelszeiten?

+ JA: return false;

? Anzahl der maximal gleichzeitigen Orders bereits erreicht?

+ JA: return false;

- return true;

Implementiert als:

void start()
{
  handleOpenOrders();
  if(isTradeAllowed()) 
    checkForOpen();
}

bool isTradeAllowed() {
  if (!EachTickMode && !isNewBar()) 
    return false;       
  if(Bars<100 || !IsTradeAllowed()) 
    return false;
  if(!isTradingTime()) 
    return false;
  if(calculateCurrentOrders() < MaxOpenOrders) 
    return true;
  else
    return false;
}

 

Als nächsten Punkt würd ich diesen vorschlagen:

Überprüfe auf Signal:

- Berechne Signalrichtung (SHORT, FLAT oder LONG)

- Berechne Filterrichtung (SHORT, FLAT oder LONG)

? Sind bereits Positionen offen?

+ JA: Ermittle Richtung dieser Positionen

? Sind Richtung von Signal und Filter unterschiedlich (oder Signal flat)?

+ JA: return

? Ist Signalrichtung ungleich der bestehenden Positionen und keine gegensätzlichen Positionen erlaubt?

+ JA: return

- Berechne InitStopentfernung

- Berechne Positionsgröße

- Berechne TPentfernung

- Öffne Position

 

Dieses Modul entspricht im wesentlichen der Funktion checkForOpen() aus Wolfs EA.

 

Hier eine leicht modifizierte Variante als mein Vorschlag für das Modul:

void checkForOpen()
{
  int res;
  int filterSignal=FLAT;
  int entrySignal =FLAT;
  double stop=0.0;
  double tp=0.0;
  double entry= 0;
  double lots= 1.0;
//---- get Signals for opening positions
  entrySignal = calcEntrySignal();
  filterSignal = calcFilterSignal();
  if(filterSignal == FLAT || filterSignal*entrySignal <= 0)
    return;
//---- open buy
  if(filterSignal + entrySignal == 2*LONG && 
     (calculateCurrentOrders() == 0 || calcOpenDirection() == LONG || HedgeAllowed)) {
  entry= Ask;
     stop=calcInitStopDiff(OP_BUY);
     lots= calcLots(stop);
     if(stop > 0)
       stop = entry - stop;
     tp=calcTPDiff(OP_BUY);
     if(tp > 0)
       tp= entry + tp;
     res = tbSendOrder(Symbol(),OP_BUY,lots,entry,3,stop,tp,"buy",MAGICNR, 0,-1);
  }
//---- open sell
  if(filterSignal + entrySignal == 2*SHORT && 
     (calculateCurrentOrders() == 0 || calcOpenDirection() == SHORT || HedgeAllowed)) {
     entry= Bid;
     stop=calcInitStopDiff(OP_SELL);
     lots= calcLots(stop);
     if(stop > 0)
       stop = entry - stop;
     tp=calcTPDiff(OP_SELL);
     if(tp > 0)
       tp= entry + tp;
     res = tbSendOrder(Symbol(),OP_SELL,lots,entry,3,stop,tp,"sell",MAGICNR, 0,-1);
  }
//----
}

 

Wie beim ersten Teil muss man hier noch die Funktionen für die tatsächliche EA-Logik erst implementieren, aber ich starte hiermit einfach mal die "Diskussionsgrundlage". Ich denk es is leichter verständlich wenn wir uns vom Groben ins Feine arbeiten und erstmal die allgemeine Programmstruktur in code fassen bevor wir dann die konkreten Logik-Funktionen angehen.

 

Freu mich wie immer auf Meinungen.

  • Upvote 4
Posted

Ich schnappe mir mal ein paar Stellen:

 

(1)

Den Funktionsnamen checkForOpen() finde ich nicht korrekt. Hier wird nicht nur geprüft, sondern auch schon geordert. Also sollte entweder die Funktion umbenannt oder die Prüfung und das Ordern getrennt werden.

 

(2)

  if(filterSignal == FLAT || filterSignal*entrySignal <= 0)

Ich liebe solche schlanken und effizienten Programmierungen. Allerdings erschweren diese die Lesbarkeit des Codes vor allem für Außenstehende, aber auch für einen selbst, wenn man länger nicht mehr drauf geschaut hat. Ich vermeide daher gerne solche Konstrukte, da sie aus Performance-Sicht in heutigen Programmiersprachen eher irrelevant sind (außer es kommt auf jede Nanosekunde an).

 

Vielleicht zur Erklärung für diejenigen Mitleser, denen sich der Sinn der Zeile nicht sofort erschließt:

Die Signale werden durch -1 (short), 0 (flat) und +1 (long) gekennzeichnet. Damit ergbit sich nachfolgende Entscheidungstabelle.

filterSignal 0, entrySignal 0 --> true

filterSignal 0, entrySignal 1 --> true

filterSignal 0, entrySignal -1 --> true

filterSignal 1, entrySignal 0 --> true

filterSignal 1, entrySignal 1 --> false

filterSignal 1, entrySignal -1 --> true

filterSignal -1, entrySignal 0 --> true

filterSignal -1, entrySignal 1 --> true

filterSignal -1, entrySignal -1 --> false

 

Heißt auf deutsch: zeigen FilterSignal und EntrySignal in die gleiche Richtung, ergibt der Ausdruck false, ansonsten ist das Ergebnis true. Im Falle von true wird mit dem return (ohne ein Entry vorzunehmen) die Funktion verlassen. Finde ich schwer zu lesen. Warum nicht einfach:

 

if !(filterSignal == entrySignal) return; 
//oder
if (filterSignal != entrySignal) return;

 

(3)

     stop=calcInitStopDiff(OP_BUY);
  lots= calcLots(stop);
  if(stop > 0)
	stop = entry - stop;
     tp=calcTPDiff(OP_BUY);
  if(tp > 0)
	tp= entry + tp;
     res = tbSendOrder(Symbol(),OP_BUY,lots,entry,3,stop,tp,"buy",MAGICNR, 0,-1);

Hierzu gleich zwei Anmerkungen:

Was soll geschehen, wenn stop oder tp 0 bzw. negativ sind? Da es sich anscheinend um Differenzwerte handelt, wird tbSendOrder mit invaliden Parametern gefüttert.

Der Aufruf von calcInitStopDiff und calcTPDiff sollte mit den nötigen Parametern geschen, sodass diese Funktionen auch losgelöst einsetzbar sind. Ich würde es gerne vermeiden, dass innerhalb dieser beiden Funktionen noch Indikatoren o.ä. ausgewertet werden. Dann ist ein späterer Austausch eher schwer.

  • Upvote 4
Posted

Juhu Beteiligung :shakehands: ;)

 

(1)

Den Funktionsnamen checkForOpen() finde ich nicht korrekt. Hier wird nicht nur geprüft, sondern auch schon geordert. Also sollte entweder die Funktion umbenannt oder die Prüfung und das Ordern getrennt werden.

guter Punkt, ich wär dafür es in einer Funktion zu lassen. wie wärs mit checkAndHandleSignals() ?

 

Ich liebe solche schlanken und effizienten Programmierungen. Allerdings erschweren diese die Lesbarkeit des Codes vor allem für Außenstehende, aber auch für einen selbst, wenn man länger nicht mehr drauf geschaut hat. Ich vermeide daher gerne solche Konstrukte, da sie aus Performance-Sicht in heutigen Programmiersprachen eher irrelevant sind (außer es kommt auf jede Nanosekunde an).

hoppla, hast natürlich recht. Ich merks schon gar nimmer, vermutlich ne Berufskrankheit ;)

 

also so?

if(filterSignal == FLAT || filterSignal != entrySignal)
 return;

 

Was soll geschehen, wenn stop oder tp 0 bzw. negativ sind?

hoppla... um sicher zu gehen sollte es wohl eher so heißen:

if(stop > 0)
 stop = entry - stop;
else
 stop= 0;

Die calcStop soll auch die Möglichkeit haben ein "kein Stop" zurückzugeben, was einer Stopdiff von 0 entspricht. Wär dann konsistent mit dem Parameter für die OrderSend.

 

Der Aufruf von calcInitStopDiff und calcTPDiff sollte mit den nötigen Parametern geschen, sodass diese Funktionen auch losgelöst einsetzbar sind. Ich würde es gerne vermeiden, dass innerhalb dieser beiden Funktionen noch Indikatoren o.ä. ausgewertet werden. Dann ist ein späterer Austausch eher schwer.

ich hätts genau umgekehrt gesehen.

Wenn man ihnen Logikspezifische Parameter dazugibt, muss man im Fall einer Änderung der Logik, den Code hier auch ändern. Im aktuellen Fall ist der "checkForOpen" egal wie die "calcInitStopDiff" zu ihrem Wert kommt, geht sie genaugenommen ja auch nix an. Somit kann man innerhalb der calcInitStopDiff jederzeit was ändern ohne das man hier nachbessern muss. Ändert man später die Logik für den Stop, ändert man nur diese eine Funktion, und nix drumherum...

oder versteh ich dich falsch?

 

Innerhalb der calcInitStopDiff kann man dann die Entscheidung "welchen Stopp verwenden wir?" etc. einbauen...

  • Upvote 1
Posted

wie wärs mit checkAndHandleSignals() ?

Passt besser.

 

also so?

if(filterSignal == FLAT || filterSignal != entrySignal)
 return;

Finde ich besser lesbar.

 

if(stop > 0)
 stop = entry - stop;
else
 stop= 0;

Die calcStop soll auch die Möglichkeit haben ein "kein Stop" zurückzugeben, was einer Stopdiff von 0 entspricht. Wär dann konsistent mit dem Parameter für die OrderSend.

Finde ich in Ordnung. Allerdings muss dann darauf geachtet werden, dass calcStop nicht unabsichtlich 0 zurückliefert, was "keinem Stop" entsprechen würde. Wie sieht es eigentlich mit einer Prüfung des Mindestabstands von SL und TP zum aktuellen Kurs aus? Manche Broker lassen keine Platzierung zu, wenn sie zu dicht liegen. Andere Broker hingegen lassen erst nach einem Order-Fill das Anhängen von SL und TP zu. Beachtet das dann die tbSendOrder-Funktion?

 

Im aktuellen Fall ist der "checkForOpen" egal wie die "calcInitStopDiff" zu ihrem Wert kommt, geht sie genaugenommen ja auch nix an. Somit kann man innerhalb der calcInitStopDiff jederzeit was ändern ohne das man hier nachbessern muss. Ändert man später die Logik für den Stop, ändert man nur diese eine Funktion, und nix drumherum...

Hast Recht. So rum ist es nachher doch einfacher, den Baustein auszutauschen.

Posted

Finde ich in Ordnung. Allerdings muss dann darauf geachtet werden, dass calcStop nicht unabsichtlich 0 zurückliefert, was "keinem Stop" entsprechen würde. Wie sieht es eigentlich mit einer Prüfung des Mindestabstands von SL und TP zum aktuellen Kurs aus? Manche Broker lassen keine Platzierung zu, wenn sie zu dicht liegen. Andere Broker hingegen lassen erst nach einem Order-Fill das Anhängen von SL und TP zu. Beachtet das dann die tbSendOrder-Funktion?

 

Also wenn die calcStop "unabsichtlich" stop

zu den Mindestabständen: die tbSendOrder überprüft das automatisch und setzt stop und tp so nahe wie möglich an das gewünschte Level. Wenn gar keine Stops beim eröffnen gesetzt werden dürfen, gibt die TB derzeit glaub ich einfach nach x versuchen auf. das müsste man dann ggf. für den konkreten Broker anpassen. Is mMn ein sehr spezielles Problem, das hier gleich allgemein zu lösen (mit Parameter etc.) bläst den Code eher unnötig auf oder?

Posted

Is mMn ein sehr spezielles Problem, das hier gleich allgemein zu lösen (mit Parameter etc.) bläst den Code eher unnötig auf oder?

Da hieße, dass ich bspw. auf meinem Flatex-CFD-Forex-Account den EA nicht laufen lassen könnte. Aber ich habe genügen Alternativen :wink2: Letztlich gehört die spezielle Orderbehandlung in Abhängigkeit von Broker-Eigenheiten mit in die tbSendOrder. Kommt mit auf die ToDo-Liste für - äh - 2013 :hourglass:

Posted
Letztlich gehört die spezielle Orderbehandlung in Abhängigkeit von Broker-Eigenheiten mit in die tbSendOrder. Kommt mit auf die ToDo-Liste für - äh - 2013 :hourglass:

 

Stimmt, am schönsten wär ein Parameter bei der tbSendOrder, sodass die Stops einmal direkt beim eröffnen mitgesendet, einmal nachträglich gesetzt werden.

bzw. gar nicht zur tbSendOrder sondern ein "globaler" Parameter in der TradeBox den man im init() setzt so wie das infolevel. Damit wär hier keine Codeänderung nötig ;)

Posted (edited)

Stimmt, am schönsten wär ein Parameter bei der tbSendOrder, sodass die Stops einmal direkt beim eröffnen mitgesendet, einmal nachträglich gesetzt werden.

bzw. gar nicht zur tbSendOrder sondern ein "globaler" Parameter in der TradeBox den man im init() setzt so wie das infolevel. Damit wär hier keine Codeänderung nötig ;)

Ich wollte Euch auf eine Funktionssammlung namens common_function.mqh aufmerksam machen, wo genau dies mit der Konstanten "IS_ECN_BROKER" gelöst wird.

 

Unter dem Thread "3rd Party Tools"/"Interessantes Projekt 7bit" #5 steht etwas dazu.

 

hier nochmal der Link und eine Anmerkung dazu:

 

Unter https://sites.google.com/site/prof7bit/common_functions bzw. der Dokumentation hierzu http://7bit.99k.org/common__functions_8mqh.html

gibt es eine Sammlung von allgemeinen Funktionen, die über die Funktionen des reinen Order-Managements einige interessante Goodies bieten.

 

z.B. die print(string text, bool clear)-Funktion, mit der man bis zu 20 Debug-Ausgaben auf das Chart-Window schicken kann

...

Edited by Der Wolf
Posted

Und wiedermal ein sorry von mir für die Funkstille. Bin derzeit beruflich jede Woche ein paar Tage Graz wo gar nix geht, und daheim geht leider auch recht wenig weil dann natürlich die liegen gebliebenen Dinge gemacht werden wollen.

 

Da es keine weiteren Meldungen zum letzten Codeblock gab, hier die "finale" Version zur "Abstimmung" :

 

void checkAndHandleSignals()
{
  int res;
  int filterSignal=FLAT;
  int entrySignal =FLAT;
  double stop=0.0;
  double tp=0.0;
  double entry= 0;
  double lots= 1.0;
//---- get Signals for opening positions
  entrySignal = calcEntrySignal();
  filterSignal = calcFilterSignal();
  if(filterSignal == FLAT || filterSignal != entrySignal)
    return;
//---- open buy
  if(filterSignal + entrySignal == 2*LONG && 
     (calculateCurrentOrders() == 0 || calcOpenDirection() == LONG || HedgeAllowed)) {
  entry= Ask;
     stop=calcInitStopDiff(OP_BUY);
     lots= calcLots(stop);
     if(stop > 0)
       stop = entry - stop;
     else
       stop= 0;
     tp=calcTPDiff(OP_BUY);
     if(tp > 0)
       tp= entry + tp;
     else
       tp= 0;
     res = tbSendOrder(Symbol(),OP_BUY,lots,entry,3,stop,tp,"buy",MAGICNR, 0,-1);
  }
//---- open sell
  if(filterSignal + entrySignal == 2*SHORT && 
     (calculateCurrentOrders() == 0 || calcOpenDirection() == SHORT || HedgeAllowed)) {
     entry= Bid;
     stop=calcInitStopDiff(OP_SELL);
     lots= calcLots(stop);
     if(stop > 0)
       stop = entry - stop;
     else
       stop= 0;
     tp=calcTPDiff(OP_SELL);
     if(tp > 0)
       tp= entry + tp;
     else
       tp= 0;
     res = tbSendOrder(Symbol(),OP_SELL,lots,entry,3,stop,tp,"sell",MAGICNR, 0,-1);
  }
//----
}

 

wegen Namensänderung wird somit start angepasst:

void start()
{
  handleOpenOrders();
  if(isTradeAllowed()) 
    checkAndHandleSignals();
}

 

Als nächstes fehlt eh nur mehr ein Punkt im Struktogramm:

Verarbeitung offener Positionen:

Für alle offenen Positionen

- ziehe TrailingStop/Breakeven nach

? Position aufgrund von Timeout zu schließen?

+ JA: schließe Pos und geh zur nächsten.

? Position aufgrund von Zeitfilter zu schließen?

+ JA: schließe Pos und geh zur nächsten.

 

@Wolf: hab dich nicht überlesen. Danke für den Hinweis. Mir fehlt derzeit leider die Zeit mir die Bibliothek anzuschauen. Aber klingt interessant.

Posted

@Wolf: hab dich nicht überlesen. Danke für den Hinweis. Mir fehlt derzeit leider die Zeit mir die Bibliothek anzuschauen. Aber klingt interessant.

kein Problem, neben der Funktion "print(..., ...)", die ich für's Testen intensiv nutze habe ich zwar einige nützliche weitere Funktionen der common_functions ausprobiert, die eigentlichen Order-Funktionen habe ich bisher mangels Zeit auch nur kurz angetestet.

 

Das gehört ja eigentlich auch nicht in diesen Thread, ich habe die common_funktions in diesen Thread nur reingebracht, weil hier ECN-Broker-Eigenheiten angesprochen wurden, bei denen man sich evtl. von den common_functions inspirieren lassen könnte.

 

Noch eine Anregung meinerseits, die eigentlich allgemeiner Natur ist, aber vielleicht im Sinne der Entwicklung eines SW-Projektes gerade gut an dieser Stelle in dieses Projekt hineinpasst:

In meinen jüngsten EA's habe ich bisher als Orderfunktionalität eigene MT4-Orderfunktionen oder die TradeBox-Orderfunktionen direkt eingebaut.

 

Demnächst werde ich meine EA's dahingehend umschreiben, daß ich nicht die TradeBox-Orderfunktionen direkt aufrufe, sondern eigene "Funktions-Hüllen" als Orderfunktionen aufrufen werde, also z.B. myBuy(...), myBuyStop(...), myBuyLimit(...), mySell(...) u.s.w.

 

Innerhalb dieser Funktions-Hüllen kann ich dann Order-Funktionalitäten entweder aus der TradeBox, den common_funktions.mqh, einer evtl. dritten fremden Funktionssammlung oder einer zukünftig eigenen Funtkionssammlung aufrufen. Dazu brauche ich nur eine Variable bzw. Konstante definieren, um dementsprechend "switchen" zu können.

 

Der große Vorteil wäre: in den verschiedenen EA-Quellcode's muss ich so gut wie keine Änderungen mehr vornehmen, d.h. ich kann per Switch (oder externem Paramter) Orderfunktionalitäten aus verschiedenen, austauschbaren Bibliotheken nutzen - und evtl. auch gegeneinander testen !

 

Fazit:

==> Vielleicht "nehmt ihr den Ball auf" - und wenn auch nur im Hinterkopf - und gar nicht auf dieses Projekt bezogen.

 

Je abstrakter man derartige Dienst-Funktionen definiert, umso mehr Freiheiten hat man später bei möglichen Erweiterungen !

 

Wie gesagt, nur als Anregung verstehen - vielleicht selbst für spätere Projekte anwenden - ich bau solche "Funktions-Hüllen" auch nicht sofort ein, aber spätestens bei der zweiten Alternative !

Posted
sondern eigene "Funktions-Hüllen"

 

Ernten 4.2. (dazu an anderer Stelle mehr ) arbeitet mit 2 #Include :

 

Dabei ruft der EA Funktionen auf, die die Order vorbereiten , d.h. die individuellen Variablen belegt werden :

 

     OrderSelect (B21,SELECT_BY_TICKET)         ;//                                               |
    if ((B21 == 0 || OrderCloseTime() > 0) && ( Mas_Tip[4] == 0))   //                           |
      {                                         //                                               |
       Alert("B21 Open aus Hauptprogramm")     ;//                                               |
       Pair1_B21();return                      ;//                                               |
      }                                         //                                               |

 

Pair1_B21() bedeutet, dass die erste Buy-Order aufgerufen werden soll (es können bis zu 5 werden)

 

In Pair_B21() geschieht nun folgendes :

 

//-------------------------------------------------------------------------------------------------+
int Pair1_B21()                                  //                                                |
{                                                //                                                |
bool PRT = (Bars > bb && hilfe)                ;//                                                |
double Entry = CurrentEnterLong                ;//                                                |
if (OrderSelect (B21,SELECT_BY_TICKET) == true )// gibt oder gab es je einen B21 ?                |
  {                                             //                                                |
   if (OrderCloseTime() == 0 )                  // ja , auch aktiv oder schon geschlossen ?       |
     {                                          //                                                |
      return(0)                                ;// dann braucht keiner mehr gesetzt werden        |
     }                                          //                                                |
  }                                             // Flag im Commenttext setzen 1= Handel , 0=Hedge |
if(Long == 1)string text = "1 B21 @ Time ="+ jetzt +" dAsk = "+dAsk;//                            |
if(PRT ) Print(text,",CurrentEnterLong=",Entry,",SL = ",ip_dSL,",TP=",(Entry+TPLong*Point));//    |
                                                //                                                |
        B21 = OrderEx( Symbol()                ,//                                                |
                       OP_BUYSTOP              ,// int (0 B , 1 S , 2 BL , 3 SL , 4 BS , 5 SS )   |
                       Lots                    ,// Volumen , double                               |
                       Entry                   ,// Entrypreis                                     |
                       Slippage                ,// Slip , int                                     |
                       ip_dSL                  ,// SL , double                                    |
                       Entry+TPLong*Point      ,// TP , double                                    |
                       text                    ,// Comment , strg                                 |
                       ER_MAGIC_B21            ,// Magic , int                                    |
                       0)                      ;// Expiration , datetime                          |
                                                //                                                |
                                                //                                                |
        if (B21>-1)                             // Benachrichtigen das alles OK                   |
       {                                        //                                                |
        Alert("2 START Trade B21 aus TradePair1_B21") ;//                                         |
       }                                        //                                                |
        else                                    //   irgend etwas ist schief gegangen             |
       {                                        //                                                |
        Print("FAIL Start B21 at : ", jetzt ,   //                                                |
              " /Code = ",B21," /dAsk = ",dAsk ," /dBid = ",dBid ,            //                  |
              "/ Entry = ",Entry,"/ SL= ",ip_dSL,"/ TP = ",(Entry+TPLong*Point));//               |
        Alert(" FAIL B21 , Code =",B21)        ;//                                                |
        deinit()                               ;//                                                |
       }                                        //                                                |
                                                //                                                |
      return(0)                                ;//                                                |
 }                                              //                                                |
//+------------------------------------------------------------------------------------------------+

 

In der Zeile "B21 = OrderEx( Symbol() " beginnt die Orderbelegung und die Funktion OrderEx() führt dann in einer

weiteren Funktion OrderEx() , den eigentlichen Entry durch .

 

Oben schon erwähnt, Ernten kann max 5 Long oder 5 Short in den Markt legen . Die Ordervorbereitung liegt in einer

Include schlicht um Übersichtlichkeit zu wahren . Dann das Durchführen der Order selber , Ordersend in der Funktion

"OrderEx()" , Orderclose , Ordermodify (Mythos Tradebox hier) und Orderdelete , sind in einer weiteren Include gehalten .

 

KB

  • Upvote 1
Posted

@Funktionshüllen: An sich find ich so einen Aufbau sehr gut, eben genau aus dem Grund das man bei späteren Änderungen den bestehenden Code möglichst wenig anpassen muss. Aber man muss mMn auch darauf achten das es nicht zuviel des Guten wird. IMHO reicht eine Ebene völlig aus. Also im EA wird eine Funktion zum senden der Order aufgerufen. In dieser Funktion wird dann die Order gesendet und nicht wieder per Weiche entschieden welche andere Lib aufgerufen wird. Wenn man im Laufe der Zeit draufkommt das diese Funktion was anderes tun sollte, kann man sie ja anpassen. Ansonsten wirds (vor allem für so simple Programme wie EAs) ein extremer Strukturoverhead.

Das schöne an openSource Geschichten is aber, das sich jeder den Code anpassen kann wie er will ;)

Posted
IMHO reicht eine Ebene völlig aus

 

Das finde ich auch . In diesem Fall , Ernten , stand ich vor dem Problem, dass ich 10 Orders , 5 B und 5 S ,individuell platzieren will um diese dann (in meinen Träumen) individuell steuern (TP/SL) zu können . Wie an anderer Stelle zu lesen, wäre ich heute froh, wenn ich schonmal einen Trade in den TP treiben könnte . Dieser Nachsatz/Post für den Fall, dass jemand zufällig eine Lösung in seiner Box hat, wie man "Pair1_B21()" so coden kann, dass eine oder zwei Fkten denselben Zweck erfüllen könnten . Ist aber sicher kein Schwerpunkt , mehr meine Neugierde . KB

Posted
Sorry Leute, bin in den letzten Wochen kaum dazu gekommen hier rein zu schauen. Sieht ja bisher ganz gut aus. Wenn es okay ist, steige ich tiefer mit ein, wenn es um die Abhandlung der Trades bzw. um Definieren des MM geht.
Posted
Wenn es okay ist, steige ich tiefer mit ein, wenn es um die Abhandlung der Trades bzw. um Definieren des MM geht.

 

Natürlich, zugegebenermaßen gehts im Moment mehr um das "langweilige" Gerüst rundherum. Aber damit sind wir auch demnächst durch (fehlt nur noch 1 Block), dann gehts an die spannenden Details wo die Logik implementiert wird.

 

Zeigt für die "Neulinge" natürlich auch sehr gut, wieviel rundherum zu beachten ist, das nichts mit der Entry/Exitlogik zu tun hat. Aber ohne das rundherum wird der EA nicht lauffähig ;)

Posted

Verarbeitung offener Positionen:

Für alle offenen Positionen

- ziehe TrailingStop/Breakeven nach

? Position aufgrund von Timeout zu schließen?

+ JA: schließe Pos und geh zur nächsten.

? Position aufgrund von Zeitfilter zu schließen?

+ JA: schließe Pos und geh zur nächsten.

Zum Timeout: sollte dieser in Stunden/Minuten oder besser in Anzahl Bars angegeben werden? Ich bin für die Anzahl an vergangenen Bars, da somit der Wechsel des Timeframes indirekt berücksichtigt wird.

 

Dann zu Zeitfilter: Einen Zeitfilter finde ich schwer paramatrisierbar. Wahrscheinlich wird dieser hardcoded in einer eigenständigen Funktion am besten aufgehoben sein. Nur so lassen sich Wochentage/Abendstunden/Nachtstunden einfach definieren.

 

@Mythos: Könntest du bei deinen wöchentlichen Reports bitte den derzeitigen Code immer unten mit anhängen? Ich tue mich gerade schwer, die bislang verabschiedeten Fragmente zusammenzusetzen. Auch wenn der Code noch nicht lauffähig ist, wäre es für mich eine große Hilfe :biggrin: Deinen aktuellen Codevorschlag kannst du dann mit (Kommentar) darunter packen. Den aktuellen Codebaustein kannst du in deinem Post ja dennoch darstellen. Dann kann man den Thread gut lesen und wenn man was machen will, downloaded man einfach den aktuellen Gesamtcode.

Posted

Zum Timeout: sollte dieser in Stunden/Minuten oder besser in Anzahl Bars angegeben werden? Ich bin für die Anzahl an vergangenen Bars, da somit der Wechsel des Timeframes indirekt berücksichtigt wird.

Klingt gut.

 

Dann zu Zeitfilter: Einen Zeitfilter finde ich schwer paramatrisierbar. Wahrscheinlich wird dieser hardcoded in einer eigenständigen Funktion am besten aufgehoben sein. Nur so lassen sich Wochentage/Abendstunden/Nachtstunden einfach definieren.

Ja, den Zeitfilter hätt ich auch als eigene Funktion ähnlich wie "isTradingTime" gesehen.

 

@Mythos: Könntest du bei deinen wöchentlichen Reports bitte den derzeitigen Code immer unten mit anhängen?

 

bitte sehr ;)

eTomNextCommunity.mq4

(EDIT: hab die Struktogrammteile dazugefügt)

Code is nicht lauffähig, da fehlen noch die Funktionen und externen Parameter.

Posted

Mangels anderer Vorschläge stell ich mal eine Quick and Dirty Version als Diskussionsgrundlage rein.

 

Es geht darum:

Verarbeitung offener Positionen:

Für alle offenen Positionen

- ziehe TrailingStop/Breakeven nach

? Position aufgrund von Timeout zu schließen?

+ JA: schließe Pos und geh zur nächsten.

? Position aufgrund von Zeitfilter zu schließen?

+ JA: schließe Pos und geh zur nächsten.

 

Ich hab die Reihenfolge umgedreht (wozu trailen, wenn pos sowieso geschlossen wird ;)

void handleOpenOrders() {
  double stop=0;
  int index= 0;
  for(index= OrdersTotal() -1;index >= 0;index--) {
   if(OrderSelect(index,SELECT_BY_POS,MODE_TRADES)==false) 
     break; //some error
   if(OrderMagicNumber() != MAGICNR || OrderSymbol()!=Symbol()) 
     continue;
   //handle only open orders
   if(OrderType() != OP_BUY && OrderType() != OP_SELL)
     continue;
   
   //check timeout and Timefilter
   if(isTimeOut(OrderOpenTime())){
     tbCloseOrder(OrderTicket(),OrderLots(),3);
     continue;
   }    
   
   //do trailing
   stop= OrderStopLoss();
   stop= calcNewTrailingStop(stop,OrderType());
   //check for breakeven
   if(isBreakEven(OrderOpenPrice(),OrderType())) {
     if(OrderType() == OP_BUY) 
        stop= MathMax(stop,OrderOpenPrice());
     if(OrderType() == OP_SELL)
        stop= MathMin(stop,OrderOpenPrice());
   }
   if(NormalizeDouble(stop - OrderStopLoss()) != 0)
     tbModifyOrder(OrderTicket(),OrderOpenPrice(),stop,OrderTakeProfit(), OrderExpiration());
 }  
}

Posted

Ich hangel mich dann mal durch:

 

   if(OrderSelect(index,SELECT_BY_POS,MODE_TRADES)==false) 
     break; //some error

Warum im Fehlerfall ganz aus der Schleife? Mal davon abgesehen, dass ich gar nicht wüsste, was da schief gehen könnte, so könnte man doch ruhig mit der nächsten Position weitermachen, oder?

 

 

   //check timeout and Timefilter
   if(isTimeOut(OrderOpenTime())){
     tbCloseOrder(OrderTicket(),OrderLots(),3);
     continue;
   }    

Oh, ist das hier nicht ein sowohl typischer, wie auch gemeiner Fehler!? Ich habe 10 offene Positionen, also geht die Schleife von 9 bis 0. Nun bin ich z.B. bei Pos 5, die geschlossen wird. Danach würde die Schleife mit Nummer 4 weiter machen. Wer sagt denn, dass die 4 überhaupt die nächste Order ist und nicht nochmals die 5 (weil andere nachgerückt sind). Das hängt von der Sortierung der internen Positionsliste ab. Und die ist abhängig von der Sortierung der Positionsliste in der GUI(!) im MT4. Also nichts, worauf man sich verlassen könnte. Oder sehe ich das falsch?

 

   //check for breakeven
   if(isBreakEven(OrderOpenPrice(),OrderType())) {

Wie ist denn isBreakEven angedacht? Auf BE nachziehen, wenn x Punkte im Plus?

 

Ansonsten hätte ich nur Kleinigkeiten, will aber hier nicht der Erbsenzähler sein. So z.B.:

Warum wird index initialisiert, wenn die Variable in der Schleife schon initialisiert wird? Auch stop bräuchte keinen Initialwert. Die erste Zuweisung von stop ist dann auch noch überflüssig und könnte in der Zeile danach direkt erfolgen.

Posted

   if(OrderSelect(index,SELECT_BY_POS,MODE_TRADES)==false) 
     break; //some error

Warum im Fehlerfall ganz aus der Schleife? Mal davon abgesehen, dass ich gar nicht wüsste, was da schief gehen könnte, so könnte man doch ruhig mit der nächsten Position weitermachen, oder?

Dieser Codeteil stammt aus einem Metaquotes-Sample-Programm.

Es spricht im Pirnzip nichts dagegen, mit continue weiterzumachen, aber dann würde ich zuvor mit GetLastError() zumindest der Fehler protokollieren bzw. weiter untersuchen.

Posted

   if(OrderSelect(index,SELECT_BY_POS,MODE_TRADES)==false) 
     break; //some error

Warum im Fehlerfall ganz aus der Schleife? Mal davon abgesehen, dass ich gar nicht wüsste, was da schief gehen könnte, so könnte man doch ruhig mit der nächsten Position weitermachen, oder?

Da is die Frage was genau falsch ist. Normal sollte es kein Problem geben, aber da OrderSelect die Möglichkeit hat "einen Fehler zu zeigen", dann sollte man ihn mMn auch behandeln. Ich behandle es immer als ein "Fatal Error", sprich "Wenn beim selektieren was daneben geht, is irgendwas gerade falsch-> Normaler Funktionsablauf sinnlos".

 

Oh, ist das hier nicht ein sowohl typischer, wie auch gemeiner Fehler!? Ich habe 10 offene Positionen, also geht die Schleife von 9 bis 0. Nun bin ich z.B. bei Pos 5, die geschlossen wird. Danach würde die Schleife mit Nummer 4 weiter machen. Wer sagt denn, dass die 4 überhaupt die nächste Order ist und nicht nochmals die 5 (weil andere nachgerückt sind). Das hängt von der Sortierung der internen Positionsliste ab. Und die ist abhängig von der Sortierung der Positionsliste in der GUI(!) im MT4. Also nichts, worauf man sich verlassen könnte. Oder sehe ich das falsch?

AFAIK: Die Sortierung ist zufällig, aber nicht so schnell wechselnd. Sprich es wird nicht durchs Schließen neu gereiht/sortiert. Das Problem das mir schön öfters untergekommen ist, passiert bei aufsteigendem durchlaufen. Denn wenn ich Ordernr. 3 schließe, rückt die aktuelle 4 auf Platz 3 nach und ich darf nicht als nächstes die 4 betrachten, sondern müsste die 3 nochmal anschauen. Deswegen ist hier das durchlaufen von oben sinnvoller.

Zugegeben könnt ich dir jetzt nicht garantieren das es immer funktioniert. Aber ggf. wirds beim nächsten Tick alles überprüft.

Alternative wäre nur alle OrderTickets die geschlossen werden sollen, zu merken und danach zu schließen. Wär natürlich sauberer.

 

Wie ist denn isBreakEven angedacht? Auf BE nachziehen, wenn x Punkte im Plus?

 

Aus Zusammenfassungspost Nr. 171 (werd den Inhalt dann auch in den EA packen)

Breakeven nach Anstieg um x*ATR

 

Ansonsten hätte ich nur Kleinigkeiten, will aber hier nicht der Erbsenzähler sein. So z.B.:

Warum wird index initialisiert, wenn die Variable in der Schleife schon initialisiert wird? Auch stop bräuchte keinen Initialwert. Die erste Zuweisung von stop ist dann auch noch überflüssig und könnte in der Zeile danach direkt erfolgen.

 

Ja, das sind mMn ein bissl "Glaubensfragen". Ich initialisier gern aus Prinzip um unerwünschtes Verhalten und dumme Fehler zu verhindern. (außer auf Mikrokontroller wenns um speed geht ;)

Beim Stop könnte man es kürzen, stimmt.

 

Wie gesagt, war ein bissl Quick and Dirty :white_flag:

 

btw. ihr dürft gern auch selber Codeblöcke vorschlagen/meinen anpassen. Muss ja nit alles meine Handschrift haben ;)

Posted

Ok, da es keine weiteren Meldungen gibt, hier mal die aktualisierte Version.

Ich hab auch gleich Platzhalter für die Logik-Funktionen eingebaut damit das ganze kompiliert.

(gsd hat vorher niemand bemerkt das in MQL das return anders aussieht als in java :punishR: )

 

Aus meiner Sicht wär der strukturelle Teil fertig und es folgt die Logik.

Falls wir unterwegs merken das wir was übersehen haben können wirs ja ändern.

 

Da ich ein bissl das Einschlafrisiko bei der Beteiligung sehe, stellt sich die Frage ob wir in dem Stil weitermachen, oder einfach die verschiedenen Logik-Funktionen jetzt aufteilen und in einer Woche den ersten Test fahren. Was meint ihr?

 

Die Funktionen wären folgende:

(KB) bool isTradingTime()    //nicht unbedingt notwenig, aber bereits vorbereitet für Zeitfilter
int calcEntrySignal()   //check ob Heiken Ashi gedreht hat
(KB 26.12.)int calcFilterSignal()  //check ob MAs auf höherer Ebene entsprechenden Abstand haben
(Wolf) double calcInitStopDiff(int orderType) // Berechnung des Chandelier
double calcTPDiff(int orderType)  // calc des TP 
double calcLots(double stopDiff)  // Lotsizeberechnung nach abhängig von externem Parameter
(Wolf) double calcNewTrailingStop(double curStop,int orderType) // trail des stops
bool isBreakEven(double openPrice,int orderType) // check ob BreakEven-Trigger erreicht
(KB 26.12.)bool isTimeOut(datetime openTime,int orderType)  // check ob Timout-Trigger erreicht

 

Ein paar der Funktionen sind sicher sehr schnell geschrieben. Die beinhaltende Logik und "gewünschten" Returnwerte sollten eigentlich selbsterklärend bzw. im Kommentar über der Funktion (im Source) stehen. ggf. einfach fragen. Es wird sicher einige Externe Parameter geben die wir noch einfügen müssen. Sofern es Parameter gibt die in mehreren Modulen verwendet werden (zB ATR-Period), werden wirs ggf. nachträglich abgleichen.

 

Hier noch der aktuelle Code:eTomNextCommunity.mq4

 

und jetzt einen schönen 3. Advent ;)

  • Upvote 5
Posted
Was meint ihr?

 

:hmmmm: vorweihnachtlicher Stress oder gesunkene Motivation in der Mannschaft?

 

eigentlich hatte ich auf ein paar Wortmeldungen und/oder Freiwillige gehofft...

 

dann mal einen schönen 4. Advent...

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...