Refactoring _process/throttle to let throttle handle cases when we need an extra sleep time due to poor exchange conditions

This commit is contained in:
Jean-Baptiste LE STANG 2018-01-30 09:59:47 +01:00
parent 5f86c389b0
commit 10ef0874b5
4 changed files with 16 additions and 13 deletions

View File

@ -92,14 +92,17 @@ def process_maybe_execute_sell(trade, interval):
return False return False
def _process(interval: int, nb_assets: Optional[int] = 0) -> bool: def _process(interval: int, nb_assets: Optional[int] = 0) -> (bool, int):
""" """
Queries the persistence layer for open trades and handles them, Queries the persistence layer for open trades and handles them,
otherwise a new trade is created. otherwise a new trade is created.
:param: nb_assets: the maximum number of pairs to be traded at the same time :param: nb_assets: the maximum number of pairs to be traded at the same time
:return: True if one or more trades has been created or closed, False otherwise :return: a pair, the first value is True if one or more trades has been created
or closed, False otherwise, the second argument is a requested sleep time in
seconds to be used when exchange is having problems
""" """
state_changed = False state_changed = False
extra_time = 0
try: try:
# Refresh whitelist based on wallet maintenance # Refresh whitelist based on wallet maintenance
sanitized_list = refresh_whitelist( sanitized_list = refresh_whitelist(
@ -130,7 +133,7 @@ def _process(interval: int, nb_assets: Optional[int] = 0) -> bool:
'Got %s in _process(), retrying in 30 seconds...', 'Got %s in _process(), retrying in 30 seconds...',
error error
) )
time.sleep(30) extra_time = 30
except OperationalException: except OperationalException:
rpc.send_msg('*Status:* Got OperationalException:\n```\n{traceback}```{hint}'.format( rpc.send_msg('*Status:* Got OperationalException:\n```\n{traceback}```{hint}'.format(
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
@ -138,7 +141,7 @@ def _process(interval: int, nb_assets: Optional[int] = 0) -> bool:
)) ))
logger.exception('Got OperationalException. Stopping trader ...') logger.exception('Got OperationalException. Stopping trader ...')
update_state(State.STOPPED) update_state(State.STOPPED)
return state_changed return state_changed, extra_time
# FIX: 20180110, why is cancel.order unconditionally here, whereas # FIX: 20180110, why is cancel.order unconditionally here, whereas

View File

@ -115,9 +115,9 @@ def throttle(func: Callable[..., Any], min_secs: float, *args, **kwargs) -> Any:
:return: Any :return: Any
""" """
start = time.time() start = time.time()
result = func(*args, **kwargs) (result, extra_time) = func(*args, **kwargs)
end = time.time() end = time.time()
duration = max(min_secs - (end - start), 0.0) duration = max(max(min_secs - (end - start), 0.0), extra_time)
logger.debug('Throttling %s for %.2f seconds', func.__name__, duration) logger.debug('Throttling %s for %.2f seconds', func.__name__, duration)
time.sleep(duration) time.sleep(duration)
return result return result

View File

@ -91,7 +91,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, m
assert not trades assert not trades
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=int(default_conf['ticker_interval']))
assert result is True assert result == (True, 0)
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 1 assert len(trades) == 1
@ -117,7 +117,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker):
buy=MagicMock(side_effect=requests.exceptions.RequestException)) buy=MagicMock(side_effect=requests.exceptions.RequestException))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=int(default_conf['ticker_interval']))
assert result is False assert result == (False, 30)
assert sleep_mock.has_calls() assert sleep_mock.has_calls()
@ -135,7 +135,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker):
assert get_state() == State.RUNNING assert get_state() == State.RUNNING
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=int(default_conf['ticker_interval']))
assert result is False assert result == (False, 0)
assert get_state() == State.STOPPED assert get_state() == State.STOPPED
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0] assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]
@ -155,12 +155,12 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert not trades assert not trades
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=int(default_conf['ticker_interval']))
assert result is True assert result == (True, 0)
trades = Trade.query.filter(Trade.is_open.is_(True)).all() trades = Trade.query.filter(Trade.is_open.is_(True)).all()
assert len(trades) == 1 assert len(trades) == 1
result = _process(interval=int(default_conf['ticker_interval'])) result = _process(interval=int(default_conf['ticker_interval']))
assert result is False assert result == (False, 0)
def test_create_trade(default_conf, ticker, limit_buy_order, mocker): def test_create_trade(default_conf, ticker, limit_buy_order, mocker):

View File

@ -16,7 +16,7 @@ from freqtrade.misc import (common_args_parser, file_dump_json, load_config,
def test_throttle(): def test_throttle():
def func(): def func():
return 42 return (42, 1)
start = time.time() start = time.time()
result = throttle(func, min_secs=0.1) result = throttle(func, min_secs=0.1)
@ -32,7 +32,7 @@ def test_throttle():
def test_throttle_with_assets(): def test_throttle_with_assets():
def func(nb_assets=-1): def func(nb_assets=-1):
return nb_assets return (nb_assets, 0)
result = throttle(func, min_secs=0.1, nb_assets=666) result = throttle(func, min_secs=0.1, nb_assets=666)
assert result == 666 assert result == 666