Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import ccxt | |
| import matplotlib.pyplot as plt | |
| import matplotlib.dates as mdates | |
| import json | |
| from datetime import datetime, timedelta | |
| import pytz | |
| # Prompt for the symbol and time frame | |
| symbols = input('Please input Symbol: ') | |
| timeframe = input("Please input time frame: ") | |
| # Initialize Binance Futures API | |
| binance = ccxt.binance({ | |
| 'options': {'defaultType': 'future'}, # Specify futures | |
| }) | |
| # Function to fetch historical data and calculate Z-Score | |
| def fetch_and_calculate_zscore(symbol, timeframe, since, limit=200, rolling_window=30): | |
| data = binance.fetch_ohlcv(symbol, timeframe=timeframe, since=since, 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: | |
| # Z-score crosses above 1.85 (potential sell signal) | |
| if current_z > 1.85 and previous_z <= 1.85: | |
| print(f"Sell signal candidate at index {i}, Z-score = {current_z}") | |
| in_sell_signal = True | |
| # Handle Z-score crossing extreme thresholds for buy signal | |
| if not in_buy_signal: | |
| # Z-score crosses below -1.85 (potential buy signal) | |
| if current_z < -1.85 and previous_z >= -1.85: | |
| print(f"Buy signal candidate at index {i}, Z-score = {current_z}") | |
| in_buy_signal = True | |
| # Keep the signal active if the Z-score remains within the range | |
| if in_sell_signal: | |
| # Sell signal is triggered between 1.85 and 1 | |
| if 1 <= current_z <= 1.85: | |
| df.loc[i, 'sell_signal'] = 1 # Sell signal active | |
| print(f"Sell signal active at index {i}, Z-score = {current_z}") | |
| signal_triggered = True | |
| # Exit sell signal if Z-score falls below 1 | |
| elif current_z < 1: | |
| in_sell_signal = False | |
| print(f"Sell signal exited at index {i}, Z-score = {current_z}") | |
| if in_buy_signal: | |
| # Buy signal is triggered between -1.85 and -1 | |
| if -1.85 <= current_z <= -1: | |
| df.loc[i, 'buy_signal'] = 1 # Buy signal active | |
| print(f"Buy signal active at index {i}, Z-score = {current_z}") | |
| signal_triggered = True | |
| # Exit buy signal if Z-score rises above -1 | |
| elif current_z > -1: | |
| in_buy_signal = False | |
| print(f"Buy signal exited at index {i}, Z-score = {current_z}") | |
| return df | |
| # Convert time to local timezone (Philippine Time) | |
| utc_time = datetime.utcnow() | |
| philippine_tz = pytz.timezone('Asia/Manila') | |
| philippine_time = pytz.utc.localize(utc_time).astimezone(philippine_tz) | |
| # Format the time in your preferred format | |
| formatted_ph_time = philippine_time.strftime("%Y-%m-%d %H:%M:%S") | |
| # Function to update signals in JSON with Z-Score (Appending to file) | |
| def update_signal_json(symbol, df, json_data): | |
| # Extract latest data point | |
| latest_data = df.iloc[-1] | |
| # Check if the latest Z-score has a signal | |
| signal_status = "True" if latest_data['buy_signal'] == 1 or latest_data['sell_signal'] == 1 else "False" | |
| # Prepare new entry with real-time Z-Score | |
| 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, # Add the local Philippine time (UTC+8) | |
| "current_price": latest_data['close'], | |
| "zscore": latest_data['z_score'], | |
| "detection": signal_status # Add signal status | |
| } | |
| # Append new data to the existing list in json_data | |
| json_data.append(signal_entry) | |
| return json_data | |
| # Function to plot data | |
| def plot_data(btcdom_df, pair_df, btc_df, ax): | |
| ax.clear() # Clear previous plots | |
| # 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"{symbols}/USDT 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 BTCDOM/USDT | |
| ax.scatter(btcdom_df[btcdom_df['buy_signal'] == 1]['timestamp'], btcdom_df[btcdom_df['buy_signal'] == 1]['z_score'], | |
| marker='^', color='green', label='BTCDOM Buy Signal') | |
| ax.scatter(btcdom_df[btcdom_df['sell_signal'] == 1]['timestamp'], btcdom_df[btcdom_df['sell_signal'] == 1]['z_score'], | |
| marker='v', color='red', label='BTCDOM Sell Signal') | |
| # Plot signals for the other pair | |
| ax.scatter(pair_df[pair_df['buy_signal'] == 1]['timestamp'], pair_df[pair_df['buy_signal'] == 1]['z_score'], | |
| marker='^', color='green', alpha=0.5, label=f"{symbols} 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', alpha=0.5, label=f"{symbols} Sell Signal") | |
| # Format plot | |
| ax.set_title(f"Z-Scores Signals {timeframe} for {symbols}/USDT Futures", 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) | |
| plt.draw() # Redraw the plot | |
| plt.pause(0.1) # Pause to allow plot to update | |
| # Function to run historical data processing | |
| def run_historical(): | |
| json_data = [] | |
| try: | |
| with open('signals.json', 'r') as file: | |
| json_data = json.load(file) | |
| except FileNotFoundError: | |
| pass | |
| fig, ax = plt.subplots(figsize=(14, 7)) | |
| # Set start and end dates for the loop | |
| start_date = datetime(2023, 1, 1) | |
| end_date = datetime(2024, 1, 1) | |
| # Loop through each month in the date range (or week, depending on your choice) | |
| current_date = start_date | |
| while current_date < end_date: | |
| # Set 'since' to the start of each month or week (whichever you prefer) | |
| since = binance.parse8601(current_date.strftime('%Y-%m-%dT%H:%M:%SZ')) | |
| btcdom_symbol = 'BTCDOM/USDT' | |
| pair_symbol = f'{symbols}/USDT' | |
| btc_symbol = 'BTC/USDT' | |
| # Fetch and process data | |
| btcdom_df = fetch_and_calculate_zscore(btcdom_symbol, timeframe, since) | |
| pair_df = fetch_and_calculate_zscore(pair_symbol, timeframe, since) | |
| btc_df = fetch_and_calculate_zscore(btc_symbol, timeframe, since) | |
| # Update signals and append to JSON | |
| json_data = update_signal_json(pair_symbol, pair_df, json_data) | |
| json_data = update_signal_json(btc_symbol, btc_df, json_data) | |
| json_data = update_signal_json(btcdom_symbol, btcdom_df, json_data) | |
| # Save updated signals to JSON | |
| with open('signals.json', 'w') as file: | |
| json.dump(json_data, file, indent=4) | |
| # Plot the data | |
| plot_data(btcdom_df, pair_df, btc_df, ax) | |
| # Display the plot after each loop | |
| plt.show() # Show the plot for the current iteration | |
| # Move to the next chunk (next month/week) | |
| current_date += timedelta(weeks=4) | |
| # Run the historical data processing | |
| run_historical() | |