move exchange-specific order-parsing to exchange class

Related to stoploss_on_exchange in combination with trailing stoploss.

Binance contains stopPrice in the info, while kraken returns the same
value as "price".
This commit is contained in:
Matthias 2020-01-19 19:54:30 +01:00
parent 7a22aaa111
commit cf9331919f
7 changed files with 55 additions and 5 deletions

View File

@ -32,6 +32,13 @@ class Binance(Exchange):
return super().get_order_book(pair, limit) return super().get_order_book(pair, limit)
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
"""
Verify stop_loss against stoploss-order value (limit or price)
Returns True if adjustment is necessary.
"""
return order['type'] == 'stop_loss_limit' and stop_loss > float(order['info']['stopPrice'])
def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict: def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict:
""" """
creates a stoploss limit order. creates a stoploss limit order.

View File

@ -519,6 +519,13 @@ class Exchange:
return self.create_order(pair, ordertype, 'sell', amount, rate, params) return self.create_order(pair, ordertype, 'sell', amount, rate, params)
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
"""
Verify stop_loss against stoploss-order value (limit or price)
Returns True if adjustment is necessary.
"""
raise OperationalException(f"stoploss is not implemented for {self.name}.")
def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict: def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict:
""" """
creates a stoploss order. creates a stoploss order.

View File

@ -51,6 +51,13 @@ class Kraken(Exchange):
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool:
"""
Verify stop_loss against stoploss-order value (limit or price)
Returns True if adjustment is necessary.
"""
return order['type'] == 'stop-loss' and stop_loss > float(order['price'])
def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict: def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict:
""" """
Creates a stoploss market order. Creates a stoploss market order.

View File

@ -718,8 +718,7 @@ class FreqtradeBot:
:param order: Current on exchange stoploss order :param order: Current on exchange stoploss order
:return: None :return: None
""" """
if self.exchange.stoploss_adjust(trade.stop_loss, order):
if trade.stop_loss > float(order['info']['stopPrice']):
# we check if the update is neccesary # we check if the update is neccesary
update_beat = self.strategy.order_types.get('stoploss_on_exchange_interval', 60) update_beat = self.strategy.order_types.get('stoploss_on_exchange_interval', 60)
if (datetime.utcnow() - trade.stoploss_last_update).total_seconds() >= update_beat: if (datetime.utcnow() - trade.stoploss_last_update).total_seconds() >= update_beat:

View File

@ -92,3 +92,17 @@ def test_stoploss_order_dry_run_binance(default_conf, mocker):
assert order['type'] == order_type assert order['type'] == order_type
assert order['price'] == 220 assert order['price'] == 220
assert order['amount'] == 1 assert order['amount'] == 1
def test_stoploss_adjust_binance(mocker, default_conf):
exchange = get_patched_exchange(mocker, default_conf, id='binance')
order = {
'type': 'stop_loss_limit',
'price': 1500,
'info': {'stopPrice': 1500},
}
assert exchange.stoploss_adjust(1501, order)
assert not exchange.stoploss_adjust(1499, order)
# Test with invalid order case
order['type'] = 'stop_loss'
assert not exchange.stoploss_adjust(1501, order)

View File

@ -1763,6 +1763,9 @@ def test_stoploss_order_unsupported_exchange(default_conf, mocker):
with pytest.raises(OperationalException, match=r"stoploss is not implemented .*"): with pytest.raises(OperationalException, match=r"stoploss is not implemented .*"):
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={}) exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(OperationalException, match=r"stoploss is not implemented .*"):
exchange.stoploss_adjust(1, {})
def test_merge_ft_has_dict(default_conf, mocker): def test_merge_ft_has_dict(default_conf, mocker):
mocker.patch.multiple('freqtrade.exchange.Exchange', mocker.patch.multiple('freqtrade.exchange.Exchange',

View File

@ -236,3 +236,16 @@ def test_stoploss_order_dry_run_kraken(default_conf, mocker):
assert order['type'] == order_type assert order['type'] == order_type
assert order['price'] == 220 assert order['price'] == 220
assert order['amount'] == 1 assert order['amount'] == 1
def test_stoploss_adjust_kraken(mocker, default_conf):
exchange = get_patched_exchange(mocker, default_conf, id='kraken')
order = {
'type': 'stop-loss',
'price': 1500,
}
assert exchange.stoploss_adjust(1501, order)
assert not exchange.stoploss_adjust(1499, order)
# Test with invalid order case ...
order['type'] = 'stop_loss_limit'
assert not exchange.stoploss_adjust(1501, order)