Hallo zusammen,
Ich würde gerne einen Bot bauen, der Rechtecke erstellt, wenn der Betrag der Preisbewegung eine gewisse Range überschreitet. Es werden t1 und t2 des Rechtecks durchgegangen, bis der Preis sich das nächste Mal um eine voreingestelltes Maß bewegt und dort soll er ein Rechteck stehen lassen. Aber so weit bin ich noch nicht. Normalerweise würde man das zum Beispiel mit for machen, doch um das Ganze im Strategietester erstmal sichtbar zu machen, verkleinere ich die t Zahl nur bei jedem Tick. Man sieht dann wie die Rechtecke gebildet werden.
Nun habe ich versucht, sagen wir, wenn er bei t1=t2=199 losläuft, dann hat er nur eine Kerze zu überprüfen. die 199ste. Die hat ein Hoch und ein Tief und die Beiden nimmt er dann als y-Werte für die Erstellung des Rechtecks.
Wenn er nun den t-Wert findet, bei welchem die Range überschritten wurde, soll x1=x2 sein, das wäre dann die Kerze wo das aktuelle Rechteck abgeschlossen wird und das Neue beginnt. Nun, wenn die beiden t-werte neu vergeben wurden, wird die Struktur, die die Werte, aus denen das Rechteck konstruiert wird, beinhaltet, neu errechnet und eigentlich müssten die Indexe der Hochs und Tiefs, ArrayMaximum(High,t2,t1), ArrayMinimum(Low,t2,t1) ebenfalls neu berechnet werden, aber der Eine bleibt immer bei 198 hängen, auch wenn die Struktur nach der Änderung der t-Werte neu berechnet wird. Sitze schon Stunden daran und es ist sehr frustrierend. Ich verstehe einfach nicht, was das Problem sein soll.
Ich habe es jetzt schon echt oft durch den Debugger gejagt und frage mich, wenn die einzig möglichen t-Werte t1=194 und t2=194 sind, wie es denn sein kann, dass Das ArrayMinimum bei 198 ist. Das kann doch gar nicht stimmen.
Wenn ich etwas übersehen habe, komme ich jedenfalls nicht drauf. t2 und t1 werden doch hier übertragen und ich berechne auch nach der t Änderung die Struktur für das Rechteck neu. und bei ArrayMaximum direkt nebendran geht es doch auch!!!
Hallo Carl,
danke fürs reinschauen. Verstehe gerade nicht Deinen Ansatz: warum ab 0 und von welchen Werten sprechen wir jetzt, CopyHigh/Low/Time oder die t-Werte? Mit 5 Werten kann ich nicht sicher überprüfen, ob der Übergang zum nächsten Rechteck funktioniert.
Die Änderung der t1 und t2 bei Erreichen der MinRange und die Ergebnisse aus ArrayMaximum und ArrayMinimum habe ich mit dem Debugger bereits überprüft und es scheint, dass der ArrayMinimum im Gegensatz zu ArrayMaximum die neuen Grenzen des zu prüfenden Bereichs nicht übernimmt, doch ich verstehe nicht warum.
- "warum ab 0" ab dem Index 0 des durch Copy.. ausgefüllten Arrays.
- "die neuen Grenzen des zu prüfenden Bereichs nicht übernimmt," es ist wohl eher so, dass sich nicht die gewünschten Werte im Array befinden - dass mit dem Debugger überprüfen von (Index) 0 bis Ende.
Hast du deren genaue Funktionsweise im Kopf? Habs erst verstanden, nachdme ich ein beispielEA geschrieben habe und mir die ArrayMax() genauer angesehen habe..
Villeicht hilft es ja
Bin gerade selbst an der ArrayMax() hängen geblieben...
Hast du deren genaue Funktionsweise im Kopf? Habs erst verstanden, nachdme ich ein beispielEA geschrieben habe und mir die ArrayMax() genauer angesehen habe..
Villeicht hilft es ja
Ich kann nur mutmaßen, aber man definiert ein Array und gibt dem Computer einen Ausschnitt aus dem Array an durch die Anfangs- und Endpunkte (Kann auch das gesamte Array sein). Bei ArrayMax soll er
wenn ymax<y[i] dann xmax=i setzen. Dadurch wird immer das bisherige y durch ein eventuell höheres ersetzt. Nachdem die Vergleiche über den ganzen Abschnitt durchgeführt wurden, ist ymax nun gleich dem größten y-Wert in der definierten Serie.
Das Problem, das ich habe ist ja, dass er die Grenzen des zu überprüfenden Arrays gar nicht übernimmt. wie kann es denn sein, wenn ich sage:
"Okay, hier ist ein Array von 194 bis 194, es hat also nur eine Bar und zwar die Nummer 194, diese hat ein High und ein Low," dann wundert es mich wenn ich nicht das rauskriege, was ich eingegeben habe, nämlich die 194ste Kerze.
Was genau meintest Du mit ArrayMax genauer angesehen?
- "warum ab 0" ab dem Index 0 des durch Copy.. ausgefüllten Arrays.
- "die neuen Grenzen des zu prüfenden Bereichs nicht übernimmt," es ist wohl eher so, dass sich nicht die gewünschten Werte im Array befinden - dass mit dem Debugger überprüfen von (Index) 0 bis Ende.
Habe es jetzt mal mit sechs Kerzen probiert. Es tut sich jedoch nichts was nicht auch passieren soll. Mit 200 Werten klappt es auch. Es wird ein einziges großes Rechteck gebildet und wenn er bei der 0ten Kerze ist, fängt er von vorne an. Aber das ist ja nicht was ich möchte. Das Problem beginnt, wenn er ein neues Rechteck startet, nachdem er eine bestimmte Bedingung bekommt, da er die neuen Arraygrenzen nicht übernimmt. Allerdings nur für ArrayMinimum... bei ArrayMaximum funktioniert es einwandfrei.
Also um meine Vermutung überprüfen zu können, dass der neue Wert t1=t2 nicht von ArrayMinimum übernommen wird, habe ich die Bedingung eingebaut, dass sobald t2=3 wird t1=t2. Hier wird der neue Wert zwar eingesetzt, bei der Berechnung von ArrayMinimum jedoch nicht übernommen.
Hier der Code, jeder kann es selbst ausprobieren:
//+------------------------------------------------------------------+ //| SeekMinRangeSimplified.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <ChartObjects/ChartObjectsShapes.mqh> CChartObjectRectangle rect; struct RectStruct { int highest; int lowest; datetime time1; double price1; datetime time2; double price2; }; RectStruct rs; int t1=5, t2=5, limit=200; double High[], Low[], MinRange=1.5, AbsRange; datetime Time[]; // die folgenden Variablen werden zur Überprüfung der Werte des Arrays eingeführt: double high0,high1,high2,high3,high4,high5,high6,low0,low1,low2,low3,low4,low5,low6; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArraySetAsSeries(High,true); ArraySetAsSeries(Low,true); ArraySetAsSeries(Time,true); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- ArrayFree(High); ArrayFree(Low); ArrayFree(Time); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { rect.Delete(); CopyBuffers(); GetValues(); GetStructure(); /* AbsRange=fabs(rs.price1-rs.price2); //Die alte Bedingung, die sich auf die Preisbewegung bezieht, wurde außer Kraft gesetzt. if(AbsRange>=MinRange) { t1=t2; GetStructure(); } */ if(t2==3) //Hier befindet sich die Bedingung um die Grenzen des Rechtecks auf die gleiche Kerze zu setzen { t1=t2; GetStructure(); //danach erfolgt eine Neuberechnung der Rechtecksstruktur. Somit müssten die neuen Grenzen direkt in die Berechnung //der künftigen Rechtecksstruktur einfließen. ArrayMinimum bleibt jedoch innerhalb der alten Grenze. } Comment("rs.time1: ",rs.time1, "\nrs.price1: ",rs.price1, "\nrs.time2: ",rs.time2, "\nrs.price2: ",rs.price2, "\nAbsRange: ",AbsRange ); t2--; if(t2==0) { t1=t2=5; } rect.Create(0,"Rectangle00",0,rs.time1,rs.price1,rs.time2,rs.price2); rect.Color(StringToColor("clrBlue")); rect.Width(2); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CopyBuffers() { CopyHigh(_Symbol,_Period,0,6,High); CopyLow(_Symbol,_Period,0,6,Low); CopyTime(_Symbol,_Period,0,6,Time); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void GetStructure() { rs.highest=ArrayMaximum(High,t2,t1); rs.lowest=ArrayMinimum(Low,t2,t1); rs.time1=Time[t1]; rs.price1=High[rs.highest]; rs.time2=Time[t2]; rs.price2=Low[rs.lowest]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void GetValues() { high0=High[0]; high1=High[1]; high2=High[2]; high3=High[3]; high4=High[4]; high5=High[5]; low0=Low[0]; low1=Low[1]; low2=Low[2]; low3=Low[3]; low4=Low[4]; low5=Low[5]; }
Also hier im Endeffekt der gleiche Fehler wie bei der Version mit 200. Wenn ich den Part mit der Bedingung rauslasse, macht er ein einziges Rechteck und dehnt das Tick für Tick aus, so wie er soll.
Das kann doch nicht sein, dass die Funktion einen Fehler hat, oder? Die wird doch so oft benutzt. Ich muss etwas übersehen haben, aber natürlich fällt es mir nicht auf.
Jetzt fantasiere ich schon, mir eine eigene ArrayMmin/Max include zu schreiben.
- Kannst mit Screenshots zeigen, was Du willst und was Du nicht willst, aber passiert.
- Sind t1 und t2 immer gleich und immer 5?
- Und die Arrays haben immer die Größe 6?
- Hast Du im Debugger überprüft die Werte überprüft?
- Jein. Erstmal was klappt.
Das Rechteck soll sich von links nach rechts ausdehnen. Das tut es auch und dient nur der Veranschaulichung. Wichtiger ist, dass die Werte später in einer Schleife überprüft werden und die Rechtecke nur dann gebildet werden, wo eine bestimmte Range überschritten wird. Dann möchte ich mit Hilfe der Klasse ChartObjetsshapes ein Array aus Rechtecksobjekten bereitstellen und aus der Struktur mit den x- und y- Koordinaten der Rechtecke mache ich ebenfalls ein Array. Der EA soll Rechtecke zum Array hinzufügen wenn der Preis sich ein paar hundert oder tausend Punkte bewegt hat bzw. Rechtecke entfernen, wenn der Zeitpunkt zu weit in der Vergangenheit liegt. (mal eine Frage: geht das eventuell einfacher mit CCanvas?)
Hier das Ganze mit Bedingung. Man sieht im dritten Bild, wie ein neues Rechteck gebildet wird. Dieses besteht zuerst nur aus einer Kerze, hier ist t1=t2. Gleichzeitig dürfte die blaue Linie im dritten Bild nicht so lang sein, die Kerze gibt es nicht her. Dies passiert, da immer noch das Low aus dem ersten Bild übernommen wird. Unten habe ich diese Unstimmigkeit noch anhand von Debuggerwerten belegt. - t1 und t2 sind meistens nicht gleich. t1 ist der Index im Zeitpunkt eins und t2 der Index im Zeitpunkt 2, welche man für das Rechteck benötigt. Ich gehe davon aus, dass die Funktion für das Rechteck bekannt ist, wenn nicht siehe Code oder Doku (Standardbibliothek Chart ObjectsShapes). Zuerst sind sie beide gleich, dann bewegt sich der eine mit jedem Tick eine Bar weiter. Eigentlich möchte ich das als Loop machen, aber pro Tick ist es erstmal anschaulicher, weil man die Bildung der Rechtecke und die Verschiebungen ihrer Grenzen verfolgen kann.
- In diesem Fall haben die Arrays immer die Größe 6. Ursprünglich wollte ich es mit 200 Bars versuchen. Aber wenn es funktioniert und von der Rechenleistung geht, werde ich es auch mit mehreren Tausend probieren, um Gebiete mit bestimmten Bedingungen zu Testzwecken zu markieren.
-
Ja, ich habe im Debugger die Werte überprüft. Entschuldigt bitte wenn ich so viele Bilder reinknalle, ich kriege es anders nicht erklärt. Gerne fragen.
Bild oben: t1 = 5 und wenn t2 = 3 , wird t1=t2.
Bild oben: Hier ist t1=t2. Wenn als nächstes GetStructure() aufgerufen wird, müsste rs.highest und rs.lowest Beides gleich 3 werden. Was passiert:
Bild oben: Komischerweise ist nun immer noch rs.lowest = 5. falsch!
Gleichzeitig ist nun rs.time1 = rs.time2 = 2021.07.05 19:57:00. Hier wurde der veränderte Index also richtigerweise in die Zeitpunkte umgesetzt!!!
Wie ist das hier:
- die Variablenbenennung ist schlecht, weil missverständlich: was von re.price1 und rs.price3 ist hoch bzw. tief?
- Erst dann kann man sehen, ob das Min oder Max von den ersten oder letzten 2,3 bzw. 5 genommen wird.
- Welches von den Chartbildern ist hier im Debugger gezeigt.
Wie ist das hier:
- die Variablenbenennung ist schlecht, weil missverständlich: was von re.price1 und rs.price3 ist hoch bzw. tief?
- Erst dann kann man sehen, ob das Min oder Max von den ersten oder letzten 2,3 bzw. 5 genommen wird.
- Welches von den Chartbildern ist hier im Debugger gezeigt.
- In Ordnung, das war ungenau von mir... hier ist der Code mit den geänderten Variablen.
//+------------------------------------------------------------------+ //| SeekMinRangeSimplified.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <ChartObjects/ChartObjectsShapes.mqh> CChartObjectRectangle rect; struct RectStruct { int highest; int lowest; datetime timeleft; double priceupper; datetime timeright; double pricelower; }; RectStruct rs; int t1=5, t2=5, limit=200; double High[], Low[], MinRange=1.5, AbsRange; datetime Time[], CurrTime, PrevTime; // Überprüfung double high0,high1,high2,high3,high4,high5,high6,low0,low1,low2,low3,low4,low5,low6; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArraySetAsSeries(High,true); ArraySetAsSeries(Low,true); ArraySetAsSeries(Time,true); // ArraySetAsSeries(rect,true); // ArrayResize(rect,k); // ArraySetAsSeries(rs,false); // ArrayResize(rs,k); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- ArrayFree(High); ArrayFree(Low); ArrayFree(Time); // ArrayFree(rs); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { rect.Delete(); CopyBuffers(); GetValues(); GetStructure(); /* AbsRange=fabs(rs.priceupper-rs.pricelower); if(AbsRange>=MinRange) { t1=t2; GetStructure(); } */ if(t2==3) { t1=t2; GetStructure(); } Comment("rs.timeleft: ",rs.timeleft, "\nrs.priceupper: ",rs.priceupper, "\nrs.timeright: ",rs.timeright, "\nrs.pricelower: ",rs.pricelower, "\nAbsRange: ",AbsRange ); t2--; if(t2==0) { t1=t2=5; } rect.Create(0,"Rectangle00",0,rs.timeleft,rs.priceupper,rs.timeright,rs.pricelower); rect.Color(StringToColor("clrBlue")); rect.Width(2); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CopyBuffers() { CopyHigh(_Symbol,_Period,0,6,High); CopyLow(_Symbol,_Period,0,6,Low); CopyTime(_Symbol,_Period,0,6,Time); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void GetStructure() { rs.highest=ArrayMaximum(High,t2,t1); rs.lowest=ArrayMinimum(Low,t2,t1); rs.timeleft=Time[t1]; rs.priceupper=High[rs.highest]; rs.timeright=Time[t2]; rs.pricelower=Low[rs.lowest]; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void GetValues() { high0=High[0]; high1=High[1]; high2=High[2]; high3=High[3]; high4=High[4]; high5=High[5]; low0=Low[0]; low1=Low[1]; low2=Low[2]; low3=Low[3]; low4=Low[4]; low5=Low[5]; }
- Hm. In der Doku stand, dass bei ArrayMin/Max die Zeitreihe true oder false berücksichtigt wird. Darum denke ich nicht, dass dies das Problem ist. Ehrlich gesagt, wenn es Dich interessiert, lade doch einfach mal den Code herunter und lass ihn mit und ohne Bedingung durch den Tester laufen, bitte. Du kannst es Dir dann besser vorstellen und es geht vielleicht fünf MInuten. Ich bin mir nicht sicher ob so klar wrid, was ich machen will und was das Problem ist, wenn ich hier Fotos von den Debuggerergebnissen poste...
Auf jeden Fall macht er ohne Bedingung schon genau das was ich will, nur eben mit Bedingung nicht. -
Hast Recht, war auch ungenau dargestellt. Warte, hier nochmal die Variablen im Debugger mit den dazugehörigen Charts:
Bild oben: Das Rechteck ist jetzt mit t1=t2 geupdated. Unten läuft t2=2 und t1 bleibt 3. highest und lowest sollten nun eigentlich nur noch zwischen zwei und drei sein. Warum bei fünf? Man sieht auch am Rechteck, dass die seitlichen Begrenzungen stimmen, doch die oben und unten nicht.
Bild oben: Hier erreicht t2 (rechte Grenze) die Kerze 3.
Bild oben: Dadurch wird t1 (linke Grenze) gleich t2 (rechte Grenze).
Bild oben: Hier ähnlich.
Auf diesem Bild:
ist zu sehen, dass low0 das aktuellste Tief 1790,89 hat low5 das älteste - ist das so wie Du Dir das ausgedacht hast und wird das von den Index-Grenzen so erfasst, oder ist das anders?
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Hallo zusammen,
Ich würde gerne einen Bot bauen, der Rechtecke erstellt, wenn der Betrag der Preisbewegung eine gewisse Range überschreitet. Es werden t1 und t2 des Rechtecks durchgegangen, bis der Preis sich das nächste Mal um eine voreingestelltes Maß bewegt und dort soll er ein Rechteck stehen lassen. Aber so weit bin ich noch nicht. Normalerweise würde man das zum Beispiel mit for machen, doch um das Ganze im Strategietester erstmal sichtbar zu machen, verkleinere ich die t Zahl nur bei jedem Tick. Man sieht dann wie die Rechtecke gebildet werden.
Nun habe ich versucht, sagen wir, wenn er bei t1=t2=199 losläuft, dann hat er nur eine Kerze zu überprüfen. die 199ste. Die hat ein Hoch und ein Tief und die Beiden nimmt er dann als y-Werte für die Erstellung des Rechtecks.
Wenn er nun den t-Wert findet, bei welchem die Range überschritten wurde, soll x1=x2 sein, das wäre dann die Kerze wo das aktuelle Rechteck abgeschlossen wird und das Neue beginnt. Nun, wenn die beiden t-werte neu vergeben wurden, wird die Struktur, die die Werte, aus denen das Rechteck konstruiert wird, beinhaltet, neu errechnet und eigentlich müssten die Indexe der Hochs und Tiefs, ArrayMaximum(High,t2,t1), ArrayMinimum(Low,t2,t1) ebenfalls neu berechnet werden, aber der Eine bleibt immer bei 198 hängen, auch wenn die Struktur nach der Änderung der t-Werte neu berechnet wird. Sitze schon Stunden daran und es ist sehr frustrierend. Ich verstehe einfach nicht, was das Problem sein soll.
Ich habe es jetzt schon echt oft durch den Debugger gejagt und frage mich, wenn die einzig möglichen t-Werte t1=194 und t2=194 sind, wie es denn sein kann, dass Das ArrayMinimum bei 198 ist. Das kann doch gar nicht stimmen.
Wenn ich etwas übersehen habe, komme ich jedenfalls nicht drauf. t2 und t1 werden doch hier übertragen und ich berechne auch nach der t Änderung die Struktur für das Rechteck neu. und bei ArrayMaximum direkt nebendran geht es doch auch!!!