From 48a821a8d457b948c9f68ef5e83b7cb9ccc1429e Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Wed, 4 Sep 2024 19:48:29 +0200 Subject: [PATCH] Improved error recovery --- crypto_seller/__init__.py | 119 ++++++++++++++++++++++---------------- crypto_seller/__main__.py | 6 +- 2 files changed, 73 insertions(+), 52 deletions(-) diff --git a/crypto_seller/__init__.py b/crypto_seller/__init__.py index cbbd0af..9fbcc3c 100644 --- a/crypto_seller/__init__.py +++ b/crypto_seller/__init__.py @@ -216,50 +216,63 @@ def run_auto_sell( all_executed_orders: list[fin_depo.data.TradeOrderDetails] = [] total_sleep_duration = datetime.timedelta(seconds=0) - while True: - # Check that account has tokens. - input_amount_available = config.seller.get_depo().get_amount_of_asset( - config.input_asset, - ) - logger.info( - 'Currently own %s %s', - input_amount_available, - config.input_asset.raw_short_name(), - ) - - if initial_rounds_to_skip > 0: - initial_rounds_to_skip -= 1 - logger.info('skipping this round') - elif input_amount_available > 0: - amount_to_sell = sample_from_range(rng, config.input_amount_range) - amount_to_sell = min(input_amount_available, amount_to_sell) - amount_to_sell = amount_to_sell.quantize( - ROUND_TO_WHOLE, - rounding=ROUND_DOWN, - ) - logger.info('Attempting to sell %s %s', amount_to_sell, config.input_asset) - - order_details = config.seller.place_market_order( + try: + while True: + # Check that account has tokens. + input_amount_available = config.seller.get_depo().get_amount_of_asset( config.input_asset, - amount_to_sell, - config.output_asset, + ) + logger.info( + 'Currently own %s %s', + input_amount_available, + config.input_asset.raw_short_name(), ) - config.log_order_to_csv(order_details) - all_executed_orders.append(order_details) + if initial_rounds_to_skip > 0: + initial_rounds_to_skip -= 1 + logger.info('skipping this round') + elif input_amount_available > 0: + amount_to_sell = sample_from_range(rng, config.input_amount_range) + amount_to_sell = min(input_amount_available, amount_to_sell) + amount_to_sell = amount_to_sell.quantize( + ROUND_TO_WHOLE, + rounding=ROUND_DOWN, + ) + logger.info( + 'Attempting to sell %s %s', amount_to_sell, config.input_asset, + ) - del amount_to_sell - elif config.exit_when_empty: - break + order_details = config.seller.place_market_order( + config.input_asset, + amount_to_sell, + config.output_asset, + ) - # Time out - time_to_sleep = sample_from_range(rng, config.interval_range) - time_to_sleep_secs = time_to_sleep.total_seconds() - logger.info('Sleeping %s (%d seconds)', time_to_sleep, time_to_sleep_secs) - config.sleep(time_to_sleep_secs) - total_sleep_duration += time_to_sleep + config.log_order_to_csv(order_details) + all_executed_orders.append(order_details) - del input_amount_available + del amount_to_sell + elif config.exit_when_empty: + break + + # Time out + time_to_sleep = sample_from_range(rng, config.interval_range) + time_to_sleep_secs = time_to_sleep.total_seconds() + logger.info('Sleeping %s (%d seconds)', time_to_sleep, time_to_sleep_secs) + config.sleep(time_to_sleep_secs) + total_sleep_duration += time_to_sleep + + del input_amount_available + except KeyboardInterrupt: + logger.warning('Manual interrupt') + except RuntimeError: + logger.exception( + 'A unexpected and serious error occured. The program will be winding down', + ) + logger.fatal('Please send the above error message to: mailto:jonjmaa@gmail.com') + logger.fatal( + 'He will attempt to diagnosticate the problem, and help with recovery', + ) time_end = datetime.datetime.now(tz=datetime.UTC) @@ -288,41 +301,45 @@ def log_estimates(config: AutoSellConfig): current_balance / config.input_amount_range[0], ) + minisleep = 0.1 + + logger.info('') logger.info('Welcome to crypto seller!') - config.sleep(1) + config.sleep(3) logger.info('') - config.sleep(1) + config.sleep(minisleep) logger.info('I, the great crypto seller, your humble servant, will') + config.sleep(minisleep) logger.info('now analyse your configuration and divine some estimates!') - config.sleep(1) + config.sleep(3) logger.info('') - config.sleep(1) + config.sleep(minisleep) logger.info( '- Current balance: %s %s', current_balance, config.input_asset.raw_short_name(), ) - config.sleep(1) + config.sleep(minisleep) logger.info('- Average sleep: %s seconds', average_sleep) - config.sleep(1) + config.sleep(minisleep) logger.info( '- Average amount: %s %s', average_amount, config.input_asset.raw_short_name(), ) - config.sleep(1) + config.sleep(minisleep) logger.info('- Expected counts: %s', expected_num_sell_offs) - config.sleep(1) + config.sleep(minisleep) logger.info('- Expected time: %s', expected_duration) - config.sleep(1) + config.sleep(minisleep) logger.info('- Fastest time: %s', fastest_duration) - config.sleep(1) + config.sleep(minisleep) logger.info('- Slowest time: %s', slowest_duration) - config.sleep(1) + config.sleep(minisleep) logger.info('') - config.sleep(1) + config.sleep(minisleep) logger.info('Do you still want to proceed?') - config.sleep(1) + config.sleep(minisleep) logger.info('If not, press CTRL+C within the next 10 seconds...') config.sleep(10) logger.info('') diff --git a/crypto_seller/__main__.py b/crypto_seller/__main__.py index 64ef928..1fc7a34 100644 --- a/crypto_seller/__main__.py +++ b/crypto_seller/__main__.py @@ -3,6 +3,7 @@ import datetime import json import logging import logging.handlers +import sys import time from decimal import Decimal from pathlib import Path @@ -136,7 +137,10 @@ def main(): auto_sell_config = load_config(args.config_file) # Display estimates - log_estimates(auto_sell_config) + try: + log_estimates(auto_sell_config) + except KeyboardInterrupt: + sys.exit(1) # Run auto sell results = run_auto_sell(