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()