From: Jérôme Benoit Date: Fri, 8 Aug 2025 22:32:59 +0000 (+0200) Subject: perf(qav3): code optimizations X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=fcc81c1822878040c85eac90f829097e833f8e1e;p=freqai-strategies.git perf(qav3): code optimizations Signed-off-by: Jérôme Benoit --- diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 34899fc..9bd66c2 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -433,12 +433,13 @@ class QuickAdapterV3(IStrategy): return self.get_label_natr_ratio(pair) * percent @staticmethod + @lru_cache(maxsize=128) def td_format( delta: datetime.timedelta, pattern: str = "{sign}{d}:{h:02d}:{m:02d}:{s:02d}" ) -> str: negative_duration = delta.total_seconds() < 0 delta = abs(delta) - duration = {"d": delta.days} + duration: dict[str, Any] = {"d": delta.days} duration["h"], remainder = divmod(delta.seconds, 3600) duration["m"], duration["s"] = divmod(remainder, 60) duration["ms"] = delta.microseconds // 1000 @@ -572,6 +573,7 @@ class QuickAdapterV3(IStrategy): ) @staticmethod + @lru_cache(maxsize=128) def is_trade_duration_valid(trade_duration: Optional[int | float]) -> bool: return isinstance(trade_duration, (int, float)) and not ( isna(trade_duration) or trade_duration <= 0 @@ -1077,6 +1079,7 @@ class QuickAdapterV3(IStrategy): ) @staticmethod + @lru_cache(maxsize=128) def is_isoformat(string: str) -> bool: if not isinstance(string, str): return False diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index 826d9bc..f9ede23 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -112,12 +112,15 @@ def smooth_extrema( ) +@lru_cache(maxsize=128) def format_number(value: int | float, significant_digits: int = 5) -> str: if not isinstance(value, (int, float)): return str(value) - if np.isinf(value): - return "+∞" if value > 0 else "-∞" + if np.isposinf(value): + return "+∞" + if np.isneginf(value): + return "-∞" if np.isnan(value): return "NaN" @@ -129,18 +132,11 @@ def format_number(value: int | float, significant_digits: int = 5) -> str: if abs_value >= 1.0: precision = significant_digits else: - value_str = f"{abs_value:.18f}" - first_digit_pos = -1 - for i, char in enumerate(value_str): - if char > "0" and char <= "9": - first_digit_pos = i - break - - if first_digit_pos == -1: - precision = significant_digits - else: - leading_zeros = first_digit_pos - 2 - precision = leading_zeros + significant_digits + if abs_value == 0: + return "0" + order_of_magnitude = math.floor(math.log10(abs_value)) + leading_zeros = abs(order_of_magnitude) - 1 + precision = leading_zeros + significant_digits formatted_value = f"{value:.{precision}f}" @@ -240,6 +236,7 @@ def calculate_zero_lag(series: pd.Series, period: int) -> pd.Series: return 2 * series - series.shift(int(lag)) +@lru_cache(maxsize=8) def get_ma_fn(mamode: str) -> Callable[[pd.Series, int], np.ndarray]: mamodes: dict[str, Callable[[pd.Series, int], np.ndarray]] = { "sma": ta.SMA, @@ -254,6 +251,7 @@ def get_ma_fn(mamode: str) -> Callable[[pd.Series, int], np.ndarray]: return mamodes.get(mamode, mamodes["sma"]) +@lru_cache(maxsize=8) def get_zl_ma_fn(mamode: str) -> Callable[[pd.Series, int], np.ndarray]: ma_fn = get_ma_fn(mamode) return lambda series, timeperiod: ma_fn( @@ -935,6 +933,7 @@ def soft_extremum(series: pd.Series, alpha: float) -> float: return numerator / denominator +@lru_cache(maxsize=128) def round_to_nearest_int(value: float, step: int) -> int: """ Round a value to the nearest multiple of a given step.