功率预测数据接入
风电、光伏功率预测与电力现货交易的气象数据接入:变量选择、历史预报训练集、15 分钟实时推理。
数据流程
| 阶段 | 接口 | 数据 |
|---|---|---|
| 训练 | 批量下载 API,time_range.type = "forecast" | 历史预报(archive_*),每个起报场一组 init_time |
| 回测 | 同上,按申报时刻筛选起报时次与预报时效 | 与上线时可用数据一致 |
| 上线 | 预报 API /v1/forecast | 同一模型的实时预报 |
训练集使用历史预报,而不是 ERA5 再分析。再分析数据包含观测同化后的"事后真值",用它训练的模型上线后会遇到真实预报误差,精度通常明显下降。
变量选择
风电
| 变量 | 单位 | 用途 |
|---|---|---|
wind_speed_100m | m/s | 轮毂高度风速,主特征 |
wind_direction_100m | ° | 尾流、地形效应 |
wind_gusts_10m | m/s | 切出风速、波动 |
temperature_2m | °C | 空气密度、覆冰 |
surface_pressure | hPa | 空气密度 |
relative_humidity_2m | % | 空气密度、覆冰 |
轮毂高度不是 100 m 时,选择有对应高度层的模型:
| 模型 | 风速高度 |
|---|---|
archive_hres / archive_ifs / archive_aifs | 10、100 m |
archive_gfs | 10、20、30、40、50、80、100 m |
archive_cma | 10、30、50、70、100、120、140、160、180、200 m |
archive_icon | 10、80、120、180 m |
archive_gem | 10、40、80、120 m |
光伏
| 变量 | 单位 | 用途 |
|---|---|---|
global_tilted_irradiance | W/m² | 组件斜面辐照,配合 tilt、azimuth |
shortwave_radiation | W/m² | 水平面总辐射 GHI |
direct_normal_irradiance | W/m² | 法向直射 DNI,跟踪支架 |
diffuse_radiation | W/m² | 散射辐射 DHI |
cloud_cover_low / cloud_cover_mid / cloud_cover_high | % | 云的影响 |
temperature_2m | °C | 组件温度损失 |
wind_speed_10m | m/s | 组件散热 |
snowfall | cm | 积雪遮挡 |
tilt 为组件倾角(0–90°),azimuth 为组件方位(0 为正南,-90 为正东,90 为正西)。例如格尔木 35° 正南安装:
https://api.mirror-earth.com/v1/forecast?latitude=36.4&longitude=94.9&hourly=global_tilted_irradiance,shortwave_radiation,temperature_2m&tilt=35&azimuth=0&temporal_resolution=minutely_15&forecast_days=3&models=ecmwf_ifs&timezone=Asia/Shanghai&apikey=您的API Key
请求参数说明
| 参数名 | 类型 | 描述 |
|---|---|---|
| apikey必填 | string | API Key,登陆后自动填充,或在个人中心获取 |
| latitude必填 | number | 纬度,多个纬度用逗号分隔,必须和longitude数量一致,例如 32,33 |
| longitude必填 | number | 经度,多个经度用逗号分隔,必须和latitude数量一致,例如 118,119 |
| hourly选填 | string | 小时要素,多个要素用逗号分隔:temperature_2m,precipitation |
| daily选填 | string | 逐日要素,多个要素用逗号分隔:temperature_2m_max,temperature_2m_min,precipitation_sum |
| forecast_days选填 | number | 预报天数,可以和past_days同时使用,但是不能和start_date/end_date/start_hour/end_hour同时使用 |
| past_days选填 | number | 过去天数,可以和forecast_days同时使用,但是不能和start_date/end_date/start_hour/end_hour同时使用 |
| start_date选填 | string | 开始日期,只能搭配end_date使用,例如 2025-01-01 |
| end_date选填 | string | 结束日期,只能搭配start_date使用,例如 2025-01-02 |
| start_hour选填 | number | 开始时间,只能搭配end_hour使用,例如 2025-01-01T00:00 |
| end_hour选填 | number | 结束时间,只能搭配start_hour使用,例如 2025-01-01T23:00 |
| temporal_resolution选填 | string | 时间分辨率,默认都是1小时(hourly_1),可选10分钟(minutely_10),15分钟(minutely_15),30分钟(minutely_30) |
| models选填 | string | 数据源,多个数据源用逗号分隔:ecmwf,cma |
| timezone选填 | string | 时区,默认为世界时,auto表示根据经度自动计算全部时区:时区列表 |
| cell_selection选填 | string | 坐标选取偏好,当坐标点位于陆地和海洋分界处时控制返回海洋上的点还是陆地上的点,默认是land表示陆地,sea(海洋),nearest (就近原则) |
| elevation选填 | string | 高程,默认情况下会使用高程对温度数据进行校正,数值模式算出来的数据表示的是这个网格点上的平均,我们用高程可以根据地形进行校准,nan表示不校准。 |
日内与超短期预测可叠加葵花卫星辐射(10 分钟)作为实况输入。
电价与负荷
电价和负荷模型通常按省或地市建模,使用区域平均得到面平均气象序列:
| 变量 | 用途 |
|---|---|
temperature_2m、apparent_temperature | 空调、采暖负荷 |
relative_humidity_2m | 体感、负荷 |
wind_speed_100m | 省内风电出力 |
shortwave_radiation | 省内光伏出力、分布式光伏 |
precipitation | 水电来水 |
构建训练集
以两个场站、2026 年一季度、每天 00 和 12 UTC 两个起报场为例,导出 72 小时、15 分钟步长的历史预报。
第一步:创建任务
import time
import requests
API_KEY = "your_api_key"
BASE_URL = "https://api.mirror-earth.com"
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
payload = {
"domain": "archive_hres",
"hourly": [
"wind_speed_100m", "wind_direction_100m", "wind_gusts_10m",
"temperature_2m", "surface_pressure", "relative_humidity_2m",
"shortwave_radiation", "direct_normal_irradiance", "diffuse_radiation",
"cloud_cover_low",
],
"daily": [],
"monthly": [],
"time_range": {
"type": "forecast",
"start": "2026-01-01",
"end": "2026-03-31",
"start_hour": "00,12",
"forecast_hours": 72,
},
"area": {
"type": "point",
"locations": [
{"id": "WF01", "name": "张北风场", "lon": 114.70, "lat": 41.15},
{"id": "PV01", "name": "格尔木光伏", "lon": 94.90, "lat": 36.40},
],
},
"time_resolution": "minutely_15",
"timezone": "UTC",
"area_average": False,
}
estimate = requests.post(f"{BASE_URL}/api/tasks/estimate", json=payload, headers=headers)
estimate.raise_for_status()
data = estimate.json()["data"]
if data.get("error") or not data.get("estimate_id"):
raise RuntimeError(data.get("error_msg") or "预估失败")
payload["estimate_id"] = data["estimate_id"]
res = requests.post(f"{BASE_URL}/api/tasks/export", json=payload, headers=headers)
res.raise_for_status()
task_id = res.json()["data"]["task_id"]
timezone 设为 UTC,便于下一步与 init_time 计算预报时效。场站较多时,locations 可直接由场站台账 CSV 生成。
第二步:等待并下载
import io
import zipfile
while True:
res = requests.get(f"{BASE_URL}/api/tasks/{task_id}/status", headers=headers)
res.raise_for_status()
status = res.json()["data"]
if status["status"] == "completed":
output_file = status["output_file"]
break
if status["status"] in ("failed", "cancelled"):
raise RuntimeError(status["status"])
time.sleep(10)
zip_bytes = requests.get(f"{BASE_URL}/user_downloads/{output_file}", headers=headers).content
zipfile.ZipFile(io.BytesIO(zip_bytes)).extractall("archive_hres_2026q1")
第三步:按申报时刻切片
CSV 列为 id,name,lat,lon,init_time,time,<variables>。日前申报只能使用申报截止前已入库的起报场,训练集也应只保留这些起报场与对应时效:
import glob
import pandas as pd
df = pd.concat(pd.read_csv(f) for f in glob.glob("archive_hres_2026q1/**/*.csv", recursive=True))
df["init_time"] = pd.to_datetime(df["init_time"], utc=True)
df["time"] = pd.to_datetime(df["time"], utc=True)
# 日前申报使用 D-2 日 12 UTC 起报场,运行日为北京时间 D 日 00:00–24:00
day_ahead = df[df["init_time"].dt.hour == 12].copy()
day_ahead["run_date_bj"] = (day_ahead["time"] + pd.Timedelta(hours=8)).dt.date
day_ahead["lead_h"] = (day_ahead["time"] - day_ahead["init_time"]).dt.total_seconds() / 3600
day_ahead = day_ahead[day_ahead["lead_h"].between(28, 51.75)] # 96 个点
起报时次怎么选,见起报时次与日前申报。
上线推理
上线时调用同一模型的实时预报,变量和步长与训练集一致:
https://api.mirror-earth.com/v1/forecast?latitude=41.15&longitude=114.7&hourly=wind_speed_100m,wind_direction_100m,wind_gusts_10m,temperature_2m,surface_pressure,relative_humidity_2m&temporal_resolution=minutely_15&forecast_days=3&models=ecmwf_ifs&timezone=Asia/Shanghai&apikey=您的API Key
请求参数说明
| 参数名 | 类型 | 描述 |
|---|---|---|
| apikey必填 | string | API Key,登陆后自动填充,或在个人中心获取 |
| latitude必填 | number | 纬度,多个纬度用逗号分隔,必须和longitude数量一致,例如 32,33 |
| longitude必填 | number | 经度,多个经度用逗号分隔,必须和latitude数量一致,例如 118,119 |
| hourly选填 | string | 小时要素,多个要素用逗号分隔:temperature_2m,precipitation |
| daily选填 | string | 逐日要素,多个要素用逗号分隔:temperature_2m_max,temperature_2m_min,precipitation_sum |
| forecast_days选填 | number | 预报天数,可以和past_days同时使用,但是不能和start_date/end_date/start_hour/end_hour同时使用 |
| past_days选填 | number | 过去天数,可以和forecast_days同时使用,但是不能和start_date/end_date/start_hour/end_hour同时使用 |
| start_date选填 | string | 开始日期,只能搭配end_date使用,例如 2025-01-01 |
| end_date选填 | string | 结束日期,只能搭配start_date使用,例如 2025-01-02 |
| start_hour选填 | number | 开始时间,只能搭配end_hour使用,例如 2025-01-01T00:00 |
| end_hour选填 | number | 结束时间,只能搭配start_hour使用,例如 2025-01-01T23:00 |
| temporal_resolution选填 | string | 时间分辨率,默认都是1小时(hourly_1),可选10分钟(minutely_10),15分钟(minutely_15),30分钟(minutely_30) |
| models选填 | string | 数据源,多个数据源用逗号分隔:ecmwf,cma |
| timezone选填 | string | 时区,默认为世界时,auto表示根据经度自动计算全部时区:时区列表 |
| cell_selection选填 | string | 坐标选取偏好,当坐标点位于陆地和海洋分界处时控制返回海洋上的点还是陆地上的点,默认是land表示陆地,sea(海洋),nearest (就近原则) |
| elevation选填 | string | 高程,默认情况下会使用高程对温度数据进行校正,数值模式算出来的数据表示的是这个网格点上的平均,我们用高程可以根据地形进行校准,nan表示不校准。 |
| 训练(历史预报) | 上线(实时预报) |
|---|---|
archive_hres | ecmwf_ifs |
archive_ifs | ecmwf |
archive_gfs | gfs |
archive_cma | cma |
archive_icon | icon |
archive_ukmo | ukmo |
archive_aifs | aifs |
多模型集成时,对每个模型分别构建训练集,再按 time 对齐合并特征。