#ifndef CORE_SESSION_MQH #define CORE_SESSION_MQH //+------------------------------------------------------------------+ //| session.mqh - time before price: daily trading windows | //| | //| A window is a daily span in minutes since midnight SERVER time | //| (use HM(9, 30) for 09:30). start > end wraps past midnight, so | //| HM(22, 0) .. HM(6, 0) is a valid Asian-style window. The start | //| minute is inclusive and the end minute exclusive. | //| | //| Ids returned by defineWindow() stay valid for the object's life; | //| removeWindow() retires an id but never hands it out again. | //+------------------------------------------------------------------+ #include "common.mqh" #define SESSION_ALL_DAYS 0x7F // bit n = weekday n, 0 = Sunday .. 6 = Saturday class CSession { private: struct SWindow { int startMinute; int endMinute; int dayMask; bool live; }; SWindow m_windows[]; bool covers(const SWindow &w, const datetime t) const; public: static int HM(const int hour, const int minute = 0) { return hour * 60 + minute; } //--- true and sessionIndex set on success; false on an invalid window bool defineWindow(const int startMinute, const int endMinute, int &sessionIndex, const int dayMask = SESSION_ALL_DAYS); void removeWindow(const int sessionIndex); //--- t = 0 means TimeCurrent(). Pass a bar's time when replaying history. bool isSessionActive(const int sessionIndex, const datetime t = 0) const; bool isThisTimeASession(const datetime t = 0) const { return whichSession(t) >= 0; } //--- id of the first live window that covers t, or -1 int whichSession(const datetime t = 0) const; int windowCount() const; }; //+------------------------------------------------------------------+ bool CSession::defineWindow(const int startMinute, const int endMinute, int &sessionIndex, const int dayMask) { if(startMinute < 0 || startMinute >= 1440 || endMinute < 0 || endMinute > 1440 || startMinute == endMinute || (dayMask & SESSION_ALL_DAYS) == 0) return false; const int n = ArraySize(m_windows); if(ArrayResize(m_windows, n + 1) != n + 1) return false; m_windows[n].startMinute = startMinute; m_windows[n].endMinute = endMinute; m_windows[n].dayMask = dayMask & SESSION_ALL_DAYS; m_windows[n].live = true; sessionIndex = n; return true; } void CSession::removeWindow(const int sessionIndex) { if(sessionIndex >= 0 && sessionIndex < ArraySize(m_windows)) m_windows[sessionIndex].live = false; } bool CSession::covers(const SWindow &w, const datetime t) const { MqlDateTime dt; TimeToStruct(t, dt); if((w.dayMask & (1 << dt.day_of_week)) == 0) return false; const int minute = dt.hour * 60 + dt.min; if(w.startMinute < w.endMinute) return minute >= w.startMinute && minute < w.endMinute; return minute >= w.startMinute || minute < w.endMinute; // wraps midnight } bool CSession::isSessionActive(const int sessionIndex, const datetime t) const { if(sessionIndex < 0 || sessionIndex >= ArraySize(m_windows) || !m_windows[sessionIndex].live) return false; return covers(m_windows[sessionIndex], t == 0 ? TimeCurrent() : t); } int CSession::whichSession(const datetime t) const { const datetime when = (t == 0) ? TimeCurrent() : t; for(int i = 0; i < ArraySize(m_windows); i++) { if(m_windows[i].live && covers(m_windows[i], when)) return i; } return -1; } int CSession::windowCount() const { int n = 0; for(int i = 0; i < ArraySize(m_windows); i++) if(m_windows[i].live) n++; return n; } #endif // CORE_SESSION_MQH