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>
76 lines
2.8 KiB
MQL5
76 lines
2.8 KiB
MQL5
#ifndef CORE_COMMON_MQH
|
|
#define CORE_COMMON_MQH
|
|
//+------------------------------------------------------------------+
|
|
//| common.mqh - conventions and the one data structure core/ shares |
|
|
//| |
|
|
//| Contract for every core/*.mqh: |
|
|
//| - rates[] is AS-SERIES: [0] = forming bar, [1] = last closed |
|
|
//| bar, higher index = older. Callers do CopyRates() then |
|
|
//| ArraySetAsSeries(rates, true). |
|
|
//| - Nothing reads globals or chart state. Data comes in by |
|
|
//| argument, so any symbol/timeframe can be scanned. |
|
|
//| - Direction flags are ints: +1 bullish, -1 bearish, 0 none. |
|
|
//| - Memory is bounded: history lives in CRing, never in a |
|
|
//| structure that grows per tick. |
|
|
//| - update() methods are safe to call every tick; they act once |
|
|
//| per new closed bar. |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//--- true when rates[] is as-series and holds at least minBars bars
|
|
bool CoreSeriesReady(const MqlRates &rates[], const int minBars)
|
|
{
|
|
return ArrayGetAsSeries(rates) && ArraySize(rates) >= minBars;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| CRing<T> - fixed-capacity ring buffer |
|
|
//| Push O(1), evicts the oldest entry when full |
|
|
//| At O(1), pos 0 = newest, Count()-1 = oldest |
|
|
//+------------------------------------------------------------------+
|
|
template<typename T>
|
|
class CRing
|
|
{
|
|
private:
|
|
T m_buf[];
|
|
int m_cap;
|
|
int m_head; // slot of the NEXT write
|
|
int m_count; // valid entries, never above m_cap
|
|
|
|
public:
|
|
CRing() : m_cap(0), m_head(0), m_count(0) {}
|
|
|
|
bool Init(const int capacity)
|
|
{
|
|
if(capacity <= 0 || ArrayResize(m_buf, capacity) != capacity)
|
|
return false;
|
|
m_cap = capacity;
|
|
m_head = 0;
|
|
m_count = 0;
|
|
return true;
|
|
}
|
|
|
|
void Clear() { m_head = 0; m_count = 0; }
|
|
int Count() const { return m_count; }
|
|
int Capacity() const { return m_cap; }
|
|
|
|
bool Push(const T &value)
|
|
{
|
|
if(m_cap == 0)
|
|
return false;
|
|
m_buf[m_head] = value;
|
|
m_head = (m_head + 1) % m_cap;
|
|
if(m_count < m_cap)
|
|
m_count++;
|
|
return true;
|
|
}
|
|
|
|
bool At(const int pos, T &out) const
|
|
{
|
|
if(pos < 0 || pos >= m_count)
|
|
return false;
|
|
out = m_buf[(m_head - 1 - pos + m_cap) % m_cap];
|
|
return true;
|
|
}
|
|
};
|
|
|
|
#endif // CORE_COMMON_MQH
|