slice S-B8: extend E7 off-peak rate to HW for E7-tariff dwellings

When the main heating is electric storage / direct-electric (codes
191-196, 401-409, 421-425), the cert almost always carries an
Economy-7 tariff and the immersion HW cylinder runs on the off-peak
timer. Bill HW at the 7h-low rate (5.5 p/kWh) in that case, falling
back to the lower of {7h-low, water_heating_fuel rate} so we never
over-charge an HW fuel that's already cheaper than off-peak.

100-cert parity probe:
  MAE 4.90 → 4.66   (-0.24)
  bias -1.44 → -0.70 (over-correction halved)
  within ±3: 46% → 48%
  within ±5: 67% → 68%
  within ±10: 93% → 94%

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-18 14:59:09 +00:00
parent aa2c7a9171
commit 6d256ab2bc
2 changed files with 13 additions and 6 deletions

View file

@ -383,10 +383,15 @@ def _space_heating_fuel_cost_gbp_per_kwh(main: Optional[MainHeatingDetail]) -> f
def _hot_water_fuel_cost_gbp_per_kwh(
main: Optional[MainHeatingDetail], water_heating_fuel: Optional[int]
) -> float:
"""Hot water bills at the *water-heating* fuel's rate — distinct from
the main heating fuel for gas-heated dwellings whose DHW runs off an
electric immersion. Falls back to the main fuel when the cert
doesn't lodge a separate water fuel."""
"""Hot water bills at the *water-heating* fuel's rate. Special case:
an E7-tariff dwelling (electric storage / direct-electric main
heating) running an electric immersion HW cylinder bills HW at the
7h-low rate too, since these households typically run the immersion
on the off-peak timer RdSAP convention. Falls back to the main
fuel when the cert doesn't lodge a separate water fuel."""
is_e7 = _is_electric_storage_or_direct(main)
if is_e7 and (water_heating_fuel is None or fuel_unit_price_p_per_kwh(water_heating_fuel) > _E7_LOW_RATE_P_PER_KWH):
return _E7_LOW_RATE_P_PER_KWH * _PENCE_TO_GBP
if water_heating_fuel is not None:
return fuel_unit_price_p_per_kwh(water_heating_fuel) * _PENCE_TO_GBP
return _fuel_cost_gbp_per_kwh(main)

View file

@ -335,9 +335,11 @@ def test_electric_storage_heater_space_heating_at_off_peak_rate() -> None:
# Act
inputs = cert_to_inputs(epc)
# Assert
# Assert — RdSAP convention: when an E7 dwelling's HW runs on
# electric immersion, the immersion is presumed to be on the
# off-peak timer, so HW bills at the 7h-low rate too.
assert inputs.space_heating_fuel_cost_gbp_per_kwh == 0.055
assert inputs.hot_water_fuel_cost_gbp_per_kwh == 0.1319
assert inputs.hot_water_fuel_cost_gbp_per_kwh == 0.055
assert inputs.other_fuel_cost_gbp_per_kwh == 0.1319