Zum Inhalt springen
View in the app

A better way to browse. Learn more.

#T/N/X/T

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Programmierung eines EA mit eigenen Indikatoren

Geschrieben

Hallo an alle,

 

ich möchte eine EA programmieren, der folgendermaßen funktionieren soll:

 

Gekauft wird wenn der RSI im überverkauften Bereich ist und der Schlusskurs außerhalb des Keltnerchannels liegt. Verkauft ist dann so ziemlich das gegenteil.

Jetzt weiß ich nur nicht so genau wie ich die ganzen Variabeln angeben muss. Die Indikatoren habe ich auf mql4.com heruntergeladen.

 

Also mein code sieht momentan so aus, habe ich das mit dem Include befehl richtig gemacht?

 

#property copyright "blabla"

#property link ""

 

//---- input parameters

extern double Lots=1.0;

extern double Fixed_Sl=10.0;

extern double TakeProfit=20.0;

extern double Trailing_Sl=5.0;

#include "indicators\RSI.mq4"

#include "indicators\Keltner_Channel.mq4"

 

wie gebe ich jetzt den aktuellen wert des RSI an?

Ich möchte jetzt im folgenden schritt ja testen lassen ob der RSI aktuell unter 30 ist und der priceclose außerhalb des keltnerchannels liegt.

 

 

Danke im Voraus :wub:

Featured Replies

Geschrieben

Hallo erstmal :wub: und willkommen bei Tom-Next.

 

 

Zu Deiner Frage:

 

Du muss unterscheiden, ob Du technische Indikatoren verwenden willst (die gibt's quasi eingebaut bei Metatrader mit dazu, Bsp: MACD, RSI usw., ic.arrow.right.png Mehr zu technischen Indikatoren) oder aber sogenannte Custom-Indikatoren (quasi was Selbsterdachtes, ic.arrow.right.png Mehr zu Custom-Indikatoren).

 

Beim RSI, wenn Du ihn unverändert (vom Code her) nutzen willst, brauchst Du auch keinen Code runterzuladen, nix zu includen usw. Einfach nur verwenden, wie in der Doku beschrieben ( http://docs.mql4.com/indicators/iRSI ), allerdings mit nem kleinen 'i' vorne dran (steht für 'Indikator'):

double iRSI( string symbol, int timeframe, int period, int applied_price, int shift)

 

Calculates the Relative strength index and returns its value.

 

Parameters:

symbol - Symbol the data of which should be used to calculate indicator. NULL means the current symbol.

timeframe - Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe.

period - Number of periods for calculation.

applied_price - Applied price. It can be any of Applied price enumeration values.

shift - Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).

 

Sample:

 

if(iRSI(NULL,0,14,PRICE_CLOSE,0)>iRSI(NULL,0,14,PRICE_CLOSE,1)) return(0);

 

Du kannst auch mal im Metaeditor, wenn Du ne offene Datei hast Strg+Space drücken, um Dir ne Liste aller Funktionen, Variablen, Indikatoren etc. anzeigen zu lassen, die Dir aktuell zur Verfügung stehen.

 

Willst Du hingegen selbst am Code schrauben oder nen eigenen Indikator vom EA aus verwenden, kannst Du auf den Indikatorwert mittels der iCustom-Funktion zugreifen.

ic.arrow.right.png Weitere Erklärungen zur Verwendung der iCustom-Funktion.

Geschrieben

Hallo,

 

So ist das Falsch.

Mit #include lädst du keine Indikatoren.

 

Für den Keltnerchannels Indikator benutzt du

double iCustom( string symbol, int timeframe, string name, ..., int mode, int shift)

und für den RSI benutzt du.

double iRSI( string symbol, int timeframe, int period, int applied_price, int shift)

 

Ich Empfehle dir deinen EA mit dem Expert Advisor Builder zu erstellen.

Und dann schaust du dir diesen generierten MQL4 code genau an um zu verstehen.

 

--

Capture_135.gif

Geschrieben
@Krümel bist schneller gewesen... :sad:
:sad: Ich bin so schnell, weil der Chef mir jeden Morgen nen Energy-Drink in den Kaffee schüttet :wub: .
Geschrieben
  • Autor

Danke für die schnellen Antworten :)

 

