| 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 |
|
|
| |
| 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) |
| return prices |
|
|
| |
| 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))] |
|
|
| |
| 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 |
|
|
| |
| def identify_best_pattern(df, patterns): |
| mse_scores = {} |
| actual_values = df["price"].values[-len(df) // 2:] |
|
|
| 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 |
|
|
| |
| best_pattern = min(mse_scores, key=mse_scores.get) |
| return best_pattern |
|
|
| |
| end_time = datetime.now() |
| start_time = end_time - timedelta(hours=48) |
|
|
| |
| coins = { |
| "Bitcoin": "bitcoin", |
| "Ripple": "xrp", |
| "Ethereum": "ethereum", |
| "Tether": "tether", |
| "Stellar": "stellar" |
| } |
|
|
| |
| crypto_prices = get_crypto_prices(coins, start_time, end_time) |
|
|
| |
| 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") |
|
|
| |
| 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) |
|
|
| |
| 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." |
| } |
|
|
| |
| st.write(f"### Explication du pattern ({best_pattern}):") |
| st.write(explanation[best_pattern]) |
|
|
| else: |
| st.warning(f"Aucune donnée disponible pour {coin}") |
|
|