☰
电力市场双层优化:售电商主从博弈套餐设计与购电策略
2026/10/22 19:32:32 网站建设 项目流程

去年我在复现某篇EI索引论文时,遇到了一个特别有意思的题目:基于主从博弈的售电商多元零售套餐设计与多级市场购电策略。当时第一反应是这题听起来很大,又是“主从博弈”又是“多级市场”,结果做下来发现,真正的难点不在数学公式,而在怎么把零售端的用户行为和批发端的市场时序拧在一起建模,再用Matlab把整个双层优化问题稳定解出来。

这篇东西适合两类人看:一是刚接触电力市场优化、想用博弈论做个有深度课题的研究生;二是企业里做售电套餐设计或能源运营的工程师,想理解套餐定价和购电策略之间到底有什么联动。我尽量把每一步背后的“为什么”也讲清楚,而不是只给一段能跑的代码。

1. 为什么“零售套餐设计”和“购电决策”不能分开做

1.1 零售端的套餐设计决定了用户侧的用电弹性

很多初步接触售电业务的人,会把套餐设计当成一个简单的营销问题:给用户几档电价,有人选便宜量大的,有人选贵但稳的,最后算一算平均收益就行。但在这类EI论文的框架里,套餐不是拍脑袋定的,而是直接影响用户用电行为的传导器。

比如你推出一款“夜间半价、白天溢价”的分时套餐,用户就会把可平移负荷挪到夜里。如果客户数量足够多,这种负荷转移不仅会改变零售侧的收入结构,还会反过头来影响售电商在批发市场购买电力的时段分布。零售套餐的每个价格参数,本质上都是一根杠杆,撬动的是用户侧的需求响应弹性。而弹性一旦被撬动,批发侧的购电曲线就必须跟着调整,否则就可能出现“套餐卖得越多、亏损越大”的尴尬局面。

1.2 批发端的多级市场结构让购电成本不再是单点决策

国内外的电力市场普遍存在合约市场、日前市场和实时市场。合约市场可以提前锁定中长期价格,但锁定多了,现货价格下跌时就会吃亏;日前市场能根据次日预测精准申报,但预测总有偏差;实时市场虽然最接近真实供需,但价格波动极大,只能作为平衡手段。

所以售电商的购电策略本质上是一个多时间尺度的组合优化问题。你在合约市场签多少比例,在日前市场报多少曲线,留多少空间给实时市场修正,这些比例互相牵制。更麻烦的是,购电策略不是独立的,它必须和零售套餐一起优化。因为套餐决定了用户总用电量和分时分布,而购电成本取决于批发侧的分时价格,两者强耦合。

当年读这篇论文时,我最大的顿悟就在于此:标题里的“多元零售套餐设计”和“多级市场购电策略”并不是并列的两个模块,而是一个整体。零售端每改一个价格参数,批发端的购电比例就要重新算一遍。只有把它们放到同一个优化模型里同时求,才算真正理解了这个问题。

2. 主从博弈建模:谁先动,谁后动,均衡状态怎么定义

2.1 售电商作为Stackelberg领导者的决策变量与收益函数

主从博弈又叫Stackelberg博弈,核心思想是“领导者先宣布策略,跟随者根据领导者的策略做最优响应”。放到这个场景里,售电商是领导者,用户是跟随者。

售电商先发布一组零售套餐,比如普通固定电价套餐、分时电价套餐、阶梯电价套餐,每种套餐有自己的价格参数。用户看到这些套餐后,会选择一种能最大化自身效用的套餐,并决定自己在每个时段的用电量。售电商的收益是零售收入减去批发购电成本,所以它需要预测用户会如何反应,然后倒推一个最优套餐组合。

这里有个容易搞混的点:售电商不是直接控制用户用电量,而是通过套餐价格引导用户。所以模型里售电商的决策变量是套餐价格参数,而用户用电量是内生变量。

收益函数大致可以写为售电商总利润等于各时段零售收入减去各时段购电成本。但真正复杂的在于,用户问题自身是一个优化问题,售电商的利润函数里包含着用户的最优响应函数,这就形成了一个“外层优化+内层优化”的双层结构。

2.2 用户作为跟随者的用电决策模型

用户的用电行为通常用一个效用函数来描述。经典做法是二次效用函数:用户从用电量中获得满意度,但满意度边际递减。用户会在给定电价的条件下,选择合适的用电量来最大化“效用减去电费支出”。

如果同时提供多种套餐,用户还要做一次离散选择。为了建模方便,很多论文会把用户按类型分组,比如居民用户、商业用户、工业用户,每组用户对电价敏感度不同。每种用户会计算各套餐给自己带来的净收益,然后选择最大的那一个。

