From 551dc79cf7692191b797351fb03ebf67a5771c2b Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 28 Oct 2018 13:15:49 +0100 Subject: [PATCH 1/3] Don't overwrite pair_whitelist in config dict Doing that will result in an empty whitelist after a short Exchange downtime --- freqtrade/freqtradebot.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index fa803bda7..3881f78d1 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -54,6 +54,7 @@ class FreqtradeBot(object): self.rpc: RPCManager = RPCManager(self) self.persistence = None self.exchange = Exchange(self.config) + self.active_pair_whitelist: List[str] = self.config['exchange']['pair_whitelist'] self._init_modules() def _init_modules(self) -> None: @@ -179,11 +180,10 @@ class FreqtradeBot(object): ) # Keep only the subsets of pairs wanted (up to nb_assets) - final_list = sanitized_list[:nb_assets] if nb_assets else sanitized_list - self.config['exchange']['pair_whitelist'] = final_list + self.active_pair_whitelist = sanitized_list[:nb_assets] if nb_assets else sanitized_list # Refreshing candles - self.exchange.refresh_tickers(final_list, self.strategy.ticker_interval) + self.exchange.refresh_tickers(self.active_pair_whitelist, self.strategy.ticker_interval) # Query trades from persistence layer trades = Trade.query.filter(Trade.is_open.is_(True)).all() @@ -380,7 +380,7 @@ class FreqtradeBot(object): 'Checking buy signals to create a new trade with stake_amount: %f ...', stake_amount ) - whitelist = copy.deepcopy(self.config['exchange']['pair_whitelist']) + whitelist = copy.deepcopy(self.active_pair_whitelist) # Remove currently opened and latest pairs from whitelist for trade in Trade.query.filter(Trade.is_open.is_(True)).all(): From 1121ec0724f0d69ee1d7c8b5791882cd8e6db01e Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 28 Oct 2018 14:43:35 +0100 Subject: [PATCH 2/3] don't have nb_assets as parameter - it's a config setting as any other --- freqtrade/freqtradebot.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 3881f78d1..ca503c89c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -108,11 +108,8 @@ class FreqtradeBot(object): constants.PROCESS_THROTTLE_SECS ) - nb_assets = self.config.get('dynamic_whitelist', None) - self._throttle(func=self._process, - min_secs=min_secs, - nb_assets=nb_assets) + min_secs=min_secs) return state def _startup_messages(self) -> None: @@ -163,15 +160,15 @@ class FreqtradeBot(object): time.sleep(duration) return result - def _process(self, nb_assets: Optional[int] = 0) -> bool: + def _process(self) -> bool: """ 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 """ state_changed = False try: + nb_assets = self.config.get('dynamic_whitelist', None) # Refresh whitelist based on wallet maintenance sanitized_list = self._refresh_whitelist( self._gen_pair_whitelist( From 2f55cbde35ebc839df94e414e7ddd02554a9c5be Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Oct 2018 19:23:56 +0100 Subject: [PATCH 3/3] fix #1298 --- freqtrade/freqtradebot.py | 11 +++++-- freqtrade/tests/test_freqtradebot.py | 46 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index ca503c89c..6cc46a07e 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -179,12 +179,17 @@ class FreqtradeBot(object): # Keep only the subsets of pairs wanted (up to nb_assets) self.active_pair_whitelist = sanitized_list[:nb_assets] if nb_assets else sanitized_list - # Refreshing candles - self.exchange.refresh_tickers(self.active_pair_whitelist, self.strategy.ticker_interval) - # Query trades from persistence layer trades = Trade.query.filter(Trade.is_open.is_(True)).all() + # Extend active-pair whitelist with pairs from open trades + # ensures that tickers are downloaded for open trades + self.active_pair_whitelist.extend([trade.pair for trade in trades + if trade.pair not in self.active_pair_whitelist]) + + # Refreshing candles + self.exchange.refresh_tickers(self.active_pair_whitelist, self.strategy.ticker_interval) + # First process current opened trades for trade in trades: state_changed |= self.process_maybe_execute_sell(trade) diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py index 6b13da35f..871e59240 100644 --- a/freqtrade/tests/test_freqtradebot.py +++ b/freqtrade/tests/test_freqtradebot.py @@ -663,6 +663,52 @@ def test_process_trade_handling( assert result is False +def test_process_trade_no_whitelist_pair( + default_conf, ticker, limit_buy_order, markets, fee, mocker) -> None: + """ Test _process with trade not in pair list """ + patch_RPCManager(mocker) + patch_exchange(mocker) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + get_ticker=ticker, + get_markets=markets, + buy=MagicMock(return_value={'id': limit_buy_order['id']}), + get_order=MagicMock(return_value=limit_buy_order), + get_fee=fee, + ) + freqtrade = FreqtradeBot(default_conf) + patch_get_signal(freqtrade) + pair = 'NOCLUE/BTC' + # create open trade not in whitelist + Trade.session.add(Trade( + pair=pair, + stake_amount=0.001, + fee_open=fee.return_value, + fee_close=fee.return_value, + is_open=True, + amount=20, + open_rate=0.01, + exchange='bittrex', + )) + Trade.session.add(Trade( + pair='ETH/BTC', + stake_amount=0.001, + fee_open=fee.return_value, + fee_close=fee.return_value, + is_open=True, + amount=12, + open_rate=0.001, + exchange='bittrex', + )) + + assert pair not in freqtrade.active_pair_whitelist + result = freqtrade._process() + assert pair in freqtrade.active_pair_whitelist + # Make sure each pair is only in the list once + assert len(freqtrade.active_pair_whitelist) == len(set(freqtrade.active_pair_whitelist)) + assert result is True + + def test_balance_fully_ask_side(mocker, default_conf) -> None: default_conf['bid_strategy']['ask_last_balance'] = 0.0 freqtrade = get_patched_freqtradebot(mocker, default_conf)