Skip to content

feat(regime): regime-conditional surrogate (#105)#109

Merged
jc-macdonald merged 1 commit into
mainfrom
feat/105-regime-surrogate
May 12, 2026
Merged

feat(regime): regime-conditional surrogate (#105)#109
jc-macdonald merged 1 commit into
mainfrom
feat/105-regime-surrogate

Conversation

@jc-macdonald
Copy link
Copy Markdown
Contributor

Closes #105. Builds on #82.

Summary

Adds trade_study.regime so studies that currently gate on a regime feature (e.g. n_samples, noise_level) can:

  1. Borrow strength across regimes. Settings that work at n=1k inform predictions at n=3k instead of being thrown away.
  2. Interpolate across continuous regime axes. No more hard buckets — query the surrogate at any regime value.

API

from trade_study import Factor, FactorType, fit_regime_surrogate

surrogate = fit_regime_surrogate(
    results,
    regime_factors=[Factor("n_samples", FactorType.CONTINUOUS, bounds=(1_000, 10_000))],
    factors=[Factor("lr", FactorType.CONTINUOUS, bounds=(1e-4, 1e-1))],
    method="gp",
)
surrogate.predict({"n_samples": 2200}, {"lr": 1e-3})
surrogate.uncertainty({"n_samples": 2200}, {"lr": 1e-3})       # GP only
surrogate.recommend({"n_samples": 2200}, objective="val_loss")  # Sobol' search
  • Internally: a single SurrogateModel over the joint regime_factors + factors input space, so the regime descriptors are additional input dimensions rather than separate models per bucket.
  • recommend() samples n_candidates design configs via scrambled Sobol' (or accepts an explicit candidates= pool) and returns the best surrogate prediction under mode in {"min", "max"}.
  • Inherits the GP-only uncertainty contract from SurrogateModel.

Validation

  • regime_factors must be non-empty and disjoint from factors.
  • recommend() validates mode, objective, and non-empty candidate pools.

Docs

New docs/api/regime.md page in the mkdocs nav, right after Surrogate.

Tests

13 new tests covering validation, predict/predict_batch, GP uncertainty, RF uncertainty raising, recommend() tracking the optimum across regime values, mode inversion, and input validation. regime.py coverage: 100%. Suite: 307 passing, 99.5% project coverage.

Composes with

Add `trade_study.regime` on top of #82's surrogate so studies that gate
on a regime feature (e.g. n_samples, noise level) can borrow strength
across regimes and interpolate factor recommendations across continuous
regime axes instead of relying on hard buckets.

API:
- `fit_regime_surrogate(results, regime_factors, factors, *, method,
  seed, n_estimators) -> RegimeSurrogate`. Validates non-empty regime
  factors and disjoint name sets, then fits a single per-observable
  surrogate over the joint `regime_factors + factors` input space.
- `RegimeSurrogate.predict(regime, config)` /
  `predict_batch(regime, configs)` for inspection / plotting.
- `RegimeSurrogate.uncertainty(regime, config)` propagates the GP-only
  uncertainty contract from `SurrogateModel`.
- `RegimeSurrogate.recommend(regime, *, objective, mode, n_candidates,
  seed, candidates)` samples design-factor candidates via Sobol' (or
  uses an explicit pool) and returns the surrogate-best config.

Docs: new `docs/api/regime.md` page wired into the mkdocs nav.

Tests: 13 new tests covering validation, predict / predict_batch shape,
GP uncertainty, RF uncertainty raising, recommend tracking the regime
optimum, mode='max' inversion, and recommend's input validation.
`regime.py` coverage: 100%. Suite: 307 passing, 99.5% project coverage.

Closes #105.
@jc-macdonald jc-macdonald merged commit f4ed455 into main May 12, 2026
4 checks passed
@jc-macdonald jc-macdonald deleted the feat/105-regime-surrogate branch May 12, 2026 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regime-conditional surrogate: interpolate factor recommendations across regime features

1 participant