AAYMA
RU
Войти

Samal

Агентная система для «Самрук-Казына»: почасовой прогноз выработки двух ветротурбин на 24–48 часов с интервалами P10/P50/P90, бэктест на феврале…

Доведённый продукт
Команда «KAYO» 9💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: KAYO
Кейс HackAlem.ai: Энергетика — Самрук-Казына
Стадия: Доведённый продукт

Задача кейса: AI-агент, прогнозирующий выработку ветровой электростанции по погодным данным

Суть

Агентная система для «Самрук-Казына»: почасовой прогноз выработки двух ветротурбин на 24–48 часов с интервалами P10/P50/P90, бэктест на феврале 2026, 3D-дашборд и экспорт в Excel и PDF.

Как устроено

Архивные прогнозы погоды Open-Meteo Previous Runs (ансамбль ICON/GFS/ECMWF, среднее и разброс ветра) плюс 10-минутные данные турбин, агрегированные по часам. Прогноз строится как кривая мощности плюс HistGradientBoosting, коридор P10–P90 даёт конформная калибровка. Агентный цикл: пересчёт, только если ветер сдвинулся на 1 м/с и больше; рефлексия снимает смещение по факту за 14 суток; шлюз качества откатывается на чистую кривую мощности, если модель хуже прогноза «как вчера». LLM пишет только объяснение для диспетчера, без ключа подставляется шаблон. Каждый шаг пишется в agent_log.json.

Ключевые решения

  • HistGradientBoosting
  • power curve
  • conformal calibration P10/P90
  • ICON/GFS/ECMWF ensemble features
  • reflection bias correction
  • quality gate vs persistence baseline
  • backtest

Метрики

Покрытие P10–P90 выросло с 78 до 81% (по коммиту). Сценарная цена ошибки: 7,22 млн ₸ у агента против 15,35 млн ₸ у базовой линии. README также приводит nMAE/nRMSE, но значения обрезаны.

Особенности

Честная работа с доступностью погоды: консервативный архив day2/day3. Команда нашла и исправила утечку ноукаста в скользящих окнах. Числа считает только код, LLM лишь объясняет. Есть шлюз качества с откатом к базовой линии и 3D-сцена турбин на Three.js.

Стек

Python · scikit-learn · pandas · Parquet · Three.js · Yandex Maps API · HTML/JS

Модели

GPT-6 Luna (OpenAI) · NVIDIA NIM


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-2adafad9-kayo.

README

README.md

Samal — прогноз выработки ВЭС

Агентная система прогнозирования для «Самрук-Казына», разработанная в рамках HackAlem AI.

Почасовой прогноз выработки двух ветротурбин на 24–48 часов вперёд. Система сама забирает прогноз погоды по координатам площадки, готовит признаки, считает выработку, проверяет себя против базовых линий и объясняет результат. Тестовый период — февраль 2026.

Прогноз выпускается ежедневно в 23:00 UTC на следующие 1–48 часов. Для восстановления прошлого используется консервативный архив погоды day2/day3 с запасом до выпуска не менее суток. Допущение: задержка публикации погодных прогнозов не превышала 24 часа. Архив не содержит исторических времён публикации, поэтому точную доступность каждого запуска доказать нельзя.

Площадка: ВЭС в Шелекском коридоре, Алматинская область, 43.645150 / 78.535604.

Запуск

git clone https://github.com/BAITC-Hacks/hack-2adafad9-kayo.git
cd hack-2adafad9-kayo
python -m venv .venv
# Linux/macOS: source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
python -m windagent.run --backtest
python checks/final_acceptance.py

Проверенная среда — Python 3.12. Зависимости устанавливаются через интернет; после установки полный архивный прогон работает без сети и без API-ключей. Погодные кеши и часовой срез турбин включены в репозиторий. Исходные десятиминутные CSV нужны только для пересборки часового кеша.

Одна команда делает всё: собирает часовые данные турбин, снимает кривые мощности, обучает модель, проверяет агентный цикл на отложенном окне и прокручивает его по графику из условия — выпуски 30 и 31 января, 1 февраля и далее каждый день до 27 февраля, каждый на следующие 24–48 часов. Прогноз на февраль — это ровно то, что выпустил агент в эти дни.

Что появится:

