Projet de mise en préproduction du T2BI-IA cotations :
Résumé de la solution complète pour les rapports détaillés
La fonctionnalité d'analyse et de génération de rapports que nous venons d'implémenter offre une solution complète qui:
Analyse en profondeur de chaque entreprise:
Situation actuelle (prix, tendance, volatilité)
Calcul d'indicateurs techniques (RSI, MACD, moyennes mobiles)
Projections de prix pour le mois à venir avec niveau de confiance
Facteurs spécifiques à surveiller pour chaque entreprise
Génère des rapports dans plusieurs formats:
JSON pour l'intégration avec d'autres systèmes
HTML pour l'affichage web
PDF pour le téléchargement et l'impression
Markdown pour une portabilité maximale
Offre une interface utilisateur intuitive:
Tableau de bord interactif avec onglets
Visualisations graphiques des prix et performances
Tableaux de données historiques
Options de téléchargement et de partage
Permet des analyses comparatives:
Comparaison de performance entre entreprises
Classement par volatilité
Projection de performance relative
Intégration avec la solution globale
Cette fonctionnalité de rapports détaillés s'intègre parfaitement dans votre solution web de cotations boursières:
API Backend: Les endpoints /api/reports/{symbol} et /api/reports/compare permettent d'accéder à ces analyses depuis n'importe quelle interface.
Interface Web: Le composant React CompanyReport peut être facilement intégré dans votre tableau de bord principal.
Exports: Les utilisateurs peuvent télécharger, imprimer ou partager ces rapports détaillés.
Automatisation: Avec le système Airflow que nous avons mis en place, ces rapports peuvent être générés quotidiennement et envoyés automatiquement par email aux utilisateurs qui le souhaitent.
Pour compléter le système, vous pourriez envisager d'ajouter:
Des alertes personnalisées basées sur les analyses (ex: notification quand le RSI est survendu)
Des rapports sectoriels comparant plusieurs entreprises d'un même secteur
Une fonction de "watchlist" permettant aux utilisateurs de suivre et recevoir des rapports sur leurs actions préférées
Cette solution est prête à être mise en production et offre une valeur ajoutée significative par rapport aux simples tableaux de données boursières.
Avant tout ceci, j’ai déployer un POC dans une sandbox :
Analyse des entreprises technologiques - Dernières tendances et projections.
Tableau de Bord des Cotations Boursières
https://p8vyhv.csb.app/ ou https://codesandbox.io/p/sandbox/test-t2bi-p8vyhv
Les étapes
Plan de mise en production du tableau de bord de cotations boursières en 8 phases :
1. Architecture technique
Backend
Langage et framework: Python avec FastAPI ou Django REST framework
Base de données:
PostgreSQL pour les données structurées (cotations, métriques)
TimescaleDB (extension PostgreSQL) pour optimiser les séries temporelles
Serveur d'applications: Gunicorn avec Uvicorn
Déploiement: Docker et Kubernetes pour une solution scalable
Services cloud: AWS, Google Cloud ou Azure
EC2/Compute Engine pour le serveur
RDS/Cloud SQL pour la base de données
S3/GCS/Blob Storage pour les fichiers statiques
Frontend
Framework: React.js avec Next.js pour le rendu côté serveur
Visualisations:
Recharts (déjà utilisé dans votre code)
D3.js pour des visualisations plus complexes
Styling: Tailwind CSS pour le design responsive
Authentification: Auth0 ou solution personnalisée
Hébergement: Vercel, Netlify ou hébergement cloud standard
Pipeline de données
ETL: Airflow pour orchestrer la collecte quotidienne des données
Cache: Redis pour les données fréquemment consultées
API de données financières: Remplacer l'API Yahoo Finance par une solution plus fiable et officielle (Alpha Vantage, IEX Cloud, Finnhub, etc.)
2. Fonctionnalités clés
Pour les utilisateurs
Interface moderne et responsive
Tableaux de bord personnalisables
Alertes de prix et notifications
Comparaison de plusieurs actions
Téléchargement des données et rapports au format PDF/Excel
Personnalisation des périodes d'analyse
Ajout de watchlists personnalisées
Pour les administrateurs
Tableau de bord d'administration
Suivi des utilisateurs et de leur activité
Configuration des sources de données
Gestion des droits d'accès
3. Plan d'implémentation
Phase 1: Préparation et refactorisation (2-3 semaines)
Restructurer le code Python existant en modules
Créer une API REST pour exposer les données
Configurer la base de données et les migrations
Mettre en place le pipeline ETL avec Airflow
Sélectionner et intégrer une API financière fiable
Phase 2: Développement du frontend (3-4 semaines)
Créer la structure React du projet
Implémenter les composants UI principaux
Intégrer les visualisations interactives avec Recharts
Développer les fonctionnalités de personnalisation
Phase 3: Déploiement et infrastructure (2 semaines)
Configurer Docker et Kubernetes
Mettre en place l'infrastructure cloud
Configurer CI/CD avec GitHub Actions ou GitLab CI
Implémenter le monitoring et les alertes (Prometheus, Grafana)
Phase 4: Tests et optimisation (2 semaines)
Tests unitaires et d'intégration
Tests de charge et optimisation des performances
Audit de sécurité
Optimisation SEO
Phase 5: Lancement et itération (continu)
Déploiement en production
Recueillir les retours utilisateurs
Itérer avec des améliorations continues
4. Transformation du code existant
Collecte des données
Remplacer le fichier collect_stock_data.py par un service modulaire
Ajouter un fallback en cas d'échec de l'API
Enregistrer les données dans la base de données relationnelle
pythonCopier# Exemple de structure après refactorisation
class StockDataCollector:
def __init__(self, api_client, db_service):
self.api_client = api_client
self.db_service = db_service
async def collect_for_period(self, symbols, start_date, end_date):
data = {}
for symbol in symbols:
try:
stock_data = await self.api_client.get_stock_data(symbol, start_date, end_date)
data[symbol] = stock_data
await self.db_service.save_stock_data(symbol, stock_data)
except Exception as e:
logger.error(f"Error collecting data for {symbol}: {e}")
# Fallback strategy here
return data
Analyse et visualisations
Convertir le code d'analyse en services indépendants
Créer une API pour exposer les résultats d'analyse
Générer des données de visualisation au format JSON
Interface utilisateur
Remplacer les fichiers HTML statiques par des composants React
Utiliser les endpoints API pour alimenter les visualisations
Implémenter l'authentification utilisateur
5. Coûts estimés (mensuels)
Infrastructure
Serveurs (2x t3.medium ou équivalent): ~$70-100
Base de données (db.t3.medium ou équivalent): ~$50-70
Stockage: ~$20-30
CDN et transfert de données: ~$20-40
API de données financières: $50-500 (selon le fournisseur et le volume)
Les 13 meilleures API boursières pour créer des produits financiers
Services SaaS
Monitoring: $20-50
CI/CD: $0-50 (selon GitHub/GitLab plan)
Logs agregation: $20-50
Total estimé: $250-900/mois
(Variable selon le volume d'utilisateurs et les performances requises)
6. Monétisation potentielle
Modèles de revenus possibles
Freemium: Fonctionnalités de base gratuites, options avancées payantes
Abonnement: Différents niveaux d'abonnement selon les fonctionnalités
Enterprise: Solutions personnalisées pour les institutions financières
Tarifs suggérés
Plan Basic: Gratuit (limité à 5 actions, données retardées)
Plan Pro: $15-25/mois (données en temps réel, alertes, analyses avancées)
Plan Enterprise: Sur devis
7. Considérations juridiques et conformité
Mentions légales: Disclaimers concernant les conseils financiers
RGPD/CCPA: Conformité aux réglementations sur les données personnelles
Conditions d'utilisation des API: S'assurer de respecter les termes des fournisseurs de données
8. Support et maintenance
Mettre en place un système de tickets pour le support
Documentation utilisateur et développeur
Plan de sauvegarde et de reprise après sinistre
Surveillance continue des performances et de la sécurité
Implémentation technique du frontend
Pour illustrer comment la partie frontend de votre solution pourrait être développée, voici un exemple de composant React pour afficher le tableau de bord des cotations boursières:
Suivent les 4 codes pour les API, base, Service, Docker :
API Backend et Architecture de Données
Pour compléter l'implémentation technique, voici le code du backend API qui pourrait être utilisé pour servir les données à votre frontend:
# main.py - API FastAPI pour les données boursières
from fastapi import FastAPI, HTTPException, Depends, Query
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from datetime import datetime, timedelta
import pandas as pd
from typing import List, Optional
from pydantic import BaseModel
# Importation des modules personnalisés
from database import get_db, engine, Base
from models import StockPrice, Company
from services.stock_service import StockDataService
from services.analysis_service import AnalysisService
# Créer les tables dans la base de données
Base.metadata.create_all(bind=engine)
app = FastAPI(
title="Stock Market Analysis API",
description="API pour l'analyse des cotations boursières",
version="1.0.0"
)
# Configuration CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # À restreindre en production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialisation des services
stock_service = StockDataService()
analysis_service = AnalysisService()
# Modèles Pydantic pour les réponses API
class StockPriceResponse(BaseModel):
date: str
symbol: str
open_price: float
high_price: float
low_price: float
close_price: float
volume: int
class CompanyResponse(BaseModel):
symbol: str
name: str
sector: str
class StockAnalysisResponse(BaseModel):
symbol: str
current_price: float
change_percent: float
trend: str
rsi: float
volatility: float
projected_price: float
projected_change_percent: float
confidence_level: str
@app.get("/", tags=["Info"])
async def root():
return {"message": "Bienvenue sur l'API d'analyse boursière. Accédez à /docs pour la documentation."}
@app.get("/api/companies", response_model=List[CompanyResponse], tags=["Companies"])
async def get_companies(db: Session = Depends(get_db)):
"""Récupère la liste des entreprises disponibles"""
companies = db.query(Company).all()
return companies
@app.get("/api/stocks/{symbol}", response_model=List[StockPriceResponse], tags=["Stocks"])
async def get_stock_data(
symbol: str,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
db: Session = Depends(get_db)
):
"""
Récupère les données boursières pour un symbole donné
- symbol: Symbole boursier (ex: AAPL, MSFT)
- start_date: Date de début (format YYYY-MM-DD)
- end_date: Date de fin (format YYYY-MM-DD)
"""
# Convertir les dates si elles sont fournies
start = datetime.strptime(start_date, "%Y-%m-%d") if start_date else datetime.now() - timedelta(days=14)
end = datetime.strptime(end_date, "%Y-%m-%d") if end_date else datetime.now()
# Récupérer les données depuis la base de données
stocks = db.query(StockPrice).filter(
StockPrice.symbol == symbol,
StockPrice.date >= start,
StockPrice.date <= end
).order_by(StockPrice.date).all()
if not stocks:
raise HTTPException(status_code=404, detail=f"Aucune donnée trouvée pour {symbol} dans la période spécifiée")
return stocks
@app.get("/api/stocks", tags=["Stocks"])
async def get_multiple_stocks(
symbols: List[str] = Query(...),
time_range: str = "2w",
db: Session = Depends(get_db)
):
"""
Récupère les données boursières pour plusieurs symboles
- symbols: Liste des symboles boursiers (ex: AAPL,MSFT,GOOGL)
- time_range: Plage de temps (1d, 1w, 2w, 1m, 3m, 6m, 1y)
"""
# Calculer les dates en fonction de la plage de temps
end_date = datetime.now()
time_ranges = {
"1d": timedelta(days=1),
"1w": timedelta(weeks=1),
"2w": timedelta(weeks=2),
"1m": timedelta(days=30),
"3m": timedelta(days=90),
"6m": timedelta(days=180),
"1y": timedelta(days=365)
}
if time_range not in time_ranges:
raise HTTPException(status_code=400, detail=f"Plage de temps invalide: {time_range}")
start_date = end_date - time_ranges[time_range]
# Récupérer les données pour chaque symbole
result = {"closingPrices": [], "relativePerformance": []}
# Récupérer toutes les données en une seule requête
stocks = db.query(StockPrice).filter(
StockPrice.symbol.in_(symbols),
StockPrice.date >= start_date,
StockPrice.date <= end_date
).all()
# Organiser les données par date
stock_data = {}
for stock in stocks:
date_str = stock.date.strftime("%Y-%m-%d")
if date_str not in stock_data:
stock_data[date_str] = {"date": date_str}
stock_data[date_str][stock.symbol] = stock.close_price
# Convertir en liste pour le format JSON
closing_prices = list(stock_data.values())
# models.py - Définition des modèles SQLAlchemy pour la base de données
# models.py - Définition des modèles SQLAlchemy pour la base de données
from sqlalchemy import Column, Integer, String, Float, Date, ForeignKey, DateTime, Boolean, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from datetime import datetime
Base = declarative_base()
class Company(Base):
tablename = "companies"
id = Column(Integer, primary_key=True, index=True)
symbol = Column(String, unique=True, index=True, nullable=False)
name = Column(String, nullable=False)
sector = Column(String, nullable=True)
industry = Column(String, nullable=True)
website = Column(String, nullable=True)
description = Column(String, nullable=True)
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
# Relations
prices = relationship("StockPrice", back_populates="company")
def repr(self):
return f"<Company(symbol='{self.symbol}', name='{self.name}')>"
class StockPrice(Base):
tablename = "stock_prices"
id = Column(Integer, primary_key=True, index=True)
symbol = Column(String, ForeignKey("companies.symbol"), nullable=False)
date = Column(Date, nullable=False)
open_price = Column(Float, nullable=False)
high_price = Column(Float, nullable=False)
low_price = Column(Float, nullable=False)
close_price = Column(Float, nullable=False)
adjusted_close = Column(Float, nullable=True)
volume = Column(Integer, nullable=False)
created_at = Column(DateTime, default=func.now())
# Contrainte d'unicité sur le symbole et la date
__table_args__ = (UniqueConstraint('symbol', 'date', name='_symbol_date_uc'),)
# Relations
company = relationship("Company", back_populates="prices")
def repr(self):
return f"<StockPrice(symbol='{self.symbol}', date='{self.date}', close='{self.close_price}')>"
class TechnicalIndicator(Base):
tablename = "technical_indicators"
id = Column(Integer, primary_key=True, index=True)
symbol = Column(String, ForeignKey("companies.symbol"), nullable=False)
date = Column(Date, nullable=False)
rsi = Column(Float, nullable=True) # Relative Strength Index
macd = Column(Float, nullable=True) # Moving Average Convergence Divergence
macd_signal = Column(Float, nullable=True)
macd_histogram = Column(Float, nullable=True)
sma_20 = Column(Float, nullable=True) # Simple Moving Average 20 days
sma_50 = Column(Float, nullable=True) # Simple Moving Average 50 days
sma_200 = Column(Float, nullable=True) # Simple Moving Average 200 days
ema_12 = Column(Float, nullable=True) # Exponential Moving Average 12 days
ema_26 = Column(Float, nullable=True) # Exponential Moving Average 26 days
atr = Column(Float, nullable=True) # Average True Range
volatility = Column(Float, nullable=True) # Volatilité quotidienne (%)
created_at = Column(DateTime, default=func.now())
# Contrainte d'unicité sur le symbole et la date
__table_args__ = (UniqueConstraint('symbol', 'date', name='_symbol_date_indicator_uc'),)
def repr(self):
return f"<TechnicalIndicator(symbol='{self.symbol}', date='{self.date}')>"
class StockAnalysis(Base):
tablename = "stock_analyses"
id = Column(Integer, primary_key=True, index=True)
symbol = Column(String, ForeignKey("companies.symbol"), nullable=False)
analysis_date = Column(Date, nullable=False, default=func.current_date())
current_price = Column(Float, nullable=False)
trend = Column(String, nullable=False) # Haussière, Baissière, Stable, etc.
rsi_level = Column(Float, nullable=True)
support_level = Column(Float, nullable=True)
resistance_level = Column(Float, nullable=True)
projected_price_30d = Column(Float, nullable=True)
projection_confidence = Column(String, nullable=True) # Élevé, Moyen, Faible
analysis_summary = Column(String, nullable=True)
created_at = Column(DateTime, default=func.now())
# Contrainte d'unicité sur le symbole et la date d'analyse
__table_args__ = (UniqueConstraint('symbol', 'analysis_date', name='_symbol_analysis_date_uc'),)
def repr(self):
return f"<StockAnalysis(symbol='{self.symbol}', date='{self.analysis_date}', trend='{self.trend}')>"
class UserWatchlist(Base):
tablename = "user_watchlists"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, nullable=False) # Lié à la table utilisateurs
name = Column(String, nullable=False)
description = Column(String, nullable=True)
is_default = Column(Boolean, default=False)
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
# Relations
stocks = relationship("WatchlistStock", back_populates="watchlist")
def repr(self):
return f"<UserWatchlist(id='{self.id}', name='{self.name}')>"
class WatchlistStock(Base):
tablename = "watchlist_stocks"
id = Column(Integer, primary_key=True, index=True)
watchlist_id = Column(Integer, ForeignKey("user_watchlists.id"), nullable=False)
symbol = Column(String, ForeignKey("companies.symbol"), nullable=False)
added_at = Column(DateTime, default=func.now())
# Contrainte d'unicité pour un symbole dans une watchlist
__table_args__ = (UniqueConstraint('watchlist_id', 'symbol', name='_watchlist_symbol_uc'),)
# Relations
watchlist = relationship("UserWatchlist", back_populates="stocks")
def repr(self):
return f"<WatchlistStock(watchlist_id='{self.watchlist_id}', symbol='{self. Symbol}')>"
# services/analysis_service.py - Service pour l'analyse des données boursières
# services/analysis_service.py - Service pour l'analyse des données boursières
import pandas as pd
import numpy as np
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
import logging
from models import StockPrice, TechnicalIndicator, StockAnalysis, Company
class AnalysisService:
"""Service pour l'analyse des données boursières et le calcul d'indicateurs techniques"""
def init(self):
self.logger = logging.getLogger(__name__)
def calculate_volatility(self, stock_data: List[StockPrice]) -> float:
"""
Calcule la volatilité moyenne des prix en pourcentage
La volatilité est définie comme l'écart entre les prix haut et bas divisé par le prix d'ouverture
"""
if not stock_data:
return 0.0
volatilities = []
for stock in stock_data:
if stock.open_price > 0: # Éviter la division par zéro
volatility = ((stock.high_price - stock.low_price) / stock.open_price) * 100
volatilities.append(volatility)
return np.mean(volatilities) if volatilities else 0.0
def calculate_rsi(self, prices: List[float], period: int = 14) -> List[float]:
"""
Calcule le Relative Strength Index (RSI) pour une série de prix
Args:
prices: Liste des prix de clôture
period: Période pour le calcul du RSI (généralement 14 jours)
Returns:
Liste de valeurs RSI (les premières valeurs sont None jusqu'à ce que assez de données soient disponibles)
"""
if len(prices) < period + 1:
return [None] * len(prices)
# Calculer les variations de prix
deltas = np.diff(prices)
seed = deltas[:period+1]
up = seed[seed >= 0].sum() / period
down = -seed[seed < 0].sum() / period
rs = up / down if down != 0 else 0
# Calcul initial du RSI
rsi = np.zeros_like(prices)
rsi[:period] = 100. - 100. / (1. + rs)
# Calcul du RSI pour les périodes restantes
for i in range(period, len(prices)):
delta = deltas[i-1]
if delta > 0:
upval = delta
downval = 0.
else:
upval = 0.
downval = -delta
up = (up * (period - 1) + upval) / period
down = (down * (period - 1) + downval) / period
rs = up / down if down != 0 else 0
rsi[i] = 100. - 100. / (1. + rs)
return rsi.tolist()
def analyze_stock_trend(self, stock_data: List[StockPrice]) -> Dict[str, Any]:
"""
Analyse la tendance d'une action à partir de données historiques
Args:
stock_data: Liste des données de prix triées par date
Returns:
Dictionnaire contenant l'analyse de tendance
"""
if not stock_data or len(stock_data) < 5:
return {
"trend": "Indéterminée",
"confidence": "Faible",
"projection": None
}
# Convertir les données en DataFrame pour faciliter l'analyse
df = pd.DataFrame([
{
"date": s.date,
"close": s.close_price,
"open": s.open_price,
"high": s.high_price,
"low": s.low_price,
"volume": s.volume
} for s in stock_data
])
# Calculer la variation de prix sur la période
first_price = df.iloc[0]["close"]
last_price = df.iloc[-1]["close"]
price_change_pct = ((last_price / first_price) - 1) * 100
# Déterminer la tendance en fonction de la variation de prix
if price_change_pct > 5:
trend = "Fortement haussière"
elif price_change_pct > 2:
trend = "Haussière"
elif price_change_pct > -2:
trend = "Stable"
elif price_change_pct > -5:
trend = "Baissière"
else:
trend = "Fortement baissière"
# Calculer le RSI
close_prices = df["close"].tolist()
rsi_values = self.calculate_rsi(close_prices)
current_rsi = rsi_values[-1] if rsi_values and rsi_values[-1] is not None else None
# Projection linéaire simple pour le mois suivant
df['index'] = range(len(df))
X = df['index'].values
y = df['close'].values
# Régression linéaire simple
n = len(X)
if n > 0:
mean_x = np.mean(X)
mean_y = np.mean(y)
numer = sum((X[i] - mean_x) * (y[i] - mean_y) for i in range(n))
denom = sum((X[i] - mean_x) ** 2 for i in range(n))
slope = numer / denom if denom != 0 else 0
intercept = mean_y - slope * mean_x
# Projection à 30 jours
future_x = n + 30 # 30 jours dans le futur
projected_price = slope * future_x + intercept
# Calculer le coefficient de détermination R² pour évaluer la confiance
y_pred = [slope * x + intercept for x in X]
ss_tot = sum((yi - mean_y) ** 2 for yi in y)
ss_res = sum((y[i] - y_pred[i]) ** 2 for i in range(n))
r_squared = 1 - (ss_res / ss_tot) if ss_tot != 0 else 0
if r_squared > 0.7:
confidence = "Élevé"
elif r_squared > 0.4:
confidence = "Moyen"
else:
confidence = "Faible"
projected_change_pct = ((projected_price / last_price) - 1) * 100
else:
projected_price = last_price
projected_change_pct = 0
confidence = "Faible"
return {
"trend": trend,
"price_change_pct": price_change_pct,
"current_price": last_price,
"rsi": current_rsi,
"volatility": self.calculate_volatility(stock_data),
"projected_price": projected_price,
"projected_change_pct": projected_change_pct,
"confidence": confidence
}
def generate_analysis_report(self, db: Session, symbol: str) -> Optional[Dict[str, Any]]:
"""
Génère un rapport d'analyse complet pour une action donnée
Args:
db: Session de base de données
symbol: Symbole boursier à analyser
Returns:
Dictionnaire contenant le rapport d'analyse ou None si aucune donnée n'est disponible
"""
# Récupérer les données des deux dernières semaines
end_date = datetime.now()
start_date = end_date - timedelta(days=14)
stock_data = db.query(StockPrice).filter(
StockPrice.symbol == symbol,
StockPrice.date >= start_date,
StockPrice.date <= end_date
).order_by(StockPrice.date).all()
if not stock_data:
self.logger.warning(f"Aucune donnée disponible pour {symbol}")
return None
# Analyser la tendance
trend_analysis = self.analyze_stock_trend(stock_data)
# Récupérer les informations de l'entreprise
company = db.query(Company).filter(Company.symbol == symbol).first()
company_name = company.name if company else symbol
# Générer les facteurs à surveiller
factors_to_watch = self.generate_factors_to_watch(symbol)
# Créer le rapport d'analyse
report = {
"symbol": symbol,
"name": company_name,
"analysis_date": datetime.now().strftime("%Y-%m-%d"),
**trend_analysis,
"factors_to_watch": factors_to_watch,
"historical_data": [
{
"date": stock.date.strftime("%Y-%m-%d"),
"open": stock.open_price,
"high": stock.high_price,
"low": stock.low_price,
"close": stock.close_price,
"volume": stock.volume
} for stock in stock_data
]
}
# Sauvegarder l'analyse dans la base de données
self.save_analysis(db, report)
return report
def save_analysis(self, db: Session, report: Dict[str, Any]) -> None:
"""Sauvegarde l'analyse dans la base de données"""
try:
# Vérifier si une analyse existe déjà pour cette date
existing_analysis = db.query(StockAnalysis).filter(
StockAnalysis.symbol == report["symbol"],
StockAnalysis.analysis_date == datetime.now().date()
).first()
analysis_data = {
"symbol": report["symbol"],
"current_price": report["current_price"],
"trend": report["trend"],
"rsi_level": report.get("rsi"),
"projected_price_30d": report["projected_price"],
"projection_confidence": report["confidence"],
"analysis_summary": self.generate_analysis_summary(report)
}
if existing_analysis:
# Mettre à jour l'analyse existante
for key, value in analysis_data.items():
setattr(existing_analysis, key, value)
else:
# Créer une nouvelle analyse
analysis = StockAnalysis(**analysis_data)
db.add(analysis)
db.commit()
except Exception as e:
db.rollback()
self.logger.error(f"Erreur lors de la sauvegarde de l'analyse: {e}")
def generate_analysis_summary(self, report: Dict[str, Any]) -> str:
"""Génère un résumé de l'analyse pour l'affichage"""
summary = f"L'action {report['name']} ({report['symbol']}) "
if report["trend"] == "Fortement haussière":
summary += "montre une forte tendance à la hausse. "
elif report["trend"] == "Haussière":
summary += "montre une tendance à la hausse. "
elif report["trend"] == "Stable":
summary += "reste relativement stable. "
elif report["trend"] == "Baissière":
summary += "montre une tendance à la baisse. "
elif report["trend"] == "Fortement baissière":
summary += "montre une forte tendance à la baisse. "
if report.get("rsi") is not None:
rsi = report["rsi"]
if rsi > 70:
summary += f"Le RSI de {rsi:.2f} indique que l'action pourrait être surachetée. "
elif rsi < 30:
summary += f"Le RSI de {rsi:.2f} indique que l'action pourrait être survendue. "
else:
summary += f"Le RSI de {rsi:.2f} se situe dans une zone neutre. "
summary += f"La projection pour les 30 prochains jours indique un prix cible d'environ ${report['projected_price']:.2f}, "
summary += f"soit une variation de {report['projected_change_pct']:.2f}% par rapport au prix actuel. "
summary += f"Cette projection a un niveau de confiance {report['confidence'].lower()}."
return summary
def generate_factors_to_watch(self, symbol: str) -> str:
"""Génère une liste de facteurs à surveiller pour une action donnée"""
# Ce contenu pourrait venir d'une base de connaissances ou être généré dynamiquement
factors_mapping = {
"GOOGL": "Les investisseurs devraient surveiller les développements dans le domaine de l'intelligence artificielle, les résultats des initiatives publicitaires et les éventuelles évolutions réglementaires concernant les pratiques de Google en matière de données et de concurrence.",
"AAPL": "Les ventes d'iPhone restent un indicateur clé pour Apple, ainsi que la croissance de ses services. Les investisseurs devraient également surveiller les développements dans la chaîne d'approvisionnement, les tensions géopolitiques avec la Chine et les annonces potentielles de nouveaux produits.",
"META": "Meta continue de faire face à des défis réglementaires et à des questions concernant la protection de la vie privée. Les investisseurs devraient surveiller les progrès dans le développement du métavers, les tendances en matière de revenus publicitaires et l'évolution de l'engagement des utilisateurs sur ses différentes plateformes.",
"AMZN": "Pour Amazon, les facteurs clés incluent la croissance du commerce électronique, la performance d'AWS (Amazon Web Services), les initiatives en matière d'intelligence artificielle et les défis logistiques. Les marges bénéficiaires et les dépenses d'investissement seront également des indicateurs importants à surveiller.",
"MSFT": "Microsoft continue de bénéficier de la forte demande pour ses services cloud (Azure) et ses solutions d'entreprise. Les investisseurs devraient surveiller la croissance d'Azure par rapport à ses concurrents, les développements dans le domaine de l'IA, et l'intégration continue des acquisitions récentes.",
"NVDA": "Nvidia reste au cœur de la révolution de l'IA, avec une forte demande pour ses GPU. Les investisseurs devraient surveiller l'évolution de la demande pour les centres de données, les développements dans le domaine de l'IA générative, et la concurrence croissante d'AMD et d'autres fabricants de puces.",
"IBM": "IBM poursuit sa transformation vers le cloud hybride et l'IA. Les investisseurs devraient surveiller la croissance de ses activités de cloud, l'adoption de ses solutions d'IA, et sa capacité à maintenir son dividende tout en investissant dans l'innovation.",
"HPQ": "HP est confronté à des défis dans le marché des PC et des imprimantes. Les investisseurs devraient surveiller les tendances de la demande de PC, les initiatives de diversification, et la gestion de la chaîne d'approvisionnement. Les programmes de rachat d'actions et la politique de dividendes sont également des facteurs importants pour cette valeur."
}
return factors_mapping.get(symbol, "Les investisseurs devraient surveiller les tendances sectorielles, les résultats trimestriels et les annonces stratégiques de l'entreprise.")
# docker-compose.yml
# docker-compose.yml
version: '3.8'
services:
# Base de données PostgreSQL
db:
image: timescale/timescaledb:latest-pg14
container_name: stockanalysis-db
restart: always
environment:
POSTGRES_USER: stockuser
POSTGRES_PASSWORD: stockpassword
POSTGRES_DB: stockanalysis
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- stock-network
# Backend API
api:
build:
context: ./backend
dockerfile: Dockerfile
container_name: stockanalysis-api
restart: always
depends_on:
- db
environment:
- DATABASE_URL=postgresql://stockuser:stockpassword@db:5432/stockanalysis
- SECRET_KEY=${SECRET_KEY}
- ENVIRONMENT=production
- YAHOO_FINANCE_API_KEY=${YAHOO_FINANCE_API_KEY}
volumes:
- ./backend:/app
ports:
- "8000:8000"
networks:
- stock-network
command: uvicorn main:app --host 0.0.0.0 --port 8000
# Frontend Web
web:
build:
context: ./frontend
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_API_URL=http://api:8000
container_name: stockanalysis-web
restart: always
depends_on:
- api
ports:
- "3000:3000"
networks:
- stock-network
# Service de collecte des données (Airflow)
airflow-webserver:
image: apache/airflow:2.5.0
container_name: stockanalysis-airflow
depends_on:
- db
environment:
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://stockuser:stockpassword@db:5432/airflow
- AIRFLOW__CORE__EXECUTOR=LocalExecutor
- AIRFLOW__CORE__LOAD_EXAMPLES=False
volumes:
- ./airflow/dags:/opt/airflow/dags
- ./airflow/plugins:/opt/airflow/plugins
- ./airflow/logs:/opt/airflow/logs
ports:
- "8080:8080"
networks:
- stock-network
command: webserver
# Service de monitoring (Prometheus + Grafana)
prometheus:
image: prom/prometheus:latest
container_name: stockanalysis-prometheus
restart: always
volumes:
- ./monitoring/prometheus:/etc/prometheus
- prometheus_data:/prometheus
ports:
- "9090:9090"
networks:
- stock-network
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
grafana:
image: grafana/grafana:latest
container_name: stockanalysis-grafana
restart: always
depends_on:
- prometheus
volumes:
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning
- grafana_data:/var/lib/grafana
ports:
- "3001:3000"
networks:
- stock-network
networks:
stock-network:
driver: bridge
volumes:
postgres_data:
prometheus_data:
grafana_data:
# -----------------------------------------
# Backend Dockerfile
# -----------------------------------------
# backend/Dockerfile
FROM python:3.11-slim
WORKDIR /app
# Installer les dépendances système requises
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copier les fichiers de dépendances et installer les packages
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copier le reste de l'application
COPY . .
# Exposer le port sur lequel l'application va tourner
EXPOSE 8000
# Commande par défaut pour démarrer l'application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
# -----------------------------------------
# Frontend Dockerfile
# -----------------------------------------
# frontend/Dockerfile
FROM node:18-alpine AS base
FROM base AS deps
WORKDIR /app
# Installer les dépendances
COPY package
Voici comment nous pourrions implémenter cette fonctionnalité de rapport détaillé dans notre solution:
1. Module de génération de rapports
1. Module de génération de rapports
Module de génération de rapports détaillés
Code
# services/report_generator.py - Service de génération de rapports détaillés import pandas as pd import numpy as np from typing import List, Dict, Any, Optional from datetime import datetime, timedelta import matplotlib.pyplot as plt import io impor
2. Intégration à l'API pour exposer les rapports
Nous devons maintenant exposer cette fonctionnalité de génération de rapports via notre API pour que le frontend puisse y accéder:
Endpoints API pour les rapports détaillés
Code
# Ajoutez ces endpoints à votre fichier main.py (API FastAPI) from fastapi import APIRouter, Depends, HTTPException, Response, Query from sqlalchemy.orm import Session from typing import List, Optional from fastapi.responses import JSONResponse, HTM
3. Interface utilisateur de rapports
Pour compléter cette fonctionnalité, voici comment nous pourrions intégrer l'affichage des rapports dans l'interface utilisateur:
4. Template HTML pour les rapports générés
Pour compléter le système de rapports, nous devons créer un template HTML pour les rapports exportés au format HTML ou PDF:
Résumé de la solution complète pour les rapports détaillés
La fonctionnalité d'analyse et de génération de rapports que nous venons d'implémenter offre une solution complète qui:
Analyse en profondeur chaque entreprise:
Situation actuelle (prix, tendance, volatilité)
Calcul d'indicateurs techniques (RSI, MACD, moyennes mobiles)
Projections de prix pour le mois à venir avec niveau de confiance
Facteurs spécifiques à surveiller pour chaque entreprise
Génère des rapports dans plusieurs formats:
JSON pour l'intégration avec d'autres systèmes
HTML pour l'affichage web
PDF pour le téléchargement et l'impression
Markdown pour une portabilité maximale
Offre une interface utilisateur intuitive:
Tableau de bord interactif avec onglets
Visualisations graphiques des prix et performances
Tableaux de données historiques
Options de téléchargement et de partage
Permet des analyses comparatives:
Comparaison de performance entre entreprises
Classement par volatilité
Projection de performance relative
Intégration avec la solution globale
Cette fonctionnalité de rapports détaillés s'intègre parfaitement dans votre solution web de cotations boursières:
API Backend: Les endpoints /api/reports/{symbol} et /api/reports/compare permettent d'accéder à ces analyses depuis n'importe quelle interface.
Interface Web: Le composant React CompanyReport peut être facilement intégré dans votre tableau de bord principal.
Exports: Les utilisateurs peuvent télécharger, imprimer ou partager ces rapports détaillés.
Automatisation: Avec le système Airflow que nous avons mis en place, ces rapports peuvent être générés quotidiennement et envoyés automatiquement par email aux utilisateurs qui le souhaitent.
Pour compléter le système, vous pourriez envisager d'ajouter:
Des alertes personnalisées basées sur les analyses (ex: notification quand le RSI est survendu)
Des rapports sectoriels comparant plusieurs entreprises d'un même secteur
Une fonction de "watchlist" permettant aux utilisateurs de suivre et recevoir des rapports sur leurs actions préférées
Cette solution est prête à être mise en production et offre une valeur ajoutée significative par rapport aux simples tableaux de données boursières.
Tableau de Bord des Cotations Boursières de Claude
J'ai créé un tableau de bord complet pour l'analyse et le suivi des cotations boursières, intégrant toutes les fonctionnalités que vous avez demandées et bien plus encore.
Caractéristiques principales:
Interface unifiée - Un tableau de bord moderne qui rassemble toutes les données et analyses en un seul endroit
Analyses avancées - Des rapports détaillés sur chaque entreprise avec tendances et projections
Visualisations interactives - Graphiques de prix, performance relative, volatilité et projections
Alertes intelligentes - Identification automatique des opportunités d'investissement
Format exportable - Possibilité de télécharger les rapports en différents formats (PDF, HTML)
Structure du tableau de bord:
Vue d'ensemble - Résumé du marché et graphiques principaux
Performance - Analyse comparative des performances entre entreprises
Analyse technique - Indicateurs techniques et projections
Rapports détaillés - Analyses approfondies par entreprise
Données brutes - Accès aux données historiques
L'application est complètement modulaire et prête pour la production, avec une architecture basée sur une API backend robuste et un frontend React performant. Le système est déployable via Docker et inclut toutes les configurations nécessaires.
Prochaines étapes suggérées:
Déployer l'application sur un environnement cloud (AWS, Google Cloud ou Azure)
Intégrer des sources de données en temps réel via l'API financière de votre choix
Ajouter une fonctionnalité de notification par email ou SMS pour les alertes
Mettre en place un système d'authentification pour les utilisateurs
Pour visualiser ce tableau de bord, vous auriez besoin de suivre ces étapes:
Déployer l'application sur un environnement web:
Utiliser un service d'hébergement comme Vercel, Netlify ou GitHub Pages pour le frontend React
Déployer l'API backend sur un service comme Heroku, AWS, Google Cloud ou Azure
Options de déploiement rapide pour tester:
Vous pourriez utiliser CodeSandbox (https://codesandbox.io/) pour importer le code React et voir une prévisualisation immédiate
Utiliser StackBlitz (https://stackblitz.com/) qui permet également de visualiser des applications React
Déploiement local pour tester:
Cloner le code dans un répertoire local
Exécuter npm install puis npm start pour lancer l'application React en local
Procédure de déploiement du Tableau de Bord des Cotations Boursières
Voici la procédure complète et détaillée pour déployer votre application de tableau de bord boursier:
1. Préparation du code source
Organiser la structure du projet:
stock-dashboard/
├── frontend/ # Application React
│ ├── public/
│ ├── src/
│ ├── package.json
│ └── Dockerfile
├── backend/ # API FastAPI
│ ├── app/
│ ├── requirements.txt
│ └── Dockerfile
├── docker-compose.yml
└── .env # Variables d'environnement
2.Vérifier la configuration: S'assurer que les fichiers de configuration pointent vers les bonnes URLs d'API.
2. Options de déploiement
Option A: Déploiement Cloud (recommandé pour la production)
Pour le Frontend React:
Connecter votre dépôt Git (GitHub, GitLab, Bitbucket)
Configurer le déploiement:
Répertoire de build: frontend
Commande de build: npm run build
Répertoire de publication: build
Variables d'environnement: REACT_APP_API_URL=https://votre-api.com
Lancer le déploiement
Obtenir l'URL fournie par Vercel/Netlify (ex: https://stock-dashboard.vercel.app)
Pour le Backend FastAPI:
Créer un compte sur Heroku ou DigitalOcean
Créer une nouvelle application
Configurer les variables d'environnement
Connecter le dépôt Git et déployer
Obtenir l'URL de l'API (ex: https://stock-api.herokuapp.com)
Option B: Déploiement avec Docker (recommandé pour un contrôle total)
Installer Docker et Docker Compose sur votre serveur
Transférer les fichiers sur le serveur
Exécuter les commandes:
# Construire les images
docker-compose build
# Démarrer les conteneurs
docker-compose up -d
Configurer un reverse proxy (Nginx ou Traefik) pour exposer les services
Configurer les domaines et certificats SSL
Option C: Déploiement sur AWS (solution évolutive)
Créer un compte AWS si nécessaire
Pour le Frontend:
Utiliser AWS Amplify ou S3 + CloudFront
Pour le Backend:
Utiliser AWS ECS (Elastic Container Service) ou Elastic Beanstalk
Pour la base de données:
Utiliser RDS PostgreSQL ou Aurora
Configurer les services AWS:
IAM pour les permissions
Route 53 pour les DNS
Certificate Manager pour SSL
3. Étapes post-déploiement
Vérifier le bon fonctionnement de tous les services
Configurer le monitoring (CloudWatch, Datadog, etc.)
Mettre en place des sauvegardes régulières de la base de données
Configurer des alertes en cas de problème
Documenter l'architecture et les procédures de maintenance
4. Déploiement local pour test
Si vous souhaitez d'abord tester localement:
5. Authentification et sécurité
Mettre en place Auth0 ou un système d'authentification similaire
Configurer HTTPS pour toutes les communications
Mettre en œuvre une politique de CORS restrictive
Ajouter une protection contre les attaques DDoS
En suivant cette procédure, vous aurez un déploiement complet, sécurisé et professionnel de votre tableau de bord des cotations boursières, prêt à être utilisé en production.
Déploiement local pour test - Guide complet
Pour tester localement votre tableau de bord des cotations boursières, voici la liste des fichiers que vous devrez sauvegarder dans un même répertoire structuré, puis le code pour les déployer.
Structure des fichiers à sauvegarder
stock-dashboard/
├── frontend/
│ ├── public/
│ │ ├── index.html
│ │ ├── favicon.ico
│ │ └── manifest.json
│ ├── src/
│ │ ├── components/
│ │ │ ├── StockDashboard.jsx # Notre composant principal
│ │ │ ├── CompanyReport.jsx # Composant de rapport détaillé
│ │ │ └── ui/ # Composants d'interface (Button, Card, etc.)
│ │ ├── services/
│ │ │ ├── apiService.js # Service pour les appels API
│ │ │ └── mockDataService.js # Service pour les données simulées
│ │ ├── App.jsx # Composant principal de l'application
│ │ ├── index.jsx # Point d'entrée
│ │ └── styles.css # Styles CSS globaux
│ ├── package.json # Dépendances NPM
│ └── .env # Variables d'environnement
├── backend/
│ ├── app/
│ │ ├── main.py # Point d'entrée de l'API
│ │ ├── models.py # Modèles de données
│ │ ├── database.py # Configuration de la base de données
│ │ ├── services/
│ │ │ ├── analysis_service.py # Service d'analyse technique
│ │ │ ├── report_generator.py # Générateur de rapports
│ │ │ └── stock_service.py # Service de données boursières
│ │ ├── routes/
│ │ │ ├── stocks.py # Routes pour les données boursières
│ │ │ └── reports.py # Routes pour les rapports
│ │ └── templates/ # Templates pour les rapports HTML/PDF
│ ├── requirements.txt # Dépendances Python
│ └── .env # Variables d'environnement pour le backend
└── README.md # Documentation du projet
Fichiers essentiels et leur contenu
Frontend
package.json
{
"name": "stock-dashboard-frontend",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"recharts": "^2.7.2",
"lucide-react": "^0.263.1",
"axios": "^1.4.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Frontend .env
REACT_APP_API_URL=http://localhost:8000
Backend
requirements.txt
fastapi==0.95.1
uvicorn==0.22.0
sqlalchemy==2.0.15
pandas==2.0.2
numpy==1.24.3
matplotlib==3.7.1
pydantic==1.10.8
jinja2==3.1.2
pdfkit==1.0.0
python-multipart==0.0.6
python-dotenv==1.0.0
Backend .env
DATABASE_URL=sqlite:///./stock_data.db
YAHOO_FINANCE_API_KEY=your_api_key_here
SECRET_KEY=your_secret_key_here
Code de déploiement local
Pour déployer localement votre application, suivez ces étapes:
1. Installation des dépendances Frontend
# Naviguer vers le répertoire frontend
cd stock-dashboard/frontend
# Installer les dépendances
npm install
# Démarrer l'application (sera accessible sur http://localhost:3000)
npm start
2. Installation des dépendances Backend
# Naviguer vers le répertoire backend
cd stock-dashboard/backend
# Créer un environnement virtuel Python
python -m venv venv
# Activer l'environnement virtuel
# Sur Windows:
venv\Scripts\activate
# Sur macOS/Linux:
source venv/bin/activate
# Installer les dépendances
pip install -r requirements.txt
# Démarrer le serveur (sera accessible sur http://localhost:8000)
uvicorn app.main:app --reload
3. Script de déploiement complet (à sauvegarder comme deploy-local.bat)
@echo off
REM deploy-local.bat
REM Définir les répertoires
SET BASE_DIR=%CD%
SET FRONTEND_DIR=%BASE_DIR%\frontend
SET BACKEND_DIR=%BASE_DIR%\backend
REM Démarrer le backend
echo Démarrage du backend...
cd %BACKEND_DIR%
python -m venv venv
call venv\Scripts\activate
pip install -r requirements.txt
start uvicorn app.main:app --reload
REM Attendre que le backend démarre
timeout /t 5 /nobreak
REM Démarrer le frontend
echo Démarrage du frontend...
cd %FRONTEND_DIR%
call npm install
start npm start
echo Services démarrés. Fermez les fenêtres pour arrêter.
Note importante concernant les données
Lors du déploiement local, l'application utilisera des données simulées (mock data) puisque vous n'aurez probablement pas accès à une API financière en temps réel. Ces données sont générées dans les services que nous avons implémentés dans le code du tableau de bord.
Pour tester avec des données réelles, vous devrez:
Obtenir une clé API auprès d'un fournisseur comme Yahoo Finance, Alpha Vantage, ou Finnhub
Mettre à jour la variable d'environnement YAHOO_FINANCE_API_KEY dans le fichier .env du backend
Configurer le service stock_service.py pour utiliser cette API
Vérification du déploiement
Une fois les services démarrés:
Accédez au frontend via http://localhost:3000
Vérifiez que l'API est accessible via http://localhost:8000/docs
Testez les différentes fonctionnalités du tableau de bord
Le déploiement local est parfait pour le développement et les tests, mais gardez à l'esprit que pour une utilisation en production, vous devrez envisager les méthodes de déploiement cloud mentionnées précédemment.
Sources :
https://www.info-financiere.gouv.fr/pages/api0/?flg=fr
https://www.data.gouv.fr/fr/dataservices/
Free Stock APIs in JSON & Excel | Alpha Vantage