]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
refactor(quickadapter): harmonize error messages
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 27 Dec 2025 14:41:47 +0000 (15:41 +0100)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Sat, 27 Dec 2025 14:41:47 +0000 (15:41 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py
quickadapter/user_data/strategies/QuickAdapterV3.py
quickadapter/user_data/strategies/Utils.py

index e009236e1f94b4a7b6670cb951a8e89aca60e977..f49dc0e96ab9a8d9840703f7effd5124ea47840f 100644 (file)
@@ -798,7 +798,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             params = self._optuna_label_params.get(pair)
         else:
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._OPTUNA_NAMESPACES)}"
             )
         return params
@@ -814,7 +814,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             self._optuna_label_params[pair] = params
         else:
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._OPTUNA_NAMESPACES)}"
             )
 
@@ -825,7 +825,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             value = self._optuna_train_value.get(pair)
         else:
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._OPTUNA_NAMESPACES[:2])}"  # Only hp and train
             )
         return value
@@ -837,7 +837,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             self._optuna_train_value[pair] = value
         else:
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._OPTUNA_NAMESPACES[:2])}"  # Only hp and train
             )
 
@@ -846,7 +846,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             values = self._optuna_label_values.get(pair)
         else:
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {QuickAdapterRegressorV3._OPTUNA_NAMESPACES[2]}"  # Only label
             )
         return values
@@ -858,7 +858,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             self._optuna_label_values[pair] = values
         else:
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {QuickAdapterRegressorV3._OPTUNA_NAMESPACES[2]}"  # Only label
             )
 
@@ -1059,7 +1059,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             QuickAdapterRegressorV3._OPTUNA_NAMESPACES[2]
         }:  # Only "label"
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {QuickAdapterRegressorV3._OPTUNA_NAMESPACES[2]}"  # Only label
             )
         if not callable(callback):
@@ -1394,7 +1394,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             pred_minima = pred_extrema[pred_extrema < -eps]
         else:
             raise ValueError(
-                f"Invalid extrema_selection '{extrema_selection}'. "
+                f"Invalid extrema_selection {extrema_selection!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._EXTREMA_SELECTION_METHODS)}"
             )
 
@@ -1489,7 +1489,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             threshold_func = getattr(skimage.filters, f"threshold_{method}")
         except AttributeError:
             raise ValueError(
-                f"Invalid skimage threshold method '{method}'. "
+                f"Invalid skimage threshold method {method!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._SKIMAGE_THRESHOLD_METHODS)}"
             )
 
@@ -1524,7 +1524,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             return threshold_func(values)
         except Exception as e:
             logger.warning(
-                f"Failed to apply skimage threshold function {threshold_func.__name__} on series {series.name}: {e!r}, falling back to median",
+                f"Threshold function {threshold_func.__name__} failed on series {series.name}: {e!r}, falling back to median",
                 exc_info=True,
             )
             return np.nanmedian(values)
@@ -1586,7 +1586,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 raise ValueError("Invalid weights: must be finite and non-negative")
             if metric in QuickAdapterRegressorV3._unsupported_cluster_metrics_set():
                 raise ValueError(
-                    f"Invalid weights: not supported for metric '{metric}'"
+                    f"Invalid weights: not supported for metric {metric!r}"
                 )
 
         matrix = np.asarray(matrix, dtype=np.float64)
@@ -1850,7 +1850,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 in QuickAdapterRegressorV3._unsupported_cluster_metrics_set()
             ):
                 raise ValueError(
-                    f"Invalid label_medoid_metric '{label_medoid_metric}'. "
+                    f"Invalid label_medoid_metric {label_medoid_metric!r}. "
                     f"Unsupported: {', '.join(QuickAdapterRegressorV3._UNSUPPORTED_CLUSTER_METRICS)}"
                 )
             p = None