ПутьЧто внутри
forecasts/2026-02/forecast_T1.csv, forecast_T2.csvпрогноз агента: 672 часа × 2 горизонта на турбину
forecasts/metrics.csvметрики по моделям, горизонтам и режимам
out/agent_log.jsonжурнал агента: каждый шаг каждого выпуска
web/data.json, web/data.jsданные для дашборда

Колонки прогноза:

КолонкаСмысл
issue_timeмомент выпуска прогноза, UTC
timeчас, на который прогноз, UTC
time_localтот же час по времени Алматы (UTC+5) — как в данных организаторов
lead_hкорзина: 24 — следующие 1–24 часа, 48 — следующие 25–48 часов
effective_lead_hфактическое число часов между выпуском и целевым часом: 1–48
weather_lead_hвозраст погодного прогноза относительно целевого часа: 48 или 72 ч
weather_reference_timeцелевой час минус возраст погоды; номинальная опорная метка, не точный init
p50прогноз выработки, доля от номинала
p10, p90диапазон с целевым покрытием 80 %; измеренное покрытие указано ниже

Дашборд — web/index.html, интернет не нужен. Для 3D-сцены запустите локальный сервер из папки web: python -m http.server 8765, затем откройте http://127.0.0.1:8765/index.html. При открытии файла двойным кликом браузер может запретить загрузку модуля Three.js — тогда сцена автоматически переключится на Canvas.

Дашборд

Первый экран — интерактивная 3D-сцена двух турбин. Компактная панель позволяет запускать и ставить на паузу просмотр, видеть выбранный час и отдельно скорость ветра; шкала времени выбирает час в 48-часовом выпуске. Перетаскивайте сцену, чтобы менять положение камеры, а кнопкой «Сбросить вид» возвращайте исходный ракурс. Для выбранного часа показаны P50, диапазон P10–P90 и прогноз ветра на высоте 100 м из того же выпуска Open-Meteo Previous Runs API, что использован моделью. Направление ветра дано по метеорологическому правилу — откуда он дует; линии в сцене движутся по ветру, в противоположную сторону. Их выраженность и схематическая скорость вращения лопастей меняются вместе с прогнозным wind_speed_100m; это визуализация прогноза, а не физическая симуляция. Фактические обороты и ориентация турбин в исходных данных не указаны. Сцена работает через локальный Three.js/WebGL, а при недоступном WebGL переключается на Canvas. Под ней остаётся подробный отчёт.

«На карте» показывает обе турбины по координатам из ссылок в условии: T1 — 43.645150 / 78.535604, T2 — 43.643198 / 78.538828. Карте нужны интернет и отдельный ключ JavaScript API Яндекс Карт. Локальный web/map-config.json имеет поле apiKey и исключён из Git; для запуска на другом компьютере создайте свой конфиг. В кабинете Яндекса укажите допустимые HTTP Referer, в том числе localhost и 127.0.0.1 для локальной проверки. Ключ браузерного API виден браузеру, его доступ ограничивается доменами в кабинете. Основной прогноз и 3D-сцена работают без карты.

Экспорт предлагает выбранный выпуск или весь период. Excel — настоящий .xlsx с листами «Сводка», «Прогноз», «Точность», «Описание», «Журнал», числовыми значениями и фильтрами. В начале почасового листа — местное время, турбина, P10/P50/P90 и ветер; технические метки находятся справа. Длинные пояснения переносятся по строкам, шапки закреплены. Лист «Экономика» содержит текущий сценарий и формулы: изменение мощности или цены ошибки пересчитывает оценку. PDF — отдельный отчёт с показателями, графиком выбранного выпуска и полной почасовой таблицей; кнопка скачивает готовый .pdf без диалога печати. Обе выгрузки включают обе турбины и все доступные часы выпуска; на границе февраля выпуск может быть неполным. Время UTC и UTC+5 подписано. Даты Excel имеют числовой формат дат и подходят для фильтрации. Формирование отчётов работает локально без сети.

Экономический сценарий

После почасового графика показана сценарная цена ошибки. Пользователь задаёт номинал одной турбины и условную цену ошибки; исходные 2,5 МВт и 12 000 ₸/МВт·ч — допущения, а не данные ВЭС. Расчёт: nMAE × число турбин × номинал × часы периода × цена ошибки. При исходных параметрах и округлённых метриках дашборда: 15,35 млн ₸ для базы, 7,22 млн ₸ для агента, разница 8,13 млн ₸. Это перенос средней ошибки валидации на масштаб 28 дней, не измеренная экономия февраля, не выручка и не прибыль. Реальные договоры могут рассчитывать небаланс иначе.

