diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index 20d643a83..73347f1eb 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -28,9 +28,13 @@ class Ftx(Exchange): def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict) -> Dict: """ - Creates a stoploss market order. - Stoploss market orders is the only stoploss type supported by ftx. + Creates a stoploss order. + depending on order_types.stoploss configuration, uses 'market' or limit order. + + Limit orders are defined by having orderPrice set, otherwise a market order is used. """ + limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99) + limit_rate = stop_price * limit_price_pct ordertype = "stop" @@ -43,9 +47,11 @@ class Ftx(Exchange): try: params = self._params.copy() + if order_types.get('stoploss', 'market') == 'limit': + # set orderPrice to place limit order, otherwise it's a market order + params['orderPrice'] = limit_rate amount = self.amount_to_precision(pair, amount) - # set orderPrice to place limit order (?) order = self._api.create_order(symbol=pair, type=ordertype, side='sell', amount=amount, price=stop_price, params=params) diff --git a/tests/exchange/test_ftx.py b/tests/exchange/test_ftx.py index 2b75e5324..bead63096 100644 --- a/tests/exchange/test_ftx.py +++ b/tests/exchange/test_ftx.py @@ -34,6 +34,14 @@ def test_stoploss_order_ftx(default_conf, mocker): # stoploss_on_exchange_limit_ratio is irrelevant for ftx market orders order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=190, order_types={'stoploss_on_exchange_limit_ratio': 1.05}) + + assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC' + assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE + assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell' + assert api_mock.create_order.call_args_list[0][1]['amount'] == 1 + assert api_mock.create_order.call_args_list[0][1]['price'] == 190 + assert 'orderPrice' not in api_mock.create_order.call_args_list[0][1]['params'] + assert api_mock.create_order.call_count == 1 api_mock.create_order.reset_mock() @@ -48,6 +56,22 @@ def test_stoploss_order_ftx(default_conf, mocker): assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell' assert api_mock.create_order.call_args_list[0][1]['amount'] == 1 assert api_mock.create_order.call_args_list[0][1]['price'] == 220 + assert 'orderPrice' not in api_mock.create_order.call_args_list[0][1]['params'] + + api_mock.create_order.reset_mock() + order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, + order_types={'stoploss': 'limit'}) + + assert 'id' in order + assert 'info' in order + assert order['id'] == order_id + assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC' + assert api_mock.create_order.call_args_list[0][1]['type'] == STOPLOSS_ORDERTYPE + assert api_mock.create_order.call_args_list[0][1]['side'] == 'sell' + assert api_mock.create_order.call_args_list[0][1]['amount'] == 1 + assert api_mock.create_order.call_args_list[0][1]['price'] == 220 + assert 'orderPrice' in api_mock.create_order.call_args_list[0][1]['params'] + assert api_mock.create_order.call_args_list[0][1]['params']['orderPrice'] == 217.8 # test exception handling with pytest.raises(DependencyException):