import streamlit as st import requests import pandas as pd import matplotlib.pyplot as plt import numpy as np from datetime import datetime, timedelta from sklearn.metrics import mean_squared_error # Fonction pour récupérer les prix historiques def get_crypto_prices(coins, start_time, end_time, interval='m15'): prices = {} for coin, coin_id in coins.items(): url = f'https://api.coincap.io/v2/assets/{coin_id}/history' params = { 'interval': interval, 'start': int(start_time.timestamp() * 1000), 'end': int(end_time.timestamp() * 1000) } response = requests.get(url, params=params) if response.status_code == 200: data = response.json().get('data', []) prices[coin] = [[int(item['time']), float(item['priceUsd'])] for item in data] if data: prices[coin].append([int(end_time.timestamp() * 1000), float(data[-1]['priceUsd'])]) else: st.error(f"Erreur lors de la récupération des prix pour {coin}: {response.status_code}") st.write(response.text) # Debug pour afficher l'erreur complète return prices # Fonction pour prédire les tendances basées sur les patterns def predict_patterns(data, future_hours=24): df = pd.DataFrame(data, columns=["timestamp", "price"]) df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms") df.set_index("timestamp", inplace=True) last_timestamp = df.index[-1] future_timestamps = [last_timestamp + timedelta(minutes=15 * i) for i in range(1, (future_hours * 60 // 15) + 1)] last_price = df["price"].iloc[-1] trend = (df["price"].iloc[-1] - df["price"].iloc[0]) / len(df) sma = df["price"].rolling(window=10).mean().iloc[-1] ema = df["price"].ewm(span=10, adjust=False).mean().iloc[-1] cycle_amplitude = (df["price"].max() - df["price"].min()) / 2 mean_price = df["price"].mean() patterns = {} patterns["Trend"] = [last_price + i * trend for i in range(1, len(future_timestamps) + 1)] patterns["Reversal"] = [last_price - i * trend for i in range(1, len(future_timestamps) + 1)] patterns["SMA"] = [sma] * len(future_timestamps) patterns["EMA"] = [ema] * len(future_timestamps) patterns["Cycle"] = [ last_price + cycle_amplitude * np.sin(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps)) ] patterns["Rebound"] = [last_price + trend * (0.5 ** i) for i in range(len(future_timestamps))] patterns["Plateau"] = [last_price] * len(future_timestamps) patterns["Breakout"] = [ last_price + (trend * 2 if i < len(future_timestamps) // 2 else -trend * 2) for i in range(len(future_timestamps)) ] patterns["Recovery"] = [last_price + (mean_price - last_price) * (i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["Acceleration"] = [last_price + (trend * 1.5) * i for i in range(len(future_timestamps))] # Ajout des 20 autres patterns patterns["Overbought"] = [last_price + cycle_amplitude * np.cos(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["Oversold"] = [last_price - cycle_amplitude * np.cos(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["DoubleTop"] = [last_price + trend * 2 if i < len(future_timestamps) // 2 else last_price - trend * 2 for i in range(len(future_timestamps))] patterns["DoubleBottom"] = [last_price - trend * 2 if i < len(future_timestamps) // 2 else last_price + trend * 2 for i in range(len(future_timestamps))] patterns["HeadAndShoulders"] = [last_price + (cycle_amplitude * np.sin(2 * np.pi * i / (len(future_timestamps) // 2))) for i in range(len(future_timestamps))] patterns["InverseHeadAndShoulders"] = [last_price - (cycle_amplitude * np.sin(2 * np.pi * i / (len(future_timestamps) // 2))) for i in range(len(future_timestamps))] patterns["Parabolic"] = [last_price + (cycle_amplitude * i ** 2) for i in range(len(future_timestamps))] patterns["ExponentialGrowth"] = [last_price * (1 + 0.05) ** i for i in range(len(future_timestamps))] patterns["ExponentialDecay"] = [last_price * (1 - 0.05) ** i for i in range(len(future_timestamps))] patterns["Sinusoidal"] = [last_price + cycle_amplitude * np.sin(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["Flatline"] = [last_price for i in range(len(future_timestamps))] patterns["HarmonicOscillator"] = [last_price + cycle_amplitude * np.cos(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["Waveform"] = [last_price + cycle_amplitude * np.sin(i) for i in range(len(future_timestamps))] patterns["SwingHigh"] = [last_price + cycle_amplitude * np.sin(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["SwingLow"] = [last_price - cycle_amplitude * np.sin(2 * np.pi * i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["AscendingTriangle"] = [last_price + cycle_amplitude * np.exp(i / len(future_timestamps)) for i in range(len(future_timestamps))] patterns["DescendingTriangle"] = [last_price - cycle_amplitude * np.exp(i / len(future_timestamps)) for i in range(len(future_timestamps))] pattern_dfs = { pattern_name: pd.DataFrame({"timestamp": future_timestamps, "price": prices}) for pattern_name, prices in patterns.items() } return pattern_dfs # Fonction pour identifier le pattern le plus ressemblant def identify_best_pattern(df, patterns): mse_scores = {} actual_values = df["price"].values[-len(df) // 2:] # Dernières heures for pattern_name, pattern_df in patterns.items(): predicted_values = np.array(pattern_df["price"].values[:len(actual_values)]) min_length = min(len(actual_values), len(predicted_values)) mse = mean_squared_error(actual_values[:min_length], predicted_values[:min_length]) mse_scores[pattern_name] = mse # Sélection du pattern avec la MSE la plus faible best_pattern = min(mse_scores, key=mse_scores.get) return best_pattern # Configuration des dates end_time = datetime.now() start_time = end_time - timedelta(hours=48) # Liste des cryptos avec leurs IDs corrects sur CoinCap coins = { "Bitcoin": "bitcoin", "Ripple": "xrp", "Ethereum": "ethereum", "Tether": "tether", "Stellar": "stellar" } # Récupération des prix crypto_prices = get_crypto_prices(coins, start_time, end_time) # Affichage des graphiques st.title("Analyse et Prédictions des Cryptos avec Patterns") for coin, price_data in crypto_prices.items(): if price_data: df = pd.DataFrame(price_data, columns=["timestamp", "price"]) df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms") patterns = predict_patterns(price_data, future_hours=24) best_pattern = identify_best_pattern(df, patterns) st.write(f"#### {coin} - Prix et Prédictions") fig, ax = plt.subplots(figsize=(12, 6)) ax.plot(df["timestamp"], df["price"], label="Prix réel", color="blue") # Affiche uniquement le meilleur pattern best_pattern_df = patterns[best_pattern] ax.plot( best_pattern_df["timestamp"], best_pattern_df["price"], label=f"Prédiction ({best_pattern})", linestyle="dashed", color="orange" ) ax.set_title(f"{coin} - Prix (48h réels + 24h prévu avec {best_pattern})") ax.set_xlabel("Temps") ax.set_ylabel("Prix (USD)") ax.legend() st.pyplot(fig) # Texte explicatif du pattern choisi explanation = { "Trend": "Ce pattern indique que le prix continue sur la tendance actuelle, il suit la direction des prix précédents.", "Reversal": "Ce pattern suggère que le prix pourrait inverser la tendance actuelle, en suivant la direction opposée.", "SMA": "Le prix pourrait se stabiliser autour de la moyenne mobile simple (SMA), une approximation de la tendance générale.", "EMA": "Ce pattern suit la moyenne mobile exponentielle (EMA), qui réagit plus rapidement aux changements de prix.", "Cycle": "Le pattern de cycle suppose une oscillation autour d'un point central, représentant des mouvements de prix cycliques.", "Rebound": "Le prix pourrait rebondir après avoir montré des signes de ralentissement, suivant une courbe d'amortissement.", "Plateau": "Ce pattern suggère que le prix restera relativement stable et horizontal, sans mouvements majeurs.", "Breakout": "Le breakout indique une rupture de la tendance actuelle, avec une direction plus forte dans une des deux directions.", "Recovery": "Le pattern de récupération suggère que le prix pourrait revenir à sa moyenne historique après une variation importante.", "Acceleration": "L'accélération suggère un mouvement rapide des prix, souvent après une période de stagnation ou de consolidation.", "Overbought": "Le prix est suracheté, ce qui pourrait indiquer une inversion de tendance à la baisse.", "Oversold": "Le prix est survendu, ce qui pourrait indiquer une inversion de tendance à la hausse.", "DoubleTop": "Il y a deux pics proches, et le prix pourrait redescendre après le deuxième sommet.", "DoubleBottom": "Il y a deux creux proches, et le prix pourrait rebondir après le deuxième creux.", "HeadAndShoulders": "La tête et les épaules représentent une inversion de tendance, le prix pourrait chuter après la formation.", "InverseHeadAndShoulders": "L'inverse de la tête et des épaules représente une inversion à la hausse.", "Parabolic": "Le prix suit une courbe parabolique, souvent avant un renversement brusque.", "ExponentialGrowth": "Le prix suit une croissance exponentielle rapide.", "ExponentialDecay": "Le prix suit une décroissance exponentielle rapide.", "Sinusoidal": "Le prix fluctue selon un pattern sinusoïdal.", "Flatline": "Le prix est stable, sans changements significatifs.", "HarmonicOscillator": "Le prix suit un oscillateur harmonique, avec des fluctuations régulières.", "Waveform": "Le prix suit une forme d'onde régulière.", "SwingHigh": "Le prix forme des pics élevés, suggérant un renversement.", "SwingLow": "Le prix forme des creux profonds, suggérant une tendance à la hausse.", "AscendingTriangle": "Le prix suit une formation de triangle ascendant, avec des résistances élevées.", "DescendingTriangle": "Le prix suit une formation de triangle descendant, avec des supports bas." } # Afficher l'explication sous le graphique st.write(f"### Explication du pattern ({best_pattern}):") st.write(explanation[best_pattern]) else: st.warning(f"Aucune donnée disponible pour {coin}")