From 7d69b635899115798458358e4610d3d742be0e82 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 20 Jun 2025 22:59:03 +0200 Subject: [PATCH] perf(qav3): readd properly some caching MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../freqaimodels/QuickAdapterRegressorV3.py | 31 ++++++++++--------- .../user_data/strategies/QuickAdapterV3.py | 25 ++++++++------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index 2a8b9d5..049e202 100644 --- a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py +++ b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py @@ -74,6 +74,19 @@ class QuickAdapterRegressorV3(BaseRegressionModel): **self.freqai_info.get("optuna_hyperopt", {}), } + @cached_property + def _optuna_label_candle_pool_full(self) -> list[int]: + n_pairs = len(self.pairs) + label_frequency_candles = max( + 2, 2 * n_pairs, int(self.ft_params.get("label_frequency_candles", 12)) + ) + min_offset = -int(label_frequency_candles / 2) + max_offset = int(label_frequency_candles / 2) + return [ + max(1, label_frequency_candles + offset) + for offset in range(min_offset, max_offset + 1) + ] + def __init__(self, **kwargs): super().__init__(**kwargs) self.pairs = self.config.get("exchange", {}).get("pair_whitelist") @@ -189,20 +202,8 @@ class QuickAdapterRegressorV3(BaseRegressionModel): else: raise ValueError(f"Invalid namespace: {namespace}") - def build_optuna_label_candle_pool(self) -> list[int]: - n_pairs = len(self.pairs) - label_frequency_candles = max( - 2, 2 * n_pairs, int(self.ft_params.get("label_frequency_candles", 12)) - ) - min_offset = -int(label_frequency_candles / 2) - max_offset = int(label_frequency_candles / 2) - return [ - max(1, label_frequency_candles + offset) - for offset in range(min_offset, max_offset + 1) - ] - def init_optuna_label_candle_pool(self) -> None: - self._optuna_label_candle_pool = self.build_optuna_label_candle_pool() + self._optuna_label_candle_pool = self._optuna_label_candle_pool_full random.shuffle(self._optuna_label_candle_pool) if len(self._optuna_label_candle_pool) == 0: raise RuntimeError("Failed to initialize optuna label candle pool") @@ -212,7 +213,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): logger.warning( "Optuna label candle pool is empty, reinitializing it (" f"{self._optuna_label_candle_pool=} ," - f"{self.build_optuna_label_candle_pool()=} ," + f"{self._optuna_label_candle_pool_full=} ," f"{self._optuna_label_candle.values()=} ," f"{self._optuna_label_candles.values()=} ," f"{self._optuna_label_incremented_pairs=})" @@ -237,7 +238,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): self._optuna_label_candle[pair] = optuna_label_candle self._optuna_label_candle_pool.remove(optuna_label_candle) optuna_label_available_candles = ( - set(self.build_optuna_label_candle_pool()) + set(self._optuna_label_candle_pool_full) - set(self._optuna_label_candle_pool) - set(self._optuna_label_candle.values()) ) diff --git a/quickadapter/user_data/strategies/QuickAdapterV3.py b/quickadapter/user_data/strategies/QuickAdapterV3.py index 5a9ff18..8801f75 100644 --- a/quickadapter/user_data/strategies/QuickAdapterV3.py +++ b/quickadapter/user_data/strategies/QuickAdapterV3.py @@ -149,6 +149,18 @@ class QuickAdapterV3(IStrategy): # Match the predictions warmup period return self.freqai_info.get("fit_live_predictions_candles", 100) + @cached_property + def max_open_trades_per_side(self) -> int: + max_open_trades = self.config.get("max_open_trades") + if max_open_trades < 0: + return -1 + if self.is_short_allowed(): + if max_open_trades % 2 == 1: + max_open_trades += 1 + return int(max_open_trades / 2) + else: + return max_open_trades + def bot_start(self, **kwargs) -> None: self.pairs = self.config.get("exchange", {}).get("pair_whitelist") if not self.pairs: @@ -819,7 +831,7 @@ class QuickAdapterV3(IStrategy): ) -> bool: if Trade.get_open_trade_count() >= self.config.get("max_open_trades"): return False - max_open_trades_per_side = self.max_open_trades_per_side() + max_open_trades_per_side = self.max_open_trades_per_side if max_open_trades_per_side >= 0: open_trades = Trade.get_open_trades() trades_per_side = sum(1 for trade in open_trades if trade.enter_tag == side) @@ -860,17 +872,6 @@ class QuickAdapterV3(IStrategy): ) return False - def max_open_trades_per_side(self) -> int: - max_open_trades = self.config.get("max_open_trades") - if max_open_trades < 0: - return -1 - if self.is_short_allowed(): - if max_open_trades % 2 == 1: - max_open_trades += 1 - return int(max_open_trades / 2) - else: - return max_open_trades - def is_short_allowed(self) -> bool: trading_mode = self.config.get("trading_mode") if trading_mode == "margin" or trading_mode == "futures": -- 2.43.0