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
| |
*/
| |
}
| |
//+------------------------------------------------------------------+
|