Strategy Validation Properties (Exhaustive)¶
This is the canonical running list of properties that validation enforces for strategies.
Framework contract reference: docs/framework.md
Validation Execution Flow¶
flowchart LR
A["Input strategy + date range"] --> B["Contract checks"]
B --> C["Backtest metrics"]
C --> D["Leakage + strict diagnostics"]
D --> E["Threshold checks"]
E --> F["Validation pass/fail summary"]
Validation Property Checklist¶
- [ ] Allocation span config is valid
-
STACKSATS_ALLOCATION_SPAN_DAYSmust be an integer in[90, 1460](default365). -
[ ] Strategy cannot bypass framework orchestration
-
Custom
compute_weightsoverrides are rejected. -
[ ] Strategy must implement an allowed hook path
-
At least one is required:
propose_weight(state)orbuild_target_profile(ctx, features_df, signals). -
[ ] Strategy feature sets must be registry-backed
required_feature_sets()must resolve to registered framework-owned feature providers.-
Strategy classes should avoid sourcing external files, databases, or network data directly.
-
[ ] AST lint blockers are not present
-
Best-effort static lint hard-fails on patterns such as negative
.shift(...), centered.rolling(..., center=True), direct file I/O, direct DB access, and direct network access inside strategy methods. -
[ ]
transform_featuresoutput type is valid -
Must return a Polars
DataFrame. -
[ ] Observed-only feature context is enforced
ctx.features_dfonly contains rows fromstart_datethroughcurrent_date.-
Strategy hooks never receive rows after
current_date. -
[ ]
build_signalsoutput type is valid -
Must return
dict[str, pl.Series]. -
[ ] Signal and profile series shape/date contract holds
-
Each series must be a Polars
Series, with exact positional alignment to the observed windowdatecolumn. -
[ ] Signal and profile series numeric validity holds
-
Series values must be finite numeric (no
NaN,inf, or non-numeric coercion failures). -
[ ]
propose_weightoutputs are finite -
Every proposal must be finite numeric.
-
[ ] Target profile mode is valid
-
Only
preferenceandabsolutemodes are allowed. -
[ ] Allocation index monotonicity holds for temporal counting
-
Allocation index used for
n_pastmust be monotonic increasing. -
[ ] Locked-prefix structural validity holds
-
locked_weightsmust be 1D, finite, values in[0, 1], and length<= n_past. -
[ ] Locked-prefix budget feasibility holds
-
Running sum of locked weights must never exceed total budget
1.0. -
[ ] Locked-prefix daily bounds hold on contract-length windows
-
When window length equals configured span, locked values must be within
[1e-5, 0.1]. -
[ ] Per-day clipping obeys future feasibility constraints
- For contract-length windows, daily clipping enforces both day bounds and future-budget feasibility.
-
Infeasible bounds must hard-fail.
-
[ ] Output weight vector structure is valid
-
Final weights must be 1D and finite.
-
[ ] Output weight values are valid
-
No negative weights; no values above
1.0(within tolerance). -
[ ] Output weights sum exactly to budget (within tolerance)
-
Final weight sum must be
1.0. -
[ ] Contract-length day bounds hold on final weights
-
For span-length windows, each day weight must be within
[1e-5, 0.1]. -
[ ] Daily bounds are globally feasible for span length
-
Span must satisfy feasibility:
n_days * min_daily_weight <= 1.0 <= n_days * max_daily_weight. -
[ ] Historical lock immutability is enforced in strict checks
-
Injected locked prefix must be preserved exactly when recomputing under perturbed future features.
-
[ ] Forward-leakage resistance: truncated-source invariance
-
Prefix outputs at probe date must match when source data is truncated at the probe date and rematerialized as-of that date.
-
[ ] Forward-leakage resistance: perturbed-future invariance
-
Prefix outputs at probe date must match when source data strictly after the probe date is strongly perturbed before rematerialization.
-
[ ] Profile-only leakage resistance is enforced
-
For profile-hook strategies (without propose hook), prefix profile values must be invariant under masked/perturbed future inputs.
-
[ ] Strict mode forbids in-place feature mutation
-
Strategy must not mutate
ctx.features_dfduring weight computation. -
[ ] Strict mode forbids profile-build feature mutation
-
Strategy must not mutate
ctx.features_dfduring transform/signal/profile build path. -
[ ] Strict mode determinism holds
-
Repeated runs with identical inputs must produce exactly matching weights (within
atol=1e-12). -
[ ] Weight constraints hold across validation windows
-
Validation windows must not violate sum, negativity, or (when applicable) min/max day bounds.
-
[ ] Boundary saturation stays below strict threshold
-
In strict mode, boundary-hit rate (days at
MINorMAX) must be<= max_boundary_hit_rate(default0.85). -
[ ] Purged fold robustness minimum is met in strict mode (when fold checks run)
- Minimum fold win rate must be
>= min_fold_win_rate(default20.0). - Folds use a purged walk-forward split with an embargo equal to the allocation span.
-
Fold checks are skipped when there is insufficient date range for at least two valid folds.
-
[ ] Purged fold instability is bounded in strict mode (when fold checks run)
- Fold win-rate standard deviation must be
<= max_fold_win_rate_std(default35.0). -
Fold checks are skipped when there is insufficient date range for at least two valid folds.
-
[ ] Block-shuffled null robustness threshold is met in strict mode (when shuffled checks run)
- Mean win rate on block-shuffled price trials must be
<= max_shuffled_win_rate(default80.0) acrossshuffled_trials(default3). -
Shuffled checks are skipped when
price_usdis missing, the shuffled window is empty, orshuffled_trials <= 0. -
[ ] Bootstrap confidence interval threshold is met in strict mode
-
Lower bootstrap CI for anchored excess must be
>= min_bootstrap_ci_lower_excess. -
[ ] Block-permutation null threshold is met in strict mode
-
Block-permutation p-value for anchored excess versus uniform baseline must be
<= max_permutation_pvalue. -
[ ] Feature drift is bounded in strict mode
- Feature PSI must be
<= max_feature_psi. -
Feature KS statistic must be
<= max_feature_ks. -
[ ] Global win-rate threshold is met
-
Validation backtest win rate must be
>= min_win_rate(default50.0). -
[ ] Daily paper/live execution is gated on strict validation
-
run_daily()performs strict validation on the same strategy fingerprint and data snapshot before order submission. -
[ ] Validation receipts and run fingerprints are persisted
-
Daily runs persist validation receipt IDs, source-data hashes, and observed feature snapshot hashes for reconciliation.
-
[ ] Validation date range must contain data
-
Empty requested validation range is an automatic validation failure.
-
[ ] Backtest path must generate windows
- Validation relies on backtest windows; if none are generated, validation cannot pass.