| //+------------------------------------------------------------------+
|
| //| VolumeFeed.mqh |
|
| //| AnimateDread |
|
| //| |
|
| //| ONE PLACE THAT ANSWERS "HOW BUSY WAS THIS BAR, FOR ITS HOUR". |
|
| //| |
|
| //| The neural module and the management net each used to compute |
|
| //| their own bar-over-recent-mean volume ratio, and both carried the |
|
| //| same defect (see Mind\VolumeProfile.mqh: the ratio mostly encoded |
|
| //| the hour of day). They now ask this feed instead, so there is one |
|
| //| definition of relative volume in the codebase and one place to fix |
|
| //| it. The Mind's own volume modality reads the same profile. |
|
| //| |
|
| //| One feed per chart, guarded by the symbol/period it was built for, |
|
| //| like g_wyckoffFeed. It owns a bar cache of the whole history - the |
|
| //| stdlib series stop at shift 1023 and the neural module trains far |
|
| //| deeper than that. |
|
| //+------------------------------------------------------------------+
|
| #ifndef WARRIOR_VOLUMEFEED_MQH
|
| #define WARRIOR_VOLUMEFEED_MQH
|
|
|
| #include "VolumeProfile.mqh"
|
|
|
| class CVolumeFeed
|
| {
|
| protected:
|
| CBarCache m_cache;
|
| CVolumeProfile m_profile;
|
| string m_for;
|
|
|
| public:
|
| CVolumeFeed(void) : m_for("") {}
|
| bool Ensure(const string symbol, const ENUM_TIMEFRAMES tf)
|
| {
|
| const string want = symbol + "/" + IntegerToString((int)tf);
|
| if(m_for == want)
|
| return true;
|
| m_cache.Init(symbol, tf, 14, 30);
|
| m_profile.Init(GetPointer(m_cache));
|
| m_for = want;
|
| return true;
|
| }
|
| //--- Bring the cache up to the newest closed bar and fold it into the profile.
|
| bool Sync(void)
|
| {
|
| if(m_for == "" || !m_cache.Sync())
|
| return false;
|
| m_profile.Update();
|
| return true;
|
| }
|
| //--- The bar that OPENED at `barTime`: its level-detrended log volume against the hour's norm,
|
| //--- that reading's mean over the last five bars, and its change from the previous bar.
|
| //--- False when any of them is not yet defined - the caller drops the row, as it does for any
|
| //--- other feature it cannot compute.
|
| bool Reading(const datetime barTime, double &now, double &mean5, double &change) const
|
| {
|
| const int i = m_cache.IndexOf(barTime);
|
| if(i < 5)
|
| return false;
|
| now = m_profile.Detrended(i);
|
| const double prev = m_profile.Detrended(i - 1);
|
| if(now == VOLPROF_NA || prev == VOLPROF_NA)
|
| return false;
|
| double s = now;
|
| for(int k = 1; k < 5; k++)
|
| {
|
| const double d = m_profile.Detrended(i - k);
|
| if(d == VOLPROF_NA)
|
| return false;
|
| s += d;
|
| }
|
| mean5 = s / 5.0;
|
| change = now - prev;
|
| return true;
|
| }
|
| };
|
|
|
| CVolumeFeed g_volFeed;
|
| #endif // WARRIOR_VOLUMEFEED_MQH
|