finding · findings/evolution/shared_data/slicing-robustness-findings.md
Before running any feature experiment, we measured every box in our 441-box grid of market data to confirm each one has enough bars to trust — and built guardrails so the thin boxes can't quietly corrupt the results.
This is a one-time validation pass — a dress rehearsal, not the real experiment. On 2026-05-30 the operator ran read-only checks (look-but-never-touch queries) against the production database on bigblack (the team's GPU server). The data lives in ClickHouse, a fast analytics database. The goal was to answer three questions before committing to the full study:
750 dbps means a bar closes after a 0.75% price move. Higher dbps = bigger moves needed = fewer bars produced.Every cell falls into one of four buckets. The headline: 414 of 441 are healthy, and the remaining 27 are explicitly handled rather than ignored.
| Cell class | Count | What it means & what happens to it |
|---|---|---|
| Healthy clears the 1000-bar floor | 414 | Gets the full verdict: the duplicate-check score (Spearman), a redundancy measure (h_norm), and candidate features evaluated. |
Empty bar_count = 0 | 3 | ETHUSDT@100 in slices 01/02/03 — SKIPPED. The data simply ends 2025-06-17, so these windows are blank. |
| Sub-floor 200–999 bars | 24 | Mostly the 750 dbps cells. Flagged meets_floor_1000=false and excluded from the combined tally so they can't skew it. |
| Below 200-bar floor | 0 | None. Wherever a cell has any data at all, it has enough to compute candidates. |
BTCUSDT@750 misses the 1000-bar floor in 10 of 21 slices; BNBUSDT@750 misses in 9. This is exactly what the design doc (slicing-methodology.md) predicted: "bar density at 750 dbps becomes risky."This shows the spread. Where the minimum dips under 1000, the offending slices are named in the last column.
| Cell | Min | Median | Max | Slices under 1000 bars |
|---|---|---|---|---|
| BTCUSDT@100 | 14,082 | 57,246 | 354,751 | — |
| BTCUSDT@250 | 2,618 | 9,119 | 76,680 | — |
| BTCUSDT@500 | 711 | 2,558 | 20,957 | s03, s11 |
| BTCUSDT@750 | 242 | 1,103 | 9,188 | s01, s03, s04, s05, s08, s09, s10, s11, s12, s13 |
| ETHUSDT@100 | 0 | 84,602 | 501,183 | s01, s02, s03 (empty — ends 2025-06-17) |
| ETHUSDT@250 | 2,922 | 18,257 | 97,593 | — |
| BNBUSDT@750 | 312 | 1,156 | 15,301 | s01, s03, s04, s06, s09, s10, s11, s12, s13 |
| LTCUSDT@250 | 7,635 | 16,089 | 116,841 | — (LTC@100 dropped: only 26 bars) |
| XRPUSDT@100 | 51,714 | 132,315 | 1,058,962 | — |
The 500/750 settings for ADA and XRP clear the floor in all but the noted slices.
Beyond counting, the team ran the full probe end-to-end (still read-only) to confirm each safety behavior triggers in real life. A "smoke test" just means: turn it on and check nothing catches fire.
ofi and turnover_imbalance) scored ρ = 0.999999 and were correctly flagged redundant — proof the duplicate-detector has teeth.BTCUSDT@250, slice 01): 21,473 rows, 100 comparison columns + 5 new candidate features, and all candidates passed (their overlap with existing features stayed at or below the 0.85 limit).BTCUSDT@750, slice 01, just 260 bars): the numbers were computed but the cell was flagged meets_floor_1000=false and held out of the summary tally.ETHUSDT@100, slice 01): skipped gracefully with the reason "insufficient bars (0 < 200)" — no crash, no garbage.The validation drove a set of design changes. The first three are scope decisions; #1–#4 are the new mechanics that keep results honest.
| # | Decision | Why (in plain terms) |
|---|---|---|
| — | Crypto-only (forex removed) | Operator directive of 2026-05-30. Forex isn't deleted — it's parked for possible later reintroduction. |
| — | 2021+ only (drop 3 of the 2020 windows) | BTC/ETH bars only begin 2021-01-01, so 2020 windows were empty or ragged. This drops the count from 24 to 21 windows and makes the grid a clean rectangle across 6 coins. |
| — | Drop LTCUSDT@100 | Only 26 bars exist in the whole database — effectively broken, so it's out. |
| #1 | Threshold tiers: 750 = "Spearman only"; 100/250/500 = "full" | Because 750 dbps falls below the 1000-bar floor in about half the slices, its deeper metrics aren't reliable there. So 750 cells only get the basic duplicate-check, not the fancier ones. This keeps every cell on the same tidy 2-month grid (an alternative — a special 3-month window just for 750 — was rejected). |
| #2 | Effective-sample-size honesty | Slices from the same quarter live in the same market mood, so 21 windows aren't 21 independent tests — really about 7. The summary now reports the worst-case pass rate across these 7 moods, not just a flattering pooled count. |
| #3 | Regime stratification | Each candidate's pass rate is broken out by market era — bull_2021 / bear_2022 / stress_2022 / recovery_2023 / bull_2024 / range_2025 / current_2026 — so we catch features that look unique in calm times but turn into duplicates under stress. |
| #4 | --subsample N option | Cells range from 242 to over a million bars. This optional, seed-fixed trimming makes cells comparable and faster. It's safe because the duplicate-check (Spearman) ignores row order, so trimming after the ordered computation changes nothing. |
A fifth suggestion from the earlier assessment ("wire in EURUSD@5 / forex") is superseded by the crypto-only directive and intentionally not applied.
The core design invariant: fragile cells are never silently mixed into a conclusion. Four guardrails enforce it:
meets_floor_1000=false; the roll-up function (aggregate_candidates()) only sums the floor-clearing cells.min_regime_pass_rate is reported next to the pooled rate, because the pooled rate over-counts correlated same-era slices.data-quality-notes.md.--subsample 5000 for speed and fair cross-cell comparison.