]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
refactor(quickadapter): polish configuration validation (#164)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Tue, 28 Jul 2026 13:21:22 +0000 (15:21 +0200)
committerGitHub <noreply@github.com>
Tue, 28 Jul 2026 13:21:22 +0000 (15:21 +0200)
quickadapter/user_data/strategies/QuickAdapterV3.py
quickadapter/user_data/strategies/Utils.py

index aaae7550b5f74cfe6ad845421af22da3e33a5ce8..1182fda91aa923a76af4f6f4b2a159e332989598 100644 (file)
@@ -179,7 +179,7 @@ class QuickAdapterV3(IStrategy):
     }
 
     default_exit_thresholds_calibration: ClassVar[dict[str, float]] = (
-        DEFAULTS_EXIT_THRESHOLDS_CALIBRATION
+        DEFAULTS_EXIT_THRESHOLDS_CALIBRATION.copy()
     )
 
     position_adjustment_enable = True
index f2c577857409b4a6d790a97fef42e7d497098136..90a530bb69681548c0665ba1a66527399af6260e 100644 (file)
@@ -476,6 +476,89 @@ def _validate_params(
     return result
 
 
+def validate_range(
+    min_val: float | int,
+    max_val: float | int,
+    logger: Logger,
+    *,
+    name: str,
+    default_min: float | int,
+    default_max: float | int,
+    allow_equal: bool = False,
+    non_negative: bool = True,
+    finite_only: bool = True,
+    max_value: float | int | None = None,
+) -> tuple[float | int, float | int]:
+    min_name = f"min_{name}"
+    max_name = f"max_{name}"
+
+    if not isinstance(default_min, (int, float)) or not isinstance(
+        default_max, (int, float)
+    ):
+        raise ValueError(
+            f"Invalid {name}: defaults must be numeric, "
+            f"got min={type(default_min).__name__!r}, max={type(default_max).__name__!r}"
+        )
+    if default_min > default_max or (not allow_equal and default_min == default_max):
+        raise ValueError(
+            f"Invalid {name}: defaults ordering must have min < max, "
+            f"got min={default_min!r}, max={default_max!r}"
+        )
+    if max_value is not None and (default_min > max_value or default_max > max_value):
+        raise ValueError(
+            f"Invalid {name}: defaults must be <= {max_value!r}, "
+            f"got min={default_min!r}, max={default_max!r}"
+        )
+
+    def _validate_component(
+        value: float | int | None, name: str, default_value: float | int
+    ) -> float | int:
+        constraints = []
+        if finite_only:
+            constraints.append("finite")
+        if non_negative:
+            constraints.append("non-negative")
+        constraints.append("numeric")
+        if max_value is not None:
+            constraints.append(f"<= {max_value}")
+        constraint_str = " ".join(constraints)
+        if (
+            not isinstance(value, (int, float))
+            or isinstance(value, bool)
+            or (finite_only and not _is_finite_value(value))
+            or (non_negative and value < 0)
+            or (max_value is not None and value > max_value)
+        ):
+            logger.warning(
+                f"Invalid {name} {value!r}: must be {constraint_str}, using default {default_value!r}"
+            )
+            return default_value
+        return value
+
+    sanitized_min = _validate_component(min_val, min_name, default_min)
+    sanitized_max = _validate_component(max_val, max_name, default_max)
+
+    ordering_ok = (
+        (sanitized_min < sanitized_max)
+        if not allow_equal
+        else (sanitized_min <= sanitized_max)
+    )
+    if not ordering_ok:
+        logger.warning(
+            f"Invalid {name} ordering: must have {min_name} < {max_name}, "
+            f"got {min_name}={sanitized_min!r}, {max_name}={sanitized_max!r}, "
+            f"using defaults {default_min!r}, {default_max!r}"
+        )
+        sanitized_min, sanitized_max = default_min, default_max
+
+    if sanitized_min != min_val or sanitized_max != max_val:
+        logger.warning(
+            f"Invalid {name} range ({min_name}={min_val!r}, {max_name}={max_val!r}), using ({sanitized_min!r}, {sanitized_max!r})"
+        )
+
+    return sanitized_min, sanitized_max
+
+
 _WEIGHTING_SPECS: Final[dict[str, _ParamSpec]] = {
     "strategy": _ParamSpec(_EnumValidator(WEIGHT_STRATEGIES)),
     "metric_coefficients": _ParamSpec(_DictValidator(COMBINED_METRICS)),
@@ -1246,28 +1329,28 @@ def get_label_kind_config(
 
 
 def get_label_weighting_config(
-    config: dict[str, Any],
+    config: Any,
     logger: Logger,
 ) -> dict[str, Any]:
     return get_label_kind_config("label_weighting", config, logger)
 
 
 def get_label_pipeline_config(
-    config: dict[str, Any],
+    config: Any,
     logger: Logger,
 ) -> dict[str, Any]:
     return get_label_kind_config("label_pipeline", config, logger)
 
 
 def get_label_smoothing_config(
-    config: dict[str, Any],
+    config: Any,
     logger: Logger,
 ) -> dict[str, Any]:
     return get_label_kind_config("label_smoothing", config, logger)
 
 
 def get_label_prediction_config(
-    config: dict[str, Any],
+    config: Any,
     logger: Logger,
 ) -> dict[str, Any]:
     return get_label_kind_config("label_prediction", config, logger)
@@ -5389,89 +5472,6 @@ def floor_to_step(value: float | int, step: int) -> int:
     return int(math.floor(float(value) / step) * step)
 
 
-def validate_range(
-    min_val: float | int,
-    max_val: float | int,
-    logger: Logger,
-    *,
-    name: str,
-    default_min: float | int,
-    default_max: float | int,
-    allow_equal: bool = False,
-    non_negative: bool = True,
-    finite_only: bool = True,
-    max_value: float | int | None = None,
-) -> tuple[float | int, float | int]:
-    min_name = f"min_{name}"
-    max_name = f"max_{name}"
-
-    if not isinstance(default_min, (int, float)) or not isinstance(
-        default_max, (int, float)
-    ):
-        raise ValueError(
-            f"Invalid {name}: defaults must be numeric, "
-            f"got min={type(default_min).__name__!r}, max={type(default_max).__name__!r}"
-        )
-    if default_min > default_max or (not allow_equal and default_min == default_max):
-        raise ValueError(
-            f"Invalid {name}: defaults ordering must have min < max, "
-            f"got min={default_min!r}, max={default_max!r}"
-        )
-    if max_value is not None and (default_min > max_value or default_max > max_value):
-        raise ValueError(
-            f"Invalid {name}: defaults must be <= {max_value!r}, "
-            f"got min={default_min!r}, max={default_max!r}"
-        )
-
-    def _validate_component(
-        value: float | int | None, name: str, default_value: float | int
-    ) -> float | int:
-        constraints = []
-        if finite_only:
-            constraints.append("finite")
-        if non_negative:
-            constraints.append("non-negative")
-        constraints.append("numeric")
-        if max_value is not None:
-            constraints.append(f"<= {max_value}")
-        constraint_str = " ".join(constraints)
-        if (
-            not isinstance(value, (int, float))
-            or isinstance(value, bool)
-            or (finite_only and not _is_finite_value(value))
-            or (non_negative and value < 0)
-            or (max_value is not None and value > max_value)
-        ):
-            logger.warning(
-                f"Invalid {name} {value!r}: must be {constraint_str}, using default {default_value!r}"
-            )
-            return default_value
-        return value
-
-    sanitized_min = _validate_component(min_val, min_name, default_min)
-    sanitized_max = _validate_component(max_val, max_name, default_max)
-
-    ordering_ok = (
-        (sanitized_min < sanitized_max)
-        if not allow_equal
-        else (sanitized_min <= sanitized_max)
-    )
-    if not ordering_ok:
-        logger.warning(
-            f"Invalid {name} ordering: must have {min_name} < {max_name}, "
-            f"got {min_name}={sanitized_min!r}, {max_name}={sanitized_max!r}, "
-            f"using defaults {default_min!r}, {default_max!r}"
-        )
-        sanitized_min, sanitized_max = default_min, default_max
-
-    if sanitized_min != min_val or sanitized_max != max_val:
-        logger.warning(
-            f"Invalid {name} range ({min_name}={min_val!r}, {max_name}={max_val!r}), using ({sanitized_min!r}, {sanitized_max!r})"
-        )
-
-    return sanitized_min, sanitized_max
-
-
 def get_label_defaults(
     feature_parameters: dict[str, Any],
     logger: Logger,