microgrid 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. microgrid-0.1.0/.gitignore +37 -0
  2. microgrid-0.1.0/CHANGELOG.md +67 -0
  3. microgrid-0.1.0/LICENSE +21 -0
  4. microgrid-0.1.0/PKG-INFO +106 -0
  5. microgrid-0.1.0/README.md +78 -0
  6. microgrid-0.1.0/examples/dataset/engine.toml +3 -0
  7. microgrid-0.1.0/examples/dataset/expected/ledger-2026-10-21.txt +6 -0
  8. microgrid-0.1.0/examples/dataset/expected/live-2026-10-25.txt +49 -0
  9. microgrid-0.1.0/examples/dataset/expected/replay-2026-10-22.txt +21 -0
  10. microgrid-0.1.0/examples/dataset/expected/value-2026-10-22T13-03.txt +290 -0
  11. microgrid-0.1.0/examples/dataset/expected/value-2026-10-25T02-30.txt +275 -0
  12. microgrid-0.1.0/examples/dataset/forecasts/load_forecast.json +1 -0
  13. microgrid-0.1.0/examples/dataset/forecasts/prices.json +1 -0
  14. microgrid-0.1.0/examples/dataset/forecasts/pv_forecast.json +1 -0
  15. microgrid-0.1.0/examples/dataset/manifest.json +70 -0
  16. microgrid-0.1.0/examples/dataset/plant.toml +35 -0
  17. microgrid-0.1.0/examples/dataset/series/battery.json +1 -0
  18. microgrid-0.1.0/examples/dataset/series/battery_first.json +1 -0
  19. microgrid-0.1.0/examples/dataset/series/export_price.json +1 -0
  20. microgrid-0.1.0/examples/dataset/series/grid.json +1 -0
  21. microgrid-0.1.0/examples/dataset/series/heartbeat.json +1 -0
  22. microgrid-0.1.0/examples/dataset/series/house.json +1 -0
  23. microgrid-0.1.0/examples/dataset/series/import_price.json +1 -0
  24. microgrid-0.1.0/examples/dataset/series/inverter.json +1 -0
  25. microgrid-0.1.0/examples/dataset/series/pv.json +1 -0
  26. microgrid-0.1.0/examples/dataset/series/soc.json +1 -0
  27. microgrid-0.1.0/pyproject.toml +123 -0
  28. microgrid-0.1.0/scripts/ci_local.sh +49 -0
  29. microgrid-0.1.0/scripts/griffe_microgrid.py +83 -0
  30. microgrid-0.1.0/scripts/install-hooks.sh +41 -0
  31. microgrid-0.1.0/scripts/make_example_dataset.py +249 -0
  32. microgrid-0.1.0/scripts/make_expected_outputs.py +55 -0
  33. microgrid-0.1.0/scripts/mkdocs_hooks.py +19 -0
  34. microgrid-0.1.0/src/microgrid/__init__.py +12 -0
  35. microgrid-0.1.0/src/microgrid/_checks.py +29 -0
  36. microgrid-0.1.0/src/microgrid/cli/__init__.py +35 -0
  37. microgrid-0.1.0/src/microgrid/cli/check_plant.py +171 -0
  38. microgrid-0.1.0/src/microgrid/cli/dataset.py +463 -0
  39. microgrid-0.1.0/src/microgrid/cli/evaluation.py +375 -0
  40. microgrid-0.1.0/src/microgrid/cli/fit_battery.py +430 -0
  41. microgrid-0.1.0/src/microgrid/cli/history.py +457 -0
  42. microgrid-0.1.0/src/microgrid/cli/inputs.py +248 -0
  43. microgrid-0.1.0/src/microgrid/cli/main.py +572 -0
  44. microgrid-0.1.0/src/microgrid/cli/offline.py +464 -0
  45. microgrid-0.1.0/src/microgrid/cli/replay.py +176 -0
  46. microgrid-0.1.0/src/microgrid/cli/sources/__init__.py +39 -0
  47. microgrid-0.1.0/src/microgrid/cli/sources/config.py +499 -0
  48. microgrid-0.1.0/src/microgrid/cli/sources/emhass.py +122 -0
  49. microgrid-0.1.0/src/microgrid/cli/sources/entity.py +133 -0
  50. microgrid-0.1.0/src/microgrid/cli/sources/fetch.py +119 -0
  51. microgrid-0.1.0/src/microgrid/cli/sources/home_assistant.py +153 -0
  52. microgrid-0.1.0/src/microgrid/cli/sources/predbat.py +99 -0
  53. microgrid-0.1.0/src/microgrid/cli/sources/read.py +254 -0
  54. microgrid-0.1.0/src/microgrid/cli/sources/solcast.py +147 -0
  55. microgrid-0.1.0/src/microgrid/cli/sources/tariffkit.py +147 -0
  56. microgrid-0.1.0/src/microgrid/cli/toml_text.py +75 -0
  57. microgrid-0.1.0/src/microgrid/engine/__init__.py +126 -0
  58. microgrid-0.1.0/src/microgrid/engine/_api.py +1289 -0
  59. microgrid-0.1.0/src/microgrid/engine/_assess.py +77 -0
  60. microgrid-0.1.0/src/microgrid/engine/_engine_config.py +214 -0
  61. microgrid-0.1.0/src/microgrid/engine/_inputs.py +108 -0
  62. microgrid-0.1.0/src/microgrid/engine/_live.py +305 -0
  63. microgrid-0.1.0/src/microgrid/engine/_stored.py +142 -0
  64. microgrid-0.1.0/src/microgrid/engine/_supply.py +138 -0
  65. microgrid-0.1.0/src/microgrid/engine/_surplus.py +146 -0
  66. microgrid-0.1.0/src/microgrid/engine/_timeline.py +40 -0
  67. microgrid-0.1.0/src/microgrid/engine/_value.py +1101 -0
  68. microgrid-0.1.0/src/microgrid/engine/analysis/__init__.py +2 -0
  69. microgrid-0.1.0/src/microgrid/engine/analysis/ground_truth.py +549 -0
  70. microgrid-0.1.0/src/microgrid/engine/analysis/scoring.py +334 -0
  71. microgrid-0.1.0/src/microgrid/engine/extend.py +66 -0
  72. microgrid-0.1.0/src/microgrid/engine/ledger.py +450 -0
  73. microgrid-0.1.0/src/microgrid/engine/py.typed +0 -0
  74. microgrid-0.1.0/src/microgrid/engine/schemas/valuation-2.schema.json +375 -0
  75. microgrid-0.1.0/src/microgrid/engine/series.py +821 -0
  76. microgrid-0.1.0/src/microgrid/engine/testing.py +284 -0
  77. microgrid-0.1.0/src/microgrid/engine/units.py +125 -0
  78. microgrid-0.1.0/src/microgrid/plant/__init__.py +74 -0
  79. microgrid-0.1.0/src/microgrid/plant/_battery.py +235 -0
  80. microgrid-0.1.0/src/microgrid/plant/_config.py +1249 -0
  81. microgrid-0.1.0/src/microgrid/plant/_meters.py +241 -0
  82. microgrid-0.1.0/src/microgrid/plant/_paths.py +1455 -0
  83. microgrid-0.1.0/src/microgrid/plant/_plant.py +456 -0
  84. microgrid-0.1.0/src/microgrid/plant/examples.py +162 -0
  85. microgrid-0.1.0/src/microgrid/plant/flows.py +417 -0
  86. microgrid-0.1.0/src/microgrid/plant/port.py +241 -0
  87. microgrid-0.1.0/src/microgrid/py.typed +0 -0
  88. microgrid-0.1.0/tests/architecture.py +610 -0
  89. microgrid-0.1.0/tests/cli/makeup/engine.toml +6 -0
  90. microgrid-0.1.0/tests/cli/makeup/live-2026-10-25.txt +49 -0
  91. microgrid-0.1.0/tests/cli/makeup/replay-2026-10-22.txt +21 -0
  92. microgrid-0.1.0/tests/cli/makeup/value-2026-10-22T13-03.txt +290 -0
  93. microgrid-0.1.0/tests/cli/makeup/value-2026-10-25T02-30.txt +275 -0
  94. microgrid-0.1.0/tests/cli/test_dataset.py +457 -0
  95. microgrid-0.1.0/tests/cli/test_end_to_end.py +51 -0
  96. microgrid-0.1.0/tests/cli/test_evaluation_properties.py +33 -0
  97. microgrid-0.1.0/tests/cli/test_fit_battery.py +32 -0
  98. microgrid-0.1.0/tests/cli/test_history.py +126 -0
  99. microgrid-0.1.0/tests/cli/test_main.py +444 -0
  100. microgrid-0.1.0/tests/cli/test_sources.py +464 -0
  101. microgrid-0.1.0/tests/engine_fixtures.py +404 -0
  102. microgrid-0.1.0/tests/legacy_dispatch.py +572 -0
  103. microgrid-0.1.0/tests/test_api.py +284 -0
  104. microgrid-0.1.0/tests/test_architecture.py +271 -0
  105. microgrid-0.1.0/tests/test_assess.py +18 -0
  106. microgrid-0.1.0/tests/test_by_source.py +406 -0
  107. microgrid-0.1.0/tests/test_config.py +732 -0
  108. microgrid-0.1.0/tests/test_dc_loads.py +540 -0
  109. microgrid-0.1.0/tests/test_dispatch_parts.py +354 -0
  110. microgrid-0.1.0/tests/test_engine_config.py +342 -0
  111. microgrid-0.1.0/tests/test_examples.py +141 -0
  112. microgrid-0.1.0/tests/test_ground_truth.py +429 -0
  113. microgrid-0.1.0/tests/test_inputs.py +407 -0
  114. microgrid-0.1.0/tests/test_internals.py +89 -0
  115. microgrid-0.1.0/tests/test_ledger.py +506 -0
  116. microgrid-0.1.0/tests/test_ledger_properties.py +114 -0
  117. microgrid-0.1.0/tests/test_limits.py +293 -0
  118. microgrid-0.1.0/tests/test_live_core.py +226 -0
  119. microgrid-0.1.0/tests/test_meters.py +509 -0
  120. microgrid-0.1.0/tests/test_models.py +105 -0
  121. microgrid-0.1.0/tests/test_outputs.py +105 -0
  122. microgrid-0.1.0/tests/test_paths.py +974 -0
  123. microgrid-0.1.0/tests/test_plant.py +314 -0
  124. microgrid-0.1.0/tests/test_plant_properties.py +186 -0
  125. microgrid-0.1.0/tests/test_port.py +841 -0
  126. microgrid-0.1.0/tests/test_projection.py +189 -0
  127. microgrid-0.1.0/tests/test_pv_per_array.py +319 -0
  128. microgrid-0.1.0/tests/test_rule_on_port.py +458 -0
  129. microgrid-0.1.0/tests/test_scoring.py +500 -0
  130. microgrid-0.1.0/tests/test_series.py +484 -0
  131. microgrid-0.1.0/tests/test_stored_cost.py +368 -0
  132. microgrid-0.1.0/tests/test_supply_properties.py +231 -0
  133. microgrid-0.1.0/tests/test_timeline_properties.py +63 -0
  134. microgrid-0.1.0/tests/test_units.py +115 -0
  135. microgrid-0.1.0/tests/test_value.py +367 -0
  136. microgrid-0.1.0/tests/test_without_battery_or_pv.py +544 -0
