I've reviewed everything. Here's my assessment and questions:
The config is well-structured. Key numbers:
1. Grand total discrepancy — which number is authoritative?
The JSON says 50,497 but the CSV has 53,136 rows. The difference appears to be the level1_standalone (9,191) + ratio items (21) + cross-sectional prank (6,552) + companion counts (5,824) living in the CSV but the JSON grand_total only counting interactions (31,548) + some subset. For D2 implementation: should the spoke chat treat the CSV as the canonical feature list and just iterate through it, or should it reconstruct from the JSON config programmatically?
2. Execution strategy given 53K features × 1M rows:
The implementation guide flags that expensive transforms (autocorrelation, percentile rank, binned entropy) run at 5K–50K rows/sec. At 1M rows, that's 20–200 seconds per column. With 91 eligible stats, the expensive transforms alone could take 30–100+ minutes per bucket.
The guide recommends limiting expensive transforms to "top 10–15 columns." Has this already been encoded in the config (i.e., do the 53K features already reflect that restriction), or does D2 need to make a runtime decision about which columns get the expensive treatment?
3. Per-market iteration — how does this change D2?
You said D2–D5 will run iteratively per market. But the Level-1 features and companion counts are market-agnostic — they're rolling stats of base columns regardless of what you're predicting. Only the interactions (and later the selection gates) are market-dependent.
Does this mean D2 should be split into:
Or do ALL 53K features get generated once, stored as Parquet, and then D3 (gating) is the step that runs per-market?
4. Storage format for 53K columns × 1M rows:
That's ~53 billion cells. Even at 8 bytes per float64, that's ~400 GB uncompressed. The handoff doc mentioned "temporary Parquet (too large for permanent DuckDB columns)." What's the storage plan?
5. The implementation guide uses min_periods=1 but the D1 spec says strict thresholding (require exactly W observations → else NULL). Which wins?
The implementation guide's rolling_grouped helper uses min_periods=1 and relies on companion counts for downstream reliability weighting. The D1 spec says "if window has fewer observations than window size, return NULL." These are contradictory. The companion-count approach is more flexible (lets the model decide), but the strict-threshold approach is cleaner. Which policy does D2 implement?
6. DuckDB vs pandas for D2 execution:
The implementation guide offers both pandas and DuckDB SQL approaches. Given you're on Bento with the live DuckDB file, DuckDB window functions would be ~10x faster for the vectorized transforms (rolling_mean, rolling_std, momentum, expanding_mean, ACWR, companion_count — probably 70% of features). Should D2 prefer DuckDB SQL where possible and fall back to pandas only for the custom-apply transforms (entropy, autocorr, percentile_rank)?
My recommendation: Over/Under 2.5 (OU).
Reasons:
Runner-up: Asian Handicap (AH) — also binary, uses difference-type interactions, but requires the handicap line as context which adds complexity.
Avoid for first run: 1X2 (3-class, hardest), BTS (ceiling concerns noted in v0.7.1 — the "floor=0.358" issue).
What are your thoughts on these 6 questions + the OU recommendation?