Strategies¶
This is the canonical strategy catalog for StackSats built-ins. The published page is generated from the in-repo strategy catalog.
Built-in support tier is defined by catalog metadata, not by the implementation module path. For the maintainer workflow that adds new cataloged strategies, use Add a Built-in Strategy.
Use this page for:
- built-in behavior and intent mode
- model card links, owners, and promotion stage
- required feature sets/columns
- exposed tuning parameters and defaults
- canonical validate/backtest/audit commands
- reasonableness expectations when interpreting model results
- support tier for stable versus experimental reference strategies
Model cards for all cataloged built-ins:
uniformmodel cardrun-daily-papermodel cardsimple-zscoremodel cardmomentummodel cardmvrvmodel cardexample-mvrvmodel cardmvrv-plusmodel card
Purpose and Scope¶
Framework boundary (canonical):
- User strategy code owns feature transforms, signal formulas, and allocation intent.
- Framework runtime owns feature sourcing/materialization, window iteration, clipping, lock semantics, and final invariants.
See Framework Boundary for the full contract.
Global Strategy Contract¶
All strategy hooks are Polars-only:
transform_features(...) -> pl.DataFramebuild_signals(...) -> dict[str, pl.Series]propose_weight(state) -> floatorbuild_target_profile(...) -> TargetProfile | pl.DataFrame
Data shape contract:
- strategy-facing frames use canonical
datecolumns (no index semantics) TargetProfile.valuespayload must bedate+value- runtime rejects ambiguous dual-hook strategies unless
intent_preferenceis set explicitly
Canonical Dataset and Scoring Window¶
Dataset flow:
- Canonical source dataset is long-format
merged_metrics*.parquet(day_utc,metric,value) - Runtime commands consume a derived BRK-wide parquet via
STACKSATS_ANALYTICS_PARQUET, managed default~/.stacksats/data/bitcoin_analytics.parquet, or legacy local fallback./bitcoin_analytics.parquet - Canonical schema: Merged Metrics Parquet Schema
- Projection workflow: BRK Data Source
Scoring defaults used by runtime and strategy audits:
- default backtest start:
2018-01-01 - default backtest end:
2025-12-31(or earlier if data coverage ends sooner) - feature warmup history is included by default; scored windows still begin at the requested
start_date
Stable Supported Built-ins¶
These strategies are part of the stable 1.x contract because their catalog entries are marked tier=stable. Stable built-in strategy IDs: uniform, run-daily-paper, simple-zscore, momentum, mvrv.
| Strategy | strategy_id |
Model card | Tier | Promotion | Family | Owner | Benchmarks | Import spec | Intent mode | Required feature sets | Required columns | Configurable params (defaults) | Validation defaults | Backtest defaults | Description / use case |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
UniformStrategy |
uniform |
card | stable |
promoted |
baseline |
StackSats Maintainers |
none | stacksats.strategies.stable.baselines.uniform:UniformStrategy |
propose |
core_model_features_v1 |
none | none | min_win_rate=50.0, strict=True |
start_date='2018-01-01', end_date='2025-12-31' |
Uniform baseline allocation across each window. Tags: baseline, sanity-check. |
RunDailyPaperStrategy |
run-daily-paper |
card | stable |
promoted |
baseline |
StackSats Maintainers |
uniform |
stacksats.strategies.stable.baselines.run_daily_paper:RunDailyPaperStrategy |
propose |
core_model_features_v1 |
none | none | min_win_rate=0.0, strict=False |
start_date='2018-01-01', end_date='2025-12-31' |
Canonical agent-facing daily decision example with relaxed daily validation defaults. Tags: agent, daily, paper. |
SimpleZScoreStrategy |
simple-zscore |
card | stable |
promoted |
signal |
StackSats Maintainers |
uniform, mvrv |
stacksats.strategies.stable.signals.simple_zscore:SimpleZScoreStrategy |
profile |
core_model_features_v1 |
none | none | min_win_rate=50.0, strict=True |
start_date='2018-01-01', end_date='2025-12-31' |
Preference tilts toward lower mvrv_zscore values. Tags: toy, profile, value. |
MomentumStrategy |
momentum |
card | stable |
promoted |
signal |
StackSats Maintainers |
uniform, mvrv |
stacksats.strategies.stable.signals.momentum:MomentumStrategy |
profile |
core_model_features_v1 |
price_usd |
none | min_win_rate=50.0, strict=True |
start_date='2018-01-01', end_date='2025-12-31' |
Contrarian 30-day momentum preference model. Tags: toy, profile, momentum. |
MVRVStrategy |
mvrv |
card | stable |
promoted |
mvrv |
StackSats Maintainers |
uniform |
stacksats.strategies.stable.mvrv.core:MVRVStrategy |
profile |
core_model_features_v1 |
price_vs_ma, mvrv_zscore, mvrv_gradient, mvrv_percentile, mvrv_acceleration, mvrv_zone, mvrv_volatility, signal_confidence |
none | min_win_rate=50.0, strict=True |
start_date='2018-01-01', end_date='2025-12-31' |
Core package MVRV and MA preference model. Tags: baseline, mvrv, production. |
Experimental Reference Strategies¶
These strategies are cataloged as tier=experimental and are not part of the stable 1.x contract. Their current implementation modules may live under stacksats.strategies.experimental.*, but support status comes from the catalog entry. Experimental built-in strategy IDs: example-mvrv, mvrv-plus.
| Strategy | strategy_id |
Model card | Tier | Promotion | Family | Owner | Benchmarks | Import spec | Intent mode | Required feature sets | Required columns | Configurable params (defaults) | Validation defaults | Backtest defaults | Description / use case |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ExampleMVRVStrategy |
example-mvrv |
card | experimental |
research |
overlay |
StackSats Maintainers |
uniform, mvrv |
stacksats.strategies.experimental.overlays.example_mvrv:ExampleMVRVStrategy |
profile |
core_model_features_v1, brk_overlay_v1 |
price_vs_ma, mvrv_zscore, mvrv_gradient, mvrv_percentile, mvrv_acceleration, mvrv_zone, mvrv_volatility, signal_confidence, brk_netflow_fast, brk_netflow_slow, brk_netflow_slope, brk_activity_level, brk_activity_div_fast, brk_activity_div_slow, brk_liquidity_level, brk_liquidity_impulse, brk_exchange_share_level, brk_exchange_share_delta, brk_miner_pressure, brk_hash_momentum, brk_roi30, brk_roi1y |
activity_weight=0.3, base_temperature=0.58, exchange_share_weight=0.08, interaction_weight=0.12, liquidity_weight=0.1, miner_pressure_weight=0.12, momentum_follow_weight=0.18, netflow_weight=0.22, overlay_features=['brk_netflow_fast', 'brk_netflow_slow', 'brk_netflow_slope', 'brk_activity_level', 'brk_activity_div_fast', 'brk_activity_div_slow', 'brk_liquidity_level', 'brk_liquidity_impulse', 'brk_exchange_share_level', 'brk_exchange_share_delta', 'brk_miner_pressure', 'brk_hash_momentum', 'brk_roi30', 'brk_roi1y'], overlay_scale=0.75, roi_weight=0.12, temperature_confidence_boost=0.55, temperature_volatility_penalty=0.35, temperature_zone_boost=0.14 |
min_win_rate=50.0, strict=True |
start_date='2018-01-01', end_date='2025-12-31' |
Experimental MVRV model with multi-horizon BRK overlays. Tags: experimental, overlay, brk. |
MVRVPlusStrategy |
mvrv-plus |
card | experimental |
candidate |
overlay |
StackSats Maintainers |
uniform, mvrv |
stacksats.strategies.experimental.overlays.mvrv_plus:MVRVPlusStrategy |
profile |
core_model_features_v1, brk_overlay_v1 |
price_usd, price_vs_ma, mvrv_zscore, mvrv_gradient, mvrv_percentile, mvrv_acceleration, mvrv_zone, mvrv_volatility, signal_confidence, brk_netflow, brk_exchange_share, brk_exchange_share_delta, brk_activity_div, brk_roi_context, brk_liquidity_impulse, brk_miner_pressure, brk_hash_momentum |
confidence_boost=0.16, deep_value_boost=1.18, derived_features=['plus_vol21', 'plus_drawdown90'], disagreement_penalty=0.2, drawdown_penalty=0.24, hash_momentum_weight=0.12, high_vol_penalty=0.34, miner_pressure_weight=0.2, neutral_scale=1.0, overheat_dampen=0.62, overlay_features=['brk_netflow', 'brk_exchange_share', 'brk_exchange_share_delta', 'brk_activity_div', 'brk_roi_context', 'brk_liquidity_impulse', 'brk_miner_pressure', 'brk_hash_momentum'], overlay_scale=0.2, risk_budget_base=1.02, risk_budget_max=1.22, risk_budget_min=0.72, smooth_alpha=0.1 |
min_win_rate=50.0, strict=True |
start_date='2018-01-01', end_date='2025-12-31' |
Experimental MVRV baseline with BRK-aware regime gating. Tags: experimental, overlay, risk. |
Built-in intent is explicit by implementation shape:
UniformStrategyusesproposemode.RunDailyPaperStrategyusesproposemode.SimpleZScoreStrategyusesprofilemode.MomentumStrategyusesprofilemode.MVRVStrategyusesprofilemode.
How to Run (Parquet-First)¶
Fetch and prepare the managed runtime parquet:
Validate a built-in strategy on fixed comparison bounds:
Run a backtest on the same canonical window:
stacksats strategy backtest \
--strategy mvrv \
--start-date 2018-01-01 \
--end-date 2025-12-31 \
--output-dir output
Run the built-in strategy audit matrix (uses local workspace code and emits output/strategy_audit.json):
Compare a candidate against baselines on a shared window (uses strategy_id for built-ins and module_or_path:ClassName for customs):
python scripts/compare_strategies.py \
--strategy my_strategy.py:MyStrategy \
--strategy simple-zscore \
--strategy mvrv \
--baseline uniform \
--start-date 2024-01-01 \
--end-date 2024-12-31 \
--strict
Profile hot paths for strategy runtime:
Generate an execution-ready daily decision payload for an external agent:
Metric Interpretation Guide¶
Primary metrics:
win_rate: percent of windows where strategy percentile beats uniform percentileexp_decay_percentile: recency-weighted strategy percentileuniform_exp_decay_percentile: recency-weighted baseline percentileexp_decay_multiple_vs_uniform: ratio of dynamic vs uniform recency-weighted percentilescore: blended headline metric (0.5 * win_rate + 0.5 * exp_decay_percentile)
Reasonableness expectations by strategy family:
uniform: baseline multiple should stay near1.0; material drift indicates a bug.run-daily-paper: treat as a daily-execution harness, not a benchmark; expect near-uniform behavior and use it to verify paper-flow correctness.simple-zscore,momentum: acceptable if finite/stable and non-pathological, even when close to baseline.mvrv: stable baseline model; should produce distinct, non-baseline behavior on representative windows.- experimental overlay models: treat outputs as reference or research signals, not as stable benchmark promises.
Comparability discipline:
- compare strategies on the same start/end window
- keep allocation span and strictness settings fixed
- avoid comparing fixed-end runs with extended-to-latest runs without calling out recency effects
- treat all example interpretations as illustrative unless explicitly dated; regenerate current metrics from local parquet before decisions
Troubleshooting¶
Missing columns or provider data errors¶
- Confirm strategy
required_feature_sets()andrequired_feature_columns()are satisfied. - Verify runtime parquet was derived from canonical merged metrics with required BRK columns.
- For overlay models, ensure required overlay metrics exist in the runtime parquet.
No backtest windows generated¶
- Ensure
end_date >= start_date. - Ensure date span is long enough for 365-day window generation.
- Confirm runtime parquet covers the full requested range.
Forward leakage failures¶
- Ensure strategy logic uses observed-only inputs.
- Remove any dependence on future rows, centered/forward-looking transforms, or direct external I/O inside strategy hooks.
- Remember that causal lint is best-effort static analysis, not a runtime sandbox.
- Re-run strict validation to inspect leakage diagnostics.
Warmup and horizon drift¶
- Keep explicit bounds (
2018-01-01to2025-12-31) for stable model comparisons. - Understand that extending end date changes recency-weighted metrics materially.
- Warmup history can shift early-window features; this is expected and should be held constant across comparisons.
Extending with New Strategies¶
When adding a custom strategy, keep this contract:
- Subclass
BaseStrategyand provide stable metadata (strategy_id,version,description). - Declare provider-backed
required_feature_sets()and hard-required transformed columns. - Keep hooks Polars-native and return canonical shapes.
- If implementing both intent hooks, set
intent_preferenceexplicitly. - Keep external data access out of strategy methods; use framework providers.
- Validate and backtest on explicit date bounds before claiming model deltas.
Selector rules:
- built-in strategies use
strategy_id - custom strategies use
module_or_path:ClassName - service registry built-ins use
catalog_strategy_id
Related references: