parent
24f480b4ce
commit
11c76c3c89
@ -9,7 +9,7 @@ import logging
|
||||
from copy import deepcopy
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from math import ceil
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from typing import Any, Coroutine, Dict, List, Optional, Tuple
|
||||
|
||||
import arrow
|
||||
import ccxt
|
||||
@ -1371,6 +1371,22 @@ class Exchange:
|
||||
data = sorted(data, key=lambda x: x[0])
|
||||
return pair, timeframe, data
|
||||
|
||||
def _build_coroutine(self, pair: str, timeframe: str, since_ms: Optional[int]) -> Coroutine:
|
||||
if not since_ms and self.required_candle_call_count > 1:
|
||||
# Multiple calls for one pair - to get more history
|
||||
one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit(timeframe)
|
||||
move_to = one_call * self.required_candle_call_count
|
||||
now = timeframe_to_next_date(timeframe)
|
||||
since_ms = int((now - timedelta(seconds=move_to // 1000)).timestamp() * 1000)
|
||||
|
||||
if since_ms:
|
||||
return self._async_get_historic_ohlcv(
|
||||
pair, timeframe, since_ms=since_ms, raise_=True)
|
||||
else:
|
||||
# One call ... "regular" refresh
|
||||
return self._async_get_candle_history(
|
||||
pair, timeframe, since_ms=since_ms)
|
||||
|
||||
def refresh_latest_ohlcv(self, pair_list: ListPairsWithTimeframes, *,
|
||||
since_ms: Optional[int] = None, cache: bool = True
|
||||
) -> Dict[Tuple[str, str], DataFrame]:
|
||||
@ -1389,22 +1405,15 @@ class Exchange:
|
||||
cached_pairs = []
|
||||
# Gather coroutines to run
|
||||
for pair, timeframe in set(pair_list):
|
||||
if timeframe not in self.timeframes:
|
||||
logger.warning(
|
||||
f"Cannot download ({pair}, {timeframe}) combination as this timeframe is "
|
||||
f"not available on {self.name}. Available timeframes are "
|
||||
f"{', '.join(self.timeframes)}.")
|
||||
continue
|
||||
if ((pair, timeframe) not in self._klines or not cache
|
||||
or self._now_is_time_to_refresh(pair, timeframe)):
|
||||
if not since_ms and self.required_candle_call_count > 1:
|
||||
# Multiple calls for one pair - to get more history
|
||||
one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit(timeframe)
|
||||
move_to = one_call * self.required_candle_call_count
|
||||
now = timeframe_to_next_date(timeframe)
|
||||
since_ms = int((now - timedelta(seconds=move_to // 1000)).timestamp() * 1000)
|
||||
|
||||
if since_ms:
|
||||
input_coroutines.append(self._async_get_historic_ohlcv(
|
||||
pair, timeframe, since_ms=since_ms, raise_=True))
|
||||
else:
|
||||
# One call ... "regular" refresh
|
||||
input_coroutines.append(self._async_get_candle_history(
|
||||
pair, timeframe, since_ms=since_ms))
|
||||
input_coroutines.append(self._build_coroutine(pair, timeframe, since_ms))
|
||||
else:
|
||||
logger.debug(
|
||||
"Using cached candle (OHLCV) data for pair %s, timeframe %s ...",
|
||||
|
@ -107,6 +107,8 @@ def patch_exchange(mocker, api_mock=None, id='binance', mock_markets=True) -> No
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
else:
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock())
|
||||
mocker.patch('freqtrade.exchange.Exchange.timeframes', PropertyMock(
|
||||
return_value=['5m', '15m', '1h', '1d']))
|
||||
|
||||
|
||||
def get_patched_exchange(mocker, config, api_mock=None, id='binance',
|
||||
|
@ -1692,6 +1692,13 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
|
||||
cache=False)
|
||||
assert len(res) == 3
|
||||
assert exchange._api_async.fetch_ohlcv.call_count == 3
|
||||
exchange._api_async.fetch_ohlcv.reset_mock()
|
||||
caplog.clear()
|
||||
# Call with invalid timeframe
|
||||
res = exchange.refresh_latest_ohlcv([('IOTA/ETH', '3m')],cache=False)
|
||||
assert not res
|
||||
assert len(res) == 0
|
||||
assert log_has_re(r'Cannot download \(IOTA\/ETH, 3m\).*', caplog)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
Loading…
Reference in New Issue
Block a user