这里有个微妙的设计:用户不仅选择“用多少电”,还选择“用哪个套餐”。这两种决策是嵌套的。如果只是简单的连续用电量优化,问题会退化成单层;一旦引入套餐选择,就变成混合整数双层问题,难度陡增。

我在复现时发现,作者非常聪明地假设用户是同质的或者按少数几类聚合,这样离散选择就可以通过比较净收益大小来确定,而不需要显式引入整数变量。这种简化虽然牺牲了一部分精细度,但让主从博弈模型具备了可解性。

3. 多级市场购电的数学建模:从日前到实时的时序衔接

3.1 合约市场、日前市场与实时市场的互补关系

购电策略的建模首先要理清三个市场的角色。

合约市场通常在日前市场关闭之前很久就签订,一旦签订就是物理合同,必须执行。它起到价格对冲和风险规避作用。日前市场允许售电商根据负荷预测申报第二天的分段购电曲线,价格按出清价结算。实时市场则针对实际负荷与日前申报的偏差,按实时价格多退少补。

这三个市场构成了一个时间链:合约锁定基础量,日前申报计划量,实时修正偏差量。售电商的总购电成本由三部分组成,但三部分的购电价格性质完全不同。合约价格相对稳定,日前价格波动较大,实时价格可能剧烈跳动。

在模型里,售电商要决策的是:合约电量占总需求的比重、日前市场在不同时段的申报电量、以及预留的实时调整空间。约束条件包括各时段购电量之和必须等于该时段总负荷需求,合约电量不能超过某个比例上限,实时购电电量可以在某个范围内等。

3.2 购电组合约束与风险偏好表达

在实际建模中,风险因素通常用一个权重项来表达。有些论文会用CVaR(条件风险价值)来衡量实时市场价格暴涨带来的损失,有些则简单采用加权平均成本。

我复现的那篇论文没有用太复杂的风险度量,而是在目标函数里给实时购电价格设定了一个惩罚系数,相当于变相表达了售电商对实时市场的风险厌恶。这种做法在复现时比较容易处理,因为它保持了目标函数的线性或二次可解性。

购电组合约束里最容易忽略的是时序一致性:合约市场和日前市场的决策在时间上是先后发生的,但在数学建模里,如果没有显式的时间耦合变量,很容易把三个市场的电量写成彼此独立的决策变量。实际上,日前申报必须基于对合约电量的已知信息,实时修正又必须基于日前中标结果。这种嵌套关系需要我们用“滚动决策”或“级联约束”的方式表达,否则解出来的策略在实际运营中根本无法执行。

我记得自己第一次建模时,把三市场购电量都写成同时决策的变量,结果得到一个理论上最优但实际完全不可行的方案。后来看了论文里的决策顺序图才明白,必须把决策变量按时间分层描述,外层是合约比例,中层是日前申报,内层是实时调整。

4. Matlab复现路线:KKT条件、强对偶与MPEC求解

4.1 将用户问题替换为KKT条件的推导细节

这种双层优化问题最常用的解法学派是“下层替换法”。用户侧优化问题通常是一个凸优化问题,因此它的最优解完全等价于它的KKT条件。

把用户问题写出拉格朗日函数,对用电量求导,加上不等式约束的互补松弛条件,就能把内层问题转化为一组方程组和互补约束。替换之后,外层售电商优化问题就变成了一个带互补约束的数学规划问题,也就是MPEC(Mathematical Program with Equilibrium Constraints)。

在Matlab里做这一步时,最关键的是求导符号别算错。用户的效用函数如果带二次项,导数是线性的;价格参数会出现在约束里,所以KKT条件里会出现外层决策变量和内层决策变量的乘积项,这就是非线性互补约束的来源。

我建议先手推一遍内层KKT条件,再用符号计算工具验算,最后再把结果手工写成约束矩阵。不要省这一步,直接套现成的大规模优化工具箱往往会把非线性约束遗漏。

4.2 通过强对偶定理避免非线性互补约束

MPEC中的互补约束是非光滑的,直接丢给求解器很容易报错或收敛到假的局部最优。业界常用的办法是利用强对偶性质,把用户问题的目标函数值用其对偶目标函数等价替代,从而消去互补约束中的非线性项。

具体来说,用户问题是一个凸二次规划,在满足Slater条件下,原问题最优值等于对偶问题最优值。把用户目标函数替换成对偶表达式之后,互补约束中的乘积项会被一组线性等式替代,这样MPEC就变成了一个单层的混合整数线性规划或二次约束规划。

