Merge remote-tracking branch 'origin/develop' into pr/Axel-CH/9267

This commit is contained in:
Matthias
2024-01-02 17:04:07 +01:00
3 changed files with 49 additions and 37 deletions
+5
View File
@@ -114,6 +114,11 @@ Here we compile some external materials that provide deeper looks into various c
- [Real-time head-to-head: Adaptive modeling of financial market data using XGBoost and CatBoost](https://emergentmethods.medium.com/real-time-head-to-head-adaptive-modeling-of-financial-market-data-using-xgboost-and-catboost-995a115a7495) - [Real-time head-to-head: Adaptive modeling of financial market data using XGBoost and CatBoost](https://emergentmethods.medium.com/real-time-head-to-head-adaptive-modeling-of-financial-market-data-using-xgboost-and-catboost-995a115a7495)
- [FreqAI - from price to prediction](https://emergentmethods.medium.com/freqai-from-price-to-prediction-6fadac18b665) - [FreqAI - from price to prediction](https://emergentmethods.medium.com/freqai-from-price-to-prediction-6fadac18b665)
## Support
You can find support for FreqAI in a variety of places, including the [Freqtrade discord](https://discord.gg/Jd8JYeWHc4), the dedicated [FreqAI discord](https://discord.gg/7AMWACmbjT), and in [github issues](https://github.com/freqtrade/freqtrade/issues).
## Credits ## Credits
FreqAI is developed by a group of individuals who all contribute specific skillsets to the project. FreqAI is developed by a group of individuals who all contribute specific skillsets to the project.
+43 -35
View File
@@ -1159,9 +1159,9 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.session.scalars(select(Trade)).first() trade = Trade.session.scalars(select(Trade)).first()
trade.is_short = is_short assert trade.is_short == is_short
trade.is_open = True assert trade.is_open
trade.stoploss_order_id = None assert trade.stoploss_order_id is None
assert freqtrade.handle_stoploss_on_exchange(trade) is False assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert stoploss.call_count == 1 assert stoploss.call_count == 1
@@ -1169,34 +1169,21 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
# Second case: when stoploss is set but it is not yet hit # Second case: when stoploss is set but it is not yet hit
# should do nothing and return false # should do nothing and return false
stop_order_dict.update({'id': "102"})
trade.is_open = True trade.is_open = True
trade.stoploss_order_id = "102"
trade.orders.append(
Order(
ft_order_side='stoploss',
ft_pair=trade.pair,
ft_is_open=True,
ft_amount=trade.amount,
ft_price=trade.stop_loss,
order_id='102',
status='open',
)
)
hanging_stoploss_order = MagicMock(return_value={'status': 'open'}) hanging_stoploss_order = MagicMock(return_value={'id': '13434334', 'status': 'open'})
mocker.patch(f'{EXMS}.fetch_stoploss_order', hanging_stoploss_order) mocker.patch(f'{EXMS}.fetch_stoploss_order', hanging_stoploss_order)
assert freqtrade.handle_stoploss_on_exchange(trade) is False assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert trade.stoploss_order_id == "102" hanging_stoploss_order.assert_called_once_with('13434334', trade.pair)
assert trade.stoploss_order_id == "13434334"
# Third case: when stoploss was set but it was canceled for some reason # Third case: when stoploss was set but it was canceled for some reason
# should set a stoploss immediately and return False # should set a stoploss immediately and return False
caplog.clear() caplog.clear()
trade.is_open = True trade.is_open = True
trade.stoploss_order_id = "102"
canceled_stoploss_order = MagicMock(return_value={'id': '103_1', 'status': 'canceled'}) canceled_stoploss_order = MagicMock(return_value={'id': '13434334', 'status': 'canceled'})
mocker.patch(f'{EXMS}.fetch_stoploss_order', canceled_stoploss_order) mocker.patch(f'{EXMS}.fetch_stoploss_order', canceled_stoploss_order)
stoploss.reset_mock() stoploss.reset_mock()
amount_before = trade.amount amount_before = trade.amount
@@ -1212,25 +1199,14 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
# should unset stoploss_order_id and return true # should unset stoploss_order_id and return true
# as a trade actually happened # as a trade actually happened
caplog.clear() caplog.clear()
freqtrade.enter_positions() stop_order_dict.update({'id': "103_1"})
stop_order_dict.update({'id': "104"})
trade = Trade.session.scalars(select(Trade)).first() trade = Trade.session.scalars(select(Trade)).first()
trade.is_short = is_short trade.is_short = is_short
trade.is_open = True trade.is_open = True
trade.stoploss_order_id = "104"
trade.orders.append(Order(
ft_order_side='stoploss',
order_id='104',
ft_pair=trade.pair,
ft_is_open=True,
ft_amount=trade.amount,
ft_price=0.0,
))
assert trade
stoploss_order_hit = MagicMock(return_value={ stoploss_order_hit = MagicMock(return_value={
'id': "104", 'id': "103_1",
'status': 'closed', 'status': 'closed',
'type': 'stop_loss_limit', 'type': 'stop_loss_limit',
'price': 3, 'price': 3,
@@ -1272,7 +1248,40 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
assert freqtrade.handle_stoploss_on_exchange(trade) is False assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert stoploss.call_count == 0 assert stoploss.call_count == 0
# Seventh case: emergency exit triggered
@pytest.mark.parametrize("is_short", [False, True])
def test_handle_stoploss_on_exchange_emergency(mocker, default_conf_usdt, fee, is_short,
limit_order) -> None:
stop_order_dict = {'id': "13434334"}
stoploss = MagicMock(return_value=stop_order_dict)
enter_order = limit_order[entry_side(is_short)]
exit_order = limit_order[exit_side(is_short)]
patch_RPCManager(mocker)
patch_exchange(mocker)
mocker.patch.multiple(
EXMS,
fetch_ticker=MagicMock(return_value={
'bid': 1.9,
'ask': 2.2,
'last': 1.9
}),
create_order=MagicMock(side_effect=[
enter_order,
exit_order,
]),
get_fee=fee,
create_stoploss=stoploss
)
freqtrade = FreqtradeBot(default_conf_usdt)
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
freqtrade.enter_positions()
trade = Trade.session.scalars(select(Trade)).first()
assert trade.is_short == is_short
assert trade.is_open
assert trade.stoploss_order_id is None
# emergency exit triggered
# Trailing stop should not act anymore # Trailing stop should not act anymore
stoploss_order_cancelled = MagicMock(side_effect=[{ stoploss_order_cancelled = MagicMock(side_effect=[{
'id': "107", 'id': "107",
@@ -1286,7 +1295,6 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
'info': {'stopPrice': 22}, 'info': {'stopPrice': 22},
}]) }])
trade.stoploss_order_id = "107" trade.stoploss_order_id = "107"
trade.is_open = True
trade.stoploss_last_update = dt_now() - timedelta(hours=1) trade.stoploss_last_update = dt_now() - timedelta(hours=1)
trade.stop_loss = 24 trade.stop_loss = 24
trade.exit_reason = None trade.exit_reason = None
+1 -2
View File
@@ -11,8 +11,7 @@ from freqtrade.rpc.rpc import RPC
from tests.conftest import EXMS, get_patched_freqtradebot, log_has_re, patch_get_signal from tests.conftest import EXMS, get_patched_freqtradebot, log_has_re, patch_get_signal
def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, mocker) -> None:
limit_buy_order, mocker) -> None:
""" """
Tests workflow of selling stoploss_on_exchange. Tests workflow of selling stoploss_on_exchange.
Sells Sells