From 8201f70a80dd2f767516044f5e767b50461d6352 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 25 Oct 2019 14:19:02 +0200 Subject: [PATCH 1/5] 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/5] 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/5] 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/5] 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 From ea6b94fd0c57ac5000bd744e6602a421029134af Mon Sep 17 00:00:00 2001 From: hroff-1902 <47309513+hroff-1902@users.noreply.github.com> Date: Sat, 26 Oct 2019 11:54:04 +0300 Subject: [PATCH 5/5] docs: add a tip for The Ocean exchange --- docs/configuration.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index e3d16c57b..ff40b1750 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -331,7 +331,7 @@ This configuration enables binance, as well as rate limiting to avoid bans from Optimal settings for rate limiting depend on the exchange and the size of the whitelist, so an ideal parameter will vary on many other settings. We try to provide sensible defaults per exchange where possible, if you encounter bans please make sure that `"enableRateLimit"` is enabled and increase the `"rateLimit"` parameter step by step. -#### Advanced FreqTrade Exchange configuration +#### Advanced Freqtrade Exchange configuration Advanced options can be configured using the `_ft_has_params` setting, which will override Defaults and exchange-specific behaviours. @@ -351,6 +351,13 @@ For example, to test the order type `FOK` with Kraken, and modify candle_limit t !!! Warning Please make sure to fully understand the impacts of these settings before modifying them. +#### Random notes for other exchanges + +* The Ocean (ccxt id: 'theocean') exchange uses Web3 functionality and requires web3 package to be installed: +```shell +$ pip3 install web3 +``` + ### What values can be used for fiat_display_currency? The `fiat_display_currency` configuration parameter sets the base currency to use for the