Aller au contenu principal

Vue d'ensemble de l'architecture

Une instance Fonrex se compose d'un processus FastAPI, d'une base PostgreSQL/TimescaleDB et d'un serveur Redis. Tout ce qui collecte des données (les fournisseurs de fondamentaux, les fournisseurs d'actualités, le worker temps réel, le canari quotidien) s'exécute dans le processus de l'API.

Flux principaux​

  • Cours de clôture : GET /eod lit prices_eod ; lorsque rien n'est enregistré, la cotation est ingérée depuis Yahoo Finance (avec le symbole vérifié pour la cotation), ou depuis TradingView en repli.
  • Fondamentaux : GET /fundamental appelle les fournisseurs en parallèle, valide leurs valeurs (contrôles de plage et de consensus) et produit un document en choisissant chaque chiffre chez Yahoo, puis dans les chiffres enregistrés, puis chez les fournisseurs scrapés.
  • Temps réel : le worker diffuse les ticks TradingView dans Redis (quote:{ticker}, price:{ticker}) et dans prices_intraday ; chaque client WebSocket écoute le canal Redis de son ticker.
  • Indicateurs et valorisation sont calculés à partir de ce que contient la base.

Démarrage​

entrypoint.sh attend PostgreSQL et Redis, applique alembic upgrade head, importe éventuellement data/etf.csv (SEED_ON_FIRST_RUN), puis démarre Gunicorn avec WEB_CONCURRENCY workers (1 par défaut).

main.py crée ensuite les services et les publie dans app.state : clients de base de données et Redis, ingestion, indicateurs, worker temps réel (qui restaure les abonnements enregistrés), actualités, FRED, DCF, couche de validation, moniteur canari et son planificateur quotidien, enregistreur d'utilisation. Le démarrage est tolérant : un service qui ne démarre pas laisse ses routes répondre 503 pendant que le reste de l'API fonctionne. Un fournisseur qui ne peut pas être importé est listé par GET /health.

main.py ne modifie jamais le schéma : il compare la révision de la base avec la tête Alembic et marque la base indisponible lorsqu'elles diffèrent.

Gardez un seul worker. Les flux temps réel, les clients WebSocket et le canari quotidien vivent dans la mémoire du processus : chaque worker Gunicorn supplémentaire ouvrirait ses propres flux et exécuterait son propre canari.

Sécurité​

Toutes les routes sauf /health, /docs, /redoc, /openapi.json, /widgets.json, /apps.json, /favicon.ico et /static/* exigent une clé d'API. Les clés en lecture seule peuvent appeler les routes GET et les deux routes de calcul POST /technical/batch et POST /dcf/{ticker} ; elles ne peuvent ni vider le cache, ni nettoyer la base, ni ingérer, ni démarrer de flux. Sans aucune clé configurée, toute requête protégée est refusée.

Organisation du code​

PaquetRôle
routers/Adaptateurs HTTP, un module par fonctionnalité
use_cases/Logique applicative des fondamentaux, des fournisseurs spécialisés et du temps réel, derrière des ports
historical/, technical/, news/, valuation/, monitoring/, macro/Services fonctionnels
database/, cache/Dépôts SQLAlchemy, Redis
financials/providers/, news/providers/Fournisseurs, tous construits sur BaseFinancialProvider
realtime/Worker temps réel et gestionnaire de connexions WebSocket
integrations/openbb/Widgets, tableaux de bord et adaptateurs OpenBB
zipline_bundle/Bundle de données Zipline (non importé par l'API)

Le fichier ARCHITECTURE.md du dépôt est la référence détaillée : carte des modules, chaque route, chaque migration, limites connues.