Einzelne Kerze als "Referenzkerze" bestimmen (Werte und/oder Zeit)

 

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. :-) 

 

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!

Dokumentation zu MQL5: Zugang zu Zeitreihen und Indikatoren / CopyRates
Dokumentation zu MQL5: Zugang zu Zeitreihen und Indikatoren / CopyRates
  • www.mql5.com
Bekommt im Feld rates_array historische Daten der Struktur MqlRates des angegebenen Symbol-Periode in der angegebenen Menge. Abzählen der...
 
Carl Schreiber #:

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.

 
Wie kann ich die Werte aus der Array-Position [2] dauerhaft prüfen bis diese Werte über- oder untertroffen werden?


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.

Die Ereignisverarbeitungsroutine "Neuer Balken"
Die Ereignisverarbeitungsroutine "Neuer Balken"
  • www.mql5.com
Die Programmiersprache MQL5 kann helfen, Probleme auf einer ganz neuen Ebene zu lösen. Selbst Aufgaben, für die es bereits eine Lösung gibt, können dank der objektorientierten Programmierung auf ein höheres Niveau gebracht werden. In diesem Beitrag geht es um ein besonders einfaches Beispiel für die Überprüfung des Auftretens eines neuen Balkens in einem Diagramm, das in ein leistungsfähiges und vielseitiges Hilfsmittel verwandelt wurde. Was ist das für ein Hilfsmittel? Das verrät dieser Artikel.
 
Carl Schreiber #:

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.

 
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.

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.

 
Carl Schreiber #:

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.

 
murkelmel #:

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?

Dokumentation zu MQL5: Grundlagen der Sprache / Variablen / Statische Parameter
Dokumentation zu MQL5: Grundlagen der Sprache / Variablen / Statische Parameter
  • www.mql5.com
Speicherklasse static bezeichnet statistische Variable. Modifikator static wird vor dem Datentyp angegeben. Beispiel: Statische Variable kann durch...
 
Carl Schreiber #:

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.

 
Eben kommt mir noch die Idee, ob man es evtl. damit hinbekommt, wenn man das High und Low der Range mit dem Zeitstempel verseht und anschließend den exakten Kurs zu diesem Zeitstempel abfragt und als Variable deklariert. Dann müsste der Wert der Variable nicht mehr veränderbar sein, oder?

Keine Ahnung ob das funktioniert - werde ich aber testen ...
Grund der Beschwerde: