Zscore_Crypto / main_with_plot copy.py
gjin10969
initialize
e97cf97
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()