Download MetaTrader 5

Cannot write to file

To add comments, please log in or register
HarriMQL5
350
HarriMQL5  

Hello

Im trying to create a .csv and .hst file. Everything seems to run fine, but I can see my files in the directory!

Can you please help?

Keith Watford
Moderator
9641
Keith Watford  

Use the search function on your computer, you know the file name.

If you are using the strategy tester files may be in tester\files

HarriMQL5
350
HarriMQL5  
GumRai:

Use the search function on your computer, you know the file name.

If you are using the strategy tester files may be in tester\files

Yes, already done a search. After I added a sub-directory the files appeared, but there is still something wrong - the data isnt being written to the files!
Fernando Carreiro
2279
Fernando Carreiro  
HarriMQL5:
Yes, already done a search. After I added a sub-directory the files appeared, but there is still something wrong - the data isnt being written to the files!
If you don't post any of your code, or provide elaborate details, it becomes difficult for us to try to help you. We cannot read your mind nor see your setup.
HarriMQL5
350
HarriMQL5  
FMIC:
If you don't post any of your code, or provide elaborate details, it becomes difficult for us to try to help you. We cannot read your mind nor see your setup.

I did post my code on the first post, using the SRC button, but it didnt show up. Here it is again, inline:

#property strict
//--- input parameters
input int      range                                           = 10;


int             unused[13], csvHndl, hstHndl;
double          last, nPoint = 1;
datetime        now;

