energykit.diagnose
One-call financial audit for any smart-meter time series.
energykit.diagnose
One-call energy financial diagnosis.
diagnose() is the showcase function of energykit. Feed it a meter
series and get back a complete financial audit — demand charges, forecast value,
anomaly costs, battery ROI — printed as a terminal dashboard and returned as a
structured DiagnosisReport object.
The “before / after” story
- Before energykit:
“I have a 7% MAPE forecast and I spent $25,000 on electricity last year.”
After energykit (one call):
import energykit as ek
report = ek.diagnose(meter_data)
╔══════════════════════════════════════════════════════════════════╗
║ ⚡ ENERGYKIT | ENERGY FINANCIAL DIAGNOSIS ⚡ ║
╠══════════════════════════════════════════════════════════════════╣
║ Period : Jan 2025 → Dec 2025 (8 760 hourly readings) ║
║ Total : 26 456 kWh Avg: 3.02 kW Peak: 5.86 kW ║
╠══════════════════════════════════════════════════════════════════╣
║ 💡 DEMAND CHARGE RISK ║
║ Peak event : May 14 @ 14:00 → 5.86 kW ║
║ Est. annual demand charge : $879 (@$12.50/kW) ║
║ Battery [10 kWh / 5 kW] : save $219/yr (25%) ║
╠══════════════════════════════════════════════════════════════════╣
║ 🔍 ANOMALY DETECTION ║
║ Anomalies: 23 events (0.26% of readings) ║
║ Estimated waste : 312 kWh → $47 over the period ║
║ Top anomaly : Mar 12 @ 14:00 — spike +450 kWh ($68) ║
╠══════════════════════════════════════════════════════════════════╣
║ 🔋 DER OPPORTUNITY (battery dispatch optimisation) ║
║ Battery [13.5 kWh / 5 kW] annual savings : $729 ║
║ Estimated payback (@$8 000 install) : 11.0 yr ║
╠══════════════════════════════════════════════════════════════════╣
║ 📊 TOTAL ADDRESSABLE SAVINGS ║
║ Anomaly correction : $47/yr ║
║ Demand charge opt. : $219/yr [10 kWh battery] ║
║ DER dispatch : $729/yr [13.5 kWh] ║
║ ────────────────────────────────────────────────────── ║
║ TOTAL POTENTIAL : $995/yr (25% of spend) ║
╚══════════════════════════════════════════════════════════════════╝
Usage
>>> import energykit as ek
>>> report = ek.diagnose(meter_data) # minimal — uses defaults
>>> report = ek.diagnose( # full config
... meter_data,
... energy_price=0.15,
... demand_rate=12.50,
... battery_cost_usd=8_000,
... currency="USD",
... silent=False,
... )
>>> report.total_addressable_savings_usd
994.8
- class energykit.diagnose.DiagnosisReport(total_kwh: float = 0.0, avg_kw: float = 0.0, peak_kw: float = 0.0, peak_timestamp: Timestamp | None = None, n_readings: int = 0, data_start: str | None = None, data_end: str | None = None, demand_charge_annual_usd: float = 0.0, demand_peak_kw: float = 0.0, demand_peak_timestamp: Timestamp | None = None, demand_best_battery_kwh: float = 0.0, demand_best_battery_savings_usd: float = 0.0, anomaly_count: int = 0, anomaly_rate_pct: float = 0.0, anomaly_waste_kwh: float = 0.0, anomaly_cost_usd: float = 0.0, der_battery_kwh: float = 13.5, der_annual_savings_usd: float = 0.0, der_payback_years: float = inf, total_addressable_savings_usd: float = 0.0, pct_of_spend: float = 0.0, raw: dict = <factory>)[source]
Bases:
objectStructured output of
diagnose().- peak_timestamp
- Type:
pd.Timestamp or None
- demand_peak_timestamp
- Type:
pd.Timestamp or None
- energykit.diagnose.diagnose(meter_data: Series, energy_price: float = 0.15, demand_rate: float = 12.5, peak_hours: list | None = None, battery_cost_usd: float = 8000.0, currency: str = '$', silent: bool = False) DiagnosisReport[source]
Run a complete energy financial diagnosis on a meter series.
- Parameters:
meter_data (pd.Series) – Electricity meter readings (kW or kWh) with a
pd.DatetimeIndex. Hourly or 15-minute resolution recommended.energy_price (float, default 0.15) – Retail energy price in $/kWh. Used for anomaly cost estimation and DER savings valuation.
demand_rate (float, default 12.50) – Demand charge rate in $/kW/month. A common commercial rate in the US. Set to 0 to skip demand charge analysis.
peak_hours (list of int or None) – Hours (0–23) when demand charges apply.
None= all hours.battery_cost_usd (float, default 8_000) – All-in installed cost of a residential/small-commercial battery (USD). Used only to compute the payback period estimate.
currency (str, default "USD") – Currency symbol for the report. Does not perform conversion.
silent (bool, default False) – If True, suppress the printed ASCII dashboard.
- Returns:
Structured report with all financials. Access
report.rawfor the full outputs of each sub-module.- Return type:
Examples
>>> from energykit.datasets import load_synthetic_load >>> data = load_synthetic_load(periods=8_760, freq="h")["load_kw"] >>> report = diagnose(data)