NQ · research

MN HOLD-SIDE — the midnight-open hold day

On ~33% of MNQ sessions, price never crosses the NY midnight open after 09:30. A four-step investigation — filter, target, entry, confluence — that produced a +55 pt/trade tier-1 setup and a bonus/penalty layer that lifted 16 other models in the suite.

updated 2026-04-24
shipped midnight-openhold-daytrend-filtertarget-sweepconfluencemeta-validation

The question

Does the NY midnight open (00:00 ET 1-minute bar open) act as support/resistance during RTH, and if so, how do we trade it?

The obvious answer — “it’s a magnet, fade touches” — was the first experiment. The obvious answer was wrong. The tradable edge sits in the sessions that never reach the midnight open, and isolating those sessions in advance turned out to be a four-step investigation.

Part 1 — three modes on the midnight open

backtest_midnight_open.py ran three theses against 1,370 RTH sessions of MNQ 1-minute data:

ModeThesisResult
First-touch fadePrice touches MN after 09:30 → fade back47.8% close-favorable (coin flip)
Reclaim momentumPrice reclaims MN → continuationNegative expectancy at every target (stop too wide; Q50 risk 37.8)
Hold-sidePrice opens on one side and never crosses33.4% of sessions, Q50 excursion 172.5 pts vs 63.8 on cross days — the edge

Hold days pay 2.7× on average excursion. The question became: can we filter for them before they play out?

Part 2 — the T3 classifier

mn_hold_classifier.py mined features (gap state, open side, distance bucket, 4H trend, DOW, opening-range ratio, gap/ATR ratio) against the hold/cross label. Three features produced usable lift:

FeatureHold rateBase 33.5%
|dist| ≥ 6050.6%+17
gap/ATR = XL65.8%+32
on_range/ATR = XL68.3%+35

The cleanest two-feature combinations:

That’s the T3 filter: |RTH_open − MN| ≥ 60 AND 4H SMC trend aligns with open side. It picks 30% of sessions with a ~60% hold rate (vs 33% base). 409 qualifying sessions in 4 years of history.

Part 3 — target sweep and distance cap

backtest_mn_hold_trades.py first confirmed T3 was the best of four candidate filters (T1 raw |dist|≥60, T2 dist+gap, T3 dist+trend, T4 dist+trend+range). T3 returned +28.14 pts/trade at target 300 on 409 trades — the winner.

But risk was unbounded: worst single loss was 424.5 pts (one wide-gap outlier on 2024-08-05). The next question: does capping the distance improve the risk profile?

backtest_mn_hold_entry_refine.py (Experiment A) swept 6 distance tiers:

TiernRisk MAXBest targetExp/trTotal
T3 (baseline)409471.8300+28.14+11,508
T3a [60–100]166100.0300+45.59+7,568
T3b [60–120]244120.0300+35.81+8,738
T3c [60–150]295150.0300+34.33+10,127
T3d [60–200]341199.2300+39.09+13,330
T3e [60–250]374248.5300+35.92+13,433

Every cap beats baseline on expectancy. T3a tightens risk to 100 pts and pushes exp/tr to +45.59, but throws away half the trade count. T3d caps at 200 pts and captures the highest total points. T3d won the deployment slot.

Part 4 — should we wait for a pullback?

backtest_mn_hold_entry_refine.py (Experiment B) measured max pullback toward MN within the first 15 / 30 / 60 min after 09:30, then simulated a “wait for ≥X pts pullback, enter at limit” rule:

Pullback requiredTrades takenWin%Exp/trTotal
0 (enter at 09:30 open)40939.6%+20.25+8,283
≥ 10 pts36234.8%+12.35+4,472
≥ 20 pts31933.2%+8.32+2,654
≥ 30 pts28431.0%+4.28+1,216
≥ 40 pts25127.5%−0.02−4
≥ 50 pts22124.0%−4.11−909

Every 10-pt of waited-for pullback cost ~8 pts of expectancy. On hold days, price doesn’t retrace — that’s the definition of a hold day. Waiting for a better fill is a trap.

Part 5 — what about filtering out chased trades?

The intuition: if price has already extended, say, 80 pts away from MN in the first 30 min, the “easy move” is gone, right? Skip it?

backtest_mn_hold_entry_refine.py (Experiment C) tested extension-based skip filters at 40/60/80/100 pts. Every filter destroyed edge. The conditional table showed why:

First-30-min extensionnWin%Exp/tr
0–20 pts9610.4%−65.51
20–40 pts6622.7%−10.43
40–60 pts6217.7%−9.33
60–80 pts4240.5%+28.55
80–100 pts3966.7%+79.65
100–150 pts7070.0%+91.90
150+34100%+150.00

Early extension is the signal, not a warning. Sessions that trundle near MN for 30 min are where the losses live — price is still coiling and has room to reclaim. Once the market is 60+ pts away by 10:00, target hit becomes near-certain.

This flips the deployment logic: instead of skipping extended trades, we confirm them. Enter at 10:00 only if ≥60 pts of early extension is on the tape.