@@ -1893,7 +1893,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 in QuickAdapterRegressorV3._unsupported_cluster_metrics_set()
             ):
                 raise ValueError(
-                    f"Invalid label_kmeans_metric '{label_kmeans_metric}'. "
+                    f"Invalid label_kmeans_metric {label_kmeans_metric!r}. "
                     f"Unsupported: {', '.join(QuickAdapterRegressorV3._UNSUPPORTED_CLUSTER_METRICS)}"
                 )
             cdist_kwargs: dict[str, Any] = {}
@@ -1971,7 +1971,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                     ]
                 else:
                     raise ValueError(
-                        f"Invalid label_kmeans_selection '{label_kmeans_selection}'. "
+                        f"Invalid label_kmeans_selection {label_kmeans_selection!r}. "
                         f"Supported: {', '.join(QuickAdapterRegressorV3._CLUSTER_SELECTION_METHODS)}"
                     )
             return trial_distances
@@ -1986,7 +1986,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 in QuickAdapterRegressorV3._unsupported_cluster_metrics_set()
             ):
                 raise ValueError(
-                    f"Invalid label_kmedoids_metric '{label_kmedoids_metric}'. "
+                    f"Invalid label_kmedoids_metric {label_kmedoids_metric!r}. "
                     f"Unsupported: {', '.join(QuickAdapterRegressorV3._UNSUPPORTED_CLUSTER_METRICS)}"
                 )
             kmedoids_kwargs: dict[str, Any] = {
@@ -2054,7 +2054,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                         ]
                 else:
                     raise ValueError(
-                        f"Invalid label_kmedoids_selection '{label_kmedoids_selection}'. "
+                        f"Invalid label_kmedoids_selection {label_kmedoids_selection!r}. "
                         f"Supported: {', '.join(QuickAdapterRegressorV3._CLUSTER_SELECTION_METHODS)}"
                     )
             return trial_distances
@@ -2123,7 +2123,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 return np.nanmax(neighbor_distances, axis=1)
         else:
             raise ValueError(
-                f"Invalid label metric '{metric}'. Supported: {', '.join(metrics)}"
+                f"Invalid label metric {metric!r}. Supported: {', '.join(metrics)}"
             )
 
     def _get_multi_objective_study_best_trial(
@@ -2133,7 +2133,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             QuickAdapterRegressorV3._OPTUNA_NAMESPACES[2]
         }:  # Only "label"
             raise ValueError(
-                f"Invalid namespace '{namespace}'. "
+                f"Invalid namespace {namespace!r}. "
                 f"Supported: {QuickAdapterRegressorV3._OPTUNA_NAMESPACES[2]}"  # Only label
             )
         n_objectives = len(study.directions)
@@ -2150,7 +2150,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         )  # "euclidean"
         if label_metric not in metrics:
             raise ValueError(
-                f"Invalid label_metric '{label_metric}'. Supported: {', '.join(metrics)}"
+                f"Invalid label_metric {label_metric!r}. Supported: {', '.join(metrics)}"
             )
 
         best_trials = [
@@ -2275,7 +2275,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             }
             metric_log_msg = f" using {self.ft_params.get('label_metric', QuickAdapterRegressorV3._SCIPY_METRICS[2])} metric"
         logger.info(
-            f"[{pair}] Optuna {namespace} {objective_type} objective hyperopt done{metric_log_msg} ({time_spent:.2f} secs)"
+            f"[{pair}] Optuna {namespace} {objective_type} objective hyperopt completed{metric_log_msg} ({time_spent:.2f} secs)"
         )
         for key, value in study_best_results.items():
             if isinstance(value, list):
@@ -2320,7 +2320,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             )
         else:
             raise ValueError(
-                f"Invalid optuna storage_backend '{storage_backend}'. "
+                f"Invalid optuna storage_backend {storage_backend!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._OPTUNA_STORAGE_BACKENDS)}"
             )
         return storage
@@ -2352,7 +2352,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             )
         else:
             raise ValueError(
-                f"Invalid optuna sampler '{sampler}'. "
+                f"Invalid optuna sampler {sampler!r}. "
                 f"Supported: {', '.join(QuickAdapterRegressorV3._OPTUNA_SAMPLERS)}"
             )
 
