# Signal Dashboard Investing-signal platform for NASDAQ stocks. Surfaces the best trading opportunities through weighted multi-dimensional scoring — technical indicators, support/resistance quality, sentiment, fundamentals, and momentum — with asymmetric risk:reward scanning. **Philosophy:** Don't predict price. Find the path of least resistance, key S/R zones, and asymmetric R:R setups. ## Stack | Layer | Tech | |---|---| | Backend | Python 3.12+, FastAPI, Uvicorn, async SQLAlchemy, Alembic | | Database | PostgreSQL (asyncpg) | | Scheduler | APScheduler — OHLCV, sentiment, fundamentals, R:R scan | | Frontend | React 18, TypeScript, Vite 5 | | Styling | Tailwind CSS 3 with custom glassmorphism design system | | State | TanStack React Query v5 (server), Zustand (client/auth) | | Charts | Canvas 2D candlestick chart with S/R overlays | | Routing | React Router v6 (SPA) | | HTTP | Axios with JWT interceptor | | Data providers | Alpaca (OHLCV), Gemini 2.0 Flash (sentiment via search grounding), Financial Modeling Prep (fundamentals) | ## Features ### Backend - Ticker registry with full cascade delete - OHLCV price storage with upsert and validation - Technical indicators: ADX, EMA, RSI, ATR, Volume Profile, Pivot Points, EMA Cross - Support/Resistance detection with strength scoring and merge-within-tolerance - Sentiment analysis with time-decay weighted scoring - Fundamental data tracking (P/E, revenue growth, earnings surprise, market cap) - 5-dimension scoring engine (technical, S/R quality, sentiment, fundamental, momentum) with configurable weights - Risk:Reward scanner — long and short setups, ATR-based stops, configurable R:R threshold (default 3:1) - Auto-populated watchlist (top-10 by composite score) + manual entries (cap: 20) - JWT auth with admin role, configurable registration, user access control - Scheduled jobs with enable/disable control and status monitoring - Admin panel: user management, data cleanup, job control, system settings ### Frontend - Glassmorphism UI with frosted glass panels, gradient text, ambient glow effects, mesh gradient background - Interactive candlestick chart (Canvas 2D) with hover tooltips showing OHLCV values - Support/Resistance level overlays on chart (top 6 by strength, dashed lines with labels) - Data freshness bar showing availability and recency of each data source - Watchlist with composite scores, R:R ratios, and S/R summaries - Ticker detail page: chart, scores, sentiment breakdown, fundamentals, technical indicators, S/R table - Rankings table with configurable dimension weights - Trade scanner showing detected R:R setups - Admin page: user management, job status with live indicators, enable/disable toggles, data cleanup, system settings - Protected routes with JWT auth, admin-only sections - Responsive layout with mobile navigation - Toast notifications for async operations ## Pages | Route | Page | Access | |---|---|---| | `/login` | Login | Public | | `/register` | Register | Public (when enabled) | | `/watchlist` | Watchlist (default) | Authenticated | | `/ticker/:symbol` | Ticker Detail | Authenticated | | `/scanner` | Trade Scanner | Authenticated | | `/rankings` | Rankings | Authenticated | | `/admin` | Admin Panel | Admin only | ## API Endpoints All under `/api/v1/`. Interactive docs at `/docs` (Swagger) and `/redoc`. | Group | Endpoints | |---|---| | Health | `GET /health` | | Auth | `POST /auth/register`, `POST /auth/login` | | Tickers | `POST /tickers`, `GET /tickers`, `DELETE /tickers/{symbol}` | | OHLCV | `POST /ohlcv`, `GET /ohlcv/{symbol}` | | Ingestion | `POST /ingestion/fetch/{symbol}` | | Indicators | `GET /indicators/{symbol}/{type}`, `GET /indicators/{symbol}/ema-cross` | | S/R Levels | `GET /sr-levels/{symbol}` | | Sentiment | `GET /sentiment/{symbol}` | | Fundamentals | `GET /fundamentals/{symbol}` | | Scores | `GET /scores/{symbol}`, `GET /rankings`, `PUT /scores/weights` | | Trades | `GET /trades` | | Watchlist | `GET /watchlist`, `POST /watchlist/{symbol}`, `DELETE /watchlist/{symbol}` | | Admin | `GET /admin/users`, `PUT /admin/users/{id}/role`, `PUT /admin/users/{id}/access`, `DELETE /admin/data/{symbol}`, `POST /admin/jobs/{name}/trigger`, `PUT /admin/jobs/{name}/toggle`, `GET /admin/jobs`, `GET /admin/settings`, `PUT /admin/settings` | ## Development Setup ### Prerequisites - Python 3.12+ - PostgreSQL (via Homebrew on macOS: `brew install postgresql@17`) - Node.js 18+ and npm ### Backend Setup ```bash # Create and activate virtual environment python -m venv .venv source .venv/bin/activate pip install -e ".[dev]" # Configure environment cp .env.example .env # Edit .env with your values (see Environment Variables below) # Start PostgreSQL and create database brew services start postgresql@17 createdb stock_data_backend createuser stock_backend # Run migrations alembic upgrade head # Start the backend uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ``` A default `admin`/`admin` account is created on first startup. Open http://localhost:8000/docs for Swagger UI. ### Frontend Setup ```bash cd frontend npm install npm run dev ``` Open http://localhost:5173 for the Signal Dashboard. The Vite dev server proxies `/api/v1/` requests to the backend at `http://127.0.0.1:8000`. ### Frontend Build ```bash cd frontend npm run build # TypeScript check + production build → frontend/dist/ npm run preview # Preview the production build locally ``` ### Tests ```bash # Backend tests (in-memory SQLite — no PostgreSQL needed) pytest tests/ -v # Frontend tests cd frontend npm test ``` ## Environment Variables Configure in `.env` (copy from `.env.example`): | Variable | Required | Default | Description | |---|---|---|---| | `DATABASE_URL` | Yes | — | PostgreSQL connection string (`postgresql+asyncpg://...`) | | `JWT_SECRET` | Yes | — | Random secret for JWT signing | | `JWT_EXPIRY_MINUTES` | No | `60` | JWT token expiry | | `ALPACA_API_KEY` | For OHLCV | — | Alpaca Markets API key | | `ALPACA_API_SECRET` | For OHLCV | — | Alpaca Markets API secret | | `GEMINI_API_KEY` | For sentiment | — | Google Gemini API key | | `GEMINI_MODEL` | No | `gemini-2.0-flash` | Gemini model name | | `FMP_API_KEY` | For fundamentals | — | Financial Modeling Prep API key | | `DATA_COLLECTOR_FREQUENCY` | No | `daily` | OHLCV collection schedule | | `SENTIMENT_POLL_INTERVAL_MINUTES` | No | `30` | Sentiment polling interval | | `FUNDAMENTAL_FETCH_FREQUENCY` | No | `daily` | Fundamentals fetch schedule | | `RR_SCAN_FREQUENCY` | No | `daily` | R:R scanner schedule | | `DEFAULT_WATCHLIST_AUTO_SIZE` | No | `10` | Auto-watchlist size | | `DEFAULT_RR_THRESHOLD` | No | `3.0` | Minimum R:R ratio for setups | | `DB_POOL_SIZE` | No | `5` | Database connection pool size | | `LOG_LEVEL` | No | `INFO` | Logging level | ## Production Deployment (Debian 12) ### 1. Install dependencies ```bash sudo apt update && sudo apt install -y python3.12 python3.12-venv postgresql nginx nodejs npm ``` ### 2. Create service user ```bash sudo useradd -r -s /usr/sbin/nologin stockdata ``` ### 3. Deploy application ```bash sudo mkdir -p /opt/stock-data-backend # Copy project files to /opt/stock-data-backend cd /opt/stock-data-backend python3.12 -m venv .venv source .venv/bin/activate pip install . ``` ### 4. Configure ```bash sudo cp .env.example /opt/stock-data-backend/.env sudo chown stockdata:stockdata /opt/stock-data-backend/.env # Edit .env with production values (strong JWT_SECRET, real API keys, etc.) ``` ### 5. Database ```bash DB_NAME=stock_data_backend DB_USER=stock_backend DB_PASS=strong_password ./deploy/setup_db.sh ``` ### 6. Build frontend ```bash cd frontend npm ci npm run build ``` ### 7. Systemd service ```bash sudo cp deploy/stock-data-backend.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now stock-data-backend ``` ### 8. Nginx reverse proxy ```bash sudo cp deploy/nginx.conf /etc/nginx/sites-available/stock-data-backend sudo ln -s /etc/nginx/sites-available/stock-data-backend /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx ``` Nginx serves the frontend static files from `frontend/dist/` and proxies `/api/v1/` to the backend. ### 9. SSL (recommended) ```bash sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d signal.thiessen.io ``` ### Verify ```bash curl https://signal.thiessen.io/api/v1/health ``` ## Project Structure ``` app/ ├── main.py # FastAPI app, lifespan, router wiring ├── config.py # Pydantic settings from .env ├── database.py # Async SQLAlchemy engine + session ├── dependencies.py # DI: DB session, auth guards ├── exceptions.py # Exception hierarchy ├── middleware.py # Global error handler → JSON envelope ├── cache.py # LRU cache with per-ticker invalidation ├── scheduler.py # APScheduler job definitions ├── models/ # SQLAlchemy ORM models ├── schemas/ # Pydantic request/response schemas ├── services/ # Business logic layer ├── providers/ # External data provider integrations └── routers/ # FastAPI route handlers frontend/ ├── index.html # SPA entry point ├── vite.config.ts # Vite config with API proxy ├── tailwind.config.ts # Tailwind + glassmorphism theme ├── package.json └── src/ ├── App.tsx # Route definitions ├── main.tsx # React entry point ├── api/ # Axios API client modules (one per resource) ├── components/ │ ├── admin/ # User table, job controls, settings, data cleanup │ ├── auth/ # Protected route wrapper │ ├── charts/ # Canvas candlestick chart │ ├── layout/ # App shell, sidebar, mobile nav │ ├── rankings/ # Rankings table, weights form │ ├── scanner/ # Trade table │ ├── ticker/ # Sentiment panel, fundamentals, indicators, S/R overlay │ ├── ui/ # Badge, toast, skeleton, score card, confirm dialog │ └── watchlist/ # Watchlist table, add ticker form ├── hooks/ # React Query hooks (one per resource) ├── lib/ # Types, formatting utilities ├── pages/ # Page components (7 pages) ├── stores/ # Zustand auth store └── styles/ # Global CSS with glassmorphism classes deploy/ ├── nginx.conf # Reverse proxy + static file serving ├── setup_db.sh # Idempotent DB setup script └── stock-data-backend.service # systemd unit tests/ ├── conftest.py # Fixtures, strategies, test DB ├── unit/ # Unit tests └── property/ # Property-based tests (Hypothesis) ```