Spaces:
Running
Running
| import ccxt | |
| import pandas as pd | |
| import plotly.graph_objects as go | |
| import gradio as gr | |
| # Fetch OHLCV from MEXC | |
| def fetch_ohlcv(symbol='BTC/USDT', timeframe='1h', limit=150): | |
| exchange = ccxt.mexc() | |
| ohlcv = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit) | |
| df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) | |
| df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') | |
| return df | |
| # Indicators | |
| def calculate_ema(df, period): | |
| return df['close'].ewm(span=period, adjust=False).mean() | |
| def calculate_supertrend(df, period=10, multiplier=3): | |
| hl2 = (df['high'] + df['low']) / 2 | |
| atr = (df['high'] - df['low']).rolling(period).mean() | |
| upper = hl2 + multiplier * atr | |
| lower = hl2 - multiplier * atr | |
| st = [True] * len(df) | |
| for i in range(1, len(df)): | |
| if df['close'].iloc[i] > upper.iloc[i - 1]: | |
| st[i] = True | |
| elif df['close'].iloc[i] < lower.iloc[i - 1]: | |
| st[i] = False | |
| else: | |
| st[i] = st[i - 1] | |
| return pd.Series(st, index=df.index) | |
| def calculate_rsi(df, period=14): | |
| delta = df['close'].diff() | |
| gain = delta.clip(lower=0) | |
| loss = -delta.clip(upper=0) | |
| avg_gain = gain.rolling(period).mean() | |
| avg_loss = loss.rolling(period).mean() | |
| rs = avg_gain / avg_loss | |
| return 100 - (100 / (1 + rs)) | |
| def detect_rsi_divergence(df): | |
| df['rsi'] = calculate_rsi(df) | |
| df['bullish_div'] = False | |
| df['bearish_div'] = False | |
| for i in range(2, len(df)): | |
| if (df['close'].iloc[i] < df['close'].iloc[i - 1] < df['close'].iloc[i - 2] and | |
| df['rsi'].iloc[i] > df['rsi'].iloc[i - 1] > df['rsi'].iloc[i - 2]): | |
| df.at[df.index[i], 'bullish_div'] = True | |
| if (df['close'].iloc[i] > df['close'].iloc[i - 1] > df['close'].iloc[i - 2] and | |
| df['rsi'].iloc[i] < df['rsi'].iloc[i - 1] < df['rsi'].iloc[i - 2]): | |
| df.at[df.index[i], 'bearish_div'] = True | |
| return df | |
| # Signal Logic | |
| def generate_signal(df): | |
| df['ema_50'] = calculate_ema(df, 50) | |
| df['ema_200'] = calculate_ema(df, 200) | |
| df['supertrend'] = calculate_supertrend(df) | |
| df = detect_rsi_divergence(df) | |
| ema_sig = 'BULLISH' if df['ema_50'].iloc[-1] > df['ema_200'].iloc[-1] else 'BEARISH' | |
| st_sig = 'BULLISH' if df['supertrend'].iloc[-1] else 'BEARISH' | |
| if ema_sig == 'BULLISH' and st_sig == 'BULLISH': | |
| label = "π₯ STRONG BUY" | |
| elif ema_sig == 'BEARISH' and st_sig == 'BEARISH': | |
| label = "π STRONG SELL" | |
| elif ema_sig == st_sig: | |
| label = f"β οΈ {ema_sig}" | |
| else: | |
| label = "π€ NEUTRAL / HOLD" | |
| if df['bullish_div'].iloc[-1]: | |
| label += " + π Bullish RSI Divergence" | |
| if df['bearish_div'].iloc[-1]: | |
| label += " + π Bearish RSI Divergence" | |
| return label | |
| # Plotly chart | |
| def plot_chart(df): | |
| df['ema_50'] = calculate_ema(df, 50) | |
| df['ema_200'] = calculate_ema(df, 200) | |
| df['supertrend'] = calculate_supertrend(df) | |
| df = detect_rsi_divergence(df) | |
| fig = go.Figure() | |
| fig.add_trace(go.Candlestick( | |
| x=df['timestamp'], | |
| open=df['open'], | |
| high=df['high'], | |
| low=df['low'], | |
| close=df['close'], | |
| name='Candles' | |
| )) | |
| fig.add_trace(go.Scatter(x=df['timestamp'], y=df['ema_50'], line=dict(color='orange'), name='EMA 50')) | |
| fig.add_trace(go.Scatter(x=df['timestamp'], y=df['ema_200'], line=dict(color='purple'), name='EMA 200')) | |
| bull = df[df['bullish_div']] | |
| bear = df[df['bearish_div']] | |
| fig.add_trace(go.Scatter( | |
| x=bull['timestamp'], | |
| y=bull['low'], | |
| mode='markers+text', | |
| text=['π']*len(bull), | |
| textposition="bottom center", | |
| marker=dict(color='green', size=10), | |
| name='Bullish RSI Divergence' | |
| )) | |
| fig.add_trace(go.Scatter( | |
| x=bear['timestamp'], | |
| y=bear['high'], | |
| mode='markers+text', | |
| text=['π']*len(bear), | |
| textposition="top center", | |
| marker=dict(color='red', size=10), | |
| name='Bearish RSI Divergence' | |
| )) | |
| fig.update_layout( | |
| title="Interactive Crypto Chart", | |
| xaxis_rangeslider_visible=False, | |
| xaxis_title="Time", | |
| yaxis_title="Price", | |
| template="plotly_dark", | |
| margin=dict(t=40, b=40), | |
| height=600 | |
| ) | |
| return fig | |
| # Gradio handler | |
| def analyze(pair, timeframe): | |
| try: | |
| df = fetch_ohlcv(pair, timeframe) | |
| if len(df) < 50: | |
| return "β οΈ Not enough data", go.Figure() | |
| signal = generate_signal(df) | |
| chart = plot_chart(df) | |
| return signal, chart | |
| except Exception as e: | |
| return f"β Error: {e}", go.Figure() | |
| # Available pairs and timeframes | |
| pairs = ['BTC/USDT', 'ETH/USDT', 'SOL/USDT', 'MX/USDT'] | |
| timeframes = ['1m', '5m', '15m', '1h', '4h'] | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## π Crypto Signal Generator with Interactive Chart") | |
| with gr.Row(): | |
| pair_dropdown = gr.Dropdown(choices=pairs, value='BTC/USDT', label="Trading Pair") | |
| timeframe_dropdown = gr.Dropdown(choices=timeframes, value='1h', label="Timeframe") | |
| run_button = gr.Button("π Analyze") | |
| signal_output = gr.Textbox(label="Trading Signal", interactive=False) | |
| chart_output = gr.Plot(label="Interactive Chart") | |
| run_button.click(fn=analyze, inputs=[pair_dropdown, timeframe_dropdown], outputs=[signal_output, chart_output]) | |
| demo.launch() | |