# Sector Rotation Dashboard — UI Page Concepts & Wireframes

**Project:** TradeDingo — Sector Rotation Feature  
**Design language:** Dark industrial / trading terminal (matches existing TradeDingo dark theme)  
**Typography:** System monospace for numbers; sans-serif for labels  
**Colour palette:**  
  - Background: `#0E1117` (trading terminal black)  
  - Surface: `#161B22` (card background)  
  - Border: `#30363D`  
  - Text primary: `#E6EDF3`  
  - Text secondary: `#8B949E`  
  - Green (up): `#3FB950`  
  - Red (down): `#F85149`  
  - Amber (alert): `#D29922`  
  - Accent blue: `#58A6FF`  

---

## Page 1 — Sector Dashboard

**Route:** `/sectors`  
**Access:** Authenticated only (Andrew's TradeDingo login)

---

### Header (global nav — inherited from TradeDingo base)

| Element | Detail |
|---|---|
| Logo | TradeDingo wordmark, top-left |
| Nav links | Home · **Sectors** (active, underlined accent) · Pre-Market · Alerts · Settings |
| Status pill | `● MARKET OPEN` in green / `● PRE-MARKET` in amber / `● CLOSED` in muted — updates without reload |
| Last updated | `Data refreshed 08:47 BST` — monospace, muted, top-right |

---

### Page Title Row

```
SECTOR ROTATION DASHBOARD                    [Sort: 1D ▼] [Sort: 5D] [Sort: RS Score]
Catching rotations early — 16 sectors · 60 tickers active                [⟳ Refresh]
```

- Headline: uppercase, bold, 22px
- Sub-line: muted text, 13px — ticker count updates live
- Sort controls: pill-style toggle buttons. Active sort pill is filled accent blue. Default: 1D Performance
- Refresh button: icon + text, right-aligned, triggers manual data fetch

---

### Sector Cards Grid

Layout: **responsive grid — 4 columns desktop, 2 columns tablet, 1 column mobile**  
Each sector occupies one card; cards are sorted by the active sort criterion.

#### Sector Card (collapsed state)

```
┌─────────────────────────────────────────────────────┐
│ 🚀 SPACE                          🔥 HOT ROTATION   │
│ $ASTS · $RKLB · $RDW · $LUNR                        │
│                                                     │
│   1D    +4.8%    5D   +11.2%    1M    +22.4%        │
│  ████████████████░░░░░                              │
│  RS Rank:  #2 ↑ from #9 yesterday                  │
│                                                     │
│                              [Expand ▼] [★ Watch]   │
└─────────────────────────────────────────────────────┘
```

**Components:**
- **Sector icon + name:** emoji left, sector name uppercase bold. Name is the primary label.
- **Ticker preview line:** abbreviated list of tickers, monospace, muted — truncated to 4 then "…+1 more"
- **Hot Rotation badge:** amber pill, top-right corner — only shown when RS rank improved ≥5 positions. Text: `🔥 HOT ROTATION`
- **Performance row:** three metrics side by side — `1D`, `5D`, `1M`. Value is green if positive, red if negative. Font: monospace 16px bold for the number.
- **Mini bar:** a subtle horizontal bar showing relative strength vs the other sectors — green portion = RS score above SPY, grey = neutral, red = below. Width is proportional to RS score.
- **RS Rank:** `RS Rank: #2 ↑ from #9 yesterday` — the rank change is the rotation signal. Arrow ↑ = improving (green), ↓ = worsening (red), — = unchanged (muted).
- **Expand button:** toggles the ticker detail table open inline (no page reload)
- **Star/Watch button:** marks the sector as "focus" for the session — adds to a pinned "Today's Focus" strip at the top of the page

**Card border:** 1px `#30363D`. If Hot Rotation badge is active, the left border becomes 3px amber `#D29922`.

**Empty state (no data fetched yet):**
```
🚀 SPACE
─── Awaiting data refresh ─────────────────
                                   [⟳ Load]
```

---

#### Sector Card (expanded state)

```
┌─────────────────────────────────────────────────────────────────────────┐
│ 🚀 SPACE                                          🔥 HOT ROTATION        │
│ $ASTS · $RKLB · $RDW · $LUNR                                            │
│   1D  +4.8%    5D  +11.2%    1M  +22.4%    RS Rank: #2 ↑ from #9       │
│─────────────────────────────────────────────────────────────────────────│
│  TICKER   LAST    1D%     PM GAP%    RVOL    GAP TYPE          ACTIVE   │
│  ──────── ──────  ──────  ─────────  ──────  ───────────────   ──────   │
│  ASTS     $27.40  +5.2%   +5.2%      3.4×    Gap-and-Go ↑      ● ON    │
│  RKLB     $18.90  +3.1%   +2.9%      1.8×    Opening Drive      ● ON    │
│  RDW      $7.25   +4.4%   +4.1%      2.1×    Gap-and-Go ↑      ● ON    │
│  LUNR     $6.88   +2.2%   +1.9%      1.2×    Moderate Gap       ● ON    │
│  ──────── ──────  ──────  ─────────  ──────  ───────────────   ──────   │
│                                               [+ Add Ticker]            │
│                                               [📊 History]  [Collapse ▲]│
└─────────────────────────────────────────────────────────────────────────┘
```

**Ticker table columns:**
| Column | Source | Format |
|---|---|---|
| TICKER | SectorTicker.ticker | Uppercase monospace, clickable (links to TradeDingo ticker page if one exists) |
| LAST | Polygon last trade | `$00.00` format, no colour (it's a price not a change) |
| 1D% | Today's change from prior close | Green if positive, red if negative, monospace |
| PM GAP% | `gap_pct` from §1.1 premarket rules | Green/red with `+`/`-` prefix |
| RVOL | Relative volume vs 20-day average | Amber if >2×, green if 1.5–2×, muted if <1.5× |
| GAP TYPE | §1.1 classification logic | Pill labels: `Gap-and-Go ↑`, `Opening Drive`, `Moderate Gap`, `Flat Open`, `Fade Candidate ↓` |
| ACTIVE | SectorTicker.active | Toggle switch: blue = ON (included in briefing), grey = OFF |

**Actions at table bottom:**
- `+ Add Ticker` → opens Add Ticker Modal (see Page 3)
- `📊 History` → opens 30-day RS history popover (see Page 4)
- `Collapse ▲` → collapses card back to summary view

---

### Today's Focus Strip (pinned, appears when at least 1 sector starred)

```
┌─────────────────────────────────────────────────────────┐
│ ★ TODAY'S FOCUS   🚀 Space  ·  🔬 Semis                  [Clear]  │
└─────────────────────────────────────────────────────────┘
```

- Horizontally scrollable strip below the header
- Shows starred sectors as clickable chips — clicking one jumps to that sector card and expands it
- "Clear" removes all stars

---

### Footer / Data Credit

```
Market data: Polygon.io · Pre-market data delayed 15 min · Not financial advice
```

Muted text, 11px, bottom of page.

---

### Mobile Layout (< 768px)

- Single-column grid
- Sector cards stack vertically
- Sort controls become a dropdown select (`Sort by: [1D ▼]`)
- Ticker table scrolls horizontally within the card (sticky TICKER column)
- Today's Focus strip remains horizontal scroll at top

---

### Loading State

```
┌─────────────────────────────────────────────────────┐
│ ⊙ SPACE                                             │
│ Fetching market data…                               │
│ ────────────────────────────────────────            │
│ ────────────────────────────────────                │
└─────────────────────────────────────────────────────┘
```

Skeleton lines (grey shimmer animation) for performance rows while data loads.  
All 15 cards render empty simultaneously; they fill in as API responses arrive (parallel fetch).

---

### Error State (per card)

```
┌─────────────────────────────────────────────────────┐
│ 🚀 SPACE                                            │
│ ⚠ Data unavailable — API limit reached              │
│ Last known: +4.8% 1D (08:47 BST)      [Retry]      │
└─────────────────────────────────────────────────────┘
```

Shows stale cached value with timestamp so Andrew can still make decisions.

---

## Page 2 — Sector Rotation History Popover

**Trigger:** Clicking `📊 History` on any expanded sector card  
**Layout:** Popover / slide-in panel (does not navigate away from dashboard)

---

### Panel Header

```
SPACE — 30-Day RS Rank History                         [✕ Close]
```

---

### RS Rank Chart

```
RS Rank (1 = best)
 1 │                    ●────●────●
 3 │              ●────●
 5 │
 7 │
 9 │ ●────●────●
11 │
   └──────────────────────────────────────────────
     Jun 1   Jun 8   Jun 15  Jun 17(today)
```

- Chart.js line chart — Y axis inverted (1 at top = best rank)
- X axis: 30 calendar days
- Line colour: green when rank ≤5, amber when 6–10, red when >10
- Hover tooltip: `Jun 15: Rank #3 — Avg 1D: +2.1%`
- Vertical dotted line at today

---

### Constituent Performance Table (below chart)

```
TICKER  30D RETURN   30D RVOL AVG   BEST DAY    WORST DAY
ASTS    +38.4%       2.8×           +12.1%      -6.3%
RKLB    +22.1%       1.9×           +8.4%       -4.1%
RDW     +18.7%       1.6×           +7.2%       -5.8%
LUNR    +11.2%       1.3×           +5.1%       -3.9%
```

---

## Page 3 — Add Ticker Modal

**Trigger:** Clicking `+ Add Ticker` in an expanded sector card  
**Layout:** Centred modal overlay, max-width 400px

---

### Modal

```
┌────────────────────────────────────────────┐
│  ADD TICKER TO SPACE                        │
│                                             │
│  Search ticker                              │
│  ┌──────────────────────────────────────┐  │
│  │  🔍  e.g. ASTS, RKLB…              │  │
│  └──────────────────────────────────────┘  │
│                                             │
│  Results:                                   │
│  ┌──────────────────────────────────────┐  │
│  │  LUNR   Lunar Holdings Ltd          │  │
│  │  LUN    Lundin Gold                 │  │
│  └──────────────────────────────────────┘  │
│                                             │
│  ☑  Add as active (include in briefing)     │
│                                             │
│  [Cancel]                    [Add Ticker]   │
└────────────────────────────────────────────┘
```

**Behaviour:**
- Typeahead search using Polygon.io ticker search endpoint
- Results show: TICKER symbol (bold monospace) + company name (muted)
- Max 8 results shown
- "Add as active" checkbox — checked by default (newly added tickers go straight into briefing)
- "Add Ticker" button is disabled until a result is selected
- On success: modal closes, ticker row appears in the expanded card table with a brief green flash
- Duplicate check: if ticker already exists in this sector, shows `Already in Space watchlist` error inline

**Empty search state:** `Start typing to search US equities…` muted placeholder  
**No results state:** `No results for "XXXX" — check the symbol is a valid US equity`  
**API error state:** `Search unavailable — type the exact ticker and press Enter to add directly`

---

## Page 4 — Rotation Alerts Settings

**Route:** `/sectors/alerts`  
**Access link:** Via Settings nav item → "Sector Alerts" sub-page  
**Purpose:** Let Andrew tune the rotation detection thresholds and delivery method

---

### Header

```
SECTOR ROTATION ALERTS
Configure when and how you're notified about sector momentum shifts
```

---

### Alert Rules Panel

```
┌──────────────────────────────────────────────────────────────┐
│  ROTATION DETECTION                                           │
│                                                              │
│  Trigger alert when RS rank improves by at least:            │
│  ○ 3 positions   ● 5 positions   ○ 7 positions               │
│                                                              │
│  AND sector enters top:                                      │
│  ○ Top 3   ● Top 5   ○ Top 7                                 │
│                                                              │
│  Alert window (US ET):                                       │
│  From [09:35 ▼]  To [15:45 ▼]                               │
│  ☐ Also alert in pre-market (before 09:30 ET)               │
└──────────────────────────────────────────────────────────────┘
```

---

### Delivery Panel

```
┌──────────────────────────────────────────────────────────────┐
│  DELIVERY                                                     │
│                                                              │
│  ☑  Telegram (configured)   Bot: @TradeDingoBot             │
│  ☐  Dashboard badge only (no Telegram)                       │
│                                                              │
│  Minimum time between alerts (cooldown):                     │
│  ○ 15 min   ● 30 min   ○ 60 min   ○ No limit                │
└──────────────────────────────────────────────────────────────┘
```

---

### Test Button

```
[Send Test Alert]
```

Sends a fake rotation alert to the configured Telegram channel so Andrew can confirm delivery.

---

### Save

```
[Save Settings]
```

Persists settings to SQLite. Confirmation: `✓ Settings saved — alerts active during market hours`

---

## Page 5 — Pre-Market Briefing Preview

**Route:** `/sectors/briefing-preview`  
**Access link:** Via the Sector Dashboard — small link `📋 See today's briefing` in the page sub-title row  
**Purpose:** Show Andrew exactly what the 08:30 Telegram briefing will say before it fires (so he can sanity-check the active ticker list)

---

### Header

```
TODAY'S PRE-MARKET BRIEFING PREVIEW
What the 08:30 BST Telegram message will cover — 47 active tickers across 14 sectors
                                                            [Send Now ▶]  [Edit Tickers]
```

- `Send Now` button: manually fires the briefing at any time (useful for testing). Requires confirm dialog.
- `Edit Tickers` links back to the main dashboard for watchlist changes.

---

### Briefing Preview List

One accordion section per sector, collapsed by default:

```
▶ SPACE (4 tickers)
▶ SEMIS (4 tickers)
▶ NETWORKING (3 tickers)
...
```

Expanded section:

```
▼ SPACE (4 tickers)

  ASTS   Last $27.40   Gap +5.2%   RVOL 3.4×   [Gap-and-Go ↑]
          PDH $26.80 · PDL $24.10 · VWAP $25.90
          → Trending above overnight VWAP — positive pre-market tell

  RKLB   Last $18.90   Gap +2.9%   RVOL 1.8×   [Opening Drive]
          PDH $19.20 · PDL $17.40 · VWAP $18.10
          → Moderate gap, watch for opening drive setup

  ...
```

This mirrors the Telegram message structure exactly — what Andrew sees here is what the bot will send.

---

### Inactive Sector Notice

If a sector has zero active tickers, show inline:

```
  ⊘ NUCLEAR — No active tickers. OKLO is toggled off. [Enable OKLO]
```

---

## Cross-Page Components

### Navigation Active State

In the global nav, `Sectors` is highlighted when the user is on any `/sectors/*` route.

### Unsaved Changes Banner (Sector Dashboard)

If Andrew toggles tickers active/inactive and navigates away without the changes being auto-saved (they should be auto-saved on toggle, but as a fallback):

```
⚠  You have unsaved watchlist changes.   [Save]   [Discard]
```

### Rotation Alert Notification Banner (top of page, intraday)

If a rotation alert fires while Andrew has the dashboard open:

```
🔥  ROTATION ALERT: Defense is climbing — RS rank 12→3 in last 30 min.   [View Defense ▶]
```

Amber background strip, auto-dismisses after 30 seconds or on click.
