ZhuLinsen/daily_stock_analysis · error · ValueError
{alert_type} periods require {required_bars} bars, but at mo
Error message
{alert_type} periods require {required_bars} bars, but at most {MAX_REQUESTED_DAYS} days can be requested What it means
Raised by _ensure_required_bars_fetchable (src/services/alert_indicators.py:361) during parameter normalization: compute_required_bars (e.g. slow_period + signal_period + 1 for MACD, or period + k_period + d_period + 1 for KDJ) yields a bar count exceeding MAX_REQUESTED_DAYS = 365. Since the evaluator can request at most 365 daily bars, parameter sets needing more history are rejected up front as unfetchable.
Source
Thrown at src/services/alert_indicators.py:361
triggered = _crossed_threshold(prev_value, curr_value, threshold, direction)
message = (
f"{stock_code} CCI{period} {curr_value:.2f} crossed {direction} {threshold:.2f}"
if triggered
else f"{stock_code} CCI{period} {curr_value:.2f} did not edge-cross {direction} {threshold:.2f}"
)
return IndicatorEvaluation(
status="triggered" if triggered else "not_triggered",
observed_value=curr_value,
threshold=threshold,
message=message,
data_timestamp=latest,
)
def _ensure_required_bars_fetchable(alert_type: str, params: Dict[str, Any]) -> Dict[str, Any]:
required_bars = compute_required_bars(alert_type, params)
if required_bars > MAX_REQUESTED_DAYS:
raise ValueError(
f"{alert_type} periods require {required_bars} bars, "
f"but at most {MAX_REQUESTED_DAYS} days can be requested"
)
return params
def _direction(value: Any, allowed: frozenset[str], *, default: str) -> str:
direction = str(value or default).strip().lower()
if direction not in allowed:
raise ValueError(f"invalid direction: {direction}")
return direction
def _int_in_range(value: Any, field_name: str, *, default: int, minimum: int = 2, maximum: int = 250) -> int:
raw_value = default if value is None or value == "" else value
try:
number = int(raw_value)
except (TypeError, ValueError) as exc:View on GitHub (pinned to 5159bd72e8)
Solutions
- Reduce periods so the required bars fit within 365 daily bars (e.g. macd slow_period + signal_period <= 364).
- Compute the requirement client-side before submitting: macd => slow+signal+1, kdj => period+k+d+1, ma => window+1, rsi/cci => period+1; keep it <= 365.
- If longer history is genuinely needed, raise MAX_REQUESTED_DAYS in alert_indicators.py after confirming the data source can actually serve that many daily bars.
Example fix
// before
{ "alert_type": "kdj_cross", "parameters": { "period": 250, "k_period": 250, "d_period": 250 } } // needs 751 bars
// after
{ "alert_type": "kdj_cross", "parameters": { "period": 9, "k_period": 3, "d_period": 3 } } // needs 16 bars Defensive patterns
Strategy: validation
Validate before calling
REQUIRED = {
'ma_price_cross': lambda p: p['window'] + 1,
'rsi_threshold': lambda p: p['period'] + 1,
'macd_cross': lambda p: p['slow_period'] + p['signal_period'] + 1,
'kdj_cross': lambda p: p['period'] + p['k_period'] + p['d_period'] + 1,
'cci_threshold': lambda p: p['period'] + 1,
}
# fill defaults first, then:
if REQUIRED[alert_type](params) > 365:
raise ValueError('periods need more than 365 daily bars; reduce them') Type guard
def periods_fetchable(alert_type: str, p: dict) -> bool:
return compute_required_bars(alert_type, p) <= 365 Try / catch
try:
normalize_indicator_parameters(alert_type, params)
except ValueError as e:
if 'bars, but at most 365 days' in str(e):
return bad_request('reduce indicator periods: warm-up exceeds 365 daily bars')
raise Prevention
- Remember the per-field cap is 250 but the summed-bars cap is 365 — sums, not single fields, trip this.
- Show a live 'required history: N bars' hint in the UI computed with the same formulas.
- Never migrate long-period configs from platforms with bigger history windows without checking this bound.
When it happens
Trigger: macd_cross with slow_period=250 and signal_period=250 (needs 501 bars); kdj_cross with period=k_period=d_period=250 (needs 751 bars); any combination where the indicator's warm-up window sums past 365 trading days. Each individual field is capped at 250 by _int_in_range, but their sum can exceed 365.
Common situations: Users maximizing periods for 'smoother' signals without realizing warm-up sums; configs migrated from another platform with a higher daily-history cap; defaults are safe (12+26+1, 9+3+3+1) so this only fires with explicit overrides.
Related errors
- fast_period must be < slow_period
- unsupported alert_type for current EventMonitor runtime: {al
- Event alert rules must be a JSON array
- Event alert rules list must contain only objects; invalid en
- Event alert rule must be an object
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/b22dbcdb18b35634.
Report an issue: GitHub.