@@ -2480,7 +2480,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             optuna.delete_study(study_name=study_name, storage=storage)
         except Exception as e:
             logger.warning(
-                f"Optuna study deletion failed for study {study_name}: {e!r}",
+                f"Optuna study {study_name} deletion failed: {e!r}",
                 exc_info=True,
             )
 
index c87448f6d4224e45c9a9f68e0dcf50e8ae0819c8..1afed8672781bdd3708fc2788376be23251c957e 100644 (file)
@@ -728,7 +728,7 @@ class QuickAdapterV3(IStrategy):
     def get_label_natr_ratio_percent(self, pair: str, percent: float) -> float:
         if not isinstance(percent, float) or not (0.0 <= percent <= 1.0):
             raise ValueError(
-                f"Invalid percent {percent}: must be a float between 0 and 1"
+                f"Invalid percent {percent!r}: must be a float in range [0, 1]"
             )
         return self.get_label_natr_ratio(pair) * percent
 
@@ -789,7 +789,7 @@ class QuickAdapterV3(IStrategy):
             or weighting_mmad_scaling_factor <= 0
         ):
             logger.warning(
-                f"Invalid extrema_weighting mmad_scaling_factor {weighting_mmad_scaling_factor!r}, must be > 0, using default {DEFAULTS_EXTREMA_WEIGHTING['mmad_scaling_factor']!r}"
+                f"Invalid extrema_weighting mmad_scaling_factor {weighting_mmad_scaling_factor!r}, must be a finite number > 0, using default {DEFAULTS_EXTREMA_WEIGHTING['mmad_scaling_factor']!r}"
             )
             weighting_mmad_scaling_factor = DEFAULTS_EXTREMA_WEIGHTING[
                 "mmad_scaling_factor"
@@ -856,7 +856,7 @@ class QuickAdapterV3(IStrategy):
             or weighting_sigmoid_scale <= 0
         ):
             logger.warning(
-                f"Invalid extrema_weighting sigmoid_scale {weighting_sigmoid_scale!r}, must be > 0, using default {DEFAULTS_EXTREMA_WEIGHTING['sigmoid_scale']!r}"
+                f"Invalid extrema_weighting sigmoid_scale {weighting_sigmoid_scale!r}, must be a finite number > 0, using default {DEFAULTS_EXTREMA_WEIGHTING['sigmoid_scale']!r}"
             )
             weighting_sigmoid_scale = DEFAULTS_EXTREMA_WEIGHTING["sigmoid_scale"]
 
@@ -869,7 +869,7 @@ class QuickAdapterV3(IStrategy):
             or weighting_softmax_temperature <= 0
         ):
             logger.warning(
-                f"Invalid extrema_weighting softmax_temperature {weighting_softmax_temperature!r}, must be > 0, using default {DEFAULTS_EXTREMA_WEIGHTING['softmax_temperature']!r}"
+                f"Invalid extrema_weighting softmax_temperature {weighting_softmax_temperature!r}, must be a finite number > 0, using default {DEFAULTS_EXTREMA_WEIGHTING['softmax_temperature']!r}"
             )
             weighting_softmax_temperature = DEFAULTS_EXTREMA_WEIGHTING[
                 "softmax_temperature"
@@ -1045,7 +1045,7 @@ class QuickAdapterV3(IStrategy):
             or not np.isfinite(smoothing_sigma)
         ):
             logger.warning(
-                f"Invalid extrema_smoothing sigma {smoothing_sigma!r}, must be a positive finite number, using default {DEFAULTS_EXTREMA_SMOOTHING['sigma']!r}"
+                f"Invalid extrema_smoothing sigma {smoothing_sigma!r}, must be a finite number > 0, using default {DEFAULTS_EXTREMA_SMOOTHING['sigma']!r}"
             )
             smoothing_sigma = DEFAULTS_EXTREMA_SMOOTHING["sigma"]
 
