Merge commit '4dca84817eb1b62047a9e4d282254392ea978e44' into feature/objectify

This commit is contained in:
Gerald Lonlas 2018-03-04 02:06:40 -08:00
commit 25d0e5f942
16 changed files with 133 additions and 153 deletions

View File

@ -128,8 +128,12 @@ class Analyze(object):
# Check if dataframe is out of date # Check if dataframe is out of date
signal_date = arrow.get(latest['date']) signal_date = arrow.get(latest['date'])
if signal_date < arrow.now() - timedelta(minutes=(interval + 5)): if signal_date < arrow.utcnow() - timedelta(minutes=(interval + 5)):
self.logger.warning('Too old dataframe for pair %s', pair) 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 ? return (False, False) # return False ?
(buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1 (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) # 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): 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 return True
# Experimental: Check if the trade is profitable before selling it (avoid selling at loss) # Experimental: Check if the trade is profitable before selling it (avoid selling at loss)
if self.config.get('experimental', {}).get('sell_profit_only', False): 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: if trade.calc_profit(rate=rate) <= 0:
return False return False
if sell and not buy and self.config.get('experimental', {}).get('use_sell_signal', 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 True
return False return False

View File

@ -52,7 +52,7 @@ class Bittrex(Exchange):
'MIN_TRADE_REQUIREMENT_NOT_MET', 'MIN_TRADE_REQUIREMENT_NOT_MET',
] ]
if response['message'] in temp_error_messages: if response['message'] in temp_error_messages:
raise ContentDecodingError('Got {}'.format(response['message'])) raise ContentDecodingError(response['message'])
@property @property
def fee(self) -> float: def fee(self) -> float:
@ -109,8 +109,7 @@ class Bittrex(Exchange):
if not data.get('result') or\ if not data.get('result') or\
not all(key in data.get('result', {}) for key in keys) 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): not all(data.get('result', {})[key] is not None for key in keys):
raise ContentDecodingError('{message} params=({pair})'.format( raise ContentDecodingError('Invalid response from Bittrex params=({pair})'.format(
message='Got invalid response from bittrex',
pair=pair)) pair=pair))
# Update the pair # Update the pair
self.cached_ticker[pair] = { self.cached_ticker[pair] = {
@ -132,22 +131,20 @@ class Bittrex(Exchange):
elif tick_interval == 1440: elif tick_interval == 1440:
interval = 'Day' interval = 'Day'
else: 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) data = _API_V2.get_candles(pair.replace('_', '-'), interval)
# These sanity check are necessary because bittrex cannot keep their API stable. # These sanity check are necessary because bittrex cannot keep their API stable.
if not data.get('result'): if not data.get('result'):
raise ContentDecodingError('{message} params=({pair})'.format( raise ContentDecodingError('Invalid response from Bittrex params=({pair})'.format(
message='Got invalid response from bittrex',
pair=pair)) pair=pair))
for prop in ['C', 'V', 'O', 'H', 'L', 'T']: for prop in ['C', 'V', 'O', 'H', 'L', 'T']:
for tick in data['result']: for tick in data['result']:
if prop not in tick.keys(): if prop not in tick.keys():
raise ContentDecodingError('{message} params=({pair})'.format( raise ContentDecodingError('Required property {} not present '
message='Required property {} not present in response'.format(prop), 'in response params=({})'.format(prop, pair))
pair=pair))
if not data['success']: if not data['success']:
Bittrex._validate_response(data) Bittrex._validate_response(data)
@ -191,21 +188,21 @@ class Bittrex(Exchange):
data = _API.get_markets() data = _API.get_markets()
if not data['success']: if not data['success']:
Bittrex._validate_response(data) Bittrex._validate_response(data)
raise OperationalException('{message}'.format(message=data['message'])) raise OperationalException(data['message'])
return [m['MarketName'].replace('-', '_') for m in data['result']] return [m['MarketName'].replace('-', '_') for m in data['result']]
def get_market_summaries(self) -> List[Dict]: def get_market_summaries(self) -> List[Dict]:
data = _API.get_market_summaries() data = _API.get_market_summaries()
if not data['success']: if not data['success']:
Bittrex._validate_response(data) Bittrex._validate_response(data)
raise OperationalException('{message}'.format(message=data['message'])) raise OperationalException(data['message'])
return data['result'] return data['result']
def get_wallet_health(self) -> List[Dict]: def get_wallet_health(self) -> List[Dict]:
data = _API_V2.get_wallet_health() data = _API_V2.get_wallet_health()
if not data['success']: if not data['success']:
Bittrex._validate_response(data) Bittrex._validate_response(data)
raise OperationalException('{message}'.format(message=data['message'])) raise OperationalException(data['message'])
return [{ return [{
'Currency': entry['Health']['Currency'], 'Currency': entry['Health']['Currency'],
'IsActive': entry['Health']['IsActive'], 'IsActive': entry['Health']['IsActive'],

View File

@ -191,20 +191,17 @@ class FreqtradeBot(object):
Trade.session.flush() Trade.session.flush()
except (requests.exceptions.RequestException, json.JSONDecodeError) as error: except (requests.exceptions.RequestException, json.JSONDecodeError) as error:
self.logger.warning( self.logger.warning('%s, retrying in 30 seconds...', error)
'Got %s in _process(), retrying in 30 seconds...',
error
)
time.sleep(Constants.RETRY_TIMEOUT) time.sleep(Constants.RETRY_TIMEOUT)
except OperationalException: except OperationalException:
self.rpc.send_msg( self.rpc.send_msg(
'*Status:* Got OperationalException:\n```\n{traceback}```{hint}' '*Status:* OperationalException:\n```\n{traceback}```{hint}'
.format( .format(
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
hint='Issue `/start` if you think it is safe to restart.' 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) self.update_state(State.STOPPED)
return state_changed return state_changed
@ -294,7 +291,7 @@ class FreqtradeBot(object):
self.logger.debug('Ignoring %s in pair whitelist', trade.pair) self.logger.debug('Ignoring %s in pair whitelist', trade.pair)
if not whitelist: if not whitelist:
raise DependencyException('No pair in whitelist') raise DependencyException('No currency pairs in whitelist')
# Pick pair based on StochRSI buy signals # Pick pair based on StochRSI buy signals
for _pair in whitelist: for _pair in whitelist:
@ -356,10 +353,7 @@ class FreqtradeBot(object):
if self.create_trade(float(self.config['stake_amount']), interval): if self.create_trade(float(self.config['stake_amount']), interval):
return True return True
self.logger.info( self.logger.info('Found no buy signals for whitelisted currencies. Trying again..')
'Checked all whitelisted currencies. '
'Found no suitable entry positions for buying. Will keep looking ...'
)
return False return False
except DependencyException as exception: except DependencyException as exception:
self.logger.warning('Unable to create trade: %s', 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 # Get order details for actual price per unit
if trade.open_order_id: if trade.open_order_id:
# Update trade with order values # 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)) trade.update(exchange.get_order(trade.open_order_id))
if trade.is_open and trade.open_order_id is None: if trade.is_open and trade.open_order_id is None:

View File

@ -51,9 +51,9 @@ def main(sysargv: Dict) -> None:
state = freqtrade.worker(old_state=state) state = freqtrade.worker(old_state=state)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info('Got SIGINT, aborting ...') logger.info('SIGINT received, aborting ...')
except BaseException: except BaseException:
logger.exception('Got fatal exception!') logger.exception('Fatal exception!')
finally: finally:
freqtrade.clean() freqtrade.clean()
sys.exit(0) sys.exit(0)

View File

@ -427,7 +427,7 @@ class Telegram(RPC):
# Sometimes the telegram server resets the current connection, # Sometimes the telegram server resets the current connection,
# if this is the case we send the message again. # if this is the case we send the message again.
self.logger.warning( self.logger.warning(
'Got Telegram NetworkError: %s! Trying one more time.', 'Telegram NetworkError: %s! Trying one more time.',
network_err.message network_err.message
) )
bot.send_message( bot.send_message(
@ -438,6 +438,6 @@ class Telegram(RPC):
) )
except TelegramError as telegram_err: except TelegramError as telegram_err:
self.logger.warning( self.logger.warning(
'Got TelegramError: %s! Giving up on that message.', 'TelegramError: %s! Giving up on that message.',
telegram_err.message telegram_err.message
) )

View File

@ -10,6 +10,7 @@ from freqtrade import OperationalException
from freqtrade.exchange import init, validate_pairs, buy, sell, get_balance, get_balances, \ from freqtrade.exchange import init, validate_pairs, buy, sell, get_balance, get_balances, \
get_ticker, get_ticker_history, cancel_order, get_name, get_fee get_ticker, get_ticker_history, cancel_order, get_name, get_fee
import freqtrade.exchange as exchange import freqtrade.exchange as exchange
from freqtrade.tests.conftest import log_has
API_INIT = False API_INIT = False
@ -26,10 +27,7 @@ def maybe_init_api(conf, mocker):
def test_init(default_conf, mocker, caplog): def test_init(default_conf, mocker, caplog):
caplog.set_level(logging.INFO) caplog.set_level(logging.INFO)
maybe_init_api(default_conf, mocker) maybe_init_api(default_conf, mocker)
assert ('freqtrade.exchange', assert log_has('Instance is running with dry_run enabled', caplog.record_tuples)
logging.INFO,
'Instance is running with dry_run enabled'
) in caplog.record_tuples
def test_init_exception(default_conf): 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'): # with pytest.raises(RequestException, match=r'Unable to validate pairs'):
validate_pairs(default_conf['exchange']['pair_whitelist']) validate_pairs(default_conf['exchange']['pair_whitelist'])
assert ('freqtrade.exchange', assert log_has('Unable to validate pairs (assuming they are correct). Reason: ',
logging.WARNING, caplog.record_tuples)
'Unable to validate pairs (assuming they are correct). Reason: '
) in caplog.record_tuples
def test_buy_dry_run(default_conf, mocker): def test_buy_dry_run(default_conf, mocker):

View File

@ -211,14 +211,14 @@ def test_exchange_bittrex_get_ticker_bad():
fb = FakeBittrex() fb = FakeBittrex()
fb.result = {'success': True, 'result': {'Bid': 1, 'Ask': 0}} # incomplete result 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') wb.get_ticker('BTC_ETH')
fb.result = {'success': False, 'message': 'gone bad'} fb.result = {'success': False, 'message': 'gone bad'}
with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'): with pytest.raises(btx.OperationalException, match=r'.*gone bad.*'):
wb.get_ticker('BTC_ETH') wb.get_ticker('BTC_ETH')
fb.result = {'success': True, 'result': {}} # incomplete result 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') wb.get_ticker('BTC_ETH')
fb.result = {'success': False, 'message': 'gone bad'} fb.result = {'success': False, 'message': 'gone bad'}
with pytest.raises(btx.OperationalException, match=r'.*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, fb.result = {'success': True,
'result': {'Bid': 1, 'Ask': 0, 'Last': None}} # incomplete result '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') wb.get_ticker('BTC_ETH')
@ -242,7 +242,7 @@ def test_exchange_bittrex_get_ticker_history():
wb = make_wrap_bittrex() wb = make_wrap_bittrex()
fb = FakeBittrex() fb = FakeBittrex()
assert wb.get_ticker_history('BTC_ETH', 5) 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) wb.get_ticker_history('BTC_ETH', 2)
fb.success = False fb.success = False
@ -250,7 +250,7 @@ def test_exchange_bittrex_get_ticker_history():
wb.get_ticker_history('BTC_ETH', 5) wb.get_ticker_history('BTC_ETH', 5)
fb.success = True 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} fb.result = {'bad': 0}
wb.get_ticker_history('BTC_ETH', 5) wb.get_ticker_history('BTC_ETH', 5)

View File

@ -13,11 +13,11 @@ from freqtrade import optimize
from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration
from freqtrade.arguments import Arguments from freqtrade.arguments import Arguments
from freqtrade.analyze import Analyze 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 # Avoid to reinit the same object again and again
_BACKTESTING = Backtesting(tt.default_conf()) _BACKTESTING = Backtesting(default_conf())
def get_args(args) -> List[str]: 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 'exchange' in config
assert 'pair_whitelist' in config['exchange'] assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config assert 'datadir' in config
assert tt.log_has( assert log_has(
'Parameter --datadir detected: {} ...'.format(config['datadir']), 'Parameter --datadir detected: {} ...'.format(config['datadir']),
caplog.record_tuples caplog.record_tuples
) )
assert 'ticker_interval' in config 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 '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 '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 '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 'timerange' not in config
assert 'export' 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 'exchange' in config
assert 'pair_whitelist' in config['exchange'] assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config assert 'datadir' in config
assert tt.log_has( assert log_has(
'Parameter --datadir detected: {} ...'.format(config['datadir']), 'Parameter --datadir detected: {} ...'.format(config['datadir']),
caplog.record_tuples caplog.record_tuples
) )
assert 'ticker_interval' in config assert 'ticker_interval' in config
assert tt.log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples)
assert tt.log_has( assert log_has(
'Using ticker_interval: 1 ...', 'Using ticker_interval: 1 ...',
caplog.record_tuples caplog.record_tuples
) )
assert 'live' in config 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 'realistic_simulation'in config
assert tt.log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples)
assert tt.log_has('Using max_open_trades: 1 ...', caplog.record_tuples) assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples)
assert 'refresh_pairs'in config 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 'timerange' in config
assert tt.log_has( assert log_has(
'Parameter --timerange detected: {} ...'.format(config['timerange']), 'Parameter --timerange detected: {} ...'.format(config['timerange']),
caplog.record_tuples caplog.record_tuples
) )
assert 'export' in config assert 'export' in config
assert tt.log_has( assert log_has(
'Parameter --export detected: {} ...'.format(config['export']), 'Parameter --export detected: {} ...'.format(config['export']),
caplog.record_tuples caplog.record_tuples
) )
@ -281,7 +281,7 @@ def test_start(mocker, default_conf, caplog) -> None:
] ]
args = get_args(args) args = get_args(args)
start(args) start(args)
assert tt.log_has( assert log_has(
'Starting freqtrade in Backtesting mode', 'Starting freqtrade in Backtesting mode',
caplog.record_tuples 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)..' 'up to 2017-11-14T22:59:00+00:00 (0 days)..'
] ]
for line in exists: 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: def test_backtest(default_conf) -> None:
@ -605,4 +605,4 @@ def test_backtest_start_live(default_conf, mocker, caplog):
] ]
for line in exists: for line in exists:
tt.log_has(line, caplog.record_tuples) log_has(line, caplog.record_tuples)