/*
extern string   file                                            = "";
extern bool     printRecords                                 = false;
*/
MqlRates        rate;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void init ()
{
    int x;
    if (Digits % 2 == 0) x = Digits; else { x = Digits-1; }
    while (x > 0) { nPoint /= 10; x--; }

    string file = Symbol()+(string)range+"r";
    hstHndl = FileOpenHistory(file + ".hst", FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ);
    csvHndl = FileOpenHistory(file + ".csv", FILE_CSV|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ);
   
    PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
   
    FileWriteLong(hstHndl, 401);                                    // version
    FileWriteString(hstHndl, "Copyright © 2016 Harrison Forex", 64);//c_copyright
    string sym = Symbol();
    FileWriteString(hstHndl, sym, 12);                              // c_symbol
    FileWriteInteger(hstHndl, 5, LONG_VALUE);                       //i_period
    FileWriteInteger(hstHndl, 4, LONG_VALUE);                       //i_digits
    FileWriteLong(hstHndl, TimeCurrent());                          //time_sign
    FileWriteInteger(hstHndl, 0, LONG_VALUE);                       //last_sync
    FileWriteArray(hstHndl, unused, 0);
   
    rate.high = Close[0];
    rate.low = Close[0];
    rate.open = Close[0];
    rate.time = TimeCurrent();
    rate.real_volume = 0;
    rate.tick_volume = 0;
    rate.spread = 2;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
void OnTick()
{
    now = TimeCurrent();
    //if (last == Close[0]) return;
    last = Close[0];

    rate.high = MathMax(rate.high, Close[0]);
    rate.low = MathMin(rate.low, Close[0]);
   
    if (rate.high-rate.low > range * nPoint) {
        Print(rate.high," ",rate.low," ",rate.high-rate.low);
        while (rate.high-rate.low > range * nPoint) {
            int idx, idx2, dirn;
            dirn = (sign(last-rate.high) + sign(last-rate.low));
            idx = (1-dirn)/2;
            idx2 = (1+dirn)/2;
            //dirn      idx idx2
            // +1        0   1
            // -1        1   0
            rate.low = iif(idx == 0, rate.low, rate.high - range * nPoint);
            rate.high = iif(idx == 0, rate.low + range * nPoint, rate.high);
            rate.close = iif(idx == 0, rate.high, rate.low);
           
            FileWriteStruct(hstHndl, rate);
            FileFlush(hstHndl);
            FileWrite(csvHndl,rate.time, rate.open, rate.low, rate.high, rate.close,rate.real_volume,rate.spread,rate.tick_volume);
            FileFlush(csvHndl);

            rate.low = rate.close; rate.high = rate.close; rate.open = rate.close; rate.time = TimeCurrent();
            rate.high = MathMax(rate.high, Close[0]);
            rate.low = MathMin(rate.low, Close[0]);
            rate.real_volume = 0; rate.tick_volume = 0;
        }
    } else {
        rate.tick_volume++; rate.real_volume++; rate.close = last;
    }   
    /*
    Comment("\n"+dateTime(now)+"\n"+DoubleToStr(rate.open,Digits)+" "+
    DoubleToStr(rate.high,Digits)+" "+DoubleToStr(rate.low,Digits)+" "+
    (string)rate.real_volume," ",rate.tick_volume);
    */
    return;
}
//+------------------------------------------------------------------+
string dateTime(datetime pNow)
{
    string dDateTime;
   
    switch(TimeDayOfWeek(pNow))
    {
        case 0: { dDateTime = "Sunday "; break; }
        case 1: { dDateTime = "Monday "; break; }
        case 2: { dDateTime = "Tuesday "; break; }
        case 3: { dDateTime = "Wednesday "; break; }
        case 4: { dDateTime = "Thursday "; break; }
        case 5: { dDateTime = "Friday "; break; }
        case 6: { dDateTime = "Saturday "; break; }
    }
    dDateTime = dDateTime+" "+TimeToStr(pNow,TIME_DATE)+" "+TimeToStr(pNow,TIME_SECONDS);
   
    return(dDateTime);
}
//+------------------------------------------------------------------+
void deinit()
{
    FileFlush(hstHndl);
    FileClose(hstHndl);
    FileFlush(csvHndl);
    FileClose(csvHndl);
    if (hstHndl > 0) {
    /*
        FileSeek(hstHndl, 0x58, SEEK_SET);
        FileWriteInteger(hstHndl, (int)TimeCurrent());
        FileFlush(csvHndl);
    */
        FileClose(hstHndl);
    }   
     if (csvHndl > 0) {
         FileClose(csvHndl);
     }      
}
//---------------------------------------------------
double iif( bool condition, double ifTrue, double ifFalse )
{
    if( condition ) return( ifTrue );
   
    return( ifFalse );
}
//----------------------------------------
int sign( double val)
{
    if (val < 0) return(-1);
    if (val > 0) return(1);
    return(0);
}
Fernando Carreiro
2279
Fernando Carreiro  
HarriMQL5:
I did post my code, using the SRC button
Where? We don't see it! Do you see it on your post?
HarriMQL5
350
HarriMQL5  
One more thing, Im using the /portable switch when running metatrader
Files:
Fernando Carreiro
2279
Fernando Carreiro  
HarriMQL5:
One more thing, Im using the /portable switch when running metatrader
  1. OK! Assuming "/portable", the use of "FileOpenHistory" outputs the files to the "%mt4_root%/history/%broker-server-name%" folder. Are you sure that is where you want to put the CSV file?
  2. Usually you would use the "FileOpen()" function for CSV, so that the files go to the "%mt4_root%/MQL4/Files" folder or the "%mt4_root%/tester/files" (if in the Strategy Tester).
  3. Also, for the History File, use "FILE_BIN | FILE_WRITE | FILE_SHARE_READ". Don't share Write access. The same goes for the CSV files but as "FILE_CSV | FILE_WRITE | FILE_SHARE_READ".
  4. You are not testing the file handles "hstHnd" and "csvHndl" for validity. You are just assuming it will always work. Test the handles, and if not valid, check which errors are being returned.
  5. You are using "special" characters in the Copyright field. This is not a unicode file, so don't use any special characters. Rather use "(c)" instead.
    FileWriteString(hstHndl, "Copyright © 2016 Harrison Forex", 64);//c_copyright
  6. Why use 4 digits explicitly? It is best to use the actual number of digits for the Symbol in question.
    FileWriteInteger(hstHndl, 4, LONG_VALUE); //i_digits (use the variable "Digits" or "_Digits" instead)
  7. You are using the Period/Timeframe of "5" for the History files, but that is reserved for the Standard M5 History files. Don't overwrite standard files. Use an unused time-frame such as "6" for example.
    FileWriteInteger(hstHndl, 5, LONG_VALUE); //time_sign (use 6 instead or some other unused time-frame)
  8. Explicitly set the array size for padding the header to prevent problems: (see two posts down for correct answer)
    FileWriteArray(hstHndl, unused, 0, 48);
  9. Also, make sure to flush the Header as well (before continuing) to prevent any misreading if the file is open at the same time on an offline chart.
    FileFlush(hstHndl);
EDIT: Please note that this post was edited/updated several times, so recheck its contents again.
HarriMQL5
350
HarriMQL5  

Ok, the files are being filled up now. So the purpose of the script / EA is to generate a HST and corresponding CSV file. The data will be rangebars, not the standard usual timeframe bars that come as standard with metatrader. Bearing this in mind:

1. Dont care where the CSV file ends up as long as I can find it.

2. I looked the the example here and changed from using FileOpenHistory to FileOpen

3. Ok

4. Although I dont test in the code I put in a print statement to see if the handles get set to valid values - and they do get set.

5. Ok (the symbol, copyright fields are blank, so this could be the reason)

6. The (tick) data Im using to generate the rangebars is 4-digit (Dukascopy)

7. Yes. Generating the csv/hst is the first part of being able to backtest rangebars with real tickdata. You have to specify a standard timeframe for StrategyTester to use, although the actual bars (OHLC) will be range bars.

8. Sorry? Im looking at the file format here, which says its 52 bytes (Also, 52 divides nicely by 13 - the number of elements in the array - like a pack of cards. 48 doesnt divide so nicely)

9. Ok


Its working now, thanks. Still got a couple of minor bugs but its working. Thanks again!

Fernando Carreiro
2279
Fernando Carreiro  
HarriMQL5:

Ok, the files are being filled up now. So the purpose of the script / EA is to generate a HST and corresponding CSV file. The data will be rangebars, not the standard usual timeframe bars that come as standard with metatrader. Bearing this in mind:

1. Dont care where the CSV file ends up as long as I can find it.
2. I looked the the example here and changed from using FileOpenHistory to FileOpen
3. Ok
4. Although I dont test in the code I put in a print statement to see if the handles get set to valid values - and they do get set.
5. Ok (the symbol, copyright fields are blank, so this could be the reason)
6. The (tick) data Im using to generate the rangebars is 4-digit (Dukascopy)
7. Yes. Generating the csv/hst is the first part of being able to backtest rangebars with real tickdata. You have to specify a standard timeframe for StrategyTester to use, although the actual bars (OHLC) will be range bars.
8. Sorry? Im looking at the file format here, which says its 52 bytes (Also, 52 divides nicely by 13 - the number of elements in the array - like a pack of cards. 48 doesnt divide so nicely)
9. Ok

Its working now, thanks. Still got a couple of minor bugs but its working. Thanks again!

4. Get into the habit of ALWAYS testing. You never know where and when something could go wrong!

6. Dukascopy data is 5 digits. I don't know where you are getting 4 digits. Either way, don't assume. Use the "Digits" or "_Digits" for the Symbol in question.

7. Producing ".hst" files, will not allow you to be able to back-test range bars. To do that, you have to produce ".fxt" files and not ".hst" files. I know this for a fact, because I do this every day on my own setup to produce my own ADBars (a propriety bar format of my own). Producing ".hst" files on top of standard time-frames is not the answer, as you will loose all the tick data for the test, as it will just generate "pseudo" tick data build up from the HST files.

8. I am using 48 in my own code, but there may be another 4 bytes padding somewhere else accounting for the discrepancy. I will have to check and get back to you on this one. See edit below.

EDIT: Point 8. Figured out why using 48 or 52 makes no difference, because the FileWriteArray Count is based on the array type and number of elements and not on bytes. So in actual fact the correct value would be 13. So 48, 52 or any other value greater than 13, will always give the same result; because the array only has 13 elements and no more. So your way, of not mentioning the number of elements is correct, and I will change my own code accordingly.

Fernando Carreiro
2279
Fernando Carreiro  

One more point I just noticed which seems incorrect:

FileWriteLong(hstHndl, 401); // version
...
FileWriteLong(hstHndl, TimeCurrent()); //time_sign

According to the documentation, the FileWriteLong() function will output 8 bytes and not the intended 4 bytes. It should instead be:

FileWriteInteger(hstHndl, 401, INT_VALUE); // version
...
FileWriteInteger(hstHndl, TimeCurrent(), INT_VALUE); // time_sign

Although, MQL4 has mapped the constant LONG_VALUE to be the same as INT_VALUE (for backwards compatibility), it is an error and obsolete, so strictly speaking, you should use INT_VALUE in your other lines as well, instead of LONG VALUE, to make it future safe (or simply not use it as it is the default):

FileWriteInteger(hstHndl, 401); // version
    ...
FileWriteInteger(hstHndl, TimeCurrent()); // time_sign
12
To add comments, please log in or register