-
-
Notifications
You must be signed in to change notification settings - Fork 9
cost function math
This document provides the complete mathematical formulation of the HSEM cost function
(planner/cost_function.py). It is the source of truth for all cost calculations.
The cost function returns two distinct aggregates for every plan:
| Aggregate | Symbol | Contents | Used for |
|---|---|---|---|
| total_cost | Real money terms only | Auditing, bill comparison | |
| score |
|
Candidate selection |
The selector picks the plan with the lowest score, not the lowest money cost.
Where
The cost function prices actual grid energy drawn, not stored energy. If the battery stores
$x$ kWh and charge efficiency is$e$ , the grid import is$x/e$ , which includes conversion losses implicitly.
Where
Revenue is subtracted from total cost. Negative export prices (curtailment penalties) increase total cost.
Where
The cycle cost counts the maximum of charge and discharge per slot, not
their sum. This matches the MILP formulation where
The 2× denominator accounts for one full round-trip (charge + discharge = 2 ×
usable_kwh throughput per cycle). With this factor, charging
For battery-side charge and discharge energy, the physical AC flows are:
The first quantity increases import or consumes otherwise-exportable PV. The second reduces import or creates AC export. Import cost and export revenue thus price efficiency exactly once; another loss-price term would double-count it.
An optional per-slot fixed tariff cost, typically zero unless the user configures grid tariff fees.
These are soft guards — the SoC simulation already hard-clamps at hardware limits, so violations are rare. The quadratic form heavily penalises large deviations while tolerating tiny numerical rounding errors.
Past-slot exclusion: Slots with time_passed recommendation are excluded
from SoC penalty calculation. The SoC simulator writes estimated_battery_soc = 0.0
as a sentinel on past slots, which would otherwise generate a false penalty of
Where
Where:
-
$E_{initial}$ = stored battery energy above the discharge floor at the start of the horizon (kWh) -
$E_{final}$ = stored battery energy above the discharge floor at the end of the horizon (kWh) -
$p_{replacement}$ = the end value$V$ of one stored kWh after the horizon (issue #1138)
Sign convention:
The term depends only on cost_helpers.terminal_soc_value.
-
$p_{peak}$ = mean of that day's top-N import prices, N =ceil(usable / max_discharge_per_slot) -
$p_{night}$ = mean import price of that day from 00:00 to 06:00 -
$c$ = cycle cost per kWh
A leftover kWh is worth the lower of its discounted use at the next peak and the
cost of storing it again overnight. See docs/planner-spec.md § Terminal SoC for
why it is not derived from any price inside the horizon.
Zero unless the opt-in house-battery target SoC is active. It prices the shortfall against the target at the next target occurrence, for every candidate, undiscounted:
-
$E[T]$ =estimated_battery_capacity_kwhat the target slot$T$ -
$E_{target}$ = the configured target in model kWh (above the discharge floor) -
$P$ = the shortfall price the MILP stage-2 slack uses:$P = \min\left(\max_{t \le T} \frac{p_{exp}[t]}{\eta_{chg}} + c + \varepsilon,\ P_{ev} - \varepsilon\right)$
docs/planner-spec.md
§ House-battery target SoC by deadline.
The cost function skips any slot whose recommendation is time_passed:
- All energy-flow fields (
grid_import_kwh,batteries_charged, etc.) are zero on past slots - Including them would only affect the SoC penalty (bogus
$w_{low} \cdot soc_{min}^2$ ) - Skipping past slots does not change the winner (the bogus penalty is identical across candidates) but keeps the reported cost clean
For every planner run:
-
$C_{total} = C_{import} - R_{export} + C_{cycle} + C_{loss}$ (exact) - No synthetic penalty enters
$C_{total}$ -
$S = C_{total} + P_{soc} + P_{grid} + P_{override} + V_{terminal}$ (exact) - When all penalties = 0 and terminal-SoC is disabled:
$S = C_{total}$ - Selector picks minimum
$S$ , not minimum$C_{total}$ -
$score_{winner} = score_{final\_output}$ (no post-selection mutation) - Two identical plans, one ending with more stored energy → lower
$V_{terminal}$ → lower$S$
- Home — User-facing overview: features, FAQ, working modes, excess export, consumption sensors
- Battery Charging Economics — How to calculate the minimum charging price for your battery
- Architecture Overview — System context, layered architecture, module map, planning pipeline
- Planner Specification — Normative — all planner invariants, rules, and constraints
- Planner Technical Guide — How the planner works with worked examples
- Cost Function Math — Complete mathematical formulation of the 8-term cost function
- Energy Accounting — Physical energy flow model, SoC simulation, efficiency math
- Candidate Generation — How candidates are generated, assumptions, partial-SoC
- MILP Optimization — Full LP formulation, variable layout, constraints, and solver pipeline
- Consumption Prediction — Weighted-average model, IQR outlier detection, spike suppression
- Safety Modes — Degraded mode, read-only gate, write-verify applier, runtime resolver
- Price Scaling — EDS price cadence auto-detection and raw pass-through
- Services Reference — All 5 HSEM services with examples
- Sensors Reference — Complete entity reference: all sensor, select, switch, number, and time entities
- Dashboard Setup — Step-by-step ApexCharts dashboard with full YAML, layout reference, and troubleshooting
- Config Flow Reference — Every config/options flow step and field
- EV Charge Plan Setup — EV planned load configuration guide
- EV Surplus Charging Automation — Wire your physical EV charger (go-e, Easee, Zaptec) to follow HSEM surplus recommendations
- EV Optimal Charging Template — Legacy Home Assistant template sensor for cost-optimal EV charging
- Forecast Accuracy Tracking — Forecast vs actual tracking system
- Huawei Entities — Canonical HA entity ID reference
- Troubleshooting Guide — Diagnose and fix common problems: missing data, wrong prices, write failures, battery behaviour
- Quality Checks — Static quality tools and CI configuration
- Planner Backtest Harness — Replay recorded production cycles offline and check them against the planner spec
- Backtest Runbook — Collect a live corpus and actuals, then replay them — the commands to redo a backtest