Warrior_EA/research/VOLNORM_RESULTS.md
AnimateDread e9c562b39f Add Feature Scaling and Regime Math Classes; Implement Mind Trading Logic
- 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.
2026-09-30 18:36:33 -04:00

52 行
3.1 KiB
Markdown

# Tick-volume normalization - results (2026-09-30)
Plan: `VOLNORM_PLAN.md`. Script: `python research/volnorm.py H4|H1`. Broker M1 `.hcc`, 4 indices,
2022-01..2026-08.
## Verdict
**Test 1 confirmed. Tests 2, 3 and 4 fail as written.** The repair removes the clock from the
feature; it does not make the feature more stable across years and it does not separate paying dips
from failing ones. No EA change is justified by this run beyond the DRY clean-up.
## H4 (the book's timeframe)
| idx | R^2 old | R^2 new | yr-mean sd old | yr-mean sd new | rho old | rho new |
|---|---|---|---|---|---|---|
| SP500 | 0.567 | 0.001 | 0.080 | 0.120 | 0.190 | 0.055 |
| NAS100 | 0.583 | 0.005 | 0.064 | 0.172 | 0.159 | 0.037 |
| US30 | 0.645 | 0.003 | 0.080 | 0.093 | 0.176 | 0.065 |
| DAX40 | 0.705 | 0.014 | 0.080 | 0.228 | 0.045 | 0.057 |
Dip-z events (n 213-226 per index), top minus bottom tercile of the feature, bp:
new = SP500 -19.9, NAS100 -11.9, US30 -2.5, DAX40 -38.5; **pooled -18.0 [-38.3, +4.5]**.
old pooled +0.3 [-18.3, +22.1]. H1 pooled: old -1.6 [-7.3, 3.9], new -3.6 [-10.1, 2.8].
## Reading
1. **The defect is real and large.** 57-77% of the variance of today's relative-volume inputs is
which hour of the day the bar is. After same-slot normalization it is 0.1-1.4%. The three inputs
in `SignalNeural`, `WarriorVote::MgmtFeatures` and `FracDiff::VolumeAt` have been feeding the
clock to the models as if it were participation.
2. **Test 2 fails.** The slot profile is a 60-session median, so it lags any level shift: DAX40's
2022->2023 tick collapse leaves the yearly mean of the new feature at sd 0.23 against 0.08 for
the old one. Fix candidate (needs its own pre-registration): normalize by the slot's share of a
short trailing daily total instead of a long slot history, so the scale adapts within days.
3. **Test 3 fails literally, and the test was badly framed.** The old feature's correlation with
next-bar activity (0.16-0.41) is mostly the clock: open bars have both high volume and big
moves. What is left after removing the clock is 0.03-0.07. That is small but it is the honest
number. A within-hour comparison would have been the right control.
4. **Test 4 fails; a lead, not a finding.** The clock-free feature has the same sign on all four
indices at H4 (high-volume dips pay LESS, -18 bp pooled), but the CI includes 0 (p about 0.1) and
H1 does not repeat it convincingly. Unmodelled: the vol-regime gate is not applied to these
events, and it is itself a volume-adjacent variable.
## Consequences
- Keep the pre-registered outcome: **volume normalization does not improve the dip-buy.**
- Do fix the three duplicated computations into one shared normalizer (DRY) so that any future
volume-dependent model (Wyckoff effort-vs-result, NN inputs) is not confounded by the clock.
- Any re-test of the Wyckoff/NN volume inputs must use the repaired feature; the earlier null
results on those inputs were measured with the clock-contaminated one.
- The negative sign at H4 deserves ONE follow-up, pre-registered before it is run: gated events, and
the short-window normalizer from point 2.