From 316812f427be3ca2cb14f69aeacac00d52071327 Mon Sep 17 00:00:00 2001 From: Robert Caulk Date: Tue, 2 Jan 2024 12:44:19 +0100 Subject: [PATCH 1/5] Help direct people to freqai support --- docs/freqai.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/freqai.md b/docs/freqai.md index 820fb81f6..5546eaea7 100644 --- a/docs/freqai.md +++ b/docs/freqai.md @@ -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) - [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 FreqAI is developed by a group of individuals who all contribute specific skillsets to the project. From a9380f0d5374eff6871b370502f29bb020965576 Mon Sep 17 00:00:00 2001 From: Robert Caulk Date: Tue, 2 Jan 2024 12:46:33 +0100 Subject: [PATCH 2/5] Update freqai.md --- docs/freqai.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/freqai.md b/docs/freqai.md index 5546eaea7..a81c9a81b 100644 --- a/docs/freqai.md +++ b/docs/freqai.md @@ -117,7 +117,7 @@ Here we compile some external materials that provide deeper looks into various c ## 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]. +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 From ce63eb30a26ae2a1439fdf674be7dd7cb2db7993 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Jan 2024 16:26:43 +0100 Subject: [PATCH 3/5] Remove unused test param --- tests/test_integration.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_integration.py b/tests/test_integration.py index 3dcd91af0..2e7f38fc8 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -11,8 +11,7 @@ from freqtrade.rpc.rpc import RPC 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, - limit_buy_order, mocker) -> None: +def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, mocker) -> None: """ Tests workflow of selling stoploss_on_exchange. Sells From f3da2c6fd8dbf5038a56a25db104d8cbebf01d71 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Jan 2024 16:55:33 +0100 Subject: [PATCH 4/5] Simplify and fix handle_stoploss_on_exchange test --- tests/test_freqtradebot.py | 42 ++++++++------------------------------ 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index f38504ed6..aaabfc414 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -1160,9 +1160,9 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ freqtrade.enter_positions() trade = Trade.session.scalars(select(Trade)).first() - trade.is_short = is_short - trade.is_open = True - trade.stoploss_order_id = None + assert trade.is_short == is_short + assert trade.is_open + assert trade.stoploss_order_id is None assert freqtrade.handle_stoploss_on_exchange(trade) is False assert stoploss.call_count == 1 @@ -1170,34 +1170,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 # should do nothing and return false - stop_order_dict.update({'id': "102"}) 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) 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 # should set a stoploss immediately and return False caplog.clear() 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) stoploss.reset_mock() amount_before = trade.amount @@ -1213,25 +1200,14 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ # should unset stoploss_order_id and return true # as a trade actually happened caplog.clear() - freqtrade.enter_positions() - stop_order_dict.update({'id': "104"}) + stop_order_dict.update({'id': "103_1"}) trade = Trade.session.scalars(select(Trade)).first() trade.is_short = is_short 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={ - 'id': "104", + 'id': "103_1", 'status': 'closed', 'type': 'stop_loss_limit', 'price': 3, From 7a6888dfd3bb29ef23f650d4fcce9d4235918bf5 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 2 Jan 2024 16:58:58 +0100 Subject: [PATCH 5/5] Split stoploss test into 2 for easier testing --- tests/test_freqtradebot.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index aaabfc414..1c0499b3d 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -1249,7 +1249,40 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ assert freqtrade.handle_stoploss_on_exchange(trade) is False 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 stoploss_order_cancelled = MagicMock(side_effect=[{ 'id': "107", @@ -1263,7 +1296,6 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ 'info': {'stopPrice': 22}, }]) trade.stoploss_order_id = "107" - trade.is_open = True trade.stoploss_last_update = dt_now() - timedelta(hours=1) trade.stop_loss = 24 trade.exit_reason = None