4. 充放电策略优化:分时电价机制解读、基于动态规划的充放电策略、利用历史数据优化充放电时机以提升套利收益
大家好,我是老张。今天咱们聊聊储能运营里最核心、也最直接能产生效益的话题——充放电策略优化。
说白了,储能系统能不能赚钱,很大程度上取决于你什么时候充、什么时候放。我见过不少项目,设备选型、安装都没问题,但运营策略太粗糙,结果一年下来收益少了好几百万。嗯,这其实挺可惜的。
所以这一章,我会把分时电价机制、动态规划算法、以及如何用历史数据来优化充放电时机,掰开揉碎了讲清楚。
核心观点:充放电策略优化的本质,是在电价低时买入(充电)、电价高时卖出(放电),赚取价差。但实际运营中,还要考虑电池寿命、效率损耗、容量衰减等因素。
4.1 分时电价机制解读
先聊聊分时电价。你想想看,电网公司为什么要把一天分成好几个时段、定不同的电价?
其实很简单。白天大家都在用电,尤其是上午10点到下午3点,工厂开工、空调全开,电网压力巨大。这时候发电成本高,电价自然贵。到了深夜,大家都睡了,用电量骤降,发电机组不能随便停机,多余的电只能低价卖。
分时电价,就是通过价格信号引导用户错峰用电。
我在广东做过一个项目,当地的分时电价是这样的:
| 时段 | 时间范围 | 电价(元/kWh) | 说明 |
|---|---|---|---|
| 低谷 | 00:00 - 08:00 | 0.25 | 夜间,用电需求低 |
| 平段 | 08:00 - 10:00 15:00 - 18:00 21:00 - 24:00 |
0.65 | 用电量适中 |
| 高峰 | 10:00 - 12:00 14:00 - 15:00 18:00 - 21:00 |
1.15 | 用电高峰期 |
| 尖峰 | 12:00 - 14:00 | 1.35 | 极端高峰时段 |
你看,低谷和尖峰之间的价差高达1.1元/kWh。如果储能系统能在低谷充满电,在尖峰时段放出去,每度电就能赚1.1元。扣除充放电效率损耗(一般90%左右),净收益也有0.9元/kWh左右。
个人经验:我建议你拿到一个项目后,先拉出当地过去一年的分时电价数据。有些地区一年会调整好几次电价时段,尤其是夏季和冬季可能不一样。别只看一张表就定策略,会吃亏的。
4.2 基于动态规划的充放电策略
好,知道了电价结构,接下来就是怎么充、怎么放的问题了。
最简单的策略是「两充两放」:低谷充、高峰放;平段再充、尖峰再放。但实际操作中,电池容量有限、充放电功率有限、还要考虑电池寿命,这就变成了一个优化问题。
我个人习惯用动态规划来解决。为什么?因为充放电决策本质上是一个多阶段决策问题——每个时段你都要决定:充多少、放多少、还是闲着。
动态规划的核心思想是:把一天分成N个时段(比如每15分钟一个时段),每个时段的状态就是电池的当前SOC(荷电状态)。然后从最后一个时段往前推,找到每个状态下最优的决策。
我画了一张流程图,帮你理解这个逻辑:
下面我给出一个简化版的动态规划代码示例。这个代码只演示核心逻辑,实际项目中还要考虑更多约束。
import numpy as np
def dp_charge_discharge(price, capacity=1000, max_power=250, efficiency=0.9, soc_min=0.1, soc_max=0.9):
"""
基于动态规划的充放电策略优化
:param price: 各时段电价列表,长度N
:param capacity: 电池容量(kWh)
:param max_power: 最大充放电功率(kW)
:param efficiency: 充放电效率
:param soc_min: 最低SOC
:param soc_max: 最高SOC
:return: 最优充放电计划
"""
N = len(price)
# SOC离散化,步长1%
soc_levels = np.arange(soc_min, soc_max + 0.01, 0.01)
M = len(soc_levels)
# dp[i][j] 表示第i个时段,SOC为soc_levels[j]时的最大累计收益
dp = -np.inf * np.ones((N, M))
# 记录决策
decision = np.zeros((N, M), dtype=int) # -1:放电, 0:闲置, 1:充电
# 初始化:第0个时段
for j in range(M):
dp[0][j] = 0 # 初始收益为0
# 动态规划递推
for i in range(1, N):
for j in range(M):
current_soc = soc_levels[j]
best_value = -np.inf
best_action = 0
# 尝试三种动作:充电、放电、闲置
for action in [-1, 0, 1]:
if action == 1: # 充电
# 充电后SOC增加,但受限于功率和容量
energy_in = min(max_power, (soc_max - current_soc) * capacity / efficiency)
new_soc = current_soc + energy_in * efficiency / capacity
cost = energy_in * price[i] # 充电成本
elif action == -1: # 放电
energy_out = min(max_power, (current_soc - soc_min) * capacity)
new_soc = current_soc - energy_out / capacity
revenue = energy_out * price[i] * efficiency # 放电收益
cost = -revenue
else: # 闲置
new_soc = current_soc
cost = 0
# 找到new_soc对应的索引
new_idx = np.argmin(np.abs(soc_levels - new_soc))
total_value = dp[i-1][new_idx] - cost
if total_value > best_value:
best_value = total_value
best_action = action
dp[i][j] = best_value
decision[i][j] = best_action
# 回溯找到最优路径
best_soc_idx = np.argmax(dp[N-1])
plan = []
for i in range(N-1, -1, -1):
plan.append(decision[i][best_soc_idx])
# 更新SOC索引(反向)
if decision[i][best_soc_idx] == 1:
energy_in = min(max_power, (soc_max - soc_levels[best_soc_idx]) * capacity / efficiency)
best_soc_idx = np.argmin(np.abs(soc_levels - (soc_levels[best_soc_idx] + energy_in * efficiency / capacity)))
elif decision[i][best_soc_idx] == -1:
energy_out = min(max_power, (soc_levels[best_soc_idx] - soc_min) * capacity)
best_soc_idx = np.argmin(np.abs(soc_levels - (soc_levels[best_soc_idx] - energy_out / capacity)))
plan.reverse()
return plan, dp[N-1][np.argmax(dp[N-1])]
# 示例:使用上面表格中的电价数据
price_data = [0.25]*8 + [0.65]*2 + [1.15]*2 + [1.35]*2 + [1.15]*1 + [0.65]*3 + [1.15]*3 + [0.65]*3
plan, total_profit = dp_charge_discharge(price_data)
print(f"最优策略总收益:{total_profit:.2f} 元")
print(f"充放电计划(-1放电,0闲置,1充电):{plan[:10]}...")
避坑指南:我曾经在一个项目中直接用这个算法跑出来的策略去控制储能系统,结果发现电池的循环寿命衰减得特别快。后来才意识到,动态规划默认每次充放电都是满功率,但频繁的大功率充放电会加速电池老化。所以后来我在目标函数里加了一项「电池衰减成本」,效果好了很多。
4.3 利用历史数据优化充放电时机
动态规划虽然好,但它依赖一个前提——你得知道未来的电价。分时电价是固定的,这个没问题。但实际运营中,还有一个变量会影响你的收益:负荷曲线。
什么意思呢?如果你的储能系统是给某个工厂配套的,工厂的用电负荷每天都不一样。有时候负荷高,你需要放电来降低需量电费;有时候负荷低,你可以多充电来套利。
所以,我建议你用历史数据来优化充放电时机。具体做法分三步:
- 数据清洗与特征提取:收集过去1-2年的负荷数据、电价数据、天气数据。剔除异常值,比如设备检修日、节假日等。
- 负荷预测:用LSTM或XGBoost模型预测未来24小时的负荷曲线。我个人习惯用XGBoost,因为它训练快、解释性强。
- 联合优化:把预测的负荷曲线作为输入,结合分时电价,用动态规划重新计算最优充放电计划。
下面是一个简单的数据驱动优化流程:
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor
# 假设已有历史数据
def load_forecast(historical_data, target_date):
"""
基于历史数据预测目标日期的负荷曲线
"""
# 特征工程:时间特征、温度、节假日等
features = ['hour', 'day_of_week', 'month', 'temperature', 'is_holiday']
X = historical_data[features]
y = historical_data['load']
model = GradientBoostingRegressor(n_estimators=200, max_depth=5)
model.fit(X, y)
# 预测目标日期的24小时负荷
target_features = extract_features(target_date)
predicted_load = model.predict(target_features)
return predicted_load
# 联合优化:将预测负荷纳入约束
def optimize_with_load_forecast(price, predicted_load, battery_params):
"""
结合负荷预测进行充放电优化
核心思想:在负荷高峰时段优先放电(降低需量电费),
在负荷低谷时段优先充电(利用低价电)
"""
# 这里可以复用上面的动态规划函数,但需要修改目标函数
# 目标 = 套利收益 + 需量电费节省 - 电池衰减成本
pass
个人经验:我建议你至少用3个月的历史数据来做模型训练。数据太少了,模型容易过拟合。另外,别忘了考虑季节性因素——夏天的负荷曲线和冬天完全不一样,空调负荷占比很大。
4.4 实战中的几个关键点
最后,我总结几个实战中容易踩的坑:
- SOC不要跑满:我见过有人为了多套利,把电池充到100%、放到0%。结果半年后电池容量衰减了15%。记住,锂电池最舒服的工作区间是20%-80%。
- 考虑充放电效率:充放电效率不是100%,你充进去1度电,放出来可能只有0.9度。这个损耗在计算收益时一定要算进去。
- 动态调整策略:电价政策可能会变,负荷模式也会变。我建议每个月重新跑一次优化模型,不要一套策略用一年。
- 别忘了维护时间:储能系统需要定期维护,比如BMS校准、冷却系统检查。这些时间要预留出来,别让策略把维护时间也排满了充放电。
好了,关于充放电策略优化,核心内容就这些。说白了,就是「低价买、高价卖」这六个字,但真正做好,需要把电价机制、优化算法、历史数据这三样东西结合起来。希望今天的分享对你有帮助。
公众号:蓝海资料掘金营,微信deep3321