Zuerstmal noch eine Frage zum RSI: Was bedeutet shift?

 

shift - Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).

 

if(iRSI(NULL,0,14,PRICE_CLOSE,0)>iRSI(NULL,0,14,PRICE_CLOSE,1)) return(0);

 

shift müsste doch in diesem beispiel die zahl hinter dem price_close sein, aber was heißt das?

 

Beim iCostum leuchtet mir folgendes noch nicht ganz ein:

 

... - List of parameters (if needed). Passed parameters must correspond with the order of declaring and the type of external variables of a custom indicator.

 

mode - Index of an indicator line. Can be from - to 7 and must correspond to the index used by any of SetIndexBar functions.

 

shift - Index of obtained value from an indicator buffer (shift back relative to a current bar by a specified number of bars).

 

 

So sieht mein code bisher aus:

//---- input parameters
extern double    Lots=5.0;
extern double    Fixed_Sl=10.0;
extern double    TakeProfit=20.0;
extern double    Trailing_Sl=5.0;
extern int RSIperiod=14;


int start()
 {
  iCustom (NULL, PERIOD_H1, string Keltner_Channel, periodMA, periodATR, kshift, int mode, int shift)
  iRSI (NULL, PERIOD_H1, RSIperiod, PRICE_CLOSE,0)
  
  }

 

Beim icustom habe ich bei list of parameters genau die Inputs des KeltnerChannel eingetragen aber bei mode und shift weiß ich nicht mehr weiter, könnt ihr mir da helfen?

 

EDIT: Muss ich bei mode den verwendeten buffer des indikators eintragen??

Hier hab ich noch den Code des KeltnerChannel den ich verwenden möchte:

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Red
#property indicator_color2 Red
#property indicator_color3 Red

extern int periodMA=20; //Basic EMA
extern int periodATR=10;//Average True Range period
extern double kshift=2; //shift Lines Upper & Lower

double b0[],b1[],b2[];

int init()
 {
  
  SetIndexStyle(0,DRAW_LINE);
  SetIndexBuffer(0,b0);
  SetIndexLabel(0,"Upper"+periodATR+","+DoubleToStr(kshift,1));
  
  SetIndexStyle(1,DRAW_LINE);
  SetIndexBuffer(1,b1);
  SetIndexLabel(1,"Lower"+periodATR+","+DoubleToStr(kshift,1));
  
  SetIndexStyle(2,DRAW_LINE);
  SetIndexBuffer(2,b2);
  SetIndexLabel(2,"EMA"+periodMA);
 IndicatorShortName("Keltner_Chanel("+periodMA+","+periodATR+","+DoubleToStr(kshift,1)+")");
  
  return(0);
 }

int start()
 {
  int    i,limit=Bars-periodMA-IndicatorCounted();
  double r;
     for(i=0;i<limit;i++)
        {
     b2[i]=iMA(NULL,0,periodMA,0,MODE_EMA,PRICE_CLOSE,i);
     r=kshift*iATR(NULL,0,periodATR,i);
     b0[i]=b2[i]+r;
     b1[i]=b2[i]-r;
        }
  
  return(0);
 }
//+------------------------------------------------------------------+

 

Gruß David ;)

Bearbeitet von Alphablogger

Geschrieben
Zuerstmal noch eine Frage zum RSI: Was bedeutet shift?

Damit bestimmst du von welcher Kerze(bar) der RSI Wert berechnet werden soll.

0 = die aktuelle Kerze(bar)

1 = die vorherige

2 = die vor der vorherigen

u.s.w.

 

--

Capture_138.gif

Geschrieben
Beim iCustom leuchtet mir folgendes noch nicht ganz ein...

Ok. Schauen wir uns das Beispiel von der Verwendung des Custom-Indikators namens rocseparate von dem ic.arrow.right.png Tutorial-Link nochmal genauer an.

 

Im Code des EAs wird der Indikator wie folgt aufgerufen (weiter unten auf der Web-Seite):