Ожидаемая выработка по P50 при том же номинале — около 1 620,5 МВт·ч: суммируются часы обеих турбин только на горизонте 24 ч; 48 ч не добавляется второй раз. Денежный сценарий всегда относится ко всему периоду, даже если почасовая таблица экспортируется только для одного выпуска.

Условие кейса не назначает обязательную денежную метрику или конкретную формулу ошибки. Обязательный результат — почасовой прогноз двух турбин и работающий агентный цикл. Для оценки качества мы выбрали nMAE, nRMSE, смещение, улучшение против базовой линии и покрытие P10–P90; денежный сценарий поясняет применимость решения, оцениваемую жюри отдельно.

Ещё два режима:

python -m windagent.run --forecast   # живой выпуск на ближайшие 24–48 часов по свежей погоде (нужна сеть)
python -m windagent.run --export     # пересобрать web/data.json без выгрузок в forecasts/

Время полного прогона: около минуты на ноутбуке (обучение, валидация модели и агентного цикла на 93 выпусках, прокрутка февраля на 29 выпусках, все выгрузки). Модель — HistGradientBoosting из scikit-learn, считает на CPU.

Языковая модель

Объяснение для диспетчера пишет языковая модель. Ключ кладётся в файл .env в корне (он в .gitignore):

OPENAI_API_KEY=sk-...
# LLM_PROVIDER=nvidia и NVIDIA_API_KEY=[скрыто] — NVIDIA NIM
# LLM_MODEL=gpt-6-sol — другая модель

По умолчанию — gpt-6-luna. Без ключа система работает полностью: прогноз, проверки и журнал не зависят от языковой модели, объяснение собирается шаблоном из тех же чисел (статус «шаблон» в журнале). Проверить ключ: python checks/llm_ping.py.

Архитектура

1. Погода: Open-Meteo Previous Runs
                 |
2. Подготовка: часовая сетка, признаки, отбраковка простоев
                 |
3. Модель: кривая мощности + бустинг, P10/P50/P90
                 |
4. Прогноз на 24–48 часов
                 |
5. Анализ: сравнение с базовыми линиями
                 |
6. Пересчёт при новом прогоне погоды
       /                         \
Рефлексия по доступному факту       Шлюз качества: откат, если хуже базы
                 |
Объяснение результата; запись каждого шага в журнал

Где что считается:

  • Числа считает код. Кривая мощности, бустинг, метрики, интервалы — обычный Python, без языковой модели. Это принципиально: прогноз выработки не должен зависеть от того, что «подумала» LLM.
  • Языковая модель объясняет. Читает готовые цифры и пишет разбор для диспетчера: что ждёт станцию, где риск ошибки. Ни одна цифра прогноза от неё не зависит.
  • Решение о пересчёте. Когда выходит новый прогон погоды, агент сравнивает его с прошлым на перекрывающихся часах: если ветер сдвинулся меньше чем на 1 м/с, оставляет прежний прогноз и пишет «пересчёт не нужен», иначе считает заново.
  • Рефлексия. Перед публикацией агент сверяет свою медиану с фактом последних 14 суток и снимает систематическое смещение, если оно больше двух стандартных ошибок.
  • Шлюз качества стоит между расчётом и публикацией. Если на последних 14 днях с фактом решение проигрывает прогнозу «как вчера», агент публикует чистую кривую мощности и пишет откат в журнал.
  • Отказы не валят цикл. Нет сети или данных — запись error в журнале и понятная причина.

