test: update tests for new StrategyValidator

This commit is contained in:
Matthias
2025-05-24 16:35:12 +02:00
parent b8e19ae78a
commit ee25635c79
2 changed files with 30 additions and 44 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ class StrategyResultValidator:
if dataframe is None: if dataframe is None:
message = "No dataframe returned (return statement missing?)." message = "No dataframe returned (return statement missing?)."
elif self._length != len(dataframe): elif self._length != len(dataframe):
self.message = message_template.format("length") message = message_template.format("length")
elif self._close != dataframe["close"].iloc[-1]: elif self._close != dataframe["close"].iloc[-1]:
message = message_template.format("last close price") message = message_template.format("last close price")
elif self._date != dataframe["date"].iloc[-1]: elif self._date != dataframe["date"].iloc[-1]:
+29 -43
View File
@@ -6,7 +6,7 @@ from pathlib import Path
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
from pandas import DataFrame from pandas import DataFrame, concat
from freqtrade.configuration import TimeRange from freqtrade.configuration import TimeRange
from freqtrade.constants import CUSTOM_TAG_MAX_LENGTH from freqtrade.constants import CUSTOM_TAG_MAX_LENGTH
@@ -27,6 +27,7 @@ from freqtrade.strategy.parameters import (
IntParameter, IntParameter,
RealParameter, RealParameter,
) )
from freqtrade.strategy.strategy_validation import StrategyResultValidator
from freqtrade.util import dt_now from freqtrade.util import dt_now
from tests.conftest import CURRENT_TEST_STRATEGY, TRADE_SIDES, log_has, log_has_re from tests.conftest import CURRENT_TEST_STRATEGY, TRADE_SIDES, log_has, log_has_re
@@ -124,7 +125,7 @@ def test_returns_latest_signal(ohlcv_history):
def test_analyze_pair_empty(mocker, caplog, ohlcv_history): def test_analyze_pair_empty(mocker, caplog, ohlcv_history):
mocker.patch.object(_STRATEGY.dp, "ohlcv", return_value=ohlcv_history) mocker.patch.object(_STRATEGY.dp, "ohlcv", return_value=ohlcv_history)
mocker.patch.object(_STRATEGY, "_analyze_ticker_internal", return_value=DataFrame([])) mocker.patch.object(_STRATEGY, "_analyze_ticker_internal", return_value=DataFrame([]))
mocker.patch.object(_STRATEGY, "assert_df") mocker.patch("freqtrade.strategy.interface.StrategyResultValidator.assert_df")
_STRATEGY.analyze_pair("ETH/BTC") _STRATEGY.analyze_pair("ETH/BTC")
@@ -174,7 +175,7 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history):
mocked_history.loc[1, "enter_long"] = 1 mocked_history.loc[1, "enter_long"] = 1
caplog.set_level(logging.INFO) caplog.set_level(logging.INFO)
mocker.patch.object(_STRATEGY, "assert_df") mocker.patch("freqtrade.strategy.interface.StrategyResultValidator.assert_df")
assert (None, None) == _STRATEGY.get_latest_candle( assert (None, None) == _STRATEGY.get_latest_candle(
"xyz", default_conf["timeframe"], mocked_history "xyz", default_conf["timeframe"], mocked_history
@@ -194,7 +195,9 @@ def test_get_signal_no_sell_column(default_conf, mocker, caplog, ohlcv_history):
mocked_history.loc[1, "enter_long"] = 1 mocked_history.loc[1, "enter_long"] = 1
caplog.set_level(logging.INFO) caplog.set_level(logging.INFO)
mocker.patch.object(_STRATEGY, "assert_df") mocker.patch(
"freqtrade.strategy.interface.StrategyResultValidator.assert_df",
)
assert (SignalDirection.LONG, None) == _STRATEGY.get_entry_signal( assert (SignalDirection.LONG, None) == _STRATEGY.get_entry_signal(
"xyz", default_conf["timeframe"], mocked_history "xyz", default_conf["timeframe"], mocked_history
@@ -237,7 +240,10 @@ def test_assert_df_raise(mocker, caplog, ohlcv_history):
caplog.set_level(logging.INFO) caplog.set_level(logging.INFO)
mocker.patch.object(_STRATEGY.dp, "ohlcv", return_value=ohlcv_history) mocker.patch.object(_STRATEGY.dp, "ohlcv", return_value=ohlcv_history)
mocker.patch.object(_STRATEGY.dp, "get_analyzed_dataframe", return_value=(mocked_history, 0)) mocker.patch.object(_STRATEGY.dp, "get_analyzed_dataframe", return_value=(mocked_history, 0))
mocker.patch.object(_STRATEGY, "assert_df", side_effect=StrategyError("Dataframe returned...")) mocker.patch(
"freqtrade.strategy.interface.StrategyResultValidator.assert_df",
side_effect=StrategyError("Dataframe returned..."),
)
_STRATEGY.analyze_pair("xyz") _STRATEGY.analyze_pair("xyz")
assert log_has( assert log_has(
"Unable to analyze candle (OHLCV) data for pair xyz: Dataframe returned...", caplog "Unable to analyze candle (OHLCV) data for pair xyz: Dataframe returned...", caplog
@@ -248,59 +254,39 @@ def test_assert_df(ohlcv_history, caplog):
df_len = len(ohlcv_history) - 1 df_len = len(ohlcv_history) - 1
ohlcv_history.loc[:, "enter_long"] = 0 ohlcv_history.loc[:, "enter_long"] = 0
ohlcv_history.loc[:, "exit_long"] = 0 ohlcv_history.loc[:, "exit_long"] = 0
validator = StrategyResultValidator(ohlcv_history, warn_only=False)
# Ensure it's running when passed correctly # Ensure it's running when passed correctly
_STRATEGY.assert_df( validator.assert_df(ohlcv_history)
ohlcv_history,
len(ohlcv_history),
ohlcv_history.loc[df_len, "close"],
ohlcv_history.loc[df_len, "date"],
)
with pytest.raises(StrategyError, match=r"Dataframe returned from strategy.*length\."): with pytest.raises(StrategyError, match=r"Dataframe returned from strategy.*length\."):
_STRATEGY.assert_df( validator.assert_df(concat([ohlcv_history, ohlcv_history]))
ohlcv_history,
len(ohlcv_history) + 1,
ohlcv_history.loc[df_len, "close"],
ohlcv_history.loc[df_len, "date"],
)
with pytest.raises( with pytest.raises(
StrategyError, match=r"Dataframe returned from strategy.*last close price\." StrategyError, match=r"Dataframe returned from strategy.*last close price\."
): ):
_STRATEGY.assert_df( df = ohlcv_history.copy()
ohlcv_history, df.loc[df_len, "close"] += 0.01
len(ohlcv_history), validator.assert_df(df)
ohlcv_history.loc[df_len, "close"] + 0.01,
ohlcv_history.loc[df_len, "date"],
)
with pytest.raises(StrategyError, match=r"Dataframe returned from strategy.*last date\."): with pytest.raises(StrategyError, match=r"Dataframe returned from strategy.*last date\."):
_STRATEGY.assert_df( df = ohlcv_history.copy()
ohlcv_history, df.loc[df_len, "date"] = ohlcv_history.loc[0, "date"] - timedelta(days=1)
len(ohlcv_history), validator.assert_df(df)
ohlcv_history.loc[df_len, "close"],
ohlcv_history.loc[0, "date"],
)
with pytest.raises( with pytest.raises(
StrategyError, match=r"No dataframe returned \(return statement missing\?\)." StrategyError, match=r"No dataframe returned \(return statement missing\?\)."
): ):
_STRATEGY.assert_df( validator.assert_df(None)
None,
len(ohlcv_history), validator = StrategyResultValidator(ohlcv_history, warn_only=True)
ohlcv_history.loc[df_len, "close"],
ohlcv_history.loc[0, "date"],
)
_STRATEGY.disable_dataframe_checks = True
caplog.clear() caplog.clear()
_STRATEGY.assert_df( df = ohlcv_history.copy()
ohlcv_history, df.loc[df_len, "date"] = ohlcv_history.loc[0, "date"] - timedelta(days=1)
len(ohlcv_history),
ohlcv_history.loc[2, "close"], validator.assert_df(df)
ohlcv_history.loc[0, "date"],
)
assert log_has_re(r"Dataframe returned from strategy.*last date\.", caplog) assert log_has_re(r"Dataframe returned from strategy.*last date\.", caplog)
# reset to avoid problems in other tests due to test leakage # reset to avoid problems in other tests due to test leakage
_STRATEGY.disable_dataframe_checks = False
def test_advise_all_indicators(default_conf, testdatadir) -> None: def test_advise_all_indicators(default_conf, testdatadir) -> None: