Unusual Whales API - Seasonality endpoints
Layer mapping: L1 partial. Seasonality is a calendar-context feature, not a signal. Knowing “May has historically been -0.4% on SPY” doesn’t change today’s setup - but combined with regime gates it adds prior probability framing.
Four endpoints: market-level, per-ticker monthly, this-month best performers, and year-month historical performance.
1. Base contract
| Property | Value |
|---|---|
| Base URL | https://api.unusualwhales.com |
| Auth | Authorization: Bearer <token> header |
| Response envelope | { "data": [...] } |
| Status codes | 200, 422, 500 |
2. Endpoint matrix
| # | Path | Purpose | Layer |
|---|---|---|---|
| 1 | GET /api/seasonality/market | Market-level seasonality (likely SPY + major indices) | L1 partial |
| 2 | GET /api/seasonality/{ticker}/monthly | Per-ticker monthly seasonality | L1 partial (SPY) |
| 3 | GET /api/seasonality/month-performers | Best historical performers in current month | L2 |
| 4 | GET /api/seasonality/{ticker}/year-month | Year-by-year monthly performance for one ticker | L1 partial (SPY) |
3. GET /api/seasonality/market - Market-level
Market-level monthly seasonality (likely SPY + QQQ + sector ETFs).
No documented parameters.
Response per record:
| Field | Type | Description |
|---|---|---|
ticker | string | Index / ETF symbol |
month | int | 1-12 |
years | int | Sample size (how many years averaged) |
avg_change | decimal (string) | Average monthly % change |
median_change | decimal (string) | Median monthly % change |
max_change | decimal (string) | Best historical month |
min_change | decimal (string) | Worst historical month |
positive_closes | int | Count of positive monthly closes |
positive_months_perc | decimal (string) | Pct of months that closed positive |
MK3 use (L1). Session-start one-shot pull. Cache for the trading day. Derived features:
spy_current_month_avg_change(from this endpoint, current month)spy_current_month_positive_pct(historical hit rate)current_month_seasonality_regime=positive/negative/neutralbased onpositive_months_percandmedian_change
Used as a prior, not a gate. “May has 55% positive close rate” shifts the Setup Hunter’s confidence threshold but does not veto trades.
4. GET /api/seasonality/{ticker}/monthly - Per-ticker
Same record shape, filtered to one ticker.
Path parameter: ticker (e.g. SPY).
Use (L1). For SPY hunter specifically, this is more granular than the market endpoint (which returns multiple tickers). Returns all 12 months for one ticker.
5. GET /api/seasonality/{ticker}/year-month - Year-by-year
Historical year-month grid for one ticker (each row = one specific year + month combination, not aggregated).
Path parameter: ticker.
Response per record (inferred): year, month, change_pct,
open, close, high, low.
Use (L1). Drill into the variance behind the average. The market endpoint says “May average -0.4%” but year-month shows whether that’s “consistently -0.4% every year” vs “wild range from -10% to +8% averaging -0.4%“. The latter is much less informative.
Derived feature: spy_current_month_change_stddev - high variance
means seasonality is weak signal even if the average is suggestive.
6. GET /api/seasonality/month-performers - L2
Best historical performers in the current month across the universe.
Query parameters (inferred): month, min_marketcap,
limit.
Response per record: ticker, avg_change for the month, hit rate, sample size.
Use (L2). Pick stocks that historically outperform in the current month for swing-trade strategy. Not in MK3 scope.
7. MK3 use summary
| Endpoint | Cadence | Cache TTL |
|---|---|---|
/seasonality/market | Session start, once | 1 day |
/seasonality/SPY/monthly | Session start, once | 1 day |
/seasonality/SPY/year-month | Session start, once | 1 day |
/seasonality/month-performers | Not wired | L2 only |
Three endpoint calls at session start, three derived features:
spy_seasonality_score(combining hit rate + average)spy_seasonality_strength(1 - stddev / |mean|)spy_month_regime(positive/negative/neutral discrete bucket)
Total cost: 3 HTTP calls, ~1 KB response data, used as a confidence- modulating prior across the trading day.
8. Nautilus integration shape
Single one-shot Actor at session start: UWSeasonalityActor. Calls
all three SPY-relevant endpoints, computes derived features,
publishes once to the bus as a UWSeasonalityContext snapshot.
Strategies subscribe and read at decision time, never re-poll.
9. Known gaps
/seasonality/marketscope unclear. Returns multiple tickers but the docs don’t enumerate which. First fetch should catalog (SPY, QQQ, IWM, sector ETFs? individual stocks?)./year-monthresponse shape inferred. First fetch should confirm./month-performersfilter parameters inferred. L2-only; defer.- No intraday or weekly seasonality. Monthly is the finest granularity. Day-of-week, time-of-day, and turn-of-month effects live elsewhere (probably need a separate research session cross-referencing the 1Y UW bundle).
10. Source URLs
https://api.unusualwhales.com/docs/operations/PublicApi.SeasonalityController.market_seasonalityhttps://api.unusualwhales.com/docs/operations/PublicApi.SeasonalityController.monthlyhttps://api.unusualwhales.com/docs/operations/PublicApi.SeasonalityController.year_monthhttps://api.unusualwhales.com/docs/operations/PublicApi.SeasonalityController.month_performers
cortana-north-star uw-api-tide uw-api-market 2026-05-15-mk3-setup-hunter-architecture