Spaces:
Sleeping
Sleeping
| """ | |
| Module: visual_comparison.py | |
| Purpose: Interactive crypto pair comparison (Plotly + CoinGecko) | |
| """ | |
| import requests | |
| import pandas as pd | |
| import plotly.graph_objects as go | |
| COINGECKO_API = "https://api.coingecko.com/api/v3" | |
| def get_coin_history(coin_id: str, days: int = 180): | |
| """Fetch historical market data for given coin from CoinGecko API.""" | |
| url = f"{COINGECKO_API}/coins/{coin_id}/market_chart?vs_currency=usd&days={days}" | |
| r = requests.get(url) | |
| r.raise_for_status() | |
| data = r.json() | |
| df = pd.DataFrame(data["prices"], columns=["timestamp", "price"]) | |
| df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms") | |
| return df | |
| def build_price_chart(pair: tuple[str, str], days: int = 180): | |
| """Build comparative price chart for selected pair.""" | |
| coin_a, coin_b = pair | |
| df_a = get_coin_history(coin_a, days) | |
| df_b = get_coin_history(coin_b, days) | |
| fig = go.Figure() | |
| fig.add_trace(go.Scatter( | |
| x=df_a["timestamp"], | |
| y=df_a["price"], | |
| name=f"{coin_a.capitalize()} / USD", | |
| line=dict(width=2), | |
| )) | |
| fig.add_trace(go.Scatter( | |
| x=df_b["timestamp"], | |
| y=df_b["price"], | |
| name=f"{coin_b.capitalize()} / USD", | |
| line=dict(width=2), | |
| )) | |
| fig.update_layout( | |
| template="plotly_dark", | |
| height=480, | |
| margin=dict(l=40, r=20, t=30, b=40), | |
| xaxis_title="Date", | |
| yaxis_title="Price (USD)", | |
| legend_title="Asset", | |
| hovermode="x unified", | |
| ) | |
| return fig | |
| def build_volatility_chart(pair: tuple[str, str], days: int = 180): | |
| """Build comparative volatility chart for selected pair.""" | |
| coin_a, coin_b = pair | |
| df_a = get_coin_history(coin_a, days) | |
| df_b = get_coin_history(coin_b, days) | |
| df_a["returns"] = df_a["price"].pct_change() * 100 | |
| df_b["returns"] = df_b["price"].pct_change() * 100 | |
| fig = go.Figure() | |
| fig.add_trace(go.Scatter( | |
| x=df_a["timestamp"], | |
| y=df_a["returns"], | |
| name=f"{coin_a.upper()} Daily Change (%)", | |
| mode="lines", | |
| line=dict(width=1.6), | |
| )) | |
| fig.add_trace(go.Scatter( | |
| x=df_b["timestamp"], | |
| y=df_b["returns"], | |
| name=f"{coin_b.upper()} Daily Change (%)", | |
| mode="lines", | |
| line=dict(width=1.6), | |
| )) | |
| fig.update_layout( | |
| template="plotly_dark", | |
| height=400, | |
| margin=dict(l=40, r=20, t=30, b=40), | |
| xaxis_title="Date", | |
| yaxis_title="Daily Change (%)", | |
| legend_title="Volatility", | |
| hovermode="x unified", | |
| ) | |
| return fig | |