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"})
])
@app.callback(
Output("selected-timeframe", "data"),
Input({'type': 'tf-button', 'index': dash.dependencies.ALL}, 'n_clicks')
)
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
@app.callback(
[Output("chart", "figure"), Output("signal-box", "children")],
[Input("pair-dropdown", "value"), Input("selected-timeframe", "data")]
)
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)