L'analyce prédictive des marchés financiers représente un défi majeur en raison de la volatilité et de la nature non linéaire des données boursières. Traditionnellement, la mise en œuvre de modèles de réseaux de neurones récurrents, tels que les Long Short-Term Memory (LSTM), exige une expertise approfondie en ingénierie des caractéristiques et en architecture de modèles. L'utilisation du modèle Qwen2.5-Coder-1.5B simplifie radicalement ce processus en générant un pipeline complet, de l'acquisition des données au déploiement de l'inférence.
1. Configuration de l'environnement et extraction des données
Pour construire notre modèle de prédiction de prix d'actions (par exemple, Apple - AAPL), nous utilisons des bibliothèques standards de l'écosystème Python pour le calcul numérique et le Deep Learning.
import torch
import torch.nn as nn
import pandas as pd
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from torch.utils.data import DataLoader, TensorDataset
# Acquisition des données boursières via yfinance
def recuperer_historique(symbole="AAPL", periode="2y"):
df = yf.download(symbole, period=periode)
return df
donnees_brutes = recuperer_historique()
print(f"Dimensions du dataset : {donnees_brutes.shape}")
2. Ingénierie des caractéristiques techniques
Le prix de clôture seul est rarement suffisant. L'ajout d'indicateurs techniques permet au modèle de capter des signaux de momentum et de volatilité.
def enrichir_caracteristiques(df):
copie_df = df.copy()
# Moyennes Mobiles (MA)
copie_df['MA10'] = copie_df['Close'].rolling(window=10).mean()
copie_df['MA50'] = copie_df['Close'].rolling(window=50).mean()
# Relative Strength Index (RSI)
diff = copie_df['Close'].diff()
gain = (diff.where(diff > 0, 0)).rolling(window=14).mean()
perte = (-diff.where(diff < 0, 0)).rolling(window=14).mean()
rs = gain / perte
copie_df['RSI'] = 100 - (100 / (1 + rs))
# Nettoyage des valeurs nulles générées par les fenêtres glissantes
return copie_df.fillna(method='bfill')
df_enrichi = enrichir_caracteristiques(donnees_brutes)
3. Préparation des séquences temporelles
Les modèles LSTM nécesstient des données structurées en fenêtres glissantes. Nous transformons les séries temporelles en paires de (séquences passées, valeur cible future).
def preparer_sequences(donnees, fenetre_temporelle=60):
scaler = MinMaxScaler(feature_range=(0, 1))
donnees_scalées = scaler.fit_transform(donnees[['Close']].values)
X, y = [], []
for i in range(fenetre_temporelle, len(donnees_scalées)):
X.append(donnees_scalées[i-fenetre_temporelle:i, 0])
y.append(donnees_scalées[i, 0])
X = np.array(X).reshape(-1, fenetre_temporelle, 1)
y = np.array(y)
return torch.FloatTensor(X), torch.FloatTensor(y), scaler
X_tensor, y_tensor, mon_scaler = preparer_sequences(df_enrichi)
# Division chronologique (80% train, 20% test)
taille_train = int(len(X_tensor) * 0.8)
X_train, X_test = X_tensor[:taille_train], X_tensor[taille_train:]
y_train, y_test = y_tensor[:taille_train], y_tensor[taille_train:]
4. Architecture du modèle LSTM
Nous concevons une architecture capable de mémoriser les dépendances à long terme tout en évitant le surapprentissgae grâce à des couches de Dropout.
class AnalyseurFinancierLSTM(nn.Module):
def __init__(self, dim_entree=1, dim_cache=64, nb_couches=2):
super(AnalyseurFinancierLSTM, self).__init__()
self.dim_cache = dim_cache
self.nb_couches = nb_couches
self.lstm = nn.LSTM(dim_entree, dim_cache, nb_couches,
batch_first=True, dropout=0.2)
self.fc = nn.Linear(dim_cache, 1)
def forward(self, x):
h0 = torch.zeros(self.nb_couches, x.size(0), self.dim_cache).to(x.device)
c0 = torch.zeros(self.nb_couches, x.size(0), self.dim_cache).to(x.device)
out, _ = self.lstm(x, (h0, c0))
# Extraction du dernier état temporel
out = self.fc(out[:, -1, :])
return out
modele = AnalyseurFinancierLSTM()
5. Cycle d'entraînement et optimisation
L'optimiseur Adam et la perte MSE (Mean Squared Error) sont privilégiés pour les tâches de régression financière.
def entrainer_modele(modele, X, y, epochs=50, lr=0.001):
critere = nn.MSELoss()
optimiseur = torch.optim.Adam(modele.parameters(), lr=lr)
for epoch in range(epochs):
modele.train()
outputs = modele(X)
perte = critere(outputs, y.view(-1, 1))
optimiseur.zero_grad()
perte.backward()
optimiseur.step()
if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{epochs}], Loss: {perte.item():.6f}')
entrainer_modele(modele, X_train, y_train)
6. Évaluation et Inférence multi-pas
Une fois entraîné, le modèle peut projeter les prix futurs en utilisant ses propres prédictions comme entrées récursives.
def prediction_future(modele, derniere_sequence, nb_jours=5):
modele.eval()
predictions = []
entree_actuelle = derniere_sequence.clone().unsqueeze(0)
with torch.no_grad():
for _ in range(nb_jours):
pred = modele(entree_actuelle)
predictions.append(pred.item())
# Mise à jour de la fenêtre glissante avec la nouvelle prédiction
nouveau_point = pred.view(1, 1, 1)
entree_actuelle = torch.cat((entree_actuelle[:, 1:, :], nouveau_point), dim=1)
return predictions
# Exemple de prédiction pour la semaine suivante
derniers_jours = X_test[-1]
horizon_5j = prediction_future(modele, derniers_jours)
prix_reels = mon_scaler.inverse_transform(np.array(horizon_5j).reshape(-1, 1))
print(f"Prévisions pour les 5 prochains jours : {prix_reels.flatten()}")
7. Stratégies d'optimisation avancées
Pour améliorer la précision, le modèle Qwen2.5-Coder suggère plusieurs pistes d'optimisation structurelle :
- Mécanisme d'attention : Intégrer une couche d'attention après le LSTM pour pondérer l'importance des jours spécifiques (ex: annonces de résultats).
- Entrées multivariées : Ne pas se limiter au prix, mais inclure le volume, l'indice de volatilité (VIX) et l'analyse de sentiment textuel.
- Régularisation : Utiliser le "Early Stopping" pour interrompre l'entraînement dès que la perte sur le jeu de validation commence à diverger.
Le déploiement de tels modèles peut être encapsulé dans des API REST via FastAPI, permettant une intégration directe dans des tableaux de bord financiers ou des algorithmes de trading automatisés. L'utilisation de bibliothèques comme torch.jit permet également de sérialiser le modèle pour des performances d'exécution accrues en production.