forked from mnbvc188199/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.
99 lines
3.9 KiB
MQL5
99 lines
3.9 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| ModalityBreadth.mqh |
| |
//| AnimateDread |
| |
//| |
| |
//| WHAT THE NEIGHBOURING MARKETS ARE DOING at the same bar. |
| |
//| |
| |
//| The dip-buy's losses are bear onsets, and bear onsets show up in |
| |
//| every index at once. A dip that only this index is having is a |
| |
//| local shake-out; a dip all four are having is a market-wide sell- |
| |
//| off, which is a different thing to buy. BREADTH is the fraction of |
| |
//| the peers (this symbol excluded) at z(20) <= -1 on the same bar. |
| |
//| |
| |
//| Peers are a comma list; ones the broker does not have are skipped. |
| |
//| A peer without history for this bar simply does not answer, and |
| |
//| BREADTH_N says how many did - so a reading from one peer is not |
| |
//| mistaken for one from three. |
| |
//+------------------------------------------------------------------+
| |
#ifndef WARRIOR_MODALITYBREADTH_MQH
| |
#define WARRIOR_MODALITYBREADTH_MQH
| |
| |
#include "Modality.mqh"
| |
| |
class CModalityBreadth : public CModality
| |
{
| |
protected:
| |
string m_self;
| |
ENUM_TIMEFRAMES m_tf;
| |
string m_peers[];
| |
int m_period; // z-score window
| |
double m_dipZ; // a peer at or below this z counts as dipping
| |
| |
bool PeerZ(const string peer, const datetime when, double &z) const;
| |
| |
public:
| |
CModalityBreadth(const string self, const ENUM_TIMEFRAMES tf,
| |
const string peerList, const int period = 20,
| |
const double dipZ = -1.0)
| |
: m_self(self), m_tf(tf), m_period(period), m_dipZ(dipZ)
| |
{
| |
string all[];
| |
const int n = StringSplit(peerList, ',', all);
| |
for(int i = 0; i < n; i++)
| |
{
| |
StringTrimLeft(all[i]);
| |
StringTrimRight(all[i]);
| |
if(all[i] == "" || all[i] == m_self)
| |
continue;
| |
if(!SymbolSelect(all[i], true))
| |
continue;
| |
const int k = ArraySize(m_peers);
| |
ArrayResize(m_peers, k + 1);
| |
m_peers[k] = all[i];
| |
}
| |
}
| |
int PeerCount(void) const { return ArraySize(m_peers); }
| |
virtual string Name(void) const override { return "breadth"; }
| |
virtual bool Read(const SBarRef &bar, SMarketContext &ctx) override;
| |
};
| |
//+------------------------------------------------------------------+
| |
bool CModalityBreadth::PeerZ(const string peer, const datetime when, double &z) const
| |
{
| |
const int shift = iBarShift(peer, m_tf, when, false);
| |
if(shift < 0)
| |
return false;
| |
double c[];
| |
if(CopyClose(peer, m_tf, shift, m_period, c) != m_period)
| |
return false;
| |
double s = 0.0, s2 = 0.0;
| |
for(int i = 0; i < m_period; i++)
| |
{
| |
s += c[i];
| |
s2 += c[i] * c[i];
| |
}
| |
const double mean = s / m_period, var = s2 / m_period - mean * mean;
| |
if(var <= 0.0)
| |
return false;
| |
z = (c[m_period - 1] - mean) / MathSqrt(var); // oldest first: the last element is `shift`
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
bool CModalityBreadth::Read(const SBarRef &bar, SMarketContext &ctx)
| |
{
| |
int answered = 0, dipping = 0;
| |
for(int i = 0; i < ArraySize(m_peers); i++)
| |
{
| |
double z;
| |
if(!PeerZ(m_peers[i], bar.time, z))
| |
continue;
| |
answered++;
| |
if(z <= m_dipZ)
| |
dipping++;
| |
}
| |
ctx.v[CTX_BREADTH_N] = answered;
| |
if(answered == 0)
| |
return false;
| |
ctx.v[CTX_BREADTH] = (double)dipping / answered;
| |
return true;
| |
}
| |
#endif // WARRIOR_MODALITYBREADTH_MQH
|