Dennis Thiessen 03ea60e067
All checks were successful
Deploy / lint (push) Successful in 5s
Deploy / test (push) Successful in 29s
Deploy / deploy (push) Successful in 21s
deactivated corp proxy
2026-03-03 20:45:28 +01:00
2026-03-03 20:25:18 +01:00
2026-03-03 15:20:18 +01:00
2026-03-03 15:20:18 +01:00
2026-03-03 20:45:28 +01:00
2026-03-03 20:45:28 +01:00
2026-03-03 15:20:18 +01:00
2026-03-03 15:20:18 +01:00
2026-03-03 15:20:18 +01:00
2026-02-27 16:08:09 +01:00
2026-02-20 17:31:01 +01:00
2026-03-03 20:35:11 +01:00
2026-03-03 15:20:18 +01:00

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), OpenAI (sentiment, optional micro-batch), Fundamentals chain: FMP → Finnhub → Alpha Vantage

Features

Backend

  • Ticker registry with full cascade delete
  • Universe bootstrap for sp500, nasdaq100, nasdaq_all via admin endpoint
  • 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 1.5: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, POST /admin/users, PUT /admin/users/{id}/access, PUT /admin/users/{id}/password, PUT /admin/settings/registration, GET /admin/settings, PUT /admin/settings/{key}, GET/PUT /admin/settings/recommendations, GET/PUT /admin/settings/ticker-universe, POST /admin/tickers/bootstrap, POST /admin/data/cleanup, GET /admin/jobs, POST /admin/jobs/{name}/trigger, PUT /admin/jobs/{name}/toggle, GET /admin/pipeline/readiness

Development Setup

Prerequisites

  • Python 3.12+
  • PostgreSQL (via Homebrew on macOS: brew install postgresql@17)
  • Node.js 18+ and npm

Backend Setup

# 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

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

cd frontend
npm run build     # TypeScript check + production build → frontend/dist/
npm run preview   # Preview the production build locally

Tests

# 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
OPENAI_API_KEY For sentiment (OpenAI path) OpenAI API key
OPENAI_MODEL No gpt-4o-mini OpenAI model name
OPENAI_SENTIMENT_BATCH_SIZE No 5 Micro-batch size for sentiment collector
FMP_API_KEY Optional (fundamentals) Financial Modeling Prep API key (first provider in chain)
FINNHUB_API_KEY Optional (fundamentals) Finnhub API key (fallback provider)
ALPHA_VANTAGE_API_KEY Optional (fundamentals) Alpha Vantage API key (fallback provider)
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
FUNDAMENTAL_RATE_LIMIT_RETRIES No 3 Retries per ticker on fundamentals rate-limit
FUNDAMENTAL_RATE_LIMIT_BACKOFF_SECONDS No 15 Base backoff seconds for fundamentals retry (exponential)
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

sudo apt update && sudo apt install -y python3.12 python3.12-venv postgresql nginx nodejs npm

2. Create service user

sudo useradd -r -s /usr/sbin/nologin stockdata

3. Deploy application

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

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

DB_NAME=stock_data_backend DB_USER=stock_backend DB_PASS=strong_password ./deploy/setup_db.sh

6. Build frontend

cd frontend
npm ci
npm run build

7. Systemd service

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

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.

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d signal.thiessen.io

Verify

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)
Description
No description provided
Readme 539 KiB
Languages
Python 69.7%
TypeScript 29.4%
CSS 0.5%
Shell 0.2%