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