{"record":{"id":"bddf43a564dfd505","repo":"HKUDS/Vibe-Trading","slug":"violations-must-be-in-0-observations-got-vi","errorCode":null,"errorMessage":"violations must be in [0, {observations}], got {violations}","messagePattern":"violations must be in \\[0, (.+?)\\], got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/var_backtest.py","lineNumber":364,"sourceCode":"\n    Args:\n        violations: Number of days the loss exceeded VaR.\n        observations: Number of days tested.\n        confidence: VaR confidence level the model claims, e.g. 0.99.\n        significance: Level at which ``rejected`` is decided.\n\n    Returns:\n        A :class:`KupiecResult`.\n\n    Raises:\n        ValueError: If ``observations`` is not positive, if ``violations`` is\n            negative or exceeds ``observations``, or if either probability is\n            not strictly between 0 and 1.\n    \"\"\"\n    if observations <= 0:\n        raise ValueError(f\"observations must be > 0, got {observations}\")\n    if not 0 <= violations <= observations:\n        raise ValueError(\n            f\"violations must be in [0, {observations}], got {violations}\"\n        )\n    if not 0.0 < confidence < 1.0:\n        raise ValueError(f\"confidence must be in (0, 1), got {confidence}\")\n    if not 0.0 < significance < 1.0:\n        raise ValueError(f\"significance must be in (0, 1), got {significance}\")\n\n    expected_rate = 1.0 - confidence\n    observed_rate = violations / observations\n    calm = observations - violations\n\n    restricted = xlogy(calm, 1.0 - expected_rate) + xlogy(violations, expected_rate)\n    unrestricted = xlogy(calm, 1.0 - observed_rate) + xlogy(violations, observed_rate)\n    statistic = float(max(-2.0 * (restricted - unrestricted), 0.0))\n    p_value = float(chi2.sf(statistic, df=1))\n\n    return KupiecResult(\n        observations=observations,","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/var_backtest.py#L346-L382","documentation":"kupiec_pof requires the breach count to satisfy 0 <= violations <= observations; anything outside — negative counts or more breaches than days — raises ValueError, since the binomial likelihood behind the POF statistic is undefined there.","triggerScenarios":"Passing violations=-3, or violations=250 with observations=200; commonly from double-counting a boolean array (sum of ints plus len), or subtracting counts and going negative.","commonSituations":"Computing violations as (rets < -var).sum() over a misaligned longer series than observations; mixing units (percents vs counts); bugs where violations is passed an array length instead of a count.","solutions":["Recompute violations from the same aligned sample used for observations: v = int((ret < -var_np).sum()); n = len(ret).","Ensure both numbers describe the identical window of data.","Clamp/validate counts before the call if derived from user input."],"exampleFix":"# before\nkupiec_pof(observations=200, violations=250, ...)\n# after\nviol = violation_indicator(ret, var)  # aligned\nkupiec_pof(observations=len(viol), violations=int(viol.sum()), ...)","handlingStrategy":"validation","validationCode":"assert 0 <= violations <= observations","typeGuard":"def valid_counts(n: int, v: int) -> bool:\n    return 0 <= v <= n","tryCatchPattern":"except ValueError as e:\n    if 'violations must be in' in str(e): recompute counts from aligned sample","preventionTips":["Compute violations and observations from the same aligned arrays","Use int() around numpy sums to avoid accidental array arguments"],"tags":["var-backtest","kupiec","range-validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}