Skip to content

Providers externes

Référence opérationnelle des services externes utilisés par PortfolioAI : où s'inscrire, où trouver sa clé, quotas, et comment ils sont câblés dans le code. Mis à jour à chaque ajout / changement de provider.

TL;DR pour onboarder rapidement : tu as besoin d'une clé Twelve Data, d'une clé Finnhub, d'une clé Anthropic Claude (optionnel — Ollama local couvre offline). Toutes sont en free tier suffisant pour un usage perso. Liste complète et liens d'inscription ci-dessous.


Twelve Data — données de marché

Site https://twelvedata.com
Inscription https://twelvedata.com/register (email + mot de passe, pas de carte requise pour le free tier)
Dashboard / clé https://twelvedata.com/account/api-keys
Free tier 800 credits/jour · 8 calls/min · couverture US, TSX (XTSE), grandes places EU et Asie
Endpoints utilisés /time_series (OHLC), /quote (nom + 52w + close), /symbol_search (autocomplete watchlist v2). Note : /profile (sector GICS) n'est plus utilisé — paid-tier only, remplacé par Finnhub /stock/profile2 côté FinnhubSectorClassifier
Config market.twelvedata.api-key (env TWELVEDATA_API_KEY)
Adapter TwelveDataClient + TwelveDataSymbolSearchClient (tous deux sélectionnés par market.provider: twelvedata)
Cache Caffeine market-chart (chart), symbol-search (autocomplete). TTL 15 min partagé via market.cache.ttl-minutes

Quirks à connaître : numériques retournés en string JSON ("open": "180.00"), erreurs en HTTP 200 avec status: error dans le body. Le client absorbe les deux. Voir architecture.md section "Twelve Data — quirks à absorber".


Finnhub — news par ticker + recommandations analystes + earnings

Site https://finnhub.io
Inscription https://finnhub.io/register (email + mot de passe, pas de carte requise)
Dashboard / clé https://finnhub.io/dashboard
Free tier 60 calls/min · pas de cap quotidien · large agrégation de sources presse financière (Reuters, Bloomberg, CNBC…) + breakdown analystes monthly + earnings 4 derniers Q
Endpoints utilisés /company-news?symbol=...&from=...&to=... (Phase 2 news), /stock/recommendation?symbol=... (Phase 2 analyst — breakdown monthly), /stock/price-target?symbol=... (Phase 2 analyst — price target 12 mois, fail-soft à null sur 401/403 paid tier), /stock/earnings?symbol=... (Phase 2 earnings — historique 4 derniers Q EPS estimate/actual/surprise), /calendar/earnings?from=...&to=...&symbol=... (Phase 2 earnings — prochaine annonce sur fenêtre 90 j, fail-soft à null sur 401/403 paid tier), /stock/profile2?symbol=... (Phase 2 benchmark v2 — finnhubIndustry → SPDR ETF mapping via SpdrSectorEtfs. Remplace Twelve Data /profile paid-tier)
Config news.provider: finnhub (news) + analyst.provider: finnhub (recos analystes) + earnings.provider: finnhub (earnings) + market.finnhub.api-key (env FINNHUB_API_KEY) — clé partagée. Le sector benchmark utilise aussi Finnhub mais via le toggle market.provider (pas de sector.provider dédié) — détail caché derrière RoutingSectorClassifier
Adapter FinnhubClient (sélectionné par news.provider: finnhub) + FinnhubAnalystClient (sélectionné par analyst.provider: finnhub) + FinnhubEarningsClient (sélectionné par earnings.provider: finnhub) + FinnhubSectorClassifier (sélectionné par market.provider: twelvedata — le routage sector route en réalité vers Finnhub car Twelve Data /profile est paid-tier only)
Mock alternative MockNewsClient (sélectionné par news.provider: mock, défaut) — feed synthétique déterministe par symbole, ~10 % de tickers "quiet" qui retournent une liste vide pour exercer l'empty-state UI. MockAnalystClient (sélectionné par analyst.provider: mock, défaut) — breakdown synthétique déterministe (~50 % bullish / ~30 % mixed / ~20 % bearish, drift mois-sur-mois), symboles réservés UNKNOWN (404), RATELIMIT (503), NOTARGET (priceTarget=null). MockEarningsClient (sélectionné par earnings.provider: mock, défaut) — EPS bande $0.30–$3.50 + surprise ±15 % + next-date 1–60 j, symboles réservés UNKNOWN (404), RATELIMIT (503), NOCALENDAR (nextEarningsDate=null)
Cache Caffeine news-by-symbol (TTL 15 min, key {symbol}\|{limit}) + analyst-recommendations (TTL 15 min, key {symbol}) + earnings (TTL 15 min, key {symbol}) + sector-by-symbol (TTL 15 min, key {symbol}) — TTL partagé via market.cache.ttl-minutes