View File

@ -4,11 +4,11 @@ from copy import deepcopy
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pandas as pd import pandas as pd
from freqtrade.optimize.hyperopt import Hyperopt 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 # Avoid to reinit the same object again and again
_HYPEROPT = Hyperopt(tt.default_conf()) _HYPEROPT = Hyperopt(default_conf())
# Functions for recurrent object patching # Functions for recurrent object patching
@ -83,7 +83,7 @@ def test_log_results_if_loss_improves(caplog) -> None:
'result': 'foo' '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: 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() hyperopt.save_trials()
assert tt.log_has( assert log_has(
'Saving Trials to \'freqtrade/tests/optimize/ut_trials.pickle\'', 'Saving Trials to \'freqtrade/tests/optimize/ut_trials.pickle\'',
caplog.record_tuples caplog.record_tuples
) )
@ -259,7 +259,7 @@ def test_read_trials_returns_trials_file(mocker, default_conf, caplog) -> None:
hyperopt = _HYPEROPT hyperopt = _HYPEROPT
hyperopt_trial = hyperopt.read_trials() hyperopt_trial = hyperopt.read_trials()
assert tt.log_has( assert log_has(
'Reading Trials from \'freqtrade/tests/optimize/ut_trials.pickle\'', 'Reading Trials from \'freqtrade/tests/optimize/ut_trials.pickle\'',
caplog.record_tuples caplog.record_tuples
) )