这一步是整个复现里最“魔法”的地方。我第一次接触时完全看不懂为什么能这样代换,后来拿一个只有两个时段的小例子手算了一遍,发现其实就是利用了凸优化中“强对偶=0”的双层等值关系。在写Matlab代码时,这一步通常体现为用Yalmip定义完上层变量和约束后,把内层用户问题的目标函数用表达式替换掉,然后交给求解器处理。

4.3 用Yalmip和Gurobi求解的工程实现

在Matlab平台上,我习惯用Yalmip建模,求解器选择Gurobi。Yalmip的优点是建模语言接近数学公式,代码可读性高,而且支持线性化互补约束的内置函数。

实际写代码时,我通常把数据准备好后,先建模外层问题的基础变量和约束,再嵌入内层KKT条件替换过来的线性约束。需要注意,转化后的模型中可能含有一个二元变量用来处理互补约束中的非凸部分,Gurobi可以求解MILP,所以整体复杂度可控。

我还准备了一个简化版本的测试算例:只有3个时段、2类用户、2种套餐。在这个小算例上验证模型逻辑正确后,再扩展到96时段、5类用户、4种套餐。如果一上来就跑大算例,出了问题根本没法定位。

下面是我的代码框架片段,省略了具体数据生成部分,保留核心建模结构:

% 定义售电商决策变量 p_price = sdpvar(nTime, nTariff); % 套餐价格 p_contract = sdpvar(1,1); % 合约购电比例 % 用户用电量由KKT条件决定,通常写成变量 q_user = sdpvar(nTime, nUser); % 约束:KKT条件转换后的线性约束 Constraints = [KKT_stationarity, KKT_complementarity_linearized]; % 目标函数:售电商利润 Profit = sum(sum(q_user .* p_price_actual)) - cost_contract - cost_dayahead - cost_real; Objective = -Profit; % 最小化负利润 ops = sdpsettings('solver', 'gurobi', 'verbose', 2); optimize(Constraints, Objective, ops);

很多初学者会在互补约束的线性化上卡住。我的建议是不要直接用complements()命令,而是手动引入一个二元变量,把互补条件“要么左边为0,要么右边为0”转化为大M约束。虽然多了整数变量,但求解稳定性明显提升。

5. 复现过程中最容易踩的坑

5.1 参数初值敏感性与多均衡问题

主从博弈模型有个老毛病:可能存在多个均衡解。尤其是当用户效用函数和价格参数表达不够严格凹时,KKT条件可能有多组解,Gurobi找到的不一定是论文里那个。

我在复现时对比原论文的图,发现数值总是差一点。后来重新读论文,发现作者在参数设定里有一行很关键的小字:所有价格变量初值均采用上一轮迭代结果。这不只给了一个初值影响的提示,还暗示他们用的可能是某种迭代求解方法,而不是一次性MPEC。

如果直接用MPEC求,可能走到一个局部解。解决方法是给价格变量设置上下界,或者通过多起点尝试。我建议在代码里加一个简单的循环,随机生成几组初始价格,记录每次求得的利润值,选择最优的那个。这个方法虽然笨,但对于复现研究很有效。

5.2 数值问题:大M取值、标幺制与迭代次数

互补约束线性化时,需要引入一个足够大的M值。M太大,会导致数值病态,Gurobi的求解精度降低;M太小,则可能错误地把可行解剪掉。这个M值到底取多少,没有统一标准,必须根据电价和用电量单位来估计。

我的经验是先算一下所有变量的量级上限。例如实时电价一般在几百到几千元/兆瓦时,用电量在几十到几百兆瓦时,两者乘积的上限大概是百万级。那么M取这个上限的10到100倍就足够了。代码里最好把M定义成和基础单位相关的公式,而不是写死一个常数。

另一个坑是功率单位不一致。有的论文里用兆瓦时,有的用千瓦时,数据量级相差很大,直接代入模型会导致系数矩阵条件数极差。我在复现时把所有数据统一成标幺制,以某个基准负荷和基准电价作为1,这样所有决策变量都在0.1到10之间,求解器收敛速度快得多。

5.3 如何校验复现结果与原始论文保持一致

论文复现最怕的不是模型跑不通,而是跑通了但结果对不上。我一般会按以下顺序逐项校验:

  • 先用论文提供的基准参数,跑出一个完整结果,检查目标函数值和论文图表里的数量级是否一致。
  • 再看关键决策变量的趋势:比如套餐价格是否在某个时段升高,合约购电比例是否在某个区间波动。
  • 最后做敏感性分析:改变用户价格弹性系数,观察利润和均衡价格是上升还是下降。

如果趋势一致但数值略有偏差,很可能是求解器精度或终止误差导致的,问题不大。如果趋势都反了,那一定是模型公式抄错了,必须回到KKT推导阶段检查。

我在复现过程中,最常犯的错误是漏掉用户用电量上下限约束。很多论文为了逼真,会设置用户每个时段的最小用电量和最大用电量,这会造成互补约束里出现“下限或上限绑定”的情况。如果漏掉这些约束,均衡解里可能会出现负用电量这种明显不合理的结果。

6. 从均衡结果看运营策略:套餐价格、购电比例、用户弹性的联动关系

6.1 基准场景下的均衡结果分析

跑通模型后,我习惯先复现论文的基准算例。这个算例通常设置一个典型日的96个时段,用户分三到四类,套餐两到三种。

从均衡结果里,你能清楚看到两个关键现象。

第一,分时套餐的价格高峰低谷差比普通固定套餐大得多。因为用户有弹性,售电商敢在峰时抬高价格,引导用户少用,同时在谷时降低价格,鼓励用户多消纳。这样一来,用户侧的总负荷曲线被削峰填谷,售电商批发侧的购电均价也随之下降。

第二,合约购电比例不是越高越好。在基准参数下,合约比例通常落在一个区间,过低的话日前市场暴露风险太大,过高的话当现货价格走低时,售电商会因锁定高价合约而吃亏。均衡比例实际上是用户弹性、现货价格波动和风险偏好三者博弈的结果。

6.2 敏感性分析:电价波动、套餐种类、用户数量

复现论文时,敏感性分析是验证模型逻辑的重要手段。我通常改变三个参数:

  • 实时市场价格波动率:波动率增大时,售电商倾向于提高合约比例,同时对实时购电量设置更严格的惩罚,零售套餐的峰谷价差也会拉大。
  • 套餐种类数量:从两种套餐增加到四种套餐,用户细分程度提升,整体社会福利和售电商利润通常都会上升,但多出来的收益并不平均,有些用户群会被“价格歧视”。
  • 用户弹性系数:弹性越大,售电商越不敢定过高的价格,因为用户会快速流失。弹性低时,售电商可以把价格定得更高,利润空间更大。

通过敏感性分析,研究者还能画出“模糊区域”或者“阈值点”,这些内容往往是EI论文里最出彩的部分。我复现时最喜欢做这类图表,因为它们能直观展示模型行为,也容易让读者理解主从博弈的意义。

7. 复现过程中的其他心得与后续扩展方向

7.1 个人体会:把“理论模型”翻译成“可计算模型”的桥

这次复现经历让我对电力市场中的双层优化模型有了更深的理解。很多论文里推导出的漂亮公式,直接丢给Matlab往往是跑不动的,必须经过一系列等价转化才有实际可解性。这中间最关键的能力,就是能把“均衡”这种抽象概念翻译成“一组约束条件加上一个目标函数”。

另外,调试时的耐心也很重要。第一次真正跑通全模型并复现出论文关键图表时,我花了两天时间定位一个符号错误——就是把“用户电价敏感系数”写反了。这种错误不仔细看根本发现不了,但会导致所有结果趋势都反过来。从那以后,我养成了一个习惯:每次修改模型后,先跑一个极简场景,手动验证几个节点的数值合理性,再放大算例。

7.2 可以继续扩展的方向

如果你也想在这个方向深入,我建议可以试试以下几件事:

  • 把用户侧的离散选择行为真正建模成混合整数约束,而不是用净收益比较简化。这会显著增加求解难度,但能更真实地刻画用户切换套餐的成本。
  • 引入多个售电商同时竞争的博弈场景,把单领导者-单跟随者结构扩充成多领导者-多跟随者,这类模型通常只能用启发式算法或分布式求解器。
  • 把低碳约束纳入模型,比如绿电消费比例、碳排放配额,这会改变购电策略的可行域,也会影响套餐设计。

从工程应用角度看,这类模型虽然调度颗粒度较粗,但它提供了一个很好的框架,能帮助售电公司从“拍脑袋定价”走向“基于用户响应和市场价格的联合优化”。

如果你手头也正在复现类似的电力市场博弈论文,或者在设计零售套餐时感到定价和购电策略相互打架,欢迎在评论区聊聊你踩过的具体问题。模型细节也许各不相同,但核心逻辑大多相似,多交流几次,你就能少走不少弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询