Models are now a Composite of drift, volatility and (optional) shape components, so an experiment can swap one part against a fixed control. btcmodel/experiments.py holds seven experiments built from the ideas in the old branches (catalogued in docs/2024-ideas.md), each with its hypothesis and source, and a verdict rule fixed before anything ran. `just ab` runs them on development data. Results: - Shrinking the cycle drift, and a power-law trend (plain or reverting), beat their controls. The power law beats the random walk by 53-63% at 3-4 years with unbiased outcomes, so it is promoted to MODELS. - Every alternative volatility estimate (EWMA blends, other windows, reversion to a level or trend) is worse than the trailing 365-day window. Cycle-dependent volatility, heavy tails and stretched cycle phase show no reliable effect.
31 lines
1.1 KiB
Python
31 lines
1.1 KiB
Python
"""
|
|
Candidate models.
|
|
|
|
A model is any object with a `name` and a
|
|
`forecast(history: pd.DataFrame, horizons: np.ndarray) -> Forecast` method.
|
|
`history` holds every row up to and including the forecast origin and nothing
|
|
after it; the harness guarantees that, so models can use all of it freely.
|
|
Most models are a Composite of a drift and a volatility component.
|
|
"""
|
|
|
|
from .base import Composite
|
|
from .drift import CycleDrift, PowerLawDrift, TrailingMeanDrift, ZeroDrift
|
|
from .volatility import TrailingVol
|
|
|
|
BASELINE = "random_walk"
|
|
|
|
# Order is fixed: it sets each model's colour in every chart.
|
|
MODELS = {
|
|
m.name: m
|
|
for m in (
|
|
# "It stays about here, give or take."
|
|
Composite(BASELINE, ZeroDrift(), TrailingVol()),
|
|
# "It keeps doing what it did last cycle."
|
|
Composite("drift_rw", TrailingMeanDrift(), TrailingVol()),
|
|
# The 2024 model, distilled.
|
|
Composite("cycle", CycleDrift(), TrailingVol()),
|
|
# "Growth keeps slowing, like it always has." Passed the diminishing-returns A/B.
|
|
Composite("powerlaw", PowerLawDrift(), TrailingVol()),
|
|
)
|
|
}
|