Expand description
Pure EEG/KWKG feed-in settlement calculation for German energy markets.
Implements all settlement models defined in EEG (all versions 2000–2023)
and KWKG. Zero I/O, zero async — every function is deterministic
and synchronous. No floating-point money: amounts are computed in
rust_decimal::Decimal, and every EUR result is rounded and
range-checked through crate::EuroAmount (i64 × 10⁻⁵ EUR).
§Settlement schemes (10)
SettlementScheme | Formula | Legal basis |
|---|---|---|
FeedInTariff | kwh × verguetungssatz_ct / 100 | §21 EEG |
TenantElectricity | Vergütung + kwh × mieter_zuschlag_ct / 100 | §21 Abs. 3 EEG 2023 |
MarketPremium | max(0, AW − Marktwert) × kwh / 100 | §23a EEG + Anlage 1 |
MarketPremium + TariffSource::Auction | same formula, AW from BNetzA tender | §§22a,28 EEG 2023 |
PostEeg | kwh × EPEX / 100 (§23b cap: 10 ct; configurable floor) | §21 EEG (post-Förderung) |
Eigenverbrauch | EUR 0 (no feed-in remuneration) | §21 Abs. 3 EEG |
KwkSurcharge | eligible_kwh × rate / 100 (Vollbenutzungsstunden-Grenze) | §§7, 8 KWKG |
FlexibilityPremium | Vergütung + kwh × flex_praemie_ct / 100 | §50b EEG 2023 (bestehende Anlagen) |
FlexibilitySurcharge | kw × rate / 12 (monthly capacity payment) | §50a EEG 2023 (neue Anlagen) |
TemporaryFeedInTariff | kwh × verguetungssatz_ct / 100 (reduced Ausfallvergütung) | §21 Abs. 1 Satz 1 Nr. 3 EEG 2023 |
SonstigeDirektvermarktung | EUR 0 — revenue on the open market, no NB payment | §21a EEG |
§One formula — all EEG versions (2000–2023)
No separate tariff per EEG version is needed. The settlement formula is identical across all EEG versions. What differs between versions:
-
Vergütungssatz (rate) — fixed at commissioning for 20 years; caller provides it. Use
rates::solar_pv_ueberschuss_aw_ctoreinsd’slookup_verguetungssatz. -
§51 Negativpreisregel — applied automatically, and keyed on the Inbetriebnahmedatum rather than the law year: the Solarspitzengesetz rewrote §51 with effect from 25.02.2025, mid-year and inside the EEG 2023 range.
negativpreis::NegativpreisRegime::fuer_inbetriebnahmederives it — ≥6 h (2016–2020), ≥4 h (2021–2022), the staged 4-3-2-1 h ladder (2023–24.02.2025), the first negative quarter-hour from 25.02.2025, and never for a plant commissioned before 2016. -
§100 EEG 2023 Übergangsregelung — old plants continue under their EEG version’s rules (§100 Abs. 1). The rate is the only thing that changes per plant.
§Umsatzsteuer (not Mehrwertsteuer)
“Umsatzsteuer” (USt) is the legal term; “Mehrwertsteuer” (MwSt) is colloquial.
A feed-in Gutschrift has two VAT treatments — see ust:
- §19 UStG Kleinunternehmer: turnover ≤€25 000/yr → no USt (category
E) - Regelbesteuerung: all others → 19 % USt (category
S)
The status is a declared property of the operator (masterdata), not something
the plant size decides. Use ust::ust_tax_layers to get the right
billing::TaxLayer for a document.
§Multi-EEG-version support
Supply inbetriebnahme and leistung_kwp in SettleInput for automatic
version-specific rule enforcement:
- §51 Negativpreisregel guard — the size exemption is per regime
(
negativpreis::NegativpreisRegime::kw_grenze): Wind < 3 MW / others < 500 kW, then < 500 kW, < 400 kW, and < 100 kW until an iMSys is in (< 2 kW after) - Automatic
FoerderungBeendetwhenbilling_date > foerderendedatum
§§24 EEG Anlagenerweiterung
Plants extended with additional capacity blocks use CapacityBlock.
Settlement is proportionally allocated across all blocks by installed kWp.
§Quick start
use eeg_billing::{SettleInput, SettlementScheme, calculate_settlement, SettlementStatus};
use rust_decimal::Decimal;
use std::str::FromStr;
fn d(s: &str) -> Decimal { Decimal::from_str(s).unwrap() }
// §21 EEG 2023 — 100 kWh × 8.51 ct/kWh (Solarpaket I, ≤10 kWp Überschuss) = 8.51 EUR
let out = calculate_settlement(&SettleInput {
scheme: eeg_billing::SettlementScheme::FeedInTariff { verguetungssatz_ct: d("8.51") },
einspeisemenge_kwh: Some(d("100")),
..SettleInput::default()
});
assert_eq!(out.status, SettlementStatus::Calculated);
assert_eq!(out.settlement_eur, Some(d("8.51")));Re-exports§
pub use aw_reductions::AwReductionApplied;pub use aw_reductions::AwReductionContext;pub use aw_reductions::Sect54SolarReduction;pub use biomasse::bemessungsleistung_stunden;pub use biomasse::sect39i_hoechstanteil;pub use biomasse::sect44b_jahreskontingent_kwh;pub use foerderdauer::SECT51A_SOLAR_FACTOR_DENOMINATOR;pub use foerderdauer::calculate_pflichtzahlung;pub use foerderdauer::compute_billing_days_fraction;pub use foerderdauer::foerderendedatum_eeg;pub use foerderdauer::foerderendedatum_eeg_ausschreibung;pub use foerderdauer::foerderendedatum_repowering;pub use foerderdauer::kwk_eligible_kwh;pub use foerderdauer::kwk_max_kwh;pub use foerderdauer::pflichtzahlung_verjaehrt_am;pub use foerderdauer::sect52a_netztrennung_erforderlich;pub use foerderdauer::verguetungszeitraum_verlaengerung_qh;pub use foerderdauer::wind_onshore_korrekturfaktor_corrected_aw;pub use kwkg::KwkAnlagenart;pub use kwkg::KwkFoerderdauerInput;pub use kwkg::KwkLeistungsanteil;pub use kwkg::KwkVerwendung;pub use kwkg::KwkZuschlagInput;pub use kwkg::foerderdauer_vollbenutzungsstunden;pub use kwkg::jahreshoechstbetrag_vollbenutzungsstunden;pub use kwkg::jahreskontingent_kwh;pub use kwkg::zuschlag_ct_kwh;pub use kwkg::zuschlag_leistungsanteile;pub use negativpreis::NegativpreisInterval;pub use negativpreis::NegativpreisRegime;pub use negativpreis::NegativpreisResult;pub use negativpreis::derive_negativpreis;pub use rounding::RoundMoney;pub use scheme::ANLAGE1_NR2_STICHTAG;pub use scheme::AusschreibungMetadata;pub use scheme::CorrectionReason;pub use scheme::MarktpreisKategorie;pub use scheme::Marktwertserie;pub use scheme::Paragraph100Rule;pub use scheme::SettlementScheme;pub use scheme::SettlementType;pub use scheme::TariffSource;pub use scheme::marktwertserie;pub use seed::VerguetungssatzRow;pub use seed::verguetungssatz_rows;pub use technology::ErzeugungsArt;pub use technology::InbetriebnahmeTyp;pub use technology::InvalidErzeugungsArt;pub use technology::InvalidInbetriebnahmeTyp;pub use technology::RepoweringScope;pub use version::EegGesetz;pub use version::InvalidEegGesetz;pub use zusammenfassung::AnlageFuerZusammenfassung;pub use zusammenfassung::SolarMontage;pub use zusammenfassung::Steckersolar;pub use zusammenfassung::ZusammenfassungErgebnis;pub use zusammenfassung::ZusammenfassungGrund;pub use zusammenfassung::sind_eine_anlage;pub use zusammenfassung::zusammenlegung_within_12_months;
Modules§
- aw_
reductions - §§53b–54 EEG 2023 — reductions that act on the anzulegender Wert.
- biomasse
- Biomass-specific EEG settlement models — §§ 42–44b EEG 2023.
- bridge
- Bridge to
billingdocument types. - degression
- §49 EEG 2023 — halbjährliche Absenkung der solaren anzulegenden Werte.
- direktverm
- Veräußerungsformen and the Direktvermarktungspflicht — §§ 20–22 EEG 2023.
- foerderdauer
- Förderdauer (subsidy duration) calculation helpers.
- foerderungsende
- Funding termination and sanction lifecycle models.
- kwkg
- §§ 7–9 KWKG — Höhe und Dauer des Zuschlags für KWK-Strom.
- negativpreis
- §51 EEG — Verringerung des Zahlungsanspruchs bei negativen Preisen.
- rates
- Statutory EEG feed-in tariff rate tables.
- reductions
- §52 EEG 2023 — Pflichtzahlungen and their netting against the disbursement.
- rounding
- Kaufmännisches Runden — the one rounding mode this crate uses.
- scheme
- Clean settlement scheme architecture — the “what” and “where” of EEG remuneration.
- seed
- The statutory Einspeisevergütung series, as rows a service can seed a table with.
- settlement_
state - Monthly settlement lifecycle state machine for EEG plants.
- tariff
billing::PricingModelimplementation bridge for EEG/KWKG settlement.- technology
ErzeugungsArt— typed EEG/KWKG plant technology category.- ust
- German VAT (Umsatzsteuer) rules for EEG/KWKG feed-in settlements.
- version
EegGesetz— typed EEG law version for a plant.- wind
- Wind onshore reference yield model — §36h EEG 2023 i.V.m. Anlage 2.
- zusammenfassung
- §24 EEG 2023 — Zahlungsansprüche für Strom aus mehreren Anlagen.
Structs§
- Capacity
Block - A single capacity block for §24 EEG Anlagenerweiterung (plant extension).
- Pflichtverstoss
- §52 EEG 2023 — Pflichtverstoss input for penalty calculation.
- Settle
Input - Input for a single settlement period calculation.
- Settle
Output - Output of a settlement calculation.
- Settle
Position - A single billing component of a settlement calculation.
Enums§
- Sanktion
Alt - §52 EEG ≤2021 (old regime) — sanction tier reducing the Vergütung.
- Sanktions
Typ - §52 EEG 2023 compliance violation type.
- Settlement
Error - Errors that can be returned by
eeg-billingfunctions. - Settlement
Status - Outcome of a settlement calculation.
Functions§
- calculate_
settlement - Calculate the settlement amount and billing positions for one period.
Type Aliases§
- Euro
Amount - A monetary amount in euro at 10⁻⁵-EUR resolution.