eqmom rule (126d momentum, top decile, 21d hold), 234 rebalances, 2,351 name-events over 1-min caches. saved_bps = later price − open (BUY: positive = the open fill was the better price, i.e. waiting would have cost more). 50% IEX haircut.
| schedule | n | mean bps | haircut mean | p(mean<=0) |
|---|---|---|---|---|
| 0935 | 551 | +8.31 | +4.16 | 0.001 |
| 1030 | 540 | +11.51 | +5.76 | 0.033 |
| 1550 | 612 | +22.22 | +11.11 | 0.003 |
| close | 648 | +19.90 | +9.95 | 0.004 |
Per-year (best schedule by |haircut mean|)
schedule = 1550
| year | n | mean bps |
|---|---|---|
| 2020 | 42 | -69.85 |
| 2021 | 106 | +68.66 |
| 2022 | 103 | +32.97 |
| 2023 | 102 | -20.13 |
| 2024 | 103 | +29.81 |
| 2025 | 94 | +45.69 |
| 2026 | 62 | +8.84 |
Reading
- Positive mean = the open (actual fill) was at a BETTER price than waiting -> immediacy wins; negative = waiting would have saved cost.
- Caveat: 1550/close are confounded by intraday momentum drift (winners rise into the close), so those means overstate 'savings'. The 09:35 (5-min delay) estimate is the cleanest.
- The live shadow (scripts/exec_timing_shadow.py) applies the same quantity to real fills; bar: haircut mean > 2 bps, p<0.05, n>=100. Time 597s.