Spaces:
Running
Running
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| import pandas as pd | |
| import torch | |
| # L'import marche parfaitement car le dossier 'model' a été cloné par Docker ! | |
| from model import Kronos, KronosTokenizer, KronosPredictor | |
| app = FastAPI(title="Kronos Trading API") | |
| print("📥 Chargement du modèle Kronos-small...") | |
| try: | |
| tokenizer = KronosTokenizer.from_pretrained("NeoQuasar/Kronos-Tokenizer-base") | |
| model = Kronos.from_pretrained("NeoQuasar/Kronos-small") | |
| # max_context est de 512 pour Kronos-small | |
| predictor = KronosPredictor(model, tokenizer, max_context=512) | |
| print("✅ Modèle chargé et prêt !") | |
| except Exception as e: | |
| print(f"❌ ERREUR CRITIQUE : {str(e)}") | |
| predictor = None | |
| class PredictionRequest(BaseModel): | |
| history_data: list | |
| lookback: int = 400 | |
| pred_len: int = 24 | |
| def read_root(): | |
| return {"status": "Kronos API is running 🚀", "model_loaded": predictor is not None} | |
| # 💡 L'ASTUCE ANTI-ERREUR 404 : L'API répondra aux deux adresses ! | |
| def predict(request: PredictionRequest): | |
| if predictor is None: | |
| raise HTTPException(status_code=500, detail="Le modèle n'a pas pu démarrer.") | |
| if not request.history_data: | |
| raise HTTPException(status_code=400, detail="Aucune donnée historique (OHLC) fournie.") | |
| df = pd.DataFrame(request.history_data) | |
| required_cols = ['open', 'high', 'low', 'close'] | |
| if not all(col in df.columns for col in required_cols): | |
| raise HTTPException(status_code=400, detail=f"Colonnes manquantes. Requis : {required_cols}") | |
| if 'timestamps' not in df.columns: | |
| df['timestamps'] = pd.date_range(start='2024-01-01', periods=len(df), freq='H') | |
| else: | |
| df['timestamps'] = pd.to_datetime(df['timestamps']) | |
| actual_lookback = min(len(df), request.lookback, 512) | |
| x_df = df.tail(actual_lookback).reset_index(drop=True) | |
| x_timestamp = x_df['timestamps'] | |
| last_time = x_timestamp.iloc[-1] | |
| # 👇 CORRECTION ICI : Conversion explicite en pd.Series 👇 | |
| y_timestamp = pd.Series(pd.date_range(start=last_time, periods=request.pred_len + 1, freq='h')[1:]) | |
| try: | |
| pred_df = predictor.predict( | |
| df=x_df, | |
| x_timestamp=x_timestamp, | |
| y_timestamp=y_timestamp, | |
| pred_len=request.pred_len, | |
| T=1.0, | |
| top_p=0.9, | |
| sample_count=1 | |
| ) | |
| current_price = float(x_df['close'].iloc[-1]) | |
| predicted_price = float(pred_df['close'].iloc[-1]) | |
| expected_change = ((predicted_price - current_price) / current_price) * 100 | |
| return { | |
| "status": "success", | |
| "current_price": current_price, | |
| "predicted_price_in_24h": predicted_price, | |
| "expected_change_percent": expected_change | |
| } | |
| except Exception as e: | |
| print(f"❌ Erreur lors de la prédiction : {str(e)}") | |
| raise HTTPException(status_code=500, detail=f"Erreur interne : {str(e)}") |