Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,96 +3,115 @@ import pandas as pd
|
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
import matplotlib.dates as mdates
|
| 5 |
from io import BytesIO
|
| 6 |
-
import gradio as gr
|
| 7 |
-
from PIL import Image
|
| 8 |
from PIL import Image
|
|
|
|
| 9 |
|
| 10 |
-
# Fetch
|
| 11 |
-
def fetch_ohlcv(symbol='BTC/USDT', timeframe='1h', limit=
|
| 12 |
exchange = ccxt.mexc()
|
| 13 |
ohlcv = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit)
|
| 14 |
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
| 15 |
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
|
| 16 |
return df
|
| 17 |
|
| 18 |
-
# Calculate indicators
|
| 19 |
-
def
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
else:
|
| 54 |
-
return "HOLD"
|
| 55 |
|
| 56 |
-
#
|
| 57 |
-
def
|
| 58 |
-
df = df.
|
| 59 |
df['timestamp'] = pd.to_datetime(df['timestamp'])
|
| 60 |
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
|
|
|
| 63 |
for _, row in df.iterrows():
|
| 64 |
color = 'green' if row['close'] >= row['open'] else 'red'
|
| 65 |
-
ax.plot([row['timestamp'], row['timestamp']], [row['low'], row['high']], color='black')
|
| 66 |
-
ax.plot([row['timestamp'], row['timestamp']], [row['open'], row['close']], color=color, linewidth=
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
ax.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
plt.xticks(rotation=45)
|
| 71 |
-
plt.title(
|
| 72 |
plt.tight_layout()
|
| 73 |
|
| 74 |
-
# Save chart to image object
|
| 75 |
buf = BytesIO()
|
| 76 |
plt.savefig(buf, format='png')
|
| 77 |
buf.seek(0)
|
| 78 |
plt.close(fig)
|
| 79 |
return Image.open(buf)
|
| 80 |
|
| 81 |
-
|
| 82 |
-
# Main function
|
| 83 |
def analyze(pair, timeframe):
|
| 84 |
try:
|
| 85 |
-
df = fetch_ohlcv(
|
| 86 |
if df.empty:
|
| 87 |
-
return "β No data
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
return f"π Signal: {signal}", chart
|
| 92 |
except Exception as e:
|
| 93 |
return f"β Error: {str(e)}", None
|
| 94 |
|
| 95 |
-
# Gradio UI
|
| 96 |
pairs = ['BTC/USDT', 'ETH/USDT', 'MX/USDT', 'SOL/USDT']
|
| 97 |
timeframes = ['1m', '5m', '15m', '1h', '4h']
|
| 98 |
|
|
@@ -103,9 +122,9 @@ gr.Interface(
|
|
| 103 |
gr.Dropdown(choices=timeframes, label="Timeframe")
|
| 104 |
],
|
| 105 |
outputs=[
|
| 106 |
-
gr.Text(label="
|
| 107 |
-
gr.Image(label="
|
| 108 |
],
|
| 109 |
-
title="
|
| 110 |
-
description="
|
| 111 |
).launch()
|
|
|
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
import matplotlib.dates as mdates
|
| 5 |
from io import BytesIO
|
|
|
|
|
|
|
| 6 |
from PIL import Image
|
| 7 |
+
import gradio as gr
|
| 8 |
|
| 9 |
+
# π Fetch data from MEXC
|
| 10 |
+
def fetch_ohlcv(symbol='BTC/USDT', timeframe='1h', limit=150):
|
| 11 |
exchange = ccxt.mexc()
|
| 12 |
ohlcv = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit)
|
| 13 |
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
| 14 |
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
|
| 15 |
return df
|
| 16 |
|
| 17 |
+
# π Calculate indicators
|
| 18 |
+
def calculate_ema(df, span):
|
| 19 |
+
return df['close'].ewm(span=span, adjust=False).mean()
|
| 20 |
+
|
| 21 |
+
def calculate_supertrend(df, period=10, multiplier=3):
|
| 22 |
+
atr = df['high'].rolling(period).max() - df['low'].rolling(period).min()
|
| 23 |
+
atr = atr.rolling(period).mean()
|
| 24 |
+
|
| 25 |
+
hl2 = (df['high'] + df['low']) / 2
|
| 26 |
+
upperband = hl2 + multiplier * atr
|
| 27 |
+
lowerband = hl2 - multiplier * atr
|
| 28 |
+
|
| 29 |
+
supertrend = [True] # True for bullish, False for bearish
|
| 30 |
+
for i in range(1, len(df)):
|
| 31 |
+
if df['close'][i] > upperband[i - 1]:
|
| 32 |
+
supertrend.append(True)
|
| 33 |
+
elif df['close'][i] < lowerband[i - 1]:
|
| 34 |
+
supertrend.append(False)
|
| 35 |
+
else:
|
| 36 |
+
supertrend.append(supertrend[i - 1])
|
| 37 |
+
return supertrend
|
| 38 |
+
|
| 39 |
+
# π Generate signal logic
|
| 40 |
+
def generate_combined_signal(df):
|
| 41 |
+
df['ema_50'] = calculate_ema(df, 50)
|
| 42 |
+
df['ema_200'] = calculate_ema(df, 200)
|
| 43 |
+
df['supertrend'] = calculate_supertrend(df)
|
| 44 |
+
|
| 45 |
+
ema_signal = None
|
| 46 |
+
if df['ema_50'].iloc[-1] > df['ema_200'].iloc[-1]:
|
| 47 |
+
ema_signal = 'BULLISH'
|
| 48 |
+
elif df['ema_50'].iloc[-1] < df['ema_200'].iloc[-1]:
|
| 49 |
+
ema_signal = 'BEARISH'
|
| 50 |
+
|
| 51 |
+
supertrend_signal = 'BULLISH' if df['supertrend'].iloc[-1] else 'BEARISH'
|
| 52 |
+
|
| 53 |
+
if ema_signal == 'BULLISH' and supertrend_signal == 'BULLISH':
|
| 54 |
+
return "π₯ STRONG BUY"
|
| 55 |
+
elif ema_signal == 'BEARISH' and supertrend_signal == 'BEARISH':
|
| 56 |
+
return "π STRONG SELL"
|
| 57 |
+
elif ema_signal == supertrend_signal:
|
| 58 |
+
return f"β οΈ {ema_signal}"
|
| 59 |
else:
|
| 60 |
+
return "π€ NEUTRAL / HOLD"
|
| 61 |
|
| 62 |
+
# π Candlestick + indicator chart
|
| 63 |
+
def plot_chart(df):
|
| 64 |
+
df = df.copy().tail(100)
|
| 65 |
df['timestamp'] = pd.to_datetime(df['timestamp'])
|
| 66 |
|
| 67 |
+
df['ema_50'] = calculate_ema(df, 50)
|
| 68 |
+
df['ema_200'] = calculate_ema(df, 200)
|
| 69 |
+
df['supertrend'] = calculate_supertrend(df)
|
| 70 |
+
|
| 71 |
+
fig, ax = plt.subplots(figsize=(10, 5))
|
| 72 |
|
| 73 |
+
# Plot candles
|
| 74 |
for _, row in df.iterrows():
|
| 75 |
color = 'green' if row['close'] >= row['open'] else 'red'
|
| 76 |
+
ax.plot([row['timestamp'], row['timestamp']], [row['low'], row['high']], color='black', linewidth=1)
|
| 77 |
+
ax.plot([row['timestamp'], row['timestamp']], [row['open'], row['close']], color=color, linewidth=4)
|
| 78 |
+
|
| 79 |
+
# Plot EMAs
|
| 80 |
+
ax.plot(df['timestamp'], df['ema_50'], label='EMA 50', color='orange', linewidth=1.5)
|
| 81 |
+
ax.plot(df['timestamp'], df['ema_200'], label='EMA 200', color='purple', linewidth=1.5)
|
| 82 |
+
|
| 83 |
+
# Plot Supertrend as dots
|
| 84 |
+
for i in range(1, len(df)):
|
| 85 |
+
if df['supertrend'].iloc[i]:
|
| 86 |
+
ax.scatter(df['timestamp'].iloc[i], df['low'].iloc[i] - 0.5, color='green', marker='^', label='Buy' if i == 1 else "", s=60)
|
| 87 |
+
else:
|
| 88 |
+
ax.scatter(df['timestamp'].iloc[i], df['high'].iloc[i] + 0.5, color='red', marker='v', label='Sell' if i == 1 else "", s=60)
|
| 89 |
+
|
| 90 |
+
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d %H:%M'))
|
| 91 |
+
ax.legend()
|
| 92 |
plt.xticks(rotation=45)
|
| 93 |
+
plt.title("Crypto Chart with LuxAlgo-Inspired Signals")
|
| 94 |
plt.tight_layout()
|
| 95 |
|
|
|
|
| 96 |
buf = BytesIO()
|
| 97 |
plt.savefig(buf, format='png')
|
| 98 |
buf.seek(0)
|
| 99 |
plt.close(fig)
|
| 100 |
return Image.open(buf)
|
| 101 |
|
| 102 |
+
# π Main analysis
|
|
|
|
| 103 |
def analyze(pair, timeframe):
|
| 104 |
try:
|
| 105 |
+
df = fetch_ohlcv(pair, timeframe)
|
| 106 |
if df.empty:
|
| 107 |
+
return "β No data available", None
|
| 108 |
+
signal = generate_combined_signal(df)
|
| 109 |
+
chart = plot_chart(df)
|
| 110 |
+
return signal, chart
|
|
|
|
| 111 |
except Exception as e:
|
| 112 |
return f"β Error: {str(e)}", None
|
| 113 |
|
| 114 |
+
# π Gradio UI
|
| 115 |
pairs = ['BTC/USDT', 'ETH/USDT', 'MX/USDT', 'SOL/USDT']
|
| 116 |
timeframes = ['1m', '5m', '15m', '1h', '4h']
|
| 117 |
|
|
|
|
| 122 |
gr.Dropdown(choices=timeframes, label="Timeframe")
|
| 123 |
],
|
| 124 |
outputs=[
|
| 125 |
+
gr.Text(label="LuxAlgo-Inspired Signal"),
|
| 126 |
+
gr.Image(label="Chart with Indicators")
|
| 127 |
],
|
| 128 |
+
title="π‘ Crypto Signal Generator (Inspired by LuxAlgo)",
|
| 129 |
+
description="Signals based on EMA Cross & SuperTrend, visualized with candlestick chart and arrows."
|
| 130 |
).launch()
|