@@ -1073,7 +1073,7 @@ class QuickAdapterV3(IStrategy):
         try:
             return pattern.format(**duration)
         except (KeyError, ValueError) as e:
-            raise ValueError(f"Invalid pattern '{pattern}': {e!r}")
+            raise ValueError(f"Invalid pattern {pattern!r}: {e!r}")
 
     def set_freqai_targets(
         self, dataframe: DataFrame, metadata: dict[str, Any], **kwargs
@@ -1412,8 +1412,8 @@ class QuickAdapterV3(IStrategy):
         trade_price_target_fn = trade_price_target_methods.get(trade_price_target)
         if trade_price_target_fn is None:
             raise ValueError(
-                f"Invalid trade_price_target '{trade_price_target}'. "
-                f"Supported: {', '.join(sorted(TRADE_PRICE_TARGETS))}"
+                f"Invalid trade_price_target {trade_price_target!r}. "
+                f"Supported: {', '.join(TRADE_PRICE_TARGETS)}"
             )
         return trade_price_target_fn()
 
@@ -1442,7 +1442,7 @@ class QuickAdapterV3(IStrategy):
     ) -> Optional[float]:
         if not (0.0 <= natr_ratio_percent <= 1.0):
             raise ValueError(
-                f"Invalid natr_ratio_percent {natr_ratio_percent}: must be in [0, 1]"
+                f"Invalid natr_ratio_percent {natr_ratio_percent!r}: must be in range [0, 1]"
             )
         trade_duration_candles = self.get_trade_duration_candles(df, trade)
         if not QuickAdapterV3.is_trade_duration_valid(trade_duration_candles):
@@ -1469,7 +1469,7 @@ class QuickAdapterV3(IStrategy):
     ) -> Optional[float]:
         if not (0.0 <= natr_ratio_percent <= 1.0):
             raise ValueError(
-                f"Invalid natr_ratio_percent {natr_ratio_percent}: must be in [0, 1]"
+                f"Invalid natr_ratio_percent {natr_ratio_percent!r}: must be in range [0, 1]"
             )
         trade_duration_candles = self.get_trade_duration_candles(df, trade)
         if not QuickAdapterV3.is_trade_duration_valid(trade_duration_candles):
