Saving Labeled Prices from CArrayDouble to file doesnt work !

 

Hi Community,


this problems makes me crazy. I want to create buy and sell arrows/object on charts manually and i want the EA/script to save the prices of the arrow to a database.

The EA identifies when a Object is added successfully and also saves the price to an CArrayDouble correctly.

However the EA doesnt save the CArrayDouble correct to the file on Deinit, althoug i don't get an error.

On loading the file the CArrayDouble values are empty.

Does someone know a common CArrayDouble loading and saving problem or mistake and can help me ?

Is the problem on the saving side or the loading side ?


Best regards,
Benjamin

 

Here is my Code:

#define FilePrice   "Test_Labels_Price.bin"

#include <Arrays\ArrayDouble.mqh>
#include <Arrays\ArrayInt.mqh>

CArrayDouble      price;
int handlePrice;
int OnInit()
  {

//--- set the flag of receiving chart object creation events
   ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_CREATE,true);
//--- set the flag of receiving chart object removal events
   ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_DELETE,true);

//--- Read Signals out of File
   handlePrice=FileOpen(FilePrice,FILE_READ|  FILE_WRITE | FILE_BIN | FILE_COMMON | FILE_ANSI);

   if(!ReadFiles())
      return(INIT_FAILED);

   if(!PlotLabels())
      return(INIT_FAILED);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("---- Close (Deinit) ---");
   Print("Size to save");
   Print(price.Total());

   if(!price.Save(handlePrice))
      Print("Save to file failed");

   FileClose(handlePrice);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool ReadFiles()
  {

   if(!price.Load(handlePrice))
     {
      Print("Loading prices failed");
      price.Save(handlePrice); //Create new Data
      Print("Created new file to save data");
      handlePrice=FileOpen(FilePrice ,FILE_READ|  FILE_WRITE | FILE_BIN | FILE_COMMON | FILE_ANSI);
     }
   return(true);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool PlotLabels()
  {
//---

//---
   int size = price.Total();
   Print("---- Loading ----");
   Print("Labels to Load --> "+IntegerToString(size));

   ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_CREATE,false);
   int i = 0;
   for(i ; i < size-1; i++)
     {
      Print(price.At(i));
     }
   Print("Loaded --> "+IntegerToString(i));

   ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_CREATE,true);

   return(true);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+


OnChartEvent works fine:

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- the object has been deleted
   if(id==CHARTEVENT_OBJECT_DELETE)
     {
      Print("The object with name ",sparam," has been deleted");
     }
//--- the object has been created
   if(id==CHARTEVENT_OBJECT_CREATE)
     {
      //Print("The object with name ",sparam," has been created");
      AddLabel(sparam);
     }
  }

Add labeling to EA Array works fine

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool AddLabel(const string &cObject)
  {
   if(ObjectFind(ChartID(),cObject) == -1)
     {
      Print("ObjectNotFound");
      return(false);
     }

   if(!price.Add(ObjectGetDouble(ChartID(),cObject,OBJPROP_PRICE)))
     {
      Print("Failed to save price");
      return(false);
     }

   Print("--- New Label [" + IntegerToString(price.Total())+"] ---");
   Print(price.At(price.Total()-1));

   return(true);
  }
Dokumentation zu MQL5: Standardbibliothek / Datensammlungen / CArrayDouble
Dokumentation zu MQL5: Standardbibliothek / Datensammlungen / CArrayDouble
  • www.mql5.com
CArrayDouble - Datensammlungen - Standardbibliothek - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
Dateien:
 
Versuch doch erstmal fünf oder zehn Preise zu speichern und wieder abzurufen und auszudrucken. Nur nicht Alles auf einmal.
 
  1. Wir können hier deutsch reden :)
  2. Es ist nicht geschickt in OnDeinit() eine Datei zu sichern, da OnDeInit() nach kurzer Zeit zwangsweise(!) geschlossen wird, egal, ob 'drinnen' alles abgearbeitet wird.
  3. Ich verstehe Dein Programm nicht. Was soll es machen?
  4. Ich verwende meine eigenen Funktionen zum schreiben und lesen von Dateien, aber .csv oder .txt, die kann ich lesen und kontrollieren.
    Einlesen einer Datei insgesamt und übertragen in ein Array von Zeilen
   /* long fL = FileLoad(fName, Bytes, flag);
      Print(__FILE__", ",__LINE__," ",_ToStr(fName),_ToStr(fL),err());
      int iS  = StringSplit(CharArrayToString(Bytes), sepLine, l);
      Print(__FILE__", ",__LINE__," ",_ToStr(fName),_ToStr(iS),err());
      return(iS); */
int getCsvLines( const string fName, string &l[], int flag=0, ushort sepLine='\n') { // alternative to FileOpen 
   uchar Bytes[]; 
  return( FileLoad(fName, Bytes, flag) ? StringSplit(CharArrayToString(Bytes), sepLine, l) : 0);
}

und jetzt die Zellen einer Zeile in ein Array:

int getAllCells(const string line, string &cells[], ushort sepItm=';'){
   int nI = StringSplit(line,sepItm,cells); // ushort SepItem = StringGetCharacter(";",0);
   return(nI);
}

und hier meine Funktion eine Zeile zu einer Datei (in Common) hinzuzufügen (die Zeilen müssen mit \n enden!!):

