mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-04-29 05:20:10 +00:00
refactor: move dataframe assertion to it's own class
This commit is contained in:
@@ -38,6 +38,7 @@ from freqtrade.strategy.informative_decorator import (
|
||||
_create_and_merge_informative_pair,
|
||||
_format_pair_name,
|
||||
)
|
||||
from freqtrade.strategy.strategy_validation import StrategyResultValidator
|
||||
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
||||
from freqtrade.util import dt_now
|
||||
from freqtrade.wallets import Wallets
|
||||
@@ -1213,13 +1214,13 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
return
|
||||
|
||||
try:
|
||||
df_len, df_close, df_date = self.preserve_df(dataframe)
|
||||
validator = StrategyResultValidator(dataframe, self.disable_dataframe_checks)
|
||||
|
||||
dataframe = strategy_safe_wrapper(self._analyze_ticker_internal, message="")(
|
||||
dataframe, {"pair": pair}
|
||||
)
|
||||
|
||||
self.assert_df(dataframe, df_len, df_close, df_date)
|
||||
validator.assert_df(dataframe)
|
||||
except StrategyError as error:
|
||||
logger.warning(f"Unable to analyze candle (OHLCV) data for pair {pair}: {error}")
|
||||
return
|
||||
@@ -1236,31 +1237,6 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
for pair in pairs:
|
||||
self.analyze_pair(pair)
|
||||
|
||||
@staticmethod
|
||||
def preserve_df(dataframe: DataFrame) -> tuple[int, float, datetime]:
|
||||
"""keep some data for dataframes"""
|
||||
return len(dataframe), dataframe["close"].iloc[-1], dataframe["date"].iloc[-1]
|
||||
|
||||
def assert_df(self, dataframe: DataFrame, df_len: int, df_close: float, df_date: datetime):
|
||||
"""
|
||||
Ensure dataframe (length, last candle) was not modified, and has all elements we need.
|
||||
"""
|
||||
message_template = "Dataframe returned from strategy has mismatching {}."
|
||||
message = ""
|
||||
if dataframe is None:
|
||||
message = "No dataframe returned (return statement missing?)."
|
||||
elif df_len != len(dataframe):
|
||||
message = message_template.format("length")
|
||||
elif df_close != dataframe["close"].iloc[-1]:
|
||||
message = message_template.format("last close price")
|
||||
elif df_date != dataframe["date"].iloc[-1]:
|
||||
message = message_template.format("last date")
|
||||
if message:
|
||||
if self.disable_dataframe_checks:
|
||||
logger.warning(message)
|
||||
else:
|
||||
raise StrategyError(message)
|
||||
|
||||
def get_latest_candle(
|
||||
self,
|
||||
pair: str,
|
||||
|
||||
42
freqtrade/strategy/strategy_validation.py
Normal file
42
freqtrade/strategy/strategy_validation.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.exceptions import StrategyError
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StrategyResultValidator:
|
||||
def __init__(self, dataframe: DataFrame, warn_only: bool = False):
|
||||
self._warn_only = warn_only
|
||||
self._length: int = len(dataframe)
|
||||
self._close: float = dataframe["close"].iloc[-1]
|
||||
self._date: datetime = dataframe["date"].iloc[-1]
|
||||
|
||||
def assert_df(self, dataframe: DataFrame):
|
||||
"""
|
||||
Ensure dataframe (length, last candle) was not modified, and has all elements we need.
|
||||
Raises a StrategyError if the dataframe does not match the expected values.
|
||||
If warn_only is set, it will log a warning instead of raising an error.
|
||||
:param dataframe: DataFrame to validate
|
||||
:raises StrategyError: If the dataframe does not match the expected values.
|
||||
:logs Warning: If warn_only is set and the dataframe does not match the expected values.
|
||||
"""
|
||||
message_template = "Dataframe returned from strategy has mismatching {}."
|
||||
message = ""
|
||||
if dataframe is None:
|
||||
message = "No dataframe returned (return statement missing?)."
|
||||
elif self._length != len(dataframe):
|
||||
self.message = message_template.format("length")
|
||||
elif self._close != dataframe["close"].iloc[-1]:
|
||||
message = message_template.format("last close price")
|
||||
elif self._date != dataframe["date"].iloc[-1]:
|
||||
message = message_template.format("last date")
|
||||
if message:
|
||||
if self._warn_only:
|
||||
logger.warning(message)
|
||||
else:
|
||||
raise StrategyError(message)
|
||||
Reference in New Issue
Block a user