Route the label_smoothing method x mode check through the shared label-kind
machinery instead of a bespoke loop in the smoothing getter:
- fold the per-kind coupled-field validator into _LABEL_KIND_REGISTRY as a
third tuple element (single source of truth), with a named
CrossFieldValidatorFn type alias matching the existing ValidateParamsFn
- get_label_kind_config runs the registered validator on each resolved
per-column config; all four label-kind getters are now symmetric one-liners
- derive the bot_start wrap/causal-mode check's mode-aware method set from
SMOOTHING_METHOD_MODES, dropping the duplicate _SMOOTHING_GAUSSIAN_FILTER1D
- README: keep the per-method mode matrix in the type column, drop the
code-behavior narration from the description
* fix(quickadapter): validate exit calibration and leverage bounds at the option layer
Two config inputs bypassed the option-layer validation their siblings use:
- exit_pricing.thresholds_calibration.decline_quantile was merged raw:
documented float (0,1) but enforced nowhere (only a consumer-side guard
that raised TypeError on non-numeric input). Route it through a validated
get_exit_thresholds_calibration_config using the shared _validate_params
machinery, with DEFAULTS_EXIT_THRESHOLDS_CALIBRATION as single source of
truth (drops the duplicate class-var default). Invalid values warn and
fall back to 0.5.
- leverage() applied only the upper bound; the documented lower bound 1.0
(README: float [1.0, max_leverage]) and non-numeric guarding were missing.
Clamp to [1.0, max_leverage], falling back to proposed_leverage on
non-numeric input.
* fix(quickadapter): validate custom_protections config at the option layer
custom_protections was the last config section read ad-hoc with hard int()/
float() casts that crashed on non-numeric input, inconsistent with the
warn-and-fall-back contract every other section uses.
Add get_custom_protections_config on the shared _validate_params machinery
(new _BoolValidator for the enabled flags; nested cooldown/drawdown/stoploss
sub-dicts validated per section) with single-source DEFAULTS_*; the
protections property consumes the validated, typed config. Invalid or
non-numeric values now warn and fall back to their documented defaults
instead of raising.
* fix(quickadapter): validate fit_live_predictions_candles at the option layer
The last strategy-side config value read with a raw int() cast (protections
and startup_candle_count) crashed on non-numeric input. Route it through a
validated get_fit_live_predictions_candles (positive int, warn and fall back
to the default) on the shared _validate_params machinery; drop the now-unused
DEFAULT_FIT_LIVE_PREDICTIONS_CANDLES import.
* refactor(quickadapter): address PR review nits
- harmonize get_exit_thresholds_calibration_config to accept the parent
exit_pricing dict and deref thresholds_calibration internally, removing the
double as_dict at the call site (mirrors get_custom_protections_config)
- reject bool in _NumericValidator: bool is not a valid numeric input,
consistent with is_finite_number / leverage() / _BoolValidator
- drop the dead commented minimal_roi block referencing the removed
DEFAULT_FIT_LIVE_PREDICTIONS_CANDLES import
- align comment terminology on 'cross-field' (matches CrossFieldValidatorFn)
- warn instead of silently resetting when a config section is present but not
a mapping: new as_config_section helper applied to custom_protections
(+ cooldown/drawdown/stoploss) and exit_pricing.thresholds_calibration
- re-add default_exit_thresholds_calibration ClassVar as a compat alias to the
canonical DEFAULTS_EXIT_THRESHOLDS_CALIBRATION (public API stability)
- move the minimal_roi rationale note directly above its assignment
- Warn on non-mapping config sections by routing the section getters
(label kinds, exit_pricing, reversal_confirmation, fit_live) through
as_config_section, matching the custom_protections pattern (N-1).
- Honor the default_exit_thresholds_calibration override via an optional
overrides argument merged over the canonical defaults; user config
still wins in _validate_params (N-2).
- Resolve fit_live_predictions_candles once through the canonical
validator in the regressor so an explicit 0 floors to 100, fixing the
.iloc[-0:] whole-frame slice (N-3).
* fix(quickadapter): warn on invalid leverage before fallback
Route the configured leverage through a cached validator that logs a
harmonized warning when the value is non-numeric or a boolean before
falling back to proposed_leverage, instead of silently discarding the
user setting. The warning fires once (cached) to avoid per-call spam.
* fix(quickadapter): warn on sub-minimum leverage; cache protections
- Warn once (via the _configured_leverage cached_property) when a numeric
leverage is below the 1.0 floor before the leverage() hook clamps it;
the per-pair max_leverage ceiling is only known at entry time, so
above-ceiling values stay clamped silently.
- Promote protections to a cached_property, aligning it with the sibling
config-derived accessors and collapsing duplicate warnings on a
malformed custom_protections/freqai section to one per strategy
instance (reload re-instantiates the strategy, so the cache is fresh).
* refactor(quickadapter): drop dead FIT_LIVE_PREDICTIONS_CANDLES_DEFAULT
Both consumers were rewired to the resolved self._fit_live_predictions_candles,
leaving the ClassVar and its DEFAULT_FIT_LIVE_PREDICTIONS_CANDLES import unused.
Remove both (not a public-library API surface).
* style(quickadapter): drop redundant comments in exit-calibration getter
The as_dict coercion and defaults merge are self-explanatory; keep
comments only where the code is not clear on its own.
* fix(quickadapter): guard leverage finiteness; warn-once on fit-live warmup
- Reject non-finite leverage (NaN/Inf) via the shared is_finite_number
guard before falling back to proposed_leverage, instead of letting it
reach the clamp silently.
- Back startup_candle_count and protections with a cached
_fit_live_predictions_candles helper so an invalid fit_live_predictions_candles
warns once instead of on every access. startup_candle_count stays a plain
property so the StrategyResolver keeps protecting it from config override
(cached_property is not a property subclass).
* style(quickadapter): drop redundant _LABEL_KIND_REGISTRY comment
The tuple type (CrossFieldValidatorFn | None) and the named unpacking
(cross_field_validator) already document the third element.
* fix(quickadapter): validate exit-calibration override before use
Route the override (e.g. a subclass default_exit_thresholds_calibration)
through _validate_params against the canonical defaults so an invalid
subclass value falls back to the canonical default instead of being
trusted blindly (previously it could be returned as-is with a misleading
warning, or crash on output_type coercion). User config still wins over
the override, which still wins over the canonical default. Also restore a
concise note on the intentional silent parent coercion.