Part 6 — the stacked configuration

backtest_mn_hold_entry_D.py stacked distance cap × ext filter × target sweep. Best cells (exp/trade):

TierNo ext filterext ≥ 40ext ≥ 60ext ≥ 80
T3 (all, 409)+21.23+31.58+41.79+44.28
T3a [60–100]+31.84+40.54+54.16+52.50
T3d [60–200]+28.25+39.51+55.13+61.49

Two deployable modes emerge:

Part 7 — DOW breakdown

DOWMode A nMode A exp/trMode B nMode B exp/tr
Mon61+40.0629+26.33
Tue71+50.7735+86.11
Wed65+46.8425+55.82
Thu81+8.9229+17.23
Fri63+45.6930+82.91

All five weekdays net positive in both modes. Thursday drags Mode A (can be filtered to lift Mode A to +46/tr × 260), Tuesday and Friday shine especially in Mode B.

Part 8 — the confluence discovery

While building the target & entry logic, one more question was worth asking: does the MN HOLD signal tell us anything about the other models that fire on the same day?

backtest_mn_hold_integration.py joined 341 MN HOLD sessions against ~34k historical PredictionModel predictions and classified each line as ALIGNED, OPPOSED, or NO-HOLD. The results were striking:

Top aligned boosts

ModelBase hit%Aligned%ΔOpposed%Δ
PDH TOUCH47.877.2+29.421.6−26.2
PDL TOUCH43.574.5+31.022.8−20.7
PO XTND BEAR44.263.0+18.741.3−2.9
ASIA [Med] LOW74.389.5+15.265.1−9.2
1H CRT81.794.5+12.864.6−17.0
0809 MID85.697.1+11.673.4−12.2

PDH/PDL TOUCH swings 60 percentage points between aligned and opposed. That’s one of the cleanest directional signals we’ve ever seen in a confluence layer.

PRIME tier spikes

ModelBaseAligned + PRIMELift
LON SWEEP L80.598.4+17.8
PO RNG MID80.4100.0+19.6
LON SWEEP H84.698.5+13.9
0809 SEQ HIGH87.798.2+10.5

Heavy penalties on mean-reversion lines

ModelBaseOpposedΔ
INSIDE GAP FILL66.239.1−27.1
MN OPEN FILL66.540.1−26.4
GAP FILL → PDH65.751.6−14.0
FILL 07-08 L80.866.2−14.6

The entire “fill / magnet” family — MN OPEN FILL, INSIDE GAP FILL, GAP FILL → PDH/PDL, FILL XX-XX, VWAP MAGNET — degrades dramatically on opposed hold days. These are mean-reversion models; hold days are trend days by definition. MN HOLD turned out to be the single best “mean-reversion OFF” filter we have.

Part 9 — meta-validation

backtest_mn_hold_meta.py applied the full bonus/penalty table above to the 34k historical prediction population and measured calibration drift:

BucketBaseline hit% (n)Adjusted hit% (n)
<4545.4% (1,166)44.9% (780)
45–5448.5% (2,988)49.2% (2,947)
55–6466.9% (2,179)67.7% (2,248)
65–7470.7% (5,472)70.8% (6,083)
75–8479.5% (16,034)79.8% (14,548)
85–9489.0% (6,118)89.8% (5,994)
95+93.3% (119)97.5% (681)

Every bucket stays calibrated or slightly improves. The adjusted 95+ bucket grew 5.7× and still hit at 97.5%. Overall adjusted hit rate 75.98% vs baseline 75.16% (+0.82 pp), with 795 bad lines correctly killed — 60–70% of those kills were real losers.

The ship list

All three production layers live:

  1. smc_analysis.py (HUD producer) — emits mn_hold_* keys on its schedule.
  2. PredictionModel.cs + PredictionModelWeb.cs — draws MN HOLD BULL/BEAR (upgrades to MN HOLD PRIME) and applies the confluence bonus/penalty table to all other active lines after the AMD block.
  3. MnHoldSide.cs — NT8 strategy with Mode parameter switching between ImmediateOpen930 and ConfirmAt1000.

Model page: MN HOLD-SIDE.

Scripts

C:\SMC\scripts\
  backtest_midnight_open.py          Part 1 — three-mode exploration
  mn_hold_classifier.py              Part 2 — T3 filter discovery
  backtest_mn_hold_trades.py         Part 3 — tier comparison + target sweep
  mn_hold_show_examples.py           Concrete wins/losses/scratches for inspection
  backtest_mn_hold_entry_refine.py   Parts 3-5 — distance cap, pullback, extension
  backtest_mn_hold_entry_D.py        Part 6 — stacked grid
  backtest_mn_hold_dow.py            Part 7 — DOW breakdown
  backtest_mn_hold_integration.py    Part 8 — confluence discovery
  backtest_mn_hold_meta.py           Part 9 — end-to-end validation

Result files live in C:\SMC\backtest_results\.