From defa1c027d911c348586fbf7c0419113a122d796 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 25 Aug 2019 09:50:37 +0200 Subject: [PATCH] Move stoploss_limit to binance subclass --- freqtrade/exchange/binance.py | 52 ++++++++++++++++++++++++++++++++++ freqtrade/exchange/exchange.py | 48 ++++--------------------------- 2 files changed, 58 insertions(+), 42 deletions(-) diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 18e754e3f..b63ef59c8 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -2,6 +2,9 @@ import logging from typing import Dict +import ccxt + +from freqtrade import DependencyException, OperationalException, TemporaryError from freqtrade.exchange import Exchange logger = logging.getLogger(__name__) @@ -25,3 +28,52 @@ class Binance(Exchange): limit = min(list(filter(lambda x: limit <= x, limit_range))) return super().get_order_book(pair, limit) + + def stoploss_limit(self, pair: str, amount: float, stop_price: float, rate: float) -> Dict: + """ + creates a stoploss limit order. + this stoploss-limit is binance-specific. + It may work with a limited number of other exchanges, but this has not been tested yet. + + """ + ordertype = "stop_loss_limit" + + stop_price = self.symbol_price_prec(pair, stop_price) + + # Ensure rate is less than stop price + if stop_price <= rate: + raise OperationalException( + 'In stoploss limit order, stop price should be more than limit price') + + if self._config['dry_run']: + dry_order = self.dry_run_order( + pair, ordertype, "sell", amount, stop_price) + return dry_order + + params = self._params.copy() + params.update({'stopPrice': stop_price}) + try: + amount = self.symbol_amount_prec(pair, amount) + + rate = self.symbol_price_prec(pair, rate) + + order = self._api.create_order(pair, ordertype, 'sell', + amount, rate, params) + logger.info('stoploss limit order added for %s. ' + 'stop price: %s. limit: %s', pair, stop_price, rate) + return order + except ccxt.InsufficientFunds as e: + raise DependencyException( + f'Insufficient funds to create {ordertype} sell order on market {pair}.' + f'Tried to sell amount {amount} at rate {rate}.' + f'Message: {e}') from e + except ccxt.InvalidOrder as e: + raise DependencyException( + f'Could not create {ordertype} sell order on market {pair}. ' + f'Tried to sell amount {amount} at rate {rate}.' + f'Message: {e}') from e + except (ccxt.NetworkError, ccxt.ExchangeError) as e: + raise TemporaryError( + f'Could not place sell order due to {e.__class__.__name__}. Message: {e}') from e + except ccxt.BaseError as e: + raise OperationalException(e) from e diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 7a384b7cc..534e2ea65 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -450,50 +450,14 @@ class Exchange(object): def stoploss_limit(self, pair: str, amount: float, stop_price: float, rate: float) -> Dict: """ creates a stoploss limit order. - NOTICE: it is not supported by all exchanges. only binance is tested for now. - TODO: implementation maybe needs to be moved to the binance subclass + Since ccxt does not unify stoploss-limit orders yet, this needs to be implemented in each + exchange's subclass. + The exception below should never raise, since we disallow + starting the bot in validate_ordertypes() + Note: Changes to this interface need to be applied to all sub-classes too. """ - ordertype = "stop_loss_limit" - stop_price = self.symbol_price_prec(pair, stop_price) - - # Ensure rate is less than stop price - if stop_price <= rate: - raise OperationalException( - 'In stoploss limit order, stop price should be more than limit price') - - if self._config['dry_run']: - dry_order = self.dry_run_order( - pair, ordertype, "sell", amount, stop_price) - return dry_order - - params = self._params.copy() - params.update({'stopPrice': stop_price}) - try: - amount = self.symbol_amount_prec(pair, amount) - - rate = self.symbol_price_prec(pair, rate) - - order = self._api.create_order(pair, ordertype, 'sell', - amount, rate, params) - logger.info('stoploss limit order added for %s. ' - 'stop price: %s. limit: %s', pair, stop_price, rate) - return order - except ccxt.InsufficientFunds as e: - raise DependencyException( - f'Insufficient funds to create {ordertype} sell order on market {pair}.' - f'Tried to sell amount {amount} at rate {rate}.' - f'Message: {e}') from e - except ccxt.InvalidOrder as e: - raise DependencyException( - f'Could not create {ordertype} sell order on market {pair}. ' - f'Tried to sell amount {amount} at rate {rate}.' - f'Message: {e}') from e - except (ccxt.NetworkError, ccxt.ExchangeError) as e: - raise TemporaryError( - f'Could not place sell order due to {e.__class__.__name__}. Message: {e}') from e - except ccxt.BaseError as e: - raise OperationalException(e) from e + raise OperationalException(f"stoploss_limit not implemented for {self.name}.") @retrier def get_balance(self, currency: str) -> float: