Payback Period
How the optimization engine calculates the payback period for solar panel and battery investments, and which input parameters affect it most.
The formula
The payback period is computed after the optimization completes by dividing the total upfront investment by the annual energy cost savings:
payback_years = total_investment / annual_savings
Both values are derived from the hourly simulation (8,760 time steps per year). The engine compares two scenarios:
- Baseline (BAU) — the property's energy situation without any new equipment.
- Optimized — the property with the recommended solar panels and/or battery installed.
The difference in annual energy costs between these two scenarios is the annual_savings.
When goal is set to "self-sufficiency", the engine does not run a baseline scenario. In that mode the system is sized to maximize on-site energy coverage rather than financial return, so the payback period is less meaningful.
Annual savings breakdown
Annual savings consist of two components:
| Component | Description |
|---|---|
| Self-consumption savings | Each kWh consumed from your own solar panels is a kWh you don't buy from the grid. The value equals the grid import rate (from tariff). |
| Feed-in revenue | Excess solar energy exported to the grid earns a feed-in rate. For flat tariffs this defaults to EUR 0.05/kWh. For dynamic tariffs the hourly wholesale price is used. |
The engine simulates all 8,760 hours independently: for each hour it calculates solar production (based on location, panel orientation, and weather data), consumption (from the load profile), optional battery charge/discharge, and the resulting grid import or export. The annual totals produce the savings figure.
PV cost model
The total investment for new solar panels uses a tiered cost model based on system size (kWp):
| System size | Installed cost |
|---|---|
| ≤ 4 kWp | EUR 1,200 / kWp |
| 4 – 10 kWp | EUR 1,000 / kWp |
| > 10 kWp | EUR 800 / kWp |
The system size is derived from the newPv array: size_kwp = panel_count × panel_power_watts / 1000. The optimizer can choose any size between the minimum and maximum panel count you specify.
Existing panels (existingPv) have an installed_cost_per_kw of 0 since they are already paid for — they affect savings but not the investment amount.
Battery cost model
When an electricBattery is provided, battery costs use a similar tiered model:
| Capacity | Installed cost |
|---|---|
| ≤ 5 kWh | EUR 1,100 / kWh |
| 5 – 10 kWh | EUR 900 / kWh |
| > 10 kWh | EUR 600 / kWh |
If you provide totalCost explicitly in the battery configuration, it overrides the tiered pricing.
Impact of goal
The goal parameter fundamentally changes the cost assumptions:
| Goal | PV cost | Battery cost | Baseline run |
|---|---|---|---|
"cost-savings" (default) | Tiered pricing (800–1,200 EUR/kWp) | Tiered pricing (600–1,100 EUR/kWh) | Yes — savings are computed vs baseline |
"self-sufficiency" | EUR 0.10/kWp (near-zero) | EUR 0.10/kWh (near-zero) | No — optimizer maximizes PV and battery |
With "self-sufficiency", the near-zero costs signal to the optimizer that budget is not a constraint, causing it to install the maximum allowable capacity. The resulting payback period is not directly comparable to cost-savings mode.
Worked example
Consider a household with:
yearlyKwh: 5,200newPv: 10 panels × 440W = 4.4 kWptariff: flat at EUR 0.40/kWhgoal:"cost-savings"
The engine calculates:
- Name
investment- Type
- EUR
- Description
4.4 kWp × EUR 1,000/kWp = EUR 4,400
- Name
annual_production- Type
- kWh
- Description
4,200 kWh (based on location irradiance)
- Name
self_consumption- Type
- kWh
- Description
1,470 kWh (35% of production consumed on-site)
- Name
self_consumption_savings- Type
- EUR
- Description
1,470 × EUR 0.40 = EUR 588
- Name
feed_in_revenue- Type
- EUR
- Description
2,730 × EUR 0.05 = EUR 137
- Name
annual_savings- Type
- EUR
- Description
EUR 588 + EUR 137 = EUR 725
- Name
payback_period- Type
- years
- Description
EUR 4,400 / EUR 725 = 6.1 years
Scan request (relevant fields)
{
"yearlyKwh": 5200,
"inputMethod": "known",
"newPv": [
{
"panelCount": 10,
"panelPowerWatts": 440,
"tiltAngle": 35,
"azimuthAngle": 180
}
],
"tariff": {
"type": "flat",
"flatRateCentsPerKwh": 40
},
"goal": "cost-savings"
}