130 lines
2.9 KiB
MQL5
130 lines
2.9 KiB
MQL5
/**
|
|
* @file BarSeriesBuffer - Adapts a circular buffer to MT5's tick-driven model, tracking bar times to ensure exactly one sample per bar.
|
|
* @deps CircularBuffer.mqh, ESeriesEvent.mqh
|
|
* @state Stateful (Tracks last processed bar datetime, initialization flags, and internal buffer state across ticks)
|
|
* @io Current bar datetime & double value -> Returns ESeriesEvent state transition enum & Updates or appends to buffer
|
|
* @note AI-assisted code. Independently review and test in a demo environment before live production trading.
|
|
*/
|
|
|
|
#ifndef __BARSERIESBUFFER_MQH__
|
|
#define __BARSERIESBUFFER_MQH__
|
|
|
|
#include "..\\Storage\\CircularBuffer.mqh"
|
|
#include "..\\Common\\ESeriesEvent.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CBarSeriesBuffer
|
|
{
|
|
private:
|
|
|
|
CCircularBuffer m_buffer;
|
|
datetime m_lastBarTime;
|
|
bool m_initialized;
|
|
double m_droppedValue;
|
|
|
|
public:
|
|
|
|
CBarSeriesBuffer()
|
|
{
|
|
m_lastBarTime = 0;
|
|
m_initialized = false;
|
|
m_droppedValue = 0.0;
|
|
}
|
|
|
|
bool Init(const int capacity)
|
|
{
|
|
if(!m_buffer.Init(capacity))
|
|
return(false);
|
|
|
|
m_lastBarTime = 0;
|
|
m_initialized = false;
|
|
m_droppedValue = 0.0;
|
|
|
|
return(true);
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
m_buffer.Reset();
|
|
|
|
m_lastBarTime = 0;
|
|
m_initialized = false;
|
|
m_droppedValue = 0.0;
|
|
}
|
|
|
|
ESeriesEvent Update(const datetime barTime, const double value)
|
|
{
|
|
//m_droppedValue = 0.0;
|
|
|
|
// First sample
|
|
if(!m_initialized)
|
|
{
|
|
m_buffer.Push(value);
|
|
|
|
m_lastBarTime = barTime;
|
|
m_initialized = true;
|
|
|
|
return ESeriesEvent::SERIES_FIRST_SAMPLE;
|
|
}
|
|
|
|
// History reload / rewind
|
|
if(barTime < m_lastBarTime)
|
|
{
|
|
Reset();
|
|
|
|
m_buffer.Push(value);
|
|
|
|
m_lastBarTime = barTime;
|
|
m_initialized = true;
|
|
|
|
return ESeriesEvent::SERIES_RESET;
|
|
}
|
|
|
|
// New bar
|
|
if(barTime != m_lastBarTime)
|
|
{
|
|
if(m_buffer.IsFull())
|
|
m_buffer.At(m_buffer.Capacity() - 1, m_droppedValue);
|
|
|
|
m_buffer.Push(value);
|
|
m_lastBarTime = barTime;
|
|
|
|
return ESeriesEvent::SERIES_APPEND;
|
|
}
|
|
|
|
// Same bar
|
|
m_buffer.UpdateLast(value);
|
|
return ESeriesEvent::SERIES_REPLACE_LAST;
|
|
}
|
|
|
|
bool At(const int offset,
|
|
double &value) const
|
|
{
|
|
return(m_buffer.At(offset, value));
|
|
}
|
|
|
|
int Count() const
|
|
{
|
|
return(m_buffer.Count());
|
|
}
|
|
|
|
int Capacity() const
|
|
{
|
|
return(m_buffer.Capacity());
|
|
}
|
|
|
|
bool IsFull() const
|
|
{
|
|
return(m_buffer.IsFull());
|
|
}
|
|
|
|
double DroppedValue() const
|
|
{
|
|
return(m_droppedValue);
|
|
}
|
|
};
|
|
|
|
#endif // __BARSERIESBUFFER_MQH__
|
|
//+------------------------------------------------------------------+
|