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
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,
otherwise a new trade is created.
: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
extra_time = 0
try:
# Refresh whitelist based on wallet maintenance
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...',
error
)
time.sleep(30)
extra_time = 30
except OperationalException:
rpc.send_msg('*Status:* Got OperationalException:\n```\n{traceback}```{hint}'.format(
traceback=traceback.format_exc(),
@ -138,7 +141,7 @@ def _process(interval: int, nb_assets: Optional[int] = 0) -> bool:
))
logger.exception('Got OperationalException. Stopping trader ...')
update_state(State.STOPPED)
return state_changed
return state_changed, extra_time
# 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
"""
start = time.time()
result = func(*args, **kwargs)
(result, extra_time) = func(*args, **kwargs)
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)
time.sleep(duration)
return result

View File

@ -91,7 +91,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, m
assert not trades
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()
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))
init(default_conf, create_engine('sqlite://'))
result = _process(interval=int(default_conf['ticker_interval']))
assert result is False
assert result == (False, 30)
assert sleep_mock.has_calls()
@ -135,7 +135,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker):
assert get_state() == State.RUNNING
result = _process(interval=int(default_conf['ticker_interval']))
assert result is False
assert result == (False, 0)
assert get_state() == State.STOPPED
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()
assert not trades
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()
assert len(trades) == 1
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):

View File

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