]> Piment Noir Git Repositories - freqai-strategies.git/commit
fix(quickadapter): guard causal pivot-weight imputation (#158)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 30 Jul 2026 01:07:34 +0000 (03:07 +0200)
committerGitHub <noreply@github.com>
Thu, 30 Jul 2026 01:07:34 +0000 (03:07 +0200)
commitb28d13b3d080b9f50e10f956c7f9887aeda0e433
treea52c35f0e214c8a61cde818d5eb2f1c5921d59fb
parentb856c8cba54dc6370701aaaf1d1510fc2dc0094a
fix(quickadapter): guard causal pivot-weight imputation (#158)

* fix(quickadapter): guard causal pivot-weight imputation

Defer non-finite pivot weights and their Gaussian bands until the frame boundary when legacy full-frame imputation can change across prefixes.

* refactor(quickadapter): dedupe combined label-weight selection and align imputation-mask naming

Address initial-review findings on the causal pivot-weight imputation guard
(behaviour-preserving, verified bit-for-bit against the prior tree):

- F1: extract _select_combined_metrics so _compute_combined_label_weights and
  the imputation-dependency mask share one selection path; each caller applies
  its own imputer, keeping the mask on the legacy full-frame _impute_weights.
- F3: rename compute_label_weight_imputation_mask ->
  compute_label_weight_imputation_dependency_mask for naming coherence with
  imputation_dependency_mask / _nonfinite_imputation_dependency_mask.
- F5: raise an explicit ValueError for strategy='none', mirroring
  compute_label_weights instead of falling through to the generic message.
- F2: rewrite the label_weighting.strategy README sentence to fix a
  garden-path reading.

* refactor(quickadapter): finish combined-weight dedup and tighten mask docstrings

Address residual re-review nits (behaviour-preserving, verified bit-for-bit):

- N1: extract _aggregate_imputed_metrics so _compute_combined_label_weights and
  the imputation-dependency mask share the vstack/aggregate step (no recompute).
- N2: make _select_combined_metrics docstring describe the primitive generically
  instead of one consumer's causal-imputer rationale.
- N3: tighten _nonfinite_imputation_dependency_mask docstring to the essential
  prefix-instability rationale.

* refactor(quickadapter): dedupe weight-strategy error message and fix mask docstring

Address residual re-review nits (behaviour-preserving, error text byte-identical):

- NEW-1: extract _invalid_weight_strategy_message shared by
  compute_label_weight_imputation_dependency_mask and _compute_label_weight_values
  (removes the verbatim duplicated ValueError text).
- NEW-2: correct _nonfinite_imputation_dependency_mask docstring to enumerate all
  prefix-unstable imputation modes (boundary default/zero, interior median).

* docs(quickadapter): drop causal-availability note from label_weighting.strategy

The sentence documented internal causal-availability behaviour (pivot deferral to
the frame boundary), not a choice or value of the strategy tunable, and used
implementation terms undefined in the README. Reverting the strategy row to main
also removes the table re-padding churn, so the PR no longer touches README.

* docs(quickadapter): consolidate cross-tunable behaviour into governing tunables

Apply a global README rule: each tunable row documents that tunable's own role;
behaviour conditioned on another tunable's value lives in the governing tunable's
row (with a short pointer instead of duplication).

- causal_mode: single home for all causal split-guard behaviour (split-option
  rejections; timeseries_split gap auto-set/rejection; train_test_split fixed
  purge; label-aware availability row removal incl. Zigzag confirmation,
  centered-smoothing availability, k-NN bandwidth confirmation, and PR #158
  non-finite imputation-dependency deferral; causal epsilon baseline).
- gap / fill_method / fill_sigma_candles / label_horizon_candles / support_policy /
  continual_learning: keep role-focused text, point to causal_mode / test_size.
- Fix factual defects: optuna_hyperopt.n_jobs default (1, not CPU threads/4 which
  is only a cap); gpu_vram_gb type (int > 0, floored to nearest tier, not enum);
  label_smoothing.window_candles range (int >= 1, floored to 3 at runtime);
  label_frequency_candles range (int [2, 10000] | auto).

* docs(quickadapter): correct causal_mode guard attribution and range constraints

- causal_mode: shuffle_after_split is only causal-gated under train_test_split;
  it is rejected structurally under timeseries_split and held-out evaluation
  regardless of causal_mode, so the false-mode note no longer implies all guards
  are lifted (shuffle and reverse_train_test_order remain fully causal-gated).
- label_pipeline.minmax_range / feature_parameters.range: document the low < high
  constraint (enforced by _RangeValidator / MinMaxScaler), matching robust_quantiles.

* docs(quickadapter): tighten the causal band-skip guard comment

Comment-only: condense the fill_radius skip-guard rationale (7 -> 4 lines) while
keeping the non-obvious causal invariant (an imputation-dependent pivot is not
skipped despite weight_avail == n, since its all-non-finite metric imputes to the
non-zero legacy default and its band must defer to the frame boundary).

* docs(quickadapter): document toggle-independent shuffle-family rejections in causal_mode

NF-A: the held-out evaluation (test_size != 0) rejects shuffle, shuffle_after_split
and reverse_train_test_order unconditionally, and timeseries_split rejects
shuffle_after_split structurally -- both independent of causal_mode. The row now
states these under clause (1) and clarifies the false branch (only the causal
split-guard rejections are lifted; the toggle-independent ones remain).

* perf(quickadapter): release leading stable imputations before frame boundary

For single-metric weight strategies, a leading non-finite run imputes to
0.0 and becomes stable once the first finite pivot's weight is confirmed.
Deferring these pivots to the frame boundary over-purged causally valid
training rows.

compute_label_weight_imputation_dependency_mask now returns a second
leading_stable_mask (subset of dependency_mask) marking that run; empty
for uniform, combined, and all-non-finite metrics. The consumer releases
those pivots at weight_availability[first_finite] (the closing pivot's
backfilled confirmation, not the leaky idx[first_finite]) under an
identity-order guard, and skips their zero-weight Gaussian bands.

combined stays deferred to the frame boundary (prefix aggregation can
still shift a leading pivot), preserving causal safety.
README.md
quickadapter/user_data/strategies/QuickAdapterV3.py
quickadapter/user_data/strategies/Utils.py