Skip to main content

Crate eeg_billing

Crate eeg_billing 

Source
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)

SettlementSchemeFormulaLegal basis
FeedInTariffkwh × verguetungssatz_ct / 100§21 EEG
TenantElectricityVergütung + kwh × mieter_zuschlag_ct / 100§21 Abs. 3 EEG 2023
MarketPremiummax(0, AW − Marktwert) × kwh / 100§23a EEG + Anlage 1
MarketPremium + TariffSource::Auctionsame formula, AW from BNetzA tender§§22a,28 EEG 2023
PostEegkwh × EPEX / 100 (§23b cap: 10 ct; configurable floor)§21 EEG (post-Förderung)
EigenverbrauchEUR 0 (no feed-in remuneration)§21 Abs. 3 EEG
KwkSurchargeeligible_kwh × rate / 100 (Vollbenutzungsstunden-Grenze)§§7, 8 KWKG
FlexibilityPremiumVergütung + kwh × flex_praemie_ct / 100§50b EEG 2023 (bestehende Anlagen)
FlexibilitySurchargekw × rate / 12 (monthly capacity payment)§50a EEG 2023 (neue Anlagen)
TemporaryFeedInTariffkwh × verguetungssatz_ct / 100 (reduced Ausfallvergütung)§21 Abs. 1 Satz 1 Nr. 3 EEG 2023
SonstigeDirektvermarktungEUR 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:

  1. Vergütungssatz (rate) — fixed at commissioning for 20 years; caller provides it. Use rates::solar_pv_ueberschuss_aw_ct or einsd’s lookup_verguetungssatz.

  2. §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_inbetriebnahme derives 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.

  3. §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 FoerderungBeendet when billing_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 billing document 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::PricingModel implementation 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§

CapacityBlock
A single capacity block for §24 EEG Anlagenerweiterung (plant extension).
Pflichtverstoss
§52 EEG 2023 — Pflichtverstoss input for penalty calculation.
SettleInput
Input for a single settlement period calculation.
SettleOutput
Output of a settlement calculation.
SettlePosition
A single billing component of a settlement calculation.

Enums§

SanktionAlt
§52 EEG ≤2021 (old regime) — sanction tier reducing the Vergütung.
SanktionsTyp
§52 EEG 2023 compliance violation type.
SettlementError
Errors that can be returned by eeg-billing functions.
SettlementStatus
Outcome of a settlement calculation.

Functions§

calculate_settlement
Calculate the settlement amount and billing positions for one period.

Type Aliases§

EuroAmount
A monetary amount in euro at 10⁻⁵-EUR resolution.