grid / smartgrid_mas /engine /control.py
Not-OmKar's picture
Big update
427a79e
from __future__ import annotations
from dataclasses import dataclass
from smartgrid_mas.models import DispatchAction, MarketObservation
@dataclass
class ReliabilityDispatchControlAgent:
"""Reduced-order dispatcher that turns market state into corrective dispatch."""
personality: str = "balanced"
def act(self, obs: MarketObservation, cleared_mwh: float) -> DispatchAction:
forecast_gap = max(0.0, obs.forecast_demand_mwh - obs.forecast_renewable_mwh)
actual_gap = max(0.0, obs.demand_mwh - obs.renewable_availability_mwh)
scarcity = max(0.0, obs.scarcity_index)
reserve_pressure = min(1.0, max(0.0, scarcity - 0.15))
if self.personality == "risk_averse":
reserve_scale = 0.62
peaker_scale = 1.08
storage_scale = 0.82
redispatch_scale = 0.38
elif self.personality == "opportunistic":
reserve_scale = 0.34
peaker_scale = 0.72
storage_scale = 0.52
redispatch_scale = 0.22
else:
reserve_scale = 0.48
peaker_scale = 0.92
storage_scale = 0.68
redispatch_scale = 0.30
reserve_activation_mwh = max(0.0, forecast_gap * reserve_scale * (0.75 + 0.25 * reserve_pressure))
peaker_adjustment_mwh = max(0.0, actual_gap * peaker_scale * (0.85 + 0.15 * reserve_pressure))
storage_dispatch_mwh = 0.0
if scarcity > 0.25:
storage_dispatch_mwh = min(obs.ev_storage_mwh, actual_gap * storage_scale)
elif obs.renewable_availability_mwh > obs.demand_mwh * 0.95:
storage_dispatch_mwh = -min(
max(0.0, obs.ev_storage_capacity_mwh - obs.ev_storage_mwh),
(obs.renewable_availability_mwh - obs.demand_mwh) * 0.25,
)
corrective_redispatch_mwh = max(0.0, (cleared_mwh - obs.demand_mwh + actual_gap) * redispatch_scale)
if scarcity > 0.40:
corrective_redispatch_mwh += actual_gap * 0.20
elif scarcity < 0.12:
corrective_redispatch_mwh -= min(corrective_redispatch_mwh, obs.demand_mwh * 0.03)
return DispatchAction(
reserve_activation_mwh=round(reserve_activation_mwh, 3),
peaker_adjustment_mwh=round(peaker_adjustment_mwh, 3),
storage_dispatch_mwh=round(storage_dispatch_mwh, 3),
corrective_redispatch_mwh=round(corrective_redispatch_mwh, 3),
)