Fonctionnalités
Phase 0 — Fondation (terminé, partiellement décommissionnée)
Tout ce qui constitue l'ossature de l'app aujourd'hui. Une partie est conservée et utilisée, une partie a été décommissionnée en Phase 2.5 (le code et les tables associées ont été supprimés — voir plus bas).
Conservé
Portefeuille (lecture seule, CSV-driven)
Le portefeuille reflète l'état réel du courtier Wealthsimple. L'import d'un export CSV (« Positions ») crée ou met à jour automatiquement un portefeuille par compte. La vue Dashboard affiche les positions en lecture seule.
Import CSV
Page Import : drag & drop d'un export Wealthsimple (multi-fichiers supporté). Prévisualisation, confirmation, upsert des positions, création d'un snapshot par compte.
Historique des positions (Suivi)
Page Suivi : timeline des imports groupés par batch_id, expand par compte, détail des positions avec valeur de marché et P&L.
Thème clair / sombre
Toggle dans le header (sombre par défaut). Tokens CSS, persistance localStorage, transitions fluides.
Architecture frontend
Ports & adapters léger sous core/ + UI dans features/. Voir docs/technique/architecture.md pour la liste des repositories à jour.
Infra et qualité
Tilt + Docker Compose, CI GitHub Actions (backend Gradle + Postgres / frontend Vitest), Flyway, ports/adapters Spring, @Async sur bean séparé, tests d'intégration sur vrai PostgreSQL.
Décommissionné (Phase 2.5)
Ingestion RSS
Module ingestion/ (scheduler Rome, déduplication, 25 sources seedées, parsing robuste DOCTYPE / & nus / détection HTML) supprimé. Tables feed_source et feed_article droppées (migration V6). La Phase 6 « Réintégration Phase 0 » repartira de sources Phase 1+2 (snapshots ticker + analyst + earnings + news per-ticker), pas d'un nouveau scraping RSS.
Analyse portefeuille (LLM rebalancing)
Pipeline AnalysisExecutor (AnalysisContextLoader, LlmResponseParser, RecommendationValidator 8 règles, RecommendationPersister, AnalysisJobStore) supprimé. Tables recommendation, recommendation_action, recommendation_score, analysis_job droppées (V6). Pages frontend /recommendations et /history supprimées. Le replacement Phase 6 sera un job PortfolioAggregation qui agrège les snapshots ticker existants — pas un re-prompt LLM portfolio-wide.
Settings RSS back-office
Pages /settings/sources et /settings/test-sources (activer/désactiver flux + tester un parse RSS) supprimées avec le module ingestion/. Le sidenav settings vit aujourd'hui avec configuration/ (config runtime Phase 2) et prompts/ + prompts/:id/stats (gestion + scoring des prompts narratifs, Phase 3). La page prompt-preview/ (aperçu interpolé du prompt narratif Phase 1) a été retirée le 2026-05-14, l'éditeur de prompts Phase 3 couvrant l'usage.
Pourquoi décommissionné maintenant : la Phase 0 était gelée depuis Phase 1, mais le module restait chargé et
AnalysisExecutorchargeait encore les 200 derniers articles RSS dans le prompt LLM même quand le scheduler était off — cause d'un timeout 400 s observé sur Ollama cold-start le 2026-05-07. Plutôt que de patcher le legacy, on a tranché : drop des tables et modules, le replacement Phase 6 (PortfolioAggregation au-dessus des snapshots ticker) ne réutilisera rien de la plomberie RSS+executor.
Phase 1 — Pivot ticker (terminé, tag v0.2.0)
Données de marché
Module market/ côté backend, port MarketChartClient derrière la clé market.provider :
- Twelve Data (défaut prod) : REST documenté, free tier 800 credits/jour, TSX natif. Deux endpoints (
/time_series+/quote). - Mock (défaut sans clé) : série OHLC déterministe par symbole — onboarding sans clé, CI sans réseau.
- Caching court Caffeine 15 min.
- Endpoint REST :
GET /api/market/ticker/{symbol}.
Indicateurs calculés serveur
IndicatorCalculator — Kotlin pur, testable unit, aucun appel LLM :
- RSI (14)
- MA50, MA200 et croisements
- Momentum 30j / 90j
- Performance 1m / 3m / 1y / YTD
- Drawdown depuis 52w high
- Volume relatif (vs moyenne 30j)
- Position vs MA50, MA200 (en %)
Narratif LLM par ticker
Nouveau prompt par ticker (pas portfolio-wide) :
- Input :
{ticker, currentPrice, indicators, fundamentals, recentChange} - Output JSON :
{summary, sentiment: 'bullish'|'bearish'|'neutral', keyPoints: string[]} - Provider par défaut : Claude API (Ollama +
qwen2.5:3bconservé en backup pour dev offline ; Mistral 7B retiré, trop lent sur M1). - Pas de targetWeight, pas de BUY/SELL — l'IA décrit, elle ne décide pas.
Dossier ticker (UI)
Nouvelle page features/ticker/ :
- En-tête : symbole, nom, prix courant, variation jour, sentiment badge
- Graphique des prix en SVG inline (pas de dépendance ajoutée). Phase 1 : courbe simple 1Y daily. Phase 2 : toggle multi-timeframe (1D / 5D / 1M / 3M / 1Y / 5Y), chart enrichi (axes + grille + crosshair), overlays multi-select (MA50 / MA200 / Bollinger / 52w hi-lo), zoom drag-select avec brush mini-chart navigator, annotations user persistées localStorage et mesure tools delta % / delta time.
- Indicateurs en chips : RSI, drawdown, perf 1y, distance à la MA50
- Narratif LLM : summary + keyPoints en bullets
- Snapshot persistant : chaque consultation génère un
TickerNarrativeSnapshot(prix + indicateurs + texte LLM + horodatage)
Watchlist / liste de tickers
Deux sources visibles côté UI : - Tickers détenus (portfolio CSV Wealthsimple) — automatique, lecture seule, agrégé sur tous les portefeuilles. - Watchlist persistée — saisie manuelle de tickers à surveiller hors portefeuille (cf. Phase 2 livré).
Phase 2 — Profondeur ticker
✅ Livré
- Multi-timeframe sur le graphe : toggle
1D / 5D / 1M / 3M / 1Y / 5Yau-dessus du chart. Le dossier (indicateurs + narratif) reste ancré sur1Y daily; seul le graphe se reconfigure au clic. Endpoint dédiéGET /api/market/ticker/{symbol}/chart?timeframe=. - Chart enrichi : axes Y (prix) et X (dates), grille pointillée, crosshair au survol avec tooltip date + prix exacts.
- Watchlist persistée : module backend
watchlist/+ tablewatchlist_entry(V3). Ajouter / retirer un ticker via la sidebar dashboard (input + liste avec poubelle) ou via le bouton "Suivre / Suivi" sur le header du Dossier ticker. Add idempotent côté serveur, optimistic UI côté front avec rollback sur erreur. - Sidebar dashboard collapsable : trois sections indépendamment foldables (Portefeuilles, Tickers détenus, Watchlist) + scrollbar custom 8px globale.
- News par ticker : section dédiée sur le Dossier ticker entre la plage 52w et le narratif IA. Liste 10 headlines (Reuters / Bloomberg / CNBC agrégés via Finnhub), source + date relative, clic ouvre l'article dans un nouvel onglet. Provider Finnhub séparé (clé dédiée) car Twelve Data ne couvre pas les news. Mock synthétique disponible (
news.provider: mock, défaut sans clé) pour itérer sans consommer le quota. - Settings & config runtime : page
/settings/configuration(4e onglet sidenav, icônetune) qui édite en direct douze clés sans reboot, structurées en deux sub-sections (Providers de données / LLM). Phase 2 a posé les fondations (clés API Twelve Data + Finnhub + bouton « Tester », TTL cache Caffeine 5–60 min slider, quatre toggles provider mock ↔ livemarket.provider/news.provider/analyst.provider/earnings.provider) ; Phase 2.5 a étendu au LLM (togglellm.providerclaude ↔ ollama, modèlesollama.model+anthropic.api.modelen autocomplete libre, sliderllm.timeout-seconds60–900 s, cléanthropic.api.keySECRET avec bouton Tester depuis 2026-05-08). Hint conditionnel sur la card Twelve Data quand la clé Finnhub est absente : signale que le Sector benchmark utilise Finnhub même en mode markettwelvedata(correctif post-audit Phase 2 finding #4). Persistance dans la tableapp_config(V4) qui surcharge les défauts YAML ; bouton « Réinitialiser au défaut » par clé. Note sécu : clés API stockées en clair en BDD locale — acceptable projet perso. - Comparaison vs benchmark (v1) : overlay opt-in d'un indice (SPY / QQQ / IWM) sur le chart du dossier ticker.
mat-button-toggle-groupOff / SPY / QQQ / IWM dans la chart-toolbar, défaut Off → zéro consommation Twelve Data tant qu'aucun click. Quand un benchmark est sélectionné, le Y-axis flippe instantanément du prix absolu vers le % return signé depuis la première bar (sinon SPY à 500 $ écraserait visuellement un small-cap à 15 $). La 2ᵉ ligne dashed semi-transparente apparaît dès que le fetch résout, le tooltip enrichi compare les deux séries au même index (swatch + symbol + valeur). Tooltip +aria-labelsur les boutons SPY/QQQ/IWM expliquent l'indice complet ("S&P 500 (SPY)"). Front-only, zéro changement back : réutiliseGET /api/market/ticker/{symbol}/chart?timeframe=qui partage son cache Caffeine sur la clé(symbol, range, interval). Refetch des deux séries en parallèle au changement de timeframe. - Comparaison vs benchmark (v2 — Sector + Custom) : étend l'overlay v1 avec deux nouveaux modes. Sector auto-détecte le SPDR sector ETF qui couvre le secteur GICS du ticker (AAPL → XLK Technology, JPM → XLF Financials) ; Custom laisse l'utilisateur taper n'importe quel ticker via un
mat-autocompletesidecar dans la toolbar (réutilisesearchSymbolsdu provider de marché actif). Backend : nouveau portSectorClassifieravec deux adapters sélectionnés parmarket.provider— initialementTwelveDataSectorClassifier(REST/profile, 1 credit/call) remplacé le 2026-05-06 parFinnhubSectorClassifier(/stock/profile2, free tier) parce que/profilecôté Twelve Data est paid-tier only ;RoutingSectorClassifierroute désormais le mode livetwelvedatavers Finnhub (cf.architecture.md→ Switch provider à chaud). L'autre adapter,MockSectorClassifier(~25 tickers seedés US/TSX), reste inchangé.RoutingSectorClassifier(@Primary). Mapping hardcodéSpdrSectorEtfs(11 GICS sectors → XLK/XLF/XLV/XLE/XLY/XLP/XLC/XLI/XLB/XLRE/XLU + table de synonymes pour les variations provider type "Information Technology" / "Health Care" / "Consumer Cyclical").SectorClassifierServiceavec@Cacheable("sector-by-symbol"). EndpointGET /api/market/ticker/{symbol}/sector-benchmark. UI : toggle 5-buttons (Off/SPY/QQQ/IWM/Sector) + autocomplete sidecar "or pick…". Sector hors SPDR → 404 → message inline distinct (sectorNotMapped) du fetch error generic. - Chart : analyse + sélection (v1+v2+v3) : extension du chart Dossier ticker avec trois couches d'outils interactifs. v1 zoom drag-select :
pointerdown→ drag horizontal →pointerupau-delà de 10 px commit un zoom (slice symétrique des séries ticker + benchmark danschartGeometry), reset via bouton toolbar visible quand zoomé ou double-clic. v2 overlays multi-select :mat-button-toggle-groupMA50 / MA200 / Bollinger (BB) / 52w hi / 52w lo, calculé front-side depuis la série complète (pour rester sémantiquement "MA50 de la série complète" même sous zoom), désactivé en mode benchmark (Y axis en % return space, MA en prix space — pas le même système). v3 brush mini-chart : SVG 52 px de haut sous le main, mirroir de la full series avec rectangle draggable indiquant la zone zoomée — trois modes selon la zone du grab (pan/resize-left/resize-right, hit-zone 8 px), reset si click hors rectangle. v3 annotations : nouveau portAnnotationRepositorycôté front + adapterLocalStorageAnnotationRepository(keyticker-annotations:{SYMBOL},crypto.randomUUIDavec fallback,defer()pour convertir un throw quota-exceeded en error notification). Bouton toolbar "+ Annotation" arme le mode ; le prochain click sub-threshold pose une h-line au prix cliqué (inverse-yAt viageom.yMin+yRange). Out-of-range → clamp top/bottom + suffixe ↑/↓. Click sur le handle×→ optimistic remove avec rollback. Délégation à un futur backend-backed adapter sans rewrite UI. v3 measure tools : un click sub-threshold (sans annotation mode) pose un anchor au bar le plus proche, hover montre delta % et delta time (formatDeltaTimeadaptatif min/h/j) dans une ligne distincte du tooltip. Anchor recovered par timestamp à chaque geometry pass — robuste au zoom qui shift les indices. Désactivé en benchmark mode (le % axis fait déjà ce travail). Click vs drag distinguishment partagé (threshold 10 px) entre les 3 features. - Recommandations analystes : sous-bloc « Recommandations analystes » de la nouvelle section « Fondamentaux » sur le Dossier ticker, entre les chips d'indicateurs et la section News. Affiche le consensus monthly (chip BUY/HOLD/SELL/MIXED — seuils 60 % bullish/bearish, 50 % hold, MIXED sinon), un breakdown segmented bar 5 buckets (strongBuy / buy / hold / sell / strongSell) avec tooltip par segment, une légende chips, le price target consensus 12 mois (high / low / mean, masqué si indisponible) et une trend arrow up/down/flat sur les 6 derniers mois (delta bullish-minus-bearish / total). Backend — nouveau module
analyst/avec portAnalystRecommendationClient, deux adapters :FinnhubAnalystClient(/stock/recommendationrequis +/stock/price-targetoptionnel, fail-soft ànullsur 401/403/5xx parce que le price-target est derrière un paid tier sur certains comptes Finnhub) etMockAnalystClient(synthétique déterministe par symbole, ~50 % bullish / ~30 % mixed / ~20 % bearish, drift mois-sur-mois pour une trend non plate, symboles réservésUNKNOWN/RATELIMIT/NOTARGET).RoutingAnalystClient(@Primary),AnalystRecommendationServiceavec@Cacheable("analyst-recommendations")15 min (Finnhub stamp les snapshots mensuellement → staleness invisible). EndpointGET /api/market/ticker/{symbol}/analyst-recommendations. Nouvelle clé runtimeanalyst.provider(mock↔finnhub, séparée denews.providerpour pouvoir flipper indépendamment). Cacheanalyst-recommendationsajouté àMarketConfig, partage le TTLmarket.cache.ttl-minutes. Frontend — nouveau portAnalystRepository+ adapter HTTP, signauxanalyst / analystLoading / analystNotCovered / analystErrorscopés à la panel (404 = no coverage = empty state distinct du 503 = inline error). HelperanalystBucketPctpour la segmented bar,computed analystTrend(epsilon 5 %, defaut flat). i18n FR + EN (chip consensus, bucket labels, tooltips, trend tooltips, target labels). - Earnings dates et derniers résultats : 2ᵉ sous-bloc « Résultats » de la section « Fondamentaux » sur le Dossier ticker, sous le sous-bloc analyste. Affiche la prochaine date attendue avec countdown ("dans N jours" ou "aujourd'hui" / "demain"), un badge horaire BMO/AMC quand connu, et un tableau des 4 derniers trimestres (période / EPS estimé / EPS réel / surprise % colorée beat/miss/inline). Pin de couleur warning quand la date est ≤ 7 jours pour signaler une publication imminente sans bloquer le reste. Backend — nouveau module
earnings/avec portEarningsClient, deux adapters :FinnhubEarningsClient(/stock/earningsrequis +/calendar/earningsoptionnel, fail-soft ànullsur 401/403/5xx — fenêtre 90 j en avant pour capturer la prochaine annonce sans burn de quota sur du long terme) etMockEarningsClient(synthétique déterministe par symbole, EPS dans la bande $0.30–$3.50, surprise ±15 % autour de l'estimé, next-date 1–60 j en avant, symboles réservésUNKNOWN/RATELIMIT/NOCALENDAR).RoutingEarningsClient(@Primary),EarningsServiceavec@Cacheable("earnings")15 min. EndpointGET /api/market/ticker/{symbol}/earnings. Nouvelle clé runtimeearnings.provider(mock↔finnhub, séparée denews.provideretanalyst.provider). Cacheearningsajouté àMarketConfig(6e cache, partage le TTL). Domain helper purcomputeSurprisePercent(gère null + zero estimate + estimate négatif viaabs()au dénominateur pour qu'un beat sur loss-making reste positif). Frontend — nouveau portEarningsRepository+ adapter HTTP, signauxearnings / earningsLoading / earningsNotCovered / earningsErrorscopés à la panel (mêmes règles d'isolation que la news / analyst). HelperearningsCountdownDays(computed, anchored UTC pour éviter le drift timezone),earningsSurpriseSign(report)(beat/miss/inline). i18n FR + EN (col headers, time labels BMO/AMC, today/tomorrow/inDays/daysAgo). - News inline (v1 minimaliste) : chaque headline du panneau News du Dossier ticker est désormais un accordéon — clic sur la row toggle un body qui surface le
summaryFinnhub + un lienLire l'article complet →explicite vers laurl(target=_blank). Le default action « row click » garde l'utilisateur sur le dossier ; le lien sortant n'est plus la première chose qui se déclenche. Choix v1 explicite : on n'introduit ni scraping (ToS Reuters/Bloomberg fragiles, paywalls, sites JS-heavy) ni LLM-as-summarizer (hallucination + ~10 calls Claude par dossier ouvert) — on affiche ce que Finnhub fournit déjà dans le payload. Honnête (zéro contenu inventé), zéro nouvelle dépendance. Multiple items ouvrables simultanément pour comparer deux dépêches. Backlog v2 LLM-as-summarizer filed en Phase 2.5 dette si à l'usage le résumé Finnhub se révèle trop court.
Phase 2 clôturée 2026-05-06 — tous les items « ticker » de profondeur sont livrés. Les sujets de stabilisation et d'outillage ont été repris sous Phase 2.5 Stabilisation et outils (clôturée 2026-05-10, tag
v0.4.0; détail dansdocs/projet/journal-livraisons.md > Phase 2.5) ; l'observabilité narrative ouvre la Phase 3.
Phase 3 — Observabilité narrative
Phase 3 clôturée 2026-05-14 — tag candidat
v0.5.0. 4 livraisons en 5 jours qui forment une boucle d'audit narrative complète : foundation prompt management + scoring (2026-05-10), page observabilité narrative timeline + index (2026-05-13), score de cohérence cross-runs (2026-05-14), détection de biais (2026-05-14). Le ticket initialement projeté ici « Page Jobs DAG » a été déplacé en Phase 6 — il dépend du DAG unifié et son contenu est intrinsèquement lié à l'archi long terme. Détail des livraisons dansdocs/projet/journal-livraisons.md > Phase 3.
✅ Livré
- Prompt management + scoring (foundation Phase 3, livré 2026-05-10) : persistance des prompts narratifs en BDD (
prompt_template, V8), édition + activation live depuis/settings/prompts(éditeur textarea + diff side-by-side),prompt_scoreenregistré à chaque run (latency, retry, parse/validator failed), feedback 👍/👎 sur la card narrative du dossier ticker (PATCH /api/narrative/snapshots/{id}/thumbs), page de stats agrégées par prompt avec sparkline + tableau quotidien (/settings/prompts/{id}/stats). Permet le cycle « propose v3 → active → laisse tourner → compare vs v2 » sans toucher au code. Détail dansdocs/projet/journal-livraisons.md > Phase 3. - Page observabilité narrative (Phase 3 #1, livré 2026-05-13) : pour un ticker donné, timeline reverse-chronologique des narratifs passés mis en regard de ce que le prix a fait depuis (deltas 1 j / 1 sem / 1 mois colorisés). Filtrable par date range, par version de prompt (lecture qualitative « v3 vs v2 ») et par feedback thumbs. Page d'index
/observabilityqui liste tous les symbols ayant ≥1 snapshot. Lien direct depuis le footer de la card narrative du dossier ticker. Première surface qui transforme le corpus accumulé depuis Phase 1 en signal exploitable. Verdict implicite hit/miss volontairement absent v1 — il est traité par le score de cohérence livré le lendemain. Détail dansdocs/projet/journal-livraisons.md > Phase 3. - Score de cohérence cross-runs (Phase 3 #2, livré 2026-05-14) : chaque carte de la timeline porte une chip « Cohérence vs précédent » (OK / WARN / HIGH) qui flag quand le narratif change de manière non justifiée par le mouvement de prix entre les deux runs. Heuristique pure (sentiment 0.55 + jaccard key_points 0.30 + ratio longueur 0.15, discountée par le price move — un swing 5 % excuse fully un sentiment flip), pas de LLM-as-judge — gratuit, déterministe, transparent. Tooltip natif liste les 3 sous-mesures + le price move signé pour que le user puisse re-dériver le verdict à l'œil. Détail dans
docs/projet/journal-livraisons.md > Phase 3. - Détection de biais (Phase 3 #3, livré 2026-05-14) : page
/observability/biasqui rend une vue agrégée du corpus narratif en 4 sections — sentiment distribution avec chip « biais suspecté » à 60 %, calibration sentiment vs prix (delta moyen 1d/1w/1m par bucket sentiment), couverture thématique des key_points (top-15 tokens avec compteur, l'absence d'un thème attendu est elle-même un signal), distribution des thumbs par sentiment (auto-check biais côté humain). Filtres date range + prompt version pour comparer un prompt vs un autre. Entrée navbar « Observabilité » ajoutée, lien depuis l'index. Détail dansdocs/projet/journal-livraisons.md > Phase 3.
🧊 Reporté Phase 6
- Page Jobs (DAG) : déplacé en Phase 6 — bloqué sur le ticket fondateur « Pipeline d'analyse — modèle DAG unifié ». L'UI au-dessus du DAG n'a d'intérêt que si le DAG existe (multi-kind jobs, parent/child, cache-aware leaves). Sans ces primitives, la page se réduirait à une liste plate de
ticker_narrative_jobqui dédouble la SSE de la narrative card.
Phase 4 — Authentification (clôturée 2026-05-17)
Phase orthogonale aux features métier — pré-requis bloquant pour tout déploiement public (Phase 5). Livrée intégralement : OAuth2 Google OIDC + Spring Security backend, rôles ADMIN/USER via whitelist email, frontend
/login+ interceptor + guards + navbar role-gating, CSRF re-enabled (cookie-based SPA pattern), page/errorglobale, profile devlocal-no-authqui bypasse Spring Security pour le dev solo (user fake ADMIN seedé), migration multi-tenantuser_idFK surportfolio+watchlist_entryavec scoping systématique des reads (4 services + 1 controller), provider gating UI (toggles disabled + tooltip i18n quand la clé requise manque), logs redaction (conventionuserIdUUID, jamais l'email), Flyway squash V1→V10 en un seulV1__init.sql. Le toggleBACKEND_AUTH_MODE(no-auth ↔ oauth) dans.env+ boutons Tilt permet de switcher au runtime sans éditer de fichier. Pas reflétée en capacités utilisateur ici — c'est de la sécurité, pas une feature métier. Détails d'implémentation dansdocs/projet/journal-livraisons.md > Phase 4. Les tickets résiduels (hardening secret-management OAuth prod,forward-headers-strategy, GitHub Secrets vault, multi-provider OAuth) sont passés en début de Phase 5 ou en dette technique parce qu'ils dépendent du choix d'hébergement.
Phase 5 — Déploiement
Phase orthogonale aux features métier — sortir l'app du localhost. Reste filed côté
backlog.md(analyse hébergement OVH/Hetzner/Scaleway/AWS, CI/CD deploy, secrets, backups, DNS/TLS), pas reflétée ici parce qu'elle n'apporte pas de capacités nouvelles à l'utilisateur — c'est de l'infra qui rend les capacités existantes accessibles depuis n'importe où. Pré-requis bloquant : la Phase 4 Authentification doit avoir livré avant tout deploy public. Détails dansdocs/projet/backlog.mdsection Phase 5.
Phase 6 — Vision long terme
Cette phase est fondée sur le DAG d'analyse unifié (modèle technique décrit dans
docs/technique/architecture.md > Modèle pipeline d'analyse), qui devient le primitif sous la plupart des tickets ci-dessous : chaque analyse est un nœud cache-aware, les portfolio aggregations sont des parents qui consomment les snapshots ticker déjà calculés. Sans ce primitif, les features ci-dessous tournent à coût élevé ou sont impossibles.
- DAG d'analyse unifié : fondation pipeline (table
jobparent/child, cache-aware leaves, dedup déterministe) — pré-requis bloquant pour la plupart des autres items - Réintégration de la Phase 0 décommissionnée : les recommandations portefeuille reviennent, mais en agrégeant les insights ticker plutôt qu'en les recalculant —
PortfolioAggregationparent du DAG - Page Jobs (DAG) : visualisation des pipelines async, vibe « pipelines GitLab/GitHub Actions »
- Cron pré-chauffe quotidienne : pré-charge les analyses des positions OPEN hors heures de bureau, l'utilisateur arrive sur un dashboard cache-hit pur
- Croisement portefeuille × insights ticker : sur le Dashboard, afficher pour chaque position le sentiment ticker + alerte si RSI extrême ou drawdown important
- Watchlist alertes : seuils déclencheurs (RSI > 70, MA50 cassée, drawdown > 20%)
- Paper trading : simulation d'exécution (indépendant du DAG)
- Multi-broker : ne plus dépendre exclusivement du CSV Wealthsimple (indépendant du DAG)
- Fine-tuning : R&D long terme — entraîner un modèle sur les snapshots narratifs personnels + thumbs accumulés (indépendant du DAG)