From 5906d37818d4039f7f9452d9574846443b7e8fa1 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Wed, 20 Feb 2019 15:12:04 +0300 Subject: [PATCH 1/5] code cleanup in _process() --- freqtrade/freqtradebot.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index f67be724c..e12456cf8 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -7,7 +7,7 @@ import logging import time import traceback from datetime import datetime -from typing import Any, Callable, Dict, List, Optional +from typing import Any, Callable, Dict, List, Optional, Tuple import arrow from requests.exceptions import RequestException @@ -166,15 +166,11 @@ class FreqtradeBot(object): 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]) + # It ensures that tickers are downloaded for open trades + self._extend_whitelist_with_trades(self.active_pair_whitelist) - # Create pair-whitelist tuple with (pair, ticker_interval) - pair_whitelist_tuple = [(pair, self.config['ticker_interval']) - for pair in self.active_pair_whitelist] # Refreshing candles - self.dataprovider.refresh(pair_whitelist_tuple, + self.dataprovider.refresh(self._create_pair_whitelist(self.active_pair_whitelist), self.strategy.informative_pairs()) # First process current opened trades @@ -204,6 +200,19 @@ class FreqtradeBot(object): self.state = State.STOPPED return state_changed + def _extend_whitelist_with_trades(self, whitelist: List[str]): + # Query trades from persistence layer + trades = Trade.query.filter(Trade.is_open.is_(True)).all() + + # Extend whitelist with pairs from open trades + whitelist.extend([trade.pair for trade in trades if trade.pair not in whitelist]) + + def _create_pair_whitelist(self, pairs: List[str]) -> List[Tuple[str, str]]: + """ + Create pair-whitelist tuple with (pair, ticker_interval) + """ + return [(pair, self.config['ticker_interval']) for pair in pairs] + def get_target_bid(self, pair: str) -> float: """ Calculates bid target between current ask price and last price From 199e3d2234b6c7d3361bff5f8b5fd1920e8db6ac Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Wed, 20 Feb 2019 15:13:21 +0300 Subject: [PATCH 2/5] typo in a comment --- freqtrade/freqtradebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index e12456cf8..eda648a64 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -157,7 +157,7 @@ class FreqtradeBot(object): self.pairlists.refresh_pairlist() self.active_pair_whitelist = self.pairlists.whitelist - # Calculating Edge positiong + # Calculating Edge positioning if self.edge: self.edge.calculate() self.active_pair_whitelist = self.edge.adjust(self.active_pair_whitelist) From fac0e4e603109856c7ca877f0e75f59570cece35 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Wed, 20 Feb 2019 15:56:26 +0300 Subject: [PATCH 3/5] more code cleanup in _process() --- freqtrade/freqtradebot.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index eda648a64..6f884a98f 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -163,11 +163,11 @@ class FreqtradeBot(object): self.active_pair_whitelist = self.edge.adjust(self.active_pair_whitelist) # Query trades from persistence layer - trades = Trade.query.filter(Trade.is_open.is_(True)).all() + trades = self._query_trades() # Extend active-pair whitelist with pairs from open trades # It ensures that tickers are downloaded for open trades - self._extend_whitelist_with_trades(self.active_pair_whitelist) + self._extend_whitelist_with_trades(self.active_pair_whitelist, trades) # Refreshing candles self.dataprovider.refresh(self._create_pair_whitelist(self.active_pair_whitelist), @@ -200,10 +200,11 @@ class FreqtradeBot(object): self.state = State.STOPPED return state_changed - def _extend_whitelist_with_trades(self, whitelist: List[str]): + def _query_trades(self) -> List[Any]: # Query trades from persistence layer - trades = Trade.query.filter(Trade.is_open.is_(True)).all() + return Trade.query.filter(Trade.is_open.is_(True)).all() + def _extend_whitelist_with_trades(self, whitelist: List[str], trades: List[Any]): # Extend whitelist with pairs from open trades whitelist.extend([trade.pair for trade in trades if trade.pair not in whitelist]) From 7bc874c7fd7e0e750b1a16968875f88cf21f4d55 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Wed, 20 Feb 2019 16:12:17 +0300 Subject: [PATCH 4/5] comments adjusted --- freqtrade/freqtradebot.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 6f884a98f..295c204e3 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -201,11 +201,15 @@ class FreqtradeBot(object): return state_changed def _query_trades(self) -> List[Any]: - # Query trades from persistence layer + """ + Query trades from persistence layer + """ return Trade.query.filter(Trade.is_open.is_(True)).all() def _extend_whitelist_with_trades(self, whitelist: List[str], trades: List[Any]): - # Extend whitelist with pairs from open trades + """ + Extend whitelist with pairs from open trades + """ whitelist.extend([trade.pair for trade in trades if trade.pair not in whitelist]) def _create_pair_whitelist(self, pairs: List[str]) -> List[Tuple[str, str]]: From 0c53bd6dd48c71837bc4ffec6cfe468f788e7b13 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 25 Feb 2019 20:00:17 +0100 Subject: [PATCH 5/5] Complete refactor, moving query_trades to persistance as get_open_trades --- freqtrade/freqtradebot.py | 12 ++------ freqtrade/persistence.py | 9 +++++- freqtrade/rpc/rpc.py | 8 ++--- freqtrade/tests/test_persistence.py | 45 +++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 14 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 295c204e3..392101e26 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -163,7 +163,7 @@ class FreqtradeBot(object): self.active_pair_whitelist = self.edge.adjust(self.active_pair_whitelist) # Query trades from persistence layer - trades = self._query_trades() + trades = Trade.get_open_trades() # Extend active-pair whitelist with pairs from open trades # It ensures that tickers are downloaded for open trades @@ -200,12 +200,6 @@ class FreqtradeBot(object): self.state = State.STOPPED return state_changed - def _query_trades(self) -> List[Any]: - """ - Query trades from persistence layer - """ - return Trade.query.filter(Trade.is_open.is_(True)).all() - def _extend_whitelist_with_trades(self, whitelist: List[str], trades: List[Any]): """ Extend whitelist with pairs from open trades @@ -265,7 +259,7 @@ class FreqtradeBot(object): avaliable_amount = self.wallets.get_free(self.config['stake_currency']) if stake_amount == constants.UNLIMITED_STAKE_AMOUNT: - open_trades = len(Trade.query.filter(Trade.is_open.is_(True)).all()) + open_trades = len(Trade.get_open_trades()) if open_trades >= self.config['max_open_trades']: logger.warning('Can\'t open a new trade: max number of trades is reached') return None @@ -323,7 +317,7 @@ class FreqtradeBot(object): 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(): + for trade in Trade.get_open_trades(): if trade.pair in whitelist: whitelist.remove(trade.pair) logger.debug('Ignoring %s in pair whitelist', trade.pair) diff --git a/freqtrade/persistence.py b/freqtrade/persistence.py index f9b34fc64..f603b139f 100644 --- a/freqtrade/persistence.py +++ b/freqtrade/persistence.py @@ -5,7 +5,7 @@ This module contains the class to persist trades into SQLite import logging from datetime import datetime from decimal import Decimal -from typing import Any, Dict, Optional +from typing import Any, Dict, List, Optional import arrow from sqlalchemy import (Boolean, Column, DateTime, Float, Integer, String, @@ -371,3 +371,10 @@ class Trade(_DECL_BASE): .filter(Trade.is_open.is_(True))\ .scalar() return total_open_stake_amount or 0 + + @staticmethod + def get_open_trades() -> List[Any]: + """ + Query trades from persistence layer + """ + return Trade.query.filter(Trade.is_open.is_(True)).all() diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index e83d9d41b..5aa9bae35 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -83,7 +83,7 @@ class RPC(object): a remotely exposed function """ # Fetch open trade - trades = Trade.query.filter(Trade.is_open.is_(True)).all() + trades = Trade.get_open_trades() if not trades: raise RPCException('no active trade') else: @@ -118,7 +118,7 @@ class RPC(object): return results def _rpc_status_table(self) -> DataFrame: - trades = Trade.query.filter(Trade.is_open.is_(True)).all() + trades = Trade.get_open_trades() if not trades: raise RPCException('no active order') else: @@ -366,7 +366,7 @@ class RPC(object): if trade_id == 'all': # Execute sell for all open orders - for trade in Trade.query.filter(Trade.is_open.is_(True)).all(): + for trade in Trade.get_open_trades(): _exec_forcesell(trade) Trade.session.flush() return @@ -442,7 +442,7 @@ class RPC(object): if self._freqtrade.state != State.RUNNING: raise RPCException('trader is not running') - return Trade.query.filter(Trade.is_open.is_(True)).all() + return Trade.get_open_trades() def _rpc_whitelist(self) -> Dict: """ Returns the currently active whitelist""" diff --git a/freqtrade/tests/test_persistence.py b/freqtrade/tests/test_persistence.py index be6efc2ff..a9519e693 100644 --- a/freqtrade/tests/test_persistence.py +++ b/freqtrade/tests/test_persistence.py @@ -629,3 +629,48 @@ def test_adjust_stop_loss(limit_buy_order, limit_sell_order, fee): assert round(trade.stop_loss, 8) == 1.26 assert trade.max_rate == 1.4 assert trade.initial_stop_loss == 0.95 + + +def test_get_open(default_conf, fee): + init(default_conf) + + # Simulate dry_run entries + trade = Trade( + pair='ETH/BTC', + stake_amount=0.001, + amount=123.0, + fee_open=fee.return_value, + fee_close=fee.return_value, + open_rate=0.123, + exchange='bittrex', + open_order_id='dry_run_buy_12345' + ) + Trade.session.add(trade) + + trade = Trade( + pair='ETC/BTC', + stake_amount=0.001, + amount=123.0, + fee_open=fee.return_value, + fee_close=fee.return_value, + open_rate=0.123, + exchange='bittrex', + is_open=False, + open_order_id='dry_run_sell_12345' + ) + Trade.session.add(trade) + + # Simulate prod entry + trade = Trade( + pair='ETC/BTC', + stake_amount=0.001, + amount=123.0, + fee_open=fee.return_value, + fee_close=fee.return_value, + open_rate=0.123, + exchange='bittrex', + open_order_id='prod_buy_12345' + ) + Trade.session.add(trade) + + assert len(Trade.get_open_trades()) == 2