资讯动态

主从博弈下的售电商零售套餐与多级市场购电优化

发布时间:2026/10/14 22:05:14 来源:尧图企业网站定制
最近几年电力市场方向真是越来越热闹售电侧放开之后售电商怎么给用户定价、怎么去批发市场买电成了很多研究组和工程人员绕不开的题目。我注意到有人把这个经典方向做成了一套Matlab代码从主从博弈到零售套餐再到多级市场购电整个链路给得比较完整。这篇就以这个项目为引子把背后的思路、数学模型、代码实现链路、还有踩过的坑一五一十说清楚。这套东西适合谁刚入门电力市场但不知道从哪下手的研究生做售电公司策略优化的工程师还有想复现论文但没有头绪的科研党。它解决的核心矛盾就是售电商既要给用户设计有吸引力的套餐又要在中长期、日前、实时多个市场里把钱花明白这两件事是互相牵着的只有放一起建模才合理。主从博弈就是用来刻画这种“我先定规则、你根据规则行动”的关系。1. 项目全景售电商的钱袋子与用户的选择权1.1 这个项目到底在解决什么难题先摆一个最常见的业务闭环。售电商从批发市场买电然后打包成零售套餐卖给终端用户赚的是差价。听起来简单实际操作起来有几个让人头疼的地方。第一个矛盾是价格与需求的联动。你给用户定一个电价用户不一定照单全收。电价高了用户可能少用电或者干脆换一家售电商。电价低了用户是用得多但你利润又被吃掉了。这里面存在一个天然的双向反馈你的价格策略决定了用户的用电行为用户的用电行为又反过来决定你的购电需求购电需求再影响你在批发市场的购电成本。如果只是拍脑袋定个套餐很容易出现“套餐卖出去了但算下来亏本”的情况。第二个矛盾是多级市场的时序问题。中长期市场、日前市场、实时市场的电价不同、波动率不同、提前量也不同。中长期合同锁定了大部分电量但价格偏高日前市场灵活一些但电价每日浮动实时市场最灵活但风险最大。怎么把购电量在这几个市场之间配置本身就是个优化问题。第三个矛盾是不确定性。用户侧有新能源发电、有电动汽车充电用电曲线说变就变批发侧有新能源出力波动、有负荷预测误差电价动不动就跳。这些不确定性叠加在一起如果模型里不考虑进去算出来的结果基本没什么工程参考价值。这套项目把上面三个岗点捏成了一个模型框架上层售电商决策套餐内容与购电结构下层用户根据套餐做出最优用电响应用主从博弈把上下层之间的策略互动串起来最后通过Matlab求解给出一套可运行、可改参数的代码。这就是它最大的价值不是给你一个孤立的公式而是给你一个能跑出结果的完整闭环。1.2 为什么偏偏是主从博弈这是很多人看标题时第一个冒出念头的问题那么多博弈模型为什么要选主从博弈先理解一下博弈对象之间的关系。售电商和用户之间地位其实不对等售电商先发布零售套餐设置价格用户看到套餐之后再做用电决策。这是一个明显的Stackelberg结构——我先动你后动但我预判了你会怎么动。所以“主从”这两个字其实是很精准的售电商是“主”用户是“从”。对比一下就能理解为什么这个选择合理。如果用传统的合作博弈那默认双方信息完全对称、利益可以协商分配但现实中用户根本没有动力跟售电商坐在一起谈分成如果用一般的非合作博弈比如纳什均衡那要求双方同时决策但售电商的定价权和用户的用电权在时序上就是有先后的。主从博弈刚好贴合这个“先定价、后响应用电”的真实业务节奏把上下层之间的策略互动用数学语言表达得干净准确。另外一个重要的点是主从博弈天然是带“预见性”的。售电商在定套餐价格的时候就已经把下层用户的最优反应函数代入了自己的优化目标里。也就是说它做的不是“我随便定个价看用户怎么反应再说”而是“我知道用户在我每种价格之下会怎么选我找一个让自己利润最大的价格”。这种预见性在工程上意味着你算出来的套餐价格不是拍脑袋的而是有博弈论意义上最优性的。1.3 项目的核心创新点不是堆模型看完代码和论文后我觉得这个项目真正有意思的地方不只是主从博弈这个大框架而是它在细节上的几个处理。第一个是零售套餐的多元维度。不是简单的单一制电价而是设计了包含分时电价、阶梯电量、固定费用几类参数的套餐结构。这才是工程里面常见的样子用户在基础电价之上还要接受容量费、阶梯梯度、峰谷浮动这些规则的约束。把套餐设计成一个多维度的参数向量让上层优化去挑最优组合这比只算一个单位电价要贴近实际得多。第二个是多级市场购电策略的建模。代码里把购电分成了三段中长期合同为主力锁量锁价、日前市场做调整应对负荷预测误差、实时市场来平衡应对突发偏差和现货波动。每段购电的比例、时序、期望成本都放进优化模型里让上层决策的时候不仅是在选套餐还在选购电结构。第三个是双层模型的转化技巧。主从博弈模型天然是一个双层优化问题直接扔给求解器是解不动的。为了把它变成可以交给Matlab优化工具箱处理的形式用到了下层问题的KKT条件转换把下层用户的优化问题替换成一组等价约束嵌入上层模型。这一步是整个复现中技术含量最高、也最容易出错的地方后面第3节我会仔细讲怎么处理。2. 核心原理与数学建模思路2.1 模型框架的整体设计这个项目在数学上是一个标准的双层优化问题上层是售电商下层是用户群体。上层模型的决策变量包括零售套餐的各项参数阶梯电价梯度、峰谷时段价格、基础服务费等中长期市场的购电比例与购电量日前市场的申报电量上层目标函数是售电商的总利润最大化等于零售收入减去各市场购电成本。这里的关键是零售收入不是固定的它取决于用户在下层优化之后给出的是什么用电量。所以上层目标函数里嵌了个下层问题这就是双层优化的灵魂所在。下层模型是用户的用电量优化问题。给定售电商发布的套餐价格用户调整自己的用电量让用电效用电费用之间的净收益最大化。用户不是只选“用还是不用”而是同一时段内不同电价下的用电量会发生平移或削减比如把洗衣机的用电从高峰时段挪到低谷时段。这样设计的整个求解闭环是上层给出一组套餐价格和购电计划 → 下层用户在这些价格下做出最优响应 → 响应结果反馈到上层的收入函数里 → 上层重新评估利润调整套餐价格 → 再次让用户响应……直到达成主从博弈的均衡。2.2 用户效用与需求响应建模下层用户模型的数学表现形式直接决定了整个求解链条的稳定性。代码里常用的是二次效用函数减去电费支出的形式用户目标是最大化净收益。用一个简化表达来理解用户在时段t的净收益 一个二次函数表示的用户用电效用 - 该时段的购电费用。对电量求一阶导就能得到用户的用电量关于电价的解析表达式。这个解析表达式非常重要因为后面要把它代入上层问题。这里有个细节值得提醒二次效用函数的系数标定不能随便拍。如果系数太大用户用电量对价格完全不敏感那需求响应就没有意义了博弈结果会退化成纯购电优化如果系数太小用户的负荷会在几个时段之间剧烈波动非线性增强KKT转化之后的问题会非常病态。在实际调参过程中我一般建议先让用户弹性系数落在业界文献常用的范围内比如价格弹性在-0.1到-0.5之间再去观察响应曲线合不合理。用户侧可能还细分了多类型用户商业用户、工业用户、居民用户他们的效用函数参数和用电习惯都不一样。处理多类型用户的方式通常是各自建一个下层问题然后把它们的KKT条件都并入上层模型。变量数量会明显增加但模型表达的现实意义也更完整。2.3 多级市场购电策略的数学表达购电策略这一块从数学上看实际上是一个带随机性的多阶段资源配置问题。但代码处理得比较聪明用了期望值框架把它转化成了确定性优化。中长期市场的特点是签约电量结算价固定提前锁定减少了不确定性但价格中包含一定的溢价。所以中长期购电比例不是越高越好太高了会失去日前市场低价套利的空间太低了又扛不住电价波动风险。日前市场的特点是可以基于更准确的负荷预测比如提前一天的预测去修正中长期合同的偏差。这部分电量的成本是日前出清价它比中长期价格波动大一些但只要你中长期比例预留合理的话波动的冲击是可控的。实时市场是所有偏差的最后兜底。用电实际值和日前计划的偏差就在实时市场平衡。实时电价波动最剧烈所以实时市场的购电比例应该是最小化的。这三层购电结构合在一起上层模型的购电成本写作购电总成本 中长期购电量 × 中长期合约价 日前购电量 × 日前期望电价 实时平衡电量 × 实时期望电价其中实时平衡电量不能是负数否则意味着你在市场上卖电那逻辑就变了。这个细节在代码里通常会通过约束条件体现实时购电量的下限设为零。2.4 双层问题的KKT转化与线性化这是整个项目最硬核的部分也是复现时最容易翻车的地方。我简单说清楚原理和关键步骤。对于一个连续凸的下层优化问题KKT条件是该问题最优解的充分必要条件。这意味着如果一个解满足下层问题的KKT条件那它就是下层用户在给定价格下的最优响应。把下层用户的KKT条件写成一组约束嵌入上层问题原本的双层优化就变成一个带互补约束的单层优化问题数学规划领域叫MPEC问题。具体到这套代码用户的KKT条件由三部分组成用户购物优化问题的一阶最优条件边际效用等于电价不等式约束对应的互补松弛条件用户的用电量上限约束如果不起作用对应的对偶乘子就是零对偶变量的非负约束互补松弛条件里有一条“乘子乘以松弛变量等于零”这是一个非线性项直接扔给求解器很难处理。常见做法是把互补条件等价拆成两个方向的不等式再引入一个二进制变量做大M法转换。这一步做完之后整个模型就变成一个可以交给整数规划求解器处理的混合整数线性规划或二次约束规划问题。关于大M法里的M参数怎么选我的经验是不要一股脑取一个大数比如1e9否则数值稳定性会非常差。应该先估算对偶变量的量级再选一个比它大一到两个数量级的M值。好多代码复现到这一步卡住就是因为把M取得太大了求解器在数值上直接崩掉。3. 代码实现路线与关键操作3.1 代码架构与文件结构设计我在看这套Matlab代码时第一感觉是模块化做得相当有条理。整个工程的入口是一个主脚本负责初始化参数、调用子函数、输出结果。核心的计算逻辑分散在几个函数文件里大致包括参数初始化模块设置价格参数、负荷参数、用户弹性、市场电价等基础数据上层问题构建模块构建售电商的目标函数、约束条件下层问题构建模块构建用户响应模型、KKT转化、大M法处理互补约束求解与后处理模块调用求解器求解、解析结果、画图这种分层的文件结构最大的好处是方便做变量灵敏度分析。比如跑完一版结果之后你想看中长期购电比例从60%变到70%会怎么样只需要改参数初始化模块里的一个数值不用去翻整个模型定义。3.2 关键参数怎么设不是随便填的先说我踩过的坑。这套代码涉及的参数非常多如果对模型理解不够透彻参数就是一堆数字填错了也不知道错在哪里。有几个参数在调试时要特别小心。第一个是用户价格弹性系数。这个参数直接决定了下层KKT条件中目标函数的二次项系数它的量级直接影响整个模型的数值稳定性。我在某次测试中把弹性系数从0.3调到了0.8结果用户的用电量响应曲线出现了剧烈振荡KKT转化后的模型求解时间从几十秒暴涨到几分钟。后来查了文献很多论文里弹性系数取值范围基本都在0.1到0.6之间超过这个范围之后模型已经偏离了现实场景的合理假设。第二个是套餐价格的上限约束。这个约束必须加否则求解器为了激励用户用电可能把价格推到不可理喻的低价。上层目标是利润最大化理论上单价低于购电成本的套餐是亏钱的求解器不会主动选但如果出现大M法处理带来的数值病态求解器可能给出负的或者非常小的价格。所以必须给套餐各项价格设置合理的上下界比如不超过用户用电器成本的1.5倍、不低于批发购电成本的0.8倍。第三个是各层级市场的购电比例边界。中长期购电比例如果完全放开自由优化模型大概率会给一个非常极端的结果要么全签中长期要么全在日前买。这个比例在工程上是有约束的售电公司通常有一定的风险规避要求不可能把所有电量都放到现货市场去赌。建议把中长期购电比例的上下界设在50%到90%之间一是有实际业务依据二是能有效缩小解空间加快求解速度。3.3 求解器选择与配置yalmip还是fminconMatlab里解决这类MPEC问题最常用的两个路线是第一条路是yalmip建模 外部求解器cplex/gurobi。用yalmip的好处是建模直观约束和变量可以像写数学公式一样直接描述。处理KKT条件转化后的大M问题、混合整数项yalmip内部能自动检测数据类型并调度合适的求解器分支。工程上我个人非常推荐这条路线尤其当模型规模变大、变量数量上千的时候yalmip gurobi的组合在求解速度和数值稳定性上都要远超fmincon。第二条路是纯Matlab优化工具箱 fmincon。这条路线适合模型规模小、变量不多的情况不需要额外安装求解器。但有一个明显的坑经过KKT转化后的MPEC模型带有互补约束违反约束的可行性问题非常严重fmincon在处理这类问题时经常陷入“不可行点”就出不来了。如果你用fmincon通常要想办法增加罚函数项把互补约束“软化”掉但这样做又引入了新的参数调节问题纯经验活。我个人的建议是如果只是在Windows本地做复现实验首选gurobi或cplex的学术版用yalmip建模如果条件受限只能装开源工具箱可以考虑把互补约束用松弛变量软化掉然后用fmincon或ipopt求解但要做好结果精度受损的心理准备。3.4 迭代求解逻辑主从博弈是怎么收敛的虽然KKT转化能把模型变成单层问题但还有另一种求解路径——迭代求解法尤其在验证模型正确性的时候很有用。迭代逻辑是这样的售电商给定一套初始套餐价格用户侧响应求解用户的最优用电量售电商根据用户响应更新自己的利润调整套餐价格返回第2步直到相邻两次迭代的套餐价格变化小于设定阈值这种迭代法的好处是实现简单能直观看到“定价-响应-再定价”动态博弈过程。坏处也很明显收敛性没有理论保证价格振荡很常见。我在测试时遇到过价格在两个峰值之间来回跳、无法收敛的情况后来加了步长阻尼因子把每次价格修正量乘一个0.5到0.8的系数振荡明显缓解。如果你发现迭代法死活不收敛不要死磕直接上KKT单层化一次性求解。单层化求解虽然建模难度高但求解器会给一个全局或近似全局的最优解不像迭代法只能给出一个局部博弈均衡。4. 常见问题与调试经验4.1 模型求解结果异常负数购电量怎么处理这个问题出现的概率非常高。在很多初版代码里实时市场购电量或者用户某时段的用电量会出现负值。从模型数学逻辑上讲KKT转化后互补约束允许变量在某些极值点处取到边界值但负的电量在工程上完全不可解释。解决方法通常有两种。第一种是给购电量加非负约束这是最直接的办法。第二种是检查大M法引入的二进制变量逻辑是否正确你的条件“如果某约束松弛量大于零则对偶乘子必须为零”有没有被正确表达成两个互斥的条件。多数情况下加完非负约束之后负值问题就消失了。4.2 KKT转化后求解时间爆炸怎么办模型规模扩大之后比如多个用户类型、24个时段、三个市场层级KKT转化带来的变量数量会迅速膨胀尤其是二进制变量多了之后求解时间可能从几秒钟涨到几十分钟。我的处理思路是分层简化先把模型跑通一个简化场景比如把24个时段聚合成6个典型时段主要验证逻辑正确性。验证通过之后再逐步把时段细分回24个。这样可以在保证模型合理规模的同时快速定位求解时间异常出在哪个环节。另外还有一个技巧是固定部分决策变量做预求解。比如先固定中长期购电比例为一个初始值优化套餐价格再用这个结果作为热启动把中长期购电比例也设为变量重新求解。热启动值对混合整数规划的速度影响极大这个技巧实测下来能省50%以上的求解时间。4.3 用户响应不合理负荷没有转移或转移过度出现过一种情况用户的负荷曲线在峰谷电价差拉大后几乎没有任何变化。这说明用户效用函数里的二次项系数太大了导致用电量变化对电价不敏感。反过来如果负荷在峰谷之间疯狂转移甚至出现了违反物理约束的负荷倒灌就是二次项系数设置太小。针对这个问题我建议做一次简单的参数标定实验固定套餐价格扫一组弹性系数绘制用户各时段用电量曲线然后从曲线上看峰谷转移比例是否在合理范围一般在10%到30%之间。做完这步标定再去跑完整双层优化结果就稳健多了。4.4 主从博弈均衡解不唯一这是MPEC这类问题一个理论上的难点KKT转化之后得到的解可能是局部最优不同初值下可能收敛到不同的均衡点。这意味着两次随机初始化跑出来的套餐价格和利润可能不一样。解决思路是用多个随机初值跑多次能收敛到的最优结果记录下来作为参考解然后分析这个解的套餐参数是否在现实业务可接受范围比如峰谷电价差是否过大、套餐固定费用是否合理。如果某个初始值下收敛到的解有一个参数明显偏离常识那个解大概率是个假均衡可以直接丢弃。5. 复现效果分析与拓展思路5.1 典型复现结果这套代码能输出什么跑通代码之后输出的结果大致包含三类第一类是售电商的最优套餐结构。包括各时段的售电价格、固定费用、阶梯梯度等。结果通常会显示一个明显的峰谷电价结构高峰时段价格高于低谷时段价格差受到用户弹性系数和市场电价水平的双向影响。第二类是各市场购电比例的分配结果。中长期、日前、实时各自占多少。结果通常会显示中长期占比在50%到70%区间日前市场占20%到40%实时市场占比很小但非零——这个分布反映了模型在风险与收益之间的均衡。第三类是利润对比分析。可以对比“单层优化不博弈”和“主从博弈优化”两种情况下的利润差异也可以对比“只在单一市场购电”和“多级市场购电”的利润差异。这个对比是论文里最常出现的图表也是验证模型价值最直接的方式。5.2 从复现代码到写自己的论文怎么改造成创新点很多人下载这套代码之后最关心的是怎么在上面做自己的创新。这里我给出三条实际可操作的路径。路径一改用户模型。原始代码里的用户是纯理性用户最大化自身效用的数学表达比较理想化。你可以引入用户决策的心理因素比如有限理性、从众效应、习惯性用电等把用户模型改成更贴合实际的行为模型这在下层KKT条件转化上会带来新的数学挑战适合作为创新点。路径二改市场结构。多级市场的框架里加入碳交易市场或者绿电市场把购电成本和碳排放成本联合优化。这是在“双碳”背景下比较热门的方向上层目标函数从利润最大化改成利润减去碳排放成本的综合目标。路径三改不确定性建模。把原本基于期望值框架的市场电价处理成场景集用随机优化或分布鲁棒优化替代期望值方法这样能处理极端电价场景的冲击更贴近真实市场风险。5.3 个人心得体会理论模型与工程实现的间隙我不止一次看到有人拿到代码第一件事就是改参数跑结果最后发现结果跟自己想象的完全不一样就以为是代码有bug其实往往是参数设置和模型假设之间不匹配。做这类项目我的习惯永远是先跑通初始参数复现出论文里的基本趋势然后再动任何参数。另外这套代码能不能迁移到别的场景比如把售电商换成微网运营商把零售套餐换成综合能源服务套餐把购电市场换成气电联动市场。主从博弈的框架不需要大改但需要仔细检查KKT条件在新模型里是否依然成立。新模型的下层问题如果不是凸优化KKT转化就是不成立的这是复现扩展时最要命的一个坑。我建议在扩展之前先验证新下层问题的凸性否则后面做的所有转化都是在沙地上建塔。最后说一句关于工具链的话。如果你打算把这个项目作为硕士论文或期刊论文的基础工作我强烈建议买正版求解器授权gurobi有免费学术版。用免费工具箱省下来的钱远不够弥补花了三个星期调fmincon不收敛的时间损失。工具选对了工作就成功了一半。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