Merge pull request #2559 from freqtrade/fix/cancelordercrash
Fix 'remaining' bug when handling buy timeout
This commit is contained in:
commit
2acd2542ac
@ -787,7 +787,7 @@ class FreqtradeBot:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Check if trade is still actually open
|
# Check if trade is still actually open
|
||||||
if float(order['remaining']) == 0.0:
|
if float(order.get('remaining', 0.0)) == 0.0:
|
||||||
self.wallets.update()
|
self.wallets.update()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -813,7 +813,8 @@ class FreqtradeBot:
|
|||||||
})
|
})
|
||||||
|
|
||||||
def handle_timedout_limit_buy(self, trade: Trade, order: Dict) -> bool:
|
def handle_timedout_limit_buy(self, trade: Trade, order: Dict) -> bool:
|
||||||
"""Buy timeout - cancel order
|
"""
|
||||||
|
Buy timeout - cancel order
|
||||||
:return: True if order was fully cancelled
|
:return: True if order was fully cancelled
|
||||||
"""
|
"""
|
||||||
reason = "cancelled due to timeout"
|
reason = "cancelled due to timeout"
|
||||||
@ -824,18 +825,22 @@ class FreqtradeBot:
|
|||||||
corder = order
|
corder = order
|
||||||
reason = "canceled on Exchange"
|
reason = "canceled on Exchange"
|
||||||
|
|
||||||
if corder['remaining'] == corder['amount']:
|
if corder.get('remaining', order['remaining']) == order['amount']:
|
||||||
# if trade is not partially completed, just delete the trade
|
# if trade is not partially completed, just delete the trade
|
||||||
self.handle_buy_order_full_cancel(trade, reason)
|
self.handle_buy_order_full_cancel(trade, reason)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# if trade is partially complete, edit the stake details for the trade
|
# if trade is partially complete, edit the stake details for the trade
|
||||||
# and close the order
|
# and close the order
|
||||||
trade.amount = corder['amount'] - corder['remaining']
|
# cancel_order may not contain the full order dict, so we need to fallback
|
||||||
|
# to the order dict aquired before cancelling.
|
||||||
|
# we need to fall back to the values from order if corder does not contain these keys.
|
||||||
|
trade.amount = order['amount'] - corder.get('remaining', order['remaining'])
|
||||||
trade.stake_amount = trade.amount * trade.open_rate
|
trade.stake_amount = trade.amount * trade.open_rate
|
||||||
# verify if fees were taken from amount to avoid problems during selling
|
# verify if fees were taken from amount to avoid problems during selling
|
||||||
try:
|
try:
|
||||||
new_amount = self.get_real_amount(trade, corder, trade.amount)
|
new_amount = self.get_real_amount(trade, corder if 'fee' in corder else order,
|
||||||
|
trade.amount)
|
||||||
if not isclose(order['amount'], new_amount, abs_tol=constants.MATH_CLOSE_PREC):
|
if not isclose(order['amount'], new_amount, abs_tol=constants.MATH_CLOSE_PREC):
|
||||||
trade.amount = new_amount
|
trade.amount = new_amount
|
||||||
# Fee was applied, so set to 0
|
# Fee was applied, so set to 0
|
||||||
|
@ -1804,7 +1804,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order,
|
|||||||
def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, open_trade,
|
def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, open_trade,
|
||||||
fee, mocker) -> None:
|
fee, mocker) -> None:
|
||||||
rpc_mock = patch_RPCManager(mocker)
|
rpc_mock = patch_RPCManager(mocker)
|
||||||
cancel_order_mock = MagicMock()
|
cancel_order_mock = MagicMock(return_value=limit_buy_order_old)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
@ -2089,6 +2089,29 @@ def test_handle_timedout_limit_buy(mocker, default_conf, limit_buy_order) -> Non
|
|||||||
assert cancel_order_mock.call_count == 1
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_handle_timedout_limit_buy_corder_empty(mocker, default_conf, limit_buy_order) -> None:
|
||||||
|
patch_RPCManager(mocker)
|
||||||
|
patch_exchange(mocker)
|
||||||
|
cancel_order_mock = MagicMock(return_value={})
|
||||||
|
mocker.patch.multiple(
|
||||||
|
'freqtrade.exchange.Exchange',
|
||||||
|
cancel_order=cancel_order_mock
|
||||||
|
)
|
||||||
|
|
||||||
|
freqtrade = FreqtradeBot(default_conf)
|
||||||
|
|
||||||
|
Trade.session = MagicMock()
|
||||||
|
trade = MagicMock()
|
||||||
|
limit_buy_order['remaining'] = limit_buy_order['amount']
|
||||||
|
assert freqtrade.handle_timedout_limit_buy(trade, limit_buy_order)
|
||||||
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
|
cancel_order_mock.reset_mock()
|
||||||
|
limit_buy_order['amount'] = 2
|
||||||
|
assert not freqtrade.handle_timedout_limit_buy(trade, limit_buy_order)
|
||||||
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
def test_handle_timedout_limit_sell(mocker, default_conf) -> None:
|
def test_handle_timedout_limit_sell(mocker, default_conf) -> None:
|
||||||
patch_RPCManager(mocker)
|
patch_RPCManager(mocker)
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
|
Loading…
Reference in New Issue
Block a user