forked from animatedread/Warrior_EA
- Introduced `FeatureScale.mqh` with `FeatSquash` function for stateless feature scaling. - Added `RegimeMath.mqh` class for regime arithmetic, including efficiency and variance calculations. - Documented the Mind trading logic in `MIND.md`, detailing the trading process and modes. - Created `VOLNORM_PLAN.md` and `VOLNORM_RESULTS.md` for tick-volume normalization testing. - Implemented `read_book.py` for analyzing trade book data and correlations. - Developed `volnorm.py` for testing tick-volume normalization with new and old methods.
79 lines
3.1 KiB
MQL5
79 lines
3.1 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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
|