feat: wavelets

This commit is contained in:
OpenSquared
2026-07-19 12:44:54 +02:00
parent e627979d08
commit e6fb404062
3 changed files with 205 additions and 0 deletions

View File

@@ -110,6 +110,48 @@ def wavelet_rolling(
return result
@router.get("/reliability")
def wavelet_reliability_endpoint(
symbol: str = Query("SPY"),
period: str = Query("1y", description="how much of the causal output range to scan for turning points"),
lookback: int = Query(130, ge=32),
levels: int = Query(4, ge=2, le=6),
wavelet: str = Query("gmw"),
step: int = Query(1, ge=1),
method: str = Query("cwt", description="cwt (default) or ssq"),
smooth_days: int = Query(3, ge=1, le=10, description="lag used to smooth the slope before flagging a sign-change as a turning point"),
tolerance_days: int = Query(5, ge=0, le=15, description="a hindsight reversal within this many days of the causal one still counts as confirming it"),
confirm_horizon: int = Query(10, ge=1, le=30, description="how many extra days of real data the hindsight recomputation gets"),
):
"""For every reversal a live (causal, walk-forward) decomposition would have flagged,
checks whether redoing the decomposition `confirm_horizon` days later still shows the
same reversal — a per-band reliability score for the wavelet's turning-point signals."""
from services.wavelet_engine import wavelet_reliability
# Needs confirm_horizon extra real days beyond the requested causal output range, on
# top of the usual lookback padding, so the most recent testable turning points aren't
# silently dropped for lack of "future" data.
values, dates, out_days = _fetch_padded_history(symbol, period, lookback + confirm_horizon)
if len(values) < lookback + confirm_horizon + 32:
raise HTTPException(400, "Historique insuffisant pour un test de fiabilité (32 points minimum au-delà de la fenêtre + horizon).")
cutoff = (datetime.utcnow() - timedelta(days=out_days)).date().isoformat()
start_idx = next((i for i, d in enumerate(dates) if d[:10] >= cutoff), None)
if start_idx is None:
raise HTTPException(400, "Pas de donnees dans la plage de trading demandee.")
try:
result = wavelet_reliability(
values, dates,
start_idx=start_idx, lookback=lookback,
num_levels=levels, wavelet=wavelet, method=method, step=step,
smooth_days=smooth_days, tolerance_days=tolerance_days, confirm_horizon=confirm_horizon,
)
except ValueError as exc:
raise HTTPException(400, str(exc)) from exc
return result
# ── Saved simulation/optimization runs ────────────────────────────────────────
class SimulationCreate(BaseModel):