Spaces:
Sleeping
Sleeping
import pandas as pd | |
import numpy as np | |
import ccxt | |
import matplotlib.pyplot as plt | |
import matplotlib.dates as mdates | |
import time | |
import json | |
from datetime import datetime | |
import pytz | |
import telepot | |
import os | |
# Constants | |
BOT_TOKEN = '6787349532:AAGSwuiEJeykI2rQgsoB8C_iXZYKYuJyoOM' # Replace with your bot token | |
CHAT_ID = '-4284060853' # Replace with your chat ID | |
bot = telepot.Bot(BOT_TOKEN) | |
# Prompt for the symbol | |
symbols = ['ADA/USDT', 'ATOM/USDT', 'XRP/USDT'] | |
timeframes = ['1h', '4h'] | |
# Directories to save images | |
base_directory = '../zscore' | |
image_directory = os.path.join(base_directory, 'images') | |
os.makedirs(image_directory, exist_ok=True) | |
# Initialize Binance Futures API | |
binance = ccxt.bybit({ | |
'options': {'defaultType': 'future'}, # Specify futures | |
}) | |
def fetch_and_calculate_zscore(symbol, timeframe, limit=200, rolling_window=30): | |
# Fetch OHLCV data | |
data = binance.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit) | |
df = pd.DataFrame(data, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) | |
# Convert timestamp to UTC datetime format | |
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True) | |
# Calculate rolling mean, std, and Z-Score | |
df['mean'] = df['close'].rolling(window=rolling_window).mean() | |
df['std'] = df['close'].rolling(window=rolling_window).std() | |
df['z_score'] = (df['close'] - df['mean']) / df['std'] | |
# Initialize signal columns | |
df['buy_signal'] = 0 | |
df['sell_signal'] = 0 | |
# Variables to track thresholds | |
in_sell_signal = False | |
in_buy_signal = False | |
signal_triggered = False # Track if any signal was triggered | |
# Iterate through the dataframe to track signals | |
for i in range(1, len(df)): | |
current_z = df.loc[i, 'z_score'] | |
previous_z = df.loc[i - 1, 'z_score'] | |
# Handle Z-score crossing extreme thresholds for sell signal | |
if not in_sell_signal: | |
if current_z > 1.85 and previous_z <= 1.85: | |
in_sell_signal = True | |
# Handle Z-score crossing extreme thresholds for buy signal | |
if not in_buy_signal: | |
if current_z < -1.85 and previous_z >= -1.85: | |
in_buy_signal = True | |
# Keep the signal active if the Z-score remains within the range | |
if in_sell_signal: | |
if 1 <= current_z <= 1.85: | |
df.loc[i, 'sell_signal'] = 1 | |
signal_triggered = True | |
elif current_z < 1: | |
in_sell_signal = False | |
if in_buy_signal: | |
if -1.85 <= current_z <= -1: | |
df.loc[i, 'buy_signal'] = 1 | |
signal_triggered = True | |
elif current_z > -1: | |
in_buy_signal = False | |
return df | |
utc_time = datetime.utcnow() | |
philippine_tz = pytz.timezone('Asia/Manila') | |
philippine_time = pytz.utc.localize(utc_time).astimezone(philippine_tz) | |
formatted_ph_time = philippine_time.strftime("%Y-%m-%d %H:%M:%S") | |
# Function to update signals in JSON with real-time Z-Score | |
def update_signal_json(symbol, df, timeframe, json_data): | |
latest_data = df.iloc[-1] | |
signal_entry = { | |
"symbol": symbol, | |
"time_frame": timeframe, | |
"date_and_time": latest_data['timestamp'].strftime("%Y-%m-%d %H:%M:%S"), | |
"realtime_ph_time": formatted_ph_time, | |
"current_price": latest_data['close'], | |
"zscore": latest_data['z_score'] | |
} | |
json_data = [entry for entry in json_data if not (entry['symbol'] == symbol and entry['time_frame'] == timeframe)] | |
json_data.append(signal_entry) | |
return json_data | |
# Function to plot data for a single symbol including BTCDOM and BTC | |
def plot_data(pair_df, btcdom_df, btc_df, symbol, timeframe, ax): | |
ax.clear() | |
# Plot Z-Scores for all pairs | |
ax.plot(btcdom_df['timestamp'], btcdom_df['z_score'], label="BTCDOM/USDT Z-Score", color='blue', linestyle='-') | |
ax.plot(pair_df['timestamp'], pair_df['z_score'], label=f"{symbol} Z-Score", color='orange', linestyle='-') | |
ax.plot(btc_df['timestamp'], btc_df['z_score'], label="BTC/USDT Z-Score", color='gray', linestyle='-') | |
# Add thresholds | |
ax.axhline(y=2, color='red', linestyle='--', label='Overbought Threshold') | |
ax.axhline(y=-2, color='green', linestyle='--', label='Oversold Threshold') | |
# Plot Buy and Sell signals for the pair | |
ax.scatter(pair_df[pair_df['buy_signal'] == 1]['timestamp'], pair_df[pair_df['buy_signal'] == 1]['z_score'], | |
marker='^', color='green', label=f"{symbol} Buy Signal") | |
ax.scatter(pair_df[pair_df['sell_signal'] == 1]['timestamp'], pair_df[pair_df['sell_signal'] == 1]['z_score'], | |
marker='v', color='red', label=f"{symbol} Sell Signal") | |
# Format plot | |
ax.set_title(f"Z-Scores Signals {timeframe} for {symbol}", fontsize=16) | |
ax.set_xlabel("Time (UTC)", fontsize=12) | |
ax.set_ylabel("Z-Score", fontsize=12) | |
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d %H:%M")) | |
ax.legend(loc="upper left") | |
ax.grid(True) | |
plt.xticks(rotation=45) | |
# Real-time monitoring | |
def run_real_time(): | |
json_data = [] | |
try: | |
with open('signals.json', 'r') as file: | |
json_data = json.load(file) | |
except FileNotFoundError: | |
pass | |
while True: | |
for timeframe in timeframes: | |
btcdom_symbol = 'ETH/USDT' | |
btc_symbol = 'BTC/USDT' | |
btcdom_df = fetch_and_calculate_zscore(btcdom_symbol, timeframe) | |
btc_df = fetch_and_calculate_zscore(btc_symbol, timeframe) | |
# Send announcement message for the timeframe | |
message = f"{timeframe} time frame for {', '.join(symbols)}" | |
bot.sendMessage(chat_id=CHAT_ID, text=message) | |
media_group = [] | |
for symbol in symbols: | |
pair_df = fetch_and_calculate_zscore(symbol, timeframe) | |
# Update JSON for the pair, BTCDOM, and BTC | |
json_data = update_signal_json(symbol, pair_df, timeframe, json_data) | |
json_data = update_signal_json(btcdom_symbol, btcdom_df, timeframe, json_data) | |
json_data = update_signal_json(btc_symbol, btc_df, timeframe, json_data) | |
# Create a new figure for each symbol and timeframe | |
fig, ax = plt.subplots(figsize=(14, 7)) | |
plot_data(pair_df, btcdom_df, btc_df, symbol, timeframe, ax) | |
plt.tight_layout() | |
# Save image to the 'images' directory | |
image_path = os.path.join(image_directory, f"{symbol.lower().replace('/', '_')}_{timeframe}.png") | |
plt.savefig(image_path) | |
plt.close(fig) # Close the figure to free memory | |
# Add image to media group | |
media_group.append({'media': open(image_path, 'rb'), 'type': 'photo'}) | |
# Send the media group to Telegram | |
try: | |
bot.sendMediaGroup( | |
chat_id=CHAT_ID, | |
media=media_group, | |
disable_notification=True | |
) | |
print("Images uploaded successfully.") | |
except Exception as e: | |
print(f"Failed to send media group for {timeframe} to Telegram: {e}") | |
# Save updated JSON for both timeframes | |
with open('signals.json', 'w') as file: | |
json.dump(json_data, file, indent=4) | |
time.sleep(60) # Wait for 60 seconds before next update | |
# Run the real-time system | |
run_real_time() |