GO_LIVE flags spread_pct as a not-yet-real field. The reason it was null is
structural: OHLCV bars carry no NBBO, so minute_bars.spread_pct can never be
populated from the bars endpoint. The execution-relevant figure is the spread at
the moment a setup is evaluated — a wide book quietly eats R on the thin sub-$20
names this system trades.
This makes that metric real, shadow-first (measure before gating), mirroring how
the catalyst score was introduced:
strategy/evaluation/liquidity.py: pure compute_spread_pct(bid, ask) →
(ask-bid)/mid, or None for missing/crossed/non-positive quotes (None never
collapses to a real 0.0). Unit-tested.
Watcher: optional injected spread_provider (same shape as catalyst_score_provider); default None == prior behavior byte-for-byte.
Computed spread is logged onto the criteria_evaluated and signal_ready events.
Observe-only — it does NOT gate ready/blocked.
run_live_paper: TTL-cached spread provider off the client; degrades to None
on any fault, SPREAD_PCT_ENABLED=0 to silence.
The dead scanner.spread_pct_max knob is intentionally left for a later
promotion, once the logged data shows spread separates outcomes.
GO_LIVE flags `spread_pct` as a not-yet-real field. The reason it was null is
structural: OHLCV bars carry no NBBO, so `minute_bars.spread_pct` can never be
populated from the bars endpoint. The execution-relevant figure is the spread at
the moment a setup is evaluated — a wide book quietly eats R on the thin sub-$20
names this system trades.
This makes that metric real, shadow-first (measure before gating), mirroring how
the catalyst score was introduced:
- `strategy/evaluation/liquidity.py`: pure `compute_spread_pct(bid, ask)` →
(ask-bid)/mid, or None for missing/crossed/non-positive quotes (None never
collapses to a real 0.0). Unit-tested.
- `AlpacaPaperClient.get_latest_quotes`: batched latest-NBBO fetch, mirrors
`get_latest_trades`.
- `Watcher`: optional injected `spread_provider` (same shape as
`catalyst_score_provider`); default None == prior behavior byte-for-byte.
Computed spread is logged onto the criteria_evaluated and signal_ready events.
Observe-only — it does NOT gate ready/blocked.
- `run_live_paper`: TTL-cached spread provider off the client; degrades to None
on any fault, SPREAD_PCT_ENABLED=0 to silence.
The dead `scanner.spread_pct_max` knob is intentionally left for a later
promotion, once the logged data shows spread separates outcomes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019psgRHdtTXz6TCnnqPiqGw
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
GO_LIVE flags
spread_pctas a not-yet-real field. The reason it was null isstructural: OHLCV bars carry no NBBO, so
minute_bars.spread_pctcan never bepopulated from the bars endpoint. The execution-relevant figure is the spread at
the moment a setup is evaluated — a wide book quietly eats R on the thin sub-$20
names this system trades.
This makes that metric real, shadow-first (measure before gating), mirroring how
the catalyst score was introduced:
strategy/evaluation/liquidity.py: purecompute_spread_pct(bid, ask)→(ask-bid)/mid, or None for missing/crossed/non-positive quotes (None never
collapses to a real 0.0). Unit-tested.
AlpacaPaperClient.get_latest_quotes: batched latest-NBBO fetch, mirrorsget_latest_trades.Watcher: optional injectedspread_provider(same shape ascatalyst_score_provider); default None == prior behavior byte-for-byte.Computed spread is logged onto the criteria_evaluated and signal_ready events.
Observe-only — it does NOT gate ready/blocked.
run_live_paper: TTL-cached spread provider off the client; degrades to Noneon any fault, SPREAD_PCT_ENABLED=0 to silence.
The dead
scanner.spread_pct_maxknob is intentionally left for a laterpromotion, once the logged data shows spread separates outcomes.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_019psgRHdtTXz6TCnnqPiqGw