//+------------------------------------------------------------------+ //| Series.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include #include //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ #define DEFAULT_BUFFER_SIZE 1024 //+------------------------------------------------------------------+ //| Class CSeries. | //| Purpose: Base class for access to timeseries. | //| Derives from class CArrayObj. | //+------------------------------------------------------------------+ class CSeries : public CArrayObj { protected: string m_name; // name of series int m_buffers_total; // number of buffers int m_buffer_size; // buffer size int m_timeframe_flags; // flags of timeframes (similar to "flags of visibility of objects") string m_symbol; // symbol ENUM_TIMEFRAMES m_period; // period bool m_refresh_current; // flag //--- datetime m_first_date; public: CSeries(void); ~CSeries(void); //--- methods of access to protected data string Name(void) const { return(m_name); } int BuffersTotal(void) const { return(m_buffers_total); } int BufferSize(void) const { return(m_buffer_size); } int Timeframe(void) const { return(m_timeframe_flags); } string Symbol(void) const { return(m_symbol); } ENUM_TIMEFRAMES Period(void) const { return(m_period); } string PeriodDescription(const int val=0); void RefreshCurrent(const bool flag) { m_refresh_current=flag; } //--- method of tuning virtual bool BufferResize(const int size); //--- method of refreshing" of the data virtual void Refresh(const int flags) { } protected: //--- methods of tuning bool SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period); void PeriodToTimeframeFlag(const ENUM_TIMEFRAMES period); //--- bool CheckLoadHistory(const int size); bool CheckTerminalHistory(const int size); bool CheckServerHistory(const int size); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ void CSeries::CSeries(void) : m_name(""), m_timeframe_flags(0), m_buffers_total(0), m_buffer_size(0), m_symbol(""), m_period(WRONG_VALUE), m_refresh_current(true) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSeries::~CSeries(void) { } //+------------------------------------------------------------------+ //| Set buffer size | //+------------------------------------------------------------------+ bool CSeries::BufferResize(const int size) { //--- check history if(!CheckLoadHistory(size)) { printf("failed to get %d bars for %s,%s",size,m_symbol,EnumToString(m_period)); return(false); } //--- history is available m_buffer_size=size; //--- ok return(true); } //+------------------------------------------------------------------+ //| Set symbol and period | //+------------------------------------------------------------------+ bool CSeries::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period) { m_symbol=(symbol==NULL) ? ChartSymbol() : symbol; m_period=(period==0) ? ChartPeriod() : period; PeriodToTimeframeFlag(m_period); //--- return(true); } //+------------------------------------------------------------------+ //| Convert period to timeframe flag (similar to visibility flags) | //+------------------------------------------------------------------+ void CSeries::PeriodToTimeframeFlag(const ENUM_TIMEFRAMES period) { static ENUM_TIMEFRAMES _p_int[]= { PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6, PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30, PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12, PERIOD_D1,PERIOD_W1,PERIOD_MN1 }; //--- cycle for all timeframes for(int i=0;iTerminalInfoInteger(TERMINAL_MAXBARS)) { //--- Definitely won't have such amount of data printf(__FUNCTION__+": requested too much data (%d)",size); return(false); } m_first_date=0; if(CheckTerminalHistory(size)) return(true); if(CheckServerHistory(size)) return(true); //--- failed return(false); } //+------------------------------------------------------------------+ //| Checks data in terminal | //+------------------------------------------------------------------+ bool CSeries::CheckTerminalHistory(const int size) { datetime times[1]; long bars=0; //--- Enough data in timeseries? if(Bars(m_symbol,m_period)>=size) return(true); //--- second attempt if(SeriesInfoInteger(m_symbol,PERIOD_M1,SERIES_BARS_COUNT,bars)) { //--- there is loaded data to build timeseries if(bars>size*PeriodSeconds(m_period)/60) { //--- force timeseries build CopyTime(m_symbol,m_period,size-1,1,times); //--- check date if(SeriesInfoInteger(m_symbol,m_period,SERIES_BARS_COUNT,bars)) //--- Timeseries generated using data from terminal if(bars>size) return(true); } } //--- failed return(false); } //+------------------------------------------------------------------+ //| Downloads missing data from server | //+------------------------------------------------------------------+ bool CSeries::CheckServerHistory(const int size) { //--- load symbol history info long first_server_date=0; while(!SeriesInfoInteger(m_symbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,first_server_date) && !IsStopped()) Sleep(5); //--- Enough data on server? if(first_server_date>TimeCurrent()-size*PeriodSeconds(m_period)) return(false); //--- load data step by step int fail_cnt=0; datetime times[1]; while(!IsStopped()) { //--- wait for timeseries build while(!SeriesInfoInteger(m_symbol,m_period,SERIES_SYNCHRONIZED) && !IsStopped()) Sleep(5); //--- ask for built bars int bars=Bars(m_symbol,m_period); if(bars>size) return(true); //--- copying of next part forces data loading if(CopyTime(m_symbol,m_period,size-1,1,times)==1) return(true); //--- no more than 100 failed attempts if(++fail_cnt>=100) return(false); Sleep(10); } //--- failed return(false); } //+------------------------------------------------------------------+ //| Class CDoubleBuffer. | //| Purpose: Base class of buffer of data of the double type. | //| Derives from class CArrayDouble. | //+------------------------------------------------------------------+ class CDoubleBuffer : public CArrayDouble { protected: string m_symbol; // symbol ENUM_TIMEFRAMES m_period; // period int m_size; // size of used history public: CDoubleBuffer(void); ~CDoubleBuffer(void); //--- methods of access to protected data void Size(const int size) { m_size=size; } //--- methods of access to data double At(const int index) const; //--- method of refreshing of the data buffer virtual bool Refresh(void) { return(true); } virtual bool RefreshCurrent(void) { return(true); } //--- methods of tuning void SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CDoubleBuffer::CDoubleBuffer(void) : m_symbol(""), m_period(WRONG_VALUE), m_size(DEFAULT_BUFFER_SIZE) { ArraySetAsSeries(m_data,true); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CDoubleBuffer::~CDoubleBuffer(void) { } //+------------------------------------------------------------------+ //| Access to data in a specified position | //+------------------------------------------------------------------+ double CDoubleBuffer::At(const int index) const { //--- check if(index>=m_data_total) return(EMPTY_VALUE); //--- double d=CArrayDouble::At(index); //--- return(d); } //+------------------------------------------------------------------+ //| Set symbol and period | //+------------------------------------------------------------------+ void CDoubleBuffer::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period) { m_symbol=(symbol==NULL) ? ChartSymbol() : symbol; m_period=(period==0) ? ChartPeriod() : period; } //+------------------------------------------------------------------+