feat(regime): add volatility weighted targets#660
Merged
brndnmtthws merged 3 commits intomainfrom Apr 30, 2026
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an optional volatility-weighted target sizing mechanism to the regime rebalance engine, allowing per-symbol effective target weights to adjust based on realized volatility (with clamping, smoothing, and persistence).
Changes:
- Introduces per-symbol volatility-weight config (
volatility_weight) in the config model. - Computes volatility-adjusted effective target weights during regime rebalance and uses them for target value/share calculations, with optional smoothing from persisted state.
- Adds tests covering scaling, smoothing, band behavior, fallback conditions, and config parsing.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| thetagang/strategies/regime_engine.py | Computes effective weights from realized vol, applies them to target sizing, augments summary output, and persists state. |
| thetagang/config_models.py | Adds SymbolConfig.VolatilityWeight and a volatility_weight field on SymbolConfig. |
| tests/test_regime_rebalance.py | Adds extensive async tests for volatility-weight behavior, persistence, and fallbacks. |
| tests/test_legacy_config.py | Updates Polyfactory model factory to account for the new volatility_weight field. |
| tests/test_config_new.py | Adds config parsing/validation tests for the new volatility_weight section. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Haiku
Quiet weights breathe slow
Storms trim risk, calm lets it rise
Bands hold churn at bay
Summary
Adds optional volatility-weighted target sizing for regime rebalance symbols. The regime engine can now compute an effective target weight from realized volatility, clamp it between configured bounds, smooth it from previously persisted state, and use that effective weight for target value and share calculations.
User Impact
Operators can let high-risk sleeves such as TQQQ scale down during high-volatility periods and scale back up in calmer regimes without renormalizing other symbols. This changes regime rebalancing from fixed configured weights to dynamic effective weights for symbols that opt into the new configuration.
Root Cause
Regime rebalancing previously treated configured portfolio weights as static targets. That made TQQQ exposure insensitive to changing realized volatility, so the bot could not reduce or increase that sleeve based on recent risk conditions.
Fix
Introduces
portfolio.symbols.<symbol>.volatility_weightwith target volatility, lookback, min/max weight, rebalance band, and smoothing factors. The regime engine resolves effective weights before target-share calculations, records volatility weight state for later smoothing, displays volatility-adjusted targets in the summary, and falls back to static weights when historical data is invalid or insufficient.Validation
uv run pytestuv run ruff check thetagang testsuv run ruff format --check thetagang testsuv run ty check