{"record":{"id":"fa24a874d7e59786","repo":"HKUDS/Vibe-Trading","slug":"label-end-times-holds-a-non-finite-value","errorCode":null,"errorMessage":"label_end_times holds a non-finite value","messagePattern":"label_end_times holds a non-finite value","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/crossvalidation.py","lineNumber":149,"sourceCode":"    if isinstance(label_end_times, pd.Series):\n        if label_end_times.empty:\n            raise ValueError(\"label_end_times is empty\")\n        starts = label_end_times.index\n        ends = label_end_times.to_numpy()\n        # searchsorted on the start index converts label end *times* into label\n        # end *positions*; the right insertion point minus one keeps a label\n        # that ends between two observations attached to the earlier one.\n        positions = np.searchsorted(starts, ends, side=\"right\") - 1\n        positions = np.clip(positions, np.arange(len(starts)), len(starts) - 1)\n        span_ends = positions.astype(int)\n    else:\n        span_ends = np.asarray(label_end_times, dtype=float)\n        if span_ends.ndim != 1:\n            raise ValueError(f\"label_end_times must be 1-D, got shape {span_ends.shape}\")\n        if span_ends.size == 0:\n            raise ValueError(\"label_end_times is empty\")\n        if not np.isfinite(span_ends).all():\n            raise ValueError(\"label_end_times holds a non-finite value\")\n        span_ends = span_ends.astype(int)\n        if (span_ends < np.arange(span_ends.size)).any():\n            raise ValueError(\n                \"a label cannot end before the observation it belongs to starts\"\n            )\n\n    if n_samples is not None and span_ends.size != n_samples:\n        raise ValueError(\n            f\"label_end_times has {span_ends.size} entries but the sample has {n_samples}\"\n        )\n    return span_ends\n\n\ndef _apply_purge_and_embargo(\n    label_ends: np.ndarray,\n    test_mask: np.ndarray,\n    embargo_size: int,\n) -> tuple[np.ndarray, int, int]:","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/crossvalidation.py#L131-L167","documentation":"_as_label_spans casts array-based label_end_times to float then int positions; NaN or inf values would silently cast to garbage integers (e.g. NaN -> platform-dependent int), corrupting every purge decision. All values are therefore required to be finite.","triggerScenarios":"Passing an array containing np.nan, np.inf, or -inf as label end positions, e.g. from a merge that introduced NaNs or an unfilled mask.","commonSituations":"NaNs introduced by left joins or reindexing on misaligned indexes; sentinel values like -999 replaced later but not here; inf from division by zero when computing end positions.","solutions":["Drop or fill non-finite entries first: ends = ends[np.isfinite(ends)] or use fillna before calling","Fix the merge/reindex that introduced NaNs by aligning on observation ids","Add an assertion np.isfinite(ends).all() in your data pipeline"],"exampleFix":"# before\nfolds = purged_kfold_splits(np.array([2.0, np.nan, 5.0]), n_splits=2)\n\n# after\nends = np.nan_to_num(np.array([2.0, np.nan, 5.0]), nan=3.0)\nfolds = purged_kfold_splits(ends, n_splits=2)","handlingStrategy":"validation","validationCode":"ends = np.asarray(label_end_times, dtype=float)\nif not np.isfinite(ends).all():\n    bad = np.where(~np.isfinite(ends))[0]\n    raise ValueError(f'non-finite label end times at positions {bad}')\nfolds = purged_kfold_splits(ends, n_splits=5)","typeGuard":"def all_finite(x) -> bool:\n    return bool(np.isfinite(np.asarray(x, dtype=float)).all())","tryCatchPattern":"try:\n    folds = purged_kfold_splits(ends, n_splits=5)\nexcept ValueError as e:\n    if 'non-finite' in str(e):\n        ends = ends[np.isfinite(ends)]\n        folds = purged_kfold_splits(ends, n_splits=5)\n    else:\n        raise","preventionTips":["Run np.isfinite checks right after merges/reindexes that can inject NaN","Drop rows with missing label horizons before feature engineering","Avoid sentinel values like -999/inf in label-end columns"],"tags":["cross-validation","nan","numpy","input-validation","python"],"backgroundTag":"nan-in-input-data","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}