# Remove Pandas Future Warnings import warnings from matplotlib.transforms import TransformNode warnings.simplefilter(action='ignore', category=FutureWarning) # General Imports from config_execution_api import signal_positive_ticker from config_execution_api import signal_negative_ticker from config_execution_api import volatility_check from config_execution_api import profit_target from config_execution_api import spread_exit from config_execution_api import hedge_ratio from config_execution_api import stop_loss_fail_safe from func_get_price import get_latest_price from func_position_calls import open_position_confirmation from func_position_calls import active_position_confirmation from func_trade_management import manage_new_trades from func_execution_calls import set_leverage from func_close_positions import close_all_positions from func_get_zscore import get_latest_zscore #from config_ws_connect import ws_public # <- original code websocket method from config_ws_connect import ws_public_get_orderbook # <- new websocket method from config_ws_connect import subs_public from func_save_status import save_status from requests.exceptions import ConnectionError, Timeout, RequestException from exceptions import FailedRequestError, InvalidRequestError from json.decoder import JSONDecodeError from config_execution_api import signal_trigger_thresh from func_get_time import convert_time from func_position_calls import get_closed_pnl_info from func_position_calls import get_position_info from tabulate import tabulate from func_check_volatility import check_volatility from func_calcultions import get_trade_details import time import datetime import schedule as sd import pandas as pd import os.path import os import sys """ RUN STATBOT """ if __name__ == "__main__": # Initial printout print("StatBot initiated...") # Initialise variables status_dict = {"message": "starting..."} order_long = {} order_short = {} signal_sign_positive = False signal_side = "" kill_switch = 0 start_time = 0 long_order_qty = 0 long_order_time = "" long_order_price = 0 short_order_qty = 0 short_order_time = "" short_order_price = 0 long_ticker = "" short_ticker = "" long_ticker_pnl = 0 short_ticker_pnl = 0 zscore_entry = 0 zscore_exit = 0 exception = False low_volatility = True long_pnl_un = 0 short_pnl_un = 0 long_pos_value = 0 short_pos_value = 0 net_pnl_un = 0 net_pos_value = 0 neg_price = 0 pos_price = 0 spread = 0 # Save status save_status(status_dict) # Set leverage in case forgotten to do so on the platform print("Setting leverage...") set_leverage(signal_positive_ticker) set_leverage(signal_negative_ticker) # Commence bot print("Seeking trades...") while True: # Keep alive try: #trade = ws_public.fetch(subs_public[0]) # <- original code websocket method trade = ws_public_get_orderbook(subs_public[0]) # <- new websocket method # pos_orderbook = ws_public.fetch(f"orderBookL2_25.{signal_positive_ticker}") # neg_orderbook = ws_public.fetch(f"orderBookL2_25.{signal_negative_ticker}") # print("\n") # print('-------------------------------------------------------------------') # print("Main") # print(pos_orderbook) # print(neg_orderbook) # print('-------------------------------------------------------------------') # print("\n") except (ConnectionError, Timeout, RequestException, JSONDecodeError, FailedRequestError, InvalidRequestError) as e: print(e) continue # Pause - protect API time.sleep(3) # Check if open trades already exist is_p_ticker_open = open_position_confirmation(signal_positive_ticker) is_n_ticker_open = open_position_confirmation(signal_negative_ticker) is_p_ticker_active = active_position_confirmation(signal_positive_ticker) is_n_ticker_active = active_position_confirmation(signal_negative_ticker) checks_all = [is_p_ticker_open, is_n_ticker_open, is_p_ticker_active, is_n_ticker_active] is_manage_new_trades = not any(checks_all) print("Manage new trade: ", is_manage_new_trades) # Save status status_dict["message"] = "Initial checks made..." status_dict["checks"] = checks_all save_status(status_dict) if not is_manage_new_trades and kill_switch == 0: # Close pending position(s) which was/were failed to be closed (e.g. cancelled) kill_switch = 2 # Check for signal and place new trades if is_manage_new_trades and kill_switch == 0: status_dict["message"] = "Managing new trades..." save_status(status_dict) print("Manage new trade") kill_switch, signal_side, long_order_qty, long_order_time, long_order_price, short_order_qty, short_order_time, short_order_price, zscore_entry, exception = manage_new_trades(kill_switch) #print(kill_switch, signal_side, long_order_qty, long_order_time, long_order_price, short_order_qty, short_order_time, short_order_price, zscore_entry, exception) print(f"") if long_order_time and short_order_time: start_time = convert_time(long_order_time) #min(convert_time(long_order_time), convert_time(short_order_time)) if exception: continue print("Kill switch: ",kill_switch) # Managing open kill switch if positions change or should reach 2 # Check for signal to be false if kill_switch == 1: # Get and save the latest z-score zscore, signal_sign_positive, exception = get_latest_zscore() if exception: continue # Get and print datetime now = datetime.datetime.now() current_time = now.strftime("%Y-%m-%d %H:%M") print(f"Datetime: {current_time},", f"Z-score: {round(zscore,2)}") print("Signal side (kill switch=1): ",signal_side) # Bot 2 exit - not hot <--Copied from Bonus # if abs(zscore) < signal_trigger_thresh: # kill_switch = 2 # zscore_exit = zscore #Close positions - Mean Reversion Exit (Option #1) # if signal_side == "positive" and zscore < -signal_trigger_thresh: # zscore < -signal_trigger_thresh for extreme opposite exit # kill_switch = 2 # long_ticker = signal_positive_ticker # short_ticker = signal_negative_ticker # zscore_exit = zscore # if signal_side == "negative" and zscore >= signal_trigger_thresh: # zscore >= signal_trigger_thresh for extreme opposite exit # kill_switch = 2 # long_ticker = signal_negative_ticker # short_ticker = signal_positive_ticker # zscore_exit = zscore if signal_side == "positive": long_ticker = signal_positive_ticker short_ticker = signal_negative_ticker if zscore < -signal_trigger_thresh: kill_switch =2 zscore_exit = zscore if signal_side == "negative": long_ticker = signal_negative_ticker short_ticker = signal_positive_ticker if zscore >= signal_trigger_thresh: kill_switch =2 zscore_exit = zscore _, _, long_pnl_un, long_pos_value, exception = get_position_info(long_ticker) print("Long ticker: ", long_ticker, " Long PNL un: ", long_pnl_un, " Long POS value: ", long_pos_value ) if exception: continue _, _, short_pnl_un, short_pos_value, exception = get_position_info(short_ticker) print("Short ticker: ", short_ticker, " Short PNL un: ", short_pnl_un, " Long POS value: ", short_pos_value ) if exception: continue net_pnl_un = long_pnl_un + short_pnl_un net_pos_value = long_pos_value + short_pos_value print("Net POS value: ",net_pos_value," Net PNL value: ", net_pnl_un, " Current Profit ratio: ", net_pnl_un/(net_pos_value-net_pnl_un), "\n") if (net_pnl_un/(net_pos_value-net_pnl_un)) < -stop_loss_fail_safe: kill_switch = 2 print("Current PnL: ", round(net_pnl_un/(net_pos_value-net_pnl_un),2),"vs Stop Loss: ", -stop_loss_fail_safe) # # Put back to zero if trades are closed <-- DON'T UNCOMMENT this original code. See remarks below # print("Manage new trade: ", is_manage_new_trades, "Kill switch: ", kill_switch) # if is_manage_new_trades and kill_switch != 2: <- This will always force kill_switch = 0 in the 1st round of loop b4 is_manage_new_trade changes status # kill_switch = 0 # Close positions - Profit% Exit (Option #2) # if signal_side == "positive": # long_ticker = signal_positive_ticker # short_ticker = signal_negative_ticker # if signal_side == "negative": # long_ticker = signal_negative_ticker # short_ticker = signal_positive_ticker # _, _, long_pnl_un, long_pos_value, exception = get_position_info(long_ticker) # print("Long ticker: ", long_ticker, " Long PNL un: ", long_pnl_un, " Long POS value: ", long_pos_value ) # if exception: # continue # _, _, short_pnl_un, short_pos_value, exception = get_position_info(short_ticker) # print("Short ticker: ", short_ticker, " Short PNL un: ", short_pnl_un, " Long POS value: ", short_pos_value ) # if exception: # continue # net_pnl_un = long_pnl_un + short_pnl_un # net_pos_value = long_pos_value + short_pos_value # print("Net POS value: ",net_pos_value," Net PNL value: ", net_pnl_un, " Current Profit ratio: ", net_pnl_un/(net_pos_value-net_pnl_un), "\n") # if (net_pnl_un/(net_pos_value-net_pnl_un))> profit_target or (net_pnl_un/(net_pos_value-net_pnl_un)) < -stop_loss_fail_safe: # kill_switch = 2 # print("Current PnL: ", net_pnl_un/(net_pos_value-net_pnl_un),"vs Profit Target: ", profit_target, "vs Stop Loss: ", -stop_loss_fail_safe) # Close positions - Zero Spread Exit (Option #3) # if signal_side == "positive": # long_ticker = signal_positive_ticker # short_ticker = signal_negative_ticker # pos_price = get_latest_price(long_ticker,'Buy') # neg_price = get_latest_price(short_ticker, 'Sell') # spread = neg_price - hedge_ratio * pos_price # if spread < spread_exit: # kill_switch = 2 # print("Long ticker: ", long_ticker, " Long price: ", pos_price, " Short ticker: ", short_ticker, " Short price: ", neg_price) # else: # long_ticker = signal_negative_ticker # short_ticker = signal_positive_ticker # neg_price = get_latest_price(long_ticker,'Buy') # pos_price = get_latest_price(short_ticker, 'Sell') # spread = hedge_ratio * pos_price - neg_price # if spread < spread_exit: # kill_switch = 2 # print("Long ticker: ", long_ticker, " Long price: ", neg_price, " Short ticker: ", short_ticker, " Short price: ", pos_price) # print("Current Spread: ", spread, "\n") # _, _, long_pnl_un, long_pos_value, exception = get_position_info(long_ticker) # print("Long ticker: ", long_ticker, " Long PNL un: ", long_pnl_un, " Long POS value: ", long_pos_value ) # if exception: # continue # _, _, short_pnl_un, short_pos_value, exception = get_position_info(short_ticker) # print("Short ticker: ", short_ticker, " Short PNL un: ", short_pnl_un, " Long POS value: ", short_pos_value ) # if exception: # continue # net_pnl_un = long_pnl_un + short_pnl_un # net_pos_value = long_pos_value + short_pos_value # print("Net POS value: ",net_pos_value," Net PNL value: ", net_pnl_un, " Current Profit ratio: ", net_pnl_un/(net_pos_value-net_pnl_un), "\n") # if (net_pnl_un/(net_pos_value-net_pnl_un)) < -stop_loss_fail_safe: # kill_switch = 2 # print("Current PnL: ", net_pnl_un/(net_pos_value-net_pnl_un),"vs Stop Loss: ", -stop_loss_fail_safe) # Close all active orders and positions if kill_switch == 2: if volatility_check: low_volatility = not any ([check_volatility(signal_positive_ticker), check_volatility(signal_negative_ticker)]) if low_volatility: print("Low Volatile Market - Ready for Exit") print("Closing all positions...") status_dict["message"] = "Closing existing trades..." save_status(status_dict) kill_switch, close_long_order_qty, close_long_order_time, close_long_order_price, close_short_order_qty, close_short_order_time, close_short_order_price = close_all_positions(kill_switch, long_ticker, short_ticker) long_ticker_pnl,_ = get_closed_pnl_info(long_ticker,start_time) short_ticker_pnl,_ = get_closed_pnl_info(short_ticker,start_time) print("-------------") print("Trade Summary") print("-------------") df = pd.DataFrame({ 'Long symbol' : [long_ticker], 'Open Long qty' : [long_order_qty], 'Open Long time' : [long_order_time], 'Open Long price' : [long_order_price], 'Close Long time' : [close_long_order_time], 'Close Long price' : [close_long_order_price], 'Long PnL' : [round(long_ticker_pnl,2)], 'Short symbol' : [short_ticker], 'Open Short qty' : [short_order_qty], 'Open Short time' : [short_order_time], 'Open Short price' : [short_order_price], 'Close Short time' : [close_short_order_time], 'Close Short price' : [close_short_order_price], 'Short PnL' : [round(short_ticker_pnl,2)], 'Net PnL' : [round((long_ticker_pnl+short_ticker_pnl),2)], 'Z score thld' : [signal_trigger_thresh], 'Z score entry' : [round(zscore_entry,2)], 'Z score exit' : [round(zscore_exit,2)]}) print(tabulate(df, headers='keys', tablefmt='psql', showindex=False)) if(os.path.isfile("4_trade_summary.csv")): df.to_csv("4_trade_summary.csv", mode='a', index= False,header=False) else: df.to_csv("4_trade_summary.csv", index= False) print("File for trade summary saved.") # Sleep for 5 seconds time.sleep(5)