mql5/Experts/AnotherTriBible/Barsbydate.mqh

259 lines
9.4 KiB
MQL5

2026-03-04 17:09:32 +02:00
//+------------------------------------------------------------------+
//| CBarsbydate.mqh |
//| Based on Price.mqh (Andrew Young) |
//+------------------------------------------------------------------+
#property strict
#property copyright "Andrew Young"
#property link "http://www.expertadvisorbook.com"
class CBarsbydate {
private:
int BarCount;
2026-03-15 02:46:38 +02:00
string symbol;
2026-03-04 17:09:32 +02:00
public:
MqlRates bar[];
CBarsbydate(void);
// --- Range loading ---
// Loads bars from [fromTime .. toTime] inclusive-ish (broker availability rules apply)
int UpdateRange(string pSymbol, ENUM_TIMEFRAMES pPeriod, datetime fromTime, datetime toTime);
// Convenience: from 1st of month N months back -> now
int UpdateFromMonthsBack(string pSymbol, ENUM_TIMEFRAMES pPeriod, int monthsBack);
// --- Accessors ---
double Close(int pShift);
double High(int pShift);
double Low(int pShift);
double Open(int pShift);
datetime Time(int pShift);
long TickVolume(int pShift);
long Volume(int pShift);
// --- Extract arrays ---
void GetCloses(double &closes[]);
void GetOpens(double &opens[]);
void GetHighs(double &highs[]);
void GetLows(double &lows[]);
void GetTimes(datetime &times[]);
void GetVolumes(long &volumes[]);
int GetBarCount();
int IndexByTime(datetime t);
2026-03-15 02:46:38 +02:00
double Point();
int Size() {
return ArraySize(bar);
}
2026-03-04 17:09:32 +02:00
private:
datetime FirstOfPreviousMonths(datetime currentTime, int monthsBack);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBarsbydate::CBarsbydate(void) {
BarCount = 0;
// IMPORTANT: you said no series for this project:
// index 0 = oldest, index BarCount-1 = newest.
// So DO NOT ArraySetAsSeries(bar, true).
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
datetime CBarsbydate::FirstOfPreviousMonths(datetime currentTime, int monthsBack) {
MqlDateTime dt;
TimeToStruct(currentTime, dt);
dt.mon -= monthsBack;
while(dt.mon <= 0) {
dt.mon += 12;
dt.year--;
}
dt.day = 1;
dt.hour = 0;
dt.min = 0;
dt.sec = 0;
return StructToTime(dt);
}
//+------------------------------------------------------------------+
//| Load bars by time range |
//| bar[0] oldest, bar[count-1] newest |
//+------------------------------------------------------------------+
int CBarsbydate::UpdateRange(string pSymbol, ENUM_TIMEFRAMES pPeriod, datetime fromTime, datetime toTime) {
ArrayResize(bar, 0);
BarCount = 0;
2026-03-15 02:46:38 +02:00
symbol = pSymbol;
2026-03-04 17:09:32 +02:00
if(fromTime <= 0 || toTime <= 0 || toTime <= fromTime) {
Print("CBarsbydate::UpdateRange invalid times. from=", TimeToString(fromTime),
" to=", TimeToString(toTime));
return 0;
}
int copied = CopyRates(pSymbol, pPeriod, fromTime, toTime, bar);
if(copied <= 0) {
Print("CBarsbydate::UpdateRange CopyRates failed. err=", GetLastError(),
" from=", TimeToString(fromTime), " to=", TimeToString(toTime));
return 0;
}
BarCount = copied;
return copied;
}
//+------------------------------------------------------------------+
//| Convenience: from 1st of month N months back -> now |
//+------------------------------------------------------------------+
int CBarsbydate::UpdateFromMonthsBack(string pSymbol, ENUM_TIMEFRAMES pPeriod, int monthsBack) {
datetime toTime = TimeCurrent();
datetime fromTime = FirstOfPreviousMonths(toTime, monthsBack);
return UpdateRange(pSymbol, pPeriod, fromTime, toTime);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-03-15 02:46:38 +02:00
double CBarsbydate::Point() {
return SymbolInfoDouble(symbol, SYMBOL_POINT);
2026-03-04 17:09:32 +02:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CBarsbydate::GetBarCount(void) {
return BarCount;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double CBarsbydate::Close(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0.0;
return bar[pShift].close;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double CBarsbydate::High(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0.0;
return bar[pShift].high;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double CBarsbydate::Low(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0.0;
return bar[pShift].low;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double CBarsbydate::Open(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0.0;
return bar[pShift].open;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
datetime CBarsbydate::Time(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0;
return bar[pShift].time;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
long CBarsbydate::TickVolume(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0;
return bar[pShift].tick_volume;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
long CBarsbydate::Volume(int pShift) {
if(pShift < 0 || pShift >= BarCount) return 0;
return bar[pShift].real_volume;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBarsbydate::GetCloses(double &closes[]) {
ArrayResize(closes, BarCount);
for(int i = 0; i < BarCount; i++)
closes[i] = bar[i].close;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBarsbydate::GetOpens(double &opens[]) {
ArrayResize(opens, BarCount);
for(int i = 0; i < BarCount; i++)
opens[i] = bar[i].open;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBarsbydate::GetHighs(double &highs[]) {
ArrayResize(highs, BarCount);
for(int i = 0; i < BarCount; i++)
highs[i] = bar[i].high;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBarsbydate::GetLows(double &lows[]) {
ArrayResize(lows, BarCount);
for(int i = 0; i < BarCount; i++)
lows[i] = bar[i].low;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBarsbydate::GetTimes(datetime &times[]) {
ArrayResize(times, BarCount);
for(int i = 0; i < BarCount; i++)
times[i] = bar[i].time;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBarsbydate::GetVolumes(long &volumes[]) {
ArrayResize(volumes, BarCount);
for(int i = 0; i < BarCount; i++)
volumes[i] = bar[i].tick_volume;
}
//+------------------------------------------------------------------+
//| Index by exact time match |
//| Returns index in bar[] (0 oldest) or -1 |
//+------------------------------------------------------------------+
int CBarsbydate::IndexByTime(datetime t) {
if(t == 0 || BarCount == 0) return -1;
for(int i = 0; i < BarCount; i++) {
if(bar[i].time == t) return i;
}
return -1;
}
//+------------------------------------------------------------------+