@@ -1817,7 +1817,7 @@ class QuickAdapterV3(IStrategy):
             )
         else:
             raise ValueError(
-                f"Invalid interpolation_direction '{interpolation_direction}'. "
+                f"Invalid interpolation_direction {interpolation_direction!r}. "
                 f"Supported: {', '.join(QuickAdapterV3._INTERPOLATION_DIRECTIONS)}"
             )
         candle_deviation = (
@@ -1891,7 +1891,7 @@ class QuickAdapterV3(IStrategy):
             candle_threshold = base_price * (1 - current_deviation)
         else:
             raise ValueError(
-                f"Invalid side '{side}'. Supported: {', '.join(QuickAdapterV3._TRADE_DIRECTIONS)}"
+                f"Invalid side {side!r}. Supported: {', '.join(QuickAdapterV3._TRADE_DIRECTIONS)}"
             )
         self._candle_threshold_cache[cache_key] = candle_threshold
         return self._candle_threshold_cache[cache_key]
@@ -1999,12 +1999,12 @@ class QuickAdapterV3(IStrategy):
         if lookback_period > max_lookback_period:
             lookback_period = max_lookback_period
         if not isinstance(decay_ratio, (int, float)):
-            logger.info(
+            logger.debug(
                 f"[{pair}] Denied {trade_direction} {order}: invalid decay_ratio type"
             )
             return False
         if not (0.0 < decay_ratio <= 1.0):
-            logger.info(
+            logger.debug(
                 f"[{pair}] Denied {trade_direction} {order}: invalid decay_ratio {decay_ratio}, must be in (0, 1]"
             )
             return False
@@ -2031,7 +2031,7 @@ class QuickAdapterV3(IStrategy):
             if side == QuickAdapterV3._TRADE_DIRECTIONS[1]:  # "short"
                 trade_direction = QuickAdapterV3._TRADE_DIRECTIONS[0]  # "long"
         if not current_ok:
-            logger.info(
+            logger.debug(
                 f"[{pair}] Denied {trade_direction} {order}: rate {format_number(rate)} did not break threshold {format_number(current_threshold)}"
             )
             return False
@@ -2073,7 +2073,7 @@ class QuickAdapterV3(IStrategy):
                 side == QuickAdapterV3._TRADE_DIRECTIONS[1]
                 and not (close_k < threshold_k)  # "short"
             ):
-                logger.info(
+                logger.debug(
                     f"[{pair}] Denied {trade_direction} {order}: "
                     f"close_k[{-k}] {format_number(close_k)} "
                     f"did not break threshold_k[{-(k + 1)}] {format_number(threshold_k)} "
@@ -2474,7 +2474,7 @@ class QuickAdapterV3(IStrategy):
             return False
         else:
             raise ValueError(
-                f"Invalid trading_mode '{trading_mode}'. "
+                f"Invalid trading_mode {trading_mode!r}. "
                 f"Supported: {', '.join(QuickAdapterV3._TRADING_MODES)}"
             )
 
index 23fec9937a4699f9ff9911f65221d2e974933c0a..3652ccc659b155e2d8f7a31dd17a9a1696eb7f82 100644 (file)
@@ -199,7 +199,7 @@ def non_zero_diff(s1: pd.Series, s2: pd.Series) -> pd.Series:
 @lru_cache(maxsize=8)
 def get_odd_window(window: int) -> int:
     if window < 1:
-        raise ValueError(f"Invalid window {window}: must be > 0")
+        raise ValueError(f"Invalid window {window!r}: must be > 0")
     return window if window % 2 == 1 else window + 1
 
 
@@ -233,7 +233,7 @@ def _calculate_coeffs(
         coeffs = sp.signal.windows.triang(M=window, sym=True)
     else:
         raise ValueError(
-            f"Invalid window type '{win_type}'. "
+            f"Invalid window type {win_type!r}. "
             f"Supported: {', '.join(SMOOTHING_METHODS[:3])}"
         )
     return coeffs / np.sum(coeffs)
@@ -443,7 +443,7 @@ def standardize_weights(
 
     else:
         raise ValueError(
-            f"Invalid standardization method '{method}'. "
+            f"Invalid standardization method {method!r}. "
             f"Supported: {', '.join(STANDARDIZATION_TYPES)}"
         )
 
@@ -632,7 +632,7 @@ def normalize_weights(
         normalized_weights = _normalize_rank(standardized_weights, method=rank_method)
     else:
         raise ValueError(
-            f"Invalid normalization method '{normalization}'. "
+            f"Invalid normalization method {normalization!r}. "
             f"Supported: {', '.join(NORMALIZATION_TYPES)}"
         )
 
@@ -788,7 +788,7 @@ def calculate_hybrid_extrema_weights(
         )
     else:
         raise ValueError(
-            f"Invalid hybrid aggregation method '{aggregation}'. "
+            f"Invalid hybrid aggregation method {aggregation!r}. "
             f"Supported: {', '.join(HYBRID_AGGREGATIONS)}"
         )
 
@@ -969,7 +969,7 @@ def compute_extrema_weights(
         )
 
     raise ValueError(
-        f"Invalid extrema weighting strategy '{strategy}'. "
+        f"Invalid extrema weighting strategy {strategy!r}. "
         f"Supported: {', '.join(WEIGHT_STRATEGIES)}"
     )
 
@@ -1130,7 +1130,7 @@ def top_change_percent(dataframe: pd.DataFrame, period: int) -> pd.Series:
     :return: The top change percentage series
     """
     if period < 1:
-        raise ValueError(f"Invalid period {period}: must be >= 1")
+        raise ValueError(f"Invalid period {period!r}: must be >= 1")
 
     previous_close_top = (
         dataframe.get("close").rolling(period, min_periods=period).max().shift(1)
@@ -1148,7 +1148,7 @@ def bottom_change_percent(dataframe: pd.DataFrame, period: int) -> pd.Series:
     :return: The bottom change percentage series
     """
     if period < 1:
-        raise ValueError(f"Invalid period {period}: must be >= 1")
+        raise ValueError(f"Invalid period {period!r}: must be >= 1")
 
     previous_close_bottom = (
         dataframe.get("close").rolling(period, min_periods=period).min().shift(1)
@@ -1167,7 +1167,7 @@ def price_retracement_percent(dataframe: pd.DataFrame, period: int) -> pd.Series
     :return: Retracement percentage series
     """
     if period < 1:
-        raise ValueError(f"Invalid period {period}: must be >= 1")
+        raise ValueError(f"Invalid period {period!r}: must be >= 1")
 
     previous_close_low = (
         dataframe.get("close").rolling(period, min_periods=period).min().shift(1)
@@ -1249,7 +1249,7 @@ def _fractal_dimension(
 ) -> float:
     """Original fractal dimension computation implementation per Ehlers' paper."""
     if period % 2 != 0:
-        raise ValueError(f"Invalid period {period}: must be even")
+        raise ValueError(f"Invalid period {period!r}: must be even")
 
     half_period = period // 2
 
@@ -1278,7 +1278,7 @@ def frama(df: pd.DataFrame, period: int = 16, zero_lag: bool = False) -> pd.Seri
     Original FRAMA implementation per Ehlers' paper with optional zero lag.
     """
     if period % 2 != 0:
-        raise ValueError(f"Invalid period {period}: must be even")
+        raise ValueError(f"Invalid period {period!r}: must be even")
 
     n = len(df)
 
@@ -1320,7 +1320,7 @@ def smma(series: pd.Series, period: int, zero_lag=False, offset=0) -> pd.Series:
     https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=173&Name=Moving_Average_-_Smoothed
     """
     if period <= 0:
-        raise ValueError(f"Invalid period {period}: must be > 0")
+        raise ValueError(f"Invalid period {period!r}: must be > 0")
     n = len(series)
     if n < period:
         return pd.Series(index=series.index, dtype=float)
@@ -1960,7 +1960,7 @@ def get_optuna_callbacks(
         ]
     else:
         raise ValueError(
-            f"Invalid regressor '{regressor}'. Supported: {', '.join(REGRESSORS)}"
+            f"Invalid regressor {regressor!r}. Supported: {', '.join(REGRESSORS)}"
         )
     return callbacks
 
@@ -2031,7 +2031,7 @@ def fit_regressor(
         )
     else:
         raise ValueError(
-            f"Invalid regressor '{regressor}'. Supported: {', '.join(REGRESSORS)}"
+            f"Invalid regressor {regressor!r}. Supported: {', '.join(REGRESSORS)}"
         )
     return model
 
@@ -2045,13 +2045,13 @@ def get_optuna_study_model_parameters(
 ) -> dict[str, Any]:
     if regressor not in set(REGRESSORS):
         raise ValueError(
-            f"Invalid regressor '{regressor}'. Supported: {', '.join(REGRESSORS)}"
+            f"Invalid regressor {regressor!r}. Supported: {', '.join(REGRESSORS)}"
         )
     if not isinstance(expansion_ratio, (int, float)) or not (
         0.0 <= expansion_ratio <= 1.0
     ):
         raise ValueError(
-            f"Invalid expansion_ratio {expansion_ratio}: must be a float between 0 and 1"
+            f"Invalid expansion_ratio {expansion_ratio!r}: must be in range [0, 1]"
         )
     default_ranges: dict[str, tuple[float, float]] = {
         "n_estimators": (100, 2000),