259 lines
9.4 KiB
MQL5
259 lines
9.4 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| 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;
| |
string symbol;
| |
| |
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 ×[]);
| |
void GetVolumes(long &volumes[]);
| |
| |
int GetBarCount();
| |
int IndexByTime(datetime t);
| |
double Point();
| |
int Size() {
| |
return ArraySize(bar);
| |
}
| |
| |
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;
| |
symbol = pSymbol;
| |
| |
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);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
double CBarsbydate::Point() {
| |
return SymbolInfoDouble(symbol, SYMBOL_POINT);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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 ×[]) {
| |
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;
| |
}
| |
//+------------------------------------------------------------------+
|