跳转至

电池储能套利

背景

并网电池可以在低价时购电、高价时向电网放电。可信的调度模型需要 同时考虑充放电损耗、荷电状态运行区间、有限功率、循环损耗,以及 调度结束时剩余电量的价值。

本例优化一块标称容量 100 kWh 电池的 24 小时计划。充电和放电分别 使用非负控制量,使功率换向处的动力学与目标函数保持光滑。

问题定义

\(E(t)\) 为储能量,\(P_c(t)\) 为从电网吸收的充电功率,\(P_d(t)\) 为送回电网的放电功率。充、放电效率分别为 \(\eta_c\)\(\eta_d\), 则

\[ \dot E=\eta_cP_c-\frac{P_d}{\eta_d}. \]

光滑的日前电价曲线为

\[ \begin{aligned} p(t)={}&0.12 +0.08\exp\!\left[-\left(\frac{t-8}{2}\right)^2\right] +0.22\exp\!\left[-\left(\frac{t-19}{2.4}\right)^2\right]\\ &-0.06\exp\!\left[-\left(\frac{t-13}{2.5}\right)^2\right]. \end{aligned} \]

优化目标由电力市场现金流和凸的循环损耗代理组成:

\[ \min_{E,P_c,P_d}J=\int_0^{24} \left[p(t)(P_c-P_d)+\gamma(P_c^2+P_d^2)\right]\,\mathrm dt, \qquad \gamma=0.003. \]

第一项为负时表示获得净收入。终端能量约束避免优化器把初始库存当作 免费能源使用:

\[ E(0)=E(24)=50\ \mathrm{kWh}. \]

运行能量与功率边界为

\[ 10\le E(t)\le90\ \mathrm{kWh}, \qquad 0\le P_c(t),P_d(t)\le20\ \mathrm{kW}. \]

参数、变量与单位

符号 含义 数值或单位
\(t\) 时间 h
\(E\) 电池储能量 kWh
\(P_c,P_d\) 充电与放电功率 kW
\(p(t)\) 日前电价 货币单位/kWh
\(E_{\mathrm{nom}}\) 标称能量容量 \(100\ \mathrm{kWh}\)
\(\eta_c\) 充电效率 \(0.95\)
\(\eta_d\) 放电效率 \(0.94\)
\(\gamma\) 二次循环代价权重 \(0.003\) 货币单位/(kW² h)

建模取舍

分别设置充电与放电控制,可避免单个带符号功率模型在效率切换处不可微。 模型没有加入非凸互补约束 \(P_cP_d=0\)。对于这里的电价曲线,转换 损耗和正二次惩罚已经使同时充放电缺乏经济性;脚本仍会在密集网格上 明确报告残余重叠量。

10--90 kWh 的运行窗口在标称容量两端保留余量。相同的初始和终端 能量使每天的现金流具有可比性。离散采用 \(96\times2\) Lobatto 网格, 对应 15 分钟区间上的分段线性能量与功率历程。

运行示例

python -m examples.battery_energy_arbitrage

无界面运行并保存图片:

python -m examples.battery_energy_arbitrage --save battery-energy-arbitrage.png --no-show

实现遵循统一的可组合流程:

system, phase = build_problem()
guess = initial_guess(phase)
solution = solve_problem(system, guess)
plot_solution(solution)

验证结果

脚本在 4,001 个时刻重构能量和两个功率,检查所有边界与终端库存,并 独立积分市场现金流和电池吞吐量。

指标 验证值
目标函数 \(J\) \(-7.36173187\) 个货币单位
电力市场现金流 \(-12.312375\) 个货币单位
电池吞吐量 \(\int(P_c+P_d)\,\mathrm dt\) \(151.426069\ \mathrm{kWh}\)
最大同时充放电功率 \(5.799\times10^{-8}\ \mathrm{kW}\)
最大密集路径边界超限 \(8.949\times10^{-7}\)

目标值没有市场现金流那么负,是因为其中还包含正的循环惩罚。电池在 低价区间充电,并在两个价格峰值附近放电;最大的密集边界误差低于 \(2\times10^{-6}\) 的验证容差。

电池储能量、带符号并网功率与日前电价

源代码

完整可运行示例见: examples/battery_energy_arbitrage.py