This repository provides an optimization framework for simulating the operation of Battery Energy Storage Systems (BESS) using Mixed-Integer Linear Programming (MILP). It supports both wholesale-only arbitrage and mixed retail/wholesale arbitrage with behind-the-meter (BTM) load.
- MILP-based dispatch models using PuLP
- Supports:
- Wholesale-Only Arbitrage
- Mixed Arbitrage with BTM Load
- Includes:
- Battery degradation modeling (calendar + cycling)
- Self-discharge and throughput constraints
- Daily cycle limits
- Post-optimization KPIs:
- Energy flows, price spreads, average cycles, cost metrics
Install required Python packages:
pip install numpy pandas pulpConfigurable battery parameters include:
total_capacity: Energy capacity (kWh)total_rated_power: Max charge/discharge power (kW)rte: Round-trip efficiencyinitial_soc: Initial state of charge (fraction)max_soc/min_soc: SoC boundsdaily_cycles: Max daily throughput in cyclesyearly_degradation: Annual calendar agingreplacement_cost: Degradation cost per kWh
Optimizes BESS operation using wholesale price signals only.
Key constraints:
- State of charge (SoC) balance
- Charge/discharge power limits
- Degradation cost from throughput
- Daily throughput and cycle constraints
- Mutual exclusivity of charge/discharge
Optimizes for both retail and wholesale price opportunities, with on-site (BTM) load.
Features:
- Separate charge/discharge tracking for retail vs. wholesale
- Prioritizes serving local load before export
- Manages SoC tagged by energy source
- Additional mutual exclusivity constraints
Run the included example to simulate 24 hours:
python bess_arbitrage.pyThis runs both arbitrage models with synthetic price/load data.
=== Wholesale-Only Arbitrage ===
Objective value: $-X.XX
Total charged: XXX.X kWh
Total discharged: XXX.X kWh
Average cycles: X.XX
Wholesale spread: $0.XXX/kWh
=== Mixed Arbitrage (BTM) ===
Objective value: $-X.XX
Energy served to load: XXX.X kWh
Energy exported: XXX.X kWh
Total charged: XXX.X kWh
Average cycles: X.XX
Retail spread: $0.XXX/kWh
Wholesale spread: $0.XXX/kWh
| Metric | Description |
|---|---|
E_chg |
Total energy charged (kWh) |
E_discharge |
Total energy discharged (kWh) |
E_load |
Energy served to on-site load (kWh) |
E_wh |
Energy exported to wholesale (kWh) |
Spread_retail |
Retail arbitrage value ($/kWh) |
Spread_wholesale |
Wholesale arbitrage value ($/kWh) |
Avg_cycles |
Average daily equivalent cycles |
Container for all battery and degradation attributes used by both models.
- Method:
create_model(prices) - Method:
extract_results(model, timesteps)
- Method:
create_model(load, retail_prices, wholesale_prices) - Method:
extract_results(model, timesteps)
Calculates post-dispatch KPIs and financial indicators.