Vous pouvez bâtir un analyste financier privé en Python qui prétraite des CSV bancaires, exécute des modèles ML locaux et utilise un LLM hébergé localement (ex. Ollama) pour générer des insights—sans envoyer vos données dans le cloud. Lisez la suite pour le plan technique et les exemples concrets.
Pourquoi créer un analyste financier privé ?
Créer un analyste financier privé permet de reprendre le contrôle de vos données tout en obtenant des insights exploitables sans dépendre d’un fournisseur cloud tiers.
Le problème principal reste la confiance et la confidentialité des solutions cloud : Les données financières transitent et sont stockées sur des serveurs externes, augmentant la surface d’attaque et les risques de fuite. Les obligations légales comme le RGPD (Article 5 sur la minimisation et Article 32 sur la sécurité) imposent des exigences que l’on maîtrise mieux en local.
Objectifs concrets d’un analyste local :
- Analyse locale immédiate : Réponses quasi-instantanées sans aller-retour réseau.
- Détection d’anomalies : Identification de transactions suspectes en temps réel pour réduire le délai de réponse.
- Classification des dépenses : Catégorisation automatique pour budgétisation et reporting.
- Explications en langage naturel : Génération de comptes-rendus compréhensibles sans exporter de données.
Bénéfices chiffrés et concrets :
- Réduction du risque d’exposition des comptes : Les données qui ne quittent jamais la machine ne peuvent pas être compromises via le cloud (zéro vecteur cloud pour ces éléments).
- Conformité RGPD améliorée : Respect facilité des principes de minimisation et de sécurité (RGPD Art.5 et Art.32).
- Latence réduite : Réponses généralement perceptibles en millisecondes localement, versus centaines de ms à plusieurs secondes en cloud selon la connexion.
- Coût opérationnel maîtrisé : Économie sur les frais continus d’API / stockage cloud pour volumes sensibles.
Scénarios d’usage :
- Contrôle personnel des dépenses et alertes budgétaires.
- Détection rapide de fraude avant contact avec la banque.
- Préparation automatisée des pièces pour l’expert-comptable.
Contraintes techniques et réglementaires à considérer :
- Stockage local chiffré et gestion des clés.
- Politique de backups sécurisés et hors-site chiffrés.
- Limitation des modèles sur machine (taille, mémoire, GPU).
- Mises à jour, patching et responsabilité en cas d’incident.
- Respect des obligations de conservation et de transfert transfrontalier si applicable.
| Critère | Cloud | Local |
| Confidentialité | Partagée avec le fournisseur, dépend des contrats | Maîtrisée si chiffrage et clés locales |
| Coût | Frais récurrents d’API et stockage | Investissement initial + coûts d’infra internes |
| Latence | Variable selon réseau | Quasi-instantanée localement |
| Complexité | Moins technique pour l’utilisateur final | Plus de gestion (sécurité, backup, modèle) |
Quelle architecture pour l’application ?
Je propose une architecture modulaire pour un analyste financier local : interface Streamlit, pipeline de preprocessing, modules ML, visualisations Plotly et intégration d’un LLM local (ex. Ollama) orchestrés depuis app.py.
Je décris ici le rôle de chaque composant et leurs échanges.
- app.py : Point d’entrée Streamlit, orchestration des appels aux modules, gestion UI et secrets.
- config.py : Paramètres centralisés (chemins, hyperparamètres, endpoints locaux).
- preprocessing.py : Nettoyage, feature engineering, export en parquet pour persistance.
- ml_models.py : Entraînement, inférence, sauvegarde/chargement de modèles avec joblib.
- visualizations.py : Graphs Plotly retournant objets JSON pour Streamlit.
- llm_integration.py : Intégration d’un LLM local (LLM = Large Language Model) via requêtes HTTP vers Ollama ou équivalent.
- requirements.txt : Dépendances listées pour reproduction (pandas, scikit-learn, plotly, streamlit, joblib, requests, pyarrow).
- sample_data/ : Jeux de données exemples en parquet.
Je fais communiquer les composants par fonctions et fichiers locaux : preprocessing.write_parquet(), ml_models.load_model() utilisant joblib.load(), visualizations.plot_*() renvoyant figures, llm_integration.query(prompt) appelant l’API locale via requests.
Je recommande Python 3.10+, environnement isolé venv ou conda, et les dépendances principales citées plus haut.
# app.py (squelette)
import streamlit as st
from config import CFG
from preprocessing import load_and_prep
from ml_models import load_model, predict
from visualizations import plot_timeseries
from llm_integration import query_llm
st.sidebar.title("Contrôles")
data = load_and_prep(CFG.DATA_PATH)
model = load_model(CFG.MODEL_PATH)
if st.button("Prédire"):
preds = predict(model, data)
st.plotly_chart(plot_timeseries(data, preds))
st.write(query_llm("Explique ces prédictions", context=preds))
# config.py (squelette)
import os
class CFG:
DATA_PATH = os.getenv("DATA_PATH", "sample_data/data.parquet")
MODEL_PATH = os.getenv("MODEL_PATH", "models/model.joblib")
LLM_ENDPOINT = os.getenv("LLM_ENDPOINT", "http://localhost:11434")
Je recommande trois options de déploiement local : sur PC (développement), serveur interne pour usage d’entreprise, ou container Docker pour reproductibilité.
Je conseille sécurité : chiffrement disque (LUKS/BitLocker), accès restreint (VPN, pare-feu), secrets en variables d’environnement ou fichiers chiffrés (age/gpg), sauvegardes chiffrées hors-site.
| Fichier | Responsabilité |
| app.py | Orchestration UI et appels modules |
| config.py | Paramètres et secrets |
| preprocessing.py | Nettoyage et export parquet |
| ml_models.py | Entraînement/Inférence, joblib |
| visualizations.py | Plots Plotly |
| llm_integration.py | API locale LLM (Ollama) |
- Créer l’environnement (venv/conda) et installer requirements.
- Configurer variables d’environnement et chiffrer les secrets.
- Valider accès réseau restreint au port LLM local.
- Activer chiffrement disque et sauvegardes chiffrées régulières.
- Tester restauration depuis backup et rotation des clés/secrets.
Comment prétraiter des relevés bancaires hétérogènes ?
Traiter des relevés bancaires hétérogènes commence par résoudre des problèmes concrets : colonnes et séparateurs variables, formats de date multiples, montants répartis en débit/crédit, séparateurs décimaux différents et symboles de devise. J’utilise pandas et des regex pour détecter et normaliser automatiquement à l’import afin d’obtenir le schéma standard (date, description, amount).
- Exemples de patterns regex pour détecter les colonnes (insensibles à la casse) :
- Date : date|transaction_date|posted|valeur|booking_date
- Montant : amount|montant|credit|debit|valeur|solde
- Description : desc|libellé|libelle|description|narration
Principes de traitement automatisé :
- Détection automatique des colonnes via regex pour mapper à date/description/amount.
- Conversion des dates avec une liste de formats et fallback à pd.to_datetime (errors=’coerce’).
- Fusion Debit/Credit : calculer amount = credit.fillna(0) – debit.fillna(0) pour que les dépenses soient négatives.
- Normalisation des décimales et devises : remplacer les virgules par des points, retirer les symboles monétaires, conserver une colonne currency si détectée.
- Suppression des duplicatas et gestion des valeurs manquantes (supprimer lignes sans date/amount, remplir description par ‘N/A’).
Règle d’or : Normaliser tôt pour simplifier l’ingénierie des features et éviter la dette technique en aval.
import re
import pandas as pd
DATE_PATTERNS = re.compile(r"date|transaction_date|posted|valeur|booking_date", re.I)
AMOUNT_PATTERNS = re.compile(r"amount|montant|credit|debit|valeur|solde", re.I)
DESC_PATTERNS = re.compile(r"desc|libellé|libelle|description|narration", re.I)
CURRENCY_RE = re.compile(r"[\u20AC$£]")
def detect_columns(cols):
mapping = {}
for c in cols:
if DATE_PATTERNS.search(c):
mapping['date'] = c
elif DESC_PATTERNS.search(c):
mapping['description'] = c
elif AMOUNT_PATTERNS.search(c):
mapping.setdefault('amount_candidates', []).append(c)
return mapping
def parse_amount_series(s):
s = s.astype(str).str.replace(r"[^\d,.\-()]", "", regex=True)
s = s.str.replace(r"\(([\d.,]+)\)", r"-\1", regex=True)
s = s.str.replace(",", ".", regex=False)
return pd.to_numeric(s, errors='coerce')
def preprocess_df(df):
cols = detect_columns(df.columns)
# Date
date_col = cols.get('date')
df['date'] = pd.to_datetime(df[date_col], dayfirst=True, errors='coerce') if date_col else pd.NaT
# Description
desc_col = cols.get('description')
df['description'] = df[desc_col].fillna('N/A') if desc_col else 'N/A'
# Amount
ac = cols.get('amount_candidates', [])
if 'debit' in [c.lower() for c in ac] and 'credit' in [c.lower() for c in ac]:
credit = parse_amount_series(df[[c for c in ac if 'credit' in c.lower()][0]])
debit = parse_amount_series(df[[c for c in ac if 'debit' in c.lower()][0]])
df['amount'] = (credit.fillna(0) - debit.fillna(0))
elif ac:
df['amount'] = parse_amount_series(df[ac[0]])
else:
df['amount'] = pd.NA
# Currency detection
df['currency'] = df.apply(lambda row: 'EUR' if row.astype(str).str.contains('€').any() else None, axis=1)
# Clean
df = df.drop_duplicates()
df = df.dropna(subset=['date','amount'])
return df[['date','description','amount','currency']]
def test_preprocess_examples():
import pandas as pd
from preprocessing import preprocess_df
# Exemple 1
df1 = pd.DataFrame({'Date':['01/02/2021'],'Libellé':['Café'],'Débit':['5,00'],'Crédit':[None]})
out1 = preprocess_df(df1); assert out1['amount'].iloc[0] == -5.0
# Exemple 2
df2 = pd.DataFrame({'transaction_date':['2021-03-01'],'description':['Salaire'],'amount':['1500.00']})
out2 = preprocess_df(df2); assert out2['amount'].iloc[0] == 1500.0
# Exemple 3
df3 = pd.DataFrame({'posted':['01.04.2021'],'desc':['Remboursement'],'montant':['(20,50) €']})
out3 = preprocess_df(df3); assert out3['amount'].iloc[0] == -20.5
| Avant (exemples) | Après (schéma standard) |
| Date, Libellé, Débit, Crédit | date, description, amount (crédit – débit), currency |
| transaction_date, description, amount (virgule) | date, description, amount (float, point décimal) |
| posted, desc, montant (€ entre parenthèses) | date, description, amount (négatif), currency=EUR |
Comment intégrer ML, visualisations et LLM locaux ?
Pour construire une pipeline locale combinant ML, visualisations et LLM, commencez par extraire des features robustes: fréquence de paiement, montant moyen, écart-type, encodage des libellés (one‑hot ou embeddings), jours depuis dernière transaction, et ratio crédit/débit.
Pour la détection d’anomalies, j’identifie IsolationForest et LocalOutlierFactor comme solides points de départ. Pour la classification, RandomForest puis LightGBM si vous pouvez l’exécuter localement (plus rapide, meilleure gestion des features catégoriques).
Exemple d’entraînement IsolationForest, sauvegarde et prédiction (scikit-learn + joblib):
from sklearn.ensemble import IsolationForest
import pandas as pd
from joblib import dump, load
# Charger données pré-traitées avec features
X = pd.read_csv('features.csv').drop(columns=['id'])
# Entraîner
clf = IsolationForest(n_estimators=100, contamination=0.01, random_state=42)
clf.fit(X)
# Sauvegarder
dump(clf, 'isoforest.joblib')
# Charger et prédire (exemple)
clf = load('isoforest.joblib')
scores = clf.decision_function(X) # plus bas = anomalie
labels = clf.predict(X) # -1 anomalie, 1 normal
Intégration minimale Streamlit + Plotly: afficher série temporelle, bar par catégorie et liste d’anomalies.
import streamlit as st
import plotly.express as px
from joblib import load
import pandas as pd
clf = load('isoforest.joblib')
df = pd.read_csv('transactions.csv', parse_dates=['date'])
X = pd.read_csv('features.csv')
df['anomaly'] = clf.predict(X) == -1
st.title("Tableau financier local")
fig_ts = px.line(df.groupby('date').sum().reset_index(), x='date', y='amount', title='Timeseries')
st.plotly_chart(fig_ts)
fig_cat = px.bar(df.groupby('category').sum().reset_index(), x='category', y='amount', title='Par catégorie')
st.plotly_chart(fig_cat)
st.dataframe(df[df['anomaly']])
Pour combiner avec un LLM local (ex. Ollama), structurez un prompt clair: résumé agrégé + top N anomalies + questions spécifiques. Toujours anonymiser et agréger avant d’envoyer.
- Règles d’anonymisation: Masquer les PII (noms, IBAN), remplacer par tokens génériques, agrégation par catégorie/dates.
- Règles d’usage: Limiter texte envoyé, logger les prompts localement, revues humaines périodiques.
Exemple d’appel HTTP local vers Ollama (Python requests) et template de prompt:
import requests, json
prompt = """
Résumé: Total mois=12000€, Montant moyen=45€, Ecarts significatifs sur catégorie 'Télécoms'.
Top anomalies: 1) 2026-03-12 - 1200€ - 'Virement X' 2) 2026-03-20 - 950€ - 'Paiement Y'
Consignes: Expliquer en langage clair, proposer 3 hypothèses et prochaines actions.
"""
resp = requests.post('http://localhost:11434/api/generate', json={
"model":"your-model",
"prompt": prompt,
"max_tokens": 400
})
print(resp.json())
Tableau comparatif des rôles et métriques à suivre:
| Composant | Rôle | Métriques |
| Modèles ML | Détecter anomalies et classer transactions | Precision/Recall, FPR, taux de détection (recall), AUC |
| LLM local | Transformer résultats en langage clair, expliquer et prioriser | Latence (ms), qualité d’explication (revue humaine), taux d’humain-in-the-loop |
| Visualisations | Explorer, valider et prioriser alertes | Temps de rafraîchissement, interactivité, taux d’usage |
Surveillez en continu précision/recall pour la classification, taux de détection et faux positifs pour l’anomalie, ainsi que la latence locale du pipeline ML+LLM.
Prêt à analyser vos finances localement et en toute confidentialité ?
Un analyste financier privé local combine preprocessing robuste, modèles ML adaptés et un LLM local pour produire des insights compréhensibles—le tout sans exposer vos données au cloud. La clé : normaliser tôt, modulariser l’architecture, et appliquer des mesures de sécurité simples (chiffrement, backups). En suivant cette approche vous gagnez en confidentialité, en contrôle opérationnel et en réactivité : bénéfice direct pour vos finances et votre tranquillité d’esprit.
FAQ
A propos de l’auteur
Franck Scandolera — expert & formateur en Tracking avancé server-side, Analytics Engineering, Automatisation No/Low Code (n8n) et intégration d’IA en entreprise. Responsable de l’agence webAnalyste et de l’organisme de formation Formations Analytics. J’accompagne des clients tels que Logis Hôtel, Yelloh Village, BazarChic, Fédération Française de Football et Texdecor. Disponible pour aider les entreprises — contactez moi.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
- Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
- Data Analyst & Analytics engineering : tracking avancé (GTM server, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
- Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
- Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.






