Reference¶
Generated from docstrings at build time (DOC-4); never edit by hand.
myenergy ¶
MyEnergyOptimizer: simulate electricity dispatch decided by user-written logic rules.
Built on SmartMDAO. Scope and design: planning/SPEC.md.
adapters ¶
Adapters implementing the ports: Enedis, CSV, weather APIs, tariffs, storage, jobs.
errors ¶
Typed errors of the adapters (PY-9).
AdapterError ¶
Bases: MyEnergyError
An adapter could not read or reach its data.
DataFormatError ¶
Bases: AdapterError
Input data breaks its declared format: the message says where and how.
packs ¶
Tariff packs stored as folders of TOML files.
toml_files ¶
Tariff packs as folders: pack.toml, a rates/ folder and an optional schedules.toml.
pack.toml describes the pack (ADR 0008)::
[pack]
name = "fr-household-vat-study"
title = "French households, with VAT at 5.5 % on everything"
extends = "fr-household" # optional: inherit everything not redefined here
max_kva = 36 # optional
sharing_step_minutes = 30 # optional: step of shared-energy allocation
tags = { country = "FR", purpose = "research" }
[fields.status] # contract fields: allowed values, optional default
values = ["consumer", "collective", "producer-injection"]
default = "consumer"
[network] # off-peak template on the contract's hours...
seasons.high = { dates = "11-01..03-31", peak = "HPH", off_peak = "HCH" }
seasons.low = { dates = "04-01..10-31", peak = "HPB", off_peak = "HCB" }
# ...or year-round: peak = "HP" off_peak = "HC"
# ...or fixed: schedule = "<a schedule of schedules.toml>"
[supply] # supply options, named by a field
field = "supply_option"
options.base = { single = "base" }
options.hp-hc = { peak = "HP", off_peak = "HC" }
[[checks]] # data, not code: errors or warnings
level = "warning"
message = "8 off-peak hours a day is the norm"
when = { fta = ["CU4", "MU4"] }
off_peak_hours = 8
A pack that extends another inherits it: tags and fields merge by name; max_kva,
sharing_step_minutes, network, supply and checks are replaced when given
(checks = [] drops them all); a rate key or a schedule redefined here hides the inherited one.
MAX_BYTES
module-attribute
¶
MAX_BYTES = 256 * 1024
A pack.toml or schedules.toml is small; larger ones are refused (SEC-1).
TomlPackSource ¶
Every pack found in the given folders (each pack is a sub-folder with a pack.toml).
pack(name: str) -> TariffPack
rates(name: str) -> RateSource
The rates of pack name on top of those of the packs it extends.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
DataFormatError
|
a malformed rate file. |
schedules(name: str) -> Mapping[str, Schedule]
The schedules pack name ships, inherited ones included.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
price_book(name: str) -> PriceBook
The price book of pack name on top of those of the packs it extends.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
DataFormatError
|
a malformed |
pricebooks ¶
Price books stored as TOML files.
toml_files ¶
Price books from TOML (ADR 0010).
The same format serves a tariff pack's regulated book (price-book.toml in the pack folder)
and a user's book (a supplier's lines, with the supplier's dated prices in the same file)::
[book]
name = "my-supplier"
remove = [] # lines of the pack's book to drop
inclusion = { network = "included" } # default per layer: itemised | included
settings = { proration_days = 365, rounding = 0.01, vat_on_rounded = true }
[[lines]]
name = "supply.energy"
layer = "supply"
basis = "per_kwh" # fixed | per_kwh | tiered_per_kwh | percent_of | once
flow = "supplied"
schedule = "supply" # network | supply | a named schedule
rate = { component = "supply.energy", selectors = { period = "{period}" } }
vat = "consumption"
[[lines]]
name = "cta"
basis = "percent_of"
of = ["turpe.management", "turpe.metering", "turpe.power"] # or: of_vat = "subscription"
rate = { component = "cta", selectors = { network = "distribution" } }
vat = "subscription"
[sources.my-offer] # a user's dated prices, as in rate files
title = "My supplier's price list"
[[rates]]
component = "supply.energy"
unit = "EUR/kWh"
by = "period"
[[rates.versions]]
from = 2025-08-01
source = "my-offer"
status = "user"
value = { HP = 0.2, HC = 0.15 }
Other line keys: payee, counterparty (shared flows), credit = true (revenue),
inclusion, when = { field = [values] }, and for tiered prices reset and tiers.
Anything malformed is a DataFormatError naming the file.
MAX_BYTES
module-attribute
¶
MAX_BYTES = 512 * 1024
Price books are small; larger inputs are refused (SEC-1).
LoadedBook
dataclass
¶
A price book, the dated prices it carries (if any), and whether it set its settings.
load_price_book ¶
load_price_book(
text: str, *, origin: str = "<text>"
) -> LoadedBook
The price book in text, with its own dated prices if it carries sources/rates.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
invalid TOML, an unknown key, or a book that breaks a rule. |
read_price_book ¶
read_price_book(
path: Path, *, max_bytes: int = MAX_BYTES
) -> LoadedBook
The price book in the TOML file at path.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
the file is too large, not UTF-8, or malformed (see |
with_user_book ¶
with_user_book(
packs: PackSource,
pack: str,
user: LoadedBook | None = None,
) -> tuple[PriceBook, RateSource]
The pack's book with user's on top, and the pack's rates under user's prices.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
PriceBookError
|
|
profiles ¶
Adapters implementing the ProfileSource port.
csv_files ¶
User-supplied profiles as CSV files: strict, small, and never guessed (SEC-1, SEC-2).
Each file has exactly the header timestamp,value. Timestamps are ISO 8601 with a UTC
offset, strictly increasing, one regular step that divides an hour; values are finite numbers in
the declared unit. Anything else is a DataFormatError naming the file and line.
MAX_BYTES
module-attribute
¶
MAX_BYTES = 20 * 1024 * 1024
About ten years of 5-minute values; larger inputs are refused (SEC-1).
CsvUnit ¶
Bases: StrEnum
What the value column holds.
CsvProfile
dataclass
¶
One CSV file and what it means.
CsvProfileSource ¶
A ProfileSource over a fixed list of checked CSV files.
load ¶
load(
profile: CsvProfile, max_bytes: int = MAX_BYTES
) -> tuple[ProfileMeta, TimeSeries]
Read and check one CSV profile; kWh per step becomes kW.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
the file breaks the format (the message says where). |
enedis ¶
Enedis "coefficients de profils" stored as parquet files (one per sub-profile).
Files are named <Category>_<SUBPROFILE>.parquet with a UTC timestamp column labelled by
interval start (SPEC decision 10) and coefficient columns, by default coefficient_ajuste
(decision 11). The resolution changed from 30 to 15 minutes on 2024-10-04 22:00 UTC: each value is
held over its own interval, on the finest native step. Gaps, duplicates and missing values are
errors, never filled (decision 9).
EnedisParquetSource ¶
A ProfileSource over a folder of Enedis parquet files.
Raises:
| Type | Description |
|---|---|
AdapterError
|
the folder does not exist. |
memory ¶
Shapes held in memory: the base of the CSV and synthetic sources, and a reference adapter.
InMemoryProfileSource ¶
A ProfileSource over start-labelled shapes already loaded in memory.
Raises:
| Type | Description |
|---|---|
SeriesError
|
a shape is not dimensionless, or does not sit on its declared coverage. |
UnknownProfileError
|
a profile's key differs from the key it is registered under. |
shape(key: str, grid: TimeGrid) -> TimeSeries
The shape of key resampled onto grid.
Raises:
| Type | Description |
|---|---|
UnknownProfileError
|
no profile |
CoverageError
|
|
plugins ¶
Plugins for the built-in profile sources, registered as entry points like any third party's.
synthetic ¶
Deterministic synthetic shapes for tests, notebooks and quick studies.
Values depend only on the time and the seed, never on the requested window: each UTC day is generated at 5-minute resolution with its own random generator (seed, day), then resampled. Every shape is normalised to a mean of 1 over the reference year 2021, like an Enedis coefficient.
SyntheticProfileSource ¶
Seeded household, clear-sky PV and constant shapes over 2000-2100.
shape(key: str, grid: TimeGrid) -> TimeSeries
The shape key on grid, identical whatever window it is requested for.
Raises:
| Type | Description |
|---|---|
UnknownProfileError
|
no such synthetic profile. |
CoverageError
|
|
rates ¶
Adapters that provide dated rates (RateSource).
layered ¶
Rates in layers: a key found in an upper layer hides the whole history of the lower ones.
A pack that extends another puts its own rates on top: redefining a key (say vat for a tax
study) replaces that key's history; every other key is inherited.
LayeredRateSource ¶
layers[0] on top; each key comes from the first layer that holds it.
catalog() -> Sequence[RateKey]
Every key of every layer, sorted by component then selectors.
history(key: RateKey) -> RateHistory
The history of key from the topmost layer that holds it.
Raises:
| Type | Description |
|---|---|
UnknownRateError
|
no layer holds |
toml_files ¶
Dated rates from TOML files, reviewed like code (ADR 0006).
A file declares the documents it cites under [sources.<id>] and its rates under [[rates]].
Each rate has a component, selectors, the unit as published (converted on load to a canonical
RateUnit) and versions. by names one more selector; a version's value is then a table
over it, for example the four time classes of one network option::
[sources.cre-2025-78]
title = "CRE deliberation n° 2025-78 of 2025-03-13: TURPE 7 HTA-BT from 2025-08-01"
url = "https://www.cre.fr/..."
[[rates]]
component = "turpe.withdrawal.energy"
selectors = { segment = "BT<=36kVA", fta = "CU4" }
unit = "cEUR/kWh"
by = "time_class"
[[rates.versions]]
from = 2025-08-01
source = "cre-2025-78"
status = "official"
value = { HPH = 7.49, HCH = 3.97, HPB = 1.66, HCB = 1.16 }
Versions of one key may come from several files. A version without to lasts until the next
version of the same key starts, or stays open when it is the last. Anything malformed is a
DataFormatError naming the file.
MAX_BYTES
module-attribute
¶
MAX_BYTES = 1024 * 1024
Rate files are small; larger inputs are refused (SEC-1).
UNITS
module-attribute
¶
UNITS: dict[str, tuple[RateUnit, Decimal]] = {
"EUR/year": (RateUnit.EUR_PER_YEAR, Decimal(1)),
"EUR/kVA/year": (RateUnit.EUR_PER_KVA_YEAR, Decimal(1)),
"EUR/month": (RateUnit.EUR_PER_MONTH, Decimal(1)),
"EUR": (RateUnit.EUR, Decimal(1)),
"EUR/kWh": (RateUnit.EUR_PER_KWH, Decimal(1)),
"cEUR/kWh": (RateUnit.EUR_PER_KWH, Decimal("0.01")),
"EUR/MWh": (RateUnit.EUR_PER_KWH, Decimal("0.001")),
"%": (RateUnit.FRACTION, Decimal("0.01")),
}
Published unit → canonical unit and the exact factor between them.
sites ¶
Site descriptions stored as TOML files.
toml_files ¶
Sites from TOML: a contract under a tariff pack, assets by kind, and shared energy (ADR 0009).
One file may describe several sites (a community is several sites)::
[sites.home]
pack = "fr-household"
[sites.home.contract]
subscribed_kva = 6
off_peak = "22:00-06:00" # as printed on a bill
seasonal_off_peak = { low = "02:00-06:00 11:00-15:00" } # optional
fields = { fta = "CU4", supply_option = "hp-hc" }
supply_schedule = "ev-offer" # optional: a schedule shipped by the pack
[[sites.home.assets]]
id = "house"
kind = "consumer"
profile = { source = "synthetic", key = "household", annual_kwh = 3500 }
[[sites.home.assets]]
id = "roof"
kind = "pv"
profile = { source = "synthetic", key = "pv-clear-sky", peak_kwp = 3, yield_kwh_per_kwp = 1100 }
[[sites.home.shares]]
direction = "in"
counterparty = "street-operation"
profile = { source = "csv", key = "allocated", as_measured = true }
A profile gives its source and key, an optional time_shift_minutes, and exactly one scaling:
annual_kwh, peak_kwp with yield_kwh_per_kwp, or as_measured = true. Anything
malformed is a DataFormatError naming the file and the site.
MAX_BYTES
module-attribute
¶
MAX_BYTES = 256 * 1024
Site files are small; larger inputs are refused (SEC-1).
load_sites ¶
load_sites(
text: str, packs: PackSource, *, origin: str = "<text>"
) -> dict[str, SiteSpec]
Every site described in text, by id; contracts are checked against their packs.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
invalid TOML, an unknown field, an unknown pack or schedule, or a site
that breaks a rule (a pack check of level |
Warns:
| Type | Description |
|---|---|
TariffWarning
|
a pack check of level |
read_sites ¶
read_sites(
path: Path,
packs: PackSource,
*,
max_bytes: int = MAX_BYTES,
) -> dict[str, SiteSpec]
Every site in the TOML file at path, by id.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
the file is too large, not UTF-8, or malformed (see |
tariffs ¶
Adapters that read user-defined tariff data (schedules, later price books).
schedules ¶
User-defined time-of-use schedules from TOML.
One file may hold several schedules, each under [schedules.<name>]::
[schedules.ev-offer]
default = "peak" # instants no period claims (optional)
[schedules.ev-offer.seasons] # optional; each date of the year in exactly one season
winter = "11-01..03-31"
summer = { dates = "04-01..10-31", default = "summer-peak" }
[[schedules.ev-offer.periods]]
name = "super-off-peak"
windows = "02:00-06:00" # as printed on a bill; leave out for the whole day
[[schedules.ev-offer.periods]]
name = "off-peak"
windows = "22:00-02:00 06:00-08:00"
days = ["sat", "sun"] # labels of the day calendar (optional)
seasons = ["winter"] # declared seasons (optional)
Anything malformed or ambiguous is a DataFormatError naming the file and the schedule.
MAX_BYTES
module-attribute
¶
MAX_BYTES = 256 * 1024
Schedule files are small; larger inputs are refused (SEC-1).
load_schedules ¶
load_schedules(
text: str, *, origin: str = "<text>"
) -> dict[str, Schedule]
Every schedule in text, by name.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
invalid TOML, an unknown field, or a schedule that breaks a rule. |
read_schedules ¶
read_schedules(
path: Path, *, max_bytes: int = MAX_BYTES
) -> dict[str, Schedule]
Every schedule in the TOML file at path, by name.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
the file is too large, not UTF-8, or malformed (see |
api ¶
HTTP API (FastAPI): schemas, routers and the mapping between schemas and the domain.
bootstrap ¶
Composition root: the only place that wires concrete adapters to ports (ADR 0002, MEO-DI-1).
make_app_container() builds the APP-scoped container: settings, the configured profile
sources, the ProfileResolver, the PackSource (built-in and user tariff packs) and the
SiteResolver (with every installed asset kind) and the PriceBookResolver (with every
installed price basis). Tests pass their own Settings and plugin
registries instead of patching anything (DI-3).
AppProvider ¶
Bases: Provider
APP scope: settings, profiles, tariff packs, sites and price books.
profile_sources ¶
profile_sources(
settings: Settings,
) -> Mapping[str, ProfileSource]
Every configured source, by name; plugins without configuration are left out.
profile_resolver ¶
profile_resolver(
sources: Mapping[str, ProfileSource],
) -> ProfileResolver
The resolver over every configured source.
packs ¶
packs(settings: Settings) -> PackSource
The built-in tariff packs and those in settings.pack_roots.
Raises:
| Type | Description |
|---|---|
DataFormatError
|
a malformed pack, or two packs with one name. |
site_resolver ¶
site_resolver(
profiles: ProfileResolver, packs: PackSource
) -> SiteResolver
Sites resolved with every installed asset kind.
price_book_resolver ¶
price_book_resolver() -> PriceBookResolver
Price books resolved with every installed price basis.
profile_source_plugins ¶
profile_source_plugins() -> Registry[ProfileSourcePlugin]
Every installed profile-source plugin (built-in or third-party).
asset_kind_plugins ¶
asset_kind_plugins() -> Registry[AssetKind]
Every installed asset kind (built-in or third-party).
price_basis_plugins ¶
price_basis_plugins() -> Registry[PriceBasis]
Every installed price basis (built-in or third-party).
make_app_container ¶
make_app_container(
settings: Settings | None = None,
plugins: Registry[ProfileSourcePlugin] | None = None,
asset_kinds: Registry[AssetKind] | None = None,
price_bases: Registry[PriceBasis] | None = None,
) -> Container
The application container (call close() when done).
registry ¶
Typed registries filled from entry points (MEO-PLG-1, MEO-PLG-2).
RegistryError ¶
Bases: MyEnergyError
A plugin is missing, duplicated, or not what its group expects.
Registry ¶
Named plugins of one kind, in registration order.
register ¶
register(name: str, item: T) -> None
get ¶
get(name: str) -> T
The plugin registered under name.
Raises:
| Type | Description |
|---|---|
RegistryError
|
nothing is registered under |
load_entry_points ¶
load_entry_points(
group: str,
kind: str,
check: type[T],
points: Iterable[EntryPoint] | None = None,
) -> Registry[T]
A registry with every plugin of the entry-point group, checked to be a check.
points defaults to the installed entry points of group.
Raises:
| Type | Description |
|---|---|
RegistryError
|
an entry point does not provide a |
settings ¶
Application settings, from the environment or a git-ignored .env file (SEC-7).
Each profile source reads its own options, MYENERGY_SOURCES__<SOURCE>__<OPTION>, for example
MYENERGY_SOURCES__ENEDIS__ROOT=/data/enedis or MYENERGY_SOURCES__SYNTHETIC__SEED=7.
ENEDIS_DB_PATH is also accepted for the Enedis folder. MYENERGY_PACK_ROOTS lists folders
of user-written tariff packs, as JSON ('["/data/packs"]'), searched beside the built-in ones.
Settings ¶
Bases: BaseSettings
Every setting of the application.
sources
class-attribute
instance-attribute
¶
sources: dict[str, dict[str, str | int | float | bool]] = (
Field(default_factory=dict)
)
Environment values arrive parsed as JSON (7 is an int); options() returns text.
pack_roots
class-attribute
instance-attribute
¶
pack_roots: list[Path] = Field(default_factory=list[Path])
Folders of user-written tariff packs (ADR 0008).
options ¶
options(source: str) -> dict[str, str]
Options of one source (names are case-insensitive), with ENEDIS_DB_PATH folded in.
domain ¶
Pure domain model: time grid, series, assets, topology, state, decisions, flows, KPIs.
Imports only the standard library and numpy (MEO-ARC-1). Every value is immutable.
contract ¶
A supply contract, as generic data: power, free fields, off-peak hours and two schedules.
Nothing here is specific to a country or an offer. What the fields mean, which values they may
take, and which rules apply to them come from a tariff pack (myenergy.domain.packs); the
pack also turns the contract into its network and supply schedules. Fields double as rate
selectors: a field fta = "CU4" selects the rates whose key has fta=CU4.
Contract
dataclass
¶
One connection's contract under a tariff pack.
Build it with TariffPack.contract(...), which checks it against the pack's rules and
fills the pack's defaults.
Raises:
| Type | Description |
|---|---|
ContractError
|
no pack, a power that is not positive, or a field repeated. |
fields
class-attribute
instance-attribute
¶
fields: tuple[tuple[str, str], ...] = ()
Free fields, sorted by name (for example fta, status).
off_peak
class-attribute
instance-attribute
¶
off_peak: TimeWindows = NO_WINDOWS
The connection's off-peak hours, in every season without its own.
seasonal_off_peak
class-attribute
instance-attribute
¶
seasonal_off_peak: tuple[tuple[str, TimeWindows], ...] = ()
Off-peak hours of particular seasons of the pack's network schedule.
network
class-attribute
instance-attribute
¶
network: Schedule | None = None
An explicit network schedule, instead of the pack's.
supply
class-attribute
instance-attribute
¶
supply: Schedule | None = None
The supplier's own schedule, instead of the pack's supply option.
field ¶
field(name: str) -> str
off_peak_for ¶
off_peak_for(season: str | None) -> TimeWindows
Off-peak hours of season (its own, else the general ones).
errors ¶
Typed errors of the domain (PY-9); every project error derives from MyEnergyError.
MyEnergyError ¶
Bases: Exception
Root of every error raised by MyEnergyOptimizer.
DomainError ¶
Bases: MyEnergyError
A domain rule was violated.
GridError ¶
Bases: DomainError
A time grid is invalid, or a timestamp does not fit it.
SeriesError ¶
Bases: DomainError
Time series are incompatible, or a series holds invalid values.
CoverageError ¶
Bases: DomainError
A requested period lies outside the data that would have to cover it.
UnknownProfileError ¶
Bases: DomainError
A profile reference names a source or a key that does not exist.
CalibrationError ¶
Bases: DomainError
A profile cannot be scaled as requested (e.g. a window with no energy).
RateError ¶
Bases: DomainError
A rate is missing, ambiguous, unverified, or its history is inconsistent.
UnverifiedRateError ¶
Bases: RateError
A to-verify rate was requested where only official rates are allowed.
ContractError ¶
Bases: DomainError
A supply contract breaks a tariff rule.
SiteError ¶
Bases: DomainError
A site description is inconsistent, or names an asset kind that does not exist.
FlowError ¶
Bases: DomainError
Energy flows break an invariant: negative energy, or more shared than metered.
PriceBookError ¶
Bases: DomainError
A price book is malformed, or cannot be applied to a contract over a period.
problems lists every problem found, so all of them can be fixed at once.
UnknownPackError ¶
Bases: DomainError
No tariff pack has this name.
ScheduleError ¶
Bases: DomainError
A time-of-use schedule is malformed, ambiguous, or leaves instants without a period.
TariffWarning ¶
Bases: UserWarning
A contract departs from the usual regulated values; it is still priced as given.
flows ¶
Energy flows at a site's meter: what bills charge.
The same kWh is priced differently depending on where it comes from and where it goes, so a bill
charges flows, not "consumption". SiteFlows holds, as kWh series on one grid:
importandexport: what the meter records drawing from and injecting into the network;self_consumption: production used on site, never seen by the meter;shared_in/shared_out: the parts of import / export allocated by a sharing scheme to or from a counterparty (an operation, a neighbour);- derived:
supplied= import - shared_in (what the supplier sells) andsold= export - shared_out (what goes to the grid buyer).
Flows describe what meters and sharing schemes measure; what each costs is the price book's business. Built from asset powers, flows depend on the grid's step: comparing production and consumption over 30 minutes hides moments when the site both imported and exported, so coarse steps show more self-consumption than really happens (see notebook 06).
TOLERANCE_KWH
module-attribute
¶
TOLERANCE_KWH = 1e-09
Rounding noise allowed when checking that flows are non-negative and shares fit.
FlowKind ¶
Bases: StrEnum
The flows a price book can charge.
SharedFlow
dataclass
¶
Energy (kWh per step) shared with counterparty in direction.
SiteFlows
dataclass
¶
Metered and shared energy of one site; see the module docstring.
Raises:
| Type | Description |
|---|---|
FlowError
|
a series that is not energy or not on |
counterparties
property
¶
counterparties: Mapping[ShareDirection, tuple[str, ...]]
The counterparties of each direction.
flow ¶
flow(
kind: FlowKind, counterparty: str | None = None
) -> TimeSeries
The kWh series of kind; for shared flows, one counterparty or (None) all.
Raises:
| Type | Description |
|---|---|
FlowError
|
a counterparty for a flow that has none, or an unknown counterparty. |
from_powers
classmethod
¶
from_powers(
site: str,
powers: Sequence[TimeSeries],
shared: Sequence[SharedFlow] = (),
) -> SiteFlows
Flows of a site whose assets have these signed powers (kW: + produces, - consumes).
Production and consumption are compared per step of the grid.
Raises:
| Type | Description |
|---|---|
FlowError
|
a power series that is not kW, or not on one common grid. |
measured
classmethod
¶
measured(
site: str,
imported: TimeSeries,
exported: TimeSeries,
self_consumed: TimeSeries | None = None,
shared: Sequence[SharedFlow] = (),
) -> SiteFlows
Flows as a meter recorded them (kW or kWh); a step may hold both import and export.
Raises:
| Type | Description |
|---|---|
FlowError
|
see the class. |
packs ¶
Tariff packs: user-definable rules that give contract fields their meaning.
A pack says which fields a contract has and which values they may take, the subscribed-power
limit, checks (errors or warnings, written as data), how a contract's off-peak hours become
its network schedule, and which supply options exist. Its rates live beside it (see
myenergy.ports.packs). Packs are data: the built-in French household pack is one of them, and
users write their own, from scratch or by extending another, for another country, a research
scenario or a tax study. Free tags (country, sector, purpose, …) describe a pack.
YEAR_ROUND
module-attribute
¶
YEAR_ROUND = OffPeakTemplate(
(OffPeakSeason(None, "HP", "HC"),)
)
Peak and off-peak all year, on the contract's off-peak hours.
Condition ¶
Condition = tuple[tuple[str, frozenset[str]], ...]
Fields and the values each may take: (("fta", {"CU4", "MU4"}),).
FieldSpec
dataclass
¶
A contract field: its allowed values and its default (None: the field is required).
CheckLevel ¶
ContractCheck
dataclass
¶
When the contract matches when, it must match require and have off_peak_hours.
OffPeakSeason
dataclass
¶
A season of an off-peak template and the names of its peak and off-peak periods.
OffPeakTemplate
dataclass
¶
Builds a schedule from a contract's off-peak hours: peak and off-peak, per season.
SupplyOption
dataclass
¶
A supply option: one period all the time, or peak/off-peak on the contract's hours.
single
class-attribute
instance-attribute
¶
single: str | None = None
The one period of a single-price option.
TariffPack
dataclass
¶
The rules of one tariff framework. Rates are provided alongside, by a PackSource.
tags
class-attribute
instance-attribute
¶
tags: tuple[tuple[str, str], ...] = ()
Free tags, e.g. (("country", "FR"), ("sector", "household")).
network
class-attribute
instance-attribute
¶
network: OffPeakTemplate | Schedule = YEAR_ROUND
How the network schedule is built: a template on the contract's hours, or a fixed one.
supply_field
class-attribute
instance-attribute
¶
supply_field: str | None = None
The field that names the supply option.
sharing_step
class-attribute
instance-attribute
¶
sharing_step: timedelta | None = None
The step at which shared energy is allocated, if the pack says (e.g. 30 minutes).
contract ¶
contract(
*,
subscribed_kva: Decimal | int | str,
fields: Mapping[str, str] | None = None,
off_peak: TimeWindows = NO_WINDOWS,
seasonal_off_peak: Mapping[str, TimeWindows]
| None = None,
network: Schedule | None = None,
supply: Schedule | None = None,
) -> Contract
A contract under this pack, with defaults filled in and every check applied.
Raises:
| Type | Description |
|---|---|
ContractError
|
an unknown or missing field, a value not allowed, a power above the
limit, an unknown season, or a failed check of level |
Warns:
| Type | Description |
|---|---|
TariffWarning
|
a failed check of level |
network_schedule ¶
network_schedule(contract: Contract) -> Schedule
The contract's own network schedule, or the pack's, built from its off-peak hours.
supply_schedule ¶
supply_schedule(contract: Contract) -> Schedule
The contract's own supply schedule, or the one of its supply option.
Raises:
| Type | Description |
|---|---|
ContractError
|
neither is available. |
tagged ¶
tagged(
packs: Iterable[TariffPack], **tags: str
) -> list[TariffPack]
The packs having every tag given, e.g. tagged(packs, country="FR").
pricebooks ¶
Price books: what a bill charges, as data (ADR 0010).
A PriceBook is a list of PriceLine. A line names its basis (how its amount is built:
fixed, per_kwh, tiered_per_kwh, percent_of, once; bases are plugins), the
flow it charges and the schedule whose periods split it, a rate found in dated rate
tables, a VAT category, whether it is a credit (revenue), and whether it is itemised
(added to the total) or included in other prices (shown as "of which", but not added: a
supplier that bundles the network tariff into its own prices).
Rate selectors are templates: {fta} takes the contract field fta, {subscribed_kva}
the subscribed power, {period} each period of the line's schedule, and a basis may add its own
({tier}). One line therefore prices every period without being repeated.
A tariff pack ships the regulated lines; a user's book adds the supplier's lines and prices.
merged puts a user book on a pack book: a line with the same name replaces the pack's, and
remove drops lines by name.
Inclusion ¶
Bases: StrEnum
Whether a line adds to the bill's total.
RateRef
dataclass
¶
A rate component and selector templates ({field}, {period}, ...).
key ¶
key(values: Mapping[str, str]) -> RateKey
The concrete key once every placeholder has a value.
Raises:
| Type | Description |
|---|---|
PriceBookError
|
a placeholder without a value. |
PriceLine
dataclass
¶
One line of a price book; see the module docstring.
schedule
class-attribute
instance-attribute
¶
schedule: str | None = None
network, supply (the contract's schedules) or the name of a schedule.
vat
class-attribute
instance-attribute
¶
vat: str | None = None
The VAT category whose VAT line charges this line, or None.
inclusion
class-attribute
instance-attribute
¶
inclusion: Inclusion | None = None
None: the book's default for the line's layer, else itemised.
params
class-attribute
instance-attribute
¶
params: Mapping[str, object] = field(
default_factory=dict[str, object]
)
Basis-specific parameters (e.g. of for percent_of, tiers for tiered prices).
applies_to ¶
applies_to(contract: Contract) -> bool
Whether the line's when condition holds for contract.
BookSettings
dataclass
¶
How amounts are prorated and rounded.
proration_days
class-attribute
instance-attribute
¶
proration_days: int | None = 365
Fixed charges are prorated by days / this; None: by the actual length of each year.
rounding
class-attribute
instance-attribute
¶
rounding: Decimal = Decimal('0.01')
Each line is rounded to this (euros) at the end.
vat_on_rounded
class-attribute
instance-attribute
¶
vat_on_rounded: bool = True
VAT is computed on rounded lines (else on exact amounts).
PriceBook
dataclass
¶
Named price lines, their layers' default inclusion, and settings.
inclusion
class-attribute
instance-attribute
¶
inclusion: tuple[tuple[str, Inclusion], ...] = ()
Default inclusion per layer, e.g. (("network", Inclusion.INCLUDED),).
remove
class-attribute
instance-attribute
¶
remove: tuple[str, ...] = ()
Lines of the book underneath to drop when this book is merged onto it.
line ¶
line(name: str) -> PriceLine
inclusion_of ¶
inclusion_of(line: PriceLine) -> Inclusion
The line's own inclusion, else its layer's default, else itemised.
merged ¶
merged(
user: PriceBook, *, settings: BookSettings | None = None
) -> PriceBook
user on top of this book: same-named lines replaced, user.remove dropped.
Layer defaults merge (user wins). Settings are settings when given, else this
book's.
Raises:
| Type | Description |
|---|---|
PriceBookError
|
|
profiles ¶
Profiles: where a load or production curve comes from, and how it becomes kilowatts.
A shape is a dimensionless curve whose mean is about 1 over a year (an Enedis coefficient, a synthetic curve). A scaling turns it into power with one constant factor, so the same profile serves any simulation period and any step (SPEC decision 7):
Nominal(annual_kwh): factor = annual energy / 8760 h; year-to-year variation in the data is kept, as in reality;Calibrated(energy_kwh, window): factor = energy / energy of the shape overwindow, which may be any period (a billing year starting in November, a month, a week);PVSystem(peak_kwp, specific_yield_kwh_per_kwp): a nominal annual energy, until a PV API computes production directly;AsMeasured(): the source holds kW already (factor 1).
Shapes take Nominal, PVSystem or Calibrated; measured kW takes AsMeasured or
Calibrated. Any other pairing is refused, never guessed.
HOURS_PER_NOMINAL_YEAR
module-attribute
¶
HOURS_PER_NOMINAL_YEAR = 8760.0
365 days. A leap year of data integrates to about 0.27 % more energy, which is kept.
ProfileSpec ¶
ProfileSpec = Shaped
Every way to describe a profile; PV APIs will add a computed form (SPEC §6).
ProfileKind ¶
Bases: StrEnum
Whether a profile draws or produces energy.
ProfileUnit ¶
Bases: StrEnum
What a source's values are: a dimensionless shape to scale, or measured power.
TimestampLabel ¶
Bases: StrEnum
Which end of its interval a source's timestamps name (Enedis: the start).
ProfileRef
dataclass
¶
A profile in a source, optionally shifted in time on purpose (SPEC decision 10).
A positive time_shift moves the curve later: the value used at t is the source's value
at t - time_shift. It must be a whole number of the grid's steps when used.
Raises:
| Type | Description |
|---|---|
UnknownProfileError
|
an empty source or key name. |
ProfileMeta
dataclass
¶
What a source says about one of its profiles.
coverage
instance-attribute
¶
coverage: TimeGrid
The period the data covers, on its finest native step.
Nominal
dataclass
¶
annual_kwh per nominal year (8760 h).
Raises:
| Type | Description |
|---|---|
CalibrationError
|
a non-positive energy. |
Calibrated
dataclass
¶
energy_kwh over exactly window.
Raises:
| Type | Description |
|---|---|
CalibrationError
|
a non-positive energy. |
kw_per_unit ¶
kw_per_unit(shape_unit_hours: float) -> float
Kilowatts per unit of shape, given the shape's integral over the window (unit-hours).
Raises:
| Type | Description |
|---|---|
CalibrationError
|
the shape has no positive energy over the window. |
PVSystem
dataclass
¶
A PV array of peak_kwp producing specific_yield_kwh_per_kwp per nominal year.
Raises:
| Type | Description |
|---|---|
CalibrationError
|
a non-positive peak power or yield. |
AsMeasured
dataclass
¶
The source already holds kW (measured data, e.g. a meter export): factor 1.
Shaped
dataclass
¶
A profile made of a shape and a scaling.
rates ¶
Dated rates: every regulated price is data with a validity period, a source and a status.
A RateKey names what is priced (a component and its selectors, such as the network option or
the time class); a RateHistory holds the successive RateVersion of one key. Values are
Decimal in canonical units, so a rate reads exactly as published. Lookups are exact: a date
outside every version is an error, never the nearest value (SPEC decision 9, ADR 0006).
RateUnit ¶
RateStatus ¶
Bases: StrEnum
How far a value can be trusted.
OFFICIAL
class-attribute
instance-attribute
¶
OFFICIAL = 'official'
Read in the regulator's, the operator's or the law's own publication.
TO_VERIFY
class-attribute
instance-attribute
¶
TO_VERIFY = 'to-verify'
From a secondary source or an agent; refused in bills unless explicitly allowed.
USER
class-attribute
instance-attribute
¶
USER = 'user'
Entered by the user (a supplier's prices from a bill or an offer); usable in bills.
RateKey
dataclass
¶
What is priced: a component and the selectors that pick one value of it.
of
classmethod
¶
of(component: str, **selectors: str) -> RateKey
RateKey.of("turpe.withdrawal.power", segment="BT<=36kVA", fta="CU4").
RateVersion
dataclass
¶
One value of a rate over [valid_from, valid_to); valid_to=None means still valid.
RateHistory ¶
The successive versions of one rate: one unit, no overlap; gaps are allowed.
between ¶
between(
start: date, end: date, *, allow_to_verify: bool = False
) -> tuple[RateVersion, ...]
The versions that cover [start, end) without a gap, oldest first.
Raises:
| Type | Description |
|---|---|
CoverageError
|
a day of |
UnverifiedRateError
|
a |
on ¶
on(
day: date, *, allow_to_verify: bool = False
) -> RateVersion
The version valid on day.
Raises:
| Type | Description |
|---|---|
CoverageError
|
no version covers |
UnverifiedRateError
|
the version is |
schedules ¶
Time-of-use schedules: user-defined periods by time of day, day type and season.
A Schedule names periods ("HC", "super-off-peak", "HPH", …) and says, with
PeriodRule values, which instants belong to each: daily time windows, optionally only on some
day types ("sat", "weekend", or labels such as a Tempo colour from a DayCalendar) and
in some seasons. Whatever no rule claims goes to the season's default period, else the schedule's
default. Every instant belongs to exactly one period: two rules that claim the same instant,
or an instant that nothing claims, are errors that name the instant.
Rules are applied per instant: a window is laid on every local day, then kept only where the
instant's own local date has the rule's day type and season. So 22:00-06:00 limited to
"sat" covers Saturday 00:00-06:00 and 22:00-24:00.
weights(grid) gives the share of each step in each period. Shares are exact: a step that
straddles a window edge is split by time, so energy split by period adds up to the total on any
grid. Shares are worked out in UTC, so daylight-saving days need no special case: a window
02:00-07:00 lasts 4 real hours on the spring day and 6 on the autumn day. A wall-clock time that
does not exist (02:30 on the spring day) is read with the offset in force before the change, as
Python does (PEP 495).
TimeWindow
dataclass
¶
From start to end on the wall clock; it may run past midnight.
TimeWindows
dataclass
¶
Daily windows that do not overlap, for example a connection's off-peak hours.
parse
classmethod
¶
parse(text: str) -> TimeWindows
Read windows as written on a contract or a bill.
"02:00-07:00 12:30-15:30", "2H00-7H00 12H30-15H30" and "22h30-6h30" are all
accepted; spaces, commas, ; and / between windows are ignored. "" is no window.
Raises:
| Type | Description |
|---|---|
ScheduleError
|
unreadable text, or an hour or minute out of range. |
Season
dataclass
¶
Local dates from first to last ((month, day), inclusive; may wrap the year).
default
class-attribute
instance-attribute
¶
default: str | None = None
The period of instants in this season that no rule claims (else the schedule's default).
parse
classmethod
¶
parse(
name: str, text: str, default: str | None = None
) -> Season
Season.parse("winter", "11-01..03-31").
Raises:
| Type | Description |
|---|---|
ScheduleError
|
the text is not |
DayCalendar ¶
WeekdayCalendar ¶
"mon" … "sun", plus "weekday" or "weekend".
labels ¶
labels(day: date) -> frozenset[str]
The weekday name and whether it is a weekday or the weekend.
PeriodRule
dataclass
¶
Instants of period: in windows (all day if None), on days, in seasons.
PeriodWeights
dataclass
¶
The share of each step in each period of a schedule; every row sums to 1.
shares
class-attribute
instance-attribute
¶
shares: NDArray[float64] = field(repr=False)
Shape (len(grid), len(periods)), columns in periods order.
share ¶
share(period: str) -> TimeSeries
The share of each step in period (dimensionless, 0 to 1).
Raises:
| Type | Description |
|---|---|
ScheduleError
|
the schedule has no such period. |
split ¶
split(series: TimeSeries) -> Mapping[str, float]
Energy (kWh) of a power or energy series in each period; the values add up to its total.
Raises:
| Type | Description |
|---|---|
SeriesError
|
the series is on another grid, or is neither power nor energy. |
Schedule
dataclass
¶
Named periods defined by rules, seasons and defaults; see the module docstring.
default
class-attribute
instance-attribute
¶
default: str | None = None
The period of instants no rule claims, in seasons without their own default.
seasons
class-attribute
instance-attribute
¶
seasons: tuple[Season, ...] = ()
When given, every date of the year must fall in exactly one season.
weights ¶
weights(
grid: TimeGrid, calendar: DayCalendar = WEEKDAYS
) -> PeriodWeights
The share of each step of grid in each period, on the grid's wall clock.
calendar labels the days (default: weekday names); a Tempo-like offer passes a
calendar that also gives each day its colour.
Raises:
| Type | Description |
|---|---|
ScheduleError
|
a rule uses a day label the calendar does not know, two rules claim the same instant, or an instant has no period. |
series ¶
Time series: one value per step of a grid, tagged with what the value measures.
Profiles are held as average power over the step (POWER_KW): unlike energy, this does not
depend on the step length, which is what lets one profile serve any grid. Converting to energy
multiplies by the step length. Resampling uses one overlap-weighted method for any pair of grids:
intensive quantities (power, price, shapes) become time-weighted means, and energy is summed or
split in proportion to the overlap, so it is conserved exactly.
Quantity ¶
Bases: StrEnum
What a series measures, which decides how it combines and resamples.
extensive
property
¶
extensive: bool
True when values add up over time (energy), false for rates and shapes.
TimeSeries
dataclass
¶
Read-only values on a grid.
Raises:
| Type | Description |
|---|---|
SeriesError
|
the values do not match the grid, or are not finite numbers. |
constant
classmethod
¶
constant(
grid: TimeGrid, value: float, quantity: Quantity
) -> Self
The same value on every step.
scaled ¶
scaled(
factor: float, quantity: Quantity | None = None
) -> TimeSeries
Multiply by factor; quantity re-tags the result (shape times kW is power).
energy ¶
energy() -> TimeSeries
Energy per step (kWh) from average power (kW times step hours).
Raises:
| Type | Description |
|---|---|
SeriesError
|
the series is not power. |
power ¶
power() -> TimeSeries
Average power per step (kW) from energy per step.
Raises:
| Type | Description |
|---|---|
SeriesError
|
the series is not energy. |
total ¶
total() -> float
Sum over the grid (energy only: summing power or prices has no meaning).
Raises:
| Type | Description |
|---|---|
SeriesError
|
the series is not energy. |
time_mean ¶
time_mean() -> float
Time-weighted mean over the grid (rates and shapes; all steps have equal length).
Raises:
| Type | Description |
|---|---|
SeriesError
|
the series is energy (use |
resample ¶
resample(grid: TimeGrid) -> TimeSeries
These values on another grid, which must lie within this series' range.
Raises:
| Type | Description |
|---|---|
CoverageError
|
|
isclose ¶
isclose(
other: TimeSeries,
*,
rel: float = 1e-12,
abs_: float = 1e-12,
) -> bool
Same grid, same quantity, and values equal within tolerance.
sites ¶
Sites: what is installed behind one grid connection, described as data.
A SiteSpec lists assets by id and kind (consumer, pv, later battery,
ev, ...). What a kind does is a plugin (myenergy.ports.assets.AssetKind); the flows only
look at its role: a source produces, a sink consumes, a storage does either. Adding a
household, an EV or a battery is one more entry in a site file, never a change to the flow or
bill code (ADR 0009).
AssetRole ¶
ShareDirection ¶
Bases: StrEnum
Whether shared energy comes to the site or leaves it.
AssetSpec
dataclass
¶
One asset: an id unique in its site, a kind, and what the kind needs to compute its power.
options
class-attribute
instance-attribute
¶
options: tuple[tuple[str, str], ...] = ()
Free options for the kind's plugin, as text.
ShareSpec
dataclass
¶
Energy shared with a counterparty (an operation, a neighbour), as a power profile.
SiteSpec
dataclass
¶
A grid connection: its contract, its assets and the energy it shares.
time ¶
Time grids: the half-open UTC ranges, split into equal steps, that every series lives on.
A grid is held in UTC, so daylight-saving changes cannot break it: a local day simply has 23 or 25
hours. The grid's timezone is only used for wall-clock logic (seasons, peak hours). Steps divide
an hour (SPEC decision 8), and the start is aligned on the step, so grids of the same step line up.
TimeGrid
dataclass
¶
[start, end) in UTC, divided into step-long intervals labelled by their start.
Raises:
| Type | Description |
|---|---|
GridError
|
naive or misaligned timestamps, an unsupported step, or an empty range. |
covering
classmethod
¶
covering(
start: datetime, end: datetime, step: timedelta
) -> Self
The grid from start to end in the default timezone (convenience).
timestamp ¶
timestamp(index: int) -> datetime
Start of step index (negative indices count from the end), in UTC.
Raises:
| Type | Description |
|---|---|
GridError
|
the index is outside the grid. |
index ¶
index(moment: datetime) -> int
The step that starts at moment.
Raises:
| Type | Description |
|---|---|
GridError
|
|
edges_seconds ¶
edges_seconds() -> npt.NDArray[np.float64]
The len + 1 step edges, in seconds since start (for resampling).
contains ¶
contains(other: TimeGrid) -> bool
True when other's range lies within this grid's range (any step).
engine ¶
Simulation engine: the time loop, the information boundary and the SmartMDAO step pipeline.
assets ¶
Built-in asset kinds, registered as entry points like any third party's (ADR 0009).
ProfiledKind ¶
pricebases ¶
Built-in price bases, registered as entry points like any third party's (ADR 0010).
FIXED
module-attribute
¶
FIXED = _Simple(
"fixed",
frozenset(
{
RateUnit.EUR_PER_YEAR,
RateUnit.EUR_PER_KVA_YEAR,
RateUnit.EUR_PER_MONTH,
}
),
needs_flow=False,
)
A yearly or monthly charge (per kVA if the rate is per kVA), prorated over the bill period.
PER_KWH
module-attribute
¶
PER_KWH = _Simple(
"per_kwh",
frozenset({RateUnit.EUR_PER_KWH}),
needs_flow=True,
)
The line's flow in each period, times that period's rate.
ONCE
module-attribute
¶
ONCE = _Simple(
"once", frozenset({RateUnit.EUR}), needs_flow=False
)
A one-off amount, charged once per bill.
TieredBasis ¶
Price per kWh by tranche of energy accumulated over a reset period ({tier}).
PercentOfBasis ¶
A share of other lines.
of names lines (itemised or included); of_vat takes every itemised line of a VAT
category.
pricing ¶
Resolve a price book against a contract and a bill period (ADR 0010).
Resolution decides which lines apply (when), finds each line's schedule periods and concrete
rate keys, checks that every rate covers the whole period with the right unit and status, orders
lines so that a percentage comes after what it is a percentage of, and reports every problem
at once. Amounts are computed from a resolved book (M2 task 5).
ResolvedRate
dataclass
¶
The rate of one combination of placeholder values (a period, a tier, ...).
ResolvedLine
dataclass
¶
A line ready to be computed.
boundaries
instance-attribute
¶
boundaries: tuple[date, ...]
Dates inside the bill period where one of the line's rates changes.
ResolvedBook
dataclass
¶
Every applicable line of a book, resolved for one contract and period, in compute order.
line ¶
line(name: str) -> ResolvedLine
PricingContext
dataclass
¶
What a price book is resolved against: a contract under a pack, its rates, a period.
PriceBookResolver ¶
Resolves price books with the registered price bases.
resolve ¶
resolve(
book: PriceBook, context: PricingContext
) -> ResolvedBook
The applicable lines of book for the context's contract and period, in order.
Raises:
| Type | Description |
|---|---|
PriceBookError
|
every problem found: an unknown basis or schedule, bad parameters, a missing flow, a rate that is missing, of the wrong unit, not covering the period or still to verify, an unknown or circular line reference, an empty period. |
profiles ¶
Turn profile specs into kilowatt series, from whichever source holds the shape.
ProfileResolver ¶
Resolve ProfileSpec values against the registered profile sources.
shape ¶
shape(ref: ProfileRef, grid: TimeGrid) -> TimeSeries
The shape of ref on grid, with its time_shift applied.
meta ¶
meta(ref: ProfileRef) -> ProfileMeta
What the source says about ref.
Raises:
| Type | Description |
|---|---|
UnknownProfileError
|
the source has no such profile. |
power ¶
power(spec: ProfileSpec, grid: TimeGrid) -> TimeSeries
Average power (kW) of spec on grid.
Raises:
| Type | Description |
|---|---|
CalibrationError
|
the scaling does not fit the profile's unit. |
sites ¶
Resolve a site description into asset powers and meter flows (ADR 0009).
The resolver knows asset kinds only through their plugins and roles, so a new kind never changes
this module. Flows are built per step of the requested grid (see myenergy.domain.flows).
SiteResolver ¶
Asset powers and flows of sites, from the registered asset kinds.
powers ¶
powers(
site: SiteSpec, grid: TimeGrid
) -> dict[str, TimeSeries]
Each asset's signed power on grid (kW: + produces, - consumes), by asset id.
Raises:
| Type | Description |
|---|---|
SiteError
|
an unknown kind, or a kind that returns something other than kW on
|
flows ¶
flows(site: SiteSpec, grid: TimeGrid) -> SiteFlows
The site's meter flows on grid, its shares included.
Warns:
| Type | Description |
|---|---|
TariffWarning
|
the site shares energy and |
Raises:
| Type | Description |
|---|---|
SiteError
|
see |
FlowError
|
shares above import or export, or other broken flow invariants. |
policies ¶
Dispatch policies: baseline, rule-based (SmartMDAO RuleDiscipline), forecast, MPC.
ports ¶
Ports: the Protocol interfaces every external capability is reached through.
Profile and irradiance sources, tariffs, forecasters, dispatch policies, observers, repositories, job runners and the clock (SPEC §8).
assets ¶
Asset kinds: what an asset of a given kind does, as a plugin (ADR 0009).
A site file names assets by kind (consumer, pv, ...). Each kind is an AssetKind
registered in the myenergy.asset_kinds entry-point group, built-ins included, so a third
party adds a kind (an EV, a heat pump, a battery) without editing this package.
PowerProfiles ¶
Bases: Protocol
Turns profile specs into kW series (myenergy.engine.profiles.ProfileResolver).
AssetKind ¶
Bases: Protocol
One kind of asset.
power ¶
power(
asset: AssetSpec,
grid: TimeGrid,
profiles: PowerProfiles,
) -> TimeSeries
The asset's power on grid (kW).
Non-negative for a source or a sink; signed for a storage (positive when it returns energy).
Raises:
| Type | Description |
|---|---|
SiteError
|
the asset lacks what the kind needs (a profile, an option). |
packs ¶
The PackSource port: where tariff packs, their rates and their schedules come from.
Folders of TOML files today (built-in and user-written); a database later, for packs whose rates an agent maintains (ADR 0006, ADR 0008).
PackSource ¶
Bases: Protocol
A store of tariff packs.
catalog ¶
catalog() -> Sequence[TariffPack]
Every pack, sorted by name (filter by tag with myenergy.domain.packs.tagged).
pack ¶
pack(name: str) -> TariffPack
The pack called name.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
rates ¶
rates(name: str) -> RateSource
The rates of pack name, those it inherits included.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
schedules ¶
schedules(name: str) -> Mapping[str, Schedule]
The named schedules a pack ships (e.g. example offers), those it inherits included.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
price_book ¶
price_book(name: str) -> PriceBook
The regulated price book of pack name, merged with those it extends.
Raises:
| Type | Description |
|---|---|
UnknownPackError
|
no such pack. |
plugins ¶
Plugins: how a data source joins the application without editing it (MEO-PLG-1, MEO-PLG-2).
Built-in and third-party sources register the same way, through the myenergy.profile_sources
entry-point group, each pointing at an object that satisfies ProfileSourcePlugin. Tariff packs
need no code: they are folders of data (MYENERGY_PACK_ROOTS).
ProfileSourcePlugin ¶
Bases: Protocol
Builds one ProfileSource from plain text options (from settings).
pricing ¶
Price bases: how a price line's amount is built, as plugins (ADR 0010).
Built-in bases (fixed, per_kwh, tiered_per_kwh, percent_of, once) register in
the myenergy.price_bases entry-point group like any third party's, so a new kind of charge
(for example a power-overrun charge for businesses) needs no change to the core.
PriceBasis ¶
Bases: Protocol
One way of building a line's amount.
units
property
¶
units: frozenset[RateUnit]
The rate units this basis accepts (empty: it takes no rate).
problems ¶
problems(line: PriceLine) -> list[str]
What is wrong with the line's basis parameters (empty when nothing is).
expansions ¶
expansions(
line: PriceLine,
) -> Mapping[str, tuple[str, ...]]
Extra placeholders this basis fills in rate selectors, with their values.
depends_on ¶
depends_on(
line: PriceLine, book: PriceBook
) -> tuple[str, ...]
Names of the lines whose amounts this line is computed from.
profiles ¶
The port through which profile shapes are read (MEO-PLG-1, PRT-1).
ProfileSource ¶
Bases: Protocol
A provider of dimensionless shapes (Enedis, CSV, synthetic…).
Contract (tests/contract/test_profile_sources.py):
catalog()lists every profile, with keys unique within the source;shape(key, grid)returns aDIMENSIONLESSseries on exactlygrid, labelled by interval start whatever the native convention;- a
gridoutside the profile's coverage raisesCoverageError; - an unknown key raises
UnknownProfileError.
rates ¶
The RateSource port: where dated rates come from (ADR 0006).
Packaged TOML tables now; a database filled by the billing-data agent later. Callers only ask for the history of a key, so the storage can change without touching the bill engine.
RateSource ¶
Bases: Protocol
A store of dated rates.