{"record":{"id":"9934637a8aeb239f","repo":"HKUDS/Vibe-Trading","slug":"observations-must-be-0-got-observations","errorCode":null,"errorMessage":"observations must be > 0, got {observations}","messagePattern":"observations must be > 0, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/var_backtest.py","lineNumber":362,"sourceCode":"    convention makes the zero-breach and all-breach cases well defined rather\n    than special.\n\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","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/var_backtest.py#L344-L380","documentation":"kupiec_pof (Kupiec proportion-of-failures unconditional coverage test) requires a positive observation count; observations <= 0 raises ValueError. Zero or negative samples make the likelihood-ratio statistic undefined (division and log-likelihoods per observation).","triggerScenarios":"Calling kupiec_pof(observations=0, ...) — often because violations/observations were extracted from an empty violation indicator array via sum() and len() on empty data.","commonSituations":"Wrapping var_backtest outputs where the finite-pair filter removed everything; counters computed from empty DataFrames; passing counts in the wrong argument order so a small violations number lands in observations.","solutions":["Verify observations comes from the length of the aligned, finite sample (len(violations), not 0).","Check upstream for empty/NaN-filtered inputs producing zero observations.","Confirm argument order matches (observations, violations, confidence, significance)."],"exampleFix":"# before\nkupiec_pof(0, 0, confidence=0.99, significance=0.05)\n# after\nassert len(violations) > 0\nkupiec_pof(len(violations), int(violations.sum()), 0.99, 0.05)","handlingStrategy":"validation","validationCode":"assert observations > 0, observations","typeGuard":"def positive_int(n) -> bool:\n    return isinstance(n, int) and n > 0","tryCatchPattern":"except ValueError as e:\n    if 'observations must be > 0' in str(e): raise DataError('empty backtest sample') from e","preventionTips":["Derive observations from the aligned sample length","Check the finite-pair count from var_backtest before running Kupiec"],"tags":["var-backtest","kupiec","invalid-argument"],"backgroundTag":"invalid-numeric-argument","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}