double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0);

 

  • Der erste Parameter mit dem Wert NULL hat laut ic.arrow.right.png Funktions-Referenz den Namen
    symbol : Symbol the data of which should be used to calculate indicator. NULL means current symbol.,
     
    heißt also, der mittels iCustom aufgerufene Indikator soll seine Berechnungen auf dem Instrument durchführen, auf dem der EA aktuell arbeitet, also bspw. GBPJPY.
    double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0); ist dasselbe wie
    double L_1 = iCustom("GBPJPY",0,"rocseparate",H,P,B,A,1,0);
    wenn der aktuelle Wert, auf dem der EA läuft, der GBPJPY ist.
     
    Nach Funktionsdeklaration
    double iCustom( string symbol, int timeframe, string name, ..., int mode, int shift)
    muss symbol vom Typ "string" sein, also eine Zeichenkette, wie "GBPEUR".
     
     
    Soll hingegen ein anderes Instrument als das aktuelle genutzt werden, muss der Name angegeben werden, z.B. läuft Dein EA auf dem GBPJPY, soll aber den Indikatorwert für den EURUSD berechnen (warum auch immer), dann wäre der Aufruf:

    double L_1 = iCustom("EURUSD",0,"rocseparate",H,P,B,A,1,0);
     
     
     
  • Der zweite Parameter mit dem Wert 0 heißt laut Referenz
    timeframe :Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe.

    Wenn also der aktuell geöffnete Timeframe vom GBPJPY M15 ist, dann wird dieser genommen.
    double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0); ist wiederum identisch mit
    double L_1 = iCustom(NULL,PERIOD_M15,"rocseparate",H,P,B,A,1,0); oder aber
    double L_1 = iCustom(NULL,15,"rocseparate",H,P,B,A,1,0);, wenn der aktuelle TF der M15 ist.
    ic.arrow.right.png Timeframe-Kürzel (die Ziffer > 0 ist im Übrigen immer die Minutenangabe).
     
    Wenn man hingegen auf nem anderen als dem aktuell geöffneten M15 den Indikator für den EA berechnen wöllte (z.B. Tageschart), müsste man
    double L_1 = iCustom(NULL,PERIOD_D1,"rocseparate",H,P,B,A,1,0); oder aber
    double L_1 = iCustom(NULL,1440,"rocseparate",H,P,B,A,1,0); schreiben.
     
     
    Vorteil der NULL und der 0 bei den beiden Parametern symbol und timeframe ist die Flexibilität: man kann mal schnell ohne Änderungen den EA auf nen anderes Symbol oder TF ziehen, ohne im Code Änderungen vornehmen zu müssen.

Geschrieben

Jetzt kommen wir zum Speziellen an der Funktion iCustom: Parameter name und die Parameterliste.

 

  • Der 3. Parameter heißt
    name : Custom indicator compiled program name.
     
    Laut Deklaration von iCustom
    double iCustom( string symbol, int timeframe, string name, ..., int mode, int shift)
    soll name eine Zeichenkette sein (string) und zwar der Name des Indikators. In diesem Falle heißt er rocseparate und als String "rocseparate". (Bei Dir hieße er als Zeichenkette "Keltner_Channel", im Prinzip so, wie die kompilierte Indikator-Datei heißt nur ohne die Dateierweiterung .ex4)
     
     
  • Die folgenden Parameter sind optional und die Anzahl ist nicht festgelegt. Typisch dafür sind die 3 Punkte "...".
    ... : Parameters set (if necessary). The passed parameters and their order must correspond with the desclaration order and the type of extern variables of the custom indicator.
     
    Es gibt ja Custom-Indikatoren, die keinen, einen, zwei oder mehr Eingabeparameter (im Indikator durch das vorangestellte Schlüsselwort extern gekennzeichnet) erwarten.
     
    Von daher sind auch keine Typangaben in iCustom möglich, sondern das hängt allein vom verwendeten Indikator ab.
    In unserem Beispiel hier sieht die Liste der Eingabewerte im Code von rocseparate ( http://book.mql4.com/samples/iroc#74_7 ) wie folgt aus:
    #property indicator_color6 Red // Line color of the 5th buffer
    //--------------------------------------------------------------- 2 --
    extern int History =5000; // Amount of bars in calculation history
    extern int Period_MA_1=21; // Period of calculated MA
    extern int Bars_V =13; // Amount of bars for calc. rate
    extern int Aver_Bars =5; // Amount of bars for smoothing
    //--------------------------------------------------------------- 3 --
    int Period_MA_2, Period_MA_3, // Calculation periods of MA for other timefr.
    K2, K3; // Coefficients of timeframe correlation
     
    Nur die fettmarkierten Zeilen sind interessant.
     
    D.h. wenn der Indikator mit anderen als den im Indikator-Code voreingestellten 5000,21,13,5 laufen soll, müssen ALLE Eingabeparameter (auch wenn sie mit den voreingestellten Werten laufen und lediglich ein einziger Wert geändert werden soll) in der richtigen Reihenfolge angegeben werden. Die "richtige" Reihenfolge ergibt sich aus der Auflistung in der Indikatordatei.
     
    Aufruf:
    double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0);
    H - number of bars in calculation history;
    P - period of calculation MA;
    B - number of bars for rate calculation;
    A - number of bars for smoothing.
    wobei H,P,B,A alle vom Typ int (Integer) sein müssen (wie man an den Typenangaben nach dem Wort "extern" in der Indikatordatei jeweils ablesen kann) und zuvor im EA-Code deklariert:
    int H=10;
    int P=20;
    int B=30;
    int A=40;
    ...
    double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0);