Провайдер языковой модели переключается переменной окружения: OpenAI или NVIDIA NIM (https://integrate.api.nvidia.com/v1, тот же клиент, меняется адрес и ключ).

Данные

ИсточникЧто берём
CSV турбин (даны организаторами)скорость ветра, нормализованная мощность, температура; шаг 10 минут, 11.03.2023 — 31.01.2026
Open-Meteo Previous Runs APIархивные прогнозы: ветер и направление на 100 м, ветер на 10 м, температура, давление

Обработка данных турбин:

  • часовое усреднение с подсчётом числа замеров в часе — неполные часы в обучение не идут;
  • метки времени в файлах местные, а не UTC. Сдвиг определён по взаимной корреляции измеренного ветра с прогнозным: 6 часов до перехода Казахстана на единый пояс и 5 после. Без этой поправки прогноз и факт разъезжаются на несколько часов, и любая метрика теряет смысл;
  • «ноль» в данных записан как 0.01, мощность квантована до сотых — приводим к настоящему нулю;
  • часы простоя (мощность ≈ 0 при рабочем ветре, около 1,5 % времени, серии до 47 часов) помечены отдельно: это ограничения выдачи, а не физика. В обучение они не идут и в основную метрику тоже, но показаны отдельной строкой — прятать их было бы нечестно.

Базовая погодная модель названа явно — ICON (icon_seamless). Запрос без модели («best match») отдаёт Open-Meteo на выбор, и 1 октября 2025 он сам переключился с ICON на другую модель: обучение шло бы на одной, февраль — на другой.

Архив прогнозов погоды — ICON, GFS и ECMWF, включая отдельные day3-кеши — лежит в репозитории (data/weather/*.parquet), поэтому архивный прогон воспроизводится без интернета.

Турбины стоят в 338 м друг от друга и попадают в одну ячейку любой погодной сетки, поэтому погода запрашивается один раз, а различия между машинами модель ловит признаком турбины.

Почему не historical-forecast-api

Очевидный кандидат на «архив прогнозов» у Open-Meteo — historical-forecast-api. Для этого кейса он не годится, и это главная ловушка задания.

Этот эндпоинт склеивает непрерывный ряд из первых часов каждого прогона (горизонт 0–3 часа). То есть каждое значение там — это почти факт: прогноз, выпущенный час-два назад, знает текущую погоду. Модель, обученная на таком входе, показывает отличные метрики на валидации и разваливается, когда ей дают настоящий прогноз на сутки вперёд, — а именно так её и будут использовать.

У Previous Runs API тоже есть важное ограничение: _previous_dayN задаёт возраст относительно целевого часа, а не один запуск модели на момент ежедневного выпуска. Если в полночь объявить выпуск и взять day1 на весь следующий день, поздние часы будут опираться на погоду позже выпуска.

Поэтому windagent/asof.py использует следующий фиксированный протокол:

ПараметрСледующие суткиВторые сутки
Выпуск23:00 UTCтот же выпуск
Фактический горизонт1–24 ч25–48 ч
Погодный архивprevious_day2previous_day3
Возраст относительно целевого часа48 ч72 ч
Запас reference time до выпуска24–47 ч24–47 ч

Доступность предполагает задержку публикации ≤24 ч. Это смесь значений с фиксированным возрастом, не реконструкция единственного метеорологического запуска. Для строгой реконструкции нужны архивы отдельных запусков с временем фактической публикации. Семантика источника: Previous Runs API, Single Runs API.

Проверка python checks/asof_weather.py сравнивает значения с day2/day3-кешами, проверяет запас до выпуска, закрытый час персистентности и live-окно 1–48 ч. JSON сохраняет описание допущения в forecast_protocol; CSV — временные метки, необходимые для независимой проверки.

Модель и метрики

Четыре слоя:

  1. Ансамбль погодных моделей — к базовому ICON добавлены среднее и разброс по ICON, GFS и ECMWF, каждая со своими прогнозами day2/day3. Среднее и разброс между моделями используются как признаки; сам по себе разброс не является калиброванной вероятностью ошибки. Сглаживание ветра по соседним часам считается внутри блока выпуска — один горизонт, одни сутки, — то есть ровно по тому, что агент видит в день выпуска.
  2. Кривая мощности — эмпирическая, по бинам прогнозной скорости, отдельно для каждой турбины и каждого горизонта. Строится на прогнозной, а не измеренной скорости: прогноз сглажен относительно показаний анемометра, и кривая, снятая с измерений, дала бы систематическое смещение.
  3. Градиентный бустинг на остаток — учит то, что физика не объясняет: систематические ошибки прогноза погоды, плотность воздуха, направление, сезон, час. Отдельные квантильные модели дают коридор P10–P90, поверх — конформная калибровка на отложенном срезе, чтобы покрытие соответствовало заявленному.
  4. Рефлексия агента — перед публикацией агент сверяет свою медиану с фактом последних 14 суток по каждой турбине и снимает смещение, если оно больше двух стандартных ошибок, то есть отличимо от шума; иначе пишет в журнал «в пределах шума, поправка не нужна». Сдвигается только медиана внутри коридора. Зимой модель систематически завышает, и рефлексия это ловит: строка «наше решение» против «модели без агента» в таблице ниже, замер — checks/reflect_eval.py.

Валидация — отложенное окно ноябрь 2025 — январь 2026: модель этих данных не видела, а зима — тот же режим, что и в феврале. Февраль 2026 проверить нечем: в выданных данных его нет, это режим поставки, а не теста.

«Наше решение» измерено тем же агентным циклом, который выпускает февраль, и в том же режиме: факт обрывается в начале каждого месяца валидации, как в феврале он кончается 31 января, и агент переносит поправку смещения по последним 14 суткам известного факта (если ему не больше 30 суток). Замер checks/stale_reflect.py. Рядом — та же модель без агента и лестница базовых линий: климатология по месяцу и часу, персистентность («как сутки назад»), их смесь и эмпирическая кривая мощности. Часы без простоев. Персистентность получает ежедневный факт, а агент в режиме поставки — только факт до начала месяца: базовая линия имеет больше информации. Сравнение при одинаковой доступности входов — агент против модели без агента и кривой мощности.

МодельnMAE 24 чnMAE 48 чСкилл 24 чСкилл 48 ч
Наше решение (агентный цикл, режим поставки)0,1790,1930,530,50
Агент при ежедневном факте0,1800,1930,530,50
Модель без агента0,1920,2080,500,46
Кривая мощности0,1930,2100,490,46
Персистентность + климатология0,3290,3310,140,14
Климатология0,3310,3310,130,14
Персистентность0,3810,38600

nMAE — средняя ошибка в долях номинала: 0,179 значит, что прогноз в среднем ошибается на 17,9 % мощности турбины. Скилл — относительное снижение MAE против персистентности: 0,53 — примерно на 53 %.

Покрытие коридора P10–P90: 79,4 % при средней ширине 0,522 (цель — 80 %). Достигается конформной калибровкой: квантильные модели учатся без прошлой зимы (ноябрь 2024 — февраль 2025), а на ней оценивается конформный отступ — отдельно на пару «турбина × горизонт», потому что у 48 ч разброс шире. Цели калибровочного окна исключены и из обучения квантилей, и из кривой мощности. Обучение заканчивается 30.10.2025 в 22:00 UTC — до первого выпуска валидации. Старые эксперименты с соседними окнами относятся к предыдущему протоколу; их числа здесь не используются.

Как мы поймали утечку у себя

Прежняя версия показывала nMAE 0,156. Независимое ревью нашло, что сглаживание ветра по соседним часам считалось по строкам таблицы, где соседями одного часа были горизонты 0, 24 и 48 — и в признак для суточного прогноза подмешивался ноукаст. Теперь окна считаются внутри блока выпуска одной функцией для обучения и для агента, и признаки поставки совпадают с обучающими до нуля (checks/agent_cycle.py). Затем проверка расписания нашла вторую проблему: возраст day1/day2 ошибочно трактовался как доступность всего суточного выпуска. Исправлены погодные источники, момент выпуска, граница обучения и доступность базовой линии; метрики пересчитаны целиком. Прежние 0,164/0,179 не относятся к текущему протоколу и не используются в итоговой оценке.

Метрики нормированы на установленную мощность, поэтому читаются как доля от номинала.

Требования кейса и где они выполнены

ТребованиеГдеКак проверить
Модель прогноза по историческим даннымwindagent/model.pypython -m windagent.run --backtest, таблица метрик
Прогноз погоды получается самостоятельно по координатамwindagent/weather.pypython -m windagent.run --forecast — живой запрос
Почасовой прогноз на 24–48 часовwindagent/model.py, признак lead_hforecasts/2026-02/forecast_T1.csv
Полный агентный цикл с пересчётомwindagent/agent.pyжурнал шагов на дашборде и в out/agent_log.json
Прогноз воспроизведён «как в прошлом», день за днёмwindagent/agent.py, rolloutколонка issue_time в forecast_T*.csv: выпуски 30.01 — 27.02
Только архивные прогнозы, не фактическая погодаwindagent/weather.pyраздел «Почему не historical-forecast-api»

Проверка по критериям жюри

КритерийЧто предъявляемОграничение
Соответствие задаче, 25две турбины, почасовой февраль, ежедневные выпуски, шесть шагов цикладоступность погоды опирается на явно указанное допущение
Техническая реализация, 25единые признаки обучения/поставки, независимая валидация, базовые линии, квантили, проверки времениодной площадки недостаточно для доказательства переноса на другие ВЭС
README и воспроизводимость, 25чистый клон, кеши, одна команда, безключевой режим, CSV/JSON и автоматическая приёмкаlive и карта требуют сети; карта дополнительно требует своего ключа
Ценность, 15меньшая ошибка против персистентности, диапазон риска, отчёты PDF/Excelфактическая экономия не измерена, договорных тарифов нет
Оригинальность и потенциал, 10перенос рефлексии без свежего факта, проверка утечек, 3D/карта, отдельный экспериментдополнительные признаки принимаются только при подтверждённом улучшении

Это сопоставление с условиями, а не обещание оценки жюри.

Расширенная модель: 36 признаков вместо 18

Проверен отдельный вариант с компонентами ветра, дополнительными гармониками направления, суточной/сезонной цикличностью, изменениями ветра и давления внутри выпуска, разногласием погодных моделей и взаимодействиями признаков. Окна и параметры обучения оставлены прежними; оба варианта прошли один и тот же агентный цикл. Подбора по валидации не было.

ВариантnMAE 1–24 чnMAE 25–48 чПокрытиеШирина
Основной0,17910,193079,4 %0,522
Расширенный0,19090,203076,8 %0,651

Дополнительные признаки ухудшили результат, поэтому они не включены в поставку. Воспроизведение: python -m windagent.extended; подробный результат — out/extended_experiment.json. Эксперимент не перезаписывает официальные прогнозы и данные дашборда.

Автоматическая приёмка

python checks/asof_weather.py
python checks/agent_cycle.py
python checks/final_acceptance.py
python checks/extended_features.py

Проверяются 2 688 строк поставки, отсутствие дубликатов, оба горизонта и обе турбины, порядок квантилей, совпадение CSV/JSON, время UTC+5, происхождение погоды, запас до выпуска и совпадение признаков между обучением и агентом. Для полного пересчёта сначала выполните --backtest.

Чистый клон коммита bf0c3c5 проверен в отдельном venv: установка зависимостей, полный прогон без .env и API-ключей (30,5 с), затем final_acceptance.py — успешно. В журнале пять шаблонных объяснений, ошибок нет. Веб-интерфейс дополнительно проверен на 1280×900, 390×844 и 390×667; Excel прочитан через openpyxl и сверен с JSON, PDF скачан напрямую и проверен через PyMuPDF; кириллица и все строки сохранены.

Ограничения

  • Февраль 2026 проверить нечем. В выданных данных его нет, поэтому качество на нём заявлять нельзя — мы показываем метрики на отложенном окне и явно об этом пишем.
  • Часы ограничения выдачи исключены из основной метрики: предсказать решение диспетчера по погоде невозможно, но их доля и влияние показаны отдельно.
  • Прогноз даётся в долях от номинала, как в исходных данных. Экономический блок на дашборде — оценка порядка величин на допущениях: мощность турбины 2,5 МВт и штраф за небаланс 12 000 ₸/МВт·ч — не тарифы станции.
  • Покрытие коридора 79,4 % — измерение на валидации, не гарантия для февраля или другой площадки.
  • Календарные границы февральской выгрузки заданы в UTC; time_local показывает сдвиг +5 ч.
  • Времена фактической публикации архивных погодных запусков отсутствуют: используется запас 24 ч и допущение о задержке, а не доказательство доступности каждого отдельного запуска.
  • Одна площадка и одна ячейка погодной сетки: на парк из десятков турбин решение переносится, но потребует учёта затенения между машинами.
  • Горизонт ограничен глубиной архива Previous Runs — с 17.02.2024.
  • Live использует свежую погоду, а обучение — консервативный day2/day3-архив. Качество live отдельным бэктестом не подтверждено; приведённые метрики относятся к архивному протоколу.

Подключение к действующей ВЭС

Собственник может использовать решение как основу для пилота вместе со своей ИТ-командой или интегратором. Точка подключения — система мониторинга станции (SCADA), её база или регулярная выгрузка. На первом этапе достаточно доступа к измерениям для чтения; система формирует прогноз, а решение о плане поставки принимает диспетчер.

Что потребуется от станции

Данные или доступДля чего нужны
Идентификаторы, координаты и номинальная мощность каждой турбиныпривязать измерения и погоду, переводить доли номинала в МВт
История и новые измерения активной мощности с временными метками, единицами и часовым поясомобучить модель на площадке, проверять ошибки и корректировать смещение
Статусы работы, простои и ограничения выдачи, если доступныотличать недостаток ветра от остановки или ограничения оборудования
Описание API, структуры базы или формата выгрузкиразработать адаптер конкретной системы мониторинга
Условия расчёта небаланса и реальные параметры станциизаменить демонстрационный денежный сценарий расчётом по договору
Сервер и доступ к источнику прогноза погодывыполнять расчёт регулярно и сохранять выпуски

Для другой ВЭС потребуется обучение и отдельная валидация на её истории. Качество на двух турбинах этого кейса не доказывает такую же точность на новой площадке.

Как данные используются в работе

  1. Сервис получает измерения станции и новый прогноз погоды, проверяет время, пропуски и единицы.
  2. Агент рассчитывает почасовые P10/P50/P90 на следующие 48 часов и записывает причины пересчёта.
  3. Диспетчер использует P50 как ориентир для плана выработки, а диапазон — для оценки неопределённости отдельных часов. Мощность в МВт получается умножением нормированного прогноза на номинал турбины; почасовые значения позволяют оценить энергию в МВт·ч.
  4. После поступления факта сравниваются прогноз и измерения: nMAE, nRMSE, смещение, улучшение относительно базовой линии и покрытие диапазона. Эти показатели оценивают качество системы.
  5. Планировщик и собственник получают отчёт Excel/PDF. Денежный эффект оценивается по реальным условиям договора; заявка на рынок формируется отдельным процессом.

Что уже автоматизировано, а что нужно добавить

ВозможностьСостояние прототипа
Получение погоды, подготовка признаков, расчёт, анализ и решение о пересчётевыполняются программно после запуска команды
Восстановление февральских выпусков и отчётовpython -m windagent.run --backtest
Разовый расчёт по свежей погодеpython -m windagent.run --forecast; результат выводится в консоль
Запуск каждый день без человеканужно настроить планировщик на сервере; в репозитории он не настроен
Получение свежей телеметрии SCADAнужно реализовать адаптер станции; сейчас используется исторический часовой кеш
Непрерывное обновление дашборда живыми выпускаминужно добавить сохранение live-результата и обновление данных страницы
Передача прогноза в систему планирования станциинужно согласовать формат и реализовать интеграцию
Отправка рыночных заявок и управление оборудованиемв прототипе отсутствуют

Обновление страницы не запускает прогноз. Сейчас дашборд показывает рассчитанные февральские выпуски. Для постоянной эксплуатации к существующему расчётному циклу нужно добавить расписание, приём новых измерений, хранение выпусков, контроль сбоев и отображение времени последнего успешного расчёта. Приёмка live-режима должна включать сетевую проверку источников и накопление ошибок на новых фактических данных; архивные метрики её не заменяют.

Что дальше

  • Сезонная поправка вместо скользящей: смещение зимой устойчиво отрицательное (≈ −0,08), его можно учить признаком, а не ловить рефлексией.
  • Учёт затенения между турбинами по направлению ветра — на парке это заметный вклад.
  • Перевод прогноза в заявку на рынок с учётом несимметричного штрафа за небаланс: занижать и завышать стоит по-разному.
Звёзды
⭐ 0
Форки
0
Язык
JavaScript
Последний push
в прошлом месяце
Коммиты
21
Авторы
1
Файлы
57
Ветки
1

Авторы коммитов

Bekarys Pernebayev 21

История коммитов

  • 2026-09-23 17:54Назвать систему Samal и оформить материалы для Самрук-КазынаBekarys Pernebayev
  • 2026-09-23 17:53Описать подключение к ВЭС и автоматизацию рабочих прогнозовBekarys Pernebayev
  • 2026-09-23 17:47Выделить кнопку раскрытия расчёта экономикиBekarys Pernebayev
  • 2026-09-23 17:45Добавить экономический сценарий, удобный Excel и прямое скачивание PDFBekarys Pernebayev
  • 2026-09-23 17:45Согласовать выпуски с архивом погоды и добавить отчёты собственникаBekarys Pernebayev
  • 2026-09-23 16:59Упростить управление сценой и сделать потоки ветра заметнееBekarys Pernebayev
  • 2026-09-23 16:48Добавить 3D-сцену прогноза с ветромBekarys Pernebayev
  • 2026-09-23 16:16Сделать дашборд светлым и понятнымBekarys Pernebayev
Все коммиты (21)
  • 2026-09-23 16:05Обновить схему агентного цикла и проверку переноса поправкиBekarys Pernebayev
  • 2026-09-23 16:03Редизайн дашборда с циклом агента и актуальными скриншотамиBekarys Pernebayev
  • 2026-09-23 15:39Рефлексия при обрыве факта: перенос поправки по последним 14 суткамBekarys Pernebayev
  • 2026-09-23 15:24Дашборд: редизайн, защита от инъекций, журнал по выпускам; устойчивый llm.pyBekarys Pernebayev
  • 2026-09-23 15:22README: честные цифры после исправления утечки, формат CSV, ключ LLM, как нашли утечкуBekarys Pernebayev
  • 2026-09-23 15:21Утечка ноукаста в скользящих окнах, поставка из агентного циклаBekarys Pernebayev
  • 2026-09-23 14:45Калибровка коридора на прошлой зиме: покрытие 78 -> 81 %Bekarys Pernebayev
  • 2026-09-23 14:41Медиана на полной выборке, честный замер рефлексии, GPT-6 LunaBekarys Pernebayev
  • 2026-09-23 14:28Ансамбль ICON/GFS/ECMWF: среднее и разброс ветра как признакиBekarys Pernebayev
  • 2026-09-23 14:24pandas<3 в зависимостях, подписи статусов в журнале, скриншоты дашбордаBekarys Pernebayev
  • 2026-09-23 14:15README: убрать неверное «без GPU»Bekarys Pernebayev
  • 2026-09-23 14:14Агентный цикл, конформная калибровка коридора и рефлексияBekarys Pernebayev
  • 2026-09-23 14:07Прогноз выработки ВЭС: архивные прогнозы погоды, кривая мощности и бустинг, валидация на отложенном окнеBekarys Pernebayev
Структура репозитория (57 файлов)
.gitignore
README.md
checks/agent_cycle.py
checks/asof_weather.py
checks/base_choice.py
checks/calib_windows.py
checks/extended_features.py
checks/final_acceptance.py
checks/llm_ping.py
checks/reflect_eval.py
checks/stale_reflect.py
checks/timealign.py
data/turbines_hourly.parquet
data/weather/prev_runs_2024-02-17_2026-02-28.parquet
data/weather/prev_runs_2024-02-17_2026-02-28_ecmwf_ifs025.parquet
data/weather/prev_runs_2024-02-17_2026-02-28_gfs_seamless.parquet
data/weather/prev_runs_2024-02-17_2026-02-28_icon_seamless.parquet
data/weather/prev_runs_day3_2024-02-17_2026-02-28_ecmwf_ifs025.parquet
data/weather/prev_runs_day3_2024-02-17_2026-02-28_gfs_seamless.parquet
data/weather/prev_runs_day3_2024-02-17_2026-02-28_icon_seamless.parquet
docs/screenshots/dashboard-desktop.png
docs/screenshots/dashboard-mobile.png
forecasts/2026-02/forecast_T1.csv
forecasts/2026-02/forecast_T2.csv
forecasts/metrics.csv
out/agent_log.json
out/extended_experiment.json
requirements.txt
web/data.js
web/data.json
web/data.sample.json
web/forecast3d.css
web/forecast3d.js
web/icons/arrow-down.svg
web/icons/cube.svg
web/icons/file-text.svg
web/icons/map-line.svg
web/icons/pause.svg
web/icons/play.svg
web/icons/refresh-horizontal.svg
web/icons/table.svg
web/index.html
web/make_data_js.py
web/make_sample.py
web/pdf-report.js
web/report-export.js
web/yandex-map.js
windagent/__init__.py
windagent/agent.py
windagent/asof.py
windagent/backtest.py
windagent/data.py
windagent/extended.py
windagent/llm.py
windagent/model.py
windagent/run.py
windagent/weather.py

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.