Coverage for agentlib_flexquant/data_structures/flex_offer.py: 100%
32 statements
« prev ^ index » next coverage.py v7.4.4, created at 2025-10-20 14:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2025-10-20 14:09 +0000
1"""
2Data models for flexibility offers.
4This module defines data structures for representing flexibility offers in energy markets,
5including baseline power profiles, positive and negative flexibility pricing, and offer
6status tracking. The FlexOffer class encapsulates all information needed to represent
7a flexibility bid, including power differences from baseline and acceptance status.
8"""
9from enum import Enum
10from typing import Optional
12import pandas as pd
13import pydantic
14from agentlib.core.datamodels import _TYPE_MAP
15from pydantic import BaseModel
18class OfferStatus(Enum):
19 """Status of the FlexOffer"""
21 NOT_ACCEPTED = "Not Accepted"
22 ACCEPTED_POSITIVE = "Accepted Positive"
23 ACCEPTED_NEGATIVE = "Accepted Negative"
26class FlexOffer(BaseModel):
27 """Data class for the flexibility offer."""
29 base_power_profile: pd.Series = pydantic.Field(
30 default=None,
31 unit="W",
32 scalar=False,
33 description="Power profile of the baseline MPC",
34 )
35 pos_price: Optional[float] = pydantic.Field(
36 default=None,
37 unit="ct",
38 scalar=True,
39 description="Price for positive flexibility",
40 )
41 pos_diff_profile: pd.Series = pydantic.Field(
42 default=None,
43 unit="W",
44 scalar=False,
45 description="Power profile for the positive difference",
46 )
47 neg_price: Optional[float] = pydantic.Field(
48 default=None,
49 unit="ct",
50 scalar=True,
51 description="Price for negative flexibility",
52 )
53 neg_diff_profile: pd.Series = pydantic.Field(
54 default=None,
55 unit="W",
56 scalar=False,
57 description="Power profile for the negative difference",
58 )
59 status: OfferStatus = pydantic.Field(
60 default=OfferStatus.NOT_ACCEPTED.value,
61 scalar=True,
62 description="Status of the FlexOffer",
63 )
65 class Config:
66 """Allow arbitrary (non-Pydantic) types such as pandas.Series or numpy.ndarray
67 in model fields without requiring custom validators."""
69 arbitrary_types_allowed = True
71 def as_dataframe(self) -> pd.DataFrame:
72 """Store the flexibility offer in a pd.DataFrame
74 Returns:
75 DataFrame containing the flexibility offer.
76 Scalar values are written on the first timestep.
78 """
79 data = []
80 cols = []
82 # append scalar values
83 for name, field in self.model_fields.items():
84 if field.json_schema_extra["scalar"]:
85 ser = pd.Series(getattr(self, name))
86 ser.index += self.base_power_profile.index[0]
87 data.append(ser)
88 cols.append(name)
90 df = pd.DataFrame(data).T
91 df.columns = cols
92 return df
95# add the offer type to agent variables
96_TYPE_MAP["FlexOffer"] = FlexOffer