Pourquoi Finnhub plutôt que Twelve Data pour les news : Twelve Data n'expose pas d'endpoint news public (testé en live, retourne 404). Finnhub couvre ce besoin avec un free tier plus généreux que d'autres concurrents (Alpha Vantage 25/jour, Polygon 5/min EOD only). Idem côté analyst recommendations et earnings : /stock/recommendation et /stock/earnings sont en free tier sans paywall, ce qui n'est pas le cas chez la plupart des concurrents.

Économiser les credits en itération : les trois mocks sont le défaut sur application.yml justement pour qu'un onboarding clone tourne sans clé Finnhub, et que le développement quotidien ne fasse pas chauffer le compteur. Bascule sur news.provider: finnhub, analyst.provider: finnhub et/ou earnings.provider: finnhub dans application-local.yml (ou via /settings/configuration) quand tu veux tester un vrai feed — chacun se flippe indépendamment.


Anthropic Claude — narratif LLM

Site https://www.anthropic.com
Inscription https://console.anthropic.com
Dashboard / clé https://console.anthropic.com/settings/keys
Billing https://console.anthropic.com/settings/billing — pay-as-you-go, ~5 € pour ~hundreds de narratifs
Modèle utilisé claude-opus-4-6 (default YAML), peut basculer sur claude-sonnet-4-6 (~5× moins cher, qualité narrative très correcte)
Config anthropic.api.key (env ANTHROPIC_API_KEY), anthropic.api.modelles deux éditables au runtime depuis /settings/configuration > LLM (clé masquée + bouton Tester depuis 2026-05-08, modèle en autocomplete libre)
Client ClaudeClient (sélectionné par llm.provider: claude) — clé et modèle lus per-call via AppConfigService, rotation immédiate sans reboot
Probe POST /api/config/test/anthropic accepte une clé candidate non sauvée, round-trip Claude avec le modèle courant et le prompt fixe « Reply with exactly the word OK. » — utilisé par le bouton « Tester » de la card Settings
Latence 1-3 s par narratif sur Opus, légèrement moins sur Sonnet

Si le bouton "Buy credits" est grisé : ajouter une carte au compte d'abord, et vider le champ Business tax ID (Anthropic essaie de valider un BN canadien et tape sur $-- pour la tax si la valeur est invalide).


Ollama — LLM local (offline / sans clé)

Site https://ollama.com
Installation Lancée automatiquement par tilt up via docker-compose.yml
Modèle par défaut qwen2.5:3b (~2 Go, ~5-10 s par narratif sur M1) — pull depuis /settings/configuration > LLM > Pull… (panneau État Ollama, suggestions hardcodées + tag libre)
Modèles testés qwen2.5:3b ✅ (défaut), qwen2.5:7b (15-30 s, qualité +), mistral 7B ❌ (30-60 s, timeouts sur M1)
Config ollama.base-url, ollama.model
Client OllamaClient (sélectionné par llm.provider: ollama)
API http://localhost:11434 (UI Tilt expose le link)

Ollama tourne en local — aucune clé, aucun crédit, mais qualité narrative inférieure à Claude. Utile pour dev offline ou éviter de cramer des credits Anthropic en itération.


Récapitulatif config locale

À copier dans backend/src/main/resources/application-local.yml (gitignored) :

anthropic:
  api:
    key: sk-ant-api03-...        # https://console.anthropic.com/settings/keys

llm:
  provider: claude               # ou `ollama` pour offline

ollama:
  base-url: http://localhost:11434
  model: qwen2.5:3b              # pull depuis /settings/configuration > LLM > Pull…

market:
  provider: twelvedata           # ou `mock` sans clé
  twelvedata:
    api-key: ...                 # https://twelvedata.com/account/api-keys
  finnhub:
    api-key: ...                 # https://finnhub.io/dashboard

news:
  provider: finnhub              # ou `mock` (défaut, pas de credits consommés)

analyst:
  provider: finnhub              # ou `mock` (défaut, pas de credits consommés). Partage market.finnhub.api-key

earnings:
  provider: finnhub              # ou `mock` (défaut, pas de credits consommés). Partage market.finnhub.api-key

Sécurité : ne jamais committer ces clés. application-local.yml est gitignored, application.yml lit les env vars (${TWELVEDATA_API_KEY:} etc.) qui restent vides en CI / fresh clone — c'est volontaire pour que l'onboarding marche en mode mock sans clés.