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.
132 lines
5.4 KiB
MQL5
132 lines
5.4 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| MarketContext.mqh |
|
|
//| AnimateDread |
|
|
//| |
|
|
//| WHAT THE TRADER SAW WHEN THEY PRESSED THE BUTTON. |
|
|
//| |
|
|
//| One fixed-width record of every modality's reading at the signal |
|
|
//| bar. It is the single source of truth for three consumers that |
|
|
//| used to be three hand-kept lists: the modalities WRITE it, the |
|
|
//| trade book PERSISTS it (header and row both come from CtxName()), |
|
|
//| and the reviewer BUCKETS it. Add a field once, here, and all |
|
|
//| three follow; nothing else spells a column name. |
|
|
//| |
|
|
//| CTX_NA marks a reading the modality could not produce. It is |
|
|
//| never zero: a missing Wyckoff read must not look like "phase 0". |
|
|
//+------------------------------------------------------------------+
|
|
#ifndef WARRIOR_MARKETCONTEXT_MQH
|
|
#define WARRIOR_MARKETCONTEXT_MQH
|
|
|
|
#define CTX_NA (-999.0)
|
|
|
|
enum ENUM_CTX
|
|
{
|
|
//--- price shape (ModalityPrice)
|
|
CTX_Z = 0, // z-score(20) of the close
|
|
CTX_DIST_ATR, // (close - SMA20) / ATR
|
|
CTX_RET1_ATR, // last bar's return, in ATR
|
|
CTX_DROP5_ATR, // 5-bar return, in ATR
|
|
CTX_RANGE_ATR, // bar range, in ATR
|
|
CTX_CLOSE_LOC, // where the close sat in its own range, 0..1
|
|
CTX_ER, // efficiency ratio (20)
|
|
CTX_VR, // variance ratio (60, 5)
|
|
CTX_REGIME, // 0 chop / 1 trend / 2 mean-revert
|
|
//--- volatility (ModalityPrice)
|
|
CTX_VOL_PCT, // expanding-window percentile of Garman-Klass sigma(30)
|
|
CTX_ATR_RATIO, // ATR / mean ATR of the last 100 bars
|
|
//--- volume, clock removed (ModalityVolume)
|
|
CTX_RVOL, // ln(tick volume / same-hour median), level-detrended
|
|
CTX_RVOL_RAW, // the same without the detrend
|
|
CTX_ABSORB, // effort minus result: rvol - ln(range/ATR). High = volume without progress
|
|
//--- Wyckoff structure (ModalityWyckoff)
|
|
CTX_WYK_OK, // 1 when the indicators answered
|
|
CTX_WYK_PHASE, // phase * direction: +-1..5 = A..E
|
|
CTX_WYK_EVENT, // last event within the look-back, signed code (+-1..9)
|
|
CTX_WYK_AGE, // bars since that event
|
|
CTX_WYK_SPRING, // strongest spring/UTAD grade within the look-back, signed
|
|
CTX_WYK_CHAR, // +1 accumulation / -1 distribution / 0 not anchored
|
|
CTX_WYK_RANGEPOS, // close inside the open range, 0..1 (NA when no range is open)
|
|
CTX_WYK_FAIL, // failed-structure quality, signed
|
|
CTX_WYK_BIAS, // the reader's verdict for a LONG, -1..+1
|
|
//--- cross-index breadth (ModalityBreadth)
|
|
CTX_BREADTH_N, // peers that answered
|
|
CTX_BREADTH, // fraction of them at z(20) <= -1
|
|
//--- calendar (ModalityCalendar)
|
|
CTX_DOW,
|
|
CTX_HOUR,
|
|
CTX_DOM, // day of month
|
|
CTX_TO_MONTH_END, // calendar days to month end
|
|
CTX_N
|
|
};
|
|
|
|
string CtxName(const int i)
|
|
{
|
|
switch(i)
|
|
{
|
|
case CTX_Z: return "z20";
|
|
case CTX_DIST_ATR: return "dist_sma_atr";
|
|
case CTX_RET1_ATR: return "ret1_atr";
|
|
case CTX_DROP5_ATR: return "ret5_atr";
|
|
case CTX_RANGE_ATR: return "range_atr";
|
|
case CTX_CLOSE_LOC: return "close_loc";
|
|
case CTX_ER: return "er20";
|
|
case CTX_VR: return "vr60_5";
|
|
case CTX_REGIME: return "regime";
|
|
case CTX_VOL_PCT: return "vol_pct";
|
|
case CTX_ATR_RATIO: return "atr_ratio";
|
|
case CTX_RVOL: return "rvol_tod";
|
|
case CTX_RVOL_RAW: return "rvol_tod_raw";
|
|
case CTX_ABSORB: return "absorb";
|
|
case CTX_WYK_OK: return "wyk_ok";
|
|
case CTX_WYK_PHASE: return "wyk_phase";
|
|
case CTX_WYK_EVENT: return "wyk_event";
|
|
case CTX_WYK_AGE: return "wyk_event_age";
|
|
case CTX_WYK_SPRING: return "wyk_spring";
|
|
case CTX_WYK_CHAR: return "wyk_char";
|
|
case CTX_WYK_RANGEPOS: return "wyk_range_pos";
|
|
case CTX_WYK_FAIL: return "wyk_fail";
|
|
case CTX_WYK_BIAS: return "wyk_bias";
|
|
case CTX_BREADTH_N: return "breadth_n";
|
|
case CTX_BREADTH: return "breadth";
|
|
case CTX_DOW: return "dow";
|
|
case CTX_HOUR: return "hour";
|
|
case CTX_DOM: return "dom";
|
|
case CTX_TO_MONTH_END: return "to_month_end";
|
|
}
|
|
return "?";
|
|
}
|
|
|
|
struct SMarketContext
|
|
{
|
|
datetime bar; // open time of the signal bar
|
|
double v[CTX_N];
|
|
string story; // the same reading, as a trader would say it
|
|
|
|
void Reset(const datetime t)
|
|
{
|
|
bar = t;
|
|
story = "";
|
|
for(int i = 0; i < CTX_N; i++)
|
|
v[i] = CTX_NA;
|
|
}
|
|
bool Has(const int f) const { return v[f] != CTX_NA; }
|
|
};
|
|
|
|
//--- The CSV columns for a context, in field order. Header and row are built from the same loop,
|
|
//--- so they cannot disagree about width or order.
|
|
string CtxHeader(void)
|
|
{
|
|
string h = "";
|
|
for(int i = 0; i < CTX_N; i++)
|
|
h += (i > 0 ? "," : "") + CtxName(i);
|
|
return h;
|
|
}
|
|
|
|
string CtxRow(const SMarketContext &c)
|
|
{
|
|
string r = "";
|
|
for(int i = 0; i < CTX_N; i++)
|
|
r += (i > 0 ? "," : "") + DoubleToString(c.v[i], 5);
|
|
return r;
|
|
}
|
|
#endif // WARRIOR_MARKETCONTEXT_MQH
|