ZhuLinsen/daily_stock_analysis · warning · ValueError
Phase-filtered summary candidate set matches too many rows;
Error message
Phase-filtered summary candidate set matches too many rows; narrow the analysis date range, stock code, or evaluation window.
What it means
When a summary is requested with an analysis_phase filter, BacktestService first counts candidate rows matching code/date/window filters. If that pre-phase count already exceeds MAX_DYNAMIC_SUMMARY_ROWS, building the phase-filtered summary would require scanning too much data, so it fails fast with this ValueError (HTTP 400 invalid_params). The message asks the caller to narrow date range, code, or evaluation window.
Source
Thrown at src/services/backtest_service.py:596
if analysis_date_from is not None or analysis_date_to is not None or phase_bucket is not None:
if eval_window_days is None:
eval_window_days = self._infer_eval_window_for_query(
code=code,
engine_version=engine_version,
analysis_date_from=analysis_date_from,
analysis_date_to=analysis_date_to,
)
ew = int(eval_window_days) if eval_window_days is not None else None
count = self.repo.count_results(
code=code,
eval_window_days=ew,
engine_version=engine_version,
analysis_date_from=analysis_date_from,
analysis_date_to=analysis_date_to,
)
if count > self.MAX_DYNAMIC_SUMMARY_ROWS:
if phase_bucket is not None:
raise ValueError(
"Phase-filtered summary candidate set matches too many rows; "
"narrow the analysis date range, stock code, or evaluation window."
)
raise ValueError("Date-filtered summary matches too many rows; narrow the analysis date range or stock code.")
if phase_bucket is not None:
rows_with_context = self.repo.list_results_with_context(
code=code,
eval_window_days=ew,
engine_version=engine_version,
analysis_date_from=analysis_date_from,
analysis_date_to=analysis_date_to,
limit=self.MAX_DYNAMIC_SUMMARY_ROWS + 1,
)
if len(rows_with_context) > self.MAX_DYNAMIC_SUMMARY_ROWS:
raise ValueError(
"Phase-filtered summary matches too many rows; narrow the analysis date range or stock code."
)
filtered_pairs = [View on GitHub (pinned to 5159bd72e8)
Solutions
- Add analysis_date_from/analysis_date_to to bound the range under the row cap.
- Filter by a single stock: pass code=hk00700.
- Pin eval_window_days/engine_version to a smaller slice, or clear/trim old backtest_results rows so unfiltered counts fall under MAX_DYNAMIC_SUMMARY_ROWS.
Example fix
# before
summary = service.get_backtest_summary(analysis_phase="premarket")
# after
summary = service.get_backtest_summary(
analysis_phase="premarket",
analysis_date_from="2026-07-01",
analysis_date_to="2026-08-01",
) Defensive patterns
Strategy: validation
Validate before calling
MAX_ROWS = service.MAX_DYNAMIC_SUMMARY_ROWS
count = service.repo.count_results(
code=code,
eval_window_days=eval_window_days,
engine_version=engine_version,
analysis_date_from=analysis_date_from,
analysis_date_to=analysis_date_to,
)
if count > MAX_ROWS:
# narrow filters before calling get_backtest_summary
analysis_date_from = default_recent_from(count, MAX_ROWS) Try / catch
try:
summary = service.get_backtest_summary(analysis_phase=phase, analysis_date_from=dfrom, analysis_date_to=dto)
except ValueError as exc:
if "too many rows" in str(exc):
return JSONResponse(status_code=400, content={"error": "too_many_rows", "message": str(exc), "hint": "narrow date range/code/window"})
raise Prevention
- Default the summary UI to a bounded date range (e.g. last 30 days) instead of unbounded.
- Surface MAX_DYNAMIC_SUMMARY_ROWS in UI hints when the error fires.
- Monitor backtest_results growth and prune/archived aged rows.
When it happens
Trigger: GET /api/v1/backtest/summary (or service get_backtest_summary) with analysis_phase=premarket and no code, no date bounds, and a database whose backtest_results row count exceeds MAX_DYNAMIC_SUMMARY_ROWS for the default eval window/engine version.
Common situations: After months of scheduled backtests the unfiltered result table grows past the cap; a dashboard defaults to phase-filtered summaries without date filters; combining a phase filter with the default engine_version that dominates the table.
Related errors
- Date-filtered summary matches too many rows; narrow the anal
- Phase-filtered summary matches too many rows; narrow the ana
- invalid_params
- eval_window_days must be positive
- analysis_date_from cannot be after analysis_date_to
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/fb335a3cf35c897f.
Report an issue: GitHub.