76 righe
2,8 KiB
MQL5
76 righe
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
|