mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-10-09 16:06:40 +00:00
feat(optimization): split the control horizon from the forecast tail
The optimizer treated the end of `optimization.horizon_hours` as the end of the world: energy left in the battery there was worth a single configured price per kWh, so it either dumped the battery into the last hours or hoarded it, depending on that one number. The horizon is now two spans. `horizon_hours` still receives every control command. The new `optimization.tail_horizon_hours` (default 48 h) is a pure lookahead that never produces a command. In AUTO terminal-value mode a deterministic dynamic program solves that tail backwards on a 101-point SoC grid using the production battery and inverter models - SoC bounds, power caps, conversion losses, configured charge and export rates, direct-marketing permission and LCOS on delivered DC energy - and the existing AUTO proxy supplies the continuation value at the tail end. Genetic fitness reads the resulting curve. `tail_horizon_hours: 0` restores the plain proxy at the control end, FIXED is unchanged. The forecast budget is reported, never enforced by refusal: a tail that does not fit is shortened to what the forecast covers and reported as `effective_tail_hours`, and a control horizon that does not fit is warned about at configuration time and rejected by the optimizer at run time, which knows which series ran out. `prediction.hours` defaults to 72 so the new defaults fit out of the box; existing shorter configurations keep starting. Control arrays and warm-start genomes now begin at the run timestamp rather than midnight, flagged by `controls_start_at_now` so the adapters still read older solutions. `forecast_interval_seconds` declares the resolution of shortened native quarter-hour inputs. Required forecasts are no longer silently replaced by demo providers. A missing PV, price, load, feed-in or weather forecast used to rewrite the configured provider and retry, so a run could quietly optimize against invented data. Missing values now stay missing, and provider values are held only within their own source interval instead of being extended indefinitely. Also fixes a config update that could leave EOS half-updated: the merged candidate is validated before the singleton is reinitialized. Four provider tests that hard-coded the old 48 h prediction default are rewritten to derive their expectations from the configured horizon.
This commit is contained in:
@@ -13,9 +13,10 @@
|
||||
| horizon_hours | `EOS_OPTIMIZATION__HORIZON_HOURS` | `int` | `rw` | `24` | The general time window within which the energy optimization goal shall be achieved [h]. Defaults to 24 hours. |
|
||||
| interval | `EOS_OPTIMIZATION__INTERVAL` | `int` | `rw` | `3600` | The optimization interval (slot length) [sec]. The genetic optimizer supports 3600 (1 hour) and 900 (15 min); other values fall back to 3600. Defaults to 3600 seconds (1 hour). |
|
||||
| keys | | `list[str]` | `ro` | `N/A` | The keys of the solution. |
|
||||
| tail_horizon_hours | `EOS_OPTIMIZATION__TAIL_HORIZON_HOURS` | `int` | `rw` | `48` | Forecast lookahead after the control horizon [h]. No tail commands are issued. Set 0 to disable. |
|
||||
| terminal_value_euro_per_kwh | `EOS_OPTIMIZATION__TERMINAL_VALUE_EURO_PER_KWH` | `float` | `rw` | `0.0` | Value assigned to usable battery energy remaining at the end of the optimization horizon [EUR/kWh]. This terminal value is independent of the battery LCOS. Only used with terminal_value_mode = FIXED. Defaults to 0 EUR/kWh. |
|
||||
| terminal_value_mode | `EOS_OPTIMIZATION__TERMINAL_VALUE_MODE` | `<enum 'TerminalValueMode'>` | `rw` | `AUTO` | How to value the energy left in the battery at the end of the optimization horizon. AUTO derives a concave value curve from the trailing horizon window and needs no configuration; FIXED uses 'terminal_value_euro_per_kwh'. Defaults to AUTO. |
|
||||
| terminal_value_window_hours | `EOS_OPTIMIZATION__TERMINAL_VALUE_WINDOW_HOURS` | `int` | `rw` | `24` | Length of the trailing horizon window the AUTO terminal value curve is derived from [h]. One day covers a full load and PV cycle. Defaults to 24 hours. |
|
||||
| terminal_value_mode | `EOS_OPTIMIZATION__TERMINAL_VALUE_MODE` | `<enum 'TerminalValueMode'>` | `rw` | `AUTO` | How to value the energy left in the battery at the end of the control horizon. AUTO solves the forecast tail with an AUTO continuation proxy at its end (or only the proxy if tail is zero); FIXED uses 'terminal_value_euro_per_kwh'. Defaults to AUTO. |
|
||||
| terminal_value_window_hours | `EOS_OPTIMIZATION__TERMINAL_VALUE_WINDOW_HOURS` | `int` | `rw` | `24` | Length of the trailing window at the effective tail end the AUTO continuation curve is derived from [h]. One day covers a full load and PV cycle. Defaults to 24 hours. |
|
||||
| visualize_pdf | `EOS_OPTIMIZATION__VISUALIZE_PDF` | `bool` | `rw` | `True` | Generate the PDF visualization after each optimization run. Disable for headless setups (e.g. Node-RED integration) to save several seconds per run. Defaults to True. |
|
||||
:::
|
||||
<!-- pyml enable line-length -->
|
||||
@@ -28,6 +29,7 @@
|
||||
```json
|
||||
{
|
||||
"optimization": {
|
||||
"tail_horizon_hours": 48,
|
||||
"horizon_hours": 24,
|
||||
"interval": 3600,
|
||||
"algorithm": "GENETIC",
|
||||
@@ -56,6 +58,7 @@
|
||||
```json
|
||||
{
|
||||
"optimization": {
|
||||
"tail_horizon_hours": 48,
|
||||
"horizon_hours": 24,
|
||||
"interval": 3600,
|
||||
"algorithm": "GENETIC",
|
||||
|
||||
Reference in New Issue
Block a user