def wrapper(*args, **kwargs): try: return f(*args, **kwargs) except ValueError as error: logger.warning(f"{message}" f"Strategy caused the following exception: {error}" f"{f}") if default_retval is None: raise StrategyError(str(error)) from error return default_retval except Exception as error: logger.exception(f"{message}" f"Unexpected error {error} calling {f}") if default_retval is None: raise StrategyError(str(error)) from error return default_retval
def wrapper(*args, **kwargs): try: if 'trade' in kwargs: # Protect accidental modifications from within the strategy kwargs['trade'] = deepcopy(kwargs['trade']) return f(*args, **kwargs) except ValueError as error: logger.warning(f"{message}" f"Strategy caused the following exception: {error}" f"{f}") if default_retval is None and not supress_error: raise StrategyError(str(error)) from error return default_retval except Exception as error: logger.exception(f"{message}" f"Unexpected error {error} calling {f}") if default_retval is None and not supress_error: raise StrategyError(str(error)) from error return default_retval
def assert_df(dataframe: DataFrame, df_len: int, df_close: float, df_date: datetime): """ make sure data is unmodified """ message = "" if df_len != len(dataframe): message = "length" elif df_close != dataframe["close"].iloc[-1]: message = "last close price" elif df_date != dataframe["date"].iloc[-1]: message = "last date" if message: raise StrategyError(f"Dataframe returned from strategy has mismatching {message}.")
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 = "" if df_len != len(dataframe): message = "length" elif df_close != dataframe["close"].iloc[-1]: message = "last close price" elif df_date != dataframe["date"].iloc[-1]: message = "last date" if message: if self.disable_dataframe_checks: logger.warning(f"Dataframe returned from strategy has mismatching {message}.") else: raise StrategyError(f"Dataframe returned from strategy has mismatching {message}.")
def test_assert_df_raise(mocker, caplog, ohlcv_history): ohlcv_history.loc[1, 'date'] = arrow.utcnow().shift(minutes=-16) # Take a copy to correctly modify the call mocked_history = ohlcv_history.copy() mocked_history['sell'] = 0 mocked_history['buy'] = 0 mocked_history.loc[1, 'buy'] = 1 caplog.set_level(logging.INFO) 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, 'assert_df', side_effect=StrategyError('Dataframe returned...') ) _STRATEGY.analyze_pair('xyz') assert log_has('Unable to analyze candle (OHLCV) data for pair xyz: Dataframe returned...', caplog)
def test_assert_df_raise(default_conf, mocker, caplog, ohlcv_history): # default_conf defines a 5m interval. we check interval * 2 + 5m # this is necessary as the last candle is removed (partial candles) by default ohlcv_history.loc[1, 'date'] = arrow.utcnow().shift(minutes=-16) # Take a copy to correctly modify the call mocked_history = ohlcv_history.copy() mocked_history['sell'] = 0 mocked_history['buy'] = 0 mocked_history.loc[1, 'buy'] = 1 caplog.set_level(logging.INFO) mocker.patch.object(_STRATEGY, 'assert_df', side_effect=StrategyError('Dataframe returned...')) assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['timeframe'], ohlcv_history) assert log_has( 'Unable to analyze candle (OHLCV) data for pair xyz: Dataframe returned...', caplog)
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 'buy' not in dataframe: message = "Buy column not set." 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)