From 1cc49b8f7f14724e7980dab4ce2089a57b2ebed1 Mon Sep 17 00:00:00 2001 From: Eirik Narjord Date: Tue, 4 Mar 2025 12:30:56 -0500 Subject: [PATCH 1/3] handle cases where coins list is given as ['COIN1,COIN2'] --- src/passivbot.py | 16 +++++++++++++- src/procedures.py | 53 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/passivbot.py b/src/passivbot.py index 3b7b20a1d..a543b8a44 100644 --- a/src/passivbot.py +++ b/src/passivbot.py @@ -2170,7 +2170,21 @@ def add_to_coins_lists(self, content, k_coins): psides_equal = content["long"] == content["short"] for pside in content: if not psides_equal or symbols is None: - symbols = [self.coin_to_symbol(coin) for coin in content[pside]] + coins = content[pside] + # Check if coins is a single string that needs to be split + if isinstance(coins, str): + coins = coins.split(",") + # Handle case where list contains comma-separated values in its elements + elif isinstance(coins, (list, tuple)): + expanded_coins = [] + for item in coins: + if isinstance(item, str) and "," in item: + expanded_coins.extend(item.split(",")) + else: + expanded_coins.append(item) + coins = expanded_coins + + symbols = [self.coin_to_symbol(coin) for coin in coins] symbols = set([s for s in symbols if s]) symbols_already = getattr(self, k_coins)[pside] if symbols and symbols_already != symbols: diff --git a/src/procedures.py b/src/procedures.py index 15c91f63f..e3bb9f985 100644 --- a/src/procedures.py +++ b/src/procedures.py @@ -195,10 +195,44 @@ def format_config(config: dict, verbose=True, live_only=False) -> dict: if not live_only: for k_coins in ["approved_coins", "ignored_coins"]: path = result["live"][k_coins] + + # --- 1) If it's already a dict {"long": [...], "short": [...]}, handle each side --- + sides = ["long", "short"] + if isinstance(path, dict) and all(side in path for side in sides): + for side in sides: + side_val = path.get(side, []) + if isinstance(side_val, list): + expanded = [] + for item in side_val: + # Expand comma‐delimited strings like "ADAUSDT,DOGEUSDT" + if isinstance(item, str) and "," in item: + expanded.extend(x.strip() for x in item.split(",")) + else: + expanded.append(item) + path[side] = expanded + # Reassign the modified dict back + result["live"][k_coins] = path + # Skip the rest of the loop because the original snippet only did further logic if + # path was a list or string in "approved_coins"/"ignored_coins" + continue + + # --- 2) If it's a list, first check if single item is a file path, else expand commas --- if isinstance(path, list): + # Check for single‐item list referencing an external file if len(path) == 1 and isinstance(path[0], str) and os.path.exists(path[0]): - if any([path[0].endswith(k) for k in [".txt", ".json", ".hjson"]]): - path = path[0] + if any(path[0].endswith(k) for k in [".txt", ".json", ".hjson"]): + path = path[0] # e.g. "coins.json" + else: + # Expand comma‐delimited strings, e.g. ["ADAUSDT,DOGEUSDT"] => ["ADAUSDT","DOGEUSDT"] + expanded = [] + for item in path: + if isinstance(item, str) and "," in item: + expanded.extend(x.strip() for x in item.split(",")) + else: + expanded.append(item) + path = expanded + + # --- 3) If it's now a string, apply the original file/empty logic --- if isinstance(path, str): if path == "": result["live"][k_coins] = {"long": [], "short": []} @@ -206,9 +240,8 @@ def format_config(config: dict, verbose=True, live_only=False) -> dict: try: content = read_external_coins_lists(path) if content: - if verbose: - if result["live"][k_coins] != content: - print(f"set {k_coins} {content}") + if verbose and result["live"][k_coins] != content: + print(f"set {k_coins} {content}") result["live"][k_coins] = content except Exception as e: print(f"failed to load {k_coins} from file {path} {e}") @@ -216,11 +249,15 @@ def format_config(config: dict, verbose=True, live_only=False) -> dict: if verbose: print(f"path to {k_coins} file does not exist {path}") result["live"][k_coins] = {"long": [], "short": []} - if isinstance(result["live"][k_coins], list): + + # --- 4) Finally, if it's still a list, convert it into {"long":[...],"short":[...]} --- + elif isinstance(path, list): result["live"][k_coins] = { - "long": deepcopy(result["live"][k_coins]), - "short": deepcopy(result["live"][k_coins]), + "long": deepcopy(path), + "short": deepcopy(path), } + # If it’s something else (not dict/list/str), we do nothing special, + # preserving original behavior. result["backtest"]["end_date"] = format_end_date(result["backtest"]["end_date"]) return result From 500a3766eb0ab1b2d6f43ac0d0e30066629cecc6 Mon Sep 17 00:00:00 2001 From: Eirik Narjord Date: Tue, 4 Mar 2025 12:31:13 -0500 Subject: [PATCH 2/3] up version v7.2.19 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8df8835bb..e15a361af 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ :warning: **Used at one's own risk** :warning: -v7.2.18 +v7.2.19 ## Overview From 31bc1126ca0714d29c43c41390f94406479f4a42 Mon Sep 17 00:00:00 2001 From: Eirik Narjord Date: Wed, 5 Mar 2025 11:04:20 -0500 Subject: [PATCH 3/3] if balance is less than 1.0, don't create orders --- src/passivbot.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/passivbot.py b/src/passivbot.py index a543b8a44..e0b9bf439 100644 --- a/src/passivbot.py +++ b/src/passivbot.py @@ -158,6 +158,7 @@ def __init__(self, config: dict): } self.create_ccxt_sessions() self.debug_mode = False + self.balance_threshold = 1.0 # don't create orders if balance is less than threshold async def start_bot(self): logging.info(f"Starting bot {self.exchange}...") @@ -369,6 +370,8 @@ async def execute_to_exchange(self): print(f"would create {len(to_create)} orders") # for x in to_create: # pprint.pprint(x) + elif self.balance < self.balance_threshold: + logging.info(f"Balance too low: {self.balance} {self.quote}. Not creating any orders.") else: res = None try: