Fix the dca order not being counted bug.

This commit is contained in:
Reigo Reinmets 2021-12-20 22:07:42 +02:00
parent d9f5694965
commit f6d36ce56b
2 changed files with 138 additions and 49 deletions

View File

@ -292,8 +292,8 @@ class FreqtradeBot(LoggingMixin):
for trade in trades: for trade in trades:
if trade.is_open and not trade.fee_updated('buy'): if trade.is_open and not trade.fee_updated('buy'):
order = trade.select_order('buy', False) order = trade.select_order('buy', False)
if order: open_order = trade.select_order('buy', True)
logger.info(f"Updating buy-fee on trade {trade} for order {order.order_id}.") if order and open_order is None:
self.update_trade_state(trade, order.order_id, send_msg=False) self.update_trade_state(trade, order.order_id, send_msg=False)
def handle_insufficient_funds(self, trade: Trade): def handle_insufficient_funds(self, trade: Trade):

View File

@ -4310,10 +4310,17 @@ def test_get_valid_price(mocker, default_conf_usdt) -> None:
assert valid_price_at_min_alwd > custom_price_under_min_alwd assert valid_price_at_min_alwd > custom_price_under_min_alwd
assert valid_price_at_min_alwd < proposed_price assert valid_price_at_min_alwd < proposed_price
def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
limit_buy_order_usdt_open) -> None: def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
patch_wallet(mocker, free=10000)
default_conf_usdt.update({
"position_adjustment_enable": True,
"dry_run": False,
"stake_amount": 10.0,
"dry_run_wallet": 1000.0,
})
freqtrade = FreqtradeBot(default_conf_usdt) freqtrade = FreqtradeBot(default_conf_usdt)
freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True)
bid = 11 bid = 11
@ -4333,23 +4340,26 @@ def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
pair = 'ETH/USDT' pair = 'ETH/USDT'
# Initial buy # Initial buy
limit_buy_order_usdt['status'] = 'closed' closed_successful_buy_order = {
limit_buy_order_usdt['pair'] = pair 'pair': pair,
limit_buy_order_usdt['ft_pair'] = pair 'ft_pair': pair,
limit_buy_order_usdt['ft_order_side'] = 'buy' 'ft_order_side': 'buy',
limit_buy_order_usdt['side'] = 'buy' 'side': 'buy',
limit_buy_order_usdt['price'] = bid 'type': 'limit',
limit_buy_order_usdt['average'] = bid 'status': 'closed',
limit_buy_order_usdt['cost'] = bid * stake_amount 'price': bid,
limit_buy_order_usdt['amount'] = stake_amount 'average': bid,
limit_buy_order_usdt['filled'] = stake_amount 'cost': bid * stake_amount,
limit_buy_order_usdt['ft_is_open'] = False 'amount': stake_amount,
limit_buy_order_usdt['id'] = '650' 'filled': stake_amount,
limit_buy_order_usdt['order_id'] = '650' 'ft_is_open': False,
'id': '650',
'order_id': '650'
}
mocker.patch('freqtrade.exchange.Exchange.create_order', mocker.patch('freqtrade.exchange.Exchange.create_order',
MagicMock(return_value=limit_buy_order_usdt)) MagicMock(return_value=closed_successful_buy_order))
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=limit_buy_order_usdt)) MagicMock(return_value=closed_successful_buy_order))
assert freqtrade.execute_entry(pair, stake_amount) assert freqtrade.execute_entry(pair, stake_amount)
# Should create an closed trade with an no open order id # Should create an closed trade with an no open order id
# Order is filled and trade is open # Order is filled and trade is open
@ -4363,7 +4373,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
assert trade.open_rate == 11 assert trade.open_rate == 11
assert trade.stake_amount == 110 assert trade.stake_amount == 110
# Assume it does nothing since trade is still open and no new orders # Assume it does nothing since order is closed and trade is open
freqtrade.update_closed_trades_without_assigned_fees() freqtrade.update_closed_trades_without_assigned_fees()
trade = Trade.query.first() trade = Trade.query.first()
@ -4372,22 +4382,36 @@ def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
assert trade.open_order_id is None assert trade.open_order_id is None
assert trade.open_rate == 11 assert trade.open_rate == 11
assert trade.stake_amount == 110 assert trade.stake_amount == 110
assert not trade.fee_updated('buy')
freqtrade.check_handle_timedout()
trade = Trade.query.first()
assert trade
assert trade.is_open is True
assert trade.open_order_id is None
assert trade.open_rate == 11
assert trade.stake_amount == 110
assert not trade.fee_updated('buy')
# First position adjustment buy. # First position adjustment buy.
limit_buy_order_usdt_open['ft_pair'] = pair open_dca_order_1 = {
limit_buy_order_usdt_open['ft_order_side'] = 'buy' 'ft_pair': pair,
limit_buy_order_usdt_open['side'] = 'buy' 'ft_order_side': 'buy',
limit_buy_order_usdt_open['status'] = None 'side': 'buy',
limit_buy_order_usdt_open['price'] = 9 'type': 'limit',
limit_buy_order_usdt_open['amount'] = 12 'status': None,
limit_buy_order_usdt_open['cost'] = 100 'price': 9,
limit_buy_order_usdt_open['ft_is_open'] = True 'amount': 12,
limit_buy_order_usdt_open['id'] = 651 'cost': 100,
limit_buy_order_usdt_open['order_id'] = 651 'ft_is_open': True,
'id': '651',
'order_id': '651'
}
mocker.patch('freqtrade.exchange.Exchange.create_order', mocker.patch('freqtrade.exchange.Exchange.create_order',
MagicMock(return_value=limit_buy_order_usdt_open)) MagicMock(return_value=open_dca_order_1))
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=limit_buy_order_usdt_open)) MagicMock(return_value=open_dca_order_1))
assert freqtrade.execute_entry(pair, stake_amount, trade=trade) assert freqtrade.execute_entry(pair, stake_amount, trade=trade)
orders = Order.query.all() orders = Order.query.all()
@ -4399,10 +4423,28 @@ def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
assert trade.open_rate == 11 assert trade.open_rate == 11
assert trade.amount == 10 assert trade.amount == 10
assert trade.stake_amount == 110 assert trade.stake_amount == 110
assert not trade.fee_updated('buy')
trades: List[Trade] = Trade.get_open_trades_without_assigned_fees()
assert len(trades) == 1
assert trade.is_open
assert not trade.fee_updated('buy')
order = trade.select_order('buy', False)
assert order
assert order.order_id == '650'
# Assume it does nothing since trade is still open def make_sure_its_651(*apos, **kwargs):
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=limit_buy_order_usdt_open)) if apos[0] == '650':
return closed_successful_buy_order
if apos[0] == '651':
return open_dca_order_1
return None
# Assume it does nothing since order is still open
fetch_order_mm = MagicMock(side_effect=make_sure_its_651)
mocker.patch('freqtrade.exchange.Exchange.create_order', fetch_order_mm)
mocker.patch('freqtrade.exchange.Exchange.fetch_order', fetch_order_mm)
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', fetch_order_mm)
freqtrade.update_closed_trades_without_assigned_fees() freqtrade.update_closed_trades_without_assigned_fees()
orders = Order.query.all() orders = Order.query.all()
@ -4418,27 +4460,35 @@ def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
assert trade.open_rate == 11 assert trade.open_rate == 11
assert trade.amount == 10 assert trade.amount == 10
assert trade.stake_amount == 110 assert trade.stake_amount == 110
assert trade.fee_updated('buy') is False assert not trade.fee_updated('buy')
# Make sure the closed order is found as the first order. # Make sure the closed order is found as the first order.
order = trade.select_order('buy', False) order = trade.select_order('buy', False)
assert order.order_id == '650' assert order.order_id == '650'
# Now close the order so it should update. # Now close the order so it should update.
limit_buy_order_usdt_open['ft_pair'] = pair closed_dca_order_1 = {
limit_buy_order_usdt_open['status'] = 'closed' 'ft_pair': pair,
limit_buy_order_usdt_open['ft_order_side'] = 'buy' 'ft_order_side': 'buy',
limit_buy_order_usdt_open['side'] = 'buy' 'side': 'buy',
limit_buy_order_usdt_open['price'] = 9 'type': 'limit',
limit_buy_order_usdt_open['average'] = 9 'status': 'closed',
limit_buy_order_usdt_open['amount'] = 12 'price': 9,
limit_buy_order_usdt_open['filled'] = 12 'average': 9,
limit_buy_order_usdt_open['cost'] = 108 'amount': 12,
limit_buy_order_usdt_open['ft_is_open'] = False 'filled': 12,
limit_buy_order_usdt_open['id'] = '651' 'cost': 108,
limit_buy_order_usdt_open['order_id'] = '651' 'ft_is_open': False,
'id': '651',
'order_id': '651'
}
mocker.patch('freqtrade.exchange.Exchange.create_order',
MagicMock(return_value=closed_dca_order_1))
mocker.patch('freqtrade.exchange.Exchange.fetch_order', mocker.patch('freqtrade.exchange.Exchange.fetch_order',
MagicMock(return_value=limit_buy_order_usdt_open)) MagicMock(return_value=closed_dca_order_1))
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=closed_dca_order_1))
freqtrade.check_handle_timedout() freqtrade.check_handle_timedout()
# Assert trade is as expected (averaged dca) # Assert trade is as expected (averaged dca)
@ -4461,3 +4511,42 @@ def test_position_adjust(mocker, default_conf_usdt, fee, limit_buy_order_usdt,
trades: List[Trade] = Trade.get_open_trades_without_assigned_fees() trades: List[Trade] = Trade.get_open_trades_without_assigned_fees()
assert len(trades) == 1 assert len(trades) == 1
# Add a second DCA
closed_dca_order_2 = {
'ft_pair': pair,
'status': 'closed',
'ft_order_side': 'buy',
'side': 'buy',
'type': 'limit',
'price': 7,
'average': 7,
'amount': 15,
'filled': 15,
'cost': 105,
'ft_is_open': False,
'id': '652',
'order_id': '652'
}
mocker.patch('freqtrade.exchange.Exchange.create_order',
MagicMock(return_value=closed_dca_order_2))
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
MagicMock(return_value=closed_dca_order_2))
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=closed_dca_order_2))
assert freqtrade.execute_entry(pair, stake_amount, trade=trade)
# Assert trade is as expected (averaged dca)
trade = Trade.query.first()
assert trade
assert trade.open_order_id is None
assert pytest.approx(trade.open_rate) == 8.729729729729
assert trade.amount == 37
assert trade.stake_amount == 323
orders = Order.query.all()
assert orders
assert len(orders) == 3
# Make sure the closed order is found as the second order.
order = trade.select_order('buy', False)
assert order.order_id == '652'