Hier finest Du e3eine Liste aller Funktionen von MQL5: https://www.mql5.com/de/docs/function_indices
Da es auch kurze Erklärungen gibt, kann man mit Ctrl+F nach Schlüsselwörtern suchen.
Ich denke Du brauchst: https://www.mql5.com/de/docs/series/copyrates
um die Daten der vergangenen Balken abzufragen. Kontrolliere immer die Richtung, also wo sind die jüngsten und wo die ältesten Daten.
Übrigens, wenn Du den Kursor auf eine Funktion stellst und F1 drückst kommst Du direkt zur Referenz dieser Funktion!

- www.mql5.com
Hier finest Du e3eine Liste aller Funktionen von MQL5: https://www.mql5.com/de/docs/function_indices
Da es auch kurze Erklärungen gibt, kann man mit Ctrl+F nach Schlüsselwörtern suchen.
Ich denke Du brauchst: https://www.mql5.com/de/docs/series/copyrates
um die Daten der vergangenen Balken abzufragen. Kontrolliere immer die Richtung, also wo sind die jüngsten und wo die ältesten Daten.
Übrigens, wenn Du den Kursor auf eine Funktion stellst und F1 drückst kommst Du direkt zur Referenz dieser Funktion!
Vielen Dank für die Infos. In meiner noch sehr jungen Programmier-Karriere ist das (CopyRates) absolutes Neuland ... da muss ich mich erst mal reinlesen und schauen, wie man das schreibt ...
"packen wir es an" ... :-)
PS: die Übersicht aller Funktionen kannte ich bis dato noch nicht - mega! top
Ich habe nun ein paar Videos dazu geschaut und bin tatsächlich sehr weit gekommen. Im Grunde genommen, habe ich das Gerüst für die Problemlösung fertig und in einem von zwei Fällen erhalte ich auch das gewünscht Ergebnis - aber im anderen Fall leider nicht.
Beim Bild oben ist Kerze 1 ein Außenstab, Kerze 2 demzufolge ein Innenstab und ab Kerze 3 wird es für mich interessant. Ab hier möchte ich prüfen, ob der Kurs den Außenstab verlassen hat oder ob wir uns noch in der "OutsideBarRange" befinden.
Verlässt der Kurs innerhalb der Kerze 3 den Range-Bereich, weißt der Code auch das Verlassen der Range korrekt aus. Das ist der eine Fall, bei dem alles sauber läuft.
Doch wenn erst ab Kerze 4 oder folgende die Range verlassen wird, weißt der Code nichts mehr aus. Das Problem liegt also vermutlich in der Übernahme der Werte aus der Array-Position [2], welche somit auch nur mit der Kerze 3 abgefragt werden.
Wie kann ich die Werte aus der Array-Position [2] dauerhaft prüfen bis diese Werte über- oder untertroffen werden?
Hier der Code für die Abfrage der OutsideBar:
void calcSetup(){ double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); // Array erstellen MqlRates priceInformation[]; // Abwärts sortieren ArraySetAsSeries(priceInformation,true); // Preisdaten in das Array kopieren int Data = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),priceInformation); // Outsidebar[2] prüfen if(priceInformation[2].high >= priceInformation[1].high && priceInformation[2].low <= priceInformation[1].low){ outsideBar = true; outsideBarHigh = priceInformation[2].high; outsideBarLow = priceInformation[2].low; Print(priceInformation[2].time," no signal - outsideBar (H ",outsideBarHigh,"; L ",outsideBarLow,")"); Print(priceInformation[1].time," no signal - insideBar"); }else outsideBar = false; }
Und hier die Abfrage, ob die Range noch gültig ist:
void calcOutsideBarRange(){ double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); if(bid <= outsideBarHigh && bid >= outsideBarLow){ outsideBarRange = true; }else if(bid > outsideBarHigh || bid < outsideBarLow){ outsideBarRange = false; outsideBar =false; Print(" left OutsideBarRange"); } }
Bis hierher bin ich schon mal gekommen - nun fehlt nicht mehr viel zur kompletten Problemlösung ... :-)
Vielleicht hat mir jemand einen Tipp für dieses "Array-Problem"?
Vielen Dank schon mal im Voraus.
Immer wieder überprüfen. Aber es würde genügen den Wert des Arrays nur bei einem neuen Stab (newBar) überprüfen.
Lies mal: https://www.mql5.com/de/articles/159
Aber ich mach das anders:
#define IxB(t) ((int)((t)%86400))/PeriodSeconds(_Period) // Index of the bar of the day #define IxP(t,p) ((int)((t)%86400))/PeriodSeconds(p) // Index of the bar of the day
zB. so (ungetestet)
// use: if (isNewIdx(TimeCurrent(), _Period) ) { ..; } bool isNewIdx(const datetime t, const ENUM_TIMEFRAMES p){ #define IxP(t,p) ((int)((t)%86400))/PeriodSeconds(p) // Index of the bar of the day static int idxBar = 0; int i = IxP(t,p); if ( i == idxBar ) return false; // same bar idxBar = i; return(true); }
Also Array-Check nur wenn isNewBar(_Period) ist es das, was Du Dir denkst?
Teste es mal.

