La dernière étape : agrégation multi-source avec fallback automatique, backtesting de stratégies, gestion de portefeuille, forecasting ML, et l'architecture complète d'un MCP server finance de production.
Un serveur de production ne peut pas dépendre d'un seul provider. Yahoo Finance peut être rate-limité, Binance peut être down, et SEC EDGAR peut être lent un jour de filing massif. La solution : une chaîne de providers avec fallback automatique.
# providers/aggregator.py — Fallback chain class AggregatedProvider: def __init__(self, providers: list[MarketDataProvider]): self.providers = providers # Ordonnés par priorité async def get_quote(self, ticker: str) -> dict: errors = [] for provider in self.providers: try: result = await provider.get_quote(ticker) result["source"] = provider.name return result except Exception as e: errors.append(f"{provider.name}: {e}") logger.warning(f"Provider {provider.name} failed for {ticker}: {e}") continue # Tous les providers ont échoué raise AllProvidersFailedError(ticker, errors) # Initialisation aggregator = AggregatedProvider([ YahooProvider(), # Priorité 1 : gratuit, large couverture PolygonProvider(), # Priorité 2 : payant, plus fiable AlphaVantageProvider(), # Priorité 3 : fallback ])
Mieux que le fallback linéaire : router vers le bon provider selon l'asset class :
| Asset class | Provider primaire | Fallback | Détection |
|---|---|---|---|
| Actions US | Yahoo Finance | Polygon | Ticker 1-5 lettres majuscules |
| ETFs | Yahoo Finance | IEX | Liste ETF connue (SPY, QQQ...) |
| Crypto | Binance | CoinGecko | Suffixe -USD ou paire connue |
| Forex | Yahoo (EURUSD=X) | OANDA | Pattern XXX/YYY ou =X |
| Indices | Yahoo (^GSPC) | — | Préfixe ^ |
| Commodities | Yahoo (GC=F) | FRED | Suffixe =F |
# Smart routing def get_provider_chain(ticker: str) -> list[MarketDataProvider]: if ticker.endswith("-USD") or ticker in KNOWN_CRYPTO: return [binance_provider, coingecko_provider] if ticker.startswith("^"): return [yahoo_provider] if ticker.endswith("=X"): return [yahoo_provider, oanda_provider] # Default: actions US return [yahoo_provider, polygon_provider, alphavantage_provider]
Pour la crypto, utilisez l'API Binance directement. Yahoo Finance ajoute un délai de 15-60 minutes sur les prix crypto, ce qui est inacceptable pour un marché 24/7. L'API publique Binance est gratuite, rapide (~50ms), et ne nécessite pas de clé API pour les données de marché.
Un outil de backtest via MCP permet au LLM de valider une hypothèse de trading en la testant sur données historiques. L'outil prend une stratégie en entrée et retourne des métriques de performance :
BACKTEST_TOOL = Tool(
name="RunBacktest",
description="""Backtest a trading strategy on historical data.
Takes entry/exit conditions and returns performance metrics.
Metrics returned: total_return_pct, max_drawdown_pct, sharpe_ratio,
win_rate_pct, profit_factor, avg_trade_pct, total_trades, best/worst_trade.
Example strategy:
entry: 'rsi_14 < 30 AND ema_20_slope > 0'
exit: 'rsi_14 > 70 OR trailing_stop_pct(-3)'
period: '2y'
universe: ['AAPL', 'MSFT', 'GOOGL']""",
inputSchema={
"type": "object",
"properties": {
"entry_condition": {"type": "string"},
"exit_condition": {"type": "string"},
"period": {"type": "string", "enum": ["6m","1y","2y","5y"]},
"universe": {"type": "array", "items": {"type": "string"}},
"position_size_pct": {"type": "number", "default": 10}
},
"required": ["entry_condition", "exit_condition", "period"]
}
)
Le résultat donne au LLM tout ce qu'il faut pour évaluer la stratégie :
# Résultat du backtest { "period": "2024-01-01 to 2025-12-31", "total_return_pct": 34.2, "annualized_return_pct": 16.1, "max_drawdown_pct": -8.7, "sharpe_ratio": 1.42, "sortino_ratio": 1.89, "win_rate_pct": 62.5, "profit_factor": 2.1, "total_trades": 48, "avg_trade_pct": 2.8, "avg_hold_days": 12, "best_trade": {"ticker": "NVDA", "return_pct": 18.4}, "worst_trade": {"ticker": "INTC", "return_pct": -6.2}, "benchmark_return_pct": 28.1, # SPY sur la même période "alpha_pct": 6.1 }
Le backtest doit toujours inclure le benchmark (SPY) sur la même période. Un rendement de +34% semble excellent, mais si SPY a fait +28%, l'alpha réel n'est que de 6 points. Sans benchmark, le LLM (et l'utilisateur) peuvent surestimer la stratégie. Voir notre article Backtesting Honnête pour les pièges classiques.
Un MCP finance avancé peut exposer des outils de gestion de portefeuille : optimisation de sizing, calcul de VaR, et suivi des positions :
Taille optimale de chaque position selon corrélation, volatilité, et contraintes de risque.
Value at Risk : perte maximale à 95% de confiance sur 1j/5j/1m. Monte Carlo ou historique.
Corrélation entre N tickers pour détecter les clusters de risque dans le portefeuille.
Simuler l'impact de scénarios (VIX à 40, -10% S&P, taux +100bps) sur le portefeuille.
# Outil OptimizeSizing OPTIMIZE_SIZING_TOOL = Tool( name="OptimizeSizing", description="""Optimize position sizes for a portfolio of tickers. Uses correlation matrix, ATR-based volatility, and regime to suggest optimal allocation percentages that maximize diversification while respecting risk constraints. Constraints: max_per_position (default 15%), max_correlation (default 0.7), max_sector_exposure (default 30%).""", inputSchema={ "type": "object", "properties": { "tickers": {"type": "array", "items": {"type": "string"}}, "portfolio_size": {"type": "number"}, "constraints": { "type": "object", "properties": { "max_per_position_pct": {"type": "number", "default": 15}, "max_correlation": {"type": "number", "default": 0.7}, "max_sector_exposure_pct": {"type": "number", "default": 30} } } }, "required": ["tickers", "portfolio_size"] } )
Un MCP server peut intégrer des modèles de machine learning comme TimesFM (Google) pour le forecasting de séries temporelles. Le LLM n'exécute pas le ML — il appelle un outil qui exécute le modèle et retourne les prédictions :
FORECAST_TOOL = Tool(
name="ForecastPrice",
description="""Forecast future price using TimesFM 2.0 (time-series foundation model).
Returns probabilistic forecast with confidence intervals.
IMPORTANT: Direction accuracy is ~44% (worse than random) for individual stocks.
Use confidence intervals as 'probabilistic support/resistance zones', not as
directional signals. ATR/volatility forecasts are more reliable (~70% accuracy).
Output includes: point forecast, q10/q50/q90, predicted_direction, historical_accuracy.""",
inputSchema={
"type": "object",
"properties": {
"ticker": {"type": "string"},
"horizon": {"type": "integer", "description": "Days ahead (1-30)", "default": 5},
"metric": {"type": "string", "enum": ["close", "atr", "volume"], "default": "close"}
},
"required": ["ticker"]
}
)
La description de l'outil dit explicitement que la direction est à 44%. C'est volontaire. Si le LLM croit que le forecast est fiable, il va recommander des trades basés sur les prédictions. En étant honnête dans la description, le LLM utilisera les forecasts comme zones probabilistes, pas comme des signaux directionnels. C'est la différence entre un outil utile et un outil dangereux.
Le serveur MCP n'exécute pas le modèle ML directement — il appelle un service de forecast via HTTP (dans notre cas, un serveur TimesFM sur un GPU séparé). MCP sert de passerelle : le LLM appelle l'outil, le serveur MCP appelle le service ML, et retourne le résultat formaté. Le LLM n'a pas besoin de savoir qu'il y a un modèle Google derrière — il voit juste un outil ForecastPrice.
En assemblant tout ce qu'on a construit dans les 6 parties, voici l'architecture d'un MCP server finance de production :
| Couche | Composants | Partie |
|---|---|---|
| Transport | Caddy (TLS) → FastAPI (SSE + POST) | 2, 5 |
| Sécurité | Bearer auth → Rate limiter (client + upstream) | 4 |
| Cache | TTL cache en mémoire (15s → 24h par type) | 4 |
| MCP Core | Server + tool registry + dispatch + error handling | 2 |
| Outils | QueryData, RunScreener, GetMarketOverview, RunBacktest, OptimizeSizing, ForecastPrice | 3, 6 |
| Providers | Yahoo, Binance, SEC, FRED — avec fallback chain | 3, 6 |
| Services | TimesFM (forecast), portfolio engine | 6 |
| Infra | Docker, Nomad, healthcheck, JSON logs | 5 |
Avec l'architecture complète, un LLM connecté au serveur peut :
GetQuote (prix), QueryData (analyse détaillée), et GetMarketOverview (contexte). Avec ces trois outils, le LLM peut répondre à 80% des questions finance courantes. Les outils avancés (screener, backtest, portfolio) ajoutent de la profondeur mais ne sont pas nécessaires pour commencer.En 6 parties, on a construit un serveur MCP finance complet — du concept à la production. Récapitulatif :
MCP, architecture Host-Client-Server, les 3 primitives, pourquoi pour la finance.
FastAPI + mcp-python-sdk, premier outil en 200 lignes, transport SSE.
QueryData, RunScreener, GetMarketOverview. Providers interchangeables, calculs techniques.
Bearer tokens, rate limiting token bucket, cache TTL par type de donnée.
Docker multi-stage, Nomad, Caddy TLS, logs JSON, checklist production.
Multi-source fallback, backtest, portfolio, forecasting ML.