Merge pull request #2779 from freqtrade/stoploss_market

Stoploss on exchange for Kraken
This commit is contained in:
hroff-1902
2020-02-02 14:48:45 +03:00
committed by GitHub
12 changed files with 264 additions and 75 deletions

View File

@@ -9,7 +9,7 @@ from freqtrade.exceptions import (DependencyException, InvalidOrderException,
from tests.conftest import get_patched_exchange
def test_stoploss_limit_order(default_conf, mocker):
def test_stoploss_order_binance(default_conf, mocker):
api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
order_type = 'stop_loss_limit'
@@ -28,46 +28,47 @@ def test_stoploss_limit_order(default_conf, mocker):
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
with pytest.raises(OperationalException):
order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=190, rate=200)
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=190,
order_types={'stoploss_on_exchange_limit_ratio': 1.05})
api_mock.create_order.reset_mock()
order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
assert 'id' in order
assert 'info' in order
assert order['id'] == order_id
assert api_mock.create_order.call_args[0][0] == 'ETH/BTC'
assert api_mock.create_order.call_args[0][1] == order_type
assert api_mock.create_order.call_args[0][2] == 'sell'
assert api_mock.create_order.call_args[0][3] == 1
assert api_mock.create_order.call_args[0][4] == 200
assert api_mock.create_order.call_args[0][5] == {'stopPrice': 220}
assert api_mock.create_order.call_args_list[0][1]['symbol'] == 'ETH/BTC'
assert api_mock.create_order.call_args_list[0][1]['type'] == order_type
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 api_mock.create_order.call_args_list[0][1]['params'] == {'stopPrice': 220}
# test exception handling
with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(InvalidOrderException):
api_mock.create_order = MagicMock(
side_effect=ccxt.InvalidOrder("binance Order would trigger immediately."))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(TemporaryError):
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(OperationalException, match=r".*DeadBeef.*"):
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
def test_stoploss_limit_order_dry_run(default_conf, mocker):
def test_stoploss_order_dry_run_binance(default_conf, mocker):
api_mock = MagicMock()
order_type = 'stop_loss_limit'
default_conf['dry_run'] = True
@@ -77,11 +78,12 @@ def test_stoploss_limit_order_dry_run(default_conf, mocker):
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
with pytest.raises(OperationalException):
order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=190, rate=200)
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=190,
order_types={'stoploss_on_exchange_limit_ratio': 1.05})
api_mock.create_order.reset_mock()
order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
assert 'id' in order
assert 'info' in order
@@ -90,3 +92,17 @@ def test_stoploss_limit_order_dry_run(default_conf, mocker):
assert order['type'] == order_type
assert order['price'] == 220
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

@@ -1758,10 +1758,13 @@ def test_get_fee(default_conf, mocker, exchange_name):
'get_fee', 'calculate_fee', symbol="ETH/BTC")
def test_stoploss_limit_order_unsupported_exchange(default_conf, mocker):
def test_stoploss_order_unsupported_exchange(default_conf, mocker):
exchange = get_patched_exchange(mocker, default_conf, 'bittrex')
with pytest.raises(OperationalException, match=r"stoploss_limit is not implemented .*"):
exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
with pytest.raises(OperationalException, match=r"stoploss is not implemented .*"):
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):

View File

@@ -3,6 +3,11 @@
from random import randint
from unittest.mock import MagicMock
import ccxt
import pytest
from freqtrade.exceptions import (DependencyException, InvalidOrderException,
OperationalException, TemporaryError)
from tests.conftest import get_patched_exchange
from tests.exchange.test_exchange import ccxt_exceptionhandlers
@@ -149,3 +154,98 @@ def test_get_balances_prod(default_conf, mocker):
assert balances['4ST']['used'] == 0.0
ccxt_exceptionhandlers(mocker, default_conf, api_mock, "kraken",
"get_balances", "fetch_balance")
def test_stoploss_order_kraken(default_conf, mocker):
api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
order_type = 'stop-loss'
api_mock.create_order = MagicMock(return_value={
'id': order_id,
'info': {
'foo': 'bar'
}
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
# stoploss_on_exchange_limit_ratio is irrelevant for kraken 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_count == 1
api_mock.create_order.reset_mock()
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
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'] == order_type
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 api_mock.create_order.call_args_list[0][1]['params'] == {'trading_agreement': 'agree'}
# test exception handling
with pytest.raises(DependencyException):
api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(InvalidOrderException):
api_mock.create_order = MagicMock(
side_effect=ccxt.InvalidOrder("kraken Order would trigger immediately."))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(TemporaryError):
api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
with pytest.raises(OperationalException, match=r".*DeadBeef.*"):
api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef"))
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
def test_stoploss_order_dry_run_kraken(default_conf, mocker):
api_mock = MagicMock()
order_type = 'stop-loss'
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
api_mock.create_order.reset_mock()
order = exchange.stoploss(pair='ETH/BTC', amount=1, stop_price=220, order_types={})
assert 'id' in order
assert 'info' in order
assert 'type' in order
assert order['type'] == order_type
assert order['price'] == 220
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)

View File

@@ -1023,8 +1023,8 @@ def test_add_stoploss_on_exchange(mocker, default_conf, limit_buy_order) -> None
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
return_value=limit_buy_order['amount'])
stoploss_limit = MagicMock(return_value={'id': 13434334})
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit)
stoploss = MagicMock(return_value={'id': 13434334})
mocker.patch('freqtrade.exchange.Exchange.stoploss', stoploss)
freqtrade = FreqtradeBot(default_conf)
freqtrade.strategy.order_types['stoploss_on_exchange'] = True
@@ -1037,13 +1037,13 @@ def test_add_stoploss_on_exchange(mocker, default_conf, limit_buy_order) -> None
freqtrade.exit_positions(trades)
assert trade.stoploss_order_id == '13434334'
assert stoploss_limit.call_count == 1
assert stoploss.call_count == 1
assert trade.is_open is True
def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
limit_buy_order, limit_sell_order) -> None:
stoploss_limit = MagicMock(return_value={'id': 13434334})
stoploss = MagicMock(return_value={'id': 13434334})
patch_RPCManager(mocker)
patch_exchange(mocker)
mocker.patch.multiple(
@@ -1056,7 +1056,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee,
stoploss_limit=stoploss_limit
stoploss=stoploss
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
@@ -1070,7 +1070,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
trade.stoploss_order_id = None
assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert stoploss_limit.call_count == 1
assert stoploss.call_count == 1
assert trade.stoploss_order_id == "13434334"
# Second case: when stoploss is set but it is not yet hit
@@ -1094,10 +1094,10 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
canceled_stoploss_order = MagicMock(return_value={'status': 'canceled'})
mocker.patch('freqtrade.exchange.Exchange.get_order', canceled_stoploss_order)
stoploss_limit.reset_mock()
stoploss.reset_mock()
assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert stoploss_limit.call_count == 1
assert stoploss.call_count == 1
assert trade.stoploss_order_id == "13434334"
# Fourth case: when stoploss is set and it is hit
@@ -1124,7 +1124,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
assert trade.is_open is False
mocker.patch(
'freqtrade.exchange.Exchange.stoploss_limit',
'freqtrade.exchange.Exchange.stoploss',
side_effect=DependencyException()
)
freqtrade.handle_stoploss_on_exchange(trade)
@@ -1134,11 +1134,11 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
# Fifth case: get_order returns InvalidOrder
# It should try to add stoploss order
trade.stoploss_order_id = 100
stoploss_limit.reset_mock()
stoploss.reset_mock()
mocker.patch('freqtrade.exchange.Exchange.get_order', side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit)
mocker.patch('freqtrade.exchange.Exchange.stoploss', stoploss)
freqtrade.handle_stoploss_on_exchange(trade)
assert stoploss_limit.call_count == 1
assert stoploss.call_count == 1
def test_handle_sle_cancel_cant_recreate(mocker, default_conf, fee, caplog,
@@ -1157,7 +1157,7 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf, fee, caplog,
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee,
get_order=MagicMock(return_value={'status': 'canceled'}),
stoploss_limit=MagicMock(side_effect=DependencyException()),
stoploss=MagicMock(side_effect=DependencyException()),
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
@@ -1191,7 +1191,7 @@ def test_create_stoploss_order_invalid_order(mocker, default_conf, caplog, fee,
sell=sell_mock,
get_fee=fee,
get_order=MagicMock(return_value={'status': 'canceled'}),
stoploss_limit=MagicMock(side_effect=InvalidOrderException()),
stoploss=MagicMock(side_effect=InvalidOrderException()),
)
freqtrade = FreqtradeBot(default_conf)
patch_get_signal(freqtrade)
@@ -1221,7 +1221,7 @@ def test_create_stoploss_order_invalid_order(mocker, default_conf, caplog, fee,
def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
limit_buy_order, limit_sell_order) -> None:
# When trailing stoploss is set
stoploss_limit = MagicMock(return_value={'id': 13434334})
stoploss = MagicMock(return_value={'id': 13434334})
patch_RPCManager(mocker)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
@@ -1233,7 +1233,8 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee,
stoploss_limit=stoploss_limit
stoploss=stoploss,
stoploss_adjust=MagicMock(return_value=True),
)
# enabling TSL
@@ -1288,7 +1289,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
cancel_order_mock = MagicMock()
stoploss_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.cancel_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_order_mock)
mocker.patch('freqtrade.exchange.Exchange.stoploss', stoploss_order_mock)
# stoploss should not be updated as the interval is 60 seconds
assert freqtrade.handle_trade(trade) is False
@@ -1307,7 +1308,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
cancel_order_mock.assert_called_once_with(100, 'ETH/BTC')
stoploss_order_mock.assert_called_once_with(amount=85.25149190110828,
pair='ETH/BTC',
rate=0.00002344 * 0.95 * 0.99,
order_types=freqtrade.strategy.order_types,
stop_price=0.00002344 * 0.95)
# price fell below stoploss, so dry-run sells trade.
@@ -1322,7 +1323,7 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, caplog,
limit_buy_order, limit_sell_order) -> None:
# When trailing stoploss is set
stoploss_limit = MagicMock(return_value={'id': 13434334})
stoploss = MagicMock(return_value={'id': 13434334})
patch_exchange(mocker)
mocker.patch.multiple(
@@ -1335,7 +1336,8 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee,
stoploss_limit=stoploss_limit
stoploss=stoploss,
stoploss_adjust=MagicMock(return_value=True),
)
# enabling TSL
@@ -1375,12 +1377,12 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
assert log_has_re(r"Could not cancel stoploss order abcd for pair ETH/BTC.*", caplog)
# Still try to create order
assert stoploss_limit.call_count == 1
assert stoploss.call_count == 1
# Fail creating stoploss order
caplog.clear()
cancel_mock = mocker.patch("freqtrade.exchange.Exchange.cancel_order", MagicMock())
mocker.patch("freqtrade.exchange.Exchange.stoploss_limit", side_effect=DependencyException())
mocker.patch("freqtrade.exchange.Exchange.stoploss", side_effect=DependencyException())
freqtrade.handle_trailing_stoploss_on_exchange(trade, stoploss_order_hanging)
assert cancel_mock.call_count == 1
assert log_has_re(r"Could not create trailing stoploss order for pair ETH/BTC\..*", caplog)
@@ -1390,12 +1392,13 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
limit_buy_order, limit_sell_order) -> None:
# When trailing stoploss is set
stoploss_limit = MagicMock(return_value={'id': 13434334})
stoploss = MagicMock(return_value={'id': 13434334})
patch_RPCManager(mocker)
patch_exchange(mocker)
patch_edge(mocker)
edge_conf['max_open_trades'] = float('inf')
edge_conf['dry_run_wallet'] = 999.9
edge_conf['exchange']['name'] = 'binance'
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=MagicMock(return_value={
@@ -1406,7 +1409,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
buy=MagicMock(return_value={'id': limit_buy_order['id']}),
sell=MagicMock(return_value={'id': limit_sell_order['id']}),
get_fee=fee,
stoploss_limit=stoploss_limit
stoploss=stoploss,
)
# enabling TSL
@@ -1459,7 +1462,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
cancel_order_mock = MagicMock()
stoploss_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.cancel_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_order_mock)
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss_order_mock)
# price goes down 5%
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', MagicMock(return_value={
@@ -1492,7 +1495,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
cancel_order_mock.assert_called_once_with(100, 'NEO/BTC')
stoploss_order_mock.assert_called_once_with(amount=2131074.168797954,
pair='NEO/BTC',
rate=0.00002344 * 0.99 * 0.99,
order_types=freqtrade.strategy.order_types,
stop_price=0.00002344 * 0.99)
@@ -2423,7 +2426,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf, ticker, fee, ticke
default_conf['exchange']['name'] = 'binance'
rpc_mock = patch_RPCManager(mocker)
patch_exchange(mocker)
stoploss_limit = MagicMock(return_value={
stoploss = MagicMock(return_value={
'id': 123,
'info': {
'foo': 'bar'
@@ -2437,7 +2440,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf, ticker, fee, ticke
get_fee=fee,
amount_to_precision=lambda s, x, y: y,
price_to_precision=lambda s, x, y: y,
stoploss_limit=stoploss_limit,
stoploss=stoploss,
cancel_order=cancel_order,
)
@@ -2482,14 +2485,14 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, f
price_to_precision=lambda s, x, y: y,
)
stoploss_limit = MagicMock(return_value={
stoploss = MagicMock(return_value={
'id': 123,
'info': {
'foo': 'bar'
}
})
mocker.patch('freqtrade.exchange.Binance.stoploss_limit', stoploss_limit)
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
freqtrade = FreqtradeBot(default_conf)
freqtrade.strategy.order_types['stoploss_on_exchange'] = True
@@ -2507,7 +2510,7 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, f
# Assuming stoploss on exchnage is hit
# stoploss_order_id should become None
# and trade should be sold at the price of stoploss
stoploss_limit_executed = MagicMock(return_value={
stoploss_executed = MagicMock(return_value={
"id": "123",
"timestamp": 1542707426845,
"datetime": "2018-11-20T09:50:26.845Z",
@@ -2525,7 +2528,7 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, f
"fee": None,
"trades": None
})
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_limit_executed)
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_executed)
freqtrade.exit_positions(trades)
assert trade.stoploss_order_id is None

View File

@@ -20,7 +20,7 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
default_conf['max_open_trades'] = 3
default_conf['exchange']['name'] = 'binance'
stoploss_limit = {
stoploss = {
'id': 123,
'info': {}
}
@@ -53,7 +53,7 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
SellCheckTuple(sell_flag=True, sell_type=SellType.SELL_SIGNAL)]
)
cancel_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Binance.stoploss_limit', stoploss_limit)
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker,