2020-02-06 19:26:04 +00:00
|
|
|
import logging
|
2024-11-07 20:37:33 +00:00
|
|
|
from collections.abc import Callable
|
2021-11-08 18:59:29 +00:00
|
|
|
from copy import deepcopy
|
2022-04-16 04:53:38 +00:00
|
|
|
from functools import wraps
|
2024-11-07 20:37:33 +00:00
|
|
|
from typing import Any, TypeVar, cast
|
2020-02-06 19:26:04 +00:00
|
|
|
|
|
|
|
from freqtrade.exceptions import StrategyError
|
|
|
|
|
2020-09-28 17:39:41 +00:00
|
|
|
|
2020-02-06 19:26:04 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2024-05-12 14:41:08 +00:00
|
|
|
F = TypeVar("F", bound=Callable[..., Any])
|
2022-04-16 04:53:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
def strategy_safe_wrapper(f: F, message: str = "", default_retval=None, supress_error=False) -> F:
|
2020-02-22 10:41:22 +00:00
|
|
|
"""
|
|
|
|
Wrapper around user-provided methods and functions.
|
|
|
|
Caches all exceptions and returns either the default_retval (if it's not None) or raises
|
|
|
|
a StrategyError exception, which then needs to be handled by the calling method.
|
|
|
|
"""
|
2024-05-12 14:41:08 +00:00
|
|
|
|
2022-04-16 04:53:38 +00:00
|
|
|
@wraps(f)
|
2020-02-06 19:26:04 +00:00
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
try:
|
2024-05-12 14:41:08 +00:00
|
|
|
if "trade" in kwargs:
|
2021-11-08 18:59:29 +00:00
|
|
|
# Protect accidental modifications from within the strategy
|
2024-05-12 14:41:08 +00:00
|
|
|
kwargs["trade"] = deepcopy(kwargs["trade"])
|
2020-02-06 19:26:04 +00:00
|
|
|
return f(*args, **kwargs)
|
|
|
|
except ValueError as error:
|
2024-05-12 15:51:21 +00:00
|
|
|
logger.warning(f"{message}Strategy caused the following exception: {error}{f}")
|
2020-06-14 05:15:24 +00:00
|
|
|
if default_retval is None and not supress_error:
|
2020-02-06 19:26:04 +00:00
|
|
|
raise StrategyError(str(error)) from error
|
|
|
|
return default_retval
|
|
|
|
except Exception as error:
|
2024-05-12 15:51:21 +00:00
|
|
|
logger.exception(f"{message}Unexpected error {error} calling {f}")
|
2020-06-14 05:15:24 +00:00
|
|
|
if default_retval is None and not supress_error:
|
2020-02-06 19:26:04 +00:00
|
|
|
raise StrategyError(str(error)) from error
|
|
|
|
return default_retval
|
|
|
|
|
2022-04-16 04:53:38 +00:00
|
|
|
return cast(F, wrapper)
|