ObjectGetValueByTime liefert nicht den erwarteten Wert

 

Hallo,

Im Nachschlagewerk steht, dass man mit dieser Funktion einen Wert bei einem bestimmten Zeitpunkt bekommen kann.

Da mich das für OBJ_STDDEFCHANNEL mit wenn ich eingebe, dass ich gerne die Werte der Linien des DevChannels

https://www.mql5.com/de/docs/constants/objectconstants/enum_object/obj_stddevchannel

für den aktuellen Bar berechnen möchte und diese dann als "Preise" für horizontale Linien verwende, würde ich erwarten, dass sich

1. diese im x-Wert der aktuellen Kerze mit dem Kanal schneiden und außerdem müsste, wenn ich

2. von den Werten der Kanallinien mit GetObjectTimeByValue die Zeit wieder berechne, doch wieder die Eröffnungszeit aktuellen Kerze sein.

Das ist aber beides nicht der Fall. Liegt das an Eigenheiten des Objekts oder habe ich irgendwo einen Fehler drin? Habe ihn nach einer Anleitung aus dem Internet nachgemacht und der Channel sieht auch optisch so aus wie er aussehen soll... aber seht selbst:

ChannelGetValue

Wow... was sind denn das für DDR-Farben? die drei waagerechten Linien sind DodgerBlue aber man sieht sie fast nicht... naja. Diese waagerechten Kontrollinien müssten sich also an der Stelle der aktuellen Kerze mit den Linien des Kanals schneiden und die Werte der Schnittpunkte müssten oben links in dem Kommentar stehen. Ich verstehe einfach nicht, wo der die Werte hernimmt.

Falls es jemand zu Hause nachmachen möchte:

      static int TickCount=0;
      int ChannelStart01=300;        //ab hier wird der Kanal berechnet, hier letzte 300 Bars => 299 bis 0
      double High01[], Low01[];
      MqlRates Preisdaten[];
      int Highest01, Lowest01;
      int Data;
      
      double Lowest01Value, Highest01Value;  //Normalisiert den Wert der Extrema auf zwei Nachkommastellen zum Anzeigen als Comment
      
      double Line01Value,Line02Value,Line03Value;                 //holt den Wert der Linie des Kanals mit Hilfe der Zeit
      datetime Line01ValueTime, Line02ValueTime, Line03ValueTime; //holt die Zeit eines Werts der Linien des Kanals (Kontrolle)

void OnDeinit(const int reason=1)
  {
                                              //Lösche die alten Objekte
   ObjectDelete(0,"DevChannel01");
   ObjectDelete(0,"HLine01");
   ObjectDelete(0,"HLine02");
   ObjectDelete(0,"HLine03");

  }

void OnInit()
  {
      
      ArraySetAsSeries(High01,true);             //Arrays als Zeitreihe => Start bei 299 bis 0(aktueller Bar)
      ArraySetAsSeries(Low01,true);
      ArraySetAsSeries(Preisdaten,true);
      
      Data= CopyRates(_Symbol,_Period,0,ChannelStart01,Preisdaten);       //Die Rates kommen in eine ArrayStruktur 
      
      CopyHigh(_Symbol,_Period,0,ChannelStart01,High01);                 //Die Hochs und Tiefpunkte der Bars in ihre Arrays
      CopyLow(_Symbol,_Period,0,ChannelStart01,Low01);
      
      
      Lowest01= ArrayMinimum(Low01,0,ChannelStart01);            //Berechnung der Extrema der Zeitreihe von 300 Bars
      Highest01= ArrayMaximum(High01,0,ChannelStart01);

      
      Lowest01Value= NormalizeDouble(Low01[Lowest01],2);            //zum Anzeigen der Werte als Comment
      Highest01Value= NormalizeDouble(High01[Highest01],2); 
                 
       
     
  }

void OnTick()
  {
      
                                  
      TickCount++;                                     
      if (newBar()==true) 
      {
      TickCount=0;
      SetObjectProperties();
      }

      ObjectDelete(0,"DevChannel01");
      ObjectDelete(0,"HLine01");
      ObjectDelete(0,"HLine02");
      ObjectDelete(0,"HLine03");

      
      ObjectCreate(
                     0,                                   // chart id
                     "DevChannel01",                      // Name des konkreten Objekts
                     OBJ_STDDEVCHANNEL,                   // Objekzbezeichnung
                     0,                                   // Index des Fensters
                     Preisdaten[ChannelStart01-1].time,   // Zeit des ersten Ankerpunktes
                     Preisdaten[Lowest01].low,            // Preis des ersten Ankerpunktes
                     Preisdaten[0].time,                  // Zeit des Nten Ankerpunktes
                     Preisdaten[Lowest01].low,            // Preis des Nten Ankerpunktes
                     Preisdaten[ChannelStart01-1].time,   // Zeit des Aufspannpunktes
                     Preisdaten[Highest01].high           // Preis des Aufspannpunktes
                                                          // Soweit ich das verstanden habe wenn ich jeweils die x- und y-Werte der Punkte 
                                                          // zusammennehme, wird hier ein Rechteck erstellt, das den gesamten Graphen im
fraglichen Zeitraum einrahmt. Also nicht die drei Linien, die angezeigt werden. 
                  );
                  
//--------------------------------------------------                  
//Hilfslinien zur Verdeutlichung des Problems

       ObjectCreate(
                      0,
                      "HLine01",
                      OBJ_HLINE,
                      0,
                      Preisdaten[0].time,
                      Line01Value
                   );
       
       ObjectCreate(
                      0,
                      "HLine02",
                      OBJ_HLINE,
                      0,
                      Preisdaten[0].time,
                      Line02Value
                   );
       ObjectCreate(
                      0,
                      "HLine03",
                      OBJ_HLINE,
                      0,
                      Preisdaten[0].time,
                      Line03Value
                   );

// Hier wird der Ausgabewert des ObjectGetValue vom Channel kontrolliert, indem horizontale Linien mit den Y-Werten 
// erstellt werden, die er ausspuckt. Das heißt, wenn ich eingebe, dass ich gerne die Werte der Linien des DevChannels
// für den aktuellen möchte und diese dann als "Preise" für horizontale Linien verwende, würde ich erwarten, dass sich 
// diese im x-Wert der aktuellen Kerze mit dem Kanal schneiden (was momentan nur eine von den Dreien tut) und außerdem wenn 
//ich von den Werten der Kanallinie mit GetObjectTimeByValue die Zeit wieder berechne, müsste die Zeit doch auch die Eröffnungszeit 
//der aktuellen Kerze sein. Einmal kommt sogar ein Zeitwert mit 01.01.1970 heraus.

// Das ist also Beides nicht der Fall! Was ist denn hier falsch?
//       
       Line01Value = ObjectGetValueByTime(0,"DevChannel01", Preisdaten[0].time, 0); //Eigentlich ist die Zeit hier die Zeit
       Line02Value = ObjectGetValueByTime(0,"DevChannel01", Preisdaten[0].time, 1); //der aktuellen Kerze, die als x-Wert einge-
       Line03Value = ObjectGetValueByTime(0,"DevChannel01", Preisdaten[0].time, 2); //setzt wird, um den Wert der Linie zu ermitteln
                                                                                    // 
                                                                                    //
       Line01ValueTime = ObjectGetTimeByValue(0,"DevChannel01", Line01Value, 0);    //doch dann müssten sich diese drei Hilfslinien
       Line02ValueTime = ObjectGetTimeByValue(0,"DevChannel01", Line02Value, 0);    //an der Zeit der letzten Kerze mit den Linien
       Line03ValueTime = ObjectGetTimeByValue(0,"DevChannel01", Line03Value, 0);    //des Kanals schneiden, oder?
       
        
       
       Comment("HIGHESTVALUE= ",Highest01Value,
               "\n","LOWESTVALUE= ",Lowest01Value,
               "\n","Last Error: ",GetLastError(),
               "\n","Line01Value= ",Line01Value,
               "\n","Line01ValueTime= ",Line01ValueTime,
               "\n","Line02Value= ",Line02Value,
               "\n","Line02ValueTime= ",Line02ValueTime,
               "\n","Line03Value: ",Line03Value,
               "\n","Line03ValueTime= ",Line03ValueTime/*,
               "\n","TickCount= ", TickCount*/);
       

          
  }
//+---------------------------------

bool newBar()
  {
   static datetime TimeBar=0;
   bool flag=false;
   if(TimeBar!=iTime(Symbol(),Period(),0))
     {
      TimeBar=iTime(Symbol(),PERIOD_CURRENT,0);
      flag=true;
     }
// return true if you are in new bar.
   return (flag);
  }
  
