Screener, Regime & Intraday API
Discovery + context + level inputs for strategy R&D: the screener family (candidate discovery by technical/options/fundamental/compression filters), the market regime surface (2×3-grid context plus GEX / volatility / Greeks), the intraday levels & profile that intraday strategies key off (VWAP, Initial Balance, Opening Range, pivots, volume-profile HVN/LVN, compression), and trade outcome analytics. Base path/api/graph/v1; internal Go→Python plumbing
under /api/internal/intraday. Auth as in the README.
Most intradaysession/position/signalendpoints are the live trading surface, not backtesting — R&D mainly cares about the levels/profile, volume-nodes, compression, screener, regime, and outcomes reads. They’re all listed for completeness.
Screener & Regime
Screener endpoints filter stocks by technical, fundamental, options, and market-context criteria to surface high-conviction opportunities. Regime endpoints provide market microstructure context—gamma exposure (GEX), volatility regimes, and options Greeks—using a canonical 2×3 grid (BULL/NEUTRAL/BEAR × LOW/HIGH_VOL) that gates strategy selection.POST /api/graph/v1/screener
Screen stocks using graph-native filters with optional relationship expansion. Returns paginated results with confluence scoring, technical indicators, and optional price levels, volume profile, and news. Request:ScreenerRequest (filters, include options, sort, pagination)
Response: ScreenerResponse (stocks: [StockResult], metadata: ScreenerMetadata)
Caching: 15s during market hours, 60s off-hours (Redis)
Query target: <500ms with includes, <200ms without
Filter contract: fail closed, never silently dropped (data#1606)
ScreenerRequest.filters (Filters, api/app/models/screener.py) and its 13
sub-filter models (PriceFilter, VolumeFilter, OptionsFilter,
TechnicalFilter, FundamentalFilter, ConfluenceFilter, PulseFilter,
EarningsFilter, PriceEventFilter, DarkPoolFilter, ConvictionFilter,
ThemeFilter, plus Filters itself) all set model_config = {"extra": "forbid"} — an unknown/misspelled filter key is a 422 at parse time, not a
silently-ignored field. ScreenerRequest’s own envelope carries the same
extra="forbid".
Beyond typo-rejection, every filter leaf the caller explicitly sets must
either compile into a graph predicate or the whole request is rejected — a
filter that is accepted by the schema but never wired into the query builder
used to return the unfiltered universe while claiming it was narrowed
(the original data#1606 defect). Enforcement is at the shared boundary
(GraphService.screen_stocks via assert_all_filters_compilable,
api/app/services/screener/screener_filters.py), so it applies uniformly to
the HTTP route, the natural-language screener, and internal callers like
ThesisScreener — not just this endpoint.
A request naming an unwired leaf gets 422:
patterns, technical.compression, technical.atr_compression_max,
price_events.event_types, price_events.min_severity,
price_events.days. Notably, filtering by pattern (the top-level patterns
list, or technical.compression) has no working path yet even though the
pattern registry itself already uses the current nr7id identifier (NR7 was
renamed from nr7) — the vocabulary rename is not the blocker, the missing
compiler wiring is. Pin-tested exhaustively in
api/tests/unit/test_screener_filter_fail_closed.py
(EXPECTED_COMPILED/EXPECTED_UNSUPPORTED), which fails closed itself: a
newly-added Filters field that isn’t classified in either set breaks the
test rather than rotting silently.
POST /api/graph/v1/options/screener
Screen stocks with options-centric defaults (IV percentile, chain OI, put/call ratios, pricing edges, Greeks alignment). Convenience wrapper over the base screener. Request:ScreenerRequest · Response: ScreenerResponse
POST /api/graph/v1/research/screener
Screen stocks by fundamental metrics (market cap, PE, PB, PS, EV/EBITDA, margins, ROE/ROA, debt ratios, dividend yield, FCF yield). Request:ResearchScreenerRequest (filters: ResearchScreenerFilters, sort, pagination)
Response: ResearchScreenerResponse (results: [ResearchScreenerResult], total_matched, returned, offset, query_ms)
POST /api/graph/v1/compression/screener
Screen for compression patterns (NR7, inside days, VCP contractions, Bollinger Band squeezes) with ATR-based contraction scoring. Request:CompressionScreenerRequest (days, min_nr7_count, is_nr7_today, min_inside_day_count, compression_level, max_atr_compression_ratio, min_vcp_contractions, limit, offset)
Response: CompressionScreenerResponse (results: [CompressionScreenerResult], total_count, lookback_days)
POST /api/graph/v1/screener/top-setups
Batch fetch top bullish and bearish setups in one call. Filters by ADV30 ≥$50M and Pulse bias; results cached in-memory. Request:TopSetupsRequest (limit: 1–20, default 5)
Response: (inferred from handler) {"bullish": ScreenerResponse, "bearish": ScreenerResponse, "errors": [str] | null}
GET /api/graph/v1/screener/sector-summary
Sector conviction aggregates for heatmap display. Groups stocks by sector and returns median conviction, median net confluence, and top movers by conviction delta. Response:SectorSummaryResponse (sectors: [SectorSummary], total_stocks, query_ms) · Caching: 60s (Redis)
POST /api/graph/v1/screener/nl
Translate natural language queries into structured screener filters via LLM (e.g. “oversold tech with high volume”). Request:NLScreenerRequest (query: str, regime_context: dict | null)
Response: NLScreenerResponse (filters: ScreenerRequest, explanation: str)
GET /api/graph/v1/regime/current
Current market regime + signal-strength context. Returns the dominant regime classification and which signal types perform well (win_rate ≥50%, profit_factor ≥1.0) in the current regime. Response: (inferred from handler){"current_regime": str, "timestamp": str | null, "strong_signals": [dict], "weak_signals": [dict], "performance": [dict]}
GET /api/graph/v1/regime/summary
All symbols — compact GEX + vol regime snapshot. Index ETFs (SPY, QQQ, IWM) with latest GEX regime, gamma flip strike, pin strike, vol regime, ATM IV, IV rank, term structure. Response:RegimeSummaryResponse (symbols: [RegimeSummaryItem], scheduler_running: bool, last_computation: str | null)
GET /api/graph/v1/regime//gex
Latest GEX snapshot. Optionalexpiration (YYYY-MM-DD) to filter to one expiry; omit for aggregate.
Params: symbol (path), expiration (query, optional) · Response: GEXSnapshotResponse
GET /api/graph/v1/regime//gex/history
GEX snapshot history (up to 90 days). Params:symbol (path), days (query 1–90, default 30). Response: [GEXSnapshotResponse]
GET /api/graph/v1/regime//vol
Latest volatility regime classification (e.g. “low-vol”, “high-vol”, “vol-expanding”). Params:symbol (path). Response: VolRegimeSnapshotResponse
GET /api/graph/v1/regime//vol/history
Vol regime history (up to 90 days). Params:symbol (path), days (query 1–90, default 30). Response: [VolRegimeSnapshotResponse]
GET /api/graph/v1/regime//vanna-charm
Vanna-charm Greeks curve across strikes. Params:symbol (path), expiration (query, optional). Response: VannaCharmResponse
GET /api/graph/v1/regime//auction-history
Downsampled GEX auction history + summary (regime transitions, average GEX, dominant regime, flip-strike range). Params:symbol (path), hours (query 1–168, default 72), resolution (query enum 1min/5min/15min/1h, default 5min). Response: AuctionHistoryResponse
GET /api/graph/v1/regime/transitions/performance
Regime transition performance matrix — win rates, average returns, recommended actions per transition. Params:lookback (query enum 90d/1y/5y, default 1y), signal_type (query, optional). Response: (inferred) {"transition_matrix": dict, "raw": [dict], "lookback": str}
Intraday levels, volume nodes, compression & outcomes
These power the intraday research toolkit — institutional-grade levels (VWAP, Initial Balance, Opening Range, pivots), volume-profile nodes (HVN/LVN), volatility compression (NR7, inside day, VCP), and trade outcome metrics. Thesession /
position / signal endpoints are the live-trading surface (listed for
completeness); the levels/profile, volume-nodes, compression, and
outcomes reads are what R&D consumes.
Session management (live trading surface)
POST /api/graph/v1/intraday/{symbol}/session— start session. BodyStartSessionRequest(mode: monitor|supervised|autonomous, trading_mode: paper|live). →IntradaySessionResponseGET /api/graph/v1/intraday/{symbol}/session— get current session (trading_modequery, default paper). →IntradaySessionResponsePOST .../session/stop·.../session/halt·.../session/resume— stop/pause/resume. →IntradaySessionResponsePOST .../session/mode— change mode mid-session. BodyModeChangeRequest. →IntradaySessionResponseGET /api/graph/v1/intraday/sessions— all active sessions. →AllSessionsResponsePOST /api/graph/v1/intraday/sessions/stop-all— kill-switch stop all. →AllSessionsResponsePOST /api/graph/v1/intraday/sessions/bulk-start— bulk start. BodyBulkStartRequest(items:[], trading_mode). → (inferred){created, already_active, errors, results}
Position management (live trading surface)
POST .../{symbol}/position/{position_id}/tighten-stop— BodyTightenStopBody(stop_price>0).POST .../position/{position_id}/close— close at market.POST .../position/{position_id}/close-partial— BodyPartialCloseBody(quantity>0).POST .../position/{position_id}/breakeven— move stop to entry.POST .../position/{position_id}/mark-closed— BodyMarkClosedBody(exit_price>0); monitor-mode manual close.
Signal & exit actions, close phase (live trading surface)
POST .../{symbol}/signal/{signal_id}/approve|skip|dismiss— supervised/monitor signal actions.POST .../{symbol}/exit/approve|skip— exit-recommendation actions (position_idquery).POST .../{symbol}/close-now— close phase (15:30–15:45 ET) immediate close (position_id,trading_modequery).POST .../{symbol}/mark-closed— close-phase monitor-mode mark (position_id,trading_modequery; BodyMarkClosedTimeStopBody).
Real-time stream
GET /api/graph/v1/intraday/{symbol}/stream— SSE event stream (signal, position_opened/closed, phase_change, level_update); 30s heartbeat;Last-Event-IDreplay. Content-Typetext/event-stream.
Intraday user profile (wizard persistence)
GET /api/graph/v1/user/intraday-profile/→IntradayProfileResponsePUT /api/graph/v1/user/intraday-profile/— upsert (UpsertIntradayProfileRequest) →IntradayProfileResponsePATCH /api/graph/v1/user/intraday-profile/— partial update (PatchIntradayProfileRequest) →IntradayProfileResponse
Signal statistics
GET /api/graph/v1/intraday/signal-stats— per-signal-type backtest metrics + live outcome counts (30d). →{signal_types: [{signal_type, backtest, live}]}GET /api/graph/v1/intraday/signal-stats/{signal_type}/detail— equity curve (cumulative R), P&L distribution, exit-reason breakdown, recent signals. → (inferred){signal_type, backtest_metrics, equity_curve, distribution, exit_reasons, recent_signals}
Disclaimer & privilege controls
GET .../intraday/disclaimer/status→DisclaimerStatusResponsePOST .../intraday/disclaimer/acknowledge— BodyDisclaimerAckRequest(immutable, audit-logged).GET .../intraday/disclaimer/content→DisclaimerContentResponse(public).POST .../intraday/kill-switch— cancel orders / close positions / stop sessions (5/min). BodyKillSwitchRequest.POST .../intraday/disable— kill-switch + revoke intraday access. BodyDisableIntradayRequest.GET .../intraday/privilege-events— paginated privilege-change audit log.
Internal (localhost only, Go → Python — no auth)
POST /api/internal/intraday/{symbol}/signal— signal intake. BodyIncomingSignal.POST /api/internal/intraday/{symbol}/levels— level-snapshot persistence. BodyIncomingLevelSnapshot.POST /api/internal/intraday/exit-notification— partial/stop/full exit notifications.POST /api/internal/intraday/close-phase/{session_id}— trigger close phase (15:30 ET).
Volume nodes (HVN/LVN)
GET /api/graph/v1/volume-nodes/{symbol}— detect HVN/LVN. Query:trade_date,session_type(prior|developing, default prior),hvn_threshold(0–3σ, default 1.0),lvn_threshold(-3–0σ, default -1.0),min_buckets(1–10, default 2). →VolumeNodesResponse. (HVN = support/resistance; LVN = breakout zones. <200ms; 503 if prior-session data stale.)GET /api/graph/v1/volume-nodes/{symbol}/context— nodes + full profile context (POC/VAH/VAL, strongest HVN/LVN). Same query params. →VolumeNodeContext
Compression patterns
GET /api/graph/v1/stocks/{symbol}/compression— daily compression history (ATR ratio, BB-width pct, NR7/inside-day, VCP contractions, score).days(1–365, default 30). →CompressionHistoryResponseGET /api/graph/v1/stocks/{symbol}/compression/stats— aggregated stats. →CompressionStatsGET /api/graph/v1/stocks/{symbol}/compression/trend— recent-vs-earlier trend (days5–90, default 20). →CompressionTrendResponseGET /api/graph/v1/stocks/{symbol}/compression/nr7-count— convenience NR7 count. →intPOST /api/graph/v1/compression/screener— compression screen (see Screener above). →CompressionScreenerResponse
Trade outcomes & analytics
GET /api/graph/v1/outcomes/signals/performance— hit rates / avg return / Sharpe proxy grouped bygroup_by(conviction_tier|signal_type|regime|regime_dominant|market_phase|time_bucket). Query:min_date,max_date,variant. →{groups, effective_date_range, variant_dimension, mixed_variants}GET /api/graph/v1/outcomes/signals/slippage— avg decision/market/total slippage (bps) by group.GET /api/graph/v1/outcomes/signals/regime— hit rate / avg return / directional accuracy per regime (min_conviction).GET /api/graph/v1/outcomes/signals/funnel— status distribution + top blocked/gated reasons.GET /api/graph/v1/outcomes/signals/contracts— hit rate/slippage by delta bucket × DTE bucket.GET /api/graph/v1/outcomes/debates/performance— debate-recommendation hit rate by verdict/strategy.GET /api/graph/v1/outcomes/alpha— cross-layer alpha attribution (horizoneod/1d/3d/5d). →{sources:[{source, hit_rate, avg_return, sharpe_proxy, n}], ...}
Key schemas
Levels (intraday institutional levels)
The level set intraday strategies key off (VWAP, IB, OR, pivots, volume profile):VolumeNode
CompressionScreenerResult
GEXSnapshotResponse
VolRegimeSnapshotResponse
RegimeSummaryItem
IntradaySessionResponse
IncomingLevelSnapshot / IncomingSignal (Go → Python plumbing)
Full per-schema field listings for everything referenced here are inopenapi.jsonundercomponents.schemas.