mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-12-02 18:13:04 +00:00
Merge in develop changes
This commit is contained in:
@@ -97,7 +97,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
||||
'order_date': ANY, 'order_timestamp': ANY, 'order_filled_date': ANY,
|
||||
'order_filled_timestamp': ANY, 'order_type': 'limit', 'price': 1.098e-05,
|
||||
'is_open': False, 'pair': 'ETH/BTC', 'order_id': ANY,
|
||||
'remaining': ANY, 'status': ANY, 'ft_is_entry': True,
|
||||
'remaining': ANY, 'status': ANY, 'ft_is_entry': True, 'ft_fee_base': None,
|
||||
}],
|
||||
}
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
@@ -261,8 +261,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
|
||||
assert isnan(fiat_profit_sum)
|
||||
|
||||
|
||||
def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
|
||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
||||
def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee, markets, mocker) -> None:
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
EXMS,
|
||||
@@ -295,7 +294,7 @@ def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
|
||||
assert day['starting_balance'] in (pytest.approx(1062.37), pytest.approx(1066.46))
|
||||
assert day['fiat_value'] in (0.0, )
|
||||
# ensure first day is current date
|
||||
assert str(days['data'][0]['date']) == str(datetime.utcnow().date())
|
||||
assert str(days['data'][0]['date']) == str(datetime.now(timezone.utc).date())
|
||||
|
||||
# Try invalid data
|
||||
with pytest.raises(RPCException, match=r'.*must be an integer greater than 0*'):
|
||||
@@ -418,8 +417,8 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
|
||||
assert pytest.approx(stats['winrate']) == 66.666666667
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_date'] == '2 days ago'
|
||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
||||
assert stats['first_trade_humanized'] == '2 days ago'
|
||||
assert stats['latest_trade_humanized'] == '17 minutes ago'
|
||||
assert stats['avg_duration'] in ('0:17:40')
|
||||
assert stats['best_pair'] == 'XRP/USDT'
|
||||
assert stats['best_rate'] == 10.0
|
||||
@@ -431,8 +430,8 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
MagicMock(side_effect=ExchangeError("Pair 'XRP/USDT' not available")))
|
||||
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
|
||||
assert stats['trade_count'] == 7
|
||||
assert stats['first_trade_date'] == '2 days ago'
|
||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
||||
assert stats['first_trade_humanized'] == '2 days ago'
|
||||
assert stats['latest_trade_humanized'] == '17 minutes ago'
|
||||
assert stats['avg_duration'] in ('0:17:40')
|
||||
assert stats['best_pair'] == 'XRP/USDT'
|
||||
assert stats['best_rate'] == 10.0
|
||||
@@ -551,51 +550,67 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
|
||||
'free': 10.0,
|
||||
'balance': 12.0,
|
||||
'used': 2.0,
|
||||
'bot_owned': 9.9, # available stake - reducing by reserved amount
|
||||
'est_stake': 10.0, # In futures mode, "free" is used here.
|
||||
'est_stake_bot': 9.9,
|
||||
'stake': 'BTC',
|
||||
'is_position': False,
|
||||
'leverage': 1.0,
|
||||
'position': 0.0,
|
||||
'side': 'long',
|
||||
'is_bot_managed': True,
|
||||
},
|
||||
{
|
||||
'free': 1.0,
|
||||
'balance': 5.0,
|
||||
'currency': 'ETH',
|
||||
'bot_owned': 0,
|
||||
'est_stake': 0.30794,
|
||||
'est_stake_bot': 0,
|
||||
'used': 4.0,
|
||||
'stake': 'BTC',
|
||||
'is_position': False,
|
||||
'leverage': 1.0,
|
||||
'position': 0.0,
|
||||
'side': 'long',
|
||||
|
||||
'is_bot_managed': False,
|
||||
},
|
||||
{
|
||||
'free': 5.0,
|
||||
'balance': 10.0,
|
||||
'currency': 'USDT',
|
||||
'bot_owned': 0,
|
||||
'est_stake': 0.0011562404610161968,
|
||||
'est_stake_bot': 0,
|
||||
'used': 5.0,
|
||||
'stake': 'BTC',
|
||||
'is_position': False,
|
||||
'leverage': 1.0,
|
||||
'position': 0.0,
|
||||
'side': 'long',
|
||||
'is_bot_managed': False,
|
||||
},
|
||||
{
|
||||
'free': 0.0,
|
||||
'balance': 0.0,
|
||||
'currency': 'ETH/USDT:USDT',
|
||||
'est_stake': 20,
|
||||
'est_stake_bot': 20,
|
||||
'used': 0,
|
||||
'stake': 'BTC',
|
||||
'is_position': True,
|
||||
'leverage': 5.0,
|
||||
'position': 1000.0,
|
||||
'side': 'short',
|
||||
'is_bot_managed': True,
|
||||
}
|
||||
]
|
||||
assert pytest.approx(result['total_bot']) == 29.9
|
||||
assert pytest.approx(result['total']) == 30.309096
|
||||
assert result['starting_capital'] == 10
|
||||
# Very high starting capital ratio, because the futures position really has the wrong unit.
|
||||
# TODO: improve this test (see comment above)
|
||||
assert result['starting_capital_ratio'] == pytest.approx(1.98999999)
|
||||
|
||||
|
||||
def test_rpc_start(mocker, default_conf) -> None:
|
||||
@@ -693,15 +708,15 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
|
||||
rpc._rpc_force_exit(None)
|
||||
|
||||
msg = rpc._rpc_force_exit('all')
|
||||
assert msg == {'result': 'Created sell orders for all open trades.'}
|
||||
assert msg == {'result': 'Created exit orders for all open trades.'}
|
||||
|
||||
freqtradebot.enter_positions()
|
||||
msg = rpc._rpc_force_exit('all')
|
||||
assert msg == {'result': 'Created sell orders for all open trades.'}
|
||||
assert msg == {'result': 'Created exit orders for all open trades.'}
|
||||
|
||||
freqtradebot.enter_positions()
|
||||
msg = rpc._rpc_force_exit('2')
|
||||
assert msg == {'result': 'Created sell order for trade 2.'}
|
||||
assert msg == {'result': 'Created exit order for trade 2.'}
|
||||
|
||||
freqtradebot.state = State.STOPPED
|
||||
with pytest.raises(RPCException, match=r'.*trader is not running*'):
|
||||
@@ -751,27 +766,11 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
|
||||
|
||||
freqtradebot.config['max_open_trades'] = 3
|
||||
freqtradebot.enter_positions()
|
||||
trade = Trade.session.scalars(select(Trade).filter(Trade.id == '2')).first()
|
||||
amount = trade.amount
|
||||
# make an limit-buy open trade, if there is no 'filled', don't sell it
|
||||
mocker.patch(
|
||||
f'{EXMS}.fetch_order',
|
||||
return_value={
|
||||
'status': 'open',
|
||||
'type': 'limit',
|
||||
'side': 'buy',
|
||||
'filled': None
|
||||
}
|
||||
)
|
||||
# check that the trade is called, which is done by ensuring exchange.cancel_order is called
|
||||
msg = rpc._rpc_force_exit('4')
|
||||
assert msg == {'result': 'Created sell order for trade 4.'}
|
||||
assert cancel_order_mock.call_count == 2
|
||||
assert trade.amount == amount
|
||||
|
||||
cancel_order_mock.reset_mock()
|
||||
trade = Trade.session.scalars(select(Trade).filter(Trade.id == '3')).first()
|
||||
|
||||
# make an limit-sell open trade
|
||||
amount = trade.amount
|
||||
# make an limit-sell open order trade
|
||||
mocker.patch(
|
||||
f'{EXMS}.fetch_order',
|
||||
return_value={
|
||||
@@ -784,10 +783,54 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
|
||||
'id': trade.orders[0].order_id,
|
||||
}
|
||||
)
|
||||
cancel_order_3 = mocker.patch(
|
||||
f'{EXMS}.cancel_order_with_result',
|
||||
return_value={
|
||||
'status': 'canceled',
|
||||
'type': 'limit',
|
||||
'side': 'sell',
|
||||
'amount': amount,
|
||||
'remaining': amount,
|
||||
'filled': 0.0,
|
||||
'id': trade.orders[0].order_id,
|
||||
}
|
||||
)
|
||||
msg = rpc._rpc_force_exit('3')
|
||||
assert msg == {'result': 'Created sell order for trade 3.'}
|
||||
assert msg == {'result': 'Created exit order for trade 3.'}
|
||||
# status quo, no exchange calls
|
||||
assert cancel_order_mock.call_count == 3
|
||||
assert cancel_order_3.call_count == 1
|
||||
assert cancel_order_mock.call_count == 0
|
||||
|
||||
trade = Trade.session.scalars(select(Trade).filter(Trade.id == '2')).first()
|
||||
amount = trade.amount
|
||||
# make an limit-buy open trade, if there is no 'filled', don't sell it
|
||||
mocker.patch(
|
||||
f'{EXMS}.fetch_order',
|
||||
return_value={
|
||||
'status': 'open',
|
||||
'type': 'limit',
|
||||
'side': 'buy',
|
||||
'filled': None
|
||||
}
|
||||
)
|
||||
cancel_order_4 = mocker.patch(
|
||||
f'{EXMS}.cancel_order_with_result',
|
||||
return_value={
|
||||
'status': 'canceled',
|
||||
'type': 'limit',
|
||||
'side': 'sell',
|
||||
'amount': amount,
|
||||
'remaining': 0.0,
|
||||
'filled': amount,
|
||||
'id': trade.orders[0].order_id,
|
||||
}
|
||||
)
|
||||
# check that the trade is called, which is done by ensuring exchange.cancel_order is called
|
||||
msg = rpc._rpc_force_exit('4')
|
||||
assert msg == {'result': 'Created exit order for trade 4.'}
|
||||
assert cancel_order_4.call_count == 1
|
||||
assert cancel_order_mock.call_count == 0
|
||||
assert trade.amount == amount
|
||||
|
||||
|
||||
def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None:
|
||||
|
||||
Reference in New Issue
Block a user