//+------------------------------------------------------------------+ //| ModalityPrice.mqh | //| AnimateDread | //| | //| PRICE SHAPE, REGIME AND VOLATILITY of the signal bar - the things | //| that need nothing but the bar cache. Every distance is in ATR so | //| one number means the same on an index at 5,000 and one at 40,000; | //| ratios of two prices in the same units, never a raw price. | //+------------------------------------------------------------------+ #ifndef WARRIOR_MODALITYPRICE_MQH #define WARRIOR_MODALITYPRICE_MQH #include "Modality.mqh" #include "..\System\BarCache.mqh" #include "..\System\RegimeMath.mqh" class CModalityPrice : public CModality { protected: CBarCache *m_cache; // not owned int m_volWarm; // bars before the volatility percentile may answer public: CModalityPrice(CBarCache *cache, const int volWarm = 250) : m_cache(cache), m_volWarm(volWarm) {} virtual string Name(void) const override { return "price"; } virtual bool Read(const SBarRef &bar, SMarketContext &ctx) override; }; //+------------------------------------------------------------------+ bool CModalityPrice::Read(const SBarRef &bar, SMarketContext &ctx) { const int i = bar.idx; if(m_cache == NULL || i < 100 || i >= m_cache.Count()) return false; const double atr = m_cache.Atr(i); if(atr <= 0.0) return false; const double c = m_cache.Close(i), h = m_cache.High(i), l = m_cache.Low(i); double mean = 0.0, sd = 0.0; if(m_cache.MeanStd(i, 20, mean, sd) && sd > 0.0) ctx.v[CTX_Z] = (c - mean) / sd; if(mean > 0.0) ctx.v[CTX_DIST_ATR] = (c - mean) / atr; ctx.v[CTX_RET1_ATR] = (c - m_cache.Close(i - 1)) / atr; ctx.v[CTX_DROP5_ATR] = (c - m_cache.Close(i - 5)) / atr; ctx.v[CTX_RANGE_ATR] = (h - l) / atr; ctx.v[CTX_CLOSE_LOC] = (h > l) ? (c - l) / (h - l) : 0.5; double x[]; if(m_cache.ClosesBack(i, CRegimeMath::LabelBars(), x)) { const double er = CRegimeMath::Efficiency(x, 20); const double vr = CRegimeMath::Variance(x, 60, 5); ctx.v[CTX_ER] = er; ctx.v[CTX_VR] = vr; ctx.v[CTX_REGIME] = CRegimeMath::Code(er, vr); } const double pct = m_cache.VolPercentile(i, m_volWarm); if(pct >= 0.0) ctx.v[CTX_VOL_PCT] = pct; double atrSum = 0.0; int atrN = 0; for(int k = i - 99; k <= i; k++) if(m_cache.Atr(k) > 0.0) { atrSum += m_cache.Atr(k); atrN++; } if(atrN > 50) ctx.v[CTX_ATR_RATIO] = atr / (atrSum / atrN); return true; } #endif // WARRIOR_MODALITYPRICE_MQH