AIGC标识 把并网点拆成结算单元:三个让总额对得上、明细全错的建模坑

月末对账那天,两家主体拿着同一张明细表来找我。一家算出来 285,另一家也算出来 285,总额一模一样。往下翻明细,差 200 度电。

那一刻我才承认:总额对得上,是这类 bug 最危险的伪装。

一、设备台账加几个字段,不是结算实体

过去做储能电站的能量管理系统,站内只有一块关口表,谁发的电、谁用的电,全都在一条线上,账很安静。一旦站里出现第二个权属主体(租出去的容量、共享的升压间隔、代运维的电池组),这套模型立刻不够用。

最常见的补救是在设备台账上加三个字段:所属主体、分摊比例、计量点编号。这个做法有三个问题,而且都不在数据写入那一刻暴露。

  1. 一个设备只能属于一个主体。 共用关口表要按比例分摊给两家,加一列 owner 就塞不下第二个值,只好拆成两条设备记录,然后全站的容量统计开始重复。
  2. 主体关系没有时间维度。 成员 10 月 20 日退出共用、改成独立计量,台账上改一下字段就把历史抹了。10 月 18 日那两天的账再也算不回来。
  3. 台账是给运维看的视图。 设备增删、间隔调整、检修挂牌都会动它。拿一个高频变更的视图当结算依据,等于把账本挂在会动的墙上。

结算单元的粒度不是设备,是那本要被考核的账。 先有单元,才有聚合;设备是单元的成员,不是单元本身。

二、四张表,把「账」建成实体

规则层面的依据很直接。现货新规的附件把新型经营主体做成二分:单一技术类(分布式光伏、分散式风电、储能、可调节负荷)与资源聚合类(虚拟电厂、负荷聚合商、智能微电网、绿电直连);第八条允许新能源与场站内配套储能作为联合报价主体,参与申报、出清、调用、结算和考核;聚合模式的结算数据要求由被聚合资源的计量数据汇总生成,并区分不同时段的上网与下网电量。

翻译成表结构,最小集合是四张:

CREATE TABLE settlement_unit(          -- 结算单元:法定对象,独立于设备
  unit_id TEXT PRIMARY KEY, unit_name TEXT,
  unit_type TEXT,                      -- single / aggregate
  node_id TEXT);                       -- 现货节点,决定用哪个节点价

CREATE TABLE metering_point(           -- 计量点:物理表位,不含权属
  mp_id TEXT PRIMARY KEY, mp_name TEXT, ct_ratio REAL DEFAULT 1);

CREATE TABLE unit_member(              -- 成员关系:多对多 + 分摊比例 + 有效期
  unit_id TEXT, mp_id TEXT, share_ratio REAL,
  valid_from TEXT, valid_to TEXT,
  PRIMARY KEY(unit_id, mp_id, valid_from));

CREATE TABLE meter_reading_15m(        -- 读数:带方向,带规则版本
  mp_id TEXT, ts TEXT, direction TEXT, -- import / export
  kwh REAL, rule_ver TEXT,
  PRIMARY KEY(mp_id, ts, direction, rule_ver));

关键在 unit_member 这一张。它把「哪个计量点算进哪个单元、算多少比例、从哪天算到哪天」从设备台账里剥出来,变成可以按时段回溯的关系。有了它,一个计量点同时挂给两个单元不会重复建记录,成员退出也不会改历史。

汇总口径只有一条:

SELECT u.unit_id, r.direction, ROUND(SUM(r.kwh * m.share_ratio), 2) AS kwh
FROM settlement_unit u
JOIN unit_member m       ON m.unit_id = u.unit_id
JOIN meter_reading_15m r ON r.mp_id = m.mp_id
WHERE r.ts >= m.valid_from
  AND (m.valid_to IS NULL OR r.ts < m.valid_to)   -- 这一行是命门
GROUP BY u.unit_id, r.direction;

三、三个坑,我用同一份数据跑出来的

造一份最小数据:U1 是风光场站加配储的联合报价主体,U2 是共享储能。10 月 18 日两者共用 #1 主变关口表,按 70/30 分摊,当天关口上网 1000 度;10 月 20 日 U2 退出共用、改接独立进线表,22 日充电 100 度、放电 85 度。

正确口径的结果是:U1 上网 700,U2 上网 385、下网 100。