@@ -0,0 +1,37 @@
1
+ # Secrets: never commit.
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+
6
+ # Python
7
+ __pycache__/
8
+ *.py[cod]
9
+ .venv/
10
+ build/
11
+ dist/
12
+ *.egg-info/
13
+ .coverage
14
+ .coverage.*
15
+ coverage.xml
16
+ htmlcov/
17
+ .pytest_cache/
18
+ .mypy_cache/
19
+ .ruff_cache/
20
+ .hypothesis/
21
+
22
+ # The documentation site's build (mkdocs.yml)
23
+ /site/
24
+
25
+ # Runtime
26
+ /tmp/
27
+ *.log
28
+
29
+ # Agent worktrees (Claude Code)
30
+ .claude/worktrees/
31
+
32
+ # Development records: kept locally, never published (the decisions, the research,
33
+ # their index and notes).
34
+ /docs/adr/
35
+ /docs/research/
36
+ /docs/INDEX.md
37
+ /docs/load-forecast.md
@@ -0,0 +1,67 @@
1
+ # Changelog
2
+
3
+ Each user-visible change, under the release it ships in.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.1.0] - 2026-10-18
8
+
9
+ The first version, under the MIT license.
10
+
11
+ ### Added (library)
12
+
13
+ - **The plant model, `microgrid.plant`.** A plant described as data (`plant/2`): PV
14
+ arrays of either coupling, a battery on its own inverter or on a hybrid's DC bus,
15
+ loads on either bus, the grid's limits, grid-charge and export windows, hold rules
16
+ and the meters. `Plant.project` runs it slot by slot. It stands alone: importing it
17
+ loads none of the price code. Four example plants (`microgrid.plant.examples`), and
18
+ a port for a plant model of your own (`microgrid.plant.port`: `PlantModel`,
19
+ `Storage`), checked by `microgrid.engine.testing.assert_plant_model_contract`.
20
+ - **The price model, `microgrid.engine`.** Marginal prices from inputs given as time
21
+ series (`Inputs`: prices, PV forecast quantiles, the load forecast, the SOC, the
22
+ battery's lots). For each slot it gives:
23
+ - the marginal cost, and the same for a dull day (the PV forecast's p10);
24
+ - the regime, the certainties and the surplus;
25
+ - the supply stack;
26
+ - the value of a PV kWh and of a battery kWh diverted to a flexible load.
27
+
28
+ `Engine.value` gives these as a valuation (`valuation/2`). `Engine.live_session`
29
+ gives a live value between valuations.
30
+ - **A battery kWh** is priced at the running average cost of what the battery holds
31
+ (`Pricing.battery_value = "stored_cost"`), or by the make-up rule (`"replacement"`).
32
+ - **Missing or stale inputs** move values toward the import price, and the valuation
33
+ names them in `degraded`.
34
+ - **Configuration:** `engine/2`.
35
+ - **Series and units** (`microgrid.engine.series`, `microgrid.engine.units`).
36
+ - Forecasts are series of issues, read as a client had them at a moment.
37
+ - Units are converted at the edge.
38
+ - Money is in the prices' currency, never converted, and no name says one.
39
+ - **The battery's lots** (`microgrid.engine.ledger`): what the battery holds by source,
40
+ and what it cost.
41
+ - **Analysis** (`microgrid.engine.analysis`): the plant model scored against its meters,
42
+ and valuations scored against what each kWh realised.
43
+
44
+ ### Added (command)
45
+
46
+ - **`microgrid` on a dataset** (`dataset/1`): `value`, `live`, `replay`, `check-plant`,
47
+ `ledger`, `fit-battery`, `config check` and `schema`. A dataset whose prices name two
48
+ currencies is refused.
49
+ - **`microgrid` on live sources** (`sources/1`, the `sources` extra): `sources`, `now` and
50
+ `fetch`. Each input comes from a provider's Home Assistant integration (TariffKit,
51
+ Solcast, EMHASS, Predbat) or an entity.
52
+ - **The example dataset** (`examples/dataset`): a synthetic week of an example plant in
53
+ Europe/Berlin, across the DST change, with the outputs it is expected to give.
54
+
55
+ ### Added (releases)
56
+
57
+ - **Versions and releases:** semantic versioning, explained beside the formats', the
58
+ API's and the model's versions (`docs/reference/versions.md`); `microgrid --version`
59
+ prints the release with the API (`engine-api/5`) and the model (`pricing/1.3`) it
60
+ carries. Releases are published to
61
+ PyPI from a tag (`vX.Y.Z`).
62
+
63
+ ### Added (documentation)
64
+
65
+ - **The documentation:** the methodology and the library's requirements (R-1 to R-9),
66
+ the concepts, how-to guides and the reference, published with each release at
67
+ `https://eman.github.io/microgrid/`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Emmanuel Levijarvi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.5
2
+ Name: microgrid
3
+ Version: 0.1.0
4
+ Summary: A plant model and marginal energy prices for a solar + battery microgrid: data in, data out
5
+ Project-URL: Homepage, https://github.com/eman/microgrid
6
+ Project-URL: Documentation, https://eman.github.io/microgrid/
7
+ Project-URL: Source, https://github.com/eman/microgrid
8
+ Project-URL: Changelog, https://github.com/eman/microgrid/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/eman/microgrid/issues
10
+ Author-email: Emmanuel Levijarvi <emansl@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: battery,energy,home energy,marginal price,microgrid,solar
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Scientific/Engineering
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.14
24
+ Provides-Extra: sources
25
+ Requires-Dist: httpx>=0.28; extra == 'sources'
26
+ Requires-Dist: pydantic>=2.11; extra == 'sources'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # microgrid
30
+
31
+ `microgrid` is a library that models a solar + battery plant (`microgrid.plant`) and
32
+ produces **marginal energy prices** from it (`microgrid.engine`): what one more kWh
33
+ costs, slot by slot over a horizon, and the value of energy by source. The plant model
34
+ also stands alone, without the price code.
35
+
36
+ - **Data in, data out.** No I/O: a client hands in the plant's configuration
37
+ (`plant/2`) and its inputs as time series (prices, PV and load forecasts, the
38
+ meters), and gets prices, regimes, certainties and surplus back.
39
+ - **The plant model** takes its topology as configuration: PV of either coupling,
40
+ a battery on its own inverter or on a hybrid's DC bus, loads on either bus, the
41
+ grid's limits and charge windows.
42
+
43
+ The documentation is in [`docs/`](https://github.com/eman/microgrid/blob/main/docs/index.md),
44
+ published with each release at `https://eman.github.io/microgrid/`:
45
+ how the prices are made, the concepts, how-to guides and the reference.
46
+
47
+ ## Install
48
+
49
+ ```sh
50
+ pip install microgrid # or: uv add microgrid
51
+ pip install "microgrid[sources]" # with the readers of live sources (Home Assistant)
52
+ ```
53
+
54
+ Python 3.14 or later. Before 1.0 a minor release may change a format, the API or the
55
+ model: pin the minor release you tested with (`microgrid ~= 0.1.0`,
56
+ [Versions](https://github.com/eman/microgrid/blob/main/docs/reference/versions.md)).
57
+
58
+ ## The command
59
+
60
+ `microgrid` (`microgrid.cli`, installed with the library) runs it on a dataset
61
+ (`dataset/1`: a directory of series and the plant's and engine's files), so it needs no
62
+ plant at hand. `microgrid.cli` reads the files; the engine still does no I/O. The example
63
+ dataset (`examples/dataset`) is one synthetic week of the library's example plant in
64
+ Europe/Berlin, the DST change on 2026-10-25 inside it:
65
+
66
+ ```sh
67
+ uv run microgrid value --data examples/dataset --at 2026-10-22T13:00 # one valuation
68
+ uv run microgrid live --data examples/dataset --from 2026-10-22T06:00 --to 2026-10-22T20:00
69
+ uv run microgrid replay --data examples/dataset --from 2026-10-22 --to 2026-10-25
70
+ # valuations scored against the meters
71
+ uv run microgrid check-plant --data examples/dataset --from 2026-10-21 --to 2026-10-27
72
+ # the plant model against its meters
73
+ uv run microgrid ledger --data examples/dataset --from 2026-10-21 --to 2026-10-27
74
+ # the battery's lots and their cost split
75
+ uv run microgrid fit-battery --data examples/dataset --end 2026-10-28 --days 7
76
+ # the battery's conversion, fitted
77
+ uv run microgrid config check --data examples/dataset # its plant/2 and engine/2
78
+ uv run microgrid schema # the outputs' schema
79
+ ```
80
+
81
+ With a `sources/1` file naming a provider per input (any of several, none assumed; the
82
+ `sources` extra, `microgrid[sources]`), it reads live inputs instead of a dataset:
83
+
84
+ ```sh
85
+ uv run microgrid sources --sources sources.toml # what each input is read from, or why not
86
+ uv run microgrid now --sources sources.toml # a valuation now; --save DIR keeps the inputs
87
+ uv run microgrid fetch --sources sources.toml --from 2026-10-01 --to 2026-10-08 --out DIR
88
+ # what was measured, as a dataset
89
+ ```
90
+
91
+ A time without an offset is the plant's local time (an hour that repeats, the first
92
+ time; one the clocks skip is refused).
93
+
94
+ ## Development
95
+
96
+ Python 3.14, uv. See [AGENTS.md](https://github.com/eman/microgrid/blob/main/AGENTS.md) for the rules and conventions.
97
+
98
+ ```sh
99
+ uv sync # .venv with the library and the dev tools
100
+ scripts/install-hooks.sh # pre-push runs the local gate
101
+ scripts/ci_local.sh # ruff, format, mypy --strict, the docs, pytest + coverage
102
+ ```
103
+
104
+ ## License
105
+
106
+ MIT: see [LICENSE](https://github.com/eman/microgrid/blob/main/LICENSE).
@@ -0,0 +1,78 @@
1
+ # microgrid
2
+
3
+ `microgrid` is a library that models a solar + battery plant (`microgrid.plant`) and
4
+ produces **marginal energy prices** from it (`microgrid.engine`): what one more kWh
5
+ costs, slot by slot over a horizon, and the value of energy by source. The plant model
6
+ also stands alone, without the price code.
7
+
8
+ - **Data in, data out.** No I/O: a client hands in the plant's configuration
9
+ (`plant/2`) and its inputs as time series (prices, PV and load forecasts, the
10
+ meters), and gets prices, regimes, certainties and surplus back.
11
+ - **The plant model** takes its topology as configuration: PV of either coupling,
12
+ a battery on its own inverter or on a hybrid's DC bus, loads on either bus, the
13
+ grid's limits and charge windows.
14
+
15
+ The documentation is in [`docs/`](https://github.com/eman/microgrid/blob/main/docs/index.md),
16
+ published with each release at `https://eman.github.io/microgrid/`:
17
+ how the prices are made, the concepts, how-to guides and the reference.
18
+
19
+ ## Install
20
+
21
+ ```sh
22
+ pip install microgrid # or: uv add microgrid
23
+ pip install "microgrid[sources]" # with the readers of live sources (Home Assistant)
24
+ ```
25
+
26
+ Python 3.14 or later. Before 1.0 a minor release may change a format, the API or the
27
+ model: pin the minor release you tested with (`microgrid ~= 0.1.0`,
28
+ [Versions](https://github.com/eman/microgrid/blob/main/docs/reference/versions.md)).
29
+
30
+ ## The command
31
+
32
+ `microgrid` (`microgrid.cli`, installed with the library) runs it on a dataset
33
+ (`dataset/1`: a directory of series and the plant's and engine's files), so it needs no
34
+ plant at hand. `microgrid.cli` reads the files; the engine still does no I/O. The example
35
+ dataset (`examples/dataset`) is one synthetic week of the library's example plant in
36
+ Europe/Berlin, the DST change on 2026-10-25 inside it:
37
+
38
+ ```sh
39
+ uv run microgrid value --data examples/dataset --at 2026-10-22T13:00 # one valuation
40
+ uv run microgrid live --data examples/dataset --from 2026-10-22T06:00 --to 2026-10-22T20:00
41
+ uv run microgrid replay --data examples/dataset --from 2026-10-22 --to 2026-10-25
42
+ # valuations scored against the meters
43
+ uv run microgrid check-plant --data examples/dataset --from 2026-10-21 --to 2026-10-27
44
+ # the plant model against its meters
45
+ uv run microgrid ledger --data examples/dataset --from 2026-10-21 --to 2026-10-27
46
+ # the battery's lots and their cost split
47
+ uv run microgrid fit-battery --data examples/dataset --end 2026-10-28 --days 7
48
+ # the battery's conversion, fitted
49
+ uv run microgrid config check --data examples/dataset # its plant/2 and engine/2
50
+ uv run microgrid schema # the outputs' schema
51
+ ```
52
+
53
+ With a `sources/1` file naming a provider per input (any of several, none assumed; the
54
+ `sources` extra, `microgrid[sources]`), it reads live inputs instead of a dataset:
55
+
56
+ ```sh
57
+ uv run microgrid sources --sources sources.toml # what each input is read from, or why not
58
+ uv run microgrid now --sources sources.toml # a valuation now; --save DIR keeps the inputs
59
+ uv run microgrid fetch --sources sources.toml --from 2026-10-01 --to 2026-10-08 --out DIR
60
+ # what was measured, as a dataset
61
+ ```
62
+
63
+ A time without an offset is the plant's local time (an hour that repeats, the first
64
+ time; one the clocks skip is refused).
65
+
66
+ ## Development
67
+
68
+ Python 3.14, uv. See [AGENTS.md](https://github.com/eman/microgrid/blob/main/AGENTS.md) for the rules and conventions.
69
+
70
+ ```sh
71
+ uv sync # .venv with the library and the dev tools
72
+ scripts/install-hooks.sh # pre-push runs the local gate
73
+ scripts/ci_local.sh # ruff, format, mypy --strict, the docs, pytest + coverage
74
+ ```
75
+
76
+ ## License
77
+
78
+ MIT: see [LICENSE](https://github.com/eman/microgrid/blob/main/LICENSE).
@@ -0,0 +1,3 @@
1
+ # The example dataset's engine (engine/2): prices fetched hourly.
2
+ schema = "engine/2"
3
+ price_max_age_minutes = 60
@@ -0,0 +1,6 @@
1
+ the battery's lots, 2026-10-21 00:00 CEST to 2026-10-28 00:00 CET (1014 slots)
2
+ source charged kWh cost USD to load kWh USD exported kWh held kWh USD USD/kWh
3
+ unknown 0.000 0.000 6.000 0.000 0.000 0.000 0.000 -
4
+ pv 40.497 2.968 34.184 2.505 0.000 6.397 0.469 0.0733
5
+ grid 15.249 2.902 15.249 2.902 0.000 0.000 0.000 -
6
+ unexplained: 0.084 kWh (the meters against the SOC)
@@ -0,0 +1,49 @@
1
+ at marginal import surplus kW regime degraded
2
+ 2026-10-25 01:00:00 CEST 0.1800 0.1800 0.000 import -
3
+ 2026-10-25 01:05:00 CEST 0.1800 0.1800 0.000 import -
4
+ 2026-10-25 01:10:00 CEST 0.1800 0.1800 0.000 import -
5
+ 2026-10-25 01:15:00 CEST 0.1800 0.1800 0.000 import -
6
+ 2026-10-25 01:20:00 CEST 0.1800 0.1800 0.000 import -
7
+ 2026-10-25 01:25:00 CEST 0.1800 0.1800 0.000 import -
8
+ 2026-10-25 01:30:00 CEST 0.1800 0.1800 0.000 import -
9
+ 2026-10-25 01:35:00 CEST 0.1800 0.1800 0.000 import -
10
+ 2026-10-25 01:40:00 CEST 0.1800 0.1800 0.000 import -
11
+ 2026-10-25 01:45:00 CEST 0.1800 0.1800 0.000 import -
12
+ 2026-10-25 01:50:00 CEST 0.1800 0.1800 0.000 import -
13
+ 2026-10-25 01:55:00 CEST 0.1800 0.1800 0.000 import -
14
+ 2026-10-25 02:00:00 CEST 0.1800 0.1800 0.000 import -
15
+ 2026-10-25 02:05:00 CEST 0.1800 0.1800 0.000 import -
16
+ 2026-10-25 02:10:00 CEST 0.1800 0.1800 0.000 import -
17
+ 2026-10-25 02:15:00 CEST 0.1800 0.1800 0.000 import -
18
+ 2026-10-25 02:20:00 CEST 0.1800 0.1800 0.000 import -
19
+ 2026-10-25 02:25:00 CEST 0.1800 0.1800 0.000 import -
20
+ 2026-10-25 02:30:00 CEST 0.1800 0.1800 0.000 import -
21
+ 2026-10-25 02:35:00 CEST 0.1800 0.1800 0.000 import -
22
+ 2026-10-25 02:40:00 CEST 0.1800 0.1800 0.000 import -
23
+ 2026-10-25 02:45:00 CEST 0.1800 0.1800 0.000 import -
24
+ 2026-10-25 02:50:00 CEST 0.1800 0.1800 0.000 import -
25
+ 2026-10-25 02:55:00 CEST 0.1800 0.1800 0.000 import -
26
+ 2026-10-25 02:00:00 CET 0.1800 0.1800 0.000 import -
27
+ 2026-10-25 02:05:00 CET 0.1800 0.1800 0.000 import -
28
+ 2026-10-25 02:10:00 CET 0.1800 0.1800 0.000 import -
29
+ 2026-10-25 02:15:00 CET 0.1800 0.1800 0.000 import -
30
+ 2026-10-25 02:20:00 CET 0.1800 0.1800 0.000 import -
31
+ 2026-10-25 02:25:00 CET 0.1800 0.1800 0.000 import -
32
+ 2026-10-25 02:30:00 CET 0.1800 0.1800 0.000 import -
33
+ 2026-10-25 02:35:00 CET 0.1800 0.1800 0.000 import -
34
+ 2026-10-25 02:40:00 CET 0.1800 0.1800 0.000 import -
35
+ 2026-10-25 02:45:00 CET 0.1800 0.1800 0.000 import -
36
+ 2026-10-25 02:50:00 CET 0.1800 0.1800 0.000 import -
37
+ 2026-10-25 02:55:00 CET 0.1800 0.1800 0.000 import -
38
+ 2026-10-25 03:00:00 CET 0.1800 0.1800 0.000 import -
39
+ 2026-10-25 03:05:00 CET 0.1800 0.1800 0.000 import -
40
+ 2026-10-25 03:10:00 CET 0.1800 0.1800 0.000 import -
41
+ 2026-10-25 03:15:00 CET 0.1800 0.1800 0.000 import -
42
+ 2026-10-25 03:20:00 CET 0.1800 0.1800 0.000 import -
43
+ 2026-10-25 03:25:00 CET 0.1800 0.1800 0.000 import -
44
+ 2026-10-25 03:30:00 CET 0.1800 0.1800 0.000 import -
45
+ 2026-10-25 03:35:00 CET 0.1800 0.1800 0.000 import -
46
+ 2026-10-25 03:40:00 CET 0.1800 0.1800 0.000 import -
47
+ 2026-10-25 03:45:00 CET 0.1800 0.1800 0.000 import -
48
+ 2026-10-25 03:50:00 CET 0.1800 0.1800 0.000 import -
49
+ 2026-10-25 03:55:00 CET 0.1800 0.1800 0.000 import -
@@ -0,0 +1,21 @@
1
+ 48 valuations every 1:00:00 scored, 7053 slots inside the span; fell back (not scored): 0; no prices: 0
2
+
3
+ surplus kW against the PV exported or curtailed, by hours ahead:
4
+ bucket n bias MAE p10 n p10 met
5
+ 0-1h 288 +0.016 0.019 27 100.0%
6
+ 1-3h 558 +0.026 0.029 47 100.0%
7
+ 3-12h 2214 -0.006 0.038 105 100.0%
8
+ 12-48h 3993 -0.020 0.074 126 100.0%
9
+
10
+ marginal cost against the price a kWh realised (USD/kWh), by hours ahead:
11
+ bucket n outcomes bias MAE off
12
+ 0-1h 246 11 -0.0007 0.0043 2.4%
13
+ 1-3h 474 11 -0.0011 0.0047 6.3%
14
+ 3-12h 1836 10 -0.0002 0.0041 16.5%
15
+ 12-48h 2610 6 +0.0022 0.0032 2.9%
16
+
17
+ regime against the metered regime:
18
+ 0-1h 278 of 288 agreed
19
+ 1-3h 540 of 558 agreed
20
+ 3-12h 2170 of 2214 agreed
21
+ 12-48h 3907 of 3993 agreed