HKUDS/Vibe-Trading · error · ValueError

exit_threshold must be below enter_threshold

Error message

exit_threshold must be below enter_threshold

What it means

Part of the correlation-regime skill, this state-fusion function implements hysteresis: a regime is entered when density crosses enter_threshold and exited when it falls below exit_threshold. Hysteresis only works if exit_threshold < enter_threshold; if exit_threshold >= enter_threshold the state machine logic is contradictory, so the function fails fast with ValueError.

Source

Thrown at agent/src/skills/correlation-regime/SKILL.md:122

    exit_threshold: float = 0.45,
) -> pd.DataFrame:
    """Hysteresis (Schmitt-trigger) regime state machine on smoothed density.

    The market is FUSED once smoothed density reaches ``enter_threshold`` and
    stays FUSED until it falls back to ``exit_threshold``. The dead band
    between the two thresholds is what suppresses chatter.

    Args:
        density: Edge-density series from :func:`compute_edge_density`
        smooth_window: Trailing smoothing window (causal; never centered)
        enter_threshold: Density level that opens a FUSED regime
        exit_threshold: Density level that closes it (must be < enter_threshold)

    Returns:
        DataFrame with columns ``density``, ``smoothed``, ``fused`` (0/1)
    """
    if exit_threshold >= enter_threshold:
        raise ValueError("exit_threshold must be below enter_threshold")

    # Trailing mean = causal. A centered window here silently reads the future.
    smoothed = density.rolling(smooth_window, min_periods=1).mean()

    fused = False
    states = np.zeros(len(smoothed), dtype=int)
    for i, value in enumerate(smoothed.to_numpy()):
        if np.isnan(value):
            states[i] = int(fused)
            continue
        if not fused and value >= enter_threshold:
            fused = True
        elif fused and value <= exit_threshold:
            fused = False
        states[i] = int(fused)

    return pd.DataFrame(
        {"density": density, "smoothed": smoothed, "fused": states},

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Fix the config/call so exit_threshold is strictly less than enter_threshold (e.g. enter=0.7, exit=0.4)
  2. Swap the two values if they appear reversed in config
  3. Add cross-field validation (JSON Schema 'exclusiveMinimum' referencing the other field, or a check at config load) so mistakes surface with a clear message

Example fix

# before
fused = fuse_regime_states(density, smooth_window=5, enter_threshold=0.4, exit_threshold=0.6)

# after
fused = fuse_regime_states(density, smooth_window=5, enter_threshold=0.6, exit_threshold=0.4)
Defensive patterns

Strategy: validation

Validate before calling

def validate_thresholds(enter: float, exit_: float) -> None:
    if exit_ >= enter:
        raise ValueError("exit_threshold must be below enter_threshold")

validate_thresholds(cfg["enter_threshold"], cfg["exit_threshold"])
fused = fuse_regime_states(density, smooth_window=cfg["smooth_window"], enter_threshold=cfg["enter_threshold"], exit_threshold=cfg["exit_threshold"])

Type guard

def valid_hysteresis(enter: float, exit_: float) -> bool:
    return enter > exit_

Prevention

When it happens

Trigger: Calling the function with exit_threshold equal to or greater than enter_threshold, e.g. fuse(density, enter_threshold=0.6, exit_threshold=0.6) or enter=0.5, exit=0.7 — often from YAML/JSON config where fields are swapped or defaults drift.

Common situations: Config files copying example values and editing only one threshold, parameter order confusion when calling positionally (exit passed as enter), or round-tripping configs where thresholds get overwritten by a UI without cross-field validation.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/0e9de80bed7a5c13. Report an issue: GitHub.