ictCore/Experts/core/session.mqh
nazgul 9e8ce6a0ee core: refactor into bounded, symbol-agnostic building blocks
Same code as the luvinga repo's Include/core (commit "Refactor core/ ...").

- common.mqh (new): as-series contract, CRing<T>
- session.mqh: now implemented (was declarations only); force-added because
  Experts/core is listed in .gitignore
- candlesticks/swings/marketWatchFilter: no more input variables in headers;
  use configure() / constructor arguments
- orderflow, fvg, equilibrium: multi-symbol safe, bug fixes

Breaking: bots that relied on inpWatchTimeframe from marketWatchFilter.mqh
(preReleasedBots/ttrades.mq5) must now declare that input themselves.
signalLab.mqh is untouched by this commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 21:47:19 +03:00

112 lines
4 KiB
MQL5

#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