# QuantTrade Local-first quantitative backtesting on Coolify: Streamlit UI, VectorBT engine, Parquet market data, nightly Yahoo Finance sync, Authentik OIDC via reverse proxy, and SQLite strategy persistence. ## Architecture | Layer | Technology | |-------|------------| | Auth | Authentik (`auth.aexoradao.com`) via reverse proxy headers | | UI | Streamlit (`streamlit` service, port 8501) | | Engine | VectorBT + NumPy | | Market data | Parquet volume (`parquet-data`) | | Ingestion | `harvester` cron @ 17:00 America/New_York (weekdays) | | Strategies | SQLite on `strategy-data` volume, keyed by proxy username | | Telemetry | Bugsink via `sentry-sdk` (`bugsink.aexoradao.com`) | ## Coolify deployment 1. Create a **Docker Compose** resource pointing at this repo. 2. Assign your public domain to the **`streamlit`** service on port **8501**. 3. Set environment variables in Coolify (first deploy extracts defaults from compose): - `BUGSINK_DSN` — DSN from your Bugsink project - `CORE_TICKERS` — optional comma-separated tickers - `DEV_USER` — only for unauthenticated local testing 4. Protect the domain in your reverse proxy with Authentik forward auth. ### Authentik / proxy headers After login, the proxy must forward one of these headers to Streamlit: - `X-Forwarded-User` (recommended) - `X-Authentik-Username` - `Remote-User` The app reads them via Streamlit websocket headers (`auth.get_current_user()`). Saved strategies are scoped to that username. Example Traefik middleware (adjust provider labels to your stack): ```yaml # Forward auth endpoint on Authentik http: middlewares: authentik: forwardAuth: address: https://auth.aexoradao.com/outpost.goauthentik.io/auth/traefik trustForwardHeader: true authResponseHeaders: - X-authentik-username - X-authentik-uid - X-Forwarded-User ``` Map `X-authentik-username` → `X-Forwarded-User` in your proxy if Streamlit only sees the latter. ## Services - **`data-seed`** — one-shot 5-year historical download into Parquet (idempotent). - **`harvester`** — cron container; appends daily bars after US cash close. - **`streamlit`** — dashboard, backtests, save/load strategies. ## Local development ```bash cp .env.example .env python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt python sync.py --seed DEV_USER=you@example.com streamlit run app.py ``` ## Manual sync ```bash python sync.py --seed # full history python sync.py --daily # append latest bars ``` ## Strategy storage SQLite path: `/data/strategies/strategies.db` (Docker volume `strategy-data`). Each row stores username, name, ticker, and JSON parameters (MA windows, cash, fees). ## Bugsink Set `BUGSINK_DSN` to your project DSN, e.g.: ```text http://@bugsink.aexoradao.com/ ``` Both `app.py` and `sync.py` initialize the Sentry-compatible SDK with tracing disabled for Bugsink compatibility.