Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools

Metatrader Forum | Forex Expert-Advisor | Broker & Forex Tools (http://www.expert-advisor.com/forum/index.php)
-   Programmierung MQL4 (http://www.expert-advisor.com/forum/forumdisplay.php?f=220)
-   -   Config Zeilen als Befehle ausführen (http://www.expert-advisor.com/forum/showthread.php?t=6612)

AVT 10.03.20 09:00

Config Zeilen als Befehle ausführen
 
Ich versuche Einstellungen über eine Textdatei zu speichern und anzuwenden, aber irgendwo ist noch ein Fehler. (Anmerkung: ne Textdatei deshalb, weil es einfach zu viele sind, sonst würde ich über GlobalVariables gehen.)

Ausgangslage: Benutzereingaben vom Typ bool, integer und string
Code:

extern bool  ShowHistory = false;  // old, historic lines (false)
extern int    StartDay    = 1;      // start day (1=Monday)
extern string EarliestTim = "07:00"; // begin trading day (DElocal 08:00)

Einstellungssicherung:
Code:


string ConfigFile=_Symbol+indName+".cfg";
void WriteConfigFile()
{
  int handle; 
  handle = FileOpen(ConfigFile,FILE_READ|FILE_WRITE|FILE_TXT,0);  //FileName,r|w|format,NoDelimiter
  FileWrite(handle,"ShowHistory="+IntegerToString(ShowHistory)+";\n", //bools
                    "StartDay="+IntegerToString(StartDay)+";\n",      //integers
                    "EarliestTim= \""+EarliestTim +"\" ;\n",          //strings
            );
  FileClose(handle);                                              //CloseTheFile
  if(handle<1)
      { Print(ConfigFile," not found, error code=", GetLastError());  }
}

Das Auslesen der Datei geschieht in OnInit:
Code:

if( FileIsExist(ConfigFile,0) )  ReadConfigFile();
Code:

bool ReadConfigFile()
{
  int handle;
  handle = FileOpen(ConfigFile,FILE_READ|FILE_TXT|FILE_ANSI); //ReadTextAnsi
  if(handle!=INVALID_HANDLE)                                  //ValidOpenedFile
  {
      string FoundLine;                                        //KeepingTheLine
      while(!FileIsEnding(handle))                            //AsLongAsWeHaveAnotherLine
      {
        FoundLine=FileReadString(handle);                    //ReadUntil"\r\n"
        Print(FoundLine);                                    //PrintWhatWeRead
      }
      FileClose(handle);                                      //FinallyCloseFile
  }
  else
      { Print(ConfigFile," open error, code=", GetLastError()); return(false); }
  return(true);
}

Die Ergebnisdatei sieht so aus:
Code:

ShowHistory=0;
StartDay=1;
EarliestTim= "07:00" ;

Da der Typ bereits in extern angegeben ist, sind die Zeilen gültige Befehle, das heißt ständen sie so in OnInit, würden sie ausgeführt.
Das aber werden sie nicht - ich habe immer noch die Benutzereinstellungen.
Die "FoundLine=FileReadString(handle);" scheint mir der Knackpunkt zu sein, aber auch wenn ich nur "FileReadString(handle);" benutze, komme ich nicht zum Ziel.
Wie kann ich den MT dazu zwingen, die Zeilen als Befehle auszuführen (so was wie 'exec Line')?
Danke. AVT

RetepM 10.03.20 13:51

Hi ich baute mir mal eine Funktion, die, die von einem Analyse-Programm erstellte Daten, einliest. Weil ich das für die verschiedensten Paare brauche, lege ich im Verzeichnis "C:\Users\xxx\AppData\Roaming\MetaQuotes\Terminal\ xxx\MQL4\Files\FromExternal\"Symbol()"\" die jeweilige ReadData.csv an. ReadData.csv würde in Deinem Fall 0;1;07:30 enthalten und wie folgt eingelesen werden.

void CheckReadData()
{
handle=FileOpen("FromExternal/"+Symbol()+"/ReadData.csv", FILE_CSV|FILE_READ,";");
if(handle>0)
{

ShowHistory = StrToInteger(FileReadString(handle));
StartDay = StrToInteger(FileReadString(handle));
EarliestTim= FileReadString(handle);

if(FileIsEnding(handle)==true)
FileClose(handle);
}
}

PS Ich lese bei jedem Programmstart zwischen 20 und 50 Variablen. Das funktioniert bei 28 Paar-Instanzen performant und ohne Probleme. In einem Dashboard habe ich das allerdings noch nicht probiert.

Gruß

AVT 10.03.20 21:43

Zitat:

Zitat von RetepM (Beitrag 43404)
PS Ich lese bei jedem Programmstart zwischen 20 und 50 Variablen. Das funktioniert bei 28 Paar-Instanzen performant und ohne Probleme. In einem Dashboard habe ich das allerdings noch nicht probiert.
Gruß

Danke Dir, ich habe also mal Deine CVS-Version probiert.
Aber das macht keinen Unterschied, ob das ne Text- oder CVS-Datei ist.
Ich vermute mal, Du hast keine externen Variablen, sondern weist die Werte internen Variablen zu ?? AVT

AVT 12.03.20 23:08

Problem bool Variablen
 
Die integer und string Variablen habe ich hinbekommen (für jede Benutzer-Variable noch eine "Programm-Variable", die zu Beginn entweder den Config- oder den Benutzer-Wert bekommt).

Die Schwierigkeit liegt bei den bool Variablen:
Gespeichert werden sie als Text in der Config-Datei, unabhängig davon ob das nun TEXT oder CVS Format ist. Wenn ich sie also aus der Textdatei wieder einlese, dann habe ich ja einen string.

Als Benutzerangabe nehme ich
Code:

extern bool Variable=true; // oder false
und zwar aus dem Grunde, weil da ganz klar (in Texform) steht, ob man als Benutzer wahr oder falsch wählt, denn ich kann von einem Benutzer nicht erwarten, daß er weiß was 0 und was 1 ist.
Ohne Config-Datei (also wenn die Angaben nicht gesichert werden sollen, sondern nur die aktuellen Benutzereingaben gelten) bekomme ich bei
Code:

Print(__FUNCTION__," SHOWHISTORY=",SHOWHISTORY);
//Resultat: OnInit SHOWHISTORY=false

also einen String. Beim Kompilieren krieg ich aber den Hinweis "implicit conversion from number to string", was wiederum nahelegt, daß es sich um einen integer handelt. Wenn ich aber dann umwandle:
Code:

SHOWHISTORY=StrToInteger(FileReadString(handle));
//Resultat: SHOWHISTORY=false auch wenn es true ist
//Config-File: true|true|false|true|....

Und sowas wie StringToBool gibt es nicht. Ist die einzige Lösung hier tatsächlich nur die Benutzerangaben als integer zu definieren und dann halt 0-false 1-true auch noch als Hinweis dazu zu schreiben?

Was ist Eure Meinung/Erfahrung dazu? AVT

AVT 13.03.20 14:58

(vorläufige) Lösung
 
1. externe Benutzervariable (Vorgaben in Klammern)
-. extern bool KeepValues = true; // save config (true)
-. extern int BoolShowHistory = 1; // show history (1=true)
-. extern int IntegerStopDay = 5; // stop at weekday (5)
-. extern string StringPremarkSig = "cb"; // name for premarket (cb)

2. interne Zuweisungsvariablen (heißen genauso wie die externen, nur alles Großbuchstaben)
-. int BOOLSHOWHISTORY = -1;
-. int INTEGERSTOPDAY = -1;
-. string STRINGPREMARKSIG = "";

A. Funktion für später, woher welche Werte kommen:
wenn die Zeilen zu lang werden, TXT zurücksetzen und nächste Zeile printen
Code:

void PrintResultFromConfig()
{
  string TXT="";
  TXT+=" BOOLSHOWHISTORY="+IntegerToString(BOOLSHOWHISTORY);
  TXT+=" INTEGERSTOPDAY="+IntegerToString(INTEGERSTOPDAY);
  TXT+=" STRINGPREMARKSIG="+STRINGPREMARKSIG;
  Print(TXT);
}

3. Ohne gespeicherte Werte bekommen die internen Zuweisungsvariablen den Wert der Benutzervariable:
Code:

void ReadUserSettings()
{
  BOOLSHOWHISTORY = BoolShowHistory;
  INTEGERSTOPDAY  = IntegerStopDay;
  STRINGPREMARKSIG= StringPremarkSig;
  Print(__FUNCTION__); PrintResultFromConfig();
}

4. Bei gespeicherten Werten werden die Wert aus der Speicherdatei gelesen
-. string indName = "IXDaLi"; // in OnInit: IndicatorShortName(indName);
-. string ConfigCVS=_Symbol+indName+".cvs"; // MQL4\Files\ConfigFileName

5. Speichern der Werte in der Speicherdatei:
Code:

void CheckWriteData()
{
  ResetLastError();
  int handle; 
  handle = FileOpen(ConfigCVS,FILE_CSV|FILE_WRITE,"|"); //FileName,ForWriting,Delimiter
 
  if(handle!=INVALID_HANDLE)                            //ValidOpenedFile
  {
      FileWrite(handle,
                BoolShowHistory,IntegerStopDay,StringPremarkSig
              );
      FileClose(handle);                                //CloseTheFile
  }
  else
  {
      Print(__FUNCTION__," FileOpen of ",ConfigCVS," failed, code=", GetLastError());
  }
}

6. Auslesen und Zuweisen der gespeicherten Werte:
Code:

void CheckReadData()
{
  ResetLastError();
  int handle=FileOpen(ConfigCVS,FILE_CSV|FILE_READ,"|"); //FileName,ForReading,Delimiter
  if(handle>0)
  {
      BOOLSHOWHISTORY  = StrToInteger(FileReadString(handle));
      INTEGERSTOPDAY  = StrToInteger(FileReadString(handle));
      STRINGPREMARKSIG = FileReadString(handle);
      if(FileIsEnding(handle)==true) FileClose(handle);  //EndReached,CloseTheFile
  }
  else
      { Print(ConfigCVS," open error, code=", GetLastError()); }
  Print(__FUNCTION__); PrintResultFromConfig();
}

7. Steuerung von Speichern oder nicht:
A. in OnInit:
Code:

  IndicatorShortName(indName);
  // === wenn Konfigurationsdatei existiert, einlesen, sonst Benutzereingaben
  if( FileIsExist(ConfigCVS,0) )  CheckReadData();
  else { Print(ConfigCVS," does not exist"); ReadUserSettings(); }

B. in OnDeinit:
Code:

  // === wenn Einstellungen behalten, Konfigurationsdatei schreiben, sonst löschen
  if(KeepValues) CheckWriteData();
  else if( FileIsExist(ConfigCVS,0) && !FileDelete(ConfigCVS,0) )
      Print(__FUNCTION__," deleting ",ConfigCVS," failed");

Anmerkungen:
Die einzige bool Variable bestimmt ob wir Einstellungen behalten wollen.
Bool Variablen, die im Indikator zur Steuerung verwendet werden, gehen nur über den Umweg als integer.
Das heißt im ganzen Indikator-Code müssen die Bedingungen von
if(BOOLSHOWHISTORY) auf if(BOOLSHOWHISTORY==1) geändert werden.

Eine Eigendefinition wie zum Beispiel
Code:

enum PPbase  //base of Pivot calculation
{  // === numeration starts at zero
  hlc3,
  ohlc1,
  hlcc4
};

kann man wie eine IntegerVariable behandeln, aber beim Auslesen erhält man eine Warnung: "implicit enum conversion".
Da es aber (ebenso wie StringToBool) keine StringToEnum gibt, ist mir das ehrlich gesagt Sch...egal.

Wenn noch jemand Kommentare hat, gerne her damit; ansonsten hoffe ich, irgendwem hilft das vielleicht. AVT


Alle Zeitangaben in WEZ +2. Es ist jetzt 15:35 Uhr.

Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.6.1
Powered by vBCMS® 2.7.0 ©2002 - 2024 vbdesigns.de
Copyright ©2009 - 2023 by Expert-Advisor.com - Das Metatrader Forum