- www.mql5.com
Immer wieder überprüfen. Aber es würde genügen den Wert des Arrays nur bei einem neuen Stab (newBar) überprüfen.
Lies mal: https://www.mql5.com/de/articles/159
Aber ich mach das anders:
zB. so (ungetestet)
Also Array-Check nur wenn isNewBar(_Period) ist es das, was Du Dir denkst?
Teste es mal.
Hmm, bin mir jetzt nicht sicher, aber ich glaube, ich meine was anderes (oder ich verstehe deine Antwort nicht richtig - könnte auch sein).
Mit open aktuelle Bar[0] wird mir angezeigt, ob die Bar[2] ein Außenstab und demzufolge die Bar[1] ein Innenstab ist. Soweit so gut.
Ist ein Außenstab vorhanden, ziehe ich mir das Hoch und Tief aus der Bar(2) und speichere sie in einer Variablen:
if(priceInformation[2].high >= priceInformation[1].high && priceInformation[2].low <= priceInformation[1].low){ outsideBar = true; outsideBarHigh = priceInformation[2].high; outsideBarLow = priceInformation[2].low;
Wenn nun, innerhalb der Bar[0], also der noch aktuellen Bar, das Hoch oder Tief vom Außenstab gerissen wird, wird es mir auch vorbildlich angezeigt. Doch wenn nun eine neue Bar öffnet, ist diese Bar die Bar [0] und somit die Bar [2] nicht mehr mein Außenstab. Wenn nun in dieser neuen Bar oder einer späteren das Hoch oder Tief des eigentlichen Außenstabs gerissen wird, wird es nicht mehr angezeigt.
Deshalb vermute ich, dass der Wert aus der Bar[2] nur solange gültig ist, solange der Außenstab auch die Bar [2] - mit neuem Bar dann eben nicht mehr.
Daher die Frage, ob man diese Werte (Hoch und Tief) "behalten" oder fixieren und somit weiterhin damit arbeiten kann.
Im Grunde genommen möchte ich mit jeder neuen Bar prüfen, ob der Außenstab noch Bestand hat. Sobald dies nicht mehr der Fall ist, wird der Wert auf "false" gesetzt und es bedarf keiner Prüfung mehr.
Daher die Frage, ob man diese Werte (Hoch und Tief) "behalten" oder fixieren und somit weiterhin damit arbeiten kann.
Im Grunde genommen möchte ich mit jeder neuen Bar prüfen, ob der Außenstab noch Bestand hat. Sobald dies nicht mehr der Fall ist, wird der Wert auf "false" gesetzt und es bedarf keiner Prüfung mehr.
Also musst Du wissen, wenn eine neue Bar erstellt wird, um dann die Gültigkeit des Musters zu prüfen. Ansonsten hast Du Schwellenwerte, die wenn gerissen, Dich zum rechnen zwingen.
Also musst Du wissen, wenn eine neue Bar erstellt wird, um dann die Gültigkeit des Musters zu prüfen. Ansonsten hast Du Schwellenwerte, die wenn gerissen, Dich zum rechnen zwingen.
Hmm, der EA soll ja auch bei jeder neuen Kerze neu berechnen - was er auch korrekt macht. Aber ich habe nach wie vor nicht verstanden, wie ich den High/Low-Wert "behalten" und weiter prüfen kann.
Hmm, der EA soll ja auch bei jeder neuen Kerze neu berechnen - was er auch korrekt macht. Aber ich habe nach wie vor nicht verstanden, wie ich den High/Low-Wert "behalten" und weiter prüfen kann.
Naja, das wohl in einer eigenen Variablen, die entweder lokal (inOnTick) als static oder global, d.h. außerhalb jeder Funktion deklariert wird, damit sie nicht bei jeden Funktionsstart von OnTick neu berechnet werden muss. Meintest Du das?

- www.mql5.com
Naja, das wohl in einer eigenen Variablen, die entweder lokal (inOnTick) als static oder global, d.h. außerhalb jeder Funktion deklariert wird, damit sie nicht bei jeden Funktionsstart von OnTick neu berechnet werden muss. Meintest Du das?
Das habe ich bereits - hier der komplette Code meines Lern- und Übungs-EAs:
//+------------------------------------------------------------------+ //| lern- und test-EA.mq5 | //| Copyright 2024, Anfänger | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Anfänger" #property version "1.10" #include <Trade/Trade.mqh> enum ENUM_LOT {LOT_FIX,LOT_AMOUNT,LOT_PERCENT}; enum ENUM_SL {SL_FIX,SL_CANDLE}; input group "SIGNAL" input string TimeRangeStart = "11:02"; input string TimeRangeEnd = "11:12"; input group "RISIKO" input ENUM_LOT Lotcalculation = LOT_AMOUNT; input double RiskInLots = 0.2; input double RiskInAmount = 10.00; input double RiskInPercent = 0.25; input group "HANDEL" input ENUM_SL SlVariable = SL_CANDLE; input uint SlInitial = 1500; input uint TpInitial = 3000; input group "DIVERS" input uint SymbolBuffer = 100; input ulong Magic = 202403271656; CTrade trade; ulong buyTicket; ulong sellTicket; double high1; double low1; static double outsideBarHigh; static double outsideBarLow; bool outsideBar; bool outsideBarRange; bool noSignal; bool longSignal; bool shortSignal; datetime timeRangeStart; datetime timeRangeEnd; datetime timeSignal; int OnInit(){ static bool isInit = false; if(!isInit){ isInit = true; Print(__FUNCTION__," > EA (re)start"); } return(INIT_SUCCEEDED); } void OnDeinit(const int reason){ } void OnTick(){ //---TimeRange if(timeRangeStart != StringToTime(TimeRangeStart)){ calcTimes(); } //---Signal if(TimeCurrent() >= timeRangeStart && TimeCurrent() < timeRangeEnd){ timeSignal = iTime(_Symbol,PERIOD_CURRENT,0); static datetime timestapSignal; if(timestapSignal != timeSignal){ timestapSignal = timeSignal; calcSetup(); } } //---Range Outsidebar if(outsideBar == true){ calcOutsideBarRange(); } //---Order if(longSignal == true){ executeBuy(); } longSignal = false; if(shortSignal == true){ executeSell(); } shortSignal = false; //---Close Order double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); if(OrderSelect(buyTicket) && bid <= OrderGetDouble(ORDER_SL)){ closeOrder(); } if(OrderSelect(sellTicket) && bid >= OrderGetDouble(ORDER_SL)){ closeOrder(); } } void calcTimes(){ timeRangeStart = StringToTime(TimeRangeStart); timeRangeEnd = StringToTime(TimeRangeEnd); } void calcSetup(){ double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); // Array erstellen MqlRates priceInformation[]; // Abwärts sortieren ArraySetAsSeries(priceInformation,true); // Preisdaten in das Array kopieren int Data = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),priceInformation); // Outsidebar[2] prüfen if(priceInformation[2].high >= priceInformation[1].high && priceInformation[2].low <= priceInformation[1].low){ outsideBar = true; outsideBarHigh = priceInformation[2].high; outsideBarLow = priceInformation[2].low; Print(priceInformation[2].time," no signal - outsideBar (H ",outsideBarHigh,"; L ",outsideBarLow,")"); Print(priceInformation[1].time," no signal - insideBar"); }else outsideBar = false; //---Candle 1 double open1 = iOpen(_Symbol,PERIOD_CURRENT,1); high1 = iHigh(_Symbol,PERIOD_CURRENT,1); low1 = iLow(_Symbol,PERIOD_CURRENT,1); double close1 = iClose(_Symbol,PERIOD_CURRENT,1); //---Candle 2 double open2 = iOpen(_Symbol,PERIOD_CURRENT,2); double high2 = iHigh(_Symbol,PERIOD_CURRENT,2); double low2 = iLow(_Symbol,PERIOD_CURRENT,2); double close2 = iClose(_Symbol,PERIOD_CURRENT,2); //---No Signal bool higherLowerBar = (high1 > high2 && low1 < low2); bool doji = (open1 == close1); if(higherLowerBar == true){ noSignal = true; if(outsideBar == true){ Print(priceInformation[1].time," no signal (H/L-Bar) - inside an outsideBar "); }else Print(priceInformation[1].time," no signal - higherLowerBar "); return; } if(doji == true){ noSignal = true; if(outsideBar == true){ Print(priceInformation[1].time," no signal (doji) - inside an outsideBar "); }else Print(priceInformation[1].time," no signal - doji "); return; } //---Long Signal bool lowerLow = (low1 < low2 && high1 <= high2); if(lowerLow == true){ if(outsideBarRange == true){ Print(priceInformation[1].time," no long signal - inside an outsideBarRange "); }else if(outsideBarRange == false){ longSignal = true; Print(priceInformation[1].time," !!! LONG SIGNAL"); } } //---Short Signal bool higherHigh = (high1 > high2 && low1 >= low2); if(higherHigh == true){ if(outsideBarRange == true){ Print(priceInformation[1].time," no short signal - inside an outsideBarRange "); }else if(outsideBarRange == false){ shortSignal = true; Print(priceInformation[1].time," !!! SHORT SIGNAL"); } } } void calcOutsideBarRange(){ double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); if(bid <= outsideBarHigh && bid >= outsideBarLow){ outsideBarRange = true; }else if(bid > outsideBarHigh || bid < outsideBarLow){ outsideBarRange = false; outsideBar =false; Print(" left OutsideBarRange"); } } void executeBuy(){ double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); double spread = roundUp(ask - bid); double sl = 0; double entry = roundUp(high1 + spread + SymbolBuffer * _Point); if(SlVariable == SL_FIX){ sl = entry - SlInitial * _Point; }else sl = roundUp(low1 - SymbolBuffer * _Point); double tp = roundUp(entry + TpInitial * _Point); Print(" Long: entry ",entry," (spread ",spread,"), sl ",sl,", tp ",tp); double lots = calclots(entry - sl); double price = SymbolInfoDouble(_Symbol,SYMBOL_BID); if(price < entry){ if(trade.BuyStop(lots,entry,_Symbol,sl,tp,0,0)){ if(trade.ResultRetcode() == TRADE_RETCODE_DONE){ buyTicket = trade.ResultOrder(); Print(" --> Buy-Stop-Order #",buyTicket," was sent"); } } } if(price >= entry){ if(trade.Buy(lots,_Symbol,entry,sl,tp)){ if(trade.ResultRetcode() == TRADE_RETCODE_DONE){ buyTicket = trade.ResultOrder(); Print(" --> Buy-Market-Order #",buyTicket," was sent"); } } } } void executeSell(){ double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); double spread = roundUp(ask - bid); double sl = 0; double entry = roundDn(low1 - SymbolBuffer * _Point); if(SlVariable == SL_FIX){ sl = entry + SlInitial * _Point; }else sl = roundDn(high1 + spread + SymbolBuffer * _Point); double tp = roundDn(entry - TpInitial * _Point); Print(" Short: entry ",entry,", sl ",sl," (spread ",spread,"), tp ",tp); double lots = calclots(sl - entry); double price = SymbolInfoDouble(_Symbol,SYMBOL_BID); if(price > entry){ if(trade.SellStop(lots,entry,_Symbol,sl,tp,0,0)){ if(trade.ResultRetcode() == TRADE_RETCODE_DONE){ sellTicket = trade.ResultOrder(); Print(" --> Sell-Stop-Order #",sellTicket," was sent"); } } } if(price <= entry){ if(trade.Sell(lots,_Symbol,entry,sl,tp)){ if(trade.ResultRetcode() == TRADE_RETCODE_DONE){ sellTicket = trade.ResultOrder(); Print(" --> Sell-Market-Order #",sellTicket," was sent"); } } } } void closeOrder(){ for(int i = OrdersTotal()-1; i >= 0; i--){ buyTicket = OrderGetTicket(i); if(OrderGetString(ORDER_SYMBOL) != _Symbol && OrderGetInteger(ORDER_MAGIC) != Magic) continue; if(OrderSelect(buyTicket) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP){ if(trade.OrderDelete(buyTicket)){ Print(" -x-> Buy-Stop-Order #",buyTicket," gelöscht da SL erreicht"); } } } for(int i = OrdersTotal()-1; i >= 0; i--){ sellTicket = OrderGetTicket(i); if(OrderGetString(ORDER_SYMBOL) != _Symbol && OrderGetInteger(ORDER_MAGIC) != Magic) continue; if(OrderSelect(sellTicket) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP){ if(trade.OrderDelete(sellTicket)){ Print(" -x-> Sell-Stop-Order #",sellTicket," gelöscht da SL erreicht"); } } } } double roundUp(double price){ double ticksize = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),_Digits); price = NormalizeDouble(price,_Digits); double rest = price - NormalizeDouble(price/ticksize,0) * ticksize; rest = NormalizeDouble(rest,_Digits); if(rest != 0){ for (double i = _Point; i <= ticksize; i += _Point){ price = NormalizeDouble(price + _Point,_Digits); rest = price - NormalizeDouble(price/ticksize,0) * ticksize; rest = NormalizeDouble(rest,_Digits); if(rest == 0) break; } } return price; } double roundDn(double price){ double ticksize = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),_Digits); price = NormalizeDouble(price,_Digits); double rest = price - NormalizeDouble(price/ticksize,0) * ticksize; rest = NormalizeDouble(rest,_Digits); if(rest != 0){ for (double i = _Point; i <= ticksize; i += _Point){ price = NormalizeDouble(price - _Point,_Digits); rest = price - NormalizeDouble(price/ticksize,0) * ticksize; rest = NormalizeDouble(rest,_Digits); if(rest == 0) break; } } return price; } double calclots(double slPoints){ // slPoints = Strecke (entry - sl; sl - entry) double lots = 0; double ticksize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE); double tickvalue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE); double lotstep = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep; if(Lotcalculation == LOT_FIX){ lots = NormalizeDouble(RiskInLots,_Digits); Print(" Fixe Lotsize: ",lots," lots"); } if(Lotcalculation == LOT_AMOUNT){ lots = NormalizeDouble(MathFloor(RiskInAmount / moneyPerLotstep) * lotstep,_Digits); Print(" Lotsize berechnet über Betrag: ",lots," lots"); } if(Lotcalculation == LOT_PERCENT){ // ACCOUNT_EQUITY = inkl. offene Positionen; ACCOUNT_BALANCE = ohne offene Positionen double riskPerTrade = AccountInfoDouble(ACCOUNT_EQUITY) * RiskInPercent / 100; lots = NormalizeDouble(MathFloor(riskPerTrade / moneyPerLotstep) * lotstep,_Digits); Print(" Lotsize prozentual berechnet: ",lots," lots"); } lots = MathMin(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX)); lots = MathMax(lots,SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN)); return lots; }
Es bleibt dabei, es wird nur dann angezeigt, dass die Range verlassen wurde, wenn dies mit der Bar[0] der Fall ist.
In obigem Bild wird mit open Kerze C die Kerze A als outsidebar deklariert. Da noch innerhalb der Kerze C der Kurs das High der outsidebar verlässt, wird dies im Journal um 11:02:28 Uhr auch korrekt wiedergegeben:
Mit open der Kerze 3 wird Kerze 1 als outsidebar deklariert. Hier verlässt der Kurs die Range der outsidebar erst mit Kerze 5 (11:08 Uhr) - und im Journal wird nichts ausgewiesen:
Das Ziel war, dass auch in diesem Beispiel irgendwann innerhalb der Minutenkerze um 11:08 Uhr die Meldung "left OutsideBarRange" kommt.
Keine Ahnung ob das funktioniert - werde ich aber testen ...

- 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 möchte mich auf eine Kerze, dem Außenstab, beziehen - weiß aber nicht, wie ich auf ihn zurückgreifen kann und vor allem, wie ich sein Hoch/Tief als Grenzbereich verwerten kann.
Folgendes Beispiel dazu:
Kerze 1 ist der Außenstab und wurde von mir mit open Kerze 3 wie folgt erfasst:
bool outsideBar = (high2 >= high1 && low2 <= low1);
Die Kerzen 2-4 sind allesamt Innenstäbe, bei denen nichts passieren soll. Erst wenn das Hoch oder Tief von Kerze 1 überschritten ist, kann oder soll ein neues Setup geprüft werden.
Mein Problem ist nun, wie kann ich mich auf die Kerze 1 beziehen? Da die Innenstäbe dazwischen beliebig viele sein können, kann ich mich nicht über die Anzahl der Kerzen auf den Außenstab beziehen. Wie nehme ich aber dann auf ihn Bezug? Gibt es einen Befehl, mit dem ich eine Kerze exakt deklarieren kann um mit deren Werten zu arbeiten? Ich vermute mal, dass es auch hier mit einer Schleife "irgendwie" funktioniert!? Aber auch hier muss ich ja die Kerze benennen ...
Über die Suche bin ich leider nicht fündig geworden - dafür aber dutzende Indikatoren zum Kauf angeboten bekommen ...
Schon jetzt vielen Dank für Hinweise und/oder Denkanstöße. :-)