diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index db32d6fa5..c86e2dc85 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -128,8 +128,12 @@ class Analyze(object): # Check if dataframe is out of date signal_date = arrow.get(latest['date']) - if signal_date < arrow.now() - timedelta(minutes=(interval + 5)): - self.logger.warning('Too old dataframe for pair %s', pair) + if signal_date < arrow.utcnow() - timedelta(minutes=(interval + 5)): + self.logger.warning( + 'Outdated history for pair %s. Last tick is %s minutes old', + pair, + (arrow.utcnow() - signal_date).seconds // 60 + ) return (False, False) # return False ? (buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1 @@ -150,17 +154,17 @@ class Analyze(object): """ # Check if minimal roi has been reached and no longer in buy conditions (avoiding a fee) if self.min_roi_reached(trade=trade, current_rate=rate, current_time=date): - self.logger.debug('Executing sell due to ROI ...') + self.logger.debug('Required profit reached. Selling..') return True # Experimental: Check if the trade is profitable before selling it (avoid selling at loss) if self.config.get('experimental', {}).get('sell_profit_only', False): - self.logger.debug('Checking if trade is profitable ...') + self.logger.debug('Checking if trade is profitable..') if trade.calc_profit(rate=rate) <= 0: return False if sell and not buy and self.config.get('experimental', {}).get('use_sell_signal', False): - self.logger.debug('Executing sell due to sell signal ...') + self.logger.debug('Sell signal received. Selling..') return True return False diff --git a/freqtrade/exchange/bittrex.py b/freqtrade/exchange/bittrex.py index 2be81be2d..5aa07e460 100644 --- a/freqtrade/exchange/bittrex.py +++ b/freqtrade/exchange/bittrex.py @@ -52,7 +52,7 @@ class Bittrex(Exchange): 'MIN_TRADE_REQUIREMENT_NOT_MET', ] if response['message'] in temp_error_messages: - raise ContentDecodingError('Got {}'.format(response['message'])) + raise ContentDecodingError(response['message']) @property def fee(self) -> float: @@ -109,8 +109,7 @@ class Bittrex(Exchange): if not data.get('result') or\ not all(key in data.get('result', {}) for key in keys) or\ not all(data.get('result', {})[key] is not None for key in keys): - raise ContentDecodingError('{message} params=({pair})'.format( - message='Got invalid response from bittrex', + raise ContentDecodingError('Invalid response from Bittrex params=({pair})'.format( pair=pair)) # Update the pair self.cached_ticker[pair] = { @@ -132,22 +131,20 @@ class Bittrex(Exchange): elif tick_interval == 1440: interval = 'Day' else: - raise ValueError('Cannot parse tick_interval: {}'.format(tick_interval)) + raise ValueError('Unknown tick_interval: {}'.format(tick_interval)) data = _API_V2.get_candles(pair.replace('_', '-'), interval) # These sanity check are necessary because bittrex cannot keep their API stable. if not data.get('result'): - raise ContentDecodingError('{message} params=({pair})'.format( - message='Got invalid response from bittrex', + raise ContentDecodingError('Invalid response from Bittrex params=({pair})'.format( pair=pair)) for prop in ['C', 'V', 'O', 'H', 'L', 'T']: for tick in data['result']: if prop not in tick.keys(): - raise ContentDecodingError('{message} params=({pair})'.format( - message='Required property {} not present in response'.format(prop), - pair=pair)) + raise ContentDecodingError('Required property {} not present ' + 'in response params=({})'.format(prop, pair)) if not data['success']: Bittrex._validate_response(data) @@ -191,21 +188,21 @@ class Bittrex(Exchange): data = _API.get_markets() if not data['success']: Bittrex._validate_response(data) - raise OperationalException('{message}'.format(message=data['message'])) + raise OperationalException(data['message']) return [m['MarketName'].replace('-', '_') for m in data['result']] def get_market_summaries(self) -> List[Dict]: data = _API.get_market_summaries() if not data['success']: Bittrex._validate_response(data) - raise OperationalException('{message}'.format(message=data['message'])) + raise OperationalException(data['message']) return data['result'] def get_wallet_health(self) -> List[Dict]: data = _API_V2.get_wallet_health() if not data['success']: Bittrex._validate_response(data) - raise OperationalException('{message}'.format(message=data['message'])) + raise OperationalException(data['message']) return [{ 'Currency': entry['Health']['Currency'], 'IsActive': entry['Health']['IsActive'], diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 4b3201514..e245e92cb 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -191,20 +191,17 @@ class FreqtradeBot(object): Trade.session.flush() except (requests.exceptions.RequestException, json.JSONDecodeError) as error: - self.logger.warning( - 'Got %s in _process(), retrying in 30 seconds...', - error - ) + self.logger.warning('%s, retrying in 30 seconds...', error) time.sleep(Constants.RETRY_TIMEOUT) except OperationalException: self.rpc.send_msg( - '*Status:* Got OperationalException:\n```\n{traceback}```{hint}' + '*Status:* OperationalException:\n```\n{traceback}```{hint}' .format( traceback=traceback.format_exc(), hint='Issue `/start` if you think it is safe to restart.' ) ) - self.logger.exception('Got OperationalException. Stopping trader ...') + self.logger.exception('OperationalException. Stopping trader ...') self.update_state(State.STOPPED) return state_changed @@ -294,7 +291,7 @@ class FreqtradeBot(object): self.logger.debug('Ignoring %s in pair whitelist', trade.pair) if not whitelist: - raise DependencyException('No pair in whitelist') + raise DependencyException('No currency pairs in whitelist') # Pick pair based on StochRSI buy signals for _pair in whitelist: @@ -356,10 +353,7 @@ class FreqtradeBot(object): if self.create_trade(float(self.config['stake_amount']), interval): return True - self.logger.info( - 'Checked all whitelisted currencies. ' - 'Found no suitable entry positions for buying. Will keep looking ...' - ) + self.logger.info('Found no buy signals for whitelisted currencies. Trying again..') return False except DependencyException as exception: self.logger.warning('Unable to create trade: %s', exception) @@ -373,7 +367,7 @@ class FreqtradeBot(object): # Get order details for actual price per unit if trade.open_order_id: # Update trade with order values - self.logger.info('Got open order for %s', trade) + self.logger.info('Found open order for %s', trade) trade.update(exchange.get_order(trade.open_order_id)) if trade.is_open and trade.open_order_id is None: diff --git a/freqtrade/main.py b/freqtrade/main.py index 47e941c44..97515b68b 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -51,9 +51,9 @@ def main(sysargv: Dict) -> None: state = freqtrade.worker(old_state=state) except KeyboardInterrupt: - logger.info('Got SIGINT, aborting ...') + logger.info('SIGINT received, aborting ...') except BaseException: - logger.exception('Got fatal exception!') + logger.exception('Fatal exception!') finally: freqtrade.clean() sys.exit(0) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index fa1d290b9..0d4e4403b 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -427,7 +427,7 @@ class Telegram(RPC): # Sometimes the telegram server resets the current connection, # if this is the case we send the message again. self.logger.warning( - 'Got Telegram NetworkError: %s! Trying one more time.', + 'Telegram NetworkError: %s! Trying one more time.', network_err.message ) bot.send_message( @@ -438,6 +438,6 @@ class Telegram(RPC): ) except TelegramError as telegram_err: self.logger.warning( - 'Got TelegramError: %s! Giving up on that message.', + 'TelegramError: %s! Giving up on that message.', telegram_err.message ) diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 526ff54ab..4f6eab083 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -10,6 +10,7 @@ from freqtrade import OperationalException from freqtrade.exchange import init, validate_pairs, buy, sell, get_balance, get_balances, \ get_ticker, get_ticker_history, cancel_order, get_name, get_fee import freqtrade.exchange as exchange +from freqtrade.tests.conftest import log_has API_INIT = False @@ -26,10 +27,7 @@ def maybe_init_api(conf, mocker): def test_init(default_conf, mocker, caplog): caplog.set_level(logging.INFO) maybe_init_api(default_conf, mocker) - assert ('freqtrade.exchange', - logging.INFO, - 'Instance is running with dry_run enabled' - ) in caplog.record_tuples + assert log_has('Instance is running with dry_run enabled', caplog.record_tuples) def test_init_exception(default_conf): @@ -79,10 +77,8 @@ def test_validate_pairs_exception(default_conf, mocker, caplog): # with pytest.raises(RequestException, match=r'Unable to validate pairs'): validate_pairs(default_conf['exchange']['pair_whitelist']) - assert ('freqtrade.exchange', - logging.WARNING, - 'Unable to validate pairs (assuming they are correct). Reason: ' - ) in caplog.record_tuples + assert log_has('Unable to validate pairs (assuming they are correct). Reason: ', + caplog.record_tuples) def test_buy_dry_run(default_conf, mocker): diff --git a/freqtrade/tests/exchange/test_exchange_bittrex.py b/freqtrade/tests/exchange/test_exchange_bittrex.py index 99a964815..058c25de1 100644 --- a/freqtrade/tests/exchange/test_exchange_bittrex.py +++ b/freqtrade/tests/exchange/test_exchange_bittrex.py @@ -211,14 +211,14 @@ def test_exchange_bittrex_get_ticker_bad(): fb = FakeBittrex() fb.result = {'success': True, 'result': {'Bid': 1, 'Ask': 0}} # incomplete result - with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'): + with pytest.raises(ContentDecodingError, match=r'.*Invalid response from Bittrex params.*'): wb.get_ticker('BTC_ETH') fb.result = {'success': False, 'message': 'gone bad'} with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'): wb.get_ticker('BTC_ETH') fb.result = {'success': True, 'result': {}} # incomplete result - with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'): + with pytest.raises(ContentDecodingError, match=r'.*Invalid response from Bittrex params.*'): wb.get_ticker('BTC_ETH') fb.result = {'success': False, 'message': 'gone bad'} with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'): @@ -226,7 +226,7 @@ def test_exchange_bittrex_get_ticker_bad(): fb.result = {'success': True, 'result': {'Bid': 1, 'Ask': 0, 'Last': None}} # incomplete result - with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex params.*'): + with pytest.raises(ContentDecodingError, match=r'.*Invalid response from Bittrex params.*'): wb.get_ticker('BTC_ETH') @@ -242,7 +242,7 @@ def test_exchange_bittrex_get_ticker_history(): wb = make_wrap_bittrex() fb = FakeBittrex() assert wb.get_ticker_history('BTC_ETH', 5) - with pytest.raises(ValueError, match=r'.*Cannot parse tick_interval.*'): + with pytest.raises(ValueError, match=r'.*Unknown tick_interval.*'): wb.get_ticker_history('BTC_ETH', 2) fb.success = False @@ -250,7 +250,7 @@ def test_exchange_bittrex_get_ticker_history(): wb.get_ticker_history('BTC_ETH', 5) fb.success = True - with pytest.raises(ContentDecodingError, match=r'.*Got invalid response from bittrex.*'): + with pytest.raises(ContentDecodingError, match=r'.*Invalid response from Bittrex.*'): fb.result = {'bad': 0} wb.get_ticker_history('BTC_ETH', 5) diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 728a77e53..731b93176 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -13,11 +13,11 @@ from freqtrade import optimize from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration from freqtrade.arguments import Arguments from freqtrade.analyze import Analyze -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import default_conf, log_has # Avoid to reinit the same object again and again -_BACKTESTING = Backtesting(tt.default_conf()) +_BACKTESTING = Backtesting(default_conf()) def get_args(args) -> List[str]: @@ -184,21 +184,21 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config - assert tt.log_has( + assert log_has( 'Parameter --datadir detected: {} ...'.format(config['datadir']), caplog.record_tuples ) assert 'ticker_interval' in config - assert not tt.log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) assert 'live' not in config - assert not tt.log_has('Parameter -l/--live detected ...', caplog.record_tuples) + assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert 'realistic_simulation' not in config - assert not tt.log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) + assert not log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert 'refresh_pairs' not in config - assert not tt.log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) + assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert 'timerange' not in config assert 'export' not in config @@ -232,34 +232,34 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config - assert tt.log_has( + assert log_has( 'Parameter --datadir detected: {} ...'.format(config['datadir']), caplog.record_tuples ) assert 'ticker_interval' in config - assert tt.log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert tt.log_has( + assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert log_has( 'Using ticker_interval: 1 ...', caplog.record_tuples ) assert 'live' in config - assert tt.log_has('Parameter -l/--live detected ...', caplog.record_tuples) + assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert 'realistic_simulation'in config - assert tt.log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) - assert tt.log_has('Using max_open_trades: 1 ...', caplog.record_tuples) + assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) + assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples) assert 'refresh_pairs'in config - assert tt.log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) + assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert 'timerange' in config - assert tt.log_has( + assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog.record_tuples ) assert 'export' in config - assert tt.log_has( + assert log_has( 'Parameter --export detected: {} ...'.format(config['export']), caplog.record_tuples ) @@ -281,7 +281,7 @@ def test_start(mocker, default_conf, caplog) -> None: ] args = get_args(args) start(args) - assert tt.log_has( + assert log_has( 'Starting freqtrade in Backtesting mode', caplog.record_tuples ) @@ -422,7 +422,7 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None: 'up to 2017-11-14T22:59:00+00:00 (0 days)..' ] for line in exists: - assert tt.log_has(line, caplog.record_tuples) + assert log_has(line, caplog.record_tuples) def test_backtest(default_conf) -> None: @@ -605,4 +605,4 @@ def test_backtest_start_live(default_conf, mocker, caplog): ] for line in exists: - tt.log_has(line, caplog.record_tuples) + log_has(line, caplog.record_tuples) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 4661910dd..4f6b78595 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -4,11 +4,11 @@ from copy import deepcopy from unittest.mock import MagicMock import pandas as pd from freqtrade.optimize.hyperopt import Hyperopt -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import default_conf, log_has # Avoid to reinit the same object again and again -_HYPEROPT = Hyperopt(tt.default_conf()) +_HYPEROPT = Hyperopt(default_conf()) # Functions for recurrent object patching @@ -83,7 +83,7 @@ def test_log_results_if_loss_improves(caplog) -> None: 'result': 'foo' } ) - assert tt.log_has(' 1/2: foo. Loss 1.00000', caplog.record_tuples) + assert log_has(' 1/2: foo. Loss 1.00000', caplog.record_tuples) def test_no_log_if_loss_does_not_improve(caplog) -> None: @@ -245,7 +245,7 @@ def test_save_trials_saves_trials(mocker, caplog) -> None: hyperopt.save_trials() - assert tt.log_has( + assert log_has( 'Saving Trials to \'freqtrade/tests/optimize/ut_trials.pickle\'', caplog.record_tuples ) @@ -259,7 +259,7 @@ def test_read_trials_returns_trials_file(mocker, default_conf, caplog) -> None: hyperopt = _HYPEROPT hyperopt_trial = hyperopt.read_trials() - assert tt.log_has( + assert log_has( 'Reading Trials from \'freqtrade/tests/optimize/ut_trials.pickle\'', caplog.record_tuples ) diff --git a/freqtrade/tests/optimize/test_optimize.py b/freqtrade/tests/optimize/test_optimize.py index 4e35507f5..43f46291f 100644 --- a/freqtrade/tests/optimize/test_optimize.py +++ b/freqtrade/tests/optimize/test_optimize.py @@ -2,13 +2,13 @@ import os import json -import logging import uuid from shutil import copyfile from freqtrade import optimize from freqtrade.optimize.__init__ import make_testdata_path, download_pairs,\ download_backtesting_testdata, load_tickerdata_file, trim_tickerlist from freqtrade.misc import file_dump_json +from freqtrade.tests.conftest import log_has # Change this if modifying BTC_UNITEST testdatafile _BTC_UNITTEST_LENGTH = 13681 @@ -55,9 +55,7 @@ def test_load_data_30min_ticker(ticker_history, mocker, caplog) -> None: _backup_file(file, copy_file=True) optimize.load_data(None, pairs=['BTC_UNITTEST'], ticker_interval=30) assert os.path.isfile(file) is True - assert ('freqtrade.optimize', - logging.INFO, - 'Download the pair: "BTC_ETH", Interval: 30 min') not in caplog.record_tuples + assert not log_has('Download the pair: "BTC_ETH", Interval: 30 min', caplog.record_tuples) _clean_test_file(file) @@ -71,9 +69,7 @@ def test_load_data_5min_ticker(ticker_history, mocker, caplog) -> None: _backup_file(file, copy_file=True) optimize.load_data(None, pairs=['BTC_ETH'], ticker_interval=5) assert os.path.isfile(file) is True - assert ('freqtrade.optimize', - logging.INFO, - 'Download the pair: "BTC_ETH", Interval: 5 min') not in caplog.record_tuples + assert not log_has('Download the pair: "BTC_ETH", Interval: 5 min', caplog.record_tuples) _clean_test_file(file) @@ -87,9 +83,7 @@ def test_load_data_1min_ticker(ticker_history, mocker, caplog) -> None: _backup_file(file, copy_file=True) optimize.load_data(None, ticker_interval=1, pairs=['BTC_ETH']) assert os.path.isfile(file) is True - assert ('freqtrade.optimize', - logging.INFO, - 'Download the pair: "BTC_ETH", Interval: 1 min') not in caplog.record_tuples + assert not log_has('Download the pair: "BTC_ETH", Interval: 1 min', caplog.record_tuples) _clean_test_file(file) @@ -103,9 +97,7 @@ def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog) -> None: _backup_file(file) optimize.load_data(None, ticker_interval=1, pairs=['BTC_MEME']) assert os.path.isfile(file) is True - assert ('freqtrade.optimize', - logging.INFO, - 'Download the pair: "BTC_MEME", Interval: 1 min') in caplog.record_tuples + assert log_has('Download the pair: "BTC_MEME", Interval: 1 min', caplog.record_tuples) _clean_test_file(file) @@ -165,9 +157,7 @@ def test_download_pairs_exception(ticker_history, mocker, caplog) -> None: # clean files freshly downloaded _clean_test_file(file1_1) _clean_test_file(file1_5) - assert ('freqtrade.optimize.__init__', - logging.INFO, - 'Failed to download the pair: "BTC-MEME", Interval: 1 min') in caplog.record_tuples + assert log_has('Failed to download the pair: "BTC-MEME", Interval: 1 min', caplog.record_tuples) def test_download_backtesting_testdata(ticker_history, mocker) -> None: diff --git a/freqtrade/tests/rpc/test_rpc_manager.py b/freqtrade/tests/rpc/test_rpc_manager.py index e4a7d4cda..1d56dea3a 100644 --- a/freqtrade/tests/rpc/test_rpc_manager.py +++ b/freqtrade/tests/rpc/test_rpc_manager.py @@ -8,7 +8,7 @@ from unittest.mock import MagicMock from freqtrade.rpc.rpc_manager import RPCManager from freqtrade.rpc.telegram import Telegram -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import log_has, get_patched_freqtradebot def test_rpc_manager_object() -> None: @@ -26,7 +26,7 @@ def test__init__(mocker, default_conf) -> None: Test __init__() method """ init_mock = mocker.patch('freqtrade.rpc.rpc_manager.RPCManager._init', MagicMock()) - freqtradebot = tt.get_patched_freqtradebot(mocker, default_conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) assert rpc_manager.freqtrade == freqtradebot @@ -44,10 +44,10 @@ def test_init_telegram_disabled(mocker, default_conf, caplog) -> None: conf = deepcopy(default_conf) conf['telegram']['enabled'] = False - freqtradebot = tt.get_patched_freqtradebot(mocker, conf) + freqtradebot = get_patched_freqtradebot(mocker, conf) rpc_manager = RPCManager(freqtradebot) - assert not tt.log_has('Enabling rpc.telegram ...', caplog.record_tuples) + assert not log_has('Enabling rpc.telegram ...', caplog.record_tuples) assert rpc_manager.registered_modules == [] assert rpc_manager.telegram is None @@ -59,10 +59,10 @@ def test_init_telegram_enabled(mocker, default_conf, caplog) -> None: caplog.set_level(logging.DEBUG) mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) - freqtradebot = tt.get_patched_freqtradebot(mocker, default_conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) - assert tt.log_has('Enabling rpc.telegram ...', caplog.record_tuples) + assert log_has('Enabling rpc.telegram ...', caplog.record_tuples) len_modules = len(rpc_manager.registered_modules) assert len_modules == 1 assert 'telegram' in rpc_manager.registered_modules @@ -79,11 +79,11 @@ def test_cleanup_telegram_disabled(mocker, default_conf, caplog) -> None: conf = deepcopy(default_conf) conf['telegram']['enabled'] = False - freqtradebot = tt.get_patched_freqtradebot(mocker, conf) + freqtradebot = get_patched_freqtradebot(mocker, conf) rpc_manager = RPCManager(freqtradebot) rpc_manager.cleanup() - assert not tt.log_has('Cleaning up rpc.telegram ...', caplog.record_tuples) + assert not log_has('Cleaning up rpc.telegram ...', caplog.record_tuples) assert telegram_mock.call_count == 0 @@ -95,14 +95,14 @@ def test_cleanup_telegram_enabled(mocker, default_conf, caplog) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', MagicMock()) - freqtradebot = tt.get_patched_freqtradebot(mocker, default_conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) # Check we have Telegram as a registered modules assert 'telegram' in rpc_manager.registered_modules rpc_manager.cleanup() - assert tt.log_has('Cleaning up rpc.telegram ...', caplog.record_tuples) + assert log_has('Cleaning up rpc.telegram ...', caplog.record_tuples) assert 'telegram' not in rpc_manager.registered_modules assert telegram_mock.call_count == 1 @@ -116,11 +116,11 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None: conf = deepcopy(default_conf) conf['telegram']['enabled'] = False - freqtradebot = tt.get_patched_freqtradebot(mocker, conf) + freqtradebot = get_patched_freqtradebot(mocker, conf) rpc_manager = RPCManager(freqtradebot) rpc_manager.send_msg('test') - assert tt.log_has('test', caplog.record_tuples) + assert log_has('test', caplog.record_tuples) assert telegram_mock.call_count == 0 @@ -131,9 +131,9 @@ def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None: telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock()) mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) - freqtradebot = tt.get_patched_freqtradebot(mocker, default_conf) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) rpc_manager = RPCManager(freqtradebot) rpc_manager.send_msg('test') - assert tt.log_has('test', caplog.record_tuples) + assert log_has('test', caplog.record_tuples) assert telegram_mock.call_count == 1 diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py index 353a44c37..d227bd9fb 100644 --- a/freqtrade/tests/rpc/test_rpc_telegram.py +++ b/freqtrade/tests/rpc/test_rpc_telegram.py @@ -23,7 +23,6 @@ from freqtrade.persistence import Trade from freqtrade.state import State from freqtrade.tests.test_freqtradebot import patch_get_signal, patch_pymarketcap from freqtrade.tests.conftest import get_patched_freqtradebot, log_has -import freqtrade.tests.conftest as tt # test tools class DummyCls(Telegram): @@ -160,15 +159,15 @@ def test_authorized_only(default_conf, mocker, caplog) -> None: dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://'))) dummy.dummy_handler(bot=MagicMock(), update=update) assert dummy.state['called'] is True - assert tt.log_has( + assert log_has( 'Executing handler: dummy_handler for chat_id: 0', caplog.record_tuples ) - assert not tt.log_has( + assert not log_has( 'Rejected unauthorized message from: 0', caplog.record_tuples ) - assert not tt.log_has( + assert not log_has( 'Exception occurred within Telegram module', caplog.record_tuples ) @@ -191,15 +190,15 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None: dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://'))) dummy.dummy_handler(bot=MagicMock(), update=update) assert dummy.state['called'] is False - assert not tt.log_has( + assert not log_has( 'Executing handler: dummy_handler for chat_id: 3735928559', caplog.record_tuples ) - assert tt.log_has( + assert log_has( 'Rejected unauthorized message from: 3735928559', caplog.record_tuples ) - assert not tt.log_has( + assert not log_has( 'Exception occurred within Telegram module', caplog.record_tuples ) @@ -221,15 +220,15 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None: dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://'))) dummy.dummy_exception(bot=MagicMock(), update=update) assert dummy.state['called'] is False - assert not tt.log_has( + assert not log_has( 'Executing handler: dummy_handler for chat_id: 0', caplog.record_tuples ) - assert not tt.log_has( + assert not log_has( 'Rejected unauthorized message from: 0', caplog.record_tuples ) - assert tt.log_has( + assert log_has( 'Exception occurred within Telegram module', caplog.record_tuples ) @@ -1086,7 +1085,7 @@ def test_send_msg_network_error(default_conf, mocker, caplog) -> None: # Bot should've tried to send it twice assert len(bot.method_calls) == 2 - assert tt.log_has( - 'Got TelegramError: Oh snap! Giving up on that message.', + assert log_has( + 'Telegram NetworkError: Oh snap! Trying one more time.', caplog.record_tuples ) diff --git a/freqtrade/tests/test_analyze.py b/freqtrade/tests/test_analyze.py index 36e0cd59f..4d1c31de2 100644 --- a/freqtrade/tests/test_analyze.py +++ b/freqtrade/tests/test_analyze.py @@ -12,7 +12,7 @@ from pandas import DataFrame from freqtrade.analyze import Analyze, SignalType from freqtrade.optimize.__init__ import load_tickerdata_file -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import log_has # Avoid to reinit the same object again and again @@ -109,7 +109,7 @@ def test_get_signal_empty(default_conf, mocker, caplog): caplog.set_level(logging.INFO) mocker.patch('freqtrade.analyze.get_ticker_history', return_value=None) assert (False, False) == _ANALYZE.get_signal('foo', int(default_conf['ticker_interval'])) - assert tt.log_has('Empty ticker history for pair foo', caplog.record_tuples) + assert log_has('Empty ticker history for pair foo', caplog.record_tuples) def test_get_signal_exception_valueerror(default_conf, mocker, caplog): @@ -122,8 +122,7 @@ def test_get_signal_exception_valueerror(default_conf, mocker, caplog): ) ) assert (False, False) == _ANALYZE.get_signal('foo', int(default_conf['ticker_interval'])) - assert tt.log_has('Unable to analyze ticker for pair foo: xyz', - caplog.record_tuples) + assert log_has('Unable to analyze ticker for pair foo: xyz', caplog.record_tuples) def test_get_signal_empty_dataframe(default_conf, mocker, caplog): @@ -136,8 +135,7 @@ def test_get_signal_empty_dataframe(default_conf, mocker, caplog): ) ) assert (False, False) == _ANALYZE.get_signal('xyz', int(default_conf['ticker_interval'])) - assert tt.log_has('Empty dataframe for pair xyz', - caplog.record_tuples) + assert log_has('Empty dataframe for pair xyz', caplog.record_tuples) def test_get_signal_old_dataframe(default_conf, mocker, caplog): @@ -153,8 +151,10 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog): ) ) assert (False, False) == _ANALYZE.get_signal('xyz', int(default_conf['ticker_interval'])) - assert tt.log_has('Too old dataframe for pair xyz', - caplog.record_tuples) + assert log_has( + 'Outdated history for pair xyz. Last tick is 11 minutes old', + caplog.record_tuples + ) def test_get_signal_handles_exceptions(mocker): diff --git a/freqtrade/tests/test_configuration.py b/freqtrade/tests/test_configuration.py index 20b377ddf..0c532ae73 100644 --- a/freqtrade/tests/test_configuration.py +++ b/freqtrade/tests/test_configuration.py @@ -11,7 +11,7 @@ from jsonschema import ValidationError from freqtrade.arguments import Arguments from freqtrade.configuration import Configuration -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import log_has def test_configuration_object() -> None: @@ -64,7 +64,7 @@ def test_load_config_file(default_conf, mocker, caplog) -> None: assert file_mock.call_count == 1 assert validated_conf.items() >= default_conf.items() assert 'internals' in validated_conf - assert tt.log_has('Validating configuration ...', caplog.record_tuples) + assert log_has('Validating configuration ...', caplog.record_tuples) def test_load_config(default_conf, mocker) -> None: @@ -129,19 +129,19 @@ def test_show_info(default_conf, mocker, caplog) -> None: configuration = Configuration(args) configuration.get_config() - assert tt.log_has( + assert log_has( 'Parameter --dynamic-whitelist detected. ' 'Using dynamically generated whitelist. ' '(not applicable with Backtesting and Hyperopt)', caplog.record_tuples ) - assert tt.log_has( + assert log_has( 'Parameter --dry-run-db detected ...', caplog.record_tuples ) - assert tt.log_has( + assert log_has( 'Dry_run will use the DB file: "tradesv3.dry_run.sqlite"', caplog.record_tuples ) @@ -149,7 +149,7 @@ def test_show_info(default_conf, mocker, caplog) -> None: # Test the Dry run condition configuration.config.update({'dry_run': False}) configuration._load_common_config(configuration.config) - assert tt.log_has( + assert log_has( 'Dry run is disabled. (--dry_run_db ignored)', caplog.record_tuples ) @@ -179,21 +179,21 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config - assert tt.log_has( + assert log_has( 'Parameter --datadir detected: {} ...'.format(config['datadir']), caplog.record_tuples ) assert 'ticker_interval' in config - assert not tt.log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) assert 'live' not in config - assert not tt.log_has('Parameter -l/--live detected ...', caplog.record_tuples) + assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert 'realistic_simulation' not in config - assert not tt.log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) + assert not log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert 'refresh_pairs' not in config - assert not tt.log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) + assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert 'timerange' not in config assert 'export' not in config @@ -230,34 +230,34 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config - assert tt.log_has( + assert log_has( 'Parameter --datadir detected: {} ...'.format(config['datadir']), caplog.record_tuples ) assert 'ticker_interval' in config - assert tt.log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) - assert tt.log_has( + assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert log_has( 'Using ticker_interval: 1 ...', caplog.record_tuples ) assert 'live' in config - assert tt.log_has('Parameter -l/--live detected ...', caplog.record_tuples) + assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert 'realistic_simulation'in config - assert tt.log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) - assert tt.log_has('Using max_open_trades: 1 ...', caplog.record_tuples) + assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) + assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples) assert 'refresh_pairs'in config - assert tt.log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) + assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert 'timerange' in config - assert tt.log_has( + assert log_has( 'Parameter --timerange detected: {} ...'.format(config['timerange']), caplog.record_tuples ) assert 'export' in config - assert tt.log_has( + assert log_has( 'Parameter --export detected: {} ...'.format(config['export']), caplog.record_tuples ) @@ -282,4 +282,4 @@ def test_hyperopt_space_argument(mocker, default_conf, caplog) -> None: config = configuration.get_config() assert 'spaces' in config assert config['spaces'] == ['all'] - assert tt.log_has('Parameter -s/--spaces detected: [\'all\']', caplog.record_tuples) + assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog.record_tuples) diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py index c1a6819aa..7322ba12a 100644 --- a/freqtrade/tests/test_freqtradebot.py +++ b/freqtrade/tests/test_freqtradebot.py @@ -14,7 +14,7 @@ import pytest import requests from sqlalchemy import create_engine -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import log_has from freqtrade import DependencyException, OperationalException from freqtrade.exchange import Exchanges from freqtrade.freqtradebot import FreqtradeBot @@ -145,7 +145,7 @@ def test_throttle(mocker, default_conf, caplog) -> None: assert result == 42 assert end - start > 0.1 - assert tt.log_has('Throttling func for 0.10 seconds', caplog.record_tuples) + assert log_has('Throttling func for 0.10 seconds', caplog.record_tuples) result = freqtrade._throttle(func, min_secs=-1) assert result == 42 @@ -311,7 +311,7 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker) -> None: freqtrade.create_trade(0.001, int(default_conf['ticker_interval'])) - with pytest.raises(DependencyException, match=r'.*No pair in whitelist.*'): + with pytest.raises(DependencyException, match=r'.*No currency pairs in whitelist.*'): freqtrade.create_trade(default_conf['stake_amount'], int(default_conf['ticker_interval'])) @@ -336,7 +336,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker) -> freqtrade.create_trade(0.001, int(default_conf['ticker_interval'])) - with pytest.raises(DependencyException, match=r'.*No pair in whitelist.*'): + with pytest.raises(DependencyException, match=r'.*No currency pairs in whitelist.*'): freqtrade.create_trade(conf['stake_amount'], int(conf['ticker_interval'])) @@ -399,7 +399,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, assert trade.open_rate == 0.00001099 assert trade.amount == 90.99181073703367 - assert tt.log_has( + assert log_has( 'Checking buy signals to create a new trade with stake_amount: 0.001000 ...', caplog.record_tuples ) @@ -537,7 +537,7 @@ def test_process_maybe_execute_buy_exception(mocker, default_conf, caplog) -> No MagicMock(side_effect=DependencyException) ) freqtrade.process_maybe_execute_buy(int(default_conf['ticker_interval'])) - tt.log_has('Unable to create trade:', caplog.record_tuples) + log_has('Unable to create trade:', caplog.record_tuples) def test_process_maybe_execute_sell(mocker, default_conf) -> None: @@ -690,7 +690,7 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog) -> None: # if ROI is reached we must sell patch_get_signal(mocker, value=(False, True)) assert freqtrade.handle_trade(trade, interval=int(default_conf['ticker_interval'])) - assert tt.log_has('Executing sell due to ROI ...', caplog.record_tuples) + assert log_has('Required profit reached. Selling..', caplog.record_tuples) def test_handle_trade_experimental(default_conf, ticker, mocker, caplog) -> None: @@ -723,7 +723,7 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog) -> None patch_get_signal(mocker, value=(False, True)) assert freqtrade.handle_trade(trade, int(default_conf['ticker_interval'])) - assert tt.log_has('Executing sell due to sell signal ...', caplog.record_tuples) + assert log_has('Sell signal received. Selling..', caplog.record_tuples) def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mocker) -> None: diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index ef6aabedd..d1bade6ae 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -7,7 +7,7 @@ from unittest.mock import MagicMock import pytest from freqtrade.main import main, set_loggers -import freqtrade.tests.conftest as tt # test tools +from freqtrade.tests.conftest import log_has def test_parse_args_backtesting(mocker) -> None: @@ -78,8 +78,8 @@ def test_main(mocker, caplog) -> None: # Test Main + the KeyboardInterrupt exception with pytest.raises(SystemExit) as pytest_wrapped_e: main(args) - tt.log_has('Starting freqtrade', caplog.record_tuples) - tt.log_has('Got SIGINT, aborting ...', caplog.record_tuples) + log_has('Starting freqtrade', caplog.record_tuples) + log_has('Got SIGINT, aborting ...', caplog.record_tuples) assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code == 42 @@ -90,4 +90,4 @@ def test_main(mocker, caplog) -> None: ) with pytest.raises(SystemExit): main(args) - tt.log_has('Got fatal exception!', caplog.record_tuples) + log_has('Got fatal exception!', caplog.record_tuples)