diff --git a/freqtrade/main.py b/freqtrade/main.py index ce933fe44..68277adaa 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -6,6 +6,7 @@ import time import traceback from datetime import datetime from typing import Dict, Optional +from signal import signal, SIGINT, SIGABRT, SIGTERM from jsonschema import validate @@ -223,6 +224,23 @@ def init(config: dict, db_url: Optional[str] = None) -> None: else: update_state(State.STOPPED) + # Register signal handlers + for sig in (SIGINT, SIGTERM, SIGABRT): + signal(sig, cleanup) + + +def cleanup(*args, **kwargs) -> None: + """ + Cleanup the application state und finish all pending tasks + :return: None + """ + telegram.send_msg('*Status:* `Stopping trader...`') + logger.info('Stopping trader and cleaning up modules...') + update_state(State.STOPPED) + persistence.cleanup() + telegram.cleanup() + exit(0) + def app(config: dict) -> None: """ @@ -251,10 +269,10 @@ def app(config: dict) -> None: time.sleep(exchange.EXCHANGE.sleep_time) old_state = new_state except RuntimeError: - telegram.send_msg('*Status:* Got RuntimeError: ```\n{}\n```'.format(traceback.format_exc())) + telegram.send_msg( + '*Status:* Got RuntimeError:\n```\n{}\n```'.format(traceback.format_exc()) + ) logger.exception('RuntimeError. Trader stopped!') - finally: - telegram.send_msg('*Status:* `Trader has stopped`') def main(): diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index 7f8bfbc69..fa51b1349 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -37,6 +37,14 @@ def init(config: dict, db_url: Optional[str] = None) -> None: Base.metadata.create_all(engine) +def cleanup() -> None: + """ + Flushes all pending operations to disk. + :return: None + """ + Trade.session.flush() + + class Trade(Base): __tablename__ = 'trades' diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 4b320eb85..84c86f816 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -17,7 +17,7 @@ logging.getLogger('requests.packages.urllib3').setLevel(logging.INFO) logging.getLogger('telegram').setLevel(logging.INFO) logger = logging.getLogger(__name__) -_updater = None +_updater: Updater = None _CONF = {} @@ -61,6 +61,14 @@ def init(config: dict) -> None: ) +def cleanup() -> None: + """ + Stops all running telegram threads. + :return: None + """ + _updater.stop() + + def authorized_only(command_handler: Callable[[Bot, Update], None]) -> Callable[..., Any]: """ Decorator to check if the message comes from the correct chat_id