Geschrieben

Ok, zum Schluss noch die beiden Parameter mode und shift.

 

 

  • mode: Line index. Can be from 0 to 7 and must correspond with the index used by one of SetIndexBuffer functions.
     
    double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0);
     
    In einem Indikator findet man in der Regel einen oder mehrere Buffer (Puffer), die man sich wie Zeilen in der Excel-Tabelle vorstellen kann, die Spalten sind die einzelnen Bars.
    Jetzt muss man der iCustom-Funktion noch sagen, welchen von den in dem Falle 5 Zeilen(Puffern) man denn auslesen möchte. Die Zeilen sind praktischerweise "durchnummeriert" in der Indikatordatei mittels der Funktion SetIndexBuffer
    int init() // Special function init()
    {
    SetIndexBuffer(0,Line_0); // Assigning an array to a buffer
    SetIndexBuffer(1,Line_1); // Assigning an array to a buffer
    SetIndexBuffer(2,Line_2); // Assigning an array to a buffer
    SetIndexBuffer(3,Line_3); // Assigning an array to a buffer
    SetIndexBuffer(4,Line_4); // Assigning an array to a buffer
    SetIndexBuffer(5,Line_5); // Assigning an array to a buffer
    Quelle: http://book.mql4.com/samples/iroc#74_7
     
    Was wo drin steht und was Du auslesen willst, musst Du jetzt selbst entscheiden. In unserem Beispiel soll Buffer 1 ausgelesen werden. Die "Durchnummerierung" beginnt normalerweise bei 0.
    Wie die Funktionsreferenz sagt (0-7) sind also maximal 8 Buffer erlaubt, sprich, von allen Indikatoren können die ersten 8 Buffer ausgelesen werden. Steht irgendwas in nem 9. Buffer drin, hat man leider Pech gehabt. :wub:
     
     
  • So. jetzt haben wir dem Indikator gesagt, welche Zeile wir auslesen wollen, jetzt müssen wir ihm abschließend nur noch die Spalte sagen. Das passiert über den Parameter shift.
     
    shift : Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).
     
    Das hat FinGer schon sehr schön erklärt. :mocking:
    shift ist die Verschiebung relativ zum aktuellen Bar. Es empfiehlt sich, nur rückwärts zu schieben, also Zahlen von 0,1,2,.... und größer einzusetzen, denn bei Zahlen kleiner 0 würden man nicht nach links (in die Vergangenheit) schieben und sich da Daten herholen, sondern man würde nach rechts schieben und sich Daten aus der Zukunft holen. Das ergibt in der Regel im Backtest extrem gute Ergebnisse, die allerdings im Realtime-Betrieb versagen, denn die Zukunft kennt man zu dem Zeitpunkt leider noch nicht :LLL: .

Geschrieben
  • Autor

Danke für die schnelle Hilfe echt super jetzt hab ichs kapiert :smile:

 

Nur eine kleine Frage hätte ich da noch: Ich habe jetzt den iRSI als "RSI" benannt und das funktioniert auch, aber der meckert immer 'price_close' - variable expected.

Was soll das heißen, ich kann doch den parameter nicht weglassen, oder?

 

 

 

RSI = iRSI (NULL, PERIOD_H1, int RSIperiod,PRICE_CLOSE,0)

Geschrieben
RSI = iRSI (NULL, PERIOD_H1, int RSIperiod,PRICE_CLOSE,0)

Typenangaben wie int, string, double haben in den Funktionsaufrufen, also: wenn Du die Funktion im Code verwendest, nichts verloren. Da jammert der Compiler zurecht :smile: .

 

Programmiertechnisch muss man Funktionsdeklaration, Funktionsdefinition und Funktionsaufruf unterscheiden.

 

Vor dem Beginn des Hauptprogrammes stehen die Funktionsdeklarationen (Funktionsprototyp, function prototype), als ein Modell für die Funktion die später im Programm aufscheint. Eine Funktionsdeklaration enthält den Namen der Funktion, eine Liste von Variablen (inklusive ihrer Typen) die an sie übergeben werden müssen und den Typ der Variablen den die Funktion zurückgibt, falls ein Wert zurückgeliefert wird.

 

Die Funktionsdeklaration stellt dem Compiler die Beschreibung der Funktion zur Verfügung, die zu einem späteren Zeitpunkt im Programm definiert wird.

 

Die eigentliche Funktion ist in der Funktionsdefinition enthalten. Die Definition enthält den Code, der später ausgeführt wird. Die erste Zeile der Funktionsdefinition, der Funktionskopf (function header), ist bis auf das Semikolon mit der Zeile der Funktionsdeklaration identisch.

Quelle: http://homepage.univie.ac.at/heinz.kabelka...eb/function.htm

Anmerkung: Bei MT lässt man die Deklaration oft weg, außer man will mit aus DLLs importierten externen Funktionen arbeiten, da kommt man nicht drumherum.

 

Funktionsaufruf

Eine Funktion wird aufgerufen durch Angabe des Funktionsnamens und der aktuellen Parameterwerte in runden Klammern. Besitzt die Funktion einem Ergebnistyp, der von void verschieden ist, kann das Ergebnis direkt einer Variablen vom entsprechenden Typ zugeordnet werden.

ic.arrow.right.png Funktionen: E-Learning TU Darmstadt, um mal die Unterschiede zu verstehen.

 

 

Zusammengefasst: Typangaben in Deklarationen/Definitionen: JA, in Funktionsaufrufen: NEIN.

 

Dein Aufruf muss also lauten: RSI = iRSI (NULL, PERIOD_H1, int RSIperiod,PRICE_CLOSE,0);

Geschrieben
  • Autor

ahh okay, das macht Sinn - Danke vielmals.

 

//---- input parameters
extern double    Lots=5.0;
extern double    takeprofit=20.0;
extern double    Trailing_Sl=5.0;
extern double    risk_trade=1;
extern int       maxslippage=4;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
 {
//---- 
  
//----
  return(0);
 }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
 {
//---- 
  
//----
  return(0);
 }

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+

int start()
 {
 
 int ticket;
 double total; // offene Orders
 double Keltner, RSI; // Verwendete Indikatoren
 
 
 
   // Parameter für den Keltner Channel
     int periodMA=20; //Basic EMA
     int periodATR=10;//Average True Range period
     double kshift=2; //shift Lines Upper & Lower
 
 // RSI Einstellungen
     int RSI_period=14;
 
 // Indikatoren werden "eingelesen"
 Keltner =iCustom (NULL, PERIOD_H1, "Keltner_Channel", periodMA, periodATR, kshift, 1, 0);
 RSI =iRSI (NULL, PERIOD_H1, RSI_period, PRICE_CLOSE ,0);
 
 // Erst wird gecheckt ob noch Orders offen sind, wenn nicht, dann gehts weiter
 
 total=OrdersTotal();
  if(total<1)
  {
  return(0);
  }
  
// Hier wird geschaut ob es ein Signal für einen Long-Enty gibt

double oversold = (RSI < 30); 
int outbreak = (PRICE_CLOSE < Keltner);

if(oversold < 30 && outbreak ==1)
{


}


  
  
 
 
 
 }


// the end

 

Jetzt möchte ich ja schauen ob es ein Signal gibt und zwar habe ich mir gedacht:

 

double oversold = (RSI < 30);

int outbreak = (PRICE_CLOSE < Keltner);

 

Jetzt war ich etwas verunsichert, liefert er mir jetzt bei oversold eine 1 wenn der RSI unterhalb von 30 ist, oder den wert also z.B. 25?

Beim Keltner Channel ebenfalls. Oder wäre es sinnvoll mit true oder false etwas zu machen?

 

 

Danke im Voraus :smile:

Geschrieben
double oversold = (RSI

int outbreak = (PRICE_CLOSE

 

Jetzt war ich etwas verunsichert, liefert er mir jetzt bei oversold eine 1 wenn der RSI unterhalb von 30 ist, oder den wert also z.B. 25?

Beim Keltner Channel ebenfalls. Oder wäre es sinnvoll mit true oder false etwas zu machen?

Defaultmäßig werden solche Vergleiche wie A

 

bool oversold = (RSI

bool outbreak = (PRICE_CLOSE

 

Man kann sich in einigen Programmiersprachen des Tricks bedienen, auch nen Interger (int) zu benutzen (oder nen anderen Zahlentyp, historisch bedingt gibt's da ne recht lange Liste), allerdings kommt es dann drauf an, mit welchem Zahlenwert die boolschen Werte intern dargestellt werden (oft: 1=true, 0=false), aber da gibt' auch Ausnahmen, so dass man da aufpassen muss.

 

Nimm aber lieber true und false und Variablen vom Typ bool überall dort, wo Du derartige Bedingungen im Code abtestest. Das ist in jedem Fall korrekt.

 

In Deinem obigen Beispiel bekommst Du für oversold ne 1.0 (weil vom Typ double) und für outbreak ne 1 (weil vom ganzzahligen Datentyp int).

Geschrieben
  • Autor
Nimm aber lieber true und false und Variablen vom Typ bool überall dort, wo Du derartige Bedingungen im Code abtestest. Das ist in jedem Fall korrekt.

 

In Deinem obigen Beispiel bekommst Du für oversold ne 1.0 (weil vom Typ double) und für outbreak ne 1 (weil vom ganzzahligen Datentyp int).

 

Ja das ging ja wieder schnell :smile:

 

Also dann mach ich es genau so

 

// Hier wird geschaut ob es ein Signal für einen Long-Enty gibt

bool oversold = (RSI < 30); 
bool outbreak = (PRICE_CLOSE < Keltner);

 

Bei bool bekomm ich jetzt ja als Ergebnis true (1) also geb ich im nächsten Schritt wie folgt an

 

 if(oversold == 1 && outbreak == 1)

 

Langsam macht programmieren ja richtig Spaß :wink:

Geschrieben
Bei bool bekomm ich jetzt ja als Ergebnis true (1) also geb ich im nächsten Schritt wie folgt an

 

if(oversold == 1 && outbreak == 1)

Wenn Du als Werte nur true oder false drinstehen haben kannst, ist es besser auch auf genau diese zu testen. Sonst wendest Du ja den von mir oben beschriebenen "Trick" an. Kann man machen, besser ist aber:

 

if(oversold == true && outbreak == true){...}

 

 

Langsam macht programmieren ja richtig Spaß :smile:

Ich weiß. Wenn man den Brechlevel überwunden hat, ist es ne feine Sache.

 

Bei meinem ersten Compiler stand noch "Blood, Sweat and Code" im Booklet (CodeWarrior für Mac). Über den Text hab ich damals noch gelacht. Allerdings nicht lange. Denn es wahr geworden. :wink:

Geschrieben
  • Autor
Wenn Du als Werte nur true oder false drinstehen haben kannst, ist es besser auch auf genau diese zu testen. Sonst wendest Du ja den von mir oben beschriebenen "Trick" an. Kann man machen, besser ist aber:

 

if(oversold == true && outbreak == true){...}

 

Ja bis jetzt hab ich ja nur long, aber ich glaub das ganze noch für short umzuschreiben dürfte schnell gehen.

Nur wollte ich gerade ein Backtest auf GOLD machen, aber da macht er keinen einzigen Trade, aber er lädt den EA erfolgreich :smile:

 

Das ist der Code bis jetzt

 

//---- input parameters
extern double    Lots=5.0;
extern double    takeprofit=20.0;
extern double    Trailing_Sl=5.0;
extern double    risk_trade=1;
extern int       maxslippage=4;
extern double    stoploss=10;


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
 {
//---- 
  
//----
  return(0);
 }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
 {
//---- 
  
//----
  return(0);
 }

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+

int start()
 {
 
 int ticket;
 double total; // offene Orders
 double Keltner, RSI; // Verwendete Indikatoren
 
 
 
   // Parameter für den Keltner Channel
     int periodMA=20; //Basic EMA
     int periodATR=10;//Average True Range period
     double kshift=2; //shift Lines Upper & Lower
 
 // RSI Einstellungen
     int RSI_period=14;
 
 // Indikatoren werden "eingelesen"
 Keltner =iCustom (NULL, PERIOD_H1, "Keltner_Channel", periodMA, periodATR, kshift, 1, 0);
 RSI =iRSI (NULL, PERIOD_H1, RSI_period, PRICE_CLOSE ,0);
 
 // Erst wird gecheckt ob noch Orders offen sind, wenn nicht, dann gehts weiter
 
 total=OrdersTotal();
  if(total<1)
  {
  return(0);
  }
  
// Hier wird geschaut ob es ein Signal für einen Long-Enty gibt

  int oversold = (RSI < 30); 
  int outbreak = (PRICE_CLOSE < Keltner);
  
 

  if(oversold == true && outbreak == true)
     {
     ticket=OrderSend(NULL, OP_BUY, Lots, Ask, maxslippage, stoploss, takeprofit, "Long Trade" , 12345, 0, Green);
     
     }
     return(0);
     



}



// the end

 

Müsste doch eigentlich passen bis dahin oder? :wink:

Geschrieben
Ja bis jetzt hab ich ja nur long, aber ich glaub das ganze noch für short umzuschreiben dürfte schnell gehen.

Normalerweise ja ;).

 

Nur wollte ich gerade ein Backtest auf GOLD machen, aber da macht er keinen einzigen Trade

Kann man dem armen EA :smile: auch nicht verübeln

 

int start()

{

...

// Indikatoren werden "eingelesen"

Keltner =iCustom (NULL, PERIOD_H1, "Keltner_Channel", periodMA, periodATR, kshift, 1, 0);

RSI =iRSI (NULL, PERIOD_H1, RSI_period, PRICE_CLOSE ,0);

 

// Erst wird gecheckt ob noch Orders offen sind, wenn nicht, dann gehts weiter

 

total=OrdersTotal();

if(total

{

return(0);

}

 

 

// Hier wird geschaut ob es ein Signal für einen Long-Enty gibt

 

An der Stelle kommt das Programm nie an, da Du in der if-Anweisung immer! die Funktion verlässt.

int oversold = (RSI

int outbreak = (PRICE_CLOSE

...

 

Du hast ja noch keine einzige Order gemacht, wenn die Funktion start() aufgerufen wird und das ändert sich auch nicht, weil Du immer fragst:

 

"Hast Du momentan keine Orders in der Pipeline (OrdersTotal()

 

Besser wäre :

 

total=OrdersTotal();

if(total>0)

{

return(0);

}

Geschrieben
Besser wäre :

 

das sind auch immer die Kleinigkeiten wo ich mich frage warum ist der PC so dumm und versteht nicht was ich will

Geschrieben
  • Autor
Besser wäre :

 

total=OrdersTotal();

if(total>0)

{

return(0);

}

 

Ach so, den Fehler hab ich gar nicht gesehen :smile:

Danke für deine Hilfe

 

das sind auch immer die Kleinigkeiten wo ich mich frage warum ist der PC so dumm und versteht nicht was ich will

 

Ja hab ich mir auch gerade gedacht^^

Bearbeitet von ronner
Zitat gekürzt - bitte immer auf notwendige Länge beschränken.

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

Account

Navigation

Suche

Suche

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.