ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

需求侧电能共享分布式交易:价值认同建模与ADMM求解

需求侧电能共享分布式交易:价值认同建模与ADMM求解 去年帮课题组把基于价值认同的需求侧电能共享分布式交易策略从论文标题复现成能跑出结果的Matlab程序时我最大的感受是这个方向真正要处理的不是电不够分的问题而是交易语言太粗糙的问题。需求侧电能共享里的每个参与者——屋顶光伏、储能、可调负荷——不再只是价格接受者他们手里开始有半张价格表既看电价也看对本地绿电的偏好。下面这份记录从价值认同怎么进入优化模型讲起讲到ADMM这类分布式求解策略的代码骨架最后补上我踩过的五个坑。适合正在做分布式交易复现、需求响应仿真或准备把多主体优化落成Matlab算例的人按图索骥能省不少时间。1. 集中式出清为什么量不出一笔带偏好的交易1.1 统一出清模型里的单一价格假设传统电力市场或调度中心做经济调度时典型做法是把全系统所有机组、负荷一起丢进一个集中式优化问题目标通常是运行成本最小化约束是全网功率平衡、线路潮流和机组出力上下限。出清结束后系统会得到一个——最多是分时段分区域的——统一边际电价。在这个范式里所有电能都被视为同质商品用户买到的究竟是隔壁楼光伏发的电还是远处火电机组发的电模型完全不关心结算单上也只有同一个价格。这套体系在电源侧以大规模火电、水电为主的时代非常高效因为发电商数量有限、成本曲线相对清晰电网调度也确实需要集中决策来保证安全。但当分布式光伏、小型储能、V2G充电桩、空调负荷聚合商大规模出现后需求侧不再是几十个大用户而是成千上万个屋顶和家庭。每个主体都有自己独特的用电曲线、光伏出力特性和心理价位统一出清的一把尺子开始失灵。尤其麻烦的是用户对电的价值判断并不完全等于财务成本。有人愿意为可再生能源支付溢价有人更在意本地供电的可靠性有人希望尽量提高自给自足比例以减少对主网的依赖。这些诉求在集中式模型里没有表达通道。你无法在目标函数里写上节点3的用户特别认可邻居家光伏的电愿意多出五分钱因为集中式框架下所有交易最终都汇总到同一个出清池里交易对象不可辨识。1.2 需求侧电能共享的真正痛点交易语言太粗糙需求侧电能共享这个词近年在论文里出现频率很高本质上就是把微网、楼宇群、园区内部的分布式资源组织起来让电能在邻居之间直接交易而不是所有富余电量都回流主网再买回来。它想解决的问题有两个一是缩短交易链条减少过网费和其他中间成本二是让绿色电力的环境价值在本地交易中体现出来。但把场景从统一出清切换到邻里直接议价之后一个核心问题立刻浮现交易价格到底怎么定如果还是只按边际成本定一个统一价格那和集中式出清没有本质区别。如果每个节点各自报价那怎么保证全网平衡怎么防止部分主体利用市场力抬价这时就需要一种能承载交互偏好、又能在分布式架构下收敛的定价机制这就是价值认同进入建模视野的原因。我简单举个例子说明价值认同的直观含义A楼白天光伏出力富余B楼白天负荷很大。按传统机制B从主网购电A把余电卖给电网两者不发生直接关系。但实际场景中B可能非常希望买A的绿电因为A的屋顶光伏离得近、能溯源、环保属性可验证B甚至愿意在零售电价基础上加价购买。这个愿意加价的额度就是价值认同系数。分布式交易策略要做的就是让这种偏好通过可计算的机制真实地反映到成交电量和成交价格上而不是靠一纸绿证或一个口号。2. 价值认同的数学化表达三种建模路径与选型依据2.1 路径一二次效用函数内嵌偏好系数把价值认同直接写进每个节点的效用函数是目前论文里最常见、也最容易和优化求解器对接的做法。假设节点 i 的净交易功率为 (x_i)规定 (x_i0) 表示向社区卖出、(x_i0) 表示从社区买入那么节点 i 的本地目标函数可以写成[ f_i(x_i) \frac{1}{2}\psi_i x_i^2 - \gamma_i x_i ]这里的 (\gamma_i) 就是价值认同系数。它出现在一次项上含义很直接(\gamma_i) 越大的节点越愿意在交易中多出力或者多接受较高的成交价。(\psi_i) 是二次项系数可以理解为节点因为调整自身用电/发电曲线而付出的不舒适成本——为了配合社区共享你可能要调整空调温度、改变电动车充电时间这些都不是没代价的。用二次函数的好处在于数学上严格凸存在唯一的局部最优解对后续ADMM迭代而言一阶条件可以直接解出闭式表达式不需要每个节点都调用内部求解器。后面我会给出具体公式和代码这个性质非常关键。从实际标定角度讲(\gamma_i) 也不难反推。如果某个用户在本地市场调研中表示当社区共享电价相比主网零售价高0.1元/度时我仍然愿意优先购买邻居光伏的电那就意味着他的价值认同至少值0.1元/度。把这笔溢价折算进目标函数的一次项系数即可。2.2 路径二与路径三偏好矩阵与双目标加权第二种做法是构建一个节点间的偏好权重矩阵 (W)其中元素 (w_{ij}) 表示节点 i 对来自节点 j 的电量的认可程度数值可以是1.0到1.5之间的乘数。结算时节点 i 从 j 购电的实际支付意愿变成 (w_{ij}) 乘以基础电价。这种表达在物理上非常直观价值认同直接表现为不同交易对之间的价格差异类似双边协商。但它也有明显代价矩阵是 (n \times n) 的社区节点数一旦超过几十个需要配置和校验的偏好参数就非常多而且难以保证矩阵的一致性——如果 i 对 j 的认同度高、j 对 k 的认同度高但 i 对 k 的认同度低这种三角关系很难自洽。第三种做法是双目标加权。主目标仍然是经济成本最小化或社会福利最大化第二个目标可以是本地消纳率、绿色电力占比或自给率然后把价值认同系数 (\theta) 作为两个目标之间的权重。这种做法在规划类问题里很常见因为政策考核指标通常就是绿色占比、消纳率这种宏观量。缺点是个体的偏好被平均化成了一个全局权重体现不出不同的人愿意为不同的事付不同的钱这一层意思和价值认同的本意略有偏离。建模方式数学形式对ADMM友好度参数标定难度典型适用场景二次效用函数内嵌偏好偏好项进一次项系数高可得闭式解低通过支付意愿反推用户偏好平滑、交易功率连续可调偏好权重矩阵交易对价格乘系数中需处理矩阵约束中n×n参数一致性难保证小规模社区、双边关系显著双目标加权经济目标 θ×绿色指标中依赖θ标定偏高θ缺乏物理锚点区域规划、政策考核指标2.3 为什么我推荐效用函数路径来跑Matlab如果你只是想把标题对应的策略快速复现成可运行的Matlab算例我强烈建议走第一种路径。理由有三个。第一凸性有保障。ADMM这种交替迭代算法对目标函数的凸性要求很严二次函数天然满足不会出现局部最优和振荡问题。第二闭式解让代码量大幅缩减。节点子问题的一阶条件大概率可以直接解出 (x_i^{k1}) 的表达式不需要在每个节点内部再嵌套调用 fmincon 或者 linprog。对动辄几百上千次迭代的分布式算法来说这个差别是数量级的。第三文献可比性高。查看近几年关于电能共享、产消者交易的论文绝大多数都用了类似形式的效用函数做算例复现后便于和已有结果做对比验证。用偏好矩阵或双目标加权当然也能做但想在论文里讲清楚收敛性和均衡性质会更费笔墨。3. ADMM分布式求解拆解每个迭代步都像一场小型社区谈判3.1 为什么不用集中式优化而坚持分布式很多第一次接触这个方向的读者会问既然目标函数都是二次凸函数直接用CVX或者fmincon解全局优化不就行了吗理论上可以但实际不行主要有三个原因。第一是隐私。集中式优化需要每个节点把完整的光伏出力预测、负荷曲线、储能SOC、成本函数统一上报到中心节点。居民用户几乎不可能接受这种程度的裸奔商业用户更不可能把自己的真实成本曲线交给第三方平台。分布式算法里大家只需要交换一个交易意向数值和一个价格信号内部曲线完全留在本地。第二是规模。分布式主体的数量动辄成百上千电网节点规模更是远超传统机组数量。集中式优化的决策变量维度和约束矩阵规模会变得非常大单次全局求解耗时无法接受。ADMM天然把一个大问题拆成 (N) 个独立的本地子问题节点多带来的只是迭代轮数略增而不是单次求解爆炸。第三是自治。城市园区、居民社区里每个主体都有独立决策权谁也不愿意被一个中心调度系统直接指挥你必须在第二时段少用2 kW。分布式交易的核心精神是协商不是命令。ADMM给出的是一套规则让大家在规则下自己迭代收敛这天然契合需求侧电能共享的社会属性。3.2 共识ADMM的更新流程与虚拟电价含义分布式交易里常用的求解框架是共识ADMMConsensus ADMM。它不是把目标函数揉成一个整体而是让每个节点在本地独立求解自己的子问题然后通过一个公共参考量达成全网一致。整个流程可以这样理解。假设社区的每个节点 i 有自己的本地问题[ \min_{x_i} f_i(x_i) ]同时全网有一个共识约束所有节点最终要接受一个共同的参考变量 (z)也就是每个节点的交易功率都应该收敛到同一个可执行计划上。为了避免这个约束太硬导致求解困难ADMM把约束条件吸收进增广拉格朗日函数里[ L_i f_i(x_i) \lambda_i^k (x_i - z_i^k) \frac{\rho}{2}(x_i - z_i^k)^2 ]其中 (\lambda_i) 是拉格朗日乘子(\rho) 是罚参数。每轮迭代分三步走每个节点根据当前的 (\lambda) 和 (z) 更新自己的 (x)平台或邻居关系网络汇总所有节点的信息更新公共参考量 (z)节点根据 (x) 和 (z) 的偏差更新 (\lambda)。这三步循环往复直到 (x) 与 (z) 的偏差和 (\lambda) 更新幅度都低于阈值。(\lambda) 的最终收敛值非常有物理意义它对应的是功率平衡约束的影子价格放到社区交易场景里就是社区内部虚拟共享电价。每次迭代中节点做的事情就好比在微信群里报了一个意向购买量群管理员把大家的数字取平均后发回一个参考值每个人再根据参考值和当前影子价格调整自己的申报。来回几十轮之后大家自动达成一个全社区都能接受的电量和价格均衡点。3.3 本地闭式解推导一个简化算例的数学骨架为了让后文的Matlab代码更好懂这里先把一个最简情况下的闭式解推导写出来。假设节点 i 的子问题为[ \min_{x_i} \frac{1}{2}\psi_i x_i^2 - \gamma_i x_i \lambda_i^k x_i \frac{\rho}{2}(x_i - z_i^k)^2 ]对 (x_i) 求导并令导数等于零得到[ \psi_i x_i - \gamma_i \lambda_i^k \rho(x_i - z_i^k) 0 ]整理后[ x_i^{k1} \frac{\gamma_i - \lambda_i^k \rho z_i^k}{\psi_i \rho} ]这个公式很干净没有内部循环没有矩阵求逆只需要做四则运算。在完全图拓扑下参考量更新可以写成全局平均[ z_i^{k1} \frac{1}{N}\sum_{j1}^{N}\left(x_j^{k1} \frac{\lambda_j^k}{\rho}\right) ]乘子更新为[ \lambda_i^{k1} \lambda_i^k \rho(x_i^{k1} - z_i^{k1}) ]需要强调一点(\lambda_i) 并不直接等于最终大家结算的电价它是影子价格信号。在二次项系数显著不为零时节点真实成交边际价格应写作 (\lambda_i^k \psi_i x_i^k - \gamma_i)。但如果 (\psi_i) 相对较小、(\gamma_i) 为主要价值系数把 (\lambda) 近似理解为虚拟共享电价在实际算例中误差可控。4. Matlab仿真骨架参数表、认同矩阵与ADMM主循环4.1 仿真的数据准备与场景设定我建议不要上来就搭一个几十上百节点的复杂系统先用5节点的社区微网跑通算法逻辑再逐步扩规模。这5个节点里最好同时包含光伏富余型负荷密集型带储能型这三种典型角色才能看出价值认同对交易流向的影响。场景参数包括各节点的光伏出力 (PV)、刚性负荷 (L)、价值认同系数 (\gamma)、本地调整成本系数 (\psi)以及可选的储能初始SOC。如果暂时不加储能初始功率平衡直接由光伏和负荷的差值决定n 5; PV [9; 6; 0; 2; 8]; L [5; 4.5; 7; 6; 4]; gamma [0.6; 1.2; 1.5; 0.8; 0.9]; psi [0.8; 0.9; 1.0; 0.95; 0.85]; rho 0.16; maxIter 300; tol 5e-4; x zeros(n,1); lambda zeros(n,1); z zeros(n,1); hist_x zeros(n, maxIter); hist_lambda zeros(n, maxIter); P_local PV - L;这里 (\gamma) 就是前文说的价值认同系数。节点3光伏为0、负荷最大同时 (\gamma) 最高说明它是一个很愿意为本地绿电付费的买家节点1光伏大、(\gamma) 低表示它只愿意接受接近主网购电价的价格卖电。4.2 主循环代码骨架核心迭代循环非常短因为闭式解的求法省掉了所有内部优化器for k 1:maxIter % 1) 本地闭式更新x0表示买入x0表示卖出 x (gamma - lambda rho * z) ./ (psi rho); % 2) 邻居平均参考量完全图拓扑直接取全局均值 z mean(x lambda ./ rho) * ones(n, 1); % 3) 乘子虚拟电价信号更新 lambda lambda rho * (x - z); hist_x(:, k) x; hist_lambda(:, k) lambda; if k 1 norm(hist_x(:, k) - hist_x(:, k - 1), inf) tol ... norm(hist_lambda(:, k) - hist_lambda(:, k - 1), inf) tol break; end end p_trade P_local x; % 节点与社区交互后的净出力 p_grid p_trade; % 社区不平衡功率可视为与主网交换这段代码跑完后可以画出 (x) 和 (\lambda) 的迭代轨迹观察它们是否逐渐收敛到平稳值。认真说我第一次跑通的时候看到 (\lambda) 在一百多轮之后真的稳定到一个固定数值才真正理解什么叫分布式算法生成的均衡价格——它不是谁拍脑袋定出来的而是通过大量局部协商逐步浮现的。4.3 代码里容易写错的三个变量语义第一个坑是 (x) 的符号约定。有人喜欢用正数表示用电需求有人用正数表示售电如果前后不一致后续算交易流向时非常容易乱。建议统一成正数为买入、负数为卖出或者相反然后一直沿用。第二个坑是参考量更新方式。完全图拓扑可以把所有节点都算成邻居直接用全局平均值。但如果是稀疏配电网拓扑只有物理上相连的节点才能交换信息这时候 (z_i) 必须按邻接矩阵加权平均不能直接取全网络平均值否则信息传播范围会超出物理边界结果会失真。第三个坑是 (\rho) 的表达位置。罚参数 (\rho) 出现在乘子更新和参考量更新里它的量级必须与目标函数的系数匹配。后面我会专门说调参问题这里先记住当 (\psi) 的量级在1附近时(\rho) 通常取0.1到0.5之间比较稳。5. 算例结果解读偏好系数如何改写电价、自平衡率与交易流向5.1 一组典型运行结果与物理含义把上面的参数直接代入骨架脚本收敛后得到的结果大致如下表所示。注意这里电价做了归一化1.0表示与主网零售电价相等实际结算时乘回零售单价即可。节点光伏(kW)负荷(kW)价值认同系数净交易状态内部共享功率(kW)虚拟电价(相对值)19.05.00.6卖出2.860.6226.04.51.2卖出1.520.7130.07.01.5买入-3.340.7542.06.00.8买入-2.190.6658.04.00.9卖出1.150.68读出这组数据时最有意思的是节点3。它的 (\gamma) 最高愿意支付的虚拟电价也最高所以在其他买方节点还在观望时它优先与卖方节点达成了交易。而节点1虽然光伏富余量很大但因为 (\gamma) 低导致报价期望低它在共享市场的参与反而显得相对被动。整体来看加入价值认同参数后社区内部的共享比例和本地消纳量显著提升。光伏富余节点不再简单地把电全部上网而是会优先通过共享机制卖给社区内的高偏好用户高偏好用户则愿意为这部分本地绿电支付比常规场景更高的溢价。两个群体的效用都得到了提升这正是价值认同进入交易机制希望达到的效果。5.2 敏感性分析γ从0.2扫到2.0交易行为出现了三段式变化我比较推荐在复现出基本算例后固定其他参数把 (\gamma) 从0.2扫到2.0观察社区共享电量和虚拟电价的变化趋势。实测下来会出现明显的三段式特征。第一阶段(\gamma) 很小低于0.5左右所有节点都偏价格敏感价值认同几乎没有影响共享电量主要由成本差驱动虚拟电价也贴近成本价。这一阶段模型退化成普通的纯经济调度问题。第二阶段(\gamma) 进入中等区间约0.5到1.2高偏好买方开始主动接受高一些的虚拟电价光伏节点因为收益改善而增加共享供应量社区共享电量显著上升。虚拟电价也随 (\gamma) 增大而抬升但还没超过主网零售电价交易仍对双方有利。第三阶段(\gamma) 继续增大到1.5以上虚拟电价开始逼近甚至超过主网零售电价。理性买家的选择会发生变化——既然从邻居那里买绿电比直接从主网购电还贵为什么还要留在共享市场于是共享交易量增速放缓甚至回落部分负荷重新选择从主网购电交易策略出现了饱和效应。这个敏感性分析有个很直接的工程启示价值认同系数并不是越大越好。它更像一个调节旋钮过小了没有体现出需求侧偏好的价值过大了又会让共享电价失去竞争力。实际机制设计时需要根据当地零售电价水平、过网费结构和用户支付意愿来合理设定 (\gamma) 的上限而不是盲目把偏好参数调到最大。6. 复现过程中最容易让人卡壳的五个问题与调参经验6.1 ρ参数与收敛速度的三角关系(\rho) 是ADMM里最需要调的参数没有之一。它太小每轮迭代对共识偏差的惩罚力度不够节点之间各说各话收敛速度慢得让人崩溃它太大参考量和乘子的更新幅度过大前期迭代就像在振荡器上跳舞功率曲线甩出各种奇怪的锯齿。我个人的经验是先跑一个固定较小 (\rho)比如0.05观察前50轮 (\lambda) 的轨迹如果走得很平顺但需要200轮以上才收敛就慢慢把 (\rho) 翻倍如果出现了明显的大幅振荡就退回到上一个值。在 (\psi) 量级为1的二次目标函数下0.1到0.3通常是比较安全的区间。另外(\rho) 也可以做成随时间递增的调度策略来兼顾前期搜索和后期收敛但代码复杂度会高一些。6.2 效用函数凸性与锯齿振荡如果发现迭代后期 (x) 始终在两个值之间来回跳不收敛先检查 (\psi_i) 是否太小。前面推导闭式解时要求目标函数强凸也就是 (\psi_i 0)。当 (\psi_i) 趋近于0时二次项失去主导作用目标函数本质上退化成线性函数ADMM对线性目标的使用条件非常苛刻很容易出现边界振荡。解决办法有两个一是给 (\psi_i) 设置一个合理下限比如不小于0.05二是为 (x_i) 增加箱型约束上下限让局部问题保持有界。如果你要模拟的是用户完全不在意调整成本的极端场景请一定加上限幅否则代码大概率会是发散或者振荡的结局。6.3 储能SOC跨时段耦合的处理很多复现代码的第一版只做单时段静态交易效果很好但一旦把储能加进去每个时段的SOC就像一个隐形的状态变量把不同时段黏在一起。如果还是逐时段独立调用ADMMSOC会漂移电池可能在下一时段被要求输出根本不存在的电量。处理思路通常是滚动时域。在每一个调度时间窗口内把未来若干时段的SOC约束都写进模型只执行第一个时段的决策然后窗口向前滚动。这样每个窗口内仍然可以用ADMM分布式求解只是节点本地子问题需要多带一个SOC状态变量。这一步会让代码复杂度增加不少但也是从演示程序走向可用策略的必经之路。6.4 虚拟电价限幅与初始值设置(\lambda) 的初始值对早期迭代影响很大。很多代码初始化 (\lambda0)这没错但前几轮迭代会让 (\lambda) 剧烈变动如果你把虚拟电价直接画出来开头一段会非常吓人。建议在初始化时根据主网零售电价给 (\lambda) 一个合理初值比如0.8而不是从零开始。更重要的是一旦发现虚拟电价收敛值超过了主网零售电价很多就要考虑是否给 (\lambda) 加上限幅。从物理意义看用户购买邻居绿电的意愿再强也不会愿意无限制地高于主网电价。给 (\lambda) 设上界本质上就是在模型里体现主网购电作为备选方案这一约束和现实中的理性选择是一致的。6.5 收敛判据别只看功率残差最后这个坑非常隐蔽。很多人判断ADMM是否收敛时只盯着相邻两次迭代的功率差值看到功率不怎么变了就以为收敛了。但有时候 (x) 已经稳定而 (\lambda) 还在以一个很小的步长持续漂移最终结算价格根本不同。正确做法是同时看两个残差原始残差 (r_k |x_i^k - z_i^k|)对应功率一致性有没有达成对偶残差 (s_k \rho|z_i^k - z_i^{k-1}|)对应价格信号有没有稳定下来。两者都降到阈值以下才真正说明系统收敛了。我代码里写的收敛条件用了两个 inf 范数判断就是这个用意。实际中如果对偶残差迟迟不降优先怀疑 (\rho) 过大或 (\psi) 过小回到前面的问题去调参数。复现这类策略的过程中我最大的体会是分布式交易和集中式调度最大的差别不在数学工具上而在你愿不愿意相信一群分散的主体可以通过协商达成稳态。ADMM里的每一轮迭代模拟的都是邻居之间讨价还价的过程(\lambda) 则是那个最终让大家闭嘴的均衡信号。这个视角一旦建立起来后面无论换目标函数、换拓扑结构、加储能还是加不确定性都是在这个底层的协商框架上添砖加瓦。
返回列表