forked from animatedread/Warrior_EA
52 lines
2.3 KiB
MQL5
52 lines
2.3 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| ModalityVolume.mqh |
| |||
//| AnimateDread |
| |||
//| |
| |||
//| PARTICIPATION AND EFFORT-VERSUS-RESULT, from tick volume with the |
| |||
//| hour-of-day removed (Mind\VolumeProfile.mqh). |
| |||
//| |
| |||
//| Wyckoff's third law asks whether the result matches the effort. |
| |||
//| ABSORB is that comparison in log units: volume well above normal |
| |||
//| for the hour on a bar that made little progress (a small range in |
| |||
//| ATR) reads high - somebody is taking the other side. Volume that |
| |||
//| is normal for the hour with a wide bar reads low - the move had no |
| |||
//| one to fight. Tick volume is a proxy for participation on a CFD, |
| |||
//| not the real thing; the book records what it turned out to be. |
| |||
//+------------------------------------------------------------------+
| |||
#ifndef WARRIOR_MODALITYVOLUME_MQH
| |||
#define WARRIOR_MODALITYVOLUME_MQH
| |||
| |||
#include "Modality.mqh"
| |||
#include "VolumeProfile.mqh"
| |||
| |||
class CModalityVolume : public CModality
| |||
{
| |||
protected:
| |||
CBarCache *m_cache; // not owned
| |||
CVolumeProfile *m_profile; // not owned
| |||
| |||
public:
| |||
CModalityVolume(CBarCache *cache, CVolumeProfile *profile)
| |||
: m_cache(cache), m_profile(profile) {}
| |||
virtual string Name(void) const override { return "volume"; }
| |||
virtual bool Read(const SBarRef &bar, SMarketContext &ctx) override;
| |||
};
| |||
//+------------------------------------------------------------------+
| |||
bool CModalityVolume::Read(const SBarRef &bar, SMarketContext &ctx)
| |||
{
| |||
if(m_cache == NULL || m_profile == NULL)
| |||
return false;
| |||
m_profile.Update();
| |||
const double raw = m_profile.Raw(bar.idx);
| |||
const double det = m_profile.Detrended(bar.idx);
| |||
if(raw == VOLPROF_NA)
| |||
return false;
| |||
ctx.v[CTX_RVOL_RAW] = raw;
| |||
if(det != VOLPROF_NA)
| |||
ctx.v[CTX_RVOL] = det;
| |||
const double range = ctx.Has(CTX_RANGE_ATR) ? ctx.v[CTX_RANGE_ATR] : CTX_NA;
| |||
if(det != VOLPROF_NA && range != CTX_NA)
| |||
ctx.v[CTX_ABSORB] = det - MathLog(MathMax(range, 0.1));
| |||
return true;
| |||
}
| |||
#endif // WARRIOR_MODALITYVOLUME_MQH
|