freqtrade_origin/tests/data/test_entryexitanalysis.py

483 lines
15 KiB
Python
Raw Normal View History

import logging
2022-05-24 19:27:15 +00:00
from unittest.mock import MagicMock, PropertyMock
import pandas as pd
import pytest
2022-05-24 19:27:15 +00:00
from freqtrade.commands.analyze_commands import start_analysis_entries_exits
from freqtrade.commands.optimize_commands import start_backtesting
from freqtrade.enums import ExitType
from freqtrade.optimize.backtesting import Backtesting
2022-05-24 19:27:15 +00:00
from tests.conftest import get_args, patch_exchange, patched_configuration_load_config_file
@pytest.fixture(autouse=True)
def entryexitanalysis_cleanup() -> None:
yield None
Backtesting.cleanup()
def test_backtest_analysis_on_entry_and_rejected_signals_nomock(
default_conf, mocker, caplog, testdatadir, user_dir, capsys
):
caplog.set_level(logging.INFO)
2024-05-12 14:00:45 +00:00
(user_dir / "backtest_results").mkdir(parents=True, exist_ok=True)
default_conf.update(
{
"use_exit_signal": True,
"exit_profit_only": False,
"exit_profit_offset": 0.0,
"ignore_roi_if_entry_signal": False,
}
)
2022-05-24 19:27:15 +00:00
patch_exchange(mocker)
2024-05-12 14:00:45 +00:00
result1 = pd.DataFrame(
2022-05-24 19:27:15 +00:00
{
2024-05-12 14:00:45 +00:00
"pair": ["ETH/BTC", "LTC/BTC", "ETH/BTC", "LTC/BTC"],
"profit_ratio": [0.025, 0.05, -0.1, -0.05],
"profit_abs": [0.5, 2.0, -4.0, -2.0],
"open_date": pd.to_datetime(
[
"2018-01-29 18:40:00",
"2018-01-30 03:30:00",
"2018-01-30 08:10:00",
"2018-01-31 13:30:00",
],
utc=True,
),
"close_date": pd.to_datetime(
[
"2018-01-29 20:45:00",
"2018-01-30 05:35:00",
"2018-01-30 09:10:00",
"2018-01-31 15:00:00",
],
utc=True,
),
"trade_duration": [235, 40, 60, 90],
"is_open": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01],
"open_rate": [0.104445, 0.10302485, 0.10302485, 0.10302485],
"close_rate": [0.104969, 0.103541, 0.102041, 0.102541],
"is_short": [False, False, False, False],
"enter_tag": [
"enter_tag_long_a",
"enter_tag_long_b",
"enter_tag_long_a",
"enter_tag_long_b",
],
"exit_reason": [
ExitType.ROI.value,
ExitType.EXIT_SIGNAL.value,
ExitType.STOP_LOSS.value,
ExitType.TRAILING_STOP_LOSS.value,
2024-05-12 14:00:45 +00:00
],
2022-05-24 19:27:15 +00:00
}
2024-05-12 14:00:45 +00:00
)
backtestmock = MagicMock(
side_effect=[
{
"results": result1,
"config": default_conf,
"locks": [],
"rejected_signals": 20,
"timedout_entry_orders": 0,
"timedout_exit_orders": 0,
"canceled_trade_entries": 0,
"canceled_entry_orders": 0,
"replaced_entry_orders": 0,
"final_balance": 1000,
}
]
)
mocker.patch(
"freqtrade.plugins.pairlistmanager.PairListManager.whitelist",
PropertyMock(return_value=["ETH/BTC", "LTC/BTC", "DASH/BTC"]),
)
mocker.patch("freqtrade.optimize.backtesting.Backtesting.backtest", backtestmock)
2022-05-24 19:27:15 +00:00
patched_configuration_load_config_file(mocker, default_conf)
args = [
2024-05-12 14:00:45 +00:00
"backtesting",
"--config",
"config.json",
"--datadir",
str(testdatadir),
"--user-data-dir",
str(user_dir),
"--timeframe",
"5m",
"--timerange",
"1515560100-1517287800",
"--export",
"signals",
"--cache",
"none",
2022-05-24 19:27:15 +00:00
]
args = get_args(args)
start_backtesting(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "BACKTESTING REPORT" in captured.out
assert "EXIT REASON STATS" in captured.out
assert "LEFT OPEN TRADES REPORT" in captured.out
2022-05-24 19:27:15 +00:00
base_args = [
2024-05-12 14:00:45 +00:00
"backtesting-analysis",
"--config",
"config.json",
"--datadir",
str(testdatadir),
"--user-data-dir",
str(user_dir),
2022-05-24 19:27:15 +00:00
]
# test group 0 and indicator list
2024-05-12 14:00:45 +00:00
args = get_args(
base_args + ["--analysis-groups", "0", "--indicator-list", "close", "rsi", "profit_abs"]
)
start_analysis_entries_exits(args)
2022-05-24 19:27:15 +00:00
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "LTC/BTC" in captured.out
assert "ETH/BTC" in captured.out
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
assert "0.5" in captured.out
assert "-4" in captured.out
assert "-2" in captured.out
assert "-3.5" in captured.out
assert "50" in captured.out
assert "0" in captured.out
assert "0.016" in captured.out
2024-05-12 14:00:45 +00:00
assert "34.049" in captured.out
assert "0.104" in captured.out
assert "52.829" in captured.out
# test group 1
2024-05-12 14:00:45 +00:00
args = get_args(base_args + ["--analysis-groups", "1"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "total_profit_pct" in captured.out
assert "-3.5" in captured.out
assert "-1.75" in captured.out
assert "-7.5" in captured.out
assert "-3.75" in captured.out
assert "0" in captured.out
# test group 2
2024-05-12 14:00:45 +00:00
args = get_args(base_args + ["--analysis-groups", "2"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
assert "total_profit_pct" in captured.out
assert "-10" in captured.out
assert "-5" in captured.out
assert "2.5" in captured.out
# test group 3
2024-05-12 14:00:45 +00:00
args = get_args(base_args + ["--analysis-groups", "3"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "LTC/BTC" in captured.out
assert "ETH/BTC" in captured.out
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "total_profit_pct" in captured.out
assert "-7.5" in captured.out
assert "-3.75" in captured.out
assert "-1.75" in captured.out
assert "0" in captured.out
assert "2" in captured.out
# test group 4
2024-05-12 14:00:45 +00:00
args = get_args(base_args + ["--analysis-groups", "4"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "LTC/BTC" in captured.out
assert "ETH/BTC" in captured.out
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
assert "total_profit_pct" in captured.out
assert "-10" in captured.out
assert "-5" in captured.out
assert "-4" in captured.out
assert "0.5" in captured.out
assert "1" in captured.out
assert "2.5" in captured.out
# test group 5
2024-05-12 14:00:45 +00:00
args = get_args(base_args + ["--analysis-groups", "5"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
# test date filtering
2024-05-12 14:00:45 +00:00
args = get_args(
base_args + ["--analysis-groups", "0", "1", "2", "--timerange", "20180129-20180130"]
)
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" not in captured.out
# Due to the backtest mock, there's no rejected signals generated.
2024-05-12 14:00:45 +00:00
args = get_args(base_args + ["--rejected-signals"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
2024-05-12 14:00:45 +00:00
assert "no rejected signals" in captured.out
2024-08-02 15:16:19 +00:00
def test_backtest_analysis_on_exit_signals_nomock(
default_conf, mocker, caplog, testdatadir, user_dir, capsys
):
caplog.set_level(logging.INFO)
(user_dir / "backtest_results").mkdir(parents=True, exist_ok=True)
default_conf.update(
{
"use_exit_signal": True,
"exit_profit_only": False,
"exit_profit_offset": 0.0,
"ignore_roi_if_entry_signal": False,
}
)
patch_exchange(mocker)
result1 = pd.DataFrame(
{
"pair": ["ETH/BTC", "LTC/BTC", "ETH/BTC", "LTC/BTC"],
"profit_ratio": [0.025, 0.05, -0.1, -0.05],
"profit_abs": [0.5, 2.0, -4.0, -2.0],
"open_date": pd.to_datetime(
[
"2018-01-29 18:40:00",
"2018-01-30 03:30:00",
"2018-01-30 08:10:00",
"2018-01-31 13:30:00",
],
utc=True,
),
"close_date": pd.to_datetime(
[
"2018-01-30 20:45:00",
2024-08-02 15:16:19 +00:00
"2018-01-30 05:35:00",
"2018-01-30 09:10:00",
"2018-01-31 15:00:00",
],
utc=True,
),
"trade_duration": [235, 40, 60, 90],
"is_open": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01],
"open_rate": [0.104445, 0.10302485, 0.10302485, 0.10302485],
"close_rate": [0.104969, 0.103541, 0.102041, 0.102541],
"is_short": [False, False, False, False],
"enter_tag": [
"enter_tag_long_a",
"enter_tag_long_b",
"enter_tag_long_a",
"enter_tag_long_b",
],
"exit_reason": [
ExitType.ROI.value,
ExitType.EXIT_SIGNAL.value,
ExitType.STOP_LOSS.value,
ExitType.TRAILING_STOP_LOSS.value,
],
}
)
backtestmock = MagicMock(
side_effect=[
{
"results": result1,
"config": default_conf,
"locks": [],
"rejected_signals": 20,
"timedout_entry_orders": 0,
"timedout_exit_orders": 0,
"canceled_trade_entries": 0,
"canceled_entry_orders": 0,
"replaced_entry_orders": 0,
"final_balance": 1000,
}
]
)
mocker.patch(
"freqtrade.plugins.pairlistmanager.PairListManager.whitelist",
PropertyMock(return_value=["ETH/BTC", "LTC/BTC", "DASH/BTC"]),
)
mocker.patch("freqtrade.optimize.backtesting.Backtesting.backtest", backtestmock)
patched_configuration_load_config_file(mocker, default_conf)
args = [
"backtesting",
"--config",
"config.json",
"--datadir",
str(testdatadir),
"--user-data-dir",
str(user_dir),
"--timeframe",
"5m",
"--timerange",
"1515560100-1517287800",
"--export",
"signals",
"--cache",
"none",
]
args = get_args(args)
start_backtesting(args)
captured = capsys.readouterr()
assert "BACKTESTING REPORT" in captured.out
assert "EXIT REASON STATS" in captured.out
assert "LEFT OPEN TRADES REPORT" in captured.out
base_args = [
"backtesting-analysis",
"--config",
"config.json",
"--datadir",
str(testdatadir),
"--user-data-dir",
str(user_dir),
]
# test group 0 and indicator list
args = get_args(
base_args
+ [
"--analysis-groups",
"0",
"--exit-signals",
"--indicator-list",
"close",
"rsi",
"profit_abs",
]
)
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "LTC/BTC" in captured.out
assert "ETH/BTC" in captured.out
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
assert "0.5" in captured.out
assert "-4" in captured.out
assert "-2" in captured.out
assert "57.654" in captured.out
assert "-8" in captured.out
2024-08-02 15:16:19 +00:00
assert "0" in captured.out
assert "0.104" in captured.out
assert "0.016" in captured.out
assert "52.829" in captured.out
# test group 1
args = get_args(base_args + ["--analysis-groups", "1"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "total_profit_pct" in captured.out
assert "-3.5" in captured.out
assert "-1.75" in captured.out
assert "-7.5" in captured.out
assert "-3.75" in captured.out
assert "0" in captured.out
# test group 2
args = get_args(base_args + ["--analysis-groups", "2"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
assert "total_profit_pct" in captured.out
assert "-10" in captured.out
assert "-5" in captured.out
assert "2.5" in captured.out
# test group 3
args = get_args(base_args + ["--analysis-groups", "3"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "LTC/BTC" in captured.out
assert "ETH/BTC" in captured.out
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "total_profit_pct" in captured.out
assert "-7.5" in captured.out
assert "-3.75" in captured.out
assert "-1.75" in captured.out
assert "0" in captured.out
assert "2" in captured.out
# test group 4
args = get_args(base_args + ["--analysis-groups", "4"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "LTC/BTC" in captured.out
assert "ETH/BTC" in captured.out
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" in captured.out
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
assert "total_profit_pct" in captured.out
assert "-10" in captured.out
assert "-5" in captured.out
assert "-4" in captured.out
assert "0.5" in captured.out
assert "1" in captured.out
assert "2.5" in captured.out
# test group 5
args = get_args(base_args + ["--analysis-groups", "5"])
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "exit_signal" in captured.out
assert "roi" in captured.out
assert "stop_loss" in captured.out
assert "trailing_stop_loss" in captured.out
# test date filtering
args = get_args(
base_args + ["--analysis-groups", "0", "1", "2", "--timerange", "20180129-20180130"]
)
start_analysis_entries_exits(args)
captured = capsys.readouterr()
assert "enter_tag_long_a" in captured.out
assert "enter_tag_long_b" not in captured.out