Compare commits
No commits in common. "main" and "2025.10.12" have entirely different histories.
main
...
2025.10.12
|
|
@ -1,20 +1,3 @@
|
|||
2025.12.01:
|
||||
. Modified log output of new_market_order.
|
||||
. Modified Kucoin's case in min_amount_of_base.
|
||||
|
||||
2025.11.11:
|
||||
. deals_cache and log_list cache are now 20 items long.
|
||||
. Less log spam.
|
||||
|
||||
2025.11.08:
|
||||
. broker.set_default_order_size() now saves the config file to disk after changing the value.
|
||||
. Variable renaming and other small stuff.
|
||||
|
||||
2025.10.24:
|
||||
. Toggling liquidate_after_switch now writes the config file to disk so the setting persists between trades.
|
||||
. Manually switching to long now sets double_check_price to false.
|
||||
. Added a few comments to switch_to_long.
|
||||
|
||||
2025.10.12:
|
||||
. do_cleanup relocated after generating the safety orders' prices.
|
||||
|
||||
|
|
|
|||
|
|
@ -252,7 +252,6 @@ class ConfigHandler:
|
|||
# self.broker.logger.log_this(f"liquidate_after_switch must be a boolean",1,self.get_pair())
|
||||
# return 1
|
||||
self.config_dictionary["liquidate_after_switch"] = liquidate_after_switch
|
||||
self.save_to_file()
|
||||
return 0
|
||||
|
||||
def set_tp_mode(self, tp_mode: int):
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class Broker:
|
|||
self.markets = self.exchange.load_markets()
|
||||
|
||||
#Populates deals cache
|
||||
self.deals_cache_length = 20
|
||||
self.deals_cache_length = 10
|
||||
self.deals_list = self.preload_deals(amount_to_preload=self.deals_cache_length)
|
||||
|
||||
|
||||
|
|
@ -224,7 +224,6 @@ class Broker:
|
|||
def set_default_order_size(self,size):
|
||||
try:
|
||||
self.broker_config["default_order_size"] = float(size)
|
||||
self.rewrite_config_file()
|
||||
except Exception as e:
|
||||
self.logger.log_this(f"Exception in set_default_order_size: {e}",1)
|
||||
return 1
|
||||
|
|
@ -789,7 +788,7 @@ class Broker:
|
|||
|
||||
return self.get_order(order_to_send["id"],symbol)
|
||||
except Exception as e:
|
||||
self.logger.log_this(f"Exception in new_market_order: {e} - Side: {side} - Size: {size}",1,symbol)
|
||||
self.logger.log_this(f"Exception in new_market_order: {e}",1,symbol)
|
||||
if no_retries:
|
||||
break
|
||||
time.sleep(self.wait_time)
|
||||
|
|
@ -988,7 +987,7 @@ class Broker:
|
|||
if self.get_exchange_name() in ["okex","bybit"]:
|
||||
return float(market["limits"]["amount"]["min"])
|
||||
elif self.get_exchange_name() in ["kucoin"]:
|
||||
return max(float(market["limits"]["amount"]["min"]),(float(market["limits"]["cost"]["min"])+.25)/self.get_ticker_price(pair))
|
||||
return (float(market["limits"]["cost"]["min"])+.25)/self.get_ticker_price(pair)
|
||||
elif self.get_exchange_name() in ["gateio"]:
|
||||
return (float(market["limits"]["cost"]["min"])+.1)/self.get_ticker_price(pair)
|
||||
elif self.get_exchange_name()=="binance":
|
||||
|
|
@ -1052,7 +1051,7 @@ class Logger:
|
|||
self.broker_config = broker_config
|
||||
self.exchange_name = self.broker_config["exchange"]
|
||||
self.tg_credentials = credentials.get_credentials("telegram")
|
||||
self.log_list_max_length = 20 # log cache
|
||||
self.log_list_max_length = 10
|
||||
self.log_list = collections.deque(maxlen=self.log_list_max_length)
|
||||
self.preload_logs()
|
||||
|
||||
|
|
|
|||
4
main.py
4
main.py
|
|
@ -18,7 +18,7 @@ import exchange_wrapper
|
|||
import trader
|
||||
|
||||
|
||||
version = "2025.12.01"
|
||||
version = "2025.10.12"
|
||||
|
||||
'''
|
||||
Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
|
|
@ -1642,7 +1642,7 @@ def unwrapped_switch_to_long(base,quote,calculate_profits):
|
|||
for instance in running_traders:
|
||||
if f"{base}/{quote}"==instance.status.get_pair():
|
||||
instance.set_pause(True, "Switching to long mode")
|
||||
if instance.switch_to_long(ignore_old_long=ignore_old_long,double_check_price=False)==1:
|
||||
if instance.switch_to_long(ignore_old_long=ignore_old_long)==1:
|
||||
return jsonify({"Error": "Error in switch_to_long()"})
|
||||
if instance.start_trader()==1:
|
||||
instance.quit = True
|
||||
|
|
|
|||
37
trader.py
37
trader.py
|
|
@ -42,8 +42,8 @@ class trader:
|
|||
if self.config.get_is_short():
|
||||
#Check if there is an old_long file. If so, load it.
|
||||
try:
|
||||
with open(f"status/{self.base}{self.quote}.oldlong") as old_long_file_handler:
|
||||
self.status.set_old_long(load(old_long_file_handler))
|
||||
with open(f"status/{self.base}{self.quote}.oldlong") as ol:
|
||||
self.status.set_old_long(load(ol))
|
||||
except Exception as e:
|
||||
self.broker.logger.log_this(f"Exception: No old_long file. {e}",1,base_quote)
|
||||
|
||||
|
|
@ -572,8 +572,8 @@ class trader:
|
|||
"datetime": time.strftime("[%Y/%m/%d %H:%M:%S]")
|
||||
})
|
||||
try:
|
||||
with open(f"status/{self.base}{self.quote}.oldlong","w") as old_long_file_handler:
|
||||
old_long_file_handler.write(dumps(self.status.get_old_long(),indent=4))
|
||||
with open(f"status/{self.base}{self.quote}.oldlong","w") as s:
|
||||
s.write(dumps(self.status.get_old_long(),indent=4))
|
||||
except Exception as e:
|
||||
self.broker.logger.log_this(f"Exception while saving old_long file: {e}",1,self.status.get_pair())
|
||||
|
||||
|
|
@ -606,19 +606,17 @@ class trader:
|
|||
|
||||
if double_check_price:
|
||||
#Waits a moment to see if the price has moved too much
|
||||
self.broker.logger.log_this("Confirming price...",2,self.status.get_pair())
|
||||
time.sleep(self.broker.get_wait_time()*4)
|
||||
if not self.check_old_long(True):
|
||||
self.broker.logger.log_this("False positive. Nothing to do.",1,self.status.get_pair())
|
||||
return 2
|
||||
|
||||
#Check old_long data
|
||||
self.broker.logger.log_this("Checking if old long data is valid.",2,self.status.get_pair())
|
||||
if not ignore_old_long and self.status.get_old_long()=={}:
|
||||
self.broker.logger.log_this("Can't find old long info on status_dict, searching for oldlong file",1,self.status.get_pair())
|
||||
try:
|
||||
with open(f"status/{self.base}{self.quote}.oldlong") as old_long_file_handler:
|
||||
self.status.set_old_long(load(old_long_file_handler))
|
||||
with open(f"status/{self.base}{self.quote}.oldlong") as f:
|
||||
self.status.set_old_long(load(f))
|
||||
except Exception as e:
|
||||
#self.write_to_log(time.strftime(f"[%Y/%m/%d %H:%M:%S] | {self.status.get_pair()} | Can't find old long file"))
|
||||
self.broker.logger.log_this(f"Can't file oldlong file. Exception: {e}",1,self.status.get_pair())
|
||||
|
|
@ -626,7 +624,6 @@ class trader:
|
|||
return 1
|
||||
|
||||
#Cancel open orders
|
||||
self.broker.logger.log_this("Cancelling open orders",2,self.status.get_pair())
|
||||
for order in self.status.get_safety_orders():
|
||||
self.broker.cancel_order(order["id"],self.status.get_pair())
|
||||
if self.status.get_take_profit_order() is not None:
|
||||
|
|
@ -635,21 +632,18 @@ class trader:
|
|||
self.broker.logger.log_this("Safety order is None",1,self.status.get_pair())
|
||||
|
||||
#Sell all base currency
|
||||
self.broker.logger.log_this(f"Selling {self.status.get_pair().split('/')[0]}",2,self.status.get_pair())
|
||||
self.liquidate_base(ignore_profits=ignore_old_long, already_received_quote=already_received_quote)
|
||||
|
||||
if self.config.get_liquidate_after_switch():
|
||||
self.broker.logger.log_this("Liquidate after switch active. Raising quit flag.",1,self.status.get_pair())
|
||||
self.quit = True
|
||||
return 0
|
||||
return 1
|
||||
|
||||
#Rewrite config file (if it exists)
|
||||
if path.isfile(f"configs/{self.base}{self.quote}.bak") and path.isfile(f"configs/{self.base}{self.quote}.json"):
|
||||
self.broker.logger.log_this("Restoring config file from backup",2,self.status.get_pair())
|
||||
with open(f"configs/{self.base}{self.quote}.bak") as backup_config_file_handler:
|
||||
old_config = load(backup_config_file_handler)
|
||||
with open(f"configs/{self.base}{self.quote}.json","w") as config_file_handler:
|
||||
config_file_handler.write(dumps(old_config, indent=4))
|
||||
with open(f"configs/{self.base}{self.quote}.bak") as c:
|
||||
old_config = load(c)
|
||||
with open(f"configs/{self.base}{self.quote}.json","w") as c:
|
||||
c.write(dumps(old_config, indent=4))
|
||||
if self.config.load_from_file()==1:
|
||||
self.config.reset_to_default()
|
||||
else:
|
||||
|
|
@ -671,7 +665,6 @@ class trader:
|
|||
self.status.set_so_amount(0)
|
||||
|
||||
#Done. Ready for start_trader
|
||||
self.broker.logger.log_this("Finished setting up the switch to long.",2,self.status.get_pair())
|
||||
return 0
|
||||
|
||||
|
||||
|
|
@ -808,11 +801,11 @@ class trader:
|
|||
partial_profit = market_order["cost"]-(avg_buy_price*partial_filled_amount)-self.parse_fees(market_order)[1]
|
||||
self.status.set_partial_profit(self.status.get_partial_profit()+partial_profit)
|
||||
break
|
||||
self.broker.logger.log_this("Waiting for partial fill sell order to fill.",2,self.status.get_pair())
|
||||
self.broker.logger.log_this("Waiting for partial fill sell order to fill.",1,self.status.get_pair())
|
||||
tries-=1
|
||||
time.sleep(self.broker.get_wait_time())
|
||||
if tries==0:
|
||||
self.broker.logger.log_this("Partial fill sell order not filled.",1,self.status.get_pair())
|
||||
self.broker.logger.log_this("Partial fill sell order not filling.",1,self.status.get_pair())
|
||||
break
|
||||
|
||||
if not self.broker.check_for_duplicate_profit_in_db(filled_order):
|
||||
|
|
@ -1545,8 +1538,8 @@ class trader:
|
|||
#If there is an old_long file, also copy it
|
||||
if self.config.get_is_short() and self.status.get_old_long()!={}:
|
||||
try:
|
||||
with open(f"status/{self.base}{self.quote}.oldlong","w") as old_long_file_handler:
|
||||
old_long_file_handler.write(dumps(self.status.get_old_long(), indent=4))
|
||||
with open(f"status/{self.base}{self.quote}.oldlong","w") as c:
|
||||
c.write(dumps(self.status.get_old_long(), indent=4))
|
||||
except Exception as e:
|
||||
self.broker.logger.log_this(f"Exception while writing new old_long file: {e}",1,self.status.get_pair())
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import calendar
|
|||
import logging
|
||||
import threading
|
||||
import os
|
||||
from collections import deque
|
||||
from typing import Iterable, List, Tuple
|
||||
from contextlib import contextmanager
|
||||
from flask import Flask, jsonify, request
|
||||
from flask import Flask, jsonify, request, Response
|
||||
from waitress import serve
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue