Skip to content

app.routers.electricity

electricity

Historical electricity: DA prices, load, renewables, duration curve, heatmap.

get_duration_curves async

get_duration_curves(request: Request, response: Response, max_points_per_year: int = Query(500, ge=50, le=5000), min_hours: int = Query(720, ge=1, description='Drop years with fewer hours than this (default: ~1 month)'))

All historical years as separate price-duration curves.

Each year's hourly DA prices are sorted descending and downsampled via LTTB to max_points_per_year points. X-axis is normalised to "percent of hours within that year" (0–100), so years with partial data (e.g. the current year) overlay correctly with full years.

Years with fewer than min_hours of data are excluded — these are typically stub rows at the edges of the dataset that would render as single-point degenerate curves.

Source code in dashboard/backend/app/routers/electricity.py
@router.get("/duration-curves")
async def get_duration_curves(
    request: Request,
    response: Response,
    max_points_per_year: int = Query(500, ge=50, le=5000),
    min_hours: int = Query(720, ge=1, description="Drop years with fewer hours than this (default: ~1 month)"),
):
    """All historical years as separate price-duration curves.

    Each year's hourly DA prices are sorted descending and downsampled
    via LTTB to `max_points_per_year` points. X-axis is normalised to
    "percent of hours within that year" (0–100), so years with partial
    data (e.g. the current year) overlay correctly with full years.

    Years with fewer than `min_hours` of data are excluded — these are
    typically stub rows at the edges of the dataset that would render
    as single-point degenerate curves.
    """
    engine = request.app.state.engine
    payload = await run_in_threadpool(
        _get_duration_curves_sync, engine, max_points_per_year, min_hours
    )
    years = payload["years"]
    cache_anchor = _year_end_iso(years[-1]) if years else today_iso()
    add_cache_headers(response, cache_anchor, today_iso())
    return payload