feat: curve regime
This commit is contained in:
@@ -249,10 +249,12 @@ def rolling_causal_bands(
|
||||
n = len(values)
|
||||
out_dates: list[str] = []
|
||||
out_original: list[float] = []
|
||||
out_mean: list[float] = []
|
||||
band_series: list[list[float]] = [[] for _ in range(num_levels)]
|
||||
band_labels = [f"bande {i + 1}" for i in range(num_levels)]
|
||||
band_failed = [False] * num_levels
|
||||
last_tip: list[float] | None = None
|
||||
last_tip_mean = 0.0
|
||||
recomputations = 0
|
||||
|
||||
for t in range(start_idx, n):
|
||||
@@ -264,12 +266,21 @@ def rolling_causal_bands(
|
||||
window_dates = dates[window_start:t + 1]
|
||||
result = band_decompose(window_values, window_dates, num_levels, wavelet)
|
||||
last_tip = [band["series"][-1] for band in result["bands"]]
|
||||
# band_decompose de-means each trailing window before decomposing it (see its
|
||||
# own x_mean/xc) — reconstructing a day's price needs THAT window's mean added
|
||||
# back, not one fixed constant for the whole causal run (unlike band_decompose's
|
||||
# own single-window "mean" key): a lookback window slides forward every step, so
|
||||
# its mean drifts along with any real trend. Losing this here (never captured)
|
||||
# meant the frontend's mean+sum(bands) reconstruction was silently missing the
|
||||
# entire price level — bands.sum() alone centers on ~0, not the real price.
|
||||
last_tip_mean = result["mean"]
|
||||
band_labels = [band["label"] for band in result["bands"]]
|
||||
for i, band in enumerate(result["bands"]):
|
||||
band_failed[i] = band_failed[i] or band.get("reconstruction_failed", False)
|
||||
recomputations += 1
|
||||
out_dates.append(dates[t])
|
||||
out_original.append(values[t])
|
||||
out_mean.append(last_tip_mean)
|
||||
for i in range(num_levels):
|
||||
band_series[i].append(last_tip[i])
|
||||
|
||||
@@ -288,6 +299,9 @@ def rolling_causal_bands(
|
||||
return {
|
||||
"dates": out_dates,
|
||||
"original": out_original,
|
||||
"mean": out_mean, # per-day series (the trailing window's mean drifts) — NOT a
|
||||
# single scalar like band_decompose's own "mean" key; callers
|
||||
# must add mean[i] (not a bare `mean`) to bands.sum() per day
|
||||
"bands": bands,
|
||||
"wavelet": wavelet,
|
||||
"lookback": lookback,
|
||||
@@ -442,6 +456,7 @@ def rolling_causal_bands_ssq(
|
||||
n = len(values)
|
||||
out_dates: list[str] = []
|
||||
out_original: list[float] = []
|
||||
out_mean: list[float] = []
|
||||
band_series: list[list[float]] = [[] for _ in range(num_levels)]
|
||||
energy_series: list[list[float]] = [[] for _ in range(num_levels)]
|
||||
ridge_series: list[float | None] = []
|
||||
@@ -450,6 +465,7 @@ def rolling_causal_bands_ssq(
|
||||
last_tip: list[float] | None = None
|
||||
last_energy_tip: list[float] | None = None
|
||||
last_ridge_tip: float | None = None
|
||||
last_tip_mean = 0.0
|
||||
recomputations = 0
|
||||
|
||||
for t in range(start_idx, n):
|
||||
@@ -463,12 +479,17 @@ def rolling_causal_bands_ssq(
|
||||
last_tip = [band["series"][-1] for band in result["bands"]]
|
||||
last_energy_tip = [band["energy"][-1] for band in result["bands"]]
|
||||
last_ridge_tip = result["ridge_period_days"][-1]
|
||||
# See rolling_causal_bands's identical fix for why this is a per-day series,
|
||||
# not a single scalar: each trailing window is de-meaned independently before
|
||||
# decomposition, and that mean drifts as the window slides forward.
|
||||
last_tip_mean = result["mean"]
|
||||
band_labels = [band["label"] for band in result["bands"]]
|
||||
for i, band in enumerate(result["bands"]):
|
||||
band_failed[i] = band_failed[i] or band.get("reconstruction_failed", False)
|
||||
recomputations += 1
|
||||
out_dates.append(dates[t])
|
||||
out_original.append(values[t])
|
||||
out_mean.append(last_tip_mean)
|
||||
for i in range(num_levels):
|
||||
band_series[i].append(last_tip[i])
|
||||
energy_series[i].append(last_energy_tip[i])
|
||||
@@ -490,6 +511,7 @@ def rolling_causal_bands_ssq(
|
||||
return {
|
||||
"dates": out_dates,
|
||||
"original": out_original,
|
||||
"mean": out_mean, # per-day series — see rolling_causal_bands
|
||||
"bands": bands,
|
||||
"wavelet": wavelet,
|
||||
"lookback": lookback,
|
||||
|
||||
Reference in New Issue
Block a user