//use:  addLineToFileCommon("line\n", "folder\\name.txt"); // shared=true, maxPrt=10
bool addLineToFileCommon(const string line, const string fName, const bool shared = true, const int maxPrt=10) {
   ResetLastError();
   static int nErr=0;
   int fH;
   if ( shared )
      fH = FileOpen(fName,FILE_READ|FILE_WRITE|FILE_BIN|FILE_COMMON|FILE_SHARE_READ|FILE_SHARE_WRITE);
   else 
      fH = FileOpen(fName,FILE_READ|FILE_WRITE|FILE_BIN|FILE_COMMON);
   if (fH == INVALID_HANDLE ) { if (nErr<maxPrt) ErrT("Common-File: >"+fName+"< Open FAILED"); return(false); }
   FileSeek(fH,0,SEEK_END);
   FileWriteString(fH, line, StringLen(line) );
   FileClose(fH);
   if (_LastError<2) return(true);
   if (nErr<maxPrt) ErrT("Write to Common-file: "+fName+" went wrong?");
   return(false);
}

Außerdem, wenn ein Programm nicht tut, was es soll, ist der Debugger das Mittel der Wahl!

Code-Debugging - Programme entwickeln - MetaEditor Hilfe
  • www.metatrader5.com
MetaEditor hat einen eingebauten Debugger, mit dem Sie die Programmausführung Schritt für Schritt (durch einzelne Funktionen) ü...
 
Tobias Johannes Zimmer #:
Versuch doch erstmal fünf oder zehn Preise zu speichern und wieder abzurufen und auszudrucken. Nur nicht Alles auf einmal.

Hi Tobias, danke für deine Antwort.

Der EA speichert ja nur die die Preise von meinen manuell erstellten Objekten ab. 

Wenn ich beispielsweise nur ein Objekt erstelle, erkennt der EA, dass ein Objekt erstellt wurde und speichert den Preis auch richtig im CArrayDouble ab.
Anscheinend wird dieser korrekte CArrayDouble mit den Preisen jedoch nicht korrekt im File auf Deinit abgespeichert.

Also selbst bei einem klappt es nicht.

 
Carl Schreiber #:
  1. Wir können hier deutsch reden :)
  2. Es ist nicht geschickt in OnDeinit() eine Datei zu sichern, da OnDeInit() nach kurzer Zeit zwangsweise(!) geschlossen wird, egal, ob 'drinnen' alles abgearbeitet wird.
  3. Ich verstehe Dein Programm nicht. Was soll es machen?
  4. Ich verwende meine eigenen Funktionen zum schreiben und lesen von Dateien, aber .csv oder .txt, die kann ich lesen und kontrollieren.
    Einlesen einer Datei insgesamt und übertragen in ein Array von Zeilen

und jetzt die Zellen einer Zeile in ein Array:

und hier meine Funktion eine Zeile zu einer Datei (in Common) hinzuzufügen (die Zeilen müssen mit \n enden!!):

Außerdem, wenn ein Programm nicht tut, was es soll, ist der Debugger das Mittel der Wahl!

Hi Carl,

vielen Dank für deine Antwort.

1. Ich möchte die Daten ja nur beim Beenden des Programms im File abspeichern. In der Zwischenzeit werden die Daten im CArrayDouble --> price abgespeichert. Das funktioniert auch wunderbar. Was einfach anscheinend nicht funktioniert ist die Standardfunktion von CArrayDouble ---> price.save(handle) . Ich verstehe nur nicht warum, da kein Fehler Code erstellt wird.
Oder das CArray wird ordentlich im File gespeichert und das Laden funktioniert nicht.

2. Im vorherigen Programm habe ich auch eine .txt datei genutzt und in String abgespeichert. Da ich in einem zukünftigen Projekt sehr viele Daten in Files speichern muss wollte ich die Standardfunktion von CArray testen.

3. Ja normalerweise nutze ich auch das Debugging, da es sich hier aber um manuell erstelle Objekte im Chart handelt, geht das im Debugging Modus nicht. Aber du hast mich auf die Idee gebracht einfach ein TestObjekt im Debugging per Routine zu erstellen. Ich teste das mal und schaue, ob ich einen Fehler finden kann.

Danke für deine Hilfe 

 
  1. Hast Du Dir die geschrieben Datei einmal angeschaut - mit Notepad++ zum Beispiel?
  2. In eine Datei sind immer nur 'Strings' gespeichert, es sei denn Du packst die Dateien durch zB. zip oder 7z ...
  3. Statt den Debugger kann man entweder Print verwenden - da kann aber das Log schnell sehr groß werden
    oder Comment() mit String-Variablen jeweils für eine Zeile und einem 'Thema'.
 

LÖSUNG:


Wenn die zu speichernde Datei erstmals von CArrayDouble erstellt wird, darf der Array anscheinend nicht leer sein, ansonsten ist die Datei kaputt.
Zwar wird die Datei anschließen wieder ohne Fehler geladen, jedoch können weder Daten in der Datei gespeichert noch geladen werden.

Ich habe die .bin datei manuell gelöscht und beim erstmaligen speichern einer neuen .bin datei vom EA habe ich vorsichtshalber direkt ein Testeintrag mitgegeben. Seitdem klappt es.