Download app.py from enoderr/Fx: direct link, hf CLI and curl.
- Browser
- Download file 11.2 kB
-
https://huggingface.co/spaces/enoderr/Fx/resolve/main/app.py
- Command line
-
hf download hf://spaces/enoderr/Fx/app.py
-
curl -L -o app.py https://huggingface.co/spaces/enoderr/Fx/resolve/main/app.py
11.2 kB
| 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}") | |