{"record":{"id":"05fe827e2f95abe7","repo":"HKUDS/Vibe-Trading","slug":"n-rows-rows-split-n-splits-ways-gives-subset","errorCode":null,"errorMessage":"{n_rows} rows split {n_splits} ways gives {subset_size} row(s) per subset; each subset needs at least 2 for a Sharpe","messagePattern":"(.+?) rows split (.+?) ways gives (.+?) row\\(s\\) per subset; each subset needs at least 2 for a Sharpe","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/multipletesting.py","lineNumber":494,"sourceCode":"    \"\"\"\n    if n_splits < 4 or n_splits % 2 != 0:\n        raise ValueError(f\"n_splits must be an even number >= 4, got {n_splits}\")\n\n    frame = pd.DataFrame(performance)\n    matrix = frame.to_numpy(dtype=float)\n    if matrix.ndim != 2:\n        raise ValueError(f\"performance must be 2-D, got shape {matrix.shape}\")\n\n    n_rows, n_strategies = matrix.shape\n    if n_strategies < 2:\n        raise ValueError(\n            f\"CSCV ranks strategies against each other and needs at least 2, \"\n            f\"got {n_strategies}\"\n        )\n\n    subset_size = n_rows // n_splits\n    if subset_size < 2:\n        raise ValueError(\n            f\"{n_rows} rows split {n_splits} ways gives {subset_size} row(s) per \"\n            \"subset; each subset needs at least 2 for a Sharpe\"\n        )\n\n    used_rows = subset_size * n_splits\n    dropped = n_rows - used_rows\n    trimmed = matrix[:used_rows]\n    subsets = [\n        trimmed[i * subset_size : (i + 1) * subset_size] for i in range(n_splits)\n    ]\n\n    logits: list[float] = []\n    in_sample_sharpes: list[float] = []\n    out_sample_sharpes: list[float] = []\n    all_indices = set(range(n_splits))\n\n    for chosen in combinations(range(n_splits), n_splits // 2):\n        rest = sorted(all_indices - set(chosen))","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/multipletesting.py#L476-L512","documentation":"Each CSCV subset must contain at least 2 rows for a Sharpe ratio (a standard deviation needs n >= 2) to exist. If n_rows // n_splits < 2 the per-subset Sharpe would be undefined, so probability_of_backtest_overfitting raises this error and tells you the actual arithmetic (rows, splits, subset size).","triggerScenarios":"Passing e.g. 100 rows with n_splits=64 (subset_size=1), or any combination where n_rows < 2 * n_splits.","commonSituations":"Short backtests (a few dozen daily returns) combined with the paper-default 16 or more splits; intraday data where the user thinks in trades but supplies rows of aggregated returns; raising n_splits hoping for finer PBO resolution on a fixed sample.","solutions":["Lower n_splits (e.g. 16 -> 8 -> 4) until n_rows // n_splits >= 2, preferably much larger for stable Sharpes.","Extend the sample: more history or finer time resolution so each block has many rows.","Validate the ratio up front: assert len(performance) // n_splits >= 2."],"exampleFix":"# before\npbo = probability_of_backtest_overfitting(perf_60rows, n_splits=16)  # raises\n\n# after\nn = len(perf_60rows)\nn_splits = max(4, min(16, n // 20))  # >=20 rows per block if possible\npbo = probability_of_backtest_overfitting(perf_60rows, n_splits=n_splits)","handlingStrategy":"validation","validationCode":"n_rows = np.asarray(performance).shape[0]\nassert n_rows // n_splits >= 2, f'need >= {2 * n_splits} rows for {n_splits} splits'","typeGuard":"def rows_support_splits(n_rows: int, n_splits: int) -> bool:\n    return n_rows // n_splits >= 2","tryCatchPattern":"try:\n    pbo = probability_of_backtest_overfitting(perf, n_splits)\nexcept ValueError as e:\n    if 'per subset' in str(e):\n        pbo = probability_of_backtest_overfitting(perf, n_splits=max(4, (len(perf) // 2) - (len(perf) // 2) % 2))\n    else:\n        raise","preventionTips":["Choose n_splits from sample size, e.g. n_splits = min(16, largest even n with n_rows // n >= 10).","Extend history before raising split granularity.","Add a config validator coupling n_splits to series length."],"tags":["backtesting","cscv","sample-size","sharpe"],"backgroundTag":"insufficient-data-for-operation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}