From 9fbe1357902aa90243309781f164e7328fdc5b9a Mon Sep 17 00:00:00 2001 From: "Paul D. Mendes" Date: Mon, 11 May 2020 19:32:28 +0400 Subject: [PATCH] attached pairlist manager onto dataprovider init for unified access to dynamic whitelist --- freqtrade/data/dataprovider.py | 12 +++++---- freqtrade/freqtradebot.py | 6 ++--- tests/data/test_dataprovider.py | 48 ++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index af0914939..984652e24 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional, Tuple from pandas import DataFrame from freqtrade.data.history import load_pair_history +from freqtrade.exceptions import OperationalException from freqtrade.exchange import Exchange from freqtrade.state import RunMode @@ -18,9 +19,10 @@ logger = logging.getLogger(__name__) class DataProvider: - def __init__(self, config: dict, exchange: Exchange) -> None: + def __init__(self, config: dict, exchange: Exchange, pairlists=None) -> None: self._config = config self._exchange = exchange + self._pairlists = pairlists def refresh(self, pairlist: List[Tuple[str, str]], @@ -125,8 +127,8 @@ class DataProvider: As available pairs does not show whitelist until after informative pairs have been cached. :return: list of pairs in whitelist """ - from freqtrade.pairlist.pairlistmanager import PairListManager - pairlists = PairListManager(self._exchange, self._config) - pairlists.refresh_pairlist() - return pairlists.whitelist + if self._pairlists: + return self._pairlists.whitelist + else: + raise OperationalException("Dataprovider was not initialized with a pairlist provider.") diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 4f4b3e3bb..73f0873e4 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -71,15 +71,15 @@ class FreqtradeBot: self.wallets = Wallets(self.config, self.exchange) - self.dataprovider = DataProvider(self.config, self.exchange) + self.pairlists = PairListManager(self.exchange, self.config) + + self.dataprovider = DataProvider(self.config, self.exchange, self.pairlists) # Attach Dataprovider to Strategy baseclass IStrategy.dp = self.dataprovider # Attach Wallets to Strategy baseclass IStrategy.wallets = self.wallets - self.pairlists = PairListManager(self.exchange, self.config) - # Initializing Edge only if enabled self.edge = Edge(self.config, self.exchange, self.strategy) if \ self.config.get('edge', {}).get('enabled', False) else None diff --git a/tests/data/test_dataprovider.py b/tests/data/test_dataprovider.py index e5af80bc8..45ce1c009 100644 --- a/tests/data/test_dataprovider.py +++ b/tests/data/test_dataprovider.py @@ -1,10 +1,12 @@ -from unittest.mock import MagicMock, PropertyMock +from unittest.mock import MagicMock, patch from pandas import DataFrame +import pytest from freqtrade.data.dataprovider import DataProvider +from freqtrade.exceptions import OperationalException from freqtrade.state import RunMode -from tests.conftest import get_patched_exchange, get_patched_freqtradebot +from tests.conftest import get_patched_exchange def test_ohlcv(mocker, default_conf, ohlcv_history): @@ -151,21 +153,31 @@ def test_market(mocker, default_conf, markets): assert res is None -def test_current_whitelist(mocker, shitcoinmarkets, tickers, default_conf): - default_conf.update( - {"pairlists": [{"method": "VolumePairList", - "number_assets": 10, - "sort_key": "quoteVolume"}], }, ) - default_conf['exchange']['pair_blacklist'] = ['BLK/BTC'] +@patch('freqtrade.pairlist.pairlistmanager.PairListManager') +@patch('freqtrade.exchange.Exchange') +def test_current_whitelist(exchange, PairListManager, default_conf): + # patch default conf to volumepairlist + default_conf['pairlists'][0] = {'method': 'VolumePairList', "number_assets": 5} - mocker.patch.multiple('freqtrade.exchange.Exchange', get_tickers=tickers, - exchange_has=MagicMock(return_value=True), ) - bot = get_patched_freqtradebot(mocker, default_conf) - # Remock markets with shitcoinmarkets since get_patched_freqtradebot uses the markets fixture - mocker.patch.multiple('freqtrade.exchange.Exchange', - markets=PropertyMock(return_value=shitcoinmarkets), ) - # argument: use the whitelist dynamically by exchange-volume - whitelist = ['ETH/BTC', 'TKN/BTC', 'LTC/BTC', 'XRP/BTC', 'HOT/BTC', 'FUEL/BTC'] + pairlist = PairListManager(exchange, default_conf) + dp = DataProvider(default_conf, exchange, pairlist) - current_wl = bot.dataprovider.current_whitelist() - assert whitelist == current_wl + # Simulate volumepairs from exchange. + # pairlist.refresh_pairlist() + + # Set the pairs manually... this would be done in refresh pairlist + # default whitelist + volumePL - blacklist + default_whitelist = default_conf['exchange']['pair_whitelist'] + default_blacklist = default_conf['exchange']['pair_blacklist'] + volume_pairlist = ['ETH/BTC', 'LINK/BTC', 'ZRX/BTC', 'BCH/BTC', 'XRP/BTC'] + current_whitelist = list(set(volume_pairlist + default_whitelist)) + for pair in default_blacklist: + if pair in current_whitelist: + current_whitelist.remove(pair) + pairlist._whitelist = current_whitelist + + assert dp.current_whitelist() == pairlist._whitelist + + with pytest.raises(OperationalException): + dp = DataProvider(default_conf, exchange) + dp.current_whitelist()