
前阵子做多微网电能交易仿真最大的体会就是多微网交易策略这件事看起来是电力系统问题本质上是利益分配问题。几个微电网聚在一起各自有光伏、储能、负荷白天有人多余电晚上有人缺电怎么定价才能让大家都愿意参与内部交易而不是一股脑都去找主网我用非合作博弈模型在MATLAB里做了一套动态定价仿真把交易策略完整跑通了。今天把建模思路、价格迭代机制、代码实现和调试经验一次性整理出来给想在这个方向起步的朋友做个参考。整篇内容不吹概念直接讲能跑的框架和真实踩过的坑。1. 多微网交易到底难在哪先看问题模型1.1 一个具体场景三个微网各怀心思先构造一个我经常用的算例场景。园区里有三个微电网姑且叫 A、B、CA 网光伏装机量大白天发出来的电远大于自身负荷盈余很多但傍晚之后就基本靠储能撑着B 网是办公楼区域白天负荷高屋顶光伏只能覆盖一部分属于典型的“白天缺电户”C 网有一个容量比较大的储能和部分可调负荷白天可以存电晚上可以放电还有点灵活性。三个微网都接入同一个配电台区物理上可以互相交易也可以各自找主网购售电。问题是A 网多余的电要不要卖给 B 网以什么价格卖C 网储能什么时候充满、什么时候释放如果三个微网都只想着自己利益最大化最后能不能达成的那个状态是不是对整体也足够好这类问题在过去并不算突出因为大量微网都是“自发自用、余电上网”按固定的上网电价和购电电价跟主网结算。但现在微网越来越多再去套单一电价的模式就会出现两个尴尬局面白天光伏大发的时候多个微网同时涌向主网卖电主网消纳压力很大晚上负荷高峰几个缺电微网又同时向主网购电配变很容易顶不住。明明局部就有供需互补空间却因为缺少合理的价格信号谁也调动不起来。1.2 为什么集中优化方案不好用很多人第一反应是既然要让系统总体最好那干脆由调度中心统一优化算了。把所有微网的光伏出力、负荷预测、储能SOC、设备约束全部收上来求解一个全局最优然后下发每个微网的充放电指令。这在数学上确实可行也确实能得到系统层面的最优解但实际落不了地。原因有三个。第一微网属于不同利益主体没有义务把自己的真实运行数据完整上报给别人尤其是涉及成本和边界约束的信息。第二集中优化把微网变成了“执行单元”剥夺了它们自主决策的权利一旦优化结果让某个微网明显吃亏它根本没有动力配合。第三集中模型规模一大全网联合优化很容易出现“一个主体数据更新全盘重算”的情况计算效率和维护成本都很高。所以我在这个项目里最终没有走集中优化路线而是选了非合作博弈。本质上就是让每个微网自己当决策者在统一的市场规则和价格信号下各自优化通过价格来回迭代找到一个谁都不想单方面改策略的“纳什均衡”状态。这种方法不需要任何微网公开自己的成本函数只需要它们基于价格给出电量和交易响应对隐私保护和分布式落地的友好程度高很多。用一个不太严谨但很形象的类比集中优化像是学校食堂统一配餐虽然营养搭配可以做到全校最优但众口难调大家不满意也没得选非合作博弈更像是自由菜市场每个摊位自主定价买菜的人根据价格选菜最后价格自动调整到大家都能接受的位置。1.3 非合作博弈建模的核心要素建立博弈模型先要把三个基本要素定义清楚参与者所有参与电能交易的微电网设为 N 个编号 i 1, 2, ..., N策略空间每个微网可以控制的变量包括每个时段向市场申报的购电量、售电量储能充电/放电功率等收益函数每个微网在某种策略组合下获得的效用一般是运行收益减去购电成本再减去储能损耗、弃光惩罚等。在这个框架里每个微网的决策不是孤立的。A 网想多卖电但能不能卖出去取决于当前市场价格和 B、C 网愿意买多少B 网想少买点高价电但能不能做到取决于自己的负荷刚性和 C 网储能是否愿意在晚间放电。价格就是连接所有决策的纽带。纳什均衡的定义也很直白给定其他微网的策略不变任何一个微网单独改变自己的策略都不可能获得更高的收益此时所有微网的策略组合就是一个均衡。我在仿真里要找的就是这个策略组合。2. 动态定价机制让价格自动反映供需2.1 价格更新方程的设计逻辑博弈模型确定了“谁在决策”还需要一个“价格从哪来”的机制。我采用的是迭代式动态定价不依赖集中出清而是通过观察每个微网的响应持续修正市场价格。假设内部交易市场采用统一电价 p单位是元/kWh。给定价格 p(k)每个微网会优化出一个购售电量结果。把第 k 轮所有微网的净购电需求累加I(k) sum(P_buy_i(k)) - sum(P_sell_i(k))如果 I(k) 大于 0说明当前价格下买方需求大于卖方供给价格应该往上调如果 I(k) 小于 0说明供大于求价格应该往下压。标准的价格更新公式写成p(k1) p(k) tau * I(k)其中 tau 是价格调整步长数值越大收敛越快但太大容易振荡。我实测下来tau 取 0.01 到 0.05 之间比较稳具体要看系统容量基数和价格量纲。价格上下界可以设在主网购电电价和上网电价之间避免交易价格被调到不合理区间。这个机制很像“看不见的手”的离散版本。最妙的地方在于它不需要知道每个微网内部的成本函数只需要观察微网对当前价格的响应量。每个微网都是黑箱市场只跟它们要一个“在这个价格下你买多少、卖多少”的答复。2.2 微网内部优化目标函数与约束价格更新只负责协调真正决定交易行为的是微网内部优化模型。对微网 i给定外部价格 p 后它需要求解一个单主体优化问题目标函数我一般写成max sum_t [ p_t * P_sell_i(t) - p_t * P_buy_i(t) - c_loss * P_ch_i(t) - c_curtail * P_abandon_i(t) ]其中P_sell_i(t) 是微网 i 在 t 时段卖到市场的功率P_buy_i(t) 是 t 时段从市场买进的功率P_ch_i(t) 是储能充电功率充电过程有损耗成本系数 c_loss 用来刻画电池循环损耗P_abandon_i(t) 是弃光功率给它一个惩罚系数 c_curtail让模型不会为了省钱随便弃掉清洁能源。除了目标函数约束条件才是微网优化真正的骨架功率平衡约束光伏出力加储能放电加购电必须等于负荷加储能充电加售电储能SOC动态约束下一时段SOC等于当前SOC加上充电效率系数和放电效率系数折算后的净电量SOC上下限约束一般限制在 0.1 到 0.9 之间防止电池过充过放充放电功率上限约束储能功率不能超过额定值购售互斥约束同一时段要么买要么卖不能同时又买又卖这个在优化里很重要不然模型会利用买卖价差做无意义的套利。这个子问题的目标函数如果是线性或二次的加上线性约束之后是凸优化MATLAB 里的 fmincon 可以直接求解。如果不考虑储能非线性损耗甚至可以退化成线性规划用 linprog 更快。2.3 纳什均衡与收敛判断价格迭代机制最终要回答一个问题迭代到什么时候算完我这里用两个收敛判据满足任意一个都认为达到均衡价格变化量小于阈值也就是 abs(p(k1) - p(k)) eps_p系统总净购电需求逼近 0也就是 abs(I(k)) eps_I。两个判据说的其实是一回事当总供需基本平衡且价格不再明显变化时所有微网给出的策略已经互相匹配谁也没法靠单方面改策略获得更多收益。这个状态就是纳什均衡。有朋友问过我是不是一定能收敛理论上如果每个微网子问题都是凸优化且价格更新映射满足单调性迭代会收敛到均衡但实际工程里目标函数如果加入了非线性的储能老化项、弃光惩罚项可能破坏全局收敛性。所以我在仿真里从来不只是盯着“收敛”两个字还会检查收敛点对应的总交易成本确认它不是被某个局部极值带偏。3. MATLAB代码实现从博弈模型到可跑仿真3.1 数据准备光伏出力、负荷与储能参数我习惯先造一组 24 个时段的基础数据做方案验证时用“小时级分辨率”最省事。每个微网的数据结构用一个 struct 存起来包含光伏预测曲线、负荷曲线、储能额定容量和功率、初始SOC等。下面这段代码是数据初始化部分clear; clc; N 3; % 三个微网 T 24; % 24小时 dt 1; % 时间步长单位h % 典型光伏出力标幺曲线简单模拟实际项目请替换为预测数据 pv_shape [0 0 0 0 0 0.1 0.3 0.6 0.85 0.95 1.0 0.95 0.9 0.75 0.55 0.3 0.1 0 0 0 0 0 0 0]; pv_cap [1.2, 0.6, 0.8]; % 各微网光伏装机单位MW load_profile [0.4 0.35 0.3 0.28 0.3 0.45 0.7 0.9 1.0 0.95 0.9 0.85 ... 0.8 0.85 0.9 1.0 1.1 1.2 1.05 0.9 0.8 0.7 0.6 0.5]; mg(1).pv pv_shape * pv_cap(1); mg(2).pv pv_shape * pv_cap(2) * 0.9; % B网光伏弱一些 mg(3).pv pv_shape * pv_cap(3) * 0.7; mg(1).load load_profile * 0.6; mg(2).load load_profile * 1.1; % B网负荷大 mg(3).load load_profile * 0.7; mg(1).E_max 0.4; mg(1).P_max 0.2; % 储能容量/功率上限单位MWh/MW mg(2).E_max 0.2; mg(2).P_max 0.1; mg(3).E_max 0.8; mg(3).P_max 0.4; for i 1:N mg(i).soc0 0.3; mg(i).eff_c 0.95; % 充电效率 mg(i).eff_d 0.9; % 放电效率 end实际项目里 pv_shape 和 load_profile 应该来自预测系统可以用光照辐照度数据折算光伏出力用历史负荷曲线做相似日预测。这里先用平滑曲线验证算法逻辑。3.2 单微网优化子问题求解每个微网在给定电价 p 下需要求解自己的最优买卖电量和储能充放电计划。我这里写一个函数核心思路是定义决策变量、目标函数、约束然后调用 fminconfunction [buy, sell, soc] solve_microgrid(p, data) % p: 当前交易电价1xT向量 % data: 微网数据包含 pv, load, E_max, P_max, soc0, eff_c, eff_d T length(p); % 决策变量buy(1:T) sell(1:T) ch(1:T) dis(1:T) x0 zeros(4*T, 1); % 目标函数最大化收益同时惩罚弃光 pv data.pv; load data.load; E_max data.E_max; P_max data.P_max; soc0 data.soc0; eta_c data.eff_c; eta_d data.eff_d; c_curtail 0.05; % 弃光惩罚系数 fun (x) objective(x, p, pv, load, c_curtail, T); % 约束 Aeq []; beq []; lb zeros(4*T, 1); ub [inf(T,1); inf(T,1); P_max*ones(T,1); P_max*ones(T,1)]; % 非线性约束功率平衡与SOC递推 nonlcon (x) constraints(x, pv, load, E_max, P_max, soc0, eta_c, eta_d, T); options optimoptions(fmincon, Display, off, ... Algorithm, interior-point, MaxIterations, 500); [x_opt, ~] fmincon(fun, x0, [], [], Aeq, beq, lb, ub, nonlcon, options); buy x_opt(1:T); sell x_opt(T1:2*T); ch x_opt(2*T1:3*T); dis x_opt(3*T1:4*T); % 计算SOC曲线 soc zeros(T1, 1); soc(1) soc0; for t 1:T soc(t1) soc(t) (ch(t)*eta_c - dis(t)/eta_d) * 1; end end目标函数的实现另外写。这里有几个经验值得提储能充电功率和放电功率要同时放进变量里然后通过 SOC 约束和功率上限间接限制不要直接用 buy 和 sell 代表储能的充放否则建模容易混为了让 fmincon 更快收敛x0 不要给全零向量可以先用 linprog 解一个忽略非线性约束的版本把结果作为初值如果目标函数里包含弃光惩罚最好把弃光量显式表达成 max(0, pv dis - load - ch - sell) 之类形式但这个 max 操作是非光滑的我一般用一个小技巧把弃光也设成决策变量并加约束 pv dis buy load ch sell curtailcurtail 0这样全程保持线性约束。3.3 主循环价格迭代与均衡搜索单微网子问题解决了剩下的就是把 N 个微网串起来跑价格迭代主循环% 参数设置 p_max 0.8; % 交易市场上限价格 p_min 0.2; % 交易市场下限价格 p0 0.4; % 初始价格 tau 0.02; % 价格调整步长 Kmax 200; % 最大迭代次数 tol_price 1e-3; tol_balance 1e-3; p p0 * ones(1, T); for k 1:Kmax total_buy zeros(1, T); total_sell zeros(1, T); for i 1:N [buy_i, sell_i, soc_i] solve_microgrid(p, mg(i)); mg(i).buy buy_i; mg(i).sell sell_i; mg(i).soc soc_i; total_buy total_buy buy_i; total_sell total_sell sell_i; end imbalance total_buy - total_sell; p_new p tau * imbalance; p_new min(max(p_new, p_min), p_max); if max(abs(p_new - p)) tol_price max(abs(imbalance)) tol_balance fprintf(收敛于第%3d轮最终均价 %.3f 元/kWh\n, k, mean(p)); break; end p p_new; end这个主循环看着简单其实已经把博弈求解的核心逻辑覆盖了外层迭代价格内层解每个微网的优化子问题然后根据市场总供需修正价格循环到均衡。如果迭代次数到了 Kmax 还没收敛多半是 tau 太大或者初始价格选得离均衡太远。3.4 绘图与结果导出分析结果时我一般画三张图配套的代码非常短figure; subplot(3,1,1); plot(1:T, p, o-); grid on; xlabel(时段 (h)); ylabel(价格 (元/kWh)); title(动态定价演化结果); subplot(3,1,2); bar(1:T, [mg(1).sell - mg(1).buy; mg(2).sell - mg(2).buy; ... mg(3).sell - mg(3).buy], stacked); xlabel(时段 (h)); ylabel(交易功率 (MW)); legend({微网A,微网B,微网C}, Location, best); title(各微网净交易功率); subplot(3,1,3); hold on; for i 1:N plot(0:T, mg(i).soc, -); end hold off; grid on; xlabel(时段 (h)); ylabel(SOC); title(储能SOC轨迹);第一张图看价格有没有收敛到合理区间第二张图看各个微网的交易方向是否符合预期第三张图检查储能没有触碰到上下界。这三张图基本能判断一轮仿真是否靠谱。4. 仿真结果与参数敏感性分析4.1 交易量、价格演化曲线跑完一天的仿真我通常会得到几类比较典型的画像。价格曲线在午间会出现明显低谷因为 A 网光伏大发市场上卖电供给充足价格被压到接近上网电价的位置晚高峰时段 B 网负荷上升C 网储能也开始放电报价市场购电需求集中价格抬升。整个价格曲线呈现出“午间低、傍晚高”的波动形态比固定电价更能反映供需关系。交易量方面A 网在午间大量卖出光伏盈余B 网在白天买入C 网则呈现出“中午充、傍晚放”的套利型行为。最终系统对主网的净购电量明显下降内部交易量上升。这说明动态定价确实刺激了微网之间的余缺互济。值得强调的是达到均衡时没有任何一个微网可以通过单方面改变买卖策略获得更高收益。换句话讲价格信号已经把所有微网的出力、储能、交易行为拉到了一个互相匹配的状态。4.2 三种定价策略对比为了验证动态定价的工程价值我把固定电价、分时电价、博弈动态定价放在同一组数据下做了对比。结果用一张表总结对比维度固定电价分时电价非合作博弈动态定价内部交易量低微网之间几乎没有互动中等峰谷价差能引导部分交易高价格随供需自动调整光伏消纳率有弃光风险较好最好卖方微网主动下调报价促进消纳系统总运行成本偏高中等可进一步降低微网收益公平性单一价格对所有主体一刀切价差固定灵活微网占便宜按供需贡献分配收益各方自主性高模型复杂度最低低中等需要迭代求解表格里的结论并不是说博弈动态定价一定在所有指标上碾压其他策略而是说在“多主体自主决策”的大前提下它更有希望同时兼顾整体效率和个体理性。4.3 储能容量与价格弹性的影响参数敏感性分析我重点看了两个变量。一个是储能容量。当某个微网储能容量增大时市场的“蓄水池”作用更明显价格曲线波动幅度会收窄尤其是在光伏高峰时段储能吸纳多余电能阻止价格过度下跌晚高峰时段储能释放电能抑制价格过快上涨。反过来储能容量太小价格很容易在几个小时内大幅波动甚至触发价格上下限约束。另一个是负荷的价格弹性。如果微网负荷对价格完全不敏感任何价格更新都只能通过储能调节市场对供需的响应能力有限如果能允许一部分可调负荷根据价格平移市场可以明显更快收敛均衡价格的波动也更小。实际工程中那些带柔性负荷的微网往往在交易博弈里更有竞争优势。5. 实操中的坑与排查清单5.1 迭代振荡的处理我最先跑通的版本用 tau 0.1 进行价格更新结果价格在 0.3 和 0.7 之间来回震荡始终收敛不到均衡。原因是价格步长太大微网对价格过于敏感这轮价格升高导致大家集体少买多卖下一轮价格又被打下去。解决办法有两种。第一种是把 tau 减小比如从 0.1 降到 0.02系统会稳定很多第二种是给价格更新加一个低通滤波也就是 p(k1) p(k) alpha * (tau * I(k))其中 alpha 在 0.3 到 0.7 之间。本质都是降低单次价格修正的幅度让微网响应不要被反复放大。遇到振荡先别改模型先调这两个系数多数情况能解决。5.2 fmincon常见崩溃原因很多人在 MATLAB 里跑类似模型时会报 undefined function or method optimoptions。我遇到过几次基本都是两个原因一是当前 MATLAB 版本没有安装 Optimization Toolbox或者 License 没配置好二是脚本里用了高版本新增的选项老版本不认识。检查方法很直接在命令行输入 ver 查看工具箱列表确认 Optimization Toolbox 存在如果存在但仍报错把 optimoptions 换成 optimset或者统一用 Display,off 搭配 optimoptions 的旧语法。另一次教训是 fmincon 初始点给得离可行域太远导致模型提示约束冲突。解决方案是先解除储能SOC约束用线性规划跑一个松弛结果做初值。5.3 初始电价敏感性与多均衡问题非合作博弈模型不是随便给个初始价格都能收敛到同一个结果。如果初始价格定在接近购电价格上限微网会倾向于大量卖电导致市场供过于求价格一路被打压最终可能收敛到一个低交易量、低均衡价格的角点如果初始价格定在接近上网电价下限结果又可能走向另一个方向。我的经验是把初始价格选在主网购电价和上网电价之间的中点或者用历史交易价格的平均值做初值。另外检验多均衡的方法是分别从多个初始价格出发跑仿真对比均衡价格和成本。如果收敛点差异太大需要检查是不是效用函数非凸、储能约束过强导致可行域被拆开。此时可以适当增加储能充放电损耗成本系数让目标函数更接近严格凸均衡更稳定。5.4 仿真效率优化技巧当微网数量从 3 个增加到 20 个时段从 24 增加到 96 个单轮求解量会指数增长。我试过最笨的办法是串行循环跑一次完整仿真要几分钟调一次参数等很久。后来做了三处优化。第一把每个微网的子问题从 fmincon 换成更快的线性规划或二次规划只要模型允许能用 linprog 或 quadprog 就尽量不用通用非线性优化器。第二把主循环里的微网求解改成 parfor 并行因为每个微网在当前价格下的优化是互相独立的天然适合并行。第三如果只是做机制验证先在 24 时段尺度上把算法跑通再扩展到 15 分钟粒度不要一上来就到 96 个时段。我在实际跑这套模型时最深的感受是博弈模型的均衡不只是数学上存在就算完事。价格更新机制的稳定性、求解器选型、初值设置这些工程细节才是真正决定模型能不能落到项目里的关键。如果你也准备做多微网交易策略建议先从 3 个微网、24 时段的场景起步把价格迭代、储能约束、数据精度这些环节调顺再逐步扩展到大网络。后面如果想继续往深走还可以把微网之间的网络拓扑约束、需求响应机制、以及新能源出力的随机性并进来那算是这个方向的下一层玩法了。