Spaces:
Runtime error
Runtime error
| import dash | |
| from dash import html, dcc, Input, Output | |
| import plotly.graph_objs as go | |
| import pandas as pd | |
| import ccxt | |
| from datetime import datetime | |
| from plotly.subplots import make_subplots | |
| # Init MEXC | |
| exchange = ccxt.mexc() | |
| markets = exchange.load_markets() | |
| symbols = sorted([symbol for symbol in markets if "/USDT" in symbol]) | |
| timeframes = list(exchange.timeframes.keys()) | |
| DEFAULT_SYMBOL = "BTC/USDT" | |
| DEFAULT_TIMEFRAME = "1h" | |
| def fetch_ohlcv(symbol, timeframe): | |
| try: | |
| ohlcv = exchange.fetch_ohlcv(symbol, timeframe) | |
| df = pd.DataFrame(ohlcv, columns=["timestamp", "open", "high", "low", "close", "volume"]) | |
| df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms") | |
| return df | |
| except Exception as e: | |
| print(f"β Error: {e}") | |
| return pd.DataFrame() | |
| def add_indicators(df): | |
| df = df.copy() | |
| df['ema12'] = df['close'].ewm(span=12).mean() | |
| df['ema26'] = df['close'].ewm(span=26).mean() | |
| df['macd'] = df['ema12'] - df['ema26'] | |
| df['macd_signal'] = df['macd'].ewm(span=9).mean() | |
| delta = df['close'].diff() | |
| gain = delta.clip(lower=0) | |
| loss = -delta.clip(upper=0) | |
| avg_gain = gain.rolling(14).mean() | |
| avg_loss = loss.rolling(14).mean() | |
| rs = avg_gain / avg_loss | |
| df['rsi'] = 100 - (100 / (1 + rs)) | |
| return df | |
| def add_signals(df): | |
| df['buy'] = (df['macd'] > df['macd_signal']) & (df['macd'].shift(1) <= df['macd_signal'].shift(1)) & (df['rsi'] < 50) | |
| df['sell'] = (df['macd'] < df['macd_signal']) & (df['macd'].shift(1) >= df['macd_signal'].shift(1)) & (df['rsi'] > 50) | |
| return df | |
| def create_chart(df): | |
| fig = make_subplots(rows=3, cols=1, shared_xaxes=True, | |
| vertical_spacing=0.02, row_heights=[0.6, 0.2, 0.2]) | |
| fig.add_trace(go.Candlestick(x=df['timestamp'], open=df['open'], high=df['high'], | |
| low=df['low'], close=df['close'], name='Candles'), row=1, col=1) | |
| fig.add_trace(go.Scatter(x=df['timestamp'], y=df['rsi'], name='RSI', | |
| line=dict(color='orange')), row=2, col=1) | |
| fig.add_trace(go.Scatter(x=df['timestamp'], y=df['macd'], name='MACD', | |
| line=dict(color='blue')), row=3, col=1) | |
| fig.add_trace(go.Scatter(x=df['timestamp'], y=df['macd_signal'], name='MACD Signal', | |
| line=dict(color='red')), row=3, col=1) | |
| # Signal markers | |
| buys = df[df['buy']] | |
| sells = df[df['sell']] | |
| fig.add_trace(go.Scatter(x=buys['timestamp'], y=buys['close'], mode='markers', | |
| name='Buy', marker=dict(color='green', size=10, symbol='triangle-up')), row=1, col=1) | |
| fig.add_trace(go.Scatter(x=sells['timestamp'], y=sells['close'], mode='markers', | |
| name='Sell', marker=dict(color='red', size=10, symbol='triangle-down')), row=1, col=1) | |
| fig.update_layout(height=800, margin=dict(t=30, b=20), showlegend=True) | |
| return fig | |
| # Dash App | |
| app = dash.Dash(__name__) | |
| app.title = "MEXC AI Signals" | |
| app.layout = html.Div([ | |
| html.H2("π MEXC Crypto Signal Chart", style={'textAlign': 'center'}), | |
| html.Div([ | |
| html.Label("Select Pair:"), | |
| dcc.Dropdown(id="pair-dropdown", options=[{"label": s, "value": s} for s in symbols], | |
| value=DEFAULT_SYMBOL, style={"width": "100%"}) | |
| ], style={"width": "30%", "display": "inline-block"}), | |
| html.Div([ | |
| html.Label("Timeframes:"), | |
| html.Div([ | |
| html.Button(tf, id={'type': 'tf-button', 'index': tf}, n_clicks=0, | |
| style={"margin": "2px", "width": "50px"}) for tf in timeframes | |
| ], id="tf-button-row") | |
| ], style={"width": "68%", "display": "inline-block"}), | |
| dcc.Store(id="selected-timeframe", data=DEFAULT_TIMEFRAME), | |
| dcc.Graph(id="chart", config={"displayModeBar": True}), | |
| html.Div(id="signal-box", style={"marginTop": "10px", "textAlign": "center", "fontSize": "16px"}) | |
| ]) | |
| def update_timeframe(n_clicks_list): | |
| ctx = dash.callback_context | |
| if not ctx.triggered: | |
| return DEFAULT_TIMEFRAME | |
| triggered_id = ctx.triggered[0]["prop_id"].split(".")[0] | |
| timeframe = eval(triggered_id)["index"] | |
| return timeframe | |
| def update_chart(symbol, timeframe): | |
| df = fetch_ohlcv(symbol, timeframe) | |
| if df.empty: | |
| return go.Figure(), "β No data available" | |
| df = add_indicators(df) | |
| df = add_signals(df) | |
| latest_signal = "π No recent signal" | |
| if df['buy'].iloc[-1]: | |
| latest_signal = f"π’ Latest Signal: BUY at {df['close'].iloc[-1]:.2f} on {df['timestamp'].iloc[-1]}" | |
| elif df['sell'].iloc[-1]: | |
| latest_signal = f"π΄ Latest Signal: SELL at {df['close'].iloc[-1]:.2f} on {df['timestamp'].iloc[-1]}" | |
| fig = create_chart(df) | |
| return fig, latest_signal | |
| if __name__ == "__main__": | |
| app.run(host="0.0.0.0", port=7860) | |