MQL5Book/Scripts/p4/FileAtomic.mq5
super.admin 1c8e83ce31 convert
2025-05-30 16:09:41 +02:00

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