forked from rosh/MQL5Book
138 lines
4.1 KiB
MQL5
138 lines
4.1 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| CalendarChangeReader.mq5 |
| |
//| Copyright 2022, MetaQuotes Ltd. |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2022, MetaQuotes Ltd."
| |
#property link "https://www.mql5.com"
| |
#property description "Test script to show how to read saved calendar changes from CalendarChangeSaver service."
| |
#property script_show_inputs
| |
| |
#include "..\..\Include\Defines.mqh"
| |
| |
#define PACK_DATETIME_COUNTER(D,C) (D | (((ulong)(C)) << 48))
| |
#define DATETIME(A) ((datetime)((A) & 0x7FFFFFFFF))
| |
#define COUNTER(A) ((ushort)((A) >> 48))
| |
| |
input string Filename = "calendar2.chn";
| |
input datetime Start;
| |
| |
//+------------------------------------------------------------------+
| |
//| Script program start function |
| |
//+------------------------------------------------------------------+
| |
void OnStart()
| |
{
| |
const long day = 60 * 60 * 24;
| |
datetime now = Start ? Start : (datetime)(TimeCurrent() / day * day);
| |
| |
int handle = FileOpen(Filename,
| |
FILE_READ | FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_BIN);
| |
if(handle == INVALID_HANDLE)
| |
{
| |
PrintFormat("Can't open file '%s' for reading", Filename);
| |
return;
| |
}
| |
| |
ChangeFileReader reader(handle, now);
| |
| |
// read the file step by step, incrementing time artificially in this demo
| |
while(!FileIsEnding(handle))
| |
{
| |
// in real application testing could call reader.check on every tick,
| |
// or postpond further checks until reader.getState().dt (if it's not LONG_MAX)
| |
ulong records[];
| |
if(reader.check(now, records))
| |
{
| |
Print(now);
| |
ArrayPrint(records);
| |
}
| |
now += 60; // increment time by 1 minute at once, can be 1 second
| |
}
| |
| |
FileClose(handle);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Single change (datetime + array of affected calendar record IDs) |
| |
//+------------------------------------------------------------------+
| |
struct ChangeState
| |
{
| |
datetime dt;
| |
ulong ids[];
| |
| |
ChangeState(): dt(LONG_MAX) {}
| |
ChangeState(const datetime at, ulong &_ids[])
| |
{
| |
dt = at;
| |
ArraySwap(ids, _ids);
| |
}
| |
void operator=(const ChangeState &other)
| |
{
| |
dt = other.dt;
| |
ArrayCopy(ids, other.ids);
| |
}
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Class to walk through changes saved in a file for advancing time |
| |
//+------------------------------------------------------------------+
| |
class ChangeFileReader
| |
{
| |
const int handle;
| |
ChangeState current;
| |
const ChangeState zero;
| |
| |
public:
| |
ChangeFileReader(const int h, const datetime start = 0): handle(h)
| |
{
| |
if(readState())
| |
{
| |
if(start)
| |
{
| |
ulong dummy[];
| |
check(start, dummy, true); // jump to first edit after 'start'
| |
}
| |
}
| |
}
| |
| |
bool check(datetime now, ulong &records[], const bool fastforward = false)
| |
{
| |
if(current.dt > now) return false;
| |
| |
ArrayFree(records);
| |
| |
if(!fastforward)
| |
{
| |
ArrayCopy(records, current.ids);
| |
current = zero;
| |
}
| |
| |
while(readState() && current.dt <= now)
| |
{
| |
if(!fastforward) ArrayInsert(records, current.ids, ArraySize(records));
| |
}
| |
| |
return true;
| |
}
| |
| |
bool readState()
| |
{
| |
if(FileIsEnding(handle)) return false;
| |
ResetLastError();
| |
const ulong v = FileReadLong(handle);
| |
current.dt = DATETIME(v);
| |
ArrayFree(current.ids);
| |
const int n = COUNTER(v);
| |
for(int i = 0; i < n; ++i)
| |
{
| |
PUSH(current.ids, FileReadLong(handle));
| |
}
| |
return _LastError == 0;
| |
}
| |
| |
ChangeState getState() const
| |
{
| |
return current;
| |
}
| |
};
| |
//+------------------------------------------------------------------+
|