From 8201f70a80dd2f767516044f5e767b50461d6352 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 25 Oct 2019 14:19:02 +0200 Subject: [PATCH 1/4] Change loglevel of repeated message to debug --- freqtrade/freqtradebot.py | 2 +- tests/test_freqtradebot.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 6a1be16a1..d28014608 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -443,7 +443,7 @@ class FreqtradeBot: try: # Create entity and execute trade if not self.create_trades(): - logger.info('Found no buy signals for whitelisted currencies. Trying again...') + logger.debug('Found no buy signals for whitelisted currencies. Trying again...') except DependencyException as exception: logger.warning('Unable to create trade: %s', exception) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index f1533d867..607cb8f32 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -1521,6 +1521,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog, def test_process_maybe_execute_buys(mocker, default_conf, caplog) -> None: + caplog.set_level(logging.DEBUG) freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.create_trades', MagicMock(return_value=False)) From 0773a653336f06e91bba0f0a70276dcfaf151874 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 25 Oct 2019 15:00:16 +0200 Subject: [PATCH 2/4] Add I Am Alive Message --- config_full.json.example | 3 ++- docs/configuration.md | 1 + freqtrade/freqtradebot.py | 9 +++++++++ tests/test_freqtradebot.py | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/config_full.json.example b/config_full.json.example index c6b229ea3..ebf76eaee 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -119,7 +119,8 @@ "initial_state": "running", "forcebuy_enable": false, "internals": { - "process_throttle_secs": 5 + "process_throttle_secs": 5, + "keep_alive_interval": 60 }, "strategy": "DefaultStrategy", "strategy_path": "user_data/strategies/" diff --git a/docs/configuration.md b/docs/configuration.md index 0eff4da88..c6a12d865 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -98,6 +98,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `strategy` | DefaultStrategy | Defines Strategy class to use. | `strategy_path` | null | Adds an additional strategy lookup path (must be a directory). | `internals.process_throttle_secs` | 5 | **Required.** Set the process throttle. Value in second. +| `internals.keep_alive_interval` | 60 | Print keepalive message every X seconds. Set to 0 to disable keepalive messages. | `internals.sd_notify` | false | Enables use of the sd_notify protocol to tell systemd service manager about changes in the bot state and issue keep-alive pings. See [here](installation.md#7-optional-configure-freqtrade-as-a-systemd-service) for more details. | `logfile` | | Specify Logfile. Uses a rolling strategy of 10 files, with 1Mb per file. | `user_data_dir` | cwd()/user_data | Directory containing user data. Defaults to `./user_data/`. diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index d28014608..6c79d04de 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -50,6 +50,10 @@ class FreqtradeBot: # Init objects self.config = config + self._last_alive_msg = 0 + + self.keep_alive_interval = self.config.get('internals', {}).get('keep_alive_interval', 60) + self.strategy: IStrategy = StrategyResolver(self.config).strategy # Check config consistency here since strategies can set certain options @@ -150,6 +154,11 @@ class FreqtradeBot: self.check_handle_timedout() Trade.session.flush() + if (self.keep_alive_interval + and (arrow.utcnow().timestamp - self._last_alive_msg > self.keep_alive_interval)): + logger.info("I am alive.") + self._last_alive_msg = arrow.utcnow().timestamp + def _extend_whitelist_with_trades(self, whitelist: List[str], trades: List[Any]): """ Extend whitelist with pairs from open trades diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 607cb8f32..b29bd0843 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3648,3 +3648,27 @@ def test_startup_trade_reinit(default_conf, edge_conf, mocker): ftbot = get_patched_freqtradebot(mocker, edge_conf) ftbot.startup() assert reinit_mock.call_count == 0 + + +def test_process_i_am_alive(default_conf, mocker, caplog): + patch_RPCManager(mocker) + patch_exchange(mocker) + mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True)) + + ftbot = get_patched_freqtradebot(mocker, default_conf) + message = "I am alive." + ftbot.process() + assert log_has(message, caplog) + assert ftbot._last_alive_msg != 0 + + caplog.clear() + # Message is not shown before interval is up + ftbot.process() + assert not log_has(message, caplog) + + caplog.clear() + # Set clock - 70 seconds + ftbot._last_alive_msg -= 70 + + ftbot.process() + assert log_has(message, caplog) From 2f1d9696cd1fd7efca1c619dc4a5b861353777f3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 25 Oct 2019 19:59:04 +0200 Subject: [PATCH 3/4] Change keepalive to heartbeat --- config_full.json.example | 2 +- docs/configuration.md | 2 +- freqtrade/freqtradebot.py | 25 +++++++++++++------------ tests/test_freqtradebot.py | 12 ++++++------ 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/config_full.json.example b/config_full.json.example index ebf76eaee..5789e49ac 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -120,7 +120,7 @@ "forcebuy_enable": false, "internals": { "process_throttle_secs": 5, - "keep_alive_interval": 60 + "heartbeat_interval": 60 }, "strategy": "DefaultStrategy", "strategy_path": "user_data/strategies/" diff --git a/docs/configuration.md b/docs/configuration.md index c6a12d865..e3d16c57b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -98,7 +98,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `strategy` | DefaultStrategy | Defines Strategy class to use. | `strategy_path` | null | Adds an additional strategy lookup path (must be a directory). | `internals.process_throttle_secs` | 5 | **Required.** Set the process throttle. Value in second. -| `internals.keep_alive_interval` | 60 | Print keepalive message every X seconds. Set to 0 to disable keepalive messages. +| `internals.heartbeat_interval` | 60 | Print heartbeat message every X seconds. Set to 0 to disable heartbeat messages. | `internals.sd_notify` | false | Enables use of the sd_notify protocol to tell systemd service manager about changes in the bot state and issue keep-alive pings. See [here](installation.md#7-optional-configure-freqtrade-as-a-systemd-service) for more details. | `logfile` | | Specify Logfile. Uses a rolling strategy of 10 files, with 1Mb per file. | `user_data_dir` | cwd()/user_data | Directory containing user data. Defaults to `./user_data/`. diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 6c79d04de..9bc4fb04d 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -6,26 +6,27 @@ import logging import traceback from datetime import datetime from math import isclose +from os import getpid from typing import Any, Dict, List, Optional, Tuple import arrow from requests.exceptions import RequestException -from freqtrade import (DependencyException, InvalidOrderException, - __version__, constants, persistence) +from freqtrade import (DependencyException, InvalidOrderException, __version__, + constants, persistence) +from freqtrade.configuration import validate_config_consistency from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.edge import Edge -from freqtrade.configuration import validate_config_consistency from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date from freqtrade.persistence import Trade +from freqtrade.resolvers import (ExchangeResolver, PairListResolver, + StrategyResolver) from freqtrade.rpc import RPCManager, RPCMessageType -from freqtrade.resolvers import ExchangeResolver, StrategyResolver, PairListResolver from freqtrade.state import State -from freqtrade.strategy.interface import SellType, IStrategy +from freqtrade.strategy.interface import IStrategy, SellType from freqtrade.wallets import Wallets - logger = logging.getLogger(__name__) @@ -50,9 +51,9 @@ class FreqtradeBot: # Init objects self.config = config - self._last_alive_msg = 0 + self._heartbeat_msg = 0 - self.keep_alive_interval = self.config.get('internals', {}).get('keep_alive_interval', 60) + self.hearbeat_interval = self.config.get('internals', {}).get('heartbeat_interval', 60) self.strategy: IStrategy = StrategyResolver(self.config).strategy @@ -154,10 +155,10 @@ class FreqtradeBot: self.check_handle_timedout() Trade.session.flush() - if (self.keep_alive_interval - and (arrow.utcnow().timestamp - self._last_alive_msg > self.keep_alive_interval)): - logger.info("I am alive.") - self._last_alive_msg = arrow.utcnow().timestamp + if (self.hearbeat_interval + and (arrow.utcnow().timestamp - self._heartbeat_msg > self.hearbeat_interval)): + logger.info(f"Freqtrade heartbeat. PID={getpid()}") + self._heartbeat_msg = arrow.utcnow().timestamp def _extend_whitelist_with_trades(self, whitelist: List[str], trades: List[Any]): """ diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index b29bd0843..cf67e644f 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3656,19 +3656,19 @@ def test_process_i_am_alive(default_conf, mocker, caplog): mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True)) ftbot = get_patched_freqtradebot(mocker, default_conf) - message = "I am alive." + message = r"Freqtrade heartbeat. PID=.*" ftbot.process() - assert log_has(message, caplog) - assert ftbot._last_alive_msg != 0 + assert log_has_re(message, caplog) + assert ftbot._heartbeat_msg != 0 caplog.clear() # Message is not shown before interval is up ftbot.process() - assert not log_has(message, caplog) + assert not log_has_re(message, caplog) caplog.clear() # Set clock - 70 seconds - ftbot._last_alive_msg -= 70 + ftbot._heartbeat_msg -= 70 ftbot.process() - assert log_has(message, caplog) + assert log_has_re(message, caplog) From 3929ad4e1f84fe7dca8a676d4236b47565af0468 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 26 Oct 2019 09:21:51 +0200 Subject: [PATCH 4/4] Fix typo --- freqtrade/freqtradebot.py | 8 ++++---- tests/test_freqtradebot.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 9bc4fb04d..7251715a7 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -53,7 +53,7 @@ class FreqtradeBot: self._heartbeat_msg = 0 - self.hearbeat_interval = self.config.get('internals', {}).get('heartbeat_interval', 60) + self.heartbeat_interval = self.config.get('internals', {}).get('heartbeat_interval', 60) self.strategy: IStrategy = StrategyResolver(self.config).strategy @@ -155,9 +155,9 @@ class FreqtradeBot: self.check_handle_timedout() Trade.session.flush() - if (self.hearbeat_interval - and (arrow.utcnow().timestamp - self._heartbeat_msg > self.hearbeat_interval)): - logger.info(f"Freqtrade heartbeat. PID={getpid()}") + if (self.heartbeat_interval + and (arrow.utcnow().timestamp - self._heartbeat_msg > self.heartbeat_interval)): + logger.info(f"Bot heartbeat. PID={getpid()}") self._heartbeat_msg = arrow.utcnow().timestamp def _extend_whitelist_with_trades(self, whitelist: List[str], trades: List[Any]): diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index cf67e644f..8aefaba17 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3656,7 +3656,7 @@ def test_process_i_am_alive(default_conf, mocker, caplog): mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True)) ftbot = get_patched_freqtradebot(mocker, default_conf) - message = r"Freqtrade heartbeat. PID=.*" + message = r"Bot heartbeat\. PID=.*" ftbot.process() assert log_has_re(message, caplog) assert ftbot._heartbeat_msg != 0