mms-client 1.10.0__py3-none-any.whl → 1.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mms_client/schemas/wsdl/mi-web-service-jbms.wsdl +276 -276
- mms_client/schemas/wsdl/omi-web-service.wsdl +262 -262
- mms_client/schemas/xsd/mi-market.xsd +2405 -2395
- mms_client/schemas/xsd/mi-outbnd-reports.xsd +1554 -1488
- mms_client/schemas/xsd/mi-report.xsd +379 -379
- mms_client/schemas/xsd/mpr.xsd +1858 -1816
- mms_client/schemas/xsd/omi.xsd +913 -793
- mms_client/services/base.py +1 -1
- mms_client/services/market.py +122 -0
- mms_client/services/omi.py +99 -0
- mms_client/types/award.py +6 -0
- mms_client/types/bup.py +207 -0
- mms_client/types/market.py +15 -2
- mms_client/types/offer.py +6 -0
- mms_client/types/omi.py +26 -0
- mms_client/types/settlement.py +81 -0
- mms_client/types/surplus_capcity.py +187 -0
- mms_client/utils/serialization.py +5 -2
- {mms_client-1.10.0.dist-info → mms_client-1.11.0.dist-info}/METADATA +8 -3
- {mms_client-1.10.0.dist-info → mms_client-1.11.0.dist-info}/RECORD +22 -18
- {mms_client-1.10.0.dist-info → mms_client-1.11.0.dist-info}/LICENSE +0 -0
- {mms_client-1.10.0.dist-info → mms_client-1.11.0.dist-info}/WHEEL +0 -0
mms_client/services/base.py
CHANGED
|
@@ -420,7 +420,7 @@ class BaseClient: # pylint: disable=too-many-instance-attributes
|
|
|
420
420
|
|
|
421
421
|
# First, create the MMS request from the payload and data.
|
|
422
422
|
is_list = isinstance(payload, list)
|
|
423
|
-
data_type = type(payload[0]) if is_list else type(payload) # type: ignore[index]
|
|
423
|
+
data_type: type = type(payload[0]) if is_list else type(payload) # type: ignore[index]
|
|
424
424
|
logger.debug(
|
|
425
425
|
(
|
|
426
426
|
f"{config.name}: Starting multi-request. Envelope: {type(envelope).__name__}, "
|
mms_client/services/market.py
CHANGED
|
@@ -12,6 +12,9 @@ from mms_client.services.base import mms_endpoint
|
|
|
12
12
|
from mms_client.services.base import mms_multi_endpoint
|
|
13
13
|
from mms_client.types.award import AwardQuery
|
|
14
14
|
from mms_client.types.award import AwardResponse
|
|
15
|
+
from mms_client.types.bup import BalancingUnitPriceQuery
|
|
16
|
+
from mms_client.types.bup import BalancingUnitPriceSubmit
|
|
17
|
+
from mms_client.types.market import Defaults
|
|
15
18
|
from mms_client.types.market import MarketCancel
|
|
16
19
|
from mms_client.types.market import MarketQuery
|
|
17
20
|
from mms_client.types.market import MarketSubmit
|
|
@@ -21,6 +24,8 @@ from mms_client.types.offer import OfferData
|
|
|
21
24
|
from mms_client.types.offer import OfferQuery
|
|
22
25
|
from mms_client.types.reserve import ReserveRequirement
|
|
23
26
|
from mms_client.types.reserve import ReserveRequirementQuery
|
|
27
|
+
from mms_client.types.settlement import SettlementQuery
|
|
28
|
+
from mms_client.types.settlement import SettlementResults
|
|
24
29
|
from mms_client.types.transport import RequestType
|
|
25
30
|
from mms_client.utils.serialization import SchemaType
|
|
26
31
|
from mms_client.utils.serialization import Serializer
|
|
@@ -213,3 +218,120 @@ class MarketClientMixin: # pylint: disable=unused-argument
|
|
|
213
218
|
user=self.user,
|
|
214
219
|
days=days,
|
|
215
220
|
)
|
|
221
|
+
|
|
222
|
+
@mms_endpoint(
|
|
223
|
+
name="MarketQuery_SettlementResultsFileListQuery",
|
|
224
|
+
service=config,
|
|
225
|
+
request_type=RequestType.MARKET,
|
|
226
|
+
response_envelope_type=MarketSubmit,
|
|
227
|
+
response_data_type=SettlementResults,
|
|
228
|
+
allowed_clients=[ClientType.BSP, ClientType.TSO],
|
|
229
|
+
)
|
|
230
|
+
def get_settlement_results(
|
|
231
|
+
self: ClientProto, request: SettlementQuery, days: int, date: Optional[Date] = None
|
|
232
|
+
) -> SettlementResults:
|
|
233
|
+
"""Query the MMS server for settlement results.
|
|
234
|
+
|
|
235
|
+
This endpoint is only accessible to BSPs and TSOs.
|
|
236
|
+
|
|
237
|
+
Arguments:
|
|
238
|
+
request (SettlementQuery): The query to submit to the MMS server.
|
|
239
|
+
days (int): The number of days ahead for which the data is being queried.
|
|
240
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults to the
|
|
241
|
+
current date.
|
|
242
|
+
|
|
243
|
+
Returns: The settlement results that match the query.
|
|
244
|
+
"""
|
|
245
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
246
|
+
return MarketQuery( # type: ignore[return-value]
|
|
247
|
+
date=date or Date.today(),
|
|
248
|
+
participant=self.participant,
|
|
249
|
+
user=self.user,
|
|
250
|
+
days=days,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
@mms_multi_endpoint(
|
|
254
|
+
name="MarketSubmit_BupSubmit", service=config, request_type=RequestType.MARKET, allowed_clients=[ClientType.BSP]
|
|
255
|
+
)
|
|
256
|
+
def put_bups(
|
|
257
|
+
self: ClientProto,
|
|
258
|
+
requests: List[BalancingUnitPriceSubmit],
|
|
259
|
+
date: Optional[Date] = None,
|
|
260
|
+
default: bool = False,
|
|
261
|
+
) -> List[BalancingUnitPriceSubmit]:
|
|
262
|
+
"""Submit multiple balancing unit prices to the MMS server.
|
|
263
|
+
|
|
264
|
+
This endpoint is only accessible to BSPs.
|
|
265
|
+
|
|
266
|
+
Arguments:
|
|
267
|
+
requests (List[BalancingUnitPriceSubmit]): The balancing unit prices to submit to the MMS server.
|
|
268
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value
|
|
269
|
+
defaults to the current date.
|
|
270
|
+
default (bool): Whether or not the balancing unit prices are the default.
|
|
271
|
+
|
|
272
|
+
Returns: A list of balancing unit prices that have been registered with the MMS server.
|
|
273
|
+
"""
|
|
274
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
275
|
+
return MarketSubmit( # type: ignore[return-value]
|
|
276
|
+
date=date or Date.today(),
|
|
277
|
+
participant=self.participant,
|
|
278
|
+
user=self.user,
|
|
279
|
+
defaults=Defaults(is_default=default),
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
@mms_endpoint(
|
|
283
|
+
name="MarketSubmit_BupSubmit", service=config, request_type=RequestType.MARKET, allowed_clients=[ClientType.BSP]
|
|
284
|
+
)
|
|
285
|
+
def put_bup(
|
|
286
|
+
self: ClientProto,
|
|
287
|
+
request: BalancingUnitPriceSubmit,
|
|
288
|
+
date: Optional[Date] = None,
|
|
289
|
+
default: bool = False,
|
|
290
|
+
) -> BalancingUnitPriceSubmit:
|
|
291
|
+
"""Submit a balancing unit price to the MMS server.
|
|
292
|
+
|
|
293
|
+
This endpoint is only accessible to BSPs.
|
|
294
|
+
|
|
295
|
+
Arguments:
|
|
296
|
+
request (BalancingUnitPriceSubmit): The balancing unit price to submit to the MMS server.
|
|
297
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults
|
|
298
|
+
to the current date.
|
|
299
|
+
default (bool): Whether or not the balancing unit price is the default.
|
|
300
|
+
|
|
301
|
+
Returns: The balancing unit price that has been registered with the MMS server.
|
|
302
|
+
"""
|
|
303
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
304
|
+
return MarketSubmit( # type: ignore[return-value]
|
|
305
|
+
date=date or Date.today(),
|
|
306
|
+
participant=self.participant,
|
|
307
|
+
user=self.user,
|
|
308
|
+
defaults=Defaults(is_default=default),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
@mms_multi_endpoint(
|
|
312
|
+
name="MarketQuery_BupQuery",
|
|
313
|
+
service=config,
|
|
314
|
+
request_type=RequestType.MARKET,
|
|
315
|
+
response_envelope_type=MarketSubmit,
|
|
316
|
+
response_data_type=BalancingUnitPriceSubmit,
|
|
317
|
+
)
|
|
318
|
+
def query_bups(
|
|
319
|
+
self: ClientProto, request: BalancingUnitPriceQuery, date: Optional[Date] = None
|
|
320
|
+
) -> List[BalancingUnitPriceSubmit]:
|
|
321
|
+
"""Query the MMS server for balancing unit prices.
|
|
322
|
+
|
|
323
|
+
This endpoint is accessible to all client types.
|
|
324
|
+
|
|
325
|
+
Arguments:
|
|
326
|
+
request (BalancingUnitPriceSubmit): The query to submit to the MMS server.
|
|
327
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults
|
|
328
|
+
to the current date.
|
|
329
|
+
|
|
330
|
+
Returns: A list of balancing unit prices that match the query.
|
|
331
|
+
"""
|
|
332
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
333
|
+
return MarketQuery( # type: ignore[return-value]
|
|
334
|
+
date=date or Date.today(),
|
|
335
|
+
participant=self.participant,
|
|
336
|
+
user=self.user,
|
|
337
|
+
)
|
mms_client/services/omi.py
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
"""Contains the client layer for making OMI requests to the MMS server."""
|
|
2
2
|
|
|
3
3
|
from logging import getLogger
|
|
4
|
+
from typing import List
|
|
5
|
+
from typing import Optional
|
|
4
6
|
|
|
7
|
+
from pydantic_extra_types.pendulum_dt import Date
|
|
8
|
+
|
|
9
|
+
from mms_client.services.base import ClientProto
|
|
5
10
|
from mms_client.services.base import ServiceConfiguration
|
|
11
|
+
from mms_client.services.base import mms_endpoint
|
|
12
|
+
from mms_client.services.base import mms_multi_endpoint
|
|
13
|
+
from mms_client.types.omi import MarketQuery
|
|
14
|
+
from mms_client.types.omi import MarketSubmit
|
|
15
|
+
from mms_client.types.surplus_capcity import SurplusCapacityData
|
|
16
|
+
from mms_client.types.surplus_capcity import SurplusCapacityQuery
|
|
17
|
+
from mms_client.types.surplus_capcity import SurplusCapacitySubmit
|
|
18
|
+
from mms_client.types.transport import RequestType
|
|
6
19
|
from mms_client.utils.serialization import SchemaType
|
|
7
20
|
from mms_client.utils.serialization import Serializer
|
|
21
|
+
from mms_client.utils.web import ClientType
|
|
8
22
|
from mms_client.utils.web import Interface
|
|
9
23
|
|
|
10
24
|
# Set the default logger for the MMS client
|
|
@@ -16,3 +30,88 @@ class OMIClientMixin: # pylint: disable=unused-argument
|
|
|
16
30
|
|
|
17
31
|
# The configuration for the OMI service
|
|
18
32
|
config = ServiceConfiguration(Interface.OMI, Serializer(SchemaType.OMI, "MarketData"))
|
|
33
|
+
|
|
34
|
+
@mms_endpoint(
|
|
35
|
+
name="MarketSubmit_RemainingReserveData",
|
|
36
|
+
service=config,
|
|
37
|
+
request_type=RequestType.OMI,
|
|
38
|
+
response_data_type=SurplusCapacityData,
|
|
39
|
+
allowed_clients=[ClientType.BSP],
|
|
40
|
+
)
|
|
41
|
+
def put_surplus_capacity(
|
|
42
|
+
self: ClientProto, request: SurplusCapacitySubmit, date: Optional[Date] = None
|
|
43
|
+
) -> SurplusCapacityData:
|
|
44
|
+
"""Submit an offer to the MMS server.
|
|
45
|
+
|
|
46
|
+
This endpoint is only accessible to BSPs.
|
|
47
|
+
|
|
48
|
+
Arguments:
|
|
49
|
+
request (SurplusCapacitySubmit): The surplus capacity data to submit to the MMS server.
|
|
50
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults
|
|
51
|
+
to the current date.
|
|
52
|
+
|
|
53
|
+
Returns: The surplus capacity data that has been registered with the MMS server.
|
|
54
|
+
"""
|
|
55
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
56
|
+
return MarketSubmit( # type: ignore[return-value]
|
|
57
|
+
date=date or Date.today(),
|
|
58
|
+
participant=self.participant,
|
|
59
|
+
user=self.user,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@mms_multi_endpoint(
|
|
63
|
+
name="MarketSubmit_RemainingReserveData",
|
|
64
|
+
service=config,
|
|
65
|
+
request_type=RequestType.OMI,
|
|
66
|
+
response_data_type=SurplusCapacityData,
|
|
67
|
+
allowed_clients=[ClientType.BSP],
|
|
68
|
+
)
|
|
69
|
+
def put_surplus_capacities(
|
|
70
|
+
self: ClientProto, requests: List[SurplusCapacitySubmit], date: Optional[Date] = None
|
|
71
|
+
) -> List[SurplusCapacityData]:
|
|
72
|
+
"""Submit multiple surplus capacity data to the MMS server.
|
|
73
|
+
|
|
74
|
+
This endpoint is only accessible to BSPs.
|
|
75
|
+
|
|
76
|
+
Arguments:
|
|
77
|
+
requests (list[SurplusCapacitySubmit]): The surplus capacity data to submit to the MMS server.
|
|
78
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value
|
|
79
|
+
defaults to the current date.
|
|
80
|
+
|
|
81
|
+
Returns: A list of surplus capacity data that have been registered with the MMS server.
|
|
82
|
+
"""
|
|
83
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
84
|
+
return MarketSubmit( # type: ignore[return-value]
|
|
85
|
+
date=date or Date.today(),
|
|
86
|
+
participant=self.participant,
|
|
87
|
+
user=self.user,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@mms_multi_endpoint(
|
|
91
|
+
name="MarketQuery_RemainingReserveDataQuery",
|
|
92
|
+
service=config,
|
|
93
|
+
request_type=RequestType.OMI,
|
|
94
|
+
response_envelope_type=MarketSubmit,
|
|
95
|
+
response_data_type=SurplusCapacityData,
|
|
96
|
+
allowed_clients=[ClientType.BSP, ClientType.TSO],
|
|
97
|
+
)
|
|
98
|
+
def query_surplus_capacity(
|
|
99
|
+
self: ClientProto, request: SurplusCapacityQuery, date: Optional[Date] = None
|
|
100
|
+
) -> List[SurplusCapacityData]:
|
|
101
|
+
"""Query the MMS server for surplus capacity data.
|
|
102
|
+
|
|
103
|
+
This endpoint is only accessible to BSPs and TSOs.
|
|
104
|
+
|
|
105
|
+
Arguments:
|
|
106
|
+
request (SurplusCapacityQuery): The query to submit to the MMS server.
|
|
107
|
+
date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults to
|
|
108
|
+
the current date.
|
|
109
|
+
|
|
110
|
+
Returns: A list of surplus capacity data that match the query.
|
|
111
|
+
"""
|
|
112
|
+
# NOTE: The return type does not match the method definition but the decorator will return the correct type
|
|
113
|
+
return MarketQuery( # type: ignore[return-value]
|
|
114
|
+
date=date or Date.today(),
|
|
115
|
+
participant=self.participant,
|
|
116
|
+
user=self.user,
|
|
117
|
+
)
|
mms_client/types/award.py
CHANGED
|
@@ -192,6 +192,12 @@ class Award(Payload):
|
|
|
192
192
|
# The contract price, in JPY/kW/segment
|
|
193
193
|
contract_price: Decimal = price("ContractPrice", 10000.00)
|
|
194
194
|
|
|
195
|
+
# The unit price charged for the start up cost of the power, in JPY/kW/segment
|
|
196
|
+
start_up_unit_price: Decimal = price("StartUpUnitPrice", 10000.00, True)
|
|
197
|
+
|
|
198
|
+
# The unit price charged for the ramp down cost of the power, in JPY/kW/segment
|
|
199
|
+
ramp_down_unit_price: Decimal = price("RampDownUnitPrice", 10000.00, True)
|
|
200
|
+
|
|
195
201
|
# The performance evaluation coefficient, alpha
|
|
196
202
|
performance_evaluation_coefficient: Decimal = attr(name="PerfEvalCoeff", ge=0.00, le=100.0, decimal_places=2)
|
|
197
203
|
|
mms_client/types/bup.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""Contains objects for BUPs."""
|
|
2
|
+
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
from typing import List
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from pendulum import Timezone
|
|
10
|
+
from pydantic import field_serializer
|
|
11
|
+
from pydantic import field_validator
|
|
12
|
+
from pydantic_core import PydanticUndefined
|
|
13
|
+
from pydantic_extra_types.pendulum_dt import DateTime
|
|
14
|
+
from pydantic_xml import attr
|
|
15
|
+
from pydantic_xml import element
|
|
16
|
+
from pydantic_xml import wrapped
|
|
17
|
+
|
|
18
|
+
from mms_client.types.base import Payload
|
|
19
|
+
from mms_client.types.enums import AreaCode
|
|
20
|
+
from mms_client.types.fields import capacity
|
|
21
|
+
from mms_client.types.fields import company_short_name
|
|
22
|
+
from mms_client.types.fields import participant
|
|
23
|
+
from mms_client.types.fields import power_positive
|
|
24
|
+
from mms_client.types.fields import price
|
|
25
|
+
from mms_client.types.fields import resource_name
|
|
26
|
+
from mms_client.types.fields import resource_short_name
|
|
27
|
+
from mms_client.types.fields import system_code
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def abc_price(alias: str, optional: bool = False):
|
|
31
|
+
"""Create a field for an abc price.
|
|
32
|
+
|
|
33
|
+
Arguments:
|
|
34
|
+
alias (str): The name of the alias to assign to the Pydanitc field. This value will be used to map the field
|
|
35
|
+
to the JSON/XML key.
|
|
36
|
+
optional (bool): If True, the field will be optional with a default of None. If False, the field will be
|
|
37
|
+
required, with no default.
|
|
38
|
+
|
|
39
|
+
Returns: A Pydantic Field object for the abc price.
|
|
40
|
+
"""
|
|
41
|
+
return attr(
|
|
42
|
+
default=None if optional else PydanticUndefined, name=alias, gt=-100000.0, lt=100000.0, decimal_places=1
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Status(Enum):
|
|
47
|
+
"""Enum representing the possible statuses of a pattern."""
|
|
48
|
+
|
|
49
|
+
INACTIVE = "0"
|
|
50
|
+
ACTIVE = "1"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class StartupCostBand(Payload, tag="BandStartup"):
|
|
54
|
+
"""Represents a band of a startup cost."""
|
|
55
|
+
|
|
56
|
+
# The band number which must be unique within the startup cost and will identify this band in sequence.
|
|
57
|
+
number: int = attr(name="CaseNo", ge=1, le=10)
|
|
58
|
+
|
|
59
|
+
# The time at which the startup cost is applied. This value must be greater than or equal to 0.
|
|
60
|
+
stop_time_hours: int = attr(name="StopTime", ge=0, lt=1000)
|
|
61
|
+
|
|
62
|
+
# The V3 unit price charged for this band.
|
|
63
|
+
v3_unit_price: int = attr(name="V3", ge=0, lt=100000000)
|
|
64
|
+
|
|
65
|
+
# The remarks associated with this band.
|
|
66
|
+
remarks: Optional[str] = attr(default=None, name="Remark", min_length=1, max_length=30)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class AbcBand(Payload, tag="BandAbc"):
|
|
70
|
+
"""Represents a band of an ABC, whatever that is."""
|
|
71
|
+
|
|
72
|
+
# The band number which must be unique within the ABC and will identify this band in sequence.
|
|
73
|
+
number: int = attr(name="Band", ge=1, le=5)
|
|
74
|
+
|
|
75
|
+
# The capacity from which the band is allowed to operate.
|
|
76
|
+
from_capacity: int = power_positive("FromCap")
|
|
77
|
+
|
|
78
|
+
# The a term of the band.
|
|
79
|
+
a: Decimal = abc_price("a")
|
|
80
|
+
|
|
81
|
+
# The b term of the band.
|
|
82
|
+
b: Decimal = abc_price("b")
|
|
83
|
+
|
|
84
|
+
# The c term of the band.
|
|
85
|
+
c: Decimal = abc_price("c")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class BalancingUnitPriceBand(Payload):
|
|
89
|
+
"""Represents a band of a balancing unit price."""
|
|
90
|
+
|
|
91
|
+
# The band number which must be unique within the balancing unit price and will identify this band in sequence.
|
|
92
|
+
number: int = attr(name="Band", ge=1, le=20)
|
|
93
|
+
|
|
94
|
+
# The capacity from which the band is allowed to operate. If the resource_type on the associated resource is set to
|
|
95
|
+
# THERMAL or HYDRO then the value of this field must be greater than or equal to 0. Otherwise, the value of this
|
|
96
|
+
# field is unrestricted.
|
|
97
|
+
from_capacity: int = capacity("FromCap", -10000000)
|
|
98
|
+
|
|
99
|
+
# The V1 unit price charged for this band.
|
|
100
|
+
v1_unit_price: Decimal = price("V1", 10000.00)
|
|
101
|
+
|
|
102
|
+
# The V2 unit price charged for this band. This value is only valid when the contract_type on the associated
|
|
103
|
+
# resource is set to anything other than ONLY_POWER_SUPPLY_1.
|
|
104
|
+
v2_unit_price: Annotated[Decimal, price("V2", 10000.00, True)]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class BalancingUnitPrice(Payload):
|
|
108
|
+
"""Represents a balancing unit profile."""
|
|
109
|
+
|
|
110
|
+
# The V4 unit price charged for this pattern. This value is only valid when the contract_type on the associated
|
|
111
|
+
# resource is set to anything other than ONLY_POWER_SUPPLY_1.
|
|
112
|
+
v4_unit_price: Annotated[Decimal, price("V4", 10000.00, True)]
|
|
113
|
+
|
|
114
|
+
# The bands associated with this BUP.
|
|
115
|
+
bands: Annotated[List[BalancingUnitPriceBand], element(tag="BandBup", min_length=1, max_length=20)]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Pattern(Payload):
|
|
119
|
+
"""Represents a pattern associated with a BUP."""
|
|
120
|
+
|
|
121
|
+
# A number identifying this pattern in the overall sequence of patterns
|
|
122
|
+
number: int = attr(name="PatternNo", ge=1, le=10)
|
|
123
|
+
|
|
124
|
+
# The status of the pattern
|
|
125
|
+
status: Status = attr(name="PatternStatus")
|
|
126
|
+
|
|
127
|
+
# Any comments associated with the pattern
|
|
128
|
+
remarks: Optional[str] = attr(default=None, name="PatternRemark", min_length=1, max_length=50)
|
|
129
|
+
|
|
130
|
+
# The balancing unit profile associated with this pattern
|
|
131
|
+
balancing_unit_profile: Optional[BalancingUnitPrice] = element(default=None, tag="Bup")
|
|
132
|
+
|
|
133
|
+
# The quadratic pricing bands associated with this pattern
|
|
134
|
+
abc: Annotated[Optional[List[AbcBand]], wrapped(default=None, path="Abc", min_length=1, max_length=5)]
|
|
135
|
+
|
|
136
|
+
# The startup cost bands associated with this pattern
|
|
137
|
+
startup_costs: Annotated[
|
|
138
|
+
Optional[List[StartupCostBand]], wrapped(default=None, path="StartupCost", min_length=1, max_length=10)
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class BalancingUnitPriceSubmit(Payload, tag="BupSubmit"):
|
|
143
|
+
"""Represents the data included with a BUP."""
|
|
144
|
+
|
|
145
|
+
# The resource with which the BUP is associated
|
|
146
|
+
resource_code: str = resource_name("ResourceName")
|
|
147
|
+
|
|
148
|
+
# The start date and time for the validity period of the BUP
|
|
149
|
+
start: DateTime = attr(name="StartTime")
|
|
150
|
+
|
|
151
|
+
# The end date and time for the validity period of the BUP
|
|
152
|
+
end: DateTime = attr(name="EndTime")
|
|
153
|
+
|
|
154
|
+
# The patterns associated with this BUP
|
|
155
|
+
patterns: Annotated[List[Pattern], element(tag="PatternData", max_length=10)]
|
|
156
|
+
|
|
157
|
+
# The name of the BSP participant submitting the BUP. This will only be populated when the object is returned.
|
|
158
|
+
participant_name: Optional[str] = participant("BspParticipantName", True)
|
|
159
|
+
|
|
160
|
+
# The name of the company submitting the BUP. This will only be populated when the object is returned.
|
|
161
|
+
company: Optional[str] = company_short_name("CompanyShortName", True)
|
|
162
|
+
|
|
163
|
+
# The area associated with the BUP. This will only be populated when the object is returned.
|
|
164
|
+
area: Optional[AreaCode] = attr(default=None, name="Area")
|
|
165
|
+
|
|
166
|
+
# The name of the resource being traded. This will only be populated when the object is returned.
|
|
167
|
+
resource_name: Optional[str] = resource_short_name("ResourceShortName", True)
|
|
168
|
+
|
|
169
|
+
# The MMS code of the business entity to which the registration applies. This will only be populated when the
|
|
170
|
+
# object is returned.
|
|
171
|
+
system_code: Optional[str] = system_code("SystemCode", True)
|
|
172
|
+
|
|
173
|
+
@field_serializer("start", "end")
|
|
174
|
+
def encode_datetime(self, value: DateTime) -> str:
|
|
175
|
+
"""Encode the datetime to an MMS-compliant ISO 8601 string."""
|
|
176
|
+
return value.replace(tzinfo=None).isoformat() if value else ""
|
|
177
|
+
|
|
178
|
+
@field_validator("start", "end")
|
|
179
|
+
def decode_datetime(cls, value: DateTime) -> DateTime: # pylint: disable=no-self-argument
|
|
180
|
+
"""Decode the datetime from an MMS-compliant ISO 8601 string."""
|
|
181
|
+
return value.replace(tzinfo=Timezone("Asia/Tokyo"))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class BalancingUnitPriceQuery(Payload, tag="BupQuery"):
|
|
185
|
+
"""Represents the data included with a BUP query."""
|
|
186
|
+
|
|
187
|
+
# Whether or not the BUP is the default
|
|
188
|
+
is_default: Optional[bool] = attr(default=None, name="StandingFlag")
|
|
189
|
+
|
|
190
|
+
# The resource with which the BUP is associated
|
|
191
|
+
resource_code: str = resource_name("ResourceName")
|
|
192
|
+
|
|
193
|
+
# The start date and time for the validity period of the BUP
|
|
194
|
+
start: Annotated[DateTime, attr(default=None, name="StartTime")]
|
|
195
|
+
|
|
196
|
+
# The end date and time for the validity period of the BUP
|
|
197
|
+
end: Annotated[DateTime, attr(default=None, name="EndTime")]
|
|
198
|
+
|
|
199
|
+
@field_serializer("start", "end")
|
|
200
|
+
def encode_datetime(self, value: DateTime) -> str:
|
|
201
|
+
"""Encode the datetime to an MMS-compliant ISO 8601 string."""
|
|
202
|
+
return value.replace(tzinfo=None).isoformat() if value else ""
|
|
203
|
+
|
|
204
|
+
@field_validator("start", "end")
|
|
205
|
+
def decode_datetime(cls, value: DateTime) -> DateTime: # pylint: disable=no-self-argument
|
|
206
|
+
"""Decode the datetime from an MMS-compliant ISO 8601 string."""
|
|
207
|
+
return value.replace(tzinfo=Timezone("Asia/Tokyo"))
|
mms_client/types/market.py
CHANGED
|
@@ -4,7 +4,9 @@ from enum import Enum
|
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
6
|
from pydantic_extra_types.pendulum_dt import Date
|
|
7
|
+
from pydantic_xml import BaseXmlModel
|
|
7
8
|
from pydantic_xml import attr
|
|
9
|
+
from pydantic_xml import element
|
|
8
10
|
|
|
9
11
|
from mms_client.types.base import Envelope
|
|
10
12
|
from mms_client.types.fields import participant
|
|
@@ -32,12 +34,19 @@ class BaseMarketRequest(Envelope):
|
|
|
32
34
|
user: str = attr(name="UserName", min_length=1, max_length=12, pattern=r"^[A-Z0-9]*$")
|
|
33
35
|
|
|
34
36
|
|
|
37
|
+
class Defaults(BaseXmlModel):
|
|
38
|
+
"""Represents the default settings to apply when submitting a market request."""
|
|
39
|
+
|
|
40
|
+
# Whether or not the submission represents the default
|
|
41
|
+
is_default: bool = attr(name="StandingFlag")
|
|
42
|
+
|
|
43
|
+
|
|
35
44
|
class MarketQuery(BaseMarketRequest):
|
|
36
45
|
"""Represents the base fields for a market query."""
|
|
37
46
|
|
|
38
47
|
# If the market type is specified as "DAM" (day-ahead market), the number of days should be specified as "1".
|
|
39
48
|
# Otherwise, this field indicates the number of days ahead for which the data is being queried.
|
|
40
|
-
days: int = attr(default=
|
|
49
|
+
days: Optional[int] = attr(default=None, name="NumOfDays", ge=1, le=7)
|
|
41
50
|
|
|
42
51
|
|
|
43
52
|
class MarketSubmit(BaseMarketRequest):
|
|
@@ -48,7 +57,11 @@ class MarketSubmit(BaseMarketRequest):
|
|
|
48
57
|
|
|
49
58
|
# If the market type is specified as "DAM" (day-ahead market), the number of days should be specified as "1".
|
|
50
59
|
# Otherwise, this field indicates the number of days ahead for which the data is being submitted.
|
|
51
|
-
days: int = attr(default=
|
|
60
|
+
days: Optional[int] = attr(default=None, name="NumOfDays", ge=1, le=31)
|
|
61
|
+
|
|
62
|
+
# Default values to include with the submission. The request will be rejected if this is included in a request
|
|
63
|
+
# where it is not allowed.
|
|
64
|
+
defaults: Optional[Defaults] = element(default=None, tag="StandingData")
|
|
52
65
|
|
|
53
66
|
|
|
54
67
|
class MarketCancel(BaseMarketRequest):
|
mms_client/types/offer.py
CHANGED
|
@@ -72,6 +72,12 @@ class OfferStack(Payload):
|
|
|
72
72
|
# The unit price of the power, in JPY/kW/segment
|
|
73
73
|
unit_price: Decimal = price("OfferUnitPrice", 10000.00)
|
|
74
74
|
|
|
75
|
+
# The unit price charged for the start up cost of the power, in JPY/kW/segment
|
|
76
|
+
start_up_unit_price: Annotated[Decimal, price("StartUpUnitPrice", 10000.00, True)]
|
|
77
|
+
|
|
78
|
+
# The unit price charged for the ramp down cost of the power, in JPY/kW/segment
|
|
79
|
+
ramp_down_unit_price: Annotated[Decimal, price("RampDownUnitPrice", 10000.00, True)]
|
|
80
|
+
|
|
75
81
|
# The ID of the offer to which this stack belongs
|
|
76
82
|
id: Optional[str] = offer_id("OfferId", True)
|
|
77
83
|
|
mms_client/types/omi.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Contains objects for OMI information."""
|
|
2
|
+
|
|
3
|
+
from pydantic_extra_types.pendulum_dt import Date
|
|
4
|
+
from pydantic_xml import attr
|
|
5
|
+
|
|
6
|
+
from mms_client.types.base import Envelope
|
|
7
|
+
from mms_client.types.fields import participant
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MarketSubmit(Envelope):
|
|
11
|
+
"""Represents the base fields for a market registration request."""
|
|
12
|
+
|
|
13
|
+
# Date of the transaction in the format "YYYY-MM-DD"
|
|
14
|
+
date: Date = attr(name="Date")
|
|
15
|
+
|
|
16
|
+
# MMS code of the business entity to which the requesting user belongs, and will be used to track the user who made
|
|
17
|
+
# the request. This value will be checked against the certificate used to make the request.
|
|
18
|
+
participant: str = participant("ParticipantName")
|
|
19
|
+
|
|
20
|
+
# The user name of the person making the request. This value is used to track the user who made the request, and
|
|
21
|
+
# will be checked against the certificate used to make the request.
|
|
22
|
+
user: str = attr(name="UserName", min_length=1, max_length=12, pattern=r"^[A-Z0-9]*$")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MarketQuery(MarketSubmit):
|
|
26
|
+
"""Represents the base fields for a market query."""
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Contains objects for MMS settlement."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
from typing import List
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from pendulum import Timezone
|
|
8
|
+
from pydantic import field_serializer
|
|
9
|
+
from pydantic import field_validator
|
|
10
|
+
from pydantic_core import PydanticUndefined
|
|
11
|
+
from pydantic_extra_types.pendulum_dt import Date
|
|
12
|
+
from pydantic_extra_types.pendulum_dt import DateTime
|
|
13
|
+
from pydantic_xml import attr
|
|
14
|
+
from pydantic_xml import element
|
|
15
|
+
|
|
16
|
+
from mms_client.types.base import Payload
|
|
17
|
+
from mms_client.types.fields import company_short_name
|
|
18
|
+
from mms_client.types.fields import participant
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def file_name(alias: str, optional: bool = False):
|
|
22
|
+
"""Create a field for a file name.
|
|
23
|
+
|
|
24
|
+
Arguments:
|
|
25
|
+
alias (str): The name of the alias to assign to the Pydanitc field. This value will be used to map the field
|
|
26
|
+
to the JSON/XML key.
|
|
27
|
+
optional (bool): If True, the field will be optional with a default of None. If False, the field will be
|
|
28
|
+
required, with no default.
|
|
29
|
+
|
|
30
|
+
Returns: A Pydantic Field object for the file name.
|
|
31
|
+
"""
|
|
32
|
+
return attr(
|
|
33
|
+
default=None if optional else PydanticUndefined,
|
|
34
|
+
name=alias,
|
|
35
|
+
min_length=18,
|
|
36
|
+
max_length=60,
|
|
37
|
+
pattern=r"^([A-Z0-9]{4}_){2}[A-Z0-9_-]{4,46}\.(pdf|zip|csv|xml)$",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SettlementFile(Payload):
|
|
42
|
+
"""Represents a settlement file."""
|
|
43
|
+
|
|
44
|
+
# The name of the settlement file as it is recorded in the system
|
|
45
|
+
name: str = file_name("Name")
|
|
46
|
+
|
|
47
|
+
# The name of the participant (only valid if operating as a TSO)
|
|
48
|
+
participant: Optional[str] = participant("ParticipantName", True)
|
|
49
|
+
|
|
50
|
+
# The name of the company associated with the file (only valid if operating as a TSO)
|
|
51
|
+
company: Optional[str] = company_short_name("CompanyShortName", True)
|
|
52
|
+
|
|
53
|
+
# When the file was submitted (not sure why this can be None but it's in the spec)
|
|
54
|
+
submission_time: Optional[DateTime] = attr(name="SubmissionTime", default=None)
|
|
55
|
+
|
|
56
|
+
# The date when settlement occurred (not included if settlement is in the future)
|
|
57
|
+
settlement_date: Optional[Date] = attr(name="SttlDate", default=None)
|
|
58
|
+
|
|
59
|
+
# The size of the file in bytes, if it has been uploaded
|
|
60
|
+
size: Optional[int] = attr(name="FileSize", default=None, ge=0, lt=1000000000)
|
|
61
|
+
|
|
62
|
+
@field_serializer("submission_time")
|
|
63
|
+
def encode_datetime(self, value: DateTime) -> str:
|
|
64
|
+
"""Encode the datetime to an MMS-compliant ISO 8601 string."""
|
|
65
|
+
return value.replace(tzinfo=None).isoformat() if value else ""
|
|
66
|
+
|
|
67
|
+
@field_validator("submission_time")
|
|
68
|
+
def decode_datetime(cls, value: DateTime) -> DateTime: # pylint: disable=no-self-argument
|
|
69
|
+
"""Decode the datetime from an MMS-compliant ISO 8601 string."""
|
|
70
|
+
return value.replace(tzinfo=Timezone("Asia/Tokyo"))
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SettlementResults(Payload):
|
|
74
|
+
"""Contains a list of settlement files that can be requested separately later."""
|
|
75
|
+
|
|
76
|
+
# The file results that were retrieved by the query
|
|
77
|
+
files: Annotated[List[SettlementFile], element(tag="File", min_length=1)]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class SettlementQuery(Payload, tag="SettlementResultsFileListQuery"):
|
|
81
|
+
"""Represents a request to query settlement results file list."""
|