forked from rosh/MQL5Book
197 lines
7.8 KiB
MQL5
197 lines
7.8 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| FileAtomic.mq5 |
|
|
//| Copyright 2021, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#include "..\..\Include\PRTF.mqh"
|
|
#include "..\..\Include\Periods.mqh"
|
|
#include "..\..\Include\FileHandle.mqh"
|
|
|
|
|
|
#define BARLIMIT 10 // number of bars to write into test file
|
|
#define TFLEN 3 // length of timeframe name in the file
|
|
|
|
const string filename = "MQL5Book/atomic.raw";
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Interface for writing/reading objects to/from files |
|
|
//+------------------------------------------------------------------+
|
|
interface Persistent
|
|
{
|
|
bool write(int handle);
|
|
bool read(int handle);
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Class with specific file format header |
|
|
//+------------------------------------------------------------------+
|
|
class FileHeader : public Persistent
|
|
{
|
|
const string signature;
|
|
public:
|
|
FileHeader() : signature("CANDLES/1.1") { }
|
|
bool write(int handle) override
|
|
{
|
|
PRTF(FileWriteString(handle, signature, StringLen(signature))); // 11
|
|
PRTF(FileWriteInteger(handle, StringLen(_Symbol), CHAR_VALUE)); // 1
|
|
PRTF(FileWriteString(handle, _Symbol)); // 6, for XAUUSD
|
|
PRTF(FileWriteString(handle, PeriodToString(), TFLEN)); // 3
|
|
// TODO: check _LastError
|
|
return true;
|
|
}
|
|
bool read(int handle) override
|
|
{
|
|
const string sig = PRTF(FileReadString(handle, StringLen(signature))); // CANDLES/1.1
|
|
if(sig != signature)
|
|
{
|
|
PrintFormat("Wrong file format, header is missing: want=%s vs got %s",
|
|
signature, sig);
|
|
return false;
|
|
}
|
|
const int len = PRTF(FileReadInteger(handle, CHAR_VALUE)); // 6
|
|
const string sym = PRTF(FileReadString(handle, len)); // XAUUSD (example)
|
|
if(_Symbol != sym)
|
|
{
|
|
PrintFormat("Wrong symbol: file=%s vs chart=%s", sym, _Symbol);
|
|
return false;
|
|
}
|
|
const string stf = PRTF(FileReadString(handle, TFLEN)); // H1 (example)
|
|
if(_Period != StringToPeriod(stf))
|
|
{
|
|
PrintFormat("Wrong timeframe: file=%s(%s) vs chart=%s",
|
|
stf, EnumToString(StringToPeriod(stf)), EnumToString(_Period));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Simple class to write and read partial rates using files |
|
|
//+------------------------------------------------------------------+
|
|
class Candles : public Persistent
|
|
{
|
|
FileHeader header;
|
|
int limit;
|
|
MqlRates rates[];
|
|
public:
|
|
Candles(const int size = 0) : limit(size)
|
|
{
|
|
if(size == 0) return;
|
|
int n = PRTF(CopyRates(_Symbol, _Period, 0, limit, rates)); // 10
|
|
if(n < 1)
|
|
{
|
|
limit = 0; // init failed
|
|
}
|
|
limit = n; // can be less than requested
|
|
}
|
|
|
|
bool write(int handle) override
|
|
{
|
|
if(!limit) return false; // no data
|
|
// delegate header writing to the header itself
|
|
if(!header.write(handle)) return false;
|
|
// save record count
|
|
PRTF(FileWriteInteger(handle, limit)); // 4
|
|
// save date range (last, first)
|
|
PRTF(FileWriteLong(handle, rates[0].time)); // 8
|
|
PRTF(FileWriteLong(handle, rates[limit - 1].time)); // 8
|
|
// save array of rates
|
|
for(int i = 0; i < limit; ++i)
|
|
{
|
|
FileWriteStruct(handle, rates[i], offsetof(MqlRates, tick_volume));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool read(int handle) override
|
|
{
|
|
if(!header.read(handle))
|
|
{
|
|
return false;
|
|
}
|
|
limit = PRTF(FileReadInteger(handle)); // 10
|
|
ArrayResize(rates, limit);
|
|
ZeroMemory(rates);
|
|
// dates must be read but are not used so far
|
|
datetime dt0 = (datetime)PRTF(FileReadLong(handle)); // 1629212400 (example)
|
|
datetime dt1 = (datetime)PRTF(FileReadLong(handle)); // 1629248400 (example)
|
|
|
|
for(int i = 0; i < limit; ++i)
|
|
{
|
|
FileReadStruct(handle, rates[i], offsetof(MqlRates, tick_volume));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void print() const
|
|
{
|
|
ArrayPrint(rates);
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Script program start function |
|
|
//+------------------------------------------------------------------+
|
|
void OnStart()
|
|
{
|
|
// Part I. Writing
|
|
// create new file or open existing one and empty it
|
|
FileHandle handle(PRTF(FileOpen(filename,
|
|
FILE_BIN | FILE_WRITE | FILE_ANSI | FILE_SHARE_READ))); // 1
|
|
// request rates
|
|
Candles output(BARLIMIT);
|
|
// fill the file with data by persistent object
|
|
if(!output.write(~handle))
|
|
{
|
|
Print("Can't write file");
|
|
return;
|
|
}
|
|
output.print();
|
|
/*
|
|
example output for XAUUSD,H1
|
|
[time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume]
|
|
[0] 2021.08.17 15:00:00 1791.40 1794.57 1788.04 1789.46 8157 5 0
|
|
[1] 2021.08.17 16:00:00 1789.46 1792.99 1786.69 1789.69 9285 5 0
|
|
[2] 2021.08.17 17:00:00 1789.76 1790.45 1780.95 1783.30 8165 5 0
|
|
[3] 2021.08.17 18:00:00 1783.30 1783.98 1780.53 1782.73 5114 5 0
|
|
[4] 2021.08.17 19:00:00 1782.69 1784.16 1782.09 1782.49 3586 6 0
|
|
[5] 2021.08.17 20:00:00 1782.49 1786.23 1782.17 1784.23 3515 5 0
|
|
[6] 2021.08.17 21:00:00 1784.20 1784.85 1782.73 1783.12 2627 6 0
|
|
[7] 2021.08.17 22:00:00 1783.10 1785.52 1782.37 1785.16 2114 5 0
|
|
[8] 2021.08.17 23:00:00 1785.11 1785.84 1784.71 1785.80 922 5 0
|
|
[9] 2021.08.18 01:00:00 1786.30 1786.34 1786.18 1786.20 13 5 0
|
|
*/
|
|
|
|
// Part II. Reading
|
|
// open existing file and read it out by persistent object
|
|
// meta-data from leading header drives the following process of reading actual data
|
|
handle = PRTF(FileOpen(filename,
|
|
FILE_BIN | FILE_READ | FILE_ANSI | FILE_SHARE_READ | FILE_SHARE_WRITE)); // 2
|
|
// empty object
|
|
Candles inputs;
|
|
// fill it with data from the file
|
|
if(!inputs.read(~handle))
|
|
{
|
|
Print("Can't read file");
|
|
}
|
|
else
|
|
{
|
|
inputs.print();
|
|
}
|
|
/*
|
|
example output for XAUUSD,H1
|
|
[time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume]
|
|
[0] 2021.08.17 15:00:00 1791.40 1794.57 1788.04 1789.46 0 0 0
|
|
[1] 2021.08.17 16:00:00 1789.46 1792.99 1786.69 1789.69 0 0 0
|
|
[2] 2021.08.17 17:00:00 1789.76 1790.45 1780.95 1783.30 0 0 0
|
|
[3] 2021.08.17 18:00:00 1783.30 1783.98 1780.53 1782.73 0 0 0
|
|
[4] 2021.08.17 19:00:00 1782.69 1784.16 1782.09 1782.49 0 0 0
|
|
[5] 2021.08.17 20:00:00 1782.49 1786.23 1782.17 1784.23 0 0 0
|
|
[6] 2021.08.17 21:00:00 1784.20 1784.85 1782.73 1783.12 0 0 0
|
|
[7] 2021.08.17 22:00:00 1783.10 1785.52 1782.37 1785.16 0 0 0
|
|
[8] 2021.08.17 23:00:00 1785.11 1785.84 1784.71 1785.80 0 0 0
|
|
[9] 2021.08.18 01:00:00 1786.30 1786.34 1786.18 1786.20 0 0 0
|
|
*/
|
|
}
|
|
//+------------------------------------------------------------------+
|