Updated 2026-04-25 to a 5-bucket bracket with wash trades resolved at the 10-bar close. Previous version lumped 60–70% of signals into a "wash" bucket worth $0; the new resolution splits washes into wash_loss and wash_profit based on actual close, and EV is computed from realized P&L. The qualitative result holds: only regular bullish carries positive edge (+$0.011 vs baseline EV of +$0.023). Regular bearish is significantly negative; hidden bull/bear are flat to slight-negative. Sample: 36,829 signals over 6,582 RTH sessions (Jan 2000 – Apr 2026). Codex-reviewed for look-ahead, baseline fairness, and significance.
Home
Study — TenAM Traffic PO Divergence (3-min)

Under a realistic dollar bracket, only one of the four PO divergences edges baseline — regular bullish, the one the textbook says shouldn't work standalone.

TenAMTrader's "Traffic Signal" indicator flags four divergence types. The original publish used end-of-day direction as the success criterion — a $0.01 close-up counted as a win — and hidden divergences looked +2-3 pp above baseline. Re-running with a realistic OCO bracket ($0.50 stop, $0.50 partial, $1.00 full, exit at the 10th bar's close if neither fires) flips the picture. Hidden bull is flat; hidden bear is slightly negative; regular bear is significantly negative; regular bull edges baseline by +$0.011 per signal — the only marginally positive cell, and the one labelled a "failed reversal signal" under the loose EOD view. The headline conclusion: under realistic stops the indicator does not produce a robust standalone edge, and the small positive edge that does exist is on the opposite side of where the EOD-direction view pointed.

A pivot is a local extreme of the oscillator. The indicator looks at consecutive PO pivots, compares each to the previous one, and pairs the comparison with the price extreme at the same bar. Four cases — two reversal (regular) and two continuation (hidden):

🟢
Regular Bullish
Price prints a lower low, oscillator prints a higher low.
Theory: hidden buying. The oscillator says momentum has stopped declining even as price has not. Predicted reversal up.
🟡
Hidden Bullish
Price prints a higher low, oscillator prints a lower low.
Theory: trend pause. Price is still making higher pivot lows; the oscillator has flushed deeper. Predicted continuation up.
🔴
Regular Bearish
Price prints a higher high, oscillator prints a lower high.
Theory: exhaustion. Price keeps grinding up but the oscillator is fading. Predicted reversal down.
🟡
Hidden Bearish
Price prints a lower high, oscillator prints a higher high.
Theory: relief bounce. The oscillator is recovering but price has not made a new high. Predicted continuation down.

