Funk-lab/admin/ia/finlab.md
ALI YESILKAYA 9d55cc803d
feat(finlab): import déterministe d'un relevé de compte Revolut → positions (#72)
Procédure de mise à jour du portefeuille « à chaque trade » à partir des relevés
Revolut, sans IA (exact).

- finlab/revolut.py : reconstruit les positions depuis le « trading account
  statement » (toutes transactions) par COÛT MOYEN (achats − ventes, PRU pondéré),
  mappe les tickers Revolut→Yahoo (ASME→ASML.AS, TOTB→TTE.PA, BNP→BNP.PA, AXA→CS.PA,
  FTE→ORA.PA, AIR1→AI.PA) et vérifie les cours. Idempotent, ne touche qu'un compte,
  préserve les autres comptes/cash/commentaires (round-trip ruamel.yaml)
- CLI : python -m finlab.cli import-revolut <csv> [--write] [--account]
- Dashboard : le bouton « Importer un relevé » accepte les CSV → endpoints
  /api/revolut/preview (aperçu) + /api/revolut/apply (écrit), avec garde anti-évasion
  de chemin ; le front affiche les positions + bouton « Appliquer »
- portfolio.yaml : compte Revolut reconstruit depuis l'historique complet → ajoute
  AMAT (achetée le 29/06, manquait) ; valeurs alignées au centime
- requirements : + ruamel.yaml ; persona console + admin/ia/finlab.md documentés

Validé sur l'historique réel : 11 positions reconstruites = portfolio.yaml existant
(cours vérifiés, 0 warning) + AMAT. Flux dashboard upload→preview→apply testé
(TestClient), JS OK.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 16:31:01 +02:00

95 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# FinLab — dashboard finance + console Claude Code + toolkit d'analyse
**Quoi** : boîte à outils d'analyse de marché maison (`finlab`, données Yahoo Finance gratuites)
déployée in-cluster sous **deux faces** (une seule image) : un **dashboard web** (graphiques,
portefeuille, watchlists, actions) et une **console Claude Code** finance. Remplace l'approche
OpenAlice abandonnée (cf. `admin/ia/openalice.md`) par plus simple et plus puissant : **ton vrai
Claude Code** (sur ton abonnement, pas l'API au compteur) + une UI graphique gratuite.
- **Dashboard** (`finance.lab.local/`) — graphiques chandeliers (MM50/200 + volume), portefeuille
(P&L/poids/secteurs), watchlists thématiques scannées, alertes du jour, plan de trade R:R.
FastAPI `dashboard/server.py`, **aucun LLM/clé** (analyse technique pure).
- **Console** (`finance.lab.local/console/`) — terminal web (`ttyd`) → `claude` agentique,
persona + outils finlab en MCP, login abonnement persisté.
**Où** :
- Source : `tools/finlab/` (code finlab + Dockerfile + persona `workspace/CLAUDE.md`).
- Image : CI `.github/workflows/build-finlab.yml``ghcr.io/alkatrazz24/funk-finlab`.
- Déploiement : ns `ai`, `finance.lab.local`, manifests `k8s/apps/finlab/`, app ArgoCD
`k8s/apps-of-apps/apps/finlab.yaml`.
- MCP local : `.mcp.json` (racine repo lab) → outils finlab dans les sessions Claude Code du lab.
**Cadre** : analyse/aide à la décision uniquement, **aucun ordre réel** (seul le paper trading
Alpaca fictif est exécutable). Persona dans `tools/finlab/workspace/CLAUDE.md` (profil swing
trader concentré tech/semis, philosophie R:R/concentration/discipline).
## Architecture
| Composant | Détail |
|---|---|
| initContainer `seed` | Peuple le workspace (`cp -rn`), robuste au piège NFS (fsGroup non honoré → recrée le dossier s'il est root/non-inscriptible). Tourne avant les conteneurs |
| container `dashboard` | `uvicorn dashboard.server:app` :8800 — UI + API JSON finlab |
| container `console` | `ttyd -b /console` :7681 → `claude` dans le workspace |
| container `watcher` | `python -m finlab.watcher` — alertes de prix par email, boucle **5 min** |
| Cerveau (console) | **Abonnement Claude Code** (login OAuth persisté dans `~/.claude` sur le PVC) — pas de clé API |
| Code vs data | Code (`finlab` + `dashboard`) dans l'image `/opt/app` (maj avec l'image) ; configs éditables via **`FINLAB_HOME=/home/finlab/workspace`** (PVC) |
| PVC `finlab-data` | 5Gi NFS → `/home/finlab` : login + workspace (configs + `.cache`) |
| Auth | basicAuth Traefik (`finlab-auth`) sur les deux routes — un shell web ne s'expose pas nu |
| Routes | `/console` → 7681 · reste → 8800 |
**Découplage code/data** : `finlab` lit ses configs depuis `FINLAB_HOME` si défini (sinon repli
sur le dossier du package → dév local inchangé). Le workspace est seedé au 1er boot puis vit sur
le PVC (edits + login persistent ; une nouvelle image n'ajoute que les fichiers manquants).
## Outils finlab
`digest` (vue d'ensemble compacte, à privilégier), `portfolio_summary`, `opportunities`/`scan`,
`technical_analysis`/`tech` (RSI/MACD/MM50-200/Bollinger/ATR), `fundamentals` (PER/PEG/ROE/dette/
cible), `trade_plan`/`plan` (entrée/stop ATR/objectifs/taille/**R:R**), `alerts_today`, `price`,
plus paper trading (`paper_account`/`paper_positions`/`paper_order`, clés Alpaca optionnelles).
Configs (workspace, éditables) : `portfolio.yaml` (**multi-comptes** : `accounts` avec
name/type/cash/positions — ex. Revolut + BNP Paribas PEA ; agrégats globaux + par compte),
`watchlists.yaml` (thèmes chaîne IA/datacenter), `alerts.yaml` (règles).
## Onboarding (premier boot)
Checklist détaillée : `k8s/apps/finlab/README.md`.
1. Secrets manuels dans `ai` : `ghcr-pull` (pull GHCR) + `finlab-auth` (htpasswd basicAuth).
2. Ouvrir `finance.lab.local``claude``/login` (abonnement, persisté sur le PVC).
## Import de portefeuille — relevé Revolut (déterministe)
`finlab/revolut.py` reconstruit les positions depuis un **relevé de compte Revolut** (account
statement CSV, export sur toute la période) par **coût moyen** (achats ventes, PRU pondéré),
mappe les tickers Revolut→Yahoo (`ASME→ASML.AS`, `TOTB→TTE.PA`, `BNP→BNP.PA`, `AXA→CS.PA`,
`FTE→ORA.PA`, `AIR1→AI.PA`) et vérifie les cours. **Idempotent**, ne touche qu'un compte
(défaut « Revolut »), préserve les autres comptes/cash/commentaires (round-trip ruamel).
- **Dashboard** : bouton « Importer un relevé » accepte les **CSV** → endpoints
`/api/revolut/preview` (aperçu) + `/api/revolut/apply` (écrit portfolio.yaml). Sans IA.
- **CLI** : `python -m finlab.cli import-revolut <csv> [--write] [--account Revolut]`.
C'est la **procédure de mise à jour « à chaque trade »** : ré-exporter le relevé complet → importer.
Le P&L statement et les exports mono-mois ne suffisent pas (positions incomplètes).
## Alertes de prix par email
Sidecar **`watcher`** (`finlab/watcher.py`) : boucle **toutes les 5 min**, lit
**`price_alerts.yaml`** (workspace), et envoie un email quand un seuil (`above`/`below`) est
franchi. Envoi via le **relais postfix du lab** (`storage-01:25`, `SMTP_HOST`) qui réécrit
l'expéditeur en Gmail — **aucun secret** (les pods k8s sont dans `mynetworks`, cf.
`admin/infra/email.md`). Anti-spam : un seuil ne notifie qu'**une** fois (état `.watcher-state.json`),
ré-armé en ré-éditant la règle. La **Console IA édite `price_alerts.yaml`** sur demande
(« mets un mail quand NVDA atteint 200$ »). Test : `python -m finlab.watcher --test <email>` / `--once`.
## Accès programmatique
- **MCP dans le repo lab** : `.mcp.json` racine pointe `tools/finlab/.venv` → outils finlab dans
les sessions Claude Code du lab (approbation MCP au 1er lancement).
- **Headless** : `kubectl -n ai exec deploy/finlab -- python -m finlab.cli digest`.
## Liens
- Source historique : ex-projet `Projets/Finance` (rapatrié ici).
- Approche précédente abandonnée : `admin/ia/openalice.md`.