{"record":{"id":"0e9de80bed7a5c13","repo":"HKUDS/Vibe-Trading","slug":"exit-threshold-must-be-below-enter-threshold-0e9de8","errorCode":null,"errorMessage":"exit_threshold must be below enter_threshold","messagePattern":"exit_threshold must be below enter_threshold","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/skills/correlation-regime/SKILL.md","lineNumber":122,"sourceCode":"    exit_threshold: float = 0.45,\n) -> pd.DataFrame:\n    \"\"\"Hysteresis (Schmitt-trigger) regime state machine on smoothed density.\n\n    The market is FUSED once smoothed density reaches ``enter_threshold`` and\n    stays FUSED until it falls back to ``exit_threshold``. The dead band\n    between the two thresholds is what suppresses chatter.\n\n    Args:\n        density: Edge-density series from :func:`compute_edge_density`\n        smooth_window: Trailing smoothing window (causal; never centered)\n        enter_threshold: Density level that opens a FUSED regime\n        exit_threshold: Density level that closes it (must be < enter_threshold)\n\n    Returns:\n        DataFrame with columns ``density``, ``smoothed``, ``fused`` (0/1)\n    \"\"\"\n    if exit_threshold >= enter_threshold:\n        raise ValueError(\"exit_threshold must be below enter_threshold\")\n\n    # Trailing mean = causal. A centered window here silently reads the future.\n    smoothed = density.rolling(smooth_window, min_periods=1).mean()\n\n    fused = False\n    states = np.zeros(len(smoothed), dtype=int)\n    for i, value in enumerate(smoothed.to_numpy()):\n        if np.isnan(value):\n            states[i] = int(fused)\n            continue\n        if not fused and value >= enter_threshold:\n            fused = True\n        elif fused and value <= exit_threshold:\n            fused = False\n        states[i] = int(fused)\n\n    return pd.DataFrame(\n        {\"density\": density, \"smoothed\": smoothed, \"fused\": states},","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/skills/correlation-regime/SKILL.md#L104-L140","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the config/call so exit_threshold is strictly less than enter_threshold (e.g. enter=0.7, exit=0.4)","Swap the two values if they appear reversed in config","Add cross-field validation (JSON Schema 'exclusiveMinimum' referencing the other field, or a check at config load) so mistakes surface with a clear message"],"exampleFix":"# before\nfused = fuse_regime_states(density, smooth_window=5, enter_threshold=0.4, exit_threshold=0.6)\n\n# after\nfused = fuse_regime_states(density, smooth_window=5, enter_threshold=0.6, exit_threshold=0.4)","handlingStrategy":"validation","validationCode":"def validate_thresholds(enter: float, exit_: float) -> None:\n    if exit_ >= enter:\n        raise ValueError(\"exit_threshold must be below enter_threshold\")\n\nvalidate_thresholds(cfg[\"enter_threshold\"], cfg[\"exit_threshold\"])\nfused = fuse_regime_states(density, smooth_window=cfg[\"smooth_window\"], enter_threshold=cfg[\"enter_threshold\"], exit_threshold=cfg[\"exit_threshold\"])","typeGuard":"def valid_hysteresis(enter: float, exit_: float) -> bool:\n    return enter > exit_","tryCatchPattern":null,"preventionTips":["Use keyword arguments for the two thresholds to avoid positional swaps","Add cross-field validation to strategy config schemas (exit < enter)","Keep a unit test asserting the function raises when thresholds are inverted"],"tags":["hysteresis","thresholds","config-validation","numpy"],"backgroundTag":"invalid-parameter-constraint","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}