pub struct SettleInput {Show 28 fields
pub scheme: SettlementScheme,
pub tariff_source: TariffSource,
pub settlement_type: SettlementType,
pub einspeisemenge_kwh: Option<Decimal>,
pub marktwert_ct_kwh: Option<Decimal>,
pub sanktion: Option<SanktionAlt>,
pub pflichtverstoss: Vec<Pflichtverstoss>,
pub aw_reductions: AwReductionContext,
pub negative_price_quarter_hours: Option<u64>,
pub einspeisemanagement_kwh: Option<Decimal>,
pub biomasse: Option<BiomassSettlementData>,
pub billing_days_fraction: Option<Decimal>,
pub kwh_during_negative_epex: Option<Decimal>,
pub inbetriebnahme: Option<Date>,
pub inbetriebnahme_typ: InbetriebnahmeTyp,
pub leistung_kwp: Option<Decimal>,
pub foerderendedatum: Option<Date>,
pub billing_date: Option<Date>,
pub capacity_blocks: Vec<CapacityBlock>,
pub eeg_gesetz: EegGesetz,
pub erzeugungsart: Option<ErzeugungsArt>,
pub aw_is_gross: bool,
pub biogas_sect44b_eligible_kwh: Option<Decimal>,
pub has_imesys: bool,
pub marktwert_kategorie: Option<MarktpreisKategorie>,
pub sect51_optin_wirksam_ab: Option<Date>,
pub sect51_abs3_unreported_days: u32,
pub ist_pilotwindanlage: bool,
}Expand description
Input for a single settlement period calculation.
All monetary rates are in ct/kWh (Cent per kWh), not EUR/kWh.
Supply Default::default() for fields not applicable to the model.
§Multi-EEG-version support
EEG has been revised many times (2000, 2004, 2009, 2012, 2014, 2017, 2021, 2023).
The correct verguetungssatz_ct is fixed at the plant’s commissioning date and
does not change over the 20-year Förderdauer. Supply the rate that was valid
when the plant was commissioned — use eeg_billing::rates or einsd’s
rate lookup table for historical rates.
The formula logic (which model is applicable, whether §27 applies, etc.)
differs by EEG version and commissioning date. Supply inbetriebnahme so
the engine can apply the correct version-specific guards automatically.
Fields§
§scheme: SettlementSchemeWhich regulatory formula to apply.
FeedInTariff→ §21 EEG EinspeisevergütungMarketPremium→ §20 EEG Gleitende Marktprämie (incl. Ausschreibung viatariff_source)TenantElectricity→ §21 Abs. 3 MieterstromPostEeg→ post-Förderung spot (configurablepost_eeg_price_floor)KwkSurcharge→ §7 KWKGTemporaryFeedInTariff→ §21 Abs. 1 Satz 1 Nr. 3 AusfallvergütungEigenverbrauch→ no paymentFlexibilityPremium→ §50b bestehende BiomasseanlagenFlexibilitySurcharge→ §50a neue Biomasseanlagen (capacity payment)
tariff_source: TariffSourceWhere the Anzulegender Wert (AW) comes from.
Statutory→ §48 EEG statutory tables (default)Auction(meta)→ BNetzA tender award (Ausschreibung: same formula as MarketPremium)Transitional(rule)→ §100 EEG Übergangsregelung
settlement_type: SettlementTypeSettlement type: initial, correction, or reversal.
einspeisemenge_kwh: Option<Decimal>Einspeisemenge kWh for the billing period.
None → output status = SettlementStatus::NoData.
marktwert_ct_kwh: Option<Decimal>Monthly EPEX Spot Day-Ahead average or technology-specific Jahresmarktwert (§20 Abs. 2 + Anlage 1 EEG 2023) in ct/kWh.
This is the market reference price used for all calculations that compare EEG payment against the market:
MarketPremium: spread =max(0, eff_AW - marktwert_ct_kwh)PostEeg: plant paid atmarktwert_ct_kwhper kWhSanktionAlt::VerguetungAufMarktwert: old-regime sanction uses this as rate§44bbiogas excess: excess kWh paid atmarktwert_ct_kwh
The library does not distinguish between EPEX monthly average and Jahresmarktwert — the caller resolves which value applies and passes it here.
sanktion: Option<SanktionAlt>§47 EEG (weggefallen/deleted in EEG 2023) / old EEG rules via §100 Übergangsregelung.
§52 EEG ≤2021 sanction tier (old regime via §100 Übergangsregelung).
§52 EEG 2021/2017 has three tiers that each reduce the Vergütung differently. These are for plants governed by EEG ≤2021 rules (commissioned before 01.01.2023).
SanktionAlt | §52 EEG ≤2021 | Vergütung effect |
|---|---|---|
VerguetungAufNull | Abs. 1 Nr. 1: MaStR not registered | EUR 0 |
VerguetungAufNull | Abs. 1 Nr. 2a: §10b Direktvermarktungspflicht | EUR 0 |
VerguetungAufNull | Abs. 1 Nr. 4: §27a Eigenversorgung (Ausschreibung) | EUR 0 |
VerguetungAufMarktwert | Abs. 2 Nr. 1: §9 Abs. 1/2/5 Fernsteuerbarkeit | → EPEX Marktwert |
VerguetungAufMarktwert | Abs. 2 Nr. 1a: §9 Abs. 8 Messeinrichtung | → EPEX Marktwert |
VerguetungReduziert20Prozent | Abs. 3 Nr. 1: MaStR partial/late | × 0.80 |
For EEG 2023 plants, use pflichtverstoss instead — §52 EEG 2023 charges
€10/kW/month without suspending Vergütung.
None = no sanction (normal settlement).
pflichtverstoss: Vec<Pflichtverstoss>§52 EEG 2023 — Pflichtverstöße (compliance violations).
§52 applies to plants governed by EEG 2023 rules (commissioned after 01.01.2023, or old plants for violations introduced in EEG 2023).
Each violation results in a separate payment obligation from the plant operator to the NB of €10/kW/month (§52 Abs. 2 EEG 2023). This is NOT a reduction of the Vergütung — the operator still receives the full Vergütung AND must separately pay the §52 penalty to the NB (§52 Abs. 6: the NB may net these).
§Common violation types
SanktionsTyp | §52 Abs. 1 Nr. | Trigger |
|---|---|---|
FernsteuerbarkeitFehlend | Nr. 1 | §9 Abs. 1/2: no remote-control equipment |
SpeicherAnforderungNichtErfuellt | Nr. 2 | §9 Abs. 5: missing storage requirement |
MastrNichtRegistriert | Nr. 11 | Plant not registered in MaStR |
Use crate::foerderdauer::calculate_pflichtzahlung to compute the penalty amount.
When pflichtverstoss is Some, the settlement formula still computes the
full Vergütung — the penalty is returned separately in the output’s
pflichtzahlung_eur field.
Default: empty Vec (no violations).
aw_reductions: AwReductionContext§§53b–54 EEG 2023 — reductions that act on the anzulegender Wert.
§53b Regionalnachweise, §53c Stromsteuerbefreiung and §54 solar
first-segment auction defects. Each reduces the AW before the
settlement formula, which matters for the gleitende Marktprämie: its
max(0, …) floor must absorb the reduction rather than the result being
pushed negative afterwards. See crate::aw_reductions.
negative_price_quarter_hours: Option<u64>§51a EEG 2023 — quarter-hours during which §51 reduced Vergütung to zero.
When provided, the engine computes SettleOutput.verlaengerungsanspruch_qh:
Solar PV: ceil(qh / 2) · Others: 1:1 factor.
einspeisemanagement_kwh: Option<Decimal>§13a EnWG (Redispatch 2.0) — kWh curtailed by the NB (Einspeisemanagement compensation).
§51 Negativpreisregel does NOT apply to these kWh (§19 Abs. 2 EEG 2023).
biomasse: Option<BiomassSettlementData>§§ 39i, 42–44 EEG 2023 — Biomass/biogas fuel composition for settlement enforcement.
When set for biomass or biogas plants, the engine enforces:
- § 39i Abs. 1 — a plant holding a Zuschlag whose Getreide- und
Mais-Anteil exceeds the Höchstanteil for its Gebotstermin has no § 19
Abs. 1 claim, and the period settles as
KeinAnspruchat EUR 0. A plant without a Zuschlag is outside Abs. 1 and is unaffected. - § 44 Güllekleinanlage eligibility is recorded in the position label
for audit transparency — it does not change the formula here; the
caller supplies the § 44 Abs. 1
verguetungssatz_ct(usecrate::rates::guelle_lookup).
Use crate::biomasse::BiomassSettlementData::new to derive from fuel
composition data. None = plant is not biomass/biogas.
billing_days_fraction: Option<Decimal>§25 Abs. 1 Satz 3 EEG — Fraction of the billing month with entitlement.
When None, the library auto-computes from billing_date, inbetriebnahme,
and foerderendedatum via foerderdauer::compute_billing_days_fraction().
When Some(x), the provided value is used directly (override).
Set explicitly only when the auto-computed value would be wrong for your
settlement scenario (rare edge cases). For standard plant lifecycles,
leave as None and ensure billing_date, inbetriebnahme, and
foerderendedatum are set.
kwh_during_negative_epex: Option<Decimal>§51 EEG — kWh produced during negative EPEX hours (to be excluded).
Under §51 EEG 2023, for plants ≥100 kWp commissioned after 01.01.2016, EEG Vergütung is zero during hours when the hourly EPEX Spot price is negative AND the consecutive run of negative hours meets the version-specific threshold (§51 EEG 2023: any period; §51 EEG 2017: ≥6h; §51 EEG 2021: ≥4h).
When inbetriebnahme and leistung_kwp are both set, the engine
automatically guards this rule based on eeg_gesetz.
Does NOT apply to §51b biogas Ausschreibungsanlagen — those plants use a different rule (AW = 0 when EPEX ≤ 2 ct/kWh).
Default: None (rule not applied).
inbetriebnahme: Option<Date>Plant commissioning date (Inbetriebnahmedatum).
When set, enables automatic EEG-version-aware rule enforcement:
- §51 EEG Negativpreisregel: threshold and kW exemption depend on EEG version
derived from commissioning year (see
eeg_gesetz). Key boundary: §100 Abs. 1 Satz 4 EEG 2017 exempts plants commissioned before 01.01.2016. Plants from 2016-01-01 onwards are subject to §51 EEG 2017 (6h, 500 kW/3 MW). - Audit position labels: include the commissioning year for traceability.
For multi-block plants (§24 Anlagenerweiterung), the commissioning dates
live on each CapacityBlock instead.
inbetriebnahme_typ: InbetriebnahmeTypType of commissioning event — for audit trail and Förderdauer rules.
Determines whether the Förderdauer clock resets (only Repowering resets it)
and which lifecycle state the plant is in. Stored in einsd’s
eeg_anlagen.inbetriebnahme_typ column.
InbetriebnahmeTyp | Förderdauer | Audit relevance |
|---|---|---|
Erstinbetriebnahme (default) | starts at inbetriebnahme | Normal plant |
Wiederinbetriebnahme | continues from original | Restart after shutdown |
Modernisierung | continues from original | Equipment replacement |
Repowering | resets to repowering date | New 20-year clock |
Zusammenlegung | oldest component date | §24 merger |
Erweiterung | new block from extension date | §24 capacity add |
The engine records this in position descriptions for full audit traceability.
Default: InbetriebnahmeTyp::Erstinbetriebnahme.
leistung_kwp: Option<Decimal>Installed peak power in kWp (or kW_el for KWKG).
Used for:
- §27 EEG guard (threshold: 100 kWp)
- §51 Abs. 2 kW exemption (aggregated per §24 when
capacity_blocksis set)
Ignored when capacity_blocks is non-empty.
foerderendedatum: Option<Date>EEG subsidy end date from the plant registry.
When set together with billing_date, the engine automatically returns
FoerderungBeendet when billing_date > foerderendedatum.
For KWKG plants, this is the calendar-year fallback (§8 Abs. 4 KWKG):
Förderung ends at min(kwk_hour_limit, inbetriebnahme + 15y).
billing_date: Option<Date>First day of the billing period (ISO 8601 month-start, e.g. 2026-07-01).
Used together with foerderendedatum for automatic FoerderungBeendet
detection. When omitted, the caller must check FoerderungBeendet manually.
capacity_blocks: Vec<CapacityBlock>Additional capacity blocks for §24 EEG Anlagenerweiterung / Zusammenlegung.
When non-empty, the engine performs multi-block settlement:
- Each block receives a proportional share of
einspeisemenge_kwh(proportional toleistung_kwpof each block). - The primary block uses
SettleInput.verguetungssatz_ctandSettleInput.inbetriebnahme/foerderendedatum. - Blocks whose
foerderendedatum < billing_dateare expired (EUR 0). - The §27 Negativpreisregel is applied per-block based on each block’s commissioning date and capacity.
Leave empty for single-block plants (the vast majority).
eeg_gesetz: EegGesetzEEG law year applicable to this plant (Gesetz-Jahr des anzuwendenden EEG).
Determines which version-specific rules the engine applies:
EEG law version governing this plant — the §52 Pflichtverstoß regime and the §100 Übergangsbestimmungen.
Not the source of the §51 rules: those are keyed on the commissioning
date (see SettleInput::negativpreis_regime), because the
Solarspitzengesetz rewrote §51 with effect from 25.02.2025 — inside the
EEG 2023 range.
Use EegGesetz::from_db_year to convert the eeg_gesetz DB column, or
EegGesetz::from_inbetriebnahme_year as a fallback.
erzeugungsart: Option<ErzeugungsArt>Plant technology type (optional, used for §51 EEG 2017 wind exemption).
Under EEG 2017, wind turbines get a separate 3 MW kW exemption
(§51 Abs. 3 Nr. 1); other plants get the 500 kW exemption (Nr. 2).
Derive from einsd erzeugungsart column via ErzeugungsArt::from_db_str.
None is treated as non-wind (conservative: 500 kW exemption under EEG 2017).
aw_is_gross: bool§53 Abs. 1 EEG 2023 — whether the Einspeisevergütung rate supplied in the scheme is the gross anzulegender Wert (as published in §48/BNetzA bulletins) rather than the net Vergütungssatz.
When true, the engine subtracts the §53 Abs. 1 deduction
(0.4 ct/kWh Solar/Wind, 0.2 ct/kWh Wasserkraft/Biomasse/Geothermie/Gas)
keyed on erzeugungsart for SettlementScheme::FeedInTariff. Default
false: the rate is already net (einsd’s eeg_verguetungssaetze stores
net rates), so nothing is deducted — this prevents a double deduction.
biogas_sect44b_eligible_kwh: Option<Decimal>§44b Abs. 1 EEG 2023 — Biogas >100 kW: annual 45% Bemessungsleistung cap.
For Biogas plants (fermentation biogas, excluding fermentation-biomass §44 plants and Ausschreibungsanlagen §39) with installed capacity >100 kW, the EEG payment is limited to the share of annual production corresponding to 45% of installed kW:
annual_quota_kwh = leistung_kw × 0.45 × <§3 Nr. 6 hours of the year>
The hour count is not a flat 8 760: it is the actual hours of the
calendar year (8 784 in a leap year) less the hours before the plant’s
first generation. See crate::sect44b_jahreskontingent_kwh, which is
what both the settlement and the check_sect44b_quota MCP tool call.
When set, this field is the eligible kWh for the current billing period (the
caller tracks cumulative annual production and passes min(kwh, remaining_quota)):
- Eligible part: normal remuneration (this field’s value)
- Excess part (
einspeisemenge_kwh - eligible):MarketPremium: AW reduces to zero, Marktprämie = 0 (§44b Abs. 1 Satz 2)FeedInTariff: paid at EPEX Marktwert (epex_avg_ct_kwh), requires EPEX price
None = cap does not apply (plant ≤100 kW, fermentation biomass §44, Ausschreibung §39,
or non-Biogas technology).
Legal basis: §44b Abs. 1 EEG 2023 (BGBl. I Nr. 28, 10.01.2023).
has_imesys: bool§51 Abs. 2 Nr. 1 EEG 2023 — whether the sub-100-kW exemption has lapsed.
The exemption is transitional: §51 Abs. 2 Nr. 1 grants it only „für
Zeiträume vor dem Ablauf des Kalenderjahres, in dem die Anlage mit
einem intelligenten Messsystem ausgestattet wird“. It therefore survives
the whole installation year and lapses on 1 January of the year after,
from when a 30 kWp plant is subject to §51 like any other. Derive it with
crate::negativpreis::imesys_befreiung_entfallen rather than comparing
the installation date with the settlement period.
It lifts only that exemption. The 2 kW floor of Abs. 2 Nr. 2 stands until the Bundesnetzagentur’s §85 Abs. 2 Nr. 12 Festlegung, and the exemptions of the older Fassungen (400 kW, 500 kW, 3 MW) are unaffected — they have no iMSys condition.
Default: false (conservative — retains the exemption when unknown).
marktwert_kategorie: Option<MarktpreisKategorie>Technology-specific Jahresmarktwert category (§20 Abs. 2 + Anlage 1 EEG 2023).
Documents which ÜNB technology category marktwert_ct_kwh was sourced from.
The library uses marktwert_ct_kwh directly — this field is informational only
(validation aid and audit label).
sect51_optin_wirksam_ab: Option<Date>§100 EEG — the date a Bestandsanlage’s opt-in into the Solarspitzengesetz regime takes effect.
The operator declares in Textform to the Netzbetreiber that §§ 51 and 51a
shall apply; the declaration runs at the earliest from the end of the
calendar year in which the plant is fitted with an iMSys. Derive it with
crate::negativpreis::optin_wirksam_ab. From that date the plant is
under the Solarspitzengesetz regime and its anzulegender Wert rises by
crate::negativpreis::SECT51_OPTIN_ZUSCHLAG_CT_KWH.
None — the usual case — leaves the plant on its commissioning vintage.
sect51_abs3_unreported_days: u32§51 Abs. 3 EEG — calendar days of an unreported negative-price period, for a plant on the Ausfallvergütung.
An operator on the Ausfallvergütung must report, with the §71 Abs. 1 Nr. 1 data, the quantity it fed in while the Spotmarktpreis was continuously negative. Where it does not, the claim for that calendar month falls by 5 % per calendar day on which such a period fell, wholly or partly.
Set this to the number of those days when the figure is missing, and 0
when it was reported (or the month had no negative period). Applies only
to SettlementScheme::TemporaryFeedInTariff; ignored elsewhere.
ist_pilotwindanlage: bool§3 Nr. 37 EEG 2023 — Pilotwindenergieanlage an Land.
Every Fassung of §51 carves these out of the Negativpreisregel, whatever their size. The status is a BNetzA/FGW certification fact about the turbine, so it is declared rather than derived.
Default: false.
Implementations§
Source§impl SettleInput
impl SettleInput
Sourcepub fn effective_eeg_gesetz(&self) -> EegGesetz
pub fn effective_eeg_gesetz(&self) -> EegGesetz
Effective EEG law version for §51/§52 calculation.
When tariff_source = Transitional(rule) and the rule implies a specific
EegGesetz, that implied version is returned instead of self.eeg_gesetz.
This prevents silent miscalculation when a §100 Transitional rule is set
without the corresponding eeg_gesetz being updated by the caller.
tariff_source | Returns |
|---|---|
Statutory / Auction(_) | self.eeg_gesetz (caller-supplied) |
Transitional(Pre2016Bestandsschutz) | EegGesetz::Eeg2012 — §51 never applies |
Transitional(Eeg2017Negativpreis6h) | EegGesetz::Eeg2017 — 6h threshold |
Transitional(OldPlantBeforeEeg2023) | EegGesetz::Eeg2021 — 4h threshold |
Transitional(_) other | self.eeg_gesetz |
§Example
use eeg_billing::{SettleInput, EegGesetz};
use eeg_billing::scheme::{TariffSource, Paragraph100Rule};
// Pre-2016 plant: §51 must never apply, regardless of what eeg_gesetz says.
let input = SettleInput {
tariff_source: TariffSource::Transitional(Paragraph100Rule::Pre2016Bestandsschutz),
eeg_gesetz: EegGesetz::Eeg2017, // deliberately wrong — overridden
..SettleInput::default()
};
assert_eq!(input.effective_eeg_gesetz(), EegGesetz::Eeg2012);Sourcepub fn negativpreis_regime(&self) -> NegativpreisRegime
pub fn negativpreis_regime(&self) -> NegativpreisRegime
The §51 Negativpreisregel version governing this plant.
Derived from inbetriebnahme, because the Solarspitzengesetz boundary
(25.02.2025) falls inside a calendar year and inside the EEG 2023 range.
When the commissioning date is unknown the plant’s law version supplies a
coarse fallback, and a §100 Transitional rule overrides both — a rule
that pins a plant to a pre-2016 vintage must keep §51 off it.
Trait Implementations§
Source§impl Clone for SettleInput
impl Clone for SettleInput
Source§fn clone(&self) -> SettleInput
fn clone(&self) -> SettleInput
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more