Pivots use the indicator's defaults: lbL=1, lbR=3 — one bar of confirmation to the left, three to the right. A pivot at bar i is therefore only confirmed at bar i+3; we use that confirmation bar's close as the entry. The previous pivot must be within 60 bars (the indicator's range filter).

Define success as a trader would. Enter at the close of the confirmation bar. Place a stop $0.50 against you. Take partial profit at $0.50 in your favor. Take full profit at $1.00. If 10 bars (30 minutes) elapse with neither the stop nor the partial fired, exit at the 10th bar's close at the realized P&L. This produces five mutually-exclusive outcomes:

Hard Loss
Stop fires — −$0.50.
Within-bar ordering: if a single bar's range contains both stop and partial, the stop fires first (worst-case fill).
Wash Loss
Neither stop nor partial fires; bar-10 close against the signal.
Realized P&L is the signed price diff — usually small ($0 to −$0.50).
Wash Profit
Neither stop nor partial fires; bar-10 close in favor of the signal.
Realized P&L is small ($0 to +$0.50). Most "wash" bars on 3m SPY end here or in wash-loss.
Partial Win
+$0.50 in-direction fires before stop; $1.00 doesn't fire by bar 10. +$0.50.
Once partial is locked, only a $1.00 full hit upgrades it. Subsequent stop hits don't revert to a loss.
Full Win
$1.00 in-direction fires within 10 bars (with or without partial first). +$1.00.
The cleanest cells. Rates are 4–7% across signal kinds vs ~5–6% baseline.

Across 50,000 random RTH 3-minute bars (the unconditional baseline), the 5-bucket distribution and EV are:

Direction Loss% Wash-loss% Wash-profit% Partial% Full% Total win% EV / sig
Bull18.6%30.1%34.9%11.2%5.3%51.4%+$0.023
Bear16.8%33.6%31.4%12.1%6.1%49.6%+$0.031

Bull baseline EV is +$0.023; bear baseline EV is +$0.031. (Both are positive because SPY's wash trades drift slightly with direction; bear EV is higher partly because of how within-bar ordering interacts with the bear's stop-on-up rule.) Now the signal results vs matched baseline:

Signal N Loss% Wash-loss% Wash-profit% Partial% Full% Total win% EV / sig Edge vs base
Regular Bullish10,04221.4%25.6%33.4%12.8%6.8%53.0%+$0.034+$0.011
Hidden Bullish8,28615.4%32.7%37.6%10.5%3.9%52.0%+$0.020−$0.003
Regular Bearish11,25617.0%33.5%33.4%10.8%5.2%49.5%+$0.014−$0.017
Hidden Bearish7,24518.6%33.7%28.1%13.0%6.6%47.6%+$0.026−$0.005

Only regular bullish edges baseline. reg_bull at +$0.011 per signal, with total-win rate 53.0% vs baseline 51.4% — a 1.7 pp lift in winners and a 1.6 pp drop in losers. With n=10,042 the standard error is roughly $0.005, so the gap is around 2-sigma significant on its own — small but real on this sample.

Regular bearish is significantly negative at −$0.017 per signal — shorting on a regular bearish divergence is materially worse than shorting a random RTH bar. The hidden divergences are essentially flat to slightly negative.

This is the opposite of what the EOD-direction view said, where hidden divergences looked +2-3 pp above baseline and regular looked −2-4 pp. The realized-PnL bracket exposes that the apparent "hidden edge" was small drift toward entry, not toward $0.50.

The first publish of this study used a looser definition: did price close in the predicted direction by RTH close? Under that test, hidden bullish divergences looked +2.5 pp over baseline and hidden bearish +1.7 pp — small but statistically real edges. Using a $0.50/$1.00 bracket changes the picture entirely:

Signal EOD-dir edge (loose) Bracket EV edge (real) Same direction?
Regular Bullish−2.43 pp+$0.011FLIPPED
Hidden Bullish+2.47 pp−$0.003FLIPPED
Regular Bearish−3.82 pp−$0.017same (negative)
Hidden Bearish+1.74 pp−$0.005FLIPPED

Three of the four signs flipped. Why? Hidden divergences select for low-volatility paths. They produce a slight bias toward modest closes in the predicted direction, but those closes don't get to $0.50 and they sit through paths where the stop fires intraday. A trade that drifts +0.10% by RTH close looked like a win under EOD; in a real bracket it might have already pierced the $0.50 stop hours earlier. Regular bullish does the opposite: it's worse on the EOD-correct rate but its bracket distribution shifts more probability mass into both wash_profit (33.4% vs 34.9% baseline — about even) AND partial+full (19.6% vs 16.5% baseline) at the cost of a higher hard-loss rate (21.4% vs 18.6%). Higher variance, higher stops, but the right-tail is fatter and the realized P&L wins.

Forget end-of-day — do these signals at least reach the next Saty ATR level in the predicted direction? For each signal, we restrict to cases where the relevant level is unreached at entry and ask does intraday price get there?

Signal Trigger (±23.6%) Golden Gate Entry (±38.2%) Midrange (±61.8%)
Regular Bullish (n≈9k)21.7%16.0%9.4%
Hidden Bullish (n≈5k)37.8%31.9%24.0%
Regular Bearish (n≈10k)18.8%14.3%8.5%
Hidden Bearish (n≈5k)38.8%33.1%25.5%

Sample sizes vary because the level can already be on the wrong side of entry; those events drop out. Hidden divergences reach the next ATR level roughly 2× as often as regular ones. That ratio is the most consistent finding in the study.

Why hidden > regular here? The hidden setups are trend-aligned by construction — the price trend is intact, the oscillator just took a deeper retracement. Trades in the trend direction reach the next ATR level with the wind at their back. The regular setups are trying to pick a top or bottom; against a 25-year drift up, that's a structurally hard ask.

The author's TenAMTrader handle isn't subtle — the indicator is meant to fire after the morning chop has cleared. The data agrees, partially. Hidden divergences in the 10:00–13:30 window carry the cleanest edge, and that edge gets a meaningful boost when the Pivot Ribbon trend is the same direction.

Same trend-aligned filter (clouds match signal direction) + 10:00–13:30 morning window, evaluated under the 5-bucket bracket. The morning regime does not rescue any kind:

Filter N Loss% Win% EV / sig Edge vs baseline
reg_bull, bull/bull, 10:00–13:3047947.0%53.0%+$0.029+$0.006 (not sig)
hid_bull, bull/bull, 10:00–13:304,74848.5%51.4%+$0.019−$0.004
reg_bear, bear/bear, 10:00–13:3045453.3%46.7%+$0.011−$0.020
hid_bear, bear/bear, 10:00–13:303,98053.5%46.5%+$0.025−$0.006

Under the loose EOD-direction metric, these same combos produced +3.10 pp (hid_bull) and +4.08 pp (hid_bear) "edges." Under the realistic 5-bucket bracket those edges are gone or negative. The "best" combo is reg_bull bull/bull morning at +$0.006 per signal — positive but n=479 with SE ≈ $0.018 means it is not statistically distinguishable from baseline. The morning filter shrinks the full-sample reg_bull edge of +$0.011 down to +$0.006.

The morning trend filter doesn't rescue the indicator. Stacking the divergence with a same-direction Pivot Ribbon and the 10:00–13:30 window narrows the sample but doesn't concentrate edge. The full-sample reg_bull edge is bigger than any of these filtered combos — the trend-and-time filter washes some of the alpha out, suggesting the small reg_bull edge isn't a "morning trend" thing.

The ±0.25% intraday hit-rate (not shown here for brevity) declines monotonically through the day for every signal type — from ~64% at 09:30–10:00 to ~12% at 15:30. That's pure hours-remaining decay, not signal quality. EOD-correct%, in contrast, is fairly flat; the small advantage hidden divergences enjoy holds across the day but is concentrated mid-session.

The Pine inputs include two optional zone filters — "hide signals when oscillator is between 23.6 and 61.8" (Zone A) and "hide signals when oscillator is between −61.8 and −23.6" (Zone B). Both default to off. We tested both on/off as a filter switch on EOD-correct%:

Filter / Signal In-zone n In-zone EOD% Out-zone n Out-zone EOD% Out − In
Zone A (osc in 23.6 – 61.8)
Regular Bullish10949.5%9,93349.6%+0.1
Hidden Bullish2,19955.1%6,08754.3%−0.7
Regular Bearish6,08744.2%5,16944.3%+0.1
Hidden Bearish61650.5%6,62949.6%−0.9
Zone B (osc in −61.8 – −23.6)
Regular Bullish5,03949.7%5,00349.5%−0.3
Hidden Bullish52652.1%7,76054.7%+2.6
Regular Bearish9742.3%11,15944.3%+2.0
Hidden Bearish1,68352.9%5,56248.7%−4.2

The largest cell is hidden bearish −4.2 pp inside Zone B, meaning suppressing hidden-bearish signals in that zone does help — modestly, in n=1,683. Zone A is essentially noise across all four signals. Default-off was the right default.

The natural stop for a divergence trade is the pivot extreme that triggered it — the local low for a bull, the local high for a bear. We tracked whether price re-pierced that level after entry, and whether the signal still closed correctly by EOD anyway.

Signal Clean n Clean EOD% Stopped n Stopped EOD% Stop rate
Regular Bullish2,81484.1%7,22836.2%72.0%
Hidden Bullish2,45885.9%5,82841.3%70.3%
Regular Bearish2,73080.9%8,52632.5%75.7%
Hidden Bearish1,95682.9%5,28937.3%73.0%

"Clean" = price never re-pierced the pivot extreme intraday. "Stopped" = it did. Stop rate is the fraction of signals that stopped out at least once before RTH close.

Clean signals are dramatic. When price respects the pivot — about one in four signals across all kinds — the EOD-correct rate jumps to 81–86%. That is a genuine signal, hidden inside a noisy outer envelope.

Stopped signals are below baseline. If the pivot gets re-pierced, the EOD-correct rate collapses to 32–41%. The pivot break is the real signal here — but it's an exit signal, not the entry. The trade is: enter at the confirmation bar, cut on the first close back through the pivot. That's not the same as “stop at the pivot tick price,” which fires three of every four signals on noise. Use a close-based stop or give the pivot 0.25–0.50% slip.

The only positive-edge signal is regular bullish at +$0.011 per signal under the 5-bucket bracket. Total win rate 53.0% vs baseline 51.4%. Effect size is small but real on n=10,042. Worth using only if you size for many trades; not worth back-fitting filters that shrink the sample without concentrating alpha.

Don't trade regular bearish divergences on 3m SPY. −$0.017 per signal vs baseline (z ≈ 3) is a meaningful negative edge. The signal selects for setups where shorts get steamrolled.

Hidden divergences are noise under realistic stops. Hid_bull is flat (−$0.003), hid_bear is slightly negative (−$0.005). The "+2-3 pp edge over baseline" from the EOD-direction view doesn't survive a $0.50 stop. Hidden divergences select for low-volatility paths that close slightly in-direction by EOD — useful only if you're answering "is the day green or red", not for a $0.50/$1.00 bracket where the intraday path matters.

Morning trend filter doesn't help. Stacking same-direction Pivot Ribbon plus 10:00–13:30 actually shrinks the reg_bull edge from +$0.011 to +$0.006. The clean positive edge is in the unfiltered reg_bull cell.

Skip the indicator's zone filters. Zone A is noise; Zone B has one mildly useful cell (suppressing hidden bearish) and one mildly harmful one. Default-off is correct.

What this study does not claim. PO divergences may behave differently on 10m or 1h timeframes; we did not test those. The bracket parameters here ($0.50/$0.50/$1.00, 10 bars) are one specific choice; tighter targets or longer windows would shift the picture. What the study does claim: on 3-min RTH SPY with these stops, only regular bullish has a positive standalone edge, and it is small (±$0.011 / signal). The other three signal kinds are flat to significantly negative.

Data: 25 years of SPY 1-minute data (Jan 2000 – Apr 2026), aggregated to ind_3m. Phase Oscillator computed on 3m's own timeframe; ATR Levels computed from the previous day's close and ATR(14) and broadcast to every intraday bar (Saty Day-mode). Pivot Ribbon EMAs validated to 0.000% error vs TradingView on 10m. 3-min Phase Oscillator has not been independently validated against TradingView — only 10m and 60m have. The direction of this study's findings (regular fails, hidden small-positive) is the durable result; magnitudes are approximate.

Pivot detection (not validated against TradingView): our Python uses strict < on both sides at lbL=1, lbR=3. Pine's exact tie-handling on ta.pivotlow / ta.pivothigh was not independently confirmed. A pivot at bar i in our implementation requires osc[i] < osc[i-1] AND osc[i] < osc[i+1..i+3]. Confirmation bar = i + lbR; entry = close of the confirmation bar — same bar the indicator can plot it, no look-ahead. If Pine accepts ties on either side our pivot count would be slightly higher, but we expect the qualitative results to hold.

Forward measurement: all bracket / MFE / MAE / hit-target / stop-out reads happen on bars conf+1 through end-of-day, never on the confirmation bar itself. ATR-level columns (atr_upper_trigger etc.) come from the day's previous close and ATR via the daily-reference broadcast, so they are known at the open and carry no look-ahead.

5-bucket OCO bracket details: $0.50 stop against, $0.50 partial in direction, $1.00 full in direction. Path-walk semantics: walk bar-by-bar from conf+1, stop fires before any in-direction level is hit; partial fires if the bar's range crosses $0.50 in direction without first crossing the stop; once partial is locked, only the $1.00 full level can upgrade. If neither stop nor partial fires within 10 bars (30 min), exit at the bar-10 close at realized P&L — categorized as wash_loss (close against signal) or wash_profit (close in favor). Five outcomes: loss (−$0.50), wash_loss (signed P&L < 0), wash_profit (signed P&L > 0 but < +$0.50), partial (+$0.50), full (+$1.00). Within-bar conservative ordering: a single bar containing both the stop and the partial is treated as stop-first. Random-bar baseline computed by sampling 50,000 RTH 3m bars and applying the same walk. EV is the sum of realized P&L divided by signal count, so it weights wash trades by their actual closing P&L rather than treating them as zero.

Per-session reset (changes the signal definition): pivot tracking restarts each RTH session (09:30–15:59 ET). On an RTH-only series, yesterday's 15:57 bar and today's 09:30 bar are adjacent (1 bar apart), so cross-day pairs would have passed the 60-bar range filter; we drop them anyway. That is a deliberate definitional choice, not a hygiene tweak: pre-market behaviour is mechanically different and we did not want overnight gaps polluting pivot pairs. A future revision could compare with-overnight vs without.

Range filter (off by one vs Pine): Pine's _inBarsRange(plFound[1]) using ta.barssince(plFound[1]) evaluates to i_curr − i_prev − 1 at the current confirmation. Our Python uses i_curr − i_prev, which is one bar stricter at the upper bound. In this sample bars_since_prev never exceeds 38, so the 60-bar cap was never binding either way and aggregate stats are unaffected.

Baseline: for each half-hour bucket, P(RTH-close > entry-close) computed over all 853,981 RTH 3m bars in the sample. Edge is computed against a signal-weighted matched baseline — the per-signal-type weighted average of those half-hour P(up) values, accounting for when each signal type tends to fire. Signal-type baselines: bull-direction ~52.0–52.1%, bear-direction (close-down) ~47.9–48.1%. Including signal bars in the baseline distorts it by <0.05 pp. The baseline does not control for ribbon, volatility, or trend regime; that is a known confound in the best-filter combos.

Statistical significance: with proportions in [44%, 56%] and n in [4,748, 11,256], naive Wald SEs run 0.47–0.79 pp. Every edge in the headline table is ≥3σ under the naive (independent-signal) assumption; the +3.10 and +4.08 pp morning combos clear z=4–5. Caveat: 36,829 signals come from only 6,582 sessions (median ~5 signals/session, max 15), so signal-level independence is violated and a cluster-robust SE would be larger. We did not compute a cluster-bootstrap; treat headline z-scores as upper bounds.

Early-session coverage: the lbR=3 confirmation requirement means the earliest possible confirmation timestamp is 09:42 ET, but in practice the EMA21 / ATR(14) warmup masks all signals before 09:48. The "09:30" half-hour bucket reported here actually contains only signals from 09:48–09:57, n=380 across all four kinds.

Full design doc: /root/spy/proposal_tenam_traffic.md. Implementation: /root/spy/backtest_tenam_traffic.py. Event-level JSON (36,829 records, ~57 MB): /root/spy/tenam_traffic_events.json. Reviewed by Codex 2026-04-25 for look-ahead, baseline fairness, Pine semantics, and statistical significance; all flagged corrections applied to the published numbers above.