坑一:只记净额。 把方向折成一个带符号的数再加总,U2 得到 285。数字看着对,但充电 100 和放电 85 都不见了,中间损耗的 15 度无从体现。分时价格下这是致命的:充电发生在低谷、放电发生在高峰,两个方向的电量必须按各自的时段价分别结算,一旦净额化,价差就再也算不出来。

坑二:成员有效期不过滤。 少写一个 valid_to 条件,U2 从 285 变成 485,凭空多出 300 度,正是它在 10 月 18 日共用关口表上的分摊量。这类错误在月底最容易被当成「计量异常」去查表,其实表没问题,是关系没设边界。

坑三:两个错误互相抵消。 既忘了方向、又忘了有效期,U2 算出来仍然是 285,与正确答案一字不差。这就是开头那幕的来源。两个错误抵消之后,月度总额全校验不出来,只有翻到日粒度、翻到方向维度才会露馅。

实测输出(SQLite,字段与上面一致):

A 正确口径            U1 export 700.0 | U2 export 385.0 | U2 import 100.0
B 只记净额            U1 700.0        | U2 285.0
C 忘过滤有效期         U1 700.0        | U2 485.0
D 方向+有效期双错      U1 700.0        | U2 285.0   <- 与正确答案相同

四、规则为什么逼着人这么建

两天后的另一份文件把同一件事从电源侧又说了一遍。国能发电力〔2026〕69 号要求融合项目具备煤电与新能源独立电量计量条件,合理设置关口计量表,确保计量界面清晰、结果准确;接网方式要求与公用电网形成清晰的物理界面与责任界面;涉网性能要求新能源实现可观、可测、可调、可控。

一条线路送两家电,账要在表上分开,不能在线路上分。

再往下传导,这条要求会沿着设计文件一路走到代码里:一次系统图上标了计量点,监控系统的间隔表里就得有权属主体,对外接口里就得有结算方向。任何一层偷懒,最后都会在结算单上以争议的形式出现。我在 VPP 平台项目里最耗时的从来不是调控链路,而是月底那几张对不上的表:平台里没有「结算单元」这个概念,谁属于哪个报价主体、按什么口径汇总、责任算谁的,全靠人记。

五、三个反模式,代价都在半年后

反模式 当时省了什么 六个月后的代价
设备台账加 owner 字段 少建两张表 共用表强行拆设备,容量统计重复;成员变更即断历史
汇总时用净额,省一个方向维度 少一列、少一个 group by 分时价差与充放电损耗永久丢失,考核无法复算
成员关系只存当前值,不留有效期 少两个时间字段 历史月份重算结果不稳定,同一期报表两次跑出两个数

第三种最隐蔽:它不出错,它只是不稳定。财务对账时最怕的不是错,是两次不一样。

六、落地顺序

  1. 先建 settlement_unit 与 unit_member,把关系和时间维度补上。 设备台账继续服务运维,两者用 mp_id 关联,不要合并。
  2. 读数表加 direction 和 rule_ver。 方向不做默认值,宁可写入时报错,也别让 import 悄悄落成默认。
  3. 每个申报量与报送量存四份快照。 申报值、指令值、实际值、认定值,各带规则版本号,并保留原始测点。凡是「报一个值、事后被考核」的场景(容量电价的最大放电功率认定就是典型),争议的胜负在留痕阶段就已经决定。
  4. 上线前跑一次双错校验。 故意把方向聚合与有效期过滤各关掉一次,如果两种错法的结果与正确结果相同,说明校验 SQL 本身没有覆盖到这两个维度。

数据说明

本文事实部分来源分级如下。A 级:国家发展改革委 2026-10-19《电力现货市场基本规则(公开征求意见稿)》公告及附件(新型经营主体二分、联合报价、聚合结算口径、第七十六条施行条款);国家能源局 2026-10-21《关于推动煤电与新能源融合发展的实施意见》(国能发电力〔2026〕69 号)及配套解读。B 级:上述条款细节经财新网、中国储能网 10-19 至 10-22 交叉核对。文中的电站规模、主体名称与电量数值均为示意数据,用于说明口径差异,不对应任何真实客户或项目。

涉电力市场交易与容量补偿的段落只讨论机制与实现口径,不构成投资建议。

模型是算出来的,不是接出来的。表画对了,账才算得清。

posted @ 2026-10-23 20:56  海风自语  阅读(4)  评论(0)    收藏  举报