void SetObjectProperties()
   {    
       ObjectSetInteger(0,"DevChannel01",OBJPROP_COLOR,clrLawnGreen);
       ObjectSetInteger(0,"DevChannel01",OBJPROP_WIDTH,2);
       ObjectSetInteger(0,"DevChannel01",OBJPROP_RAY_RIGHT,true);
       ObjectSetDouble(0,"DevChannel01",OBJPROP_DEVIATION,1.5);
       
       ObjectSetInteger(0,"HLine01",OBJPROP_WIDTH,0);
       ObjectSetInteger(0,"HLine01",OBJPROP_COLOR,clrDodgerBlue);
       ObjectSetInteger(0,"HLine02",OBJPROP_WIDTH,0);
       ObjectSetInteger(0,"HLine02",OBJPROP_COLOR,clrDodgerBlue);
       ObjectSetInteger(0,"HLine03",OBJPROP_WIDTH,0);
       ObjectSetInteger(0,"HLine03",OBJPROP_COLOR,clrDodgerBlue);
   }   
Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Objektkonstanten / Objekttypen / OBJ_STDDEVCHANNEL
Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Objektkonstanten / Objekttypen / OBJ_STDDEVCHANNEL
  • www.mql5.com
OBJ_STDDEVCHANNEL - Objekttypen - Objektkonstanten - Konstanten, Enumerationen und Strukturen - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
 

Wahrscheinlich ist ObjectCreate falsch:

  1. Du fragst nicht ab, ob ObjectCreate das Objekt erzeugt hat und falls nicht welchen Fehler es gibt.
  2. Schau mal hier wie Dein StdDev-Kanal definiert wird: https://www.mql5.com/en/docs/constants/objectconstants/enum_object/obj_stddevchannel
Documentation on MQL5: Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_STDDEVCHANNEL
Documentation on MQL5: Constants, Enumerations and Structures / Objects Constants / Object Types / OBJ_STDDEVCHANNEL
  • www.mql5.com
OBJ_STDDEVCHANNEL - Object Types - Objects Constants - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Carl Schreiber:

Wahrscheinlich ist ObjectCreate falsch:

  1. Du fragst nicht ab, ob ObjectCreate das Objekt erzeugt hat und falls nicht welchen Fehler es gibt.
  2. Schau mal hier wie Dein StdDev-Kanal definiert wird: https://www.mql5.com/en/docs/constants/objectconstants/enum_object/obj_stddevchannel


Ja, hast Du völlig Recht, habe ich nicht abgefragt. Allerdings kann man auf dem Screenshot erkennen, dass der Kanal erzeugt wurde. Er funktioniert auch genau wie erwartet, bewegt sich, wenn man die Indexnummer ändert, stelllt sich in Richtung des Trends usw. Ich bin sogar ziemlich sicher, dass das Objekt erzeugt wurde.

Und zu Nummer zwei, die Seite aus der Doku habe ich doch in der vierten Zeile zitiert. Dazu habe ich eine Frage: Wo wird da etwas definiert, was ich jetzt gerade gebrauchen kann? Da ist ein Script als Beispiel und die ObjectCreate wird dort total komisch angegeben (nur mir Zeiten?!?). Mir ist nicht ersichtlich, was Du genau sagen willst. Sag mal oben oder unten oder Codezeile... heiß kalt irgendwas.

Du musst mir nicht helfen, es steht Dir frei, nicht zu antworten.

 

Dort wird der StdDev-Kanal so erstellt:

 if(!ObjectCreate(chart_ID,name,OBJ_STDDEVCHANNEL,sub_window,time1,0,time2,0)) 

Schaut etwas anders aus, als bei Dir.

 
Carl Schreiber:

Dort wird der StdDev-Kanal so erstellt:

Schaut etwas anders aus, als bei Dir.


Mit Deiner Version steht da zwar auch loaded successfully, auch wenn ich sage if ! Print Error blabla.

Doch die HLinien sind immer noch irgendwo im Nirgendwo. Man beachte auch den Wert aus den Siebzigern. Lasse mich gernen belehren.

loaded successfully

Aber danke schonmal.




NACHTRAG:

Heute habe ich die Lösung gefunden und zwar in diesem Thread hier: https://www.mql5.com/en/forum/280520#comment_8773757

Er besagt, dass die ObjectGetValueByTime beim Nächsten Tick abgefragt werden sollte, weil das eine Eigenart des Objekts ist, dass die Objektfunktion erst läuft wenn alle anderen Funktionen abgerattert sind.

Daher muss man einfach die ObjectGetValueByTime in der OnTick() ÜBER die ObjectCreate setzen, damit sie als Erstes abgefragt wird, weil die Daten erst am Ende des letzten Ticks überhaupt erstellt werden.

Und weil es so schön war:

Cheneiden


Man sieht hier ganz schön wie die horizontalen Kontrolllinien die Kanallinien im Index [0] schneiden. zur Verdeutlichung wurde eine vertikale Kontrollinie eingeführt

Dokumentation zu MQL5: Allgemeine Funktionen / Comment
Dokumentation zu MQL5: Allgemeine Funktionen / Comment
  • www.mql5.com
Comment - Allgemeine Funktionen - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5