跳至主要内容
电是物理商品,不是另一种股票

电是物理商品,不是另一种股票

第一次看到负电价,我以为是数据源出错。价格字段带了个负号,清洗脚本顺手把它当异常值剔掉了。后来查了报价规则才知道,那不是脏数据,是电网在那个小时里真的希望有人多用电。

这件事之后我改了清洗规则,也开始重新理解这个市场。它表面上和股票一样有价格、有曲线、有波动率,底层却是另一套东西:电必须在发出来的那一刻被用掉,输电线有物理容量,供需失衡会直接变成设备故障。

不可存储性决定了价格形状

股票和能源最根本的差别不在波动率,在能不能存。买一股可以无限期拿着,成本几乎只有资金占用。电力不行,生产和使用必须同时发生。储能技术在进步,但相对总需求仍然很小,抽水蓄能还受地形限制。

油气可以存,但仓储有租金、保险和损耗,这些成本会变成不同到期月份之间的价差。同样的逻辑在电力上失效,因为存储这个环节根本不存在,时间维度的套利被物理条件直接掐断。

这个差别会一路传导到价格上。电价的均值回归不是统计现象,是被物理套利压出来的。价格高过边际成本,闲置机组会启机;低过燃料成本,机组会停机。两头都有人用真金白银把价格推回去,回归因此比金融资产更硬。

我一开始把「均值回归」理解成价格回到历史中枢,这个理解是错的。中枢本身会动,它跟着燃料成本走。拿历史均值做锚,在燃料价格剧烈变化的那一年会亏得很难看。更稳的做法是把长期均值当成一个需要单独建模的变量,而不是从价格序列里直接估出来。

供给曲线也值得单独看。发电机组按边际成本从低到高排队,价格由最后一台被调用的机组决定。需求稍微越过一个阈值,价格就会跳一档,这个跳变是阶梯形的,不是平滑的。用连续模型去拟合,在拐点附近会一直偏。

天气是这条曲线最重要的外生变量,但它本身也很难用。数值预报有集合成员,成员之间的分歧程度其实是一个很好的不确定性指标,比单点的预测值有用。我见过把它当特征直接喂进模型的,效果一般;把它当成仓位上限的调节项,反而更合理。

这个认识改变了我看待特征工程的方式。价格序列里包含的信息比想象中少,真正的自变量在序列之外:气温、风速、机组检修计划、管道输气量。这些东西不像行情那样高频更新,但它们决定了行情会在哪里停住。

负电价与节点电价

负电价有两个常见来源。一个是必须运行的机组:核电、大型煤电的启停成本极高,停机再启动可能要几天,所以宁愿付钱让人用电也不停机。另一个是补贴:某些可再生能源在负价区间仍然能拿到度电补贴,只要补贴大于亏损,继续发电就是理性的。

这两个来源的共同逻辑是,停机比亏钱更贵。理解这句话,很多看起来反常的报价就都能解释。

空间上的版本是节点电价。一条输电线有热极限,A 地电便宜但送不出去,B 地就得启本地贵机组。市场被切成若干节点,价差就是拥堵的价格。对写代码的人来说,这意味着电网拓扑和线路容量是模型的硬约束,不是可有可无的特征。

这条约束也解释了为什么跨区套利看起来简单、做起来难。价差存在的大部分时间,都不是因为有人没发现,而是因为送不过去。能送的时候,价差往往已经很小了。

节点电价还带来一个建模上的麻烦:节点太多。逐节点建模不现实,通常要聚类,把行为相似的节点归成一组。聚类的方式会直接影响回测结果,而且很难验证对不对。

燃料和电力之间的价差是另一类玩法。燃气电厂的毛利大致是电价减去燃料价格乘以热耗率,热耗率低意味着机组效率高。把这个式子当成一个看涨期权来理解,逻辑就通了:价差为正时发电,为负时停机,亏损被限制在固定成本里。策略交易的不是电价方向,是这组价差会不会继续扩大。

这个视角的好处是把「预测」换成了「定价」。预测电价涨跌很难,判断一台机组的启停边界相对容易,因为它由成本结构决定,不由情绪决定。

这个框架也有边界。机组启停不是免费的,频繁启停会加速设备老化,实际决策里有一条隐含的启动成本。把它忽略掉,模型会给出过于频繁的启停信号,看起来赚钱,实际在烧设备。

数据里最贵的是时间

能源数据有两个跟别处不一样的地方。

一个是前视偏差。天气是负荷和新能源出力的主要输入,回测时如果用历史实况代替当时的预报,模型会好得不像话。这个错误很隐蔽,因为实况数据往往经过事后修正,把当时的不确定性抹平了。按发布时间而不是生效时间取数,是我目前知道的唯一解法,代价是存储和查询都变复杂,而且很多历史数据源根本没有保留发布版本。

另一个是时间本身。电力按小时或十五分钟交付,各地有夏令时,一年里有一天二十三小时、一天二十五小时。时间索引重复会导致报错或者静默覆盖,前向填充又会造出并不存在的小时。这类问题不会让程序崩,只会让回测结果慢慢偏掉,而且极难定位。

粒度对齐也很烦。电价是小时粒度,负荷可能是十五分钟,气象是小时但不同模型的时间戳含义不一样。直接合并等于在无意中引入未来信息,尤其是把粒度粗的数据向后填充到细粒度上。这种错误在代码里看不出来,只会在实盘和回测的差异里显形。

数据源本身也不稳。不同电网的发布格式、字段命名、甚至时区标注都不一样,接口变更通常不发公告。我现在的做法是每个源单独写解析和校验,宁可多写几百行,也不做一个通用解析器——通用的那个每次都要改,改的时候还不知道会影响谁。

清洗规则也要改。负电价是合法值,尖峰可能是真实的拥堵信号而不是异常点,风电出力超过装机容量才是真的脏数据。通用的标准差剔除在这类数据上会删掉最值得研究的那一段。

我现在的做法是先分场景再清洗:价格序列只用上下限和物理容量做校验,不做平滑;负荷和出力序列才做异常检测。这么分很笨,但比一套规则打天下可靠。

系统设计的重心不在快

期货和衍生品那一侧,架构接近金融高频,比的是从行情到下单的耗时,内核旁路、托管、硬件加速都有意义。

电力现货和日内是另一回事。这里的「高频」指决策次数多,不是纳秒级抢单。系统要处理的是约束:机组出力上下限、爬坡率、申报截止时间、不平衡罚款。速度当然重要,但算错一次可能比慢一百毫秒贵得多,这两个量级不在同一个数量级上。

申报这件事在股票系统里没有对应物。很多电力交易需要向电网运营方提交物理计划,提交失败或者迟到,交易可能直接无效,还可能招致罚款。所以连接性不是「能连上交易所」这么简单,还要处理几套异构接口,各自有各自的截止时间和重试规则。

发电厂跳闸是个典型场景。信号进来之后,顺序比速度更关键:先冻结相关卖出指令,再在日内市场买入对冲,最后才通知人。把通知放在第一步,人还没反应过来,敞口已经扩大了。

这类系统我倾向于模块化单体,而不是微服务。远程调用在正常时候很快,在极端行情下会超时、会重试、会把一次失败放大成一片。核心链路在同一个内存空间里跑完,故障模式至少是可数的。这个判断和互联网行业的默认做法相反,但在交易链路上,可预测性比弹性更值钱。

数据接入层是例外,那部分应该隔离出去。交易所接口、电网申报接口、气象数据源,协议各不相同,变化也频繁,用适配层把它们挡在外面是值得的。核心引擎不应该知道对面是哪个交易所。

回测和实盘的偏差在这类系统里特别大,因为约束太多。回测里机组可以瞬间启停,实盘要爬坡;回测里申报随时能改,实盘有截止时间。这些差异不会体现在收益率上,会体现在最需要钱的那几天。

另一个经常被忽略的差异是数据延迟。行情在交易所是即时的,电网的计量数据往往滞后几分钟甚至更久。回测里假设同一秒拿到价格,实盘里拿到的是几分钟前的状态。这个滞后不会体现在策略逻辑里,会体现在最需要反应的那几分钟。

系统之外还有一层,我始终没做好,就是风险。风险价值在正态假设下是个漂亮的数字,但能源价格的尾部比正态厚得多,极端天气和管道事故都不在历史样本里。

我现在的做法更笨:设硬止损,设断路器,把「模型不知道什么」写进文档。承认这一点不体面,但比在极端行情里现找答案要好。断路器尤其重要,它不解决问题,只是把损失限制在一个可以商量的范围内。

还有一个容易被忽略的点是流动性。回测里假设随时可以平仓,实盘里远月合约可能根本没有对手盘。这个差异在平静的时候看不出来,在需要减仓的时候会一次性暴露。

压力测试我也做得不系统。与其说是在测,不如说是在列清单:哪些假设一旦不成立,整个头寸会同时朝一个方向走。这个清单目前只有半页,还在补。

我越来越觉得,这个市场的核心能力不是预测,是在约束下做可行的决策。预测错了还能靠约束兜住,约束理解错了,再准的预测也没用。


© Lu’s Blog · 版权所有

关于本文

由 Lu's Blog 撰写,采用 CC BY-NC 4.0 许可协议。

#数据质量 #能源交易 #量化

评论