光储充换电站分时电价与用户负荷互动双层优化模型及Matlab复现

发布时间:2026/10/13 12:16:10
光储充换电站分时电价与用户负荷互动双层优化模型及Matlab复现 光储充换电站这个概念最近两年有多热看看知网就明白了——尤其是“分时电价”和“用户负荷”两个词几乎成了这类论文标题的流量密码。但真正动手复现过的人都知道大多数公开代码只给你一张固定电价表去调度用户完全是被动接收指令而这个标题里的“互动”两个字才是整套模型的真正分水岭。这个模型的核心逻辑不复杂站点先给出一版分时电价用户看到电价后调整自己的充电时间和充电量形成新的负荷曲线站点再基于这条新曲线重新优化电价和储能策略跑几轮之后收敛到一个双方都能接受的平衡点。说白了这是一个“运营商定价”与“用户用脚投票”相互咬合的闭环优化问题。它能干的实事儿不少输出一套可执行的分时电价建议、给出储能和换电电池的充放电计划、评估用户负荷转移后的削峰填谷效果、算清楚运营商的日收益构成。对于电力方向刚入门的研究生这是一个练手价值很高的Matlab复现项目对于做充电运营平台或者光储站规划的人这套模型也能直接拿来当仿真推演工具提前判断定价策略和储能配置是否合理。我在Matlab里完整复现过一版跑通之后最大的感受是模型本身的数学难度不算高真正的坑全在“用户响应怎么建”和“双层迭代怎么收敛”这两件事上。下面按建模思路、代码实现、踩坑排查、扩展方向这个顺序把整个复现过程一步一步拆开讲。1. 模型在设计什么客流、电价、电池的三方博弈1.1 光储充换电站和普通充电站的本质区别普通充电站就是电网取电最多加个储能做峰谷套利结构简单。光储充换电站是“四合一”结构屋顶光伏发电、站内储能调峰、直流快充桩给车充电、换电通道直接更换整包电池。这四个部分通过一条直流母线或交流母线耦合成一个微型电力系统而用户的充电和换电行为决定了这条母线上的负荷曲线。光伏出力、储能SOC、换电电池库存、排队用户数量全都是优化模型的输入或约束条件。有一个容易被忽略的设计点普通充电站只有“电”这一种能量载体而换电站手里握着一批可更换的电池组。这批电池不但在车上是动力源在站内就是天然的储能资源——低谷时段可以把电池充满高峰时段既能供车换电多余电量还能反哺母线。这就是光储充换电站在调度灵活性上比单纯光储充站点多出来的那部分优化空间代码里如果不单独建模模型价值会大打折扣。1.2 分时电价在这里是决策变量不是历史数据很多人一听“分时电价”就以为是电网公司公布的峰谷平固定表拿来当输入参数。但这个模型里分时电价是优化模型的决策变量。运营站在电网允许的价格上下限内自己设计一天24个小时的电价曲线目标很现实引导用户在光伏出力最大的午间时段充电把站内光伏和储能资源吃干榨净同时避开晚高峰买电减少购电成本。“互动”这个词有两层含义。第一层是电价发生变化后用户会调整充电行为——原来打算晚上七点充一小时的用户看到下午两点电价便宜就可能改到两点来充。第二层是用户调整后的负荷曲线会反过来影响下一轮电价优化的结果。这是一个闭环不是一个单向的调度指令。用生活里的场景类比充电站就像一个给不同时段不同折扣的餐厅用户就是看折扣安排吃饭时间的食客。餐厅发现工作日中午人少就把午餐时段折扣加大客人来了客单价和翻台率也上去了。这个模型做的就是“动态折扣设计”这件事只不过折扣变成了每小时的实时电价客流变成了充电负荷。1.3 这个模型解决的三个真实痛点我梳理了三个直接用钱衡量的痛点这也是模型输出结果最值钱的地方。一是弃光问题。光伏中午出力猛但那个时段大家都在上班充电需求低多余光伏要么白白限掉、要么上网卖个低电价。通过电价引导让用户把充电需求挪到午间弃光率能明显降下来。二是晚高峰变压器过载。下班后扎堆充电负荷尖峰把变压器顶得很高扩容成本动辄几十上百万。通过分时电价的杠杆把一部分负荷平移到下午和深夜尖峰负荷直接削平站内设备利用率反而更高。三是换电备用电池的库存决策。电池备多了压资金备少了高峰期用户排队骂街。模型里把换电电池组也纳入调度根据预测负荷和电价信号决定“低谷多充几组、高峰留多少组”相当于把库存问题从拍脑袋变成了优化求解。2. 数学骨架目标函数、响应机制与约束边界2.1 目标函数的两条路线单层收益与双层互动目标函数的建法分两类。如果站在运营商角度模型是收益最大化max R 充电售电收入 换电服务收入 光伏上网补贴 − 电网购电成本 − 储能循环损耗 − 换电折旧费用如果站在用户角度目标是充电成本最小化。但标题里强调的是“互动”所以更合理的框架是双层模型——上层是运营商制定分时电价追求收益最大下层是用户接收电价后调整充电行为追求自身成本最小。复现时双层模型有三条技术路线。第一条是用KKT条件把下层用户问题转化为上层的约束条件写成单层混合整数规划求解第二条是外层用粒子群或遗传算法搜索电价内层用线性规划或二次规划求解用户响应和储能调度第三条是用主从分裂的迭代思路两层交替求解直到结果收敛。我的建议是初学复现优先走第二条路线也就是“启发式算法外层 线性规划内层”。这条路线逻辑清楚每一层都能单独验证对错出了问题方便排查。KKT转化那条路线虽然求解效率高但对数学功底要求高代码一旦报错很难定位是约束错还是对偶变量错。2.2 用户负荷对电价的响应如何表达用户充电负荷的响应建模是整个模型里最见功力的部分。最常用的是价格弹性模型用一个系数反映需求量对价格变化的敏感度P_response(t) P_base(t) × (1 ε × (price(t) − price_ref) / price_ref)其中ε是需求价格弹性系数通常取−0.1到−0.5。ε取−0.3的意思是电价相对参考价上浮10%该时段充电量下降3%。但这个简单模型有一个明显的缺陷它只调整了单个时段的负荷大小没有体现“负荷转移”这个真实行为。用户今天不充这200公里电不代表他不充了而是他会换个便宜时段来充。所以更精细的做法是引入可转移负荷矩阵把某个时段的负荷按比例转移到相邻几个时段。我在实际建模时还会把用户分成三类刚性用户必须当下充电对电价无感弹性用户对价格敏感愿意把充电时间挪到低价段换电用户关心的是电池能不能及时换上对等待时间敏感对电价相对钝感。三类用户的比例不同整个站点的价格弹性就不同。没有实测数据时可以用正态分布随机生成用户的到达时间和充电需求再按比例合成基础负荷曲线最后匹配一个聚合弹性系数。还有一个很多复现代码都会犯的错误响应模型计算出的总充电量发生了漂移。真实场景里用户一天的总充电量基本由出行需求决定电价改变的是“什么时候充”不是“充不充”。所以我在响应函数最后加了一步总量守恒修正把响应后的总电量按比例归一化回响应前的水平这一步直接决定了后面功率平衡约束能不能闭合。2.3 储能与换电电池的特殊约束储能约束是电力系统的老面孔但对于复现新手SOC更新式子里效率和单位的坑很大。正确的离散格式是SOC(t1) SOC(t) (η_ch × P_ch(t) − P_dis(t) / η_dis) × Δt / E_bat其中P_ch是充电功率P_dis是放电功率η_ch和η_dis分别是充放电效率Δt是时间步长E_bat是储能容量。这个式子要求所有功率单位统一成kW容量单位统一成kWh时间步长统一成小时否则SOC会跑出[0,1]区间后面一切结果都是废的。换电约束是这个模型最有特色的地方。站内电池组数量有限每组电池有充放电状态、SOC状态、是否被装上车运走三个状态。每次换电行为消耗一组满电电池同时释放一组空电池进入充电队列。这个“让哪些电池在什么时段充电”的小决策本质上是一个资源调度子问题——把电池组看成n个虚拟储能单元每组的SOC和可用状态分开建模模型就立体了。峰值约束也不难关键是别漏充电桩数量对应的同时充电功率上限、换电工位数量对应的服务能力上限、电价必须在电网公司允许的价格区间内、光伏出力不能超过额定容量。约束不是越多越好但功率平衡等式和SOC上下限不等式是底线漏了模型就失真。2.4 输入数据从哪里来复现这样的项目需要四类输入数据。一是光伏出力曲线可以用典型日的辐照度数据配合电站装机容量折算也可以从PVsyst导出全年数据截取典型日。二是基础充电负荷曲线可以用充电运营平台脱敏后的历史数据没有就用蒙特卡洛抽样生成典型工作日曲线。三是电网侧的购电价格和光伏上网电价。四是站内设备参数储能容量、充电桩功率、换电工位数、电池组容量这些。没有实际数据不是卡住的理由。用Matlab生成典型场景、跑多场景取期望值是这类复现论文项目的标准做法。关键是要在代码里留一个data_input函数统一管理所有数据来源后面换真实数据时只改这一个文件其他模型代码不动。3. Matlab代码复现框架、参数与逐段实现3.1 文件结构与执行顺序复现这种多层迭代模型最忌讳把所有代码堆在一个脚本里。我建议按执行顺序用数字前缀组织文件main.m % 主入口调用各模块 1_data_input.m % 参数和数据加载 2_pricing_layer.m % 外层电价优化主循环 3_user_response.m % 用户负荷响应函数 4_storage_dispatch.m % 储能和换电平抑策略 5_objective_evaluate.m % 站点收益目标函数 6_result_plot.m % 结果可视化用数字前缀的好处是执行顺序一目了然调试时能清楚知道谁拿了谁的输出。双层迭代模型里内层函数会被外层调用几十次如果函数封装不好后面改一个参数要连带改五个地方非常折磨。文件拆开之后单元测试也好做把每层函数单独喂一组已知数据验证输出是否符合预期再拼在一起联调。3.2 关键参数设置与数据口径我复现时用的一组典型参数如下参数取值说明光伏额定容量500 kW站顶光伏和车棚光伏合计储能容量1000 kWh磷酸铁锂电池组快充桩20 台 × 60 kW直流快充换电电池组50 组 × 60 kWh按单车型适配电池循环寿命3000 次折算循环折旧成本SOC上下限0.1 / 0.9保护电池需求价格弹性系数−0.3用户聚合弹性时间步长1 小时24 个决策时段开始写代码之前先把单位统一这件事办妥。论文里功率可能是MW时间可能是15分钟一个点代码里如果混着用SOC更新、购电成本计算全都会偏。我的习惯是先在代码开头加一段单位转换注释把所有数据统一到“kW、kWh、小时、元/kWh”后面所有公式都不用再纠结单位。3.3 用户响应函数弹性模型加总量修正用户响应是整个模型里最值得花时间打磨的函数。我实际用的实现是这样function P_res user_response(price, P_base, epsilon, ref_price) % 价格弹性需求响应模型 % price: 24x1 分时电价序列 % P_base: 24x1 基础充电负荷 % epsilon: 需求价格弹性系数 % ref_price: 参考电价用于归一化 P_res P_base .* (1 epsilon .* (price - ref_price) ./ ref_price); % 防止负荷被削成负值 P_res max(P_res, 0); % 总量守恒修正电价只改变充电时段不改变总充电需求 E_before sum(P_base); E_after sum(P_res); if E_after 0 P_res P_res * (E_before / E_after); end end这个函数逻辑不复杂但两个修正步骤是关键。第一步max截断防止高电价时段把负荷算成负数。第二步总量归一化保证响应前后的充电总电量一致。如果不做这两步后面的功率平衡和收益计算全会在边缘工况下出问题收益被高估或者被低估结果完全不可信。如果你想再精细一点可以在函数里加一个负荷转移耗时参数比如允许用户把充电需求向后转移最多2小时用循环把转移后的负荷叠加回去。但这会让计算量变大初版代码不建议搞这么复杂先跑通简单弹性模型再说。3.4 外层电价优化粒子群与目标函数外层负责搜索24个时段的电价序列。我用Matlab自带的particleswarm函数简单够用。由于24个变量如果完全自由搜索电价曲线会像一个锯齿现实中根本执行不了所以我在搜索空间设计上做了限制让每时段电价在参考基准价附近小范围浮动nvars 24; % 24小时电价 lb 0.3 * ones(nvars, 1); % 谷时电价下限 ub 1.2 * ones(nvars, 1); % 峰时电价上限 options optimoptions(particleswarm, ... SwarmSize, 50, ... MaxIterations, 100, ... Display, iter); [price_opt, fval] particleswarm((x) obj_station(x, pv, P_base, params), ... nvars, lb, ub, options);外层目标函数是站点收益的负值因为粒子群默认做最小化。目标函数内部串起整个链路function obj obj_station(price, pv, P_base, params) % 1. 用户响应产生新的负荷曲线 P_load user_response(price, P_base, params.epsilon, params.ref_price); % 2. 内层调度储能和换电电池计算电网交换功率 [P_grid, P_bat] storage_dispatch(price, pv, P_load, params); % 3. 计算收益项 revenue_sell sum(P_load .* price); % 充电售电收入 revenue_swap params.fee_swap * params.n_swap; % 换电服务费 % 4. 计算成本项 cost_buy sum(max(P_grid, 0) .* params.grid_price); % 购电成本 cost_bat params.battery_cost_per_kWh * sum(abs(P_bat)); % 电池循环损耗 % 5. 净利润取负作为粒子群目标 net_profit revenue_sell revenue_swap - cost_buy - cost_bat; obj -net_profit; end这里有两个容易被忽略的细节。第一个是购电成本用max(P_grid,0)计算因为P_grid可能为负负值代表光伏多余电量反送回电网那是收入不是成本。第二个是电池损耗的简化处理我按每充放一度电折算成本计入目标函数这样优化器不会不计代价地滥用储能结果更贴近工程实际。3.5 内层储能调度与功率平衡给定净负荷和电价后内层要决定储能什么时候充、什么时候放。最规范的做法是建一个小型线性规划变量是24个时段的储能充放电功率约束是功率平衡和SOC连续性。如果不想一上来就碰linprog我提供了一个规则版的过渡实现适合先验证逻辑function [P_grid, P_bat, soc_series] storage_dispatch(price, pv, P_load, params) T length(P_load); P_bat zeros(T, 1); soc params.soc_0; soc_series zeros(T, 1); for t 1:T P_net P_load(t) - pv(t); % 净负荷正为缺电负为光伏富余 if P_net 0 soc params.soc_max % 光伏富余且电池未满优先充电消纳 P_bat(t) max(P_net, -params.p_bat_max); elseif P_net 0 soc params.soc_min % 缺电且电池有余量优先放电 P_bat(t) min(P_net, params.p_bat_max); end % SOC更新注意充放电效率分开放置 soc soc (params.eta_ch * max(P_bat(t), 0) ... - max(-P_bat(t), 0) / params.eta_dis) / params.E_bat; % SOC饱和处理 soc min(max(soc, params.soc_min), params.soc_max); soc_series(t) soc; end % 电网交换功率 净负荷 - 储能出力 P_grid P_net_total(P_load, pv, P_bat); end这个规则版逻辑简单但有一个问题它没有全局视角不会为了避开高购电电价而提前在低谷蓄电。所以最终版本强烈建议换成linprog规范求解将SOC连续性约束写成矩阵不等式把“低谷充、高峰放”的套利空间真正优化出来。这也是复现质量和入门代码之间最大的分水岭。3.6 结果可视化四件套代码跑通之后出图是展示成果的关键一步。我常规输出四张图优化前后电价与负荷对比图、光伏出力与储能SOC和电网购电功率的多曲线图、各时段收益构成柱状图、电价负荷互动迭代收敛曲线。电价和负荷对比图用双轴表示figure; yyaxis left; stairs(1:24, price_opt, LineWidth, 1.5); ylabel(电价元/kWh); yyaxis right; plot(1:24, P_base, --, LineWidth, 1.2); hold on; plot(1:24, P_res, r-, LineWidth, 1.2); ylabel(充电负荷kW); legend(最优分时电价, 响应前负荷, 响应后负荷, Location, best); xlabel(时刻h); grid on;这张图是模型效果最直观的证明电价低的地方负荷鼓起来电价高的地方负荷瘪下去一眼就能看出削峰填谷的效果。迭代收敛曲线也很关键我一般是记录每一轮外层的收益值画出来看是否从锯齿状逐渐趋于平稳这是判断双层互动是否收敛的最快方式。3.7 双层迭代的终止条件主从迭代怎么停是个实操问题。我用三条经验准则电价变化量连续3轮小于0.01元目标函数变化小于0.1%达到最大迭代次数50轮防止死循环。只盯着目标函数变化是不够的因为电价的微小波动可能引起收益变化并不大但电价曲线还在振荡这种情况直接停掉结果看似稳定实则没收敛。把电价变化量加进去作为第二重判据能显著减少“假收敛”的情况。4. 复现踩坑与排查实录4.1 负荷为负、SOC发散、维度报错这三个是复现初期最常撞的墙我逐个说。负荷为负用户响应函数里弹性系数取得太猛某个高电价时段的基础负荷被削成负数。明明该时段没人充电了模型却出现负的充电功率功率平衡立刻崩掉。解决办法就是加max截断和总量归一化两个修正一起上。SOC发散SOC更新时充放电效率乘反了或者时间步长单位没统一导致SOC在循环里越跑越离谱甚至出现1.3这种超过上限的值。注意规范写法是“充电效率乘在充电项放电项除以放电效率”并且每步更新后强制做饱和处理把SOC卡在上下限之间。这个方法虽然粗暴但能防止数值意外带崩下一轮计算。linprog维度报错Matlab的linprog对变量维度极其敏感Aeq矩阵的列数必须和变量数量严格一致。我最开始图省事用全零矩阵慢慢填约束跑一次报一次错。后来把所有变量统一到一个State列向量里按顺序固定排列再用稀疏矩阵逐行生成约束一次通过。强烈建议从一开始就用这种“变量字典”的方式组织约束矩阵每一行约束都写注释说清楚“这是功率平衡等式”还是“这是SOC不等式”排查速度快十倍。4.2 双层迭代不收敛或锯齿振荡这是互动类模型复现最容易翻车的地方。我用粒子群加内层线性规划的方案通常要迭代20到40轮才能稳定收益曲线初期会有比较明显的抖动。如果收益曲线从头到尾都像锯齿一样上下乱跳大概率是电价搜索步长太大价格跨度过宽。解决办法有两个一是把粒子群的SwarmSize和MaxIterations加大到50和100以上二是对粒子群每次生成的price序列做一次平滑滤波限制相邻时段电价变化幅度在0.05元以内。第二招在工程上很常见因为现实中不可能出现相邻小时电价差出天际的定价策略加这个限制不仅收敛快结果也更可落地。还有一种情况是外层和内层目标函数的数值量级差太多收益目标是几十万元量级用户响应约束是几千kW量级粒子群在搜索时会偏向量级大的那一项。建议在目标函数里对各项做归一化或者给收益和成本分别乘权重系数平衡量级。4.3 复现问题速查表现象可能原因解决方案负荷响应后出现负值弹性系数过大或电价跨越太大截断至0再做总量守恒归一化SOC超过1或低于0充放电效率方向错、单位不统一修正效率公式加饱和处理linprog维度报错变量排列与约束矩阵不一致用变量字典稀疏矩阵构建约束双层迭代锯齿振荡价格步长过大搜索范围过宽限制单步价格变化加平滑滤波结果与论文数值对不上数据口径不同功率、价格单位混用统一kW/kWh/小时制仔细核对粒子群跑得非常慢内层调用了太多次线性规划适当减少粒子数量或者内层改用规则近似优化结果购电成本反而升高目标函数里P_grid符号处理错误检查max(P_grid,0)和min(P_grid,0)的使用这个表是我多次复现同类项目后整理出来的高频问题清单。基本都是数据口径和约束处理问题很少是算法本身的锅。5. 进阶方向从复现到能落地5.1 从确定性到随机场景目前模型用的是确定性的光伏和负荷曲线。真实场景里光伏受天气影响波动很大用户到达也有随机性。想往深做可以把输入改为场景生成加场景削减用蒙特卡洛抽样生成几百个天气和负荷场景再用K-means聚类选出有代表性的七八个场景每个场景算一次优化最后按场景概率加权得到期望收益。这样电价策略不再只对一个理想日有效而是对可能出现的多种情况都有鲁棒性。这个改动对代码结构来说不算伤筋动骨主要是在数据输入层加一个场景维度模型主体不变。但对于论文审稿或者实际决策可信度完全不是一个量级。5.2 从单站到集群协同单个站点做电价弹性的空间始终有限用户再怎么说也就那些。多站场景下不同站点的区域用户构成不同、光伏条件不同、储能配置也不同可以引入站间差异化电价引导用户在几个站点之间分流。比如A站光伏足、电便宜就引导用户去A站充B站变压器余量少就提高价格自动劝退一部分非刚需用户。这个方向是目前光储充换电领域比较热的集群协同调度代码上要在外层增加多站耦合约束比如总负荷不能超过区域变压器容量上限难度上了一个台阶但价值也明显更高。5.3 从离线优化到滚动时域控制论文里的优化常常是日内一次性求解完毕但工程落地更适合模型预测控制MPC的思路每15分钟滚动一次更新最新的光伏预测和需求预测只执行下一时刻的决策然后时间窗整体前移重新计算。这样做的好处是对光伏突变和用户临时变动反应快不会一条优化结果用到黑。Matlab里实现MPC可以直接用自带工具箱也可以用YALMIP配合求解器自己写滚动窗口。我实测下来对于光伏突变明显的阴雨天滚动窗口方案比单次离线优化方案的总收益能高出5%到8%这个差距是实打实的。我在复现这个模型时最大的体会是别急着调算法先把用户响应那层做对。这个模型的灵魂在于“互动”而这个互动最朴素的实现就是用户对电价的弹性响应。很多复现代码卡壳都是因为这个环节处理得不够真实——负荷凭空增减、忽略总量守恒导致后面所有优化结果全部失真。如果你的目标是把这套模型跑通并真正理解我的建议是第一个版本宁可全部用简单规则和线性规划把逻辑链路完整跑通再逐步升级成双层优化、随机场景、滚动控制。等你能画出一张“电价拉动负荷、负荷影响收益、收益反哺电价调整”的迭代收敛曲线时这个模型就算真正吃透了。到那个时候想换算法、换场景、换数据都会顺畅很多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询