View File

@ -2,13 +2,13 @@
import os import os
import json import json
import logging
import uuid import uuid
from shutil import copyfile from shutil import copyfile
from freqtrade import optimize from freqtrade import optimize
from freqtrade.optimize.__init__ import make_testdata_path, download_pairs,\ from freqtrade.optimize.__init__ import make_testdata_path, download_pairs,\
download_backtesting_testdata, load_tickerdata_file, trim_tickerlist download_backtesting_testdata, load_tickerdata_file, trim_tickerlist
from freqtrade.misc import file_dump_json from freqtrade.misc import file_dump_json
from freqtrade.tests.conftest import log_has
# Change this if modifying BTC_UNITEST testdatafile # Change this if modifying BTC_UNITEST testdatafile
_BTC_UNITTEST_LENGTH = 13681 _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) _backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['BTC_UNITTEST'], ticker_interval=30) optimize.load_data(None, pairs=['BTC_UNITTEST'], ticker_interval=30)
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert not log_has('Download the pair: "BTC_ETH", Interval: 30 min', caplog.record_tuples)
logging.INFO,
'Download the pair: "BTC_ETH", Interval: 30 min') not in caplog.record_tuples
_clean_test_file(file) _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) _backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['BTC_ETH'], ticker_interval=5) optimize.load_data(None, pairs=['BTC_ETH'], ticker_interval=5)
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert not log_has('Download the pair: "BTC_ETH", Interval: 5 min', caplog.record_tuples)
logging.INFO,
'Download the pair: "BTC_ETH", Interval: 5 min') not in caplog.record_tuples
_clean_test_file(file) _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) _backup_file(file, copy_file=True)
optimize.load_data(None, ticker_interval=1, pairs=['BTC_ETH']) optimize.load_data(None, ticker_interval=1, pairs=['BTC_ETH'])
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert not log_has('Download the pair: "BTC_ETH", Interval: 1 min', caplog.record_tuples)
logging.INFO,
'Download the pair: "BTC_ETH", Interval: 1 min') not in caplog.record_tuples
_clean_test_file(file) _clean_test_file(file)
@ -103,9 +97,7 @@ def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog) -> None:
_backup_file(file) _backup_file(file)
optimize.load_data(None, ticker_interval=1, pairs=['BTC_MEME']) optimize.load_data(None, ticker_interval=1, pairs=['BTC_MEME'])
assert os.path.isfile(file) is True assert os.path.isfile(file) is True
assert ('freqtrade.optimize', assert log_has('Download the pair: "BTC_MEME", Interval: 1 min', caplog.record_tuples)
logging.INFO,
'Download the pair: "BTC_MEME", Interval: 1 min') in caplog.record_tuples
_clean_test_file(file) _clean_test_file(file)
@ -165,9 +157,7 @@ def test_download_pairs_exception(ticker_history, mocker, caplog) -> None:
# clean files freshly downloaded # clean files freshly downloaded
_clean_test_file(file1_1) _clean_test_file(file1_1)
_clean_test_file(file1_5) _clean_test_file(file1_5)
assert ('freqtrade.optimize.__init__', assert log_has('Failed to download the pair: "BTC-MEME", Interval: 1 min', caplog.record_tuples)
logging.INFO,
'Failed to download the pair: "BTC-MEME", Interval: 1 min') in caplog.record_tuples
def test_download_backtesting_testdata(ticker_history, mocker) -> None: def test_download_backtesting_testdata(ticker_history, mocker) -> None:

View File

@ -8,7 +8,7 @@ from unittest.mock import MagicMock
from freqtrade.rpc.rpc_manager import RPCManager from freqtrade.rpc.rpc_manager import RPCManager
from freqtrade.rpc.telegram import Telegram 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: def test_rpc_manager_object() -> None:
@ -26,7 +26,7 @@ def test__init__(mocker, default_conf) -> None:
Test __init__() method Test __init__() method
""" """
init_mock = mocker.patch('freqtrade.rpc.rpc_manager.RPCManager._init', MagicMock()) 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) rpc_manager = RPCManager(freqtradebot)
assert rpc_manager.freqtrade == 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 = deepcopy(default_conf)
conf['telegram']['enabled'] = False conf['telegram']['enabled'] = False
freqtradebot = tt.get_patched_freqtradebot(mocker, conf) freqtradebot = get_patched_freqtradebot(mocker, conf)
rpc_manager = RPCManager(freqtradebot) 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.registered_modules == []
assert rpc_manager.telegram is None 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) caplog.set_level(logging.DEBUG)
mocker.patch('freqtrade.rpc.telegram.Telegram._init', 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 = 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) len_modules = len(rpc_manager.registered_modules)
assert len_modules == 1 assert len_modules == 1
assert 'telegram' in rpc_manager.registered_modules 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 = deepcopy(default_conf)
conf['telegram']['enabled'] = False conf['telegram']['enabled'] = False
freqtradebot = tt.get_patched_freqtradebot(mocker, conf) freqtradebot = get_patched_freqtradebot(mocker, conf)
rpc_manager = RPCManager(freqtradebot) rpc_manager = RPCManager(freqtradebot)
rpc_manager.cleanup() 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 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()) mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', 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) rpc_manager = RPCManager(freqtradebot)
# Check we have Telegram as a registered modules # Check we have Telegram as a registered modules
assert 'telegram' in rpc_manager.registered_modules assert 'telegram' in rpc_manager.registered_modules
rpc_manager.cleanup() 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' not in rpc_manager.registered_modules
assert telegram_mock.call_count == 1 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 = deepcopy(default_conf)
conf['telegram']['enabled'] = False conf['telegram']['enabled'] = False
freqtradebot = tt.get_patched_freqtradebot(mocker, conf) freqtradebot = get_patched_freqtradebot(mocker, conf)
rpc_manager = RPCManager(freqtradebot) rpc_manager = RPCManager(freqtradebot)
rpc_manager.send_msg('test') 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 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()) telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
mocker.patch('freqtrade.rpc.telegram.Telegram._init', 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 = RPCManager(freqtradebot)
rpc_manager.send_msg('test') 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 assert telegram_mock.call_count == 1

View File

@ -23,7 +23,6 @@ from freqtrade.persistence import Trade
from freqtrade.state import State from freqtrade.state import State
from freqtrade.tests.test_freqtradebot import patch_get_signal, patch_pymarketcap from freqtrade.tests.test_freqtradebot import patch_get_signal, patch_pymarketcap
from freqtrade.tests.conftest import get_patched_freqtradebot, log_has from freqtrade.tests.conftest import get_patched_freqtradebot, log_has
import freqtrade.tests.conftest as tt # test tools
class DummyCls(Telegram): class DummyCls(Telegram):
@ -160,15 +159,15 @@ def test_authorized_only(default_conf, mocker, caplog) -> None:
dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://'))) dummy = DummyCls(FreqtradeBot(conf, create_engine('sqlite://')))
dummy.dummy_handler(bot=MagicMock(), update=update) dummy.dummy_handler(bot=MagicMock(), update=update)
assert dummy.state['called'] is True assert dummy.state['called'] is True
assert tt.log_has( assert log_has(
'Executing handler: dummy_handler for chat_id: 0', 'Executing handler: dummy_handler for chat_id: 0',
caplog.record_tuples caplog.record_tuples
) )
assert not tt.log_has( assert not log_has(
'Rejected unauthorized message from: 0', 'Rejected unauthorized message from: 0',
caplog.record_tuples caplog.record_tuples
) )
assert not tt.log_has( assert not log_has(
'Exception occurred within Telegram module', 'Exception occurred within Telegram module',
caplog.record_tuples 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 = DummyCls(FreqtradeBot(conf, create_engine('sqlite://')))
dummy.dummy_handler(bot=MagicMock(), update=update) dummy.dummy_handler(bot=MagicMock(), update=update)
assert dummy.state['called'] is False assert dummy.state['called'] is False
assert not tt.log_has( assert not log_has(
'Executing handler: dummy_handler for chat_id: 3735928559', 'Executing handler: dummy_handler for chat_id: 3735928559',
caplog.record_tuples caplog.record_tuples
) )
assert tt.log_has( assert log_has(
'Rejected unauthorized message from: 3735928559', 'Rejected unauthorized message from: 3735928559',
caplog.record_tuples caplog.record_tuples
) )
assert not tt.log_has( assert not log_has(
'Exception occurred within Telegram module', 'Exception occurred within Telegram module',
caplog.record_tuples 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 = DummyCls(FreqtradeBot(conf, create_engine('sqlite://')))
dummy.dummy_exception(bot=MagicMock(), update=update) dummy.dummy_exception(bot=MagicMock(), update=update)
assert dummy.state['called'] is False assert dummy.state['called'] is False
assert not tt.log_has( assert not log_has(
'Executing handler: dummy_handler for chat_id: 0', 'Executing handler: dummy_handler for chat_id: 0',
caplog.record_tuples caplog.record_tuples
) )
assert not tt.log_has( assert not log_has(
'Rejected unauthorized message from: 0', 'Rejected unauthorized message from: 0',
caplog.record_tuples caplog.record_tuples
) )
assert tt.log_has( assert log_has(
'Exception occurred within Telegram module', 'Exception occurred within Telegram module',
caplog.record_tuples 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 # Bot should've tried to send it twice
assert len(bot.method_calls) == 2 assert len(bot.method_calls) == 2
assert tt.log_has( assert log_has(
'Got TelegramError: Oh snap! Giving up on that message.', 'Telegram NetworkError: Oh snap! Trying one more time.',
caplog.record_tuples caplog.record_tuples
) )

View File

@ -12,7 +12,7 @@ from pandas import DataFrame
from freqtrade.analyze import Analyze, SignalType from freqtrade.analyze import Analyze, SignalType
from freqtrade.optimize.__init__ import load_tickerdata_file 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 # 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) caplog.set_level(logging.INFO)
mocker.patch('freqtrade.analyze.get_ticker_history', return_value=None) mocker.patch('freqtrade.analyze.get_ticker_history', return_value=None)
assert (False, False) == _ANALYZE.get_signal('foo', int(default_conf['ticker_interval'])) 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): 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 (False, False) == _ANALYZE.get_signal('foo', int(default_conf['ticker_interval']))
assert tt.log_has('Unable to analyze ticker for pair foo: xyz', assert log_has('Unable to analyze ticker for pair foo: xyz', caplog.record_tuples)
caplog.record_tuples)
def test_get_signal_empty_dataframe(default_conf, mocker, caplog): 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 (False, False) == _ANALYZE.get_signal('xyz', int(default_conf['ticker_interval']))
assert tt.log_has('Empty dataframe for pair xyz', assert log_has('Empty dataframe for pair xyz', caplog.record_tuples)
caplog.record_tuples)
def test_get_signal_old_dataframe(default_conf, mocker, caplog): 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 (False, False) == _ANALYZE.get_signal('xyz', int(default_conf['ticker_interval']))
assert tt.log_has('Too old dataframe for pair xyz', assert log_has(
caplog.record_tuples) 'Outdated history for pair xyz. Last tick is 11 minutes old',
caplog.record_tuples
)
def test_get_signal_handles_exceptions(mocker): def test_get_signal_handles_exceptions(mocker):

View File

@ -11,7 +11,7 @@ from jsonschema import ValidationError
from freqtrade.arguments import Arguments from freqtrade.arguments import Arguments
from freqtrade.configuration import Configuration 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: 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 file_mock.call_count == 1
assert validated_conf.items() >= default_conf.items() assert validated_conf.items() >= default_conf.items()
assert 'internals' in validated_conf 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: 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 = Configuration(args)
configuration.get_config() configuration.get_config()
assert tt.log_has( assert log_has(
'Parameter --dynamic-whitelist detected. ' 'Parameter --dynamic-whitelist detected. '
'Using dynamically generated whitelist. ' 'Using dynamically generated whitelist. '
'(not applicable with Backtesting and Hyperopt)', '(not applicable with Backtesting and Hyperopt)',
caplog.record_tuples caplog.record_tuples
) )
assert tt.log_has( assert log_has(
'Parameter --dry-run-db detected ...', 'Parameter --dry-run-db detected ...',
caplog.record_tuples caplog.record_tuples
) )
assert tt.log_has( assert log_has(
'Dry_run will use the DB file: "tradesv3.dry_run.sqlite"', 'Dry_run will use the DB file: "tradesv3.dry_run.sqlite"',
caplog.record_tuples caplog.record_tuples
) )
@ -149,7 +149,7 @@ def test_show_info(default_conf, mocker, caplog) -> None:
# Test the Dry run condition # Test the Dry run condition
configuration.config.update({'dry_run': False}) configuration.config.update({'dry_run': False})
configuration._load_common_config(configuration.config) configuration._load_common_config(configuration.config)
assert tt.log_has( assert log_has(
'Dry run is disabled. (--dry_run_db ignored)', 'Dry run is disabled. (--dry_run_db ignored)',
caplog.record_tuples caplog.record_tuples
) )
@ -179,21 +179,21 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
assert 'exchange' in config assert 'exchange' in config
assert 'pair_whitelist' in config['exchange'] assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config assert 'datadir' in config
assert tt.log_has( assert log_has(
'Parameter --datadir detected: {} ...'.format(config['datadir']), 'Parameter --datadir detected: {} ...'.format(config['datadir']),
caplog.record_tuples caplog.record_tuples
) )
assert 'ticker_interval' in config 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 '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 '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 '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 'timerange' not in config
assert 'export' 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 'exchange' in config
assert 'pair_whitelist' in config['exchange'] assert 'pair_whitelist' in config['exchange']
assert 'datadir' in config assert 'datadir' in config
assert tt.log_has( assert log_has(
'Parameter --datadir detected: {} ...'.format(config['datadir']), 'Parameter --datadir detected: {} ...'.format(config['datadir']),
caplog.record_tuples caplog.record_tuples
) )
assert 'ticker_interval' in config assert 'ticker_interval' in config
assert tt.log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples)
assert tt.log_has( assert log_has(
'Using ticker_interval: 1 ...', 'Using ticker_interval: 1 ...',
caplog.record_tuples caplog.record_tuples
) )
assert 'live' in config 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 'realistic_simulation'in config
assert tt.log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples)
assert tt.log_has('Using max_open_trades: 1 ...', caplog.record_tuples) assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples)
assert 'refresh_pairs'in config 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 'timerange' in config
assert tt.log_has( assert log_has(
'Parameter --timerange detected: {} ...'.format(config['timerange']), 'Parameter --timerange detected: {} ...'.format(config['timerange']),
caplog.record_tuples caplog.record_tuples
) )
assert 'export' in config assert 'export' in config
assert tt.log_has( assert log_has(
'Parameter --export detected: {} ...'.format(config['export']), 'Parameter --export detected: {} ...'.format(config['export']),
caplog.record_tuples caplog.record_tuples
) )
@ -282,4 +282,4 @@ def test_hyperopt_space_argument(mocker, default_conf, caplog) -> None:
config = configuration.get_config() config = configuration.get_config()
assert 'spaces' in config assert 'spaces' in config
assert config['spaces'] == ['all'] 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)

View File

@ -14,7 +14,7 @@ import pytest
import requests import requests
from sqlalchemy import create_engine 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 import DependencyException, OperationalException
from freqtrade.exchange import Exchanges from freqtrade.exchange import Exchanges
from freqtrade.freqtradebot import FreqtradeBot from freqtrade.freqtradebot import FreqtradeBot
@ -145,7 +145,7 @@ def test_throttle(mocker, default_conf, caplog) -> None:
assert result == 42 assert result == 42
assert end - start > 0.1 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) result = freqtrade._throttle(func, min_secs=-1)
assert result == 42 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'])) 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'])) 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'])) 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'])) 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.open_rate == 0.00001099
assert trade.amount == 90.99181073703367 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 ...', 'Checking buy signals to create a new trade with stake_amount: 0.001000 ...',
caplog.record_tuples caplog.record_tuples
) )
@ -537,7 +537,7 @@ def test_process_maybe_execute_buy_exception(mocker, default_conf, caplog) -> No
MagicMock(side_effect=DependencyException) MagicMock(side_effect=DependencyException)
) )
freqtrade.process_maybe_execute_buy(int(default_conf['ticker_interval'])) 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: 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 # if ROI is reached we must sell
patch_get_signal(mocker, value=(False, True)) patch_get_signal(mocker, value=(False, True))
assert freqtrade.handle_trade(trade, interval=int(default_conf['ticker_interval'])) 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: 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)) patch_get_signal(mocker, value=(False, True))
assert freqtrade.handle_trade(trade, int(default_conf['ticker_interval'])) 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: def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mocker) -> None:

View File

@ -7,7 +7,7 @@ from unittest.mock import MagicMock
import pytest import pytest
from freqtrade.main import main, set_loggers 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: def test_parse_args_backtesting(mocker) -> None:
@ -78,8 +78,8 @@ def test_main(mocker, caplog) -> None:
# Test Main + the KeyboardInterrupt exception # Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit) as pytest_wrapped_e: with pytest.raises(SystemExit) as pytest_wrapped_e:
main(args) main(args)
tt.log_has('Starting freqtrade', caplog.record_tuples) log_has('Starting freqtrade', caplog.record_tuples)
tt.log_has('Got SIGINT, aborting ...', caplog.record_tuples) log_has('Got SIGINT, aborting ...', caplog.record_tuples)
assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 42 assert pytest_wrapped_e.value.code == 42
@ -90,4 +90,4 @@ def test_main(mocker, caplog) -> None:
) )
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
main(args) main(args)
tt.log_has('Got fatal exception!', caplog.record_tuples) log_has('Got fatal exception!', caplog.record_tuples)