diff --git a/config.json.example b/config.json.example index d133cd4df..7060e9881 100644 --- a/config.json.example +++ b/config.json.example @@ -5,7 +5,10 @@ "fiat_display_currency": "USD", "ticker_interval" : "5m", "dry_run": false, - "unfilledtimeout": 600, + "unfilledtimeout": { + "buy":10, + "sell":30 + } "bid_strategy": { "ask_last_balance": 0.0, "use_book_order": true, diff --git a/config_full.json.example b/config_full.json.example index 2b0930049..5fdf7b036 100644 --- a/config_full.json.example +++ b/config_full.json.example @@ -12,7 +12,10 @@ "0": 0.04 }, "stoploss": -0.10, - "unfilledtimeout": 600, + "unfilledtimeout": { + "buy":10, + "sell":30 + } "bid_strategy": { "ask_last_balance": 0.0, "use_book_order": true, diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 9cfa21565..ba7baab57 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -55,7 +55,14 @@ CONF_SCHEMA = { 'minProperties': 1 }, 'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True}, - 'unfilledtimeout': {'type': 'integer', 'minimum': 0}, + 'unfilledtimeout': { + 'type': 'object', + 'properties': { + 'use_book_order': {'type': 'boolean'}, + 'buy': {'type': 'number', 'minimum':3}, + 'sell': {'type': 'number', 'minimum':10} + } + }, 'bid_strategy': { 'type': 'object', 'properties': { @@ -76,7 +83,7 @@ CONF_SCHEMA = { 'use_book_order': {'type': 'boolean'}, 'book_order_min': {'type': 'number', 'minimum':1}, 'book_order_max': {'type': 'number', 'minimum':1} - }, + } }, 'exchange': {'$ref': '#/definitions/exchange'}, 'experimental': { diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 378c8af91..d36bbefca 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -164,7 +164,7 @@ class FreqtradeBot(object): if 'unfilledtimeout' in self.config: # Check and handle any timed out open orders - self.check_handle_timedout(self.config['unfilledtimeout']) + self.check_handle_timedout() Trade.session.flush() except TemporaryError as error: @@ -461,19 +461,22 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \ return True return False - def check_handle_timedout(self, timeoutvalue: int) -> None: + def check_handle_timedout(self) -> None: """ Check if any orders are timed out and cancel if neccessary :param timeoutvalue: Number of minutes until order is considered timed out :return: None """ - timeoutthreashold = arrow.utcnow().shift(minutes=-timeoutvalue).datetime + buy_timeout = self.config['unfilledtimeout']['buy'] + sell_timeout = self.config['unfilledtimeout']['sell'] + buy_timeoutthreashold = arrow.utcnow().shift(minutes=-buy_timeout).datetime + sell_timeoutthreashold = arrow.utcnow().shift(minutes=-sell_timeout).datetime for trade in Trade.query.filter(Trade.open_order_id.isnot(None)).all(): try: # FIXME: Somehow the query above returns results # where the open_order_id is in fact None. - # This is probably because the record got + # This is probably because the record got # updated via /forcesell in a different thread. if not trade.open_order_id: continue @@ -488,9 +491,9 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \ # Check if trade is still actually open if (int(order['filled']) == 0) and (order['status']=='open'): - if order['side'] == 'buy' and ordertime < timeoutthreashold: + if order['side'] == 'buy' and ordertime < buy_timeoutthreashold: self.handle_timedout_limit_buy(trade, order) - elif order['side'] == 'sell' and ordertime < timeoutthreashold: + elif order['side'] == 'sell' and ordertime < sell_timeoutthreashold: self.handle_timedout_limit_sell(trade, order) # FIX: 20180110, why is cancel.order unconditionally here, whereas