From 8f958ef7238dcd1fa3046ce7307873d87ad85a54 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 22 Nov 2020 11:49:41 +0100 Subject: [PATCH] Improve login-mixin structure --- freqtrade/freqtradebot.py | 4 ++-- freqtrade/mixins/logging_mixin.py | 5 +++-- freqtrade/pairlist/AgeFilter.py | 5 ++--- freqtrade/pairlist/PrecisionFilter.py | 4 ++-- freqtrade/pairlist/PriceFilter.py | 18 +++++++++--------- freqtrade/pairlist/SpreadFilter.py | 6 +++--- freqtrade/pairlist/VolumePairList.py | 2 +- freqtrade/pairlist/rangestabilityfilter.py | 6 +++--- .../plugins/protections/cooldown_period.py | 4 ++-- freqtrade/plugins/protections/iprotection.py | 2 +- .../plugins/protections/low_profit_pairs.py | 3 +-- .../plugins/protections/stoploss_guard.py | 4 ++-- tests/plugins/test_pairlist.py | 6 +++--- tests/plugins/test_protections.py | 1 + 14 files changed, 35 insertions(+), 35 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 24827a7e3..265a8ce10 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -367,7 +367,7 @@ class FreqtradeBot(LoggingMixin): "but checking to sell open trades.") return trades_created if PairLocks.is_global_lock(): - self.log_once(logger.info, "Global pairlock active. Not creating new trades.") + self.log_once("Global pairlock active. Not creating new trades.", logger.info) return trades_created # Create entity and execute trade for each pair from whitelist for pair in whitelist: @@ -553,7 +553,7 @@ class FreqtradeBot(LoggingMixin): analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(pair, self.strategy.timeframe) if self.strategy.is_pair_locked( pair, analyzed_df.iloc[-1]['date'] if len(analyzed_df) > 0 else None): - self.log_once(logger.info, f"Pair {pair} is currently locked.") + self.log_once(f"Pair {pair} is currently locked.", logger.info) return False # get_free_open_trades is checked before create_trade is called diff --git a/freqtrade/mixins/logging_mixin.py b/freqtrade/mixins/logging_mixin.py index a8dec2da7..e9921e1ec 100644 --- a/freqtrade/mixins/logging_mixin.py +++ b/freqtrade/mixins/logging_mixin.py @@ -1,5 +1,6 @@ +from typing import Callable from cachetools import TTLCache, cached @@ -19,12 +20,12 @@ class LoggingMixin(): self.refresh_period = refresh_period self._log_cache: TTLCache = TTLCache(maxsize=1024, ttl=self.refresh_period) - def log_once(self, logmethod, message: str) -> None: + def log_once(self, message: str, logmethod: Callable) -> None: """ Logs message - not more often than "refresh_period" to avoid log spamming Logs the log-message as debug as well to simplify debugging. - :param logmethod: Function that'll be called. Most likely `logger.info`. :param message: String containing the message to be sent to the function. + :param logmethod: Function that'll be called. Most likely `logger.info`. :return: None. """ @cached(cache=self._log_cache) diff --git a/freqtrade/pairlist/AgeFilter.py b/freqtrade/pairlist/AgeFilter.py index dd63c1147..ae2132637 100644 --- a/freqtrade/pairlist/AgeFilter.py +++ b/freqtrade/pairlist/AgeFilter.py @@ -76,9 +76,8 @@ class AgeFilter(IPairList): self._symbolsChecked[ticker['symbol']] = int(arrow.utcnow().float_timestamp) * 1000 return True else: - self.log_once(logger.info, - f"Removed {ticker['symbol']} from whitelist, because age " + self.log_once(f"Removed {ticker['symbol']} from whitelist, because age " f"{len(daily_candles)} is less than {self._min_days_listed} " - f"{plural(self._min_days_listed, 'day')}") + f"{plural(self._min_days_listed, 'day')}", logger.info) return False return False diff --git a/freqtrade/pairlist/PrecisionFilter.py b/freqtrade/pairlist/PrecisionFilter.py index a28d54205..db05d5883 100644 --- a/freqtrade/pairlist/PrecisionFilter.py +++ b/freqtrade/pairlist/PrecisionFilter.py @@ -59,8 +59,8 @@ class PrecisionFilter(IPairList): logger.debug(f"{ticker['symbol']} - {sp} : {stop_gap_price}") if sp <= stop_gap_price: - self.log_once(logger.info, f"Removed {ticker['symbol']} from whitelist, because " - f"stop price {sp} would be <= stop limit {stop_gap_price}") + self.log_once(f"Removed {ticker['symbol']} from whitelist, because " + f"stop price {sp} would be <= stop limit {stop_gap_price}", logger.info) return False return True diff --git a/freqtrade/pairlist/PriceFilter.py b/freqtrade/pairlist/PriceFilter.py index a5d73b728..3686cd138 100644 --- a/freqtrade/pairlist/PriceFilter.py +++ b/freqtrade/pairlist/PriceFilter.py @@ -64,9 +64,9 @@ class PriceFilter(IPairList): :return: True if the pair can stay, false if it should be removed """ if ticker['last'] is None or ticker['last'] == 0: - self.log_once(logger.info, - f"Removed {ticker['symbol']} from whitelist, because " - "ticker['last'] is empty (Usually no trade in the last 24h).") + self.log_once(f"Removed {ticker['symbol']} from whitelist, because " + "ticker['last'] is empty (Usually no trade in the last 24h).", + logger.info) return False # Perform low_price_ratio check. @@ -74,22 +74,22 @@ class PriceFilter(IPairList): compare = self._exchange.price_get_one_pip(ticker['symbol'], ticker['last']) changeperc = compare / ticker['last'] if changeperc > self._low_price_ratio: - self.log_once(logger.info, f"Removed {ticker['symbol']} from whitelist, " - f"because 1 unit is {changeperc * 100:.3f}%") + self.log_once(f"Removed {ticker['symbol']} from whitelist, " + f"because 1 unit is {changeperc * 100:.3f}%", logger.info) return False # Perform min_price check. if self._min_price != 0: if ticker['last'] < self._min_price: - self.log_once(logger.info, f"Removed {ticker['symbol']} from whitelist, " - f"because last price < {self._min_price:.8f}") + self.log_once(f"Removed {ticker['symbol']} from whitelist, " + f"because last price < {self._min_price:.8f}", logger.info) return False # Perform max_price check. if self._max_price != 0: if ticker['last'] > self._max_price: - self.log_once(logger.info, f"Removed {ticker['symbol']} from whitelist, " - f"because last price > {self._max_price:.8f}") + self.log_once(f"Removed {ticker['symbol']} from whitelist, " + f"because last price > {self._max_price:.8f}", logger.info) return False return True diff --git a/freqtrade/pairlist/SpreadFilter.py b/freqtrade/pairlist/SpreadFilter.py index 963ecb82a..6c4e9f12f 100644 --- a/freqtrade/pairlist/SpreadFilter.py +++ b/freqtrade/pairlist/SpreadFilter.py @@ -45,9 +45,9 @@ class SpreadFilter(IPairList): if 'bid' in ticker and 'ask' in ticker: spread = 1 - ticker['bid'] / ticker['ask'] if spread > self._max_spread_ratio: - self.log_once(logger.info, - f"Removed {ticker['symbol']} from whitelist, because spread " - f"{spread * 100:.3f}% > {self._max_spread_ratio * 100}%") + self.log_once(f"Removed {ticker['symbol']} from whitelist, because spread " + f"{spread * 100:.3f}% > {self._max_spread_ratio * 100}%", + logger.info) return False else: return True diff --git a/freqtrade/pairlist/VolumePairList.py b/freqtrade/pairlist/VolumePairList.py index 24e1674fd..7056bc59d 100644 --- a/freqtrade/pairlist/VolumePairList.py +++ b/freqtrade/pairlist/VolumePairList.py @@ -111,6 +111,6 @@ class VolumePairList(IPairList): # Limit pairlist to the requested number of pairs pairs = pairs[:self._number_pairs] - self.log_once(logger.info, f"Searching {self._number_pairs} pairs: {pairs}") + self.log_once(f"Searching {self._number_pairs} pairs: {pairs}", logger.info) return pairs diff --git a/freqtrade/pairlist/rangestabilityfilter.py b/freqtrade/pairlist/rangestabilityfilter.py index 7a1b69a1a..756368355 100644 --- a/freqtrade/pairlist/rangestabilityfilter.py +++ b/freqtrade/pairlist/rangestabilityfilter.py @@ -78,10 +78,10 @@ class RangeStabilityFilter(IPairList): if pct_change >= self._min_rate_of_change: result = True else: - self.log_once(logger.info, - f"Removed {pair} from whitelist, because rate of change " + self.log_once(f"Removed {pair} from whitelist, because rate of change " f"over {plural(self._days, 'day')} is {pct_change:.3f}, " - f"which is below the threshold of {self._min_rate_of_change}.") + f"which is below the threshold of {self._min_rate_of_change}.", + logger.info) result = False self._pair_cache[pair] = result diff --git a/freqtrade/plugins/protections/cooldown_period.py b/freqtrade/plugins/protections/cooldown_period.py index 4fe0a4fdc..1abec7218 100644 --- a/freqtrade/plugins/protections/cooldown_period.py +++ b/freqtrade/plugins/protections/cooldown_period.py @@ -1,6 +1,6 @@ import logging -from datetime import datetime, timedelta, timezone +from datetime import datetime, timedelta from typing import Any, Dict from freqtrade.persistence import Trade @@ -46,7 +46,7 @@ class CooldownPeriod(IProtection): ] trade = Trade.get_trades(filters).first() if trade: - self.log_once(logger.info, f"Cooldown for {pair} for {self._stop_duration}.") + self.log_once(f"Cooldown for {pair} for {self._stop_duration}.", logger.info) until = self.calculate_lock_end([trade], self._stop_duration) return True, until, self._reason() diff --git a/freqtrade/plugins/protections/iprotection.py b/freqtrade/plugins/protections/iprotection.py index 49fccb0e6..0f539bbd3 100644 --- a/freqtrade/plugins/protections/iprotection.py +++ b/freqtrade/plugins/protections/iprotection.py @@ -1,6 +1,6 @@ import logging -from abc import ABC, abstractmethod, abstractproperty +from abc import ABC, abstractmethod from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional, Tuple diff --git a/freqtrade/plugins/protections/low_profit_pairs.py b/freqtrade/plugins/protections/low_profit_pairs.py index 48efa3c9a..c45ba3a39 100644 --- a/freqtrade/plugins/protections/low_profit_pairs.py +++ b/freqtrade/plugins/protections/low_profit_pairs.py @@ -58,9 +58,8 @@ class LowProfitPairs(IProtection): profit = sum(trade.close_profit for trade in trades) if profit < self._required_profit: self.log_once( - logger.info, f"Trading for {pair} stopped due to {profit:.2f} < {self._required_profit} " - f"within {self._lookback_period} minutes.") + f"within {self._lookback_period} minutes.", logger.info) until = self.calculate_lock_end(trades, self._stop_duration) return True, until, self._reason(profit) diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index 51a2fded8..0645d366b 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -58,8 +58,8 @@ class StoplossGuard(IProtection): trades = Trade.get_trades(filters).all() if len(trades) > self._trade_limit: - self.log_once(logger.info, f"Trading stopped due to {self._trade_limit} " - f"stoplosses within {self._lookback_period} minutes.") + self.log_once(f"Trading stopped due to {self._trade_limit} " + f"stoplosses within {self._lookback_period} minutes.", logger.info) until = self.calculate_lock_end(trades, self._stop_duration) return True, until, self._reason() diff --git a/tests/plugins/test_pairlist.py b/tests/plugins/test_pairlist.py index 2f1617f6c..c2a4a69d7 100644 --- a/tests/plugins/test_pairlist.py +++ b/tests/plugins/test_pairlist.py @@ -102,14 +102,14 @@ def test_log_cached(mocker, static_pl_conf, markets, tickers): logmock = MagicMock() # Assign starting whitelist pl = freqtrade.pairlists._pairlist_handlers[0] - pl.log_once(logmock, 'Hello world') + pl.log_once('Hello world', logmock) assert logmock.call_count == 1 - pl.log_once(logmock, 'Hello world') + pl.log_once('Hello world', logmock) assert logmock.call_count == 1 assert pl._log_cache.currsize == 1 assert ('Hello world',) in pl._log_cache._Cache__data - pl.log_once(logmock, 'Hello world2') + pl.log_once('Hello world2', logmock) assert logmock.call_count == 2 assert pl._log_cache.currsize == 2 diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 3417b1a56..1a22d08a2 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -165,6 +165,7 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog): assert PairLocks.is_pair_locked('XRP/BTC') assert not PairLocks.is_global_lock() + @pytest.mark.parametrize("protectionconf,desc_expected,exception_expected", [ ({"method": "StoplossGuard", "lookback_period": 60, "trade_limit": 2}, "[{'StoplossGuard': 'StoplossGuard - Frequent Stoploss Guard, "