diff --git a/tests/persistence/test_trade_custom_data.py b/tests/persistence/test_trade_custom_data.py index cc86342d2..fe73f5f6b 100644 --- a/tests/persistence/test_trade_custom_data.py +++ b/tests/persistence/test_trade_custom_data.py @@ -1,8 +1,14 @@ +from copy import deepcopy +from unittest.mock import MagicMock + import pytest +from freqtrade.data.history.history_utils import get_timerange +from freqtrade.optimize.backtesting import Backtesting from freqtrade.persistence import Trade, disable_database_use, enable_database_use from freqtrade.persistence.custom_data import CustomDataWrapper -from tests.conftest import EXMS, create_mock_trades_usdt, get_patched_freqtradebot +from tests.conftest import (EXMS, create_mock_trades_usdt, generate_test_data, + get_patched_freqtradebot, patch_exchange) @pytest.mark.usefixtures("init_persistence") @@ -49,9 +55,7 @@ def test_trade_custom_data_strategy_compat(mocker, default_conf_usdt, fee): mocker.patch(f'{EXMS}.get_rate', return_value=0.50) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', return_value=None) - default_conf_usdt["minimal_roi"] = { - "0": 100 - } + default_conf_usdt["minimal_roi"] = {"0": 100} freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) create_mock_trades_usdt(fee) @@ -81,3 +85,74 @@ def test_trade_custom_data_strategy_compat(mocker, default_conf_usdt, fee): assert ff_spy.call_count == 2 assert trade_after.exit_reason == 'test_value_1' + + +def test_trade_custom_data_strategy_backtest_compat(mocker, default_conf_usdt, fee): + + mocker.patch(f'{EXMS}.get_fee', fee) + mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=10) + mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf')) + mocker.patch(f"{EXMS}.get_max_leverage", return_value=10) + mocker.patch(f"{EXMS}.get_maintenance_ratio_and_amt", return_value=(0.1, 0.1)) + mocker.patch('freqtrade.optimize.backtesting.Backtesting._run_funding_fees') + + patch_exchange(mocker) + default_conf_usdt.update({ + "stake_amount": 100.0, + "max_open_trades": 2, + "dry_run_wallet": 1000.0, + "strategy": "StrategyTestV3", + "trading_mode": "futures", + "margin_mode": "isolated", + "stoploss": -2, + "minimal_roi": {"0": 100}, + }) + default_conf_usdt['pairlists'] = [{'method': 'StaticPairList', 'allow_inactive': True}] + backtesting = Backtesting(default_conf_usdt) + + df = generate_test_data(default_conf_usdt['timeframe'], 100, '2022-01-01 00:00:00+00:00') + + pair_exp = 'XRP/USDT:USDT' + + def custom_exit(pair, trade, **kwargs): + custom_val = trade.get_custom_data('test_str') + custom_val_i = trade.get_custom_data('test_int', 0) + + if pair == pair_exp: + trade.set_custom_data('test_str', 'test_value') + trade.set_custom_data('test_int', custom_val_i + 1) + + if custom_val_i >= 2: + return f"{custom_val}_{custom_val_i}" + + backtesting._set_strategy(backtesting.strategylist[0]) + processed = backtesting.strategy.advise_all_indicators({ + pair_exp: df, + 'BTC/USDT:USDT': df, + }) + + def fun(dataframe, *args, **kwargs): + dataframe.loc[dataframe.index == 50, 'enter_long'] = 1 + return dataframe + + backtesting.strategy.advise_entry = fun + backtesting.strategy.leverage = MagicMock(return_value=1) + backtesting.strategy.custom_exit = custom_exit + ff_spy = mocker.spy(backtesting.strategy, 'custom_exit') + + min_date, max_date = get_timerange(processed) + + result = backtesting.backtest( + processed=deepcopy(processed), + start_date=min_date, + end_date=max_date, + ) + results = result['results'] + assert not results.empty + assert len(results) == 2 + assert results['pair'][0] == pair_exp + assert results['pair'][1] == 'BTC/USDT:USDT' + assert results['exit_reason'][0] == 'test_value_2' + assert results['exit_reason'][1] == 'exit_signal' + + assert ff_spy.call_count == 7