2025.09.18
This commit is contained in:
parent
0d753aa3cd
commit
733f6efbff
|
|
@ -1,3 +1,8 @@
|
|||
2025.09.18:
|
||||
. do_cleanup now uses get_min_quote_size.
|
||||
. Added an extra price check to switch_to_long.
|
||||
. Removed old check_old_long_price method.
|
||||
|
||||
2025.09.14:
|
||||
. Refactored full order list fetching.
|
||||
. Minor refactor of restart_pair_no_json.
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ class Broker:
|
|||
try:
|
||||
return orderbook["bids"][0][0]
|
||||
except Exception as e:
|
||||
self.logger.log_this(f"Exception getting top mid price: {e}",1,symbol)
|
||||
self.logger.log_this(f"Exception getting top bid price: {e}",1,symbol)
|
||||
return self.get_ticker_price(symbol)
|
||||
|
||||
|
||||
|
|
@ -537,7 +537,7 @@ class Broker:
|
|||
pairs = []
|
||||
try:
|
||||
if self.get_exchange_name() in ["binance","kucoin"]:
|
||||
if "unified_order_query" in self.broker_config and self.broker_config["unified_order_query"] is True:
|
||||
if self.broker_config.get("unified_order_query"):
|
||||
return self.exchange.fetch_open_orders()
|
||||
result = []
|
||||
for pair in pairs:
|
||||
|
|
@ -642,7 +642,7 @@ class Broker:
|
|||
'''
|
||||
|
||||
try:
|
||||
if "unified_order_query" in self.broker_config and self.broker_config["unified_order_query"] is True:
|
||||
if self.broker_config.get("unified_order_query"):
|
||||
return self.exchange.fetch_closed_orders()
|
||||
result = []
|
||||
for pair in pairs:
|
||||
|
|
|
|||
2
main.py
2
main.py
|
|
@ -18,7 +18,7 @@ import exchange_wrapper
|
|||
import trader
|
||||
|
||||
|
||||
version = "2025.09.14"
|
||||
version = "2025.09.18"
|
||||
|
||||
'''
|
||||
Color definitions. If you want to change them, check the reference at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
|
|
|
|||
77
trader.py
77
trader.py
|
|
@ -11,14 +11,16 @@ class trader:
|
|||
self.pause = True
|
||||
self.quit = False
|
||||
self.restart = False
|
||||
self.warnings = {
|
||||
"short_price_exceeds_old_long": False,
|
||||
"speol_notified": False
|
||||
}
|
||||
self.trader_restart_errors = {1: "start_trader returned error #1. Trader will be restarted",
|
||||
2: "start_trader returned error #2: Initial order never got filled. Trader will be restarted",
|
||||
3: "start_trader returned error #3: Slippage threshold exceeded. Trader will be restarted"}
|
||||
|
||||
#Status string caches
|
||||
self.low_price_cache = None
|
||||
self.mid_price_cache = None
|
||||
self.high_price_cache = None
|
||||
self.concurrent_so_amount_cache = None
|
||||
|
||||
self.broker = broker
|
||||
self.config = ConfigHandler(pair,broker)
|
||||
base_quote = self.config.get_pair()
|
||||
|
|
@ -30,12 +32,6 @@ class trader:
|
|||
self.status.set_start_time(int(time.time()))
|
||||
self.last_time_seen = time.time()
|
||||
|
||||
#Status string caches
|
||||
self.low_price_cache = None
|
||||
self.mid_price_cache = None
|
||||
self.high_price_cache = None
|
||||
self.concurrent_so_amount_cache = None
|
||||
|
||||
if self.config.get_is_short():
|
||||
#Check if there is an old_long file. If so, load it.
|
||||
try:
|
||||
|
|
@ -442,7 +438,7 @@ class trader:
|
|||
return 1
|
||||
balance_to_clean /= 2 #Maybe it's a good idea, sort of DCAing the dust.
|
||||
|
||||
if balance_to_clean >= self.broker.get_min_base_size(self.status.get_pair()):
|
||||
if balance_to_clean*self.status.get_start_price()>self.broker.get_min_quote_size(self.status.get_pair()):
|
||||
self.broker.logger.log_this(f"Balance to clean: {balance_to_clean} {self.base}",2,self.status.get_pair())
|
||||
self.broker.logger.log_this("Sending cleanup order...",2,self.status.get_pair())
|
||||
cleanup_order = self.broker.new_limit_order(self.status.get_pair(),balance_to_clean,"sell",self.status.get_take_profit_price(),no_retries=True)
|
||||
|
|
@ -585,7 +581,7 @@ class trader:
|
|||
return 0
|
||||
|
||||
|
||||
def switch_to_long(self, ignore_old_long: bool = False, already_received_quote: float = 0) -> int:
|
||||
def switch_to_long(self, ignore_old_long: bool = False, already_received_quote: float = 0, double_check_price: bool = True) -> int:
|
||||
'''
|
||||
Takes a short trader and changes the mode to long.
|
||||
Only does it if the current trader was previously a long one.
|
||||
|
|
@ -596,6 +592,13 @@ class trader:
|
|||
return 1
|
||||
self.broker.logger.log_this("Attempting to switch to long trader",0,self.status.get_pair())
|
||||
|
||||
if double_check_price:
|
||||
#Waits a moment to see if the price has moved too much
|
||||
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
|
||||
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())
|
||||
|
|
@ -1019,28 +1022,6 @@ class trader:
|
|||
return 0
|
||||
|
||||
|
||||
def check_old_long_price(self) -> int:
|
||||
'''
|
||||
Checks if short price exceeds old long price. If so, send a Telegram message
|
||||
'''
|
||||
|
||||
price_exceeds = False
|
||||
if self.status.get_old_long()!={}:
|
||||
price_exceeds = self.status.get_price()>float(self.status.get_old_long()["tp_price"])
|
||||
if price_exceeds:
|
||||
self.warnings["short_price_exceeds_old_long"] = True
|
||||
else:
|
||||
self.warnings["short_price_exceeds_old_long"] = False
|
||||
self.warnings["speol_notified"] = False
|
||||
if not self.warnings["speol_notified"] and price_exceeds:
|
||||
#Only notify one time AND if autoswitch is off
|
||||
self.warnings["speol_notified"] = True
|
||||
if not self.config.get_autoswitch():
|
||||
message = f"{self.base}@{self.status.get_price()} ({str(self.broker.exchange)}), exceeds old long price of {self.status.get_old_long()['tp_price']}"
|
||||
self.broker.logger.log_this(message,0,self.status.get_pair())
|
||||
return 0
|
||||
|
||||
|
||||
def check_orderbook_depth(self, threshold: float, order_size: float, old_price: float = 0, size_in_quote = True) -> bool:
|
||||
'''
|
||||
Checks if the orderbook depth exceeds the slippage threshold. Returns True if it is exceeded, False otherwise.
|
||||
|
|
@ -1084,6 +1065,21 @@ class trader:
|
|||
return False
|
||||
|
||||
|
||||
def check_old_long(self, fetch_price=False):
|
||||
'''
|
||||
Check if it is profitable to switch to back to long.
|
||||
Returns True if it is profitable, False otherwise.
|
||||
|
||||
If selling the base currency left at the current market price plus the quote already received turns out to be more than the old long deal target,
|
||||
it means that we already are in profit territory, switch back to long.
|
||||
A more conservative approach would be old_target = self.status.get_old_long()["quote_spent"], just breaking even.
|
||||
'''
|
||||
price = self.status.get_price() if not fetch_price else self.broker.get_top_bid_price(self.status.get_pair())
|
||||
old_target = self.status.get_old_long()["tp_price"]*self.status.get_old_long()["tp_amount"]
|
||||
base_left = self.status.get_old_long()["tp_amount"]-self.status.get_base_bought()
|
||||
return (base_left*price)+self.status.get_quote_spent()>=old_target
|
||||
|
||||
|
||||
def check_status(self,open_orders: list) -> int: #Should I change the order? Check the SO first?
|
||||
'''
|
||||
Main routine. It checks for closed orders and proceeds accordingly.
|
||||
|
|
@ -1094,22 +1090,13 @@ class trader:
|
|||
self.update_status(False)
|
||||
return 0
|
||||
|
||||
#Check if short price exceeds old long price. If so, send a Telegram message
|
||||
if self.config.get_is_short() and self.status.get_old_long()!={} and self.config.get_check_old_long_price():
|
||||
self.check_old_long_price()
|
||||
|
||||
self.status.set_pause_reason("check for autoswitch")
|
||||
#If it's a short trader that used to be long AND autoswitch is enabled
|
||||
if self.config.get_is_short() and self.config.get_autoswitch() and self.status.get_old_long()!={}:
|
||||
#If selling the base currency left at the current market price plus the quote already received turns out to be more than the old long deal target,
|
||||
# it means that we already are in profit territory, switch back to long.
|
||||
#A more conservative approach would be old_target = self.status.get_old_long()["quote_spent"], just breaking even.
|
||||
old_target = self.status.get_old_long()["tp_price"]*self.status.get_old_long()["tp_amount"]
|
||||
base_left = self.status.get_old_long()["tp_amount"]-self.status.get_base_bought()
|
||||
if (base_left*self.status.get_price())+self.status.get_quote_spent()>=old_target:
|
||||
if self.check_old_long():
|
||||
#Sell all base (market), report the profits and restart the trader
|
||||
self.status.set_pause_reason("automatic_switch")
|
||||
self.switch_to_long(already_received_quote=self.status.get_quote_spent())
|
||||
if self.switch_to_long(already_received_quote=self.status.get_quote_spent())!=2:
|
||||
if not self.config.get_liquidate_after_switch():
|
||||
self.restart = True
|
||||
return 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue