balancing-services 2.1.0__tar.gz → 2.2.0__tar.gz
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.
- {balancing_services-2.1.0 → balancing_services-2.2.0}/PKG-INFO +2 -2
- balancing_services-2.2.0/balancing_services/api/default/get_imbalance_price_history.py +307 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/__init__.py +6 -0
- balancing_services-2.2.0/balancing_services/models/imbalance_price_history.py +112 -0
- balancing_services-2.2.0/balancing_services/models/imbalance_price_history_response.py +128 -0
- balancing_services-2.2.0/balancing_services/models/imbalance_price_revision.py +84 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/pyproject.toml +1 -1
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/test_basic.py +23 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/test_integration.py +164 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/.env.sample +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/.gitignore +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/LICENSE +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/PUBLISHING.md +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/README.md +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/RELEASE_CHECKLIST.md +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/__init__.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/__init__.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/__init__.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_capacity_bids.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_capacity_demand.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_capacity_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_capacity_procured_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_energy_activated_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_energy_bids.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_energy_demand.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_energy_offered_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_energy_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_balancing_energy_satisfied_demand.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_cross_border_available_capacity.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_cross_border_energy_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_cross_border_marginal_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_cross_zonal_capacity_allocation.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_current_imbalance_total_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_day_ahead_energy_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_imbalance_price_forecasts.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_imbalance_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/api/default/get_imbalance_total_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/client.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/errors.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/activation_type.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/area.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_bid_period.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_bids.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_bids_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_demand.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_demands.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_demands_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_price.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_prices_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_volume.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_capacity_volumes_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_bid_period.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_bids.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_bids_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_price.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_prices_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_volume.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/balancing_energy_volumes_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/bid_status.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/capacity_bid.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_available_capacity.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_available_capacity_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_available_capacity_value.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_energy_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_energy_volumes_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_marginal_price.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_marginal_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_border_marginal_prices_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_zonal_capacity_allocation_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/cross_zonal_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/currency.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/day_ahead_energy_price.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/day_ahead_energy_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/day_ahead_energy_prices_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/demand_basis.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/direction.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/eic_code.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/energy_bid.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_direction.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_price.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_price_forecast.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_price_forecast_quantile.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_price_forecasts.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_price_forecasts_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_prices.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_prices_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_total_volumes.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/imbalance_total_volumes_response.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/period.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/problem.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/procurement.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/reserve_type.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/total_imbalance_direction.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/models/total_imbalance_volume.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/balancing_services/types.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/check.sh +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/config.yaml +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/examples/basic_usage.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/examples/error_handling.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/examples/pagination_example.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/fix_enum_validator_casts.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/generate-pyproject.sh +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/generate.sh +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/pyproject.toml.draft +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/test-and-publish.sh +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/conftest.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/test_async.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/test_datetime_compat.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/test_procured_at_none_handling.py +0 -0
- {balancing_services-2.1.0 → balancing_services-2.2.0}/tests/test_readme_execution.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: balancing-services
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Official Python client for accessing European electricity balancing market data via the Balancing Services REST API
|
|
5
5
|
Project-URL: Homepage, https://balancing.services
|
|
6
6
|
Project-URL: Documentation, https://api.balancing.services/v2/documentation
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from http import HTTPStatus
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from ... import errors
|
|
8
|
+
from ...client import AuthenticatedClient, Client
|
|
9
|
+
from ...models.area import Area
|
|
10
|
+
from ...models.imbalance_price_history_response import ImbalancePriceHistoryResponse
|
|
11
|
+
from ...models.problem import Problem
|
|
12
|
+
from ...types import UNSET, Response, Unset
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_kwargs(
|
|
16
|
+
*,
|
|
17
|
+
area: Area,
|
|
18
|
+
period_start_at: datetime.datetime,
|
|
19
|
+
period_end_at: datetime.datetime,
|
|
20
|
+
cursor: str | Unset = UNSET,
|
|
21
|
+
limit: int | Unset = 100,
|
|
22
|
+
updated_since: datetime.datetime | Unset = UNSET,
|
|
23
|
+
) -> dict[str, Any]:
|
|
24
|
+
|
|
25
|
+
params: dict[str, Any] = {}
|
|
26
|
+
|
|
27
|
+
json_area: str = area
|
|
28
|
+
params["area"] = json_area
|
|
29
|
+
|
|
30
|
+
json_period_start_at = period_start_at.isoformat()
|
|
31
|
+
params["period-start-at"] = json_period_start_at
|
|
32
|
+
|
|
33
|
+
json_period_end_at = period_end_at.isoformat()
|
|
34
|
+
params["period-end-at"] = json_period_end_at
|
|
35
|
+
|
|
36
|
+
params["cursor"] = cursor
|
|
37
|
+
|
|
38
|
+
params["limit"] = limit
|
|
39
|
+
|
|
40
|
+
json_updated_since: str | Unset = UNSET
|
|
41
|
+
if not isinstance(updated_since, Unset):
|
|
42
|
+
json_updated_since = updated_since.isoformat()
|
|
43
|
+
params["updated-since"] = json_updated_since
|
|
44
|
+
|
|
45
|
+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
|
46
|
+
|
|
47
|
+
_kwargs: dict[str, Any] = {
|
|
48
|
+
"method": "get",
|
|
49
|
+
"url": "/imbalance/prices/history",
|
|
50
|
+
"params": params,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return _kwargs
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _parse_response(
|
|
57
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
58
|
+
) -> ImbalancePriceHistoryResponse | Problem | None:
|
|
59
|
+
if response.status_code == 200:
|
|
60
|
+
response_200 = ImbalancePriceHistoryResponse.from_dict(response.json())
|
|
61
|
+
|
|
62
|
+
return response_200
|
|
63
|
+
|
|
64
|
+
if response.status_code == 400:
|
|
65
|
+
response_400 = Problem.from_dict(response.json())
|
|
66
|
+
|
|
67
|
+
return response_400
|
|
68
|
+
|
|
69
|
+
if response.status_code == 401:
|
|
70
|
+
response_401 = Problem.from_dict(response.json())
|
|
71
|
+
|
|
72
|
+
return response_401
|
|
73
|
+
|
|
74
|
+
if response.status_code == 403:
|
|
75
|
+
response_403 = Problem.from_dict(response.json())
|
|
76
|
+
|
|
77
|
+
return response_403
|
|
78
|
+
|
|
79
|
+
if response.status_code == 404:
|
|
80
|
+
response_404 = Problem.from_dict(response.json())
|
|
81
|
+
|
|
82
|
+
return response_404
|
|
83
|
+
|
|
84
|
+
if response.status_code == 429:
|
|
85
|
+
response_429 = Problem.from_dict(response.json())
|
|
86
|
+
|
|
87
|
+
return response_429
|
|
88
|
+
|
|
89
|
+
if response.status_code == 500:
|
|
90
|
+
response_500 = Problem.from_dict(response.json())
|
|
91
|
+
|
|
92
|
+
return response_500
|
|
93
|
+
|
|
94
|
+
if response.status_code == 501:
|
|
95
|
+
response_501 = Problem.from_dict(response.json())
|
|
96
|
+
|
|
97
|
+
return response_501
|
|
98
|
+
|
|
99
|
+
if client.raise_on_unexpected_status:
|
|
100
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
101
|
+
else:
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _build_response(
|
|
106
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
107
|
+
) -> Response[ImbalancePriceHistoryResponse | Problem]:
|
|
108
|
+
return Response(
|
|
109
|
+
status_code=HTTPStatus(response.status_code),
|
|
110
|
+
content=response.content,
|
|
111
|
+
headers=response.headers,
|
|
112
|
+
parsed=_parse_response(client=client, response=response),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def sync_detailed(
|
|
117
|
+
*,
|
|
118
|
+
client: AuthenticatedClient | Client,
|
|
119
|
+
area: Area,
|
|
120
|
+
period_start_at: datetime.datetime,
|
|
121
|
+
period_end_at: datetime.datetime,
|
|
122
|
+
cursor: str | Unset = UNSET,
|
|
123
|
+
limit: int | Unset = 100,
|
|
124
|
+
updated_since: datetime.datetime | Unset = UNSET,
|
|
125
|
+
) -> Response[ImbalancePriceHistoryResponse | Problem]:
|
|
126
|
+
"""Get the revision history of the imbalance prices for an area
|
|
127
|
+
|
|
128
|
+
**Experimental** - This endpoint is under active development and may change without notice.
|
|
129
|
+
|
|
130
|
+
Returns how the imbalance prices on `/imbalance/prices` reached their current values: the
|
|
131
|
+
sequence of values held for a period, each stamped with the `observedAt` it was recorded at.
|
|
132
|
+
The response is the `/imbalance/prices` shape with `observedAt` added to each entry of
|
|
133
|
+
`prices`, which carries the revision entries, ascending by `observedAt`.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
area (Area): Area code
|
|
137
|
+
period_start_at (datetime.datetime): Example: 2025-01-01T00:00:00Z.
|
|
138
|
+
period_end_at (datetime.datetime): Example: 2025-01-02T00:00:00Z.
|
|
139
|
+
cursor (str | Unset): Example: v1:AAAAAYwBAgMEBQYHCAkKCw==.
|
|
140
|
+
limit (int | Unset): Default: 100. Example: 100.
|
|
141
|
+
updated_since (datetime.datetime | Unset): Example: 2025-01-02T09:15:00Z.
|
|
142
|
+
|
|
143
|
+
Raises:
|
|
144
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
145
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Response[ImbalancePriceHistoryResponse | Problem]
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
kwargs = _get_kwargs(
|
|
152
|
+
area=area,
|
|
153
|
+
period_start_at=period_start_at,
|
|
154
|
+
period_end_at=period_end_at,
|
|
155
|
+
cursor=cursor,
|
|
156
|
+
limit=limit,
|
|
157
|
+
updated_since=updated_since,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
response = client.get_httpx_client().request(
|
|
161
|
+
**kwargs,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return _build_response(client=client, response=response)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def sync(
|
|
168
|
+
*,
|
|
169
|
+
client: AuthenticatedClient | Client,
|
|
170
|
+
area: Area,
|
|
171
|
+
period_start_at: datetime.datetime,
|
|
172
|
+
period_end_at: datetime.datetime,
|
|
173
|
+
cursor: str | Unset = UNSET,
|
|
174
|
+
limit: int | Unset = 100,
|
|
175
|
+
updated_since: datetime.datetime | Unset = UNSET,
|
|
176
|
+
) -> ImbalancePriceHistoryResponse | Problem | None:
|
|
177
|
+
"""Get the revision history of the imbalance prices for an area
|
|
178
|
+
|
|
179
|
+
**Experimental** - This endpoint is under active development and may change without notice.
|
|
180
|
+
|
|
181
|
+
Returns how the imbalance prices on `/imbalance/prices` reached their current values: the
|
|
182
|
+
sequence of values held for a period, each stamped with the `observedAt` it was recorded at.
|
|
183
|
+
The response is the `/imbalance/prices` shape with `observedAt` added to each entry of
|
|
184
|
+
`prices`, which carries the revision entries, ascending by `observedAt`.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
area (Area): Area code
|
|
188
|
+
period_start_at (datetime.datetime): Example: 2025-01-01T00:00:00Z.
|
|
189
|
+
period_end_at (datetime.datetime): Example: 2025-01-02T00:00:00Z.
|
|
190
|
+
cursor (str | Unset): Example: v1:AAAAAYwBAgMEBQYHCAkKCw==.
|
|
191
|
+
limit (int | Unset): Default: 100. Example: 100.
|
|
192
|
+
updated_since (datetime.datetime | Unset): Example: 2025-01-02T09:15:00Z.
|
|
193
|
+
|
|
194
|
+
Raises:
|
|
195
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
196
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
ImbalancePriceHistoryResponse | Problem
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
return sync_detailed(
|
|
203
|
+
client=client,
|
|
204
|
+
area=area,
|
|
205
|
+
period_start_at=period_start_at,
|
|
206
|
+
period_end_at=period_end_at,
|
|
207
|
+
cursor=cursor,
|
|
208
|
+
limit=limit,
|
|
209
|
+
updated_since=updated_since,
|
|
210
|
+
).parsed
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
async def asyncio_detailed(
|
|
214
|
+
*,
|
|
215
|
+
client: AuthenticatedClient | Client,
|
|
216
|
+
area: Area,
|
|
217
|
+
period_start_at: datetime.datetime,
|
|
218
|
+
period_end_at: datetime.datetime,
|
|
219
|
+
cursor: str | Unset = UNSET,
|
|
220
|
+
limit: int | Unset = 100,
|
|
221
|
+
updated_since: datetime.datetime | Unset = UNSET,
|
|
222
|
+
) -> Response[ImbalancePriceHistoryResponse | Problem]:
|
|
223
|
+
"""Get the revision history of the imbalance prices for an area
|
|
224
|
+
|
|
225
|
+
**Experimental** - This endpoint is under active development and may change without notice.
|
|
226
|
+
|
|
227
|
+
Returns how the imbalance prices on `/imbalance/prices` reached their current values: the
|
|
228
|
+
sequence of values held for a period, each stamped with the `observedAt` it was recorded at.
|
|
229
|
+
The response is the `/imbalance/prices` shape with `observedAt` added to each entry of
|
|
230
|
+
`prices`, which carries the revision entries, ascending by `observedAt`.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
area (Area): Area code
|
|
234
|
+
period_start_at (datetime.datetime): Example: 2025-01-01T00:00:00Z.
|
|
235
|
+
period_end_at (datetime.datetime): Example: 2025-01-02T00:00:00Z.
|
|
236
|
+
cursor (str | Unset): Example: v1:AAAAAYwBAgMEBQYHCAkKCw==.
|
|
237
|
+
limit (int | Unset): Default: 100. Example: 100.
|
|
238
|
+
updated_since (datetime.datetime | Unset): Example: 2025-01-02T09:15:00Z.
|
|
239
|
+
|
|
240
|
+
Raises:
|
|
241
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
242
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
Response[ImbalancePriceHistoryResponse | Problem]
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
kwargs = _get_kwargs(
|
|
249
|
+
area=area,
|
|
250
|
+
period_start_at=period_start_at,
|
|
251
|
+
period_end_at=period_end_at,
|
|
252
|
+
cursor=cursor,
|
|
253
|
+
limit=limit,
|
|
254
|
+
updated_since=updated_since,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
258
|
+
|
|
259
|
+
return _build_response(client=client, response=response)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
async def asyncio(
|
|
263
|
+
*,
|
|
264
|
+
client: AuthenticatedClient | Client,
|
|
265
|
+
area: Area,
|
|
266
|
+
period_start_at: datetime.datetime,
|
|
267
|
+
period_end_at: datetime.datetime,
|
|
268
|
+
cursor: str | Unset = UNSET,
|
|
269
|
+
limit: int | Unset = 100,
|
|
270
|
+
updated_since: datetime.datetime | Unset = UNSET,
|
|
271
|
+
) -> ImbalancePriceHistoryResponse | Problem | None:
|
|
272
|
+
"""Get the revision history of the imbalance prices for an area
|
|
273
|
+
|
|
274
|
+
**Experimental** - This endpoint is under active development and may change without notice.
|
|
275
|
+
|
|
276
|
+
Returns how the imbalance prices on `/imbalance/prices` reached their current values: the
|
|
277
|
+
sequence of values held for a period, each stamped with the `observedAt` it was recorded at.
|
|
278
|
+
The response is the `/imbalance/prices` shape with `observedAt` added to each entry of
|
|
279
|
+
`prices`, which carries the revision entries, ascending by `observedAt`.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
area (Area): Area code
|
|
283
|
+
period_start_at (datetime.datetime): Example: 2025-01-01T00:00:00Z.
|
|
284
|
+
period_end_at (datetime.datetime): Example: 2025-01-02T00:00:00Z.
|
|
285
|
+
cursor (str | Unset): Example: v1:AAAAAYwBAgMEBQYHCAkKCw==.
|
|
286
|
+
limit (int | Unset): Default: 100. Example: 100.
|
|
287
|
+
updated_since (datetime.datetime | Unset): Example: 2025-01-02T09:15:00Z.
|
|
288
|
+
|
|
289
|
+
Raises:
|
|
290
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
291
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
ImbalancePriceHistoryResponse | Problem
|
|
295
|
+
"""
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
await asyncio_detailed(
|
|
299
|
+
client=client,
|
|
300
|
+
area=area,
|
|
301
|
+
period_start_at=period_start_at,
|
|
302
|
+
period_end_at=period_end_at,
|
|
303
|
+
cursor=cursor,
|
|
304
|
+
limit=limit,
|
|
305
|
+
updated_since=updated_since,
|
|
306
|
+
)
|
|
307
|
+
).parsed
|
|
@@ -53,6 +53,9 @@ from .imbalance_price_forecast import ImbalancePriceForecast
|
|
|
53
53
|
from .imbalance_price_forecast_quantile import ImbalancePriceForecastQuantile
|
|
54
54
|
from .imbalance_price_forecasts import ImbalancePriceForecasts
|
|
55
55
|
from .imbalance_price_forecasts_response import ImbalancePriceForecastsResponse
|
|
56
|
+
from .imbalance_price_history import ImbalancePriceHistory
|
|
57
|
+
from .imbalance_price_history_response import ImbalancePriceHistoryResponse
|
|
58
|
+
from .imbalance_price_revision import ImbalancePriceRevision
|
|
56
59
|
from .imbalance_prices import ImbalancePrices
|
|
57
60
|
from .imbalance_prices_response import ImbalancePricesResponse
|
|
58
61
|
from .imbalance_total_volumes import ImbalanceTotalVolumes
|
|
@@ -114,6 +117,9 @@ __all__ = (
|
|
|
114
117
|
"ImbalancePriceForecastQuantile",
|
|
115
118
|
"ImbalancePriceForecasts",
|
|
116
119
|
"ImbalancePriceForecastsResponse",
|
|
120
|
+
"ImbalancePriceHistory",
|
|
121
|
+
"ImbalancePriceHistoryResponse",
|
|
122
|
+
"ImbalancePriceRevision",
|
|
117
123
|
"ImbalancePrices",
|
|
118
124
|
"ImbalancePricesResponse",
|
|
119
125
|
"ImbalanceTotalVolumes",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
5
|
+
|
|
6
|
+
from attrs import define as _attrs_define
|
|
7
|
+
from attrs import field as _attrs_field
|
|
8
|
+
|
|
9
|
+
from ..models.area import Area, check_area
|
|
10
|
+
from ..models.currency import Currency, check_currency
|
|
11
|
+
from ..models.eic_code import EicCode, check_eic_code
|
|
12
|
+
from ..models.imbalance_direction import ImbalanceDirection, check_imbalance_direction
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from ..models.imbalance_price_revision import ImbalancePriceRevision
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
T = TypeVar("T", bound="ImbalancePriceHistory")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@_attrs_define
|
|
22
|
+
class ImbalancePriceHistory:
|
|
23
|
+
"""
|
|
24
|
+
Attributes:
|
|
25
|
+
area (Area): Area code
|
|
26
|
+
eic_code (EicCode): Energy Identification Code (EIC)
|
|
27
|
+
currency (Currency): Currency code
|
|
28
|
+
direction (ImbalanceDirection): Imbalance direction
|
|
29
|
+
prices (list[ImbalancePriceRevision]):
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
area: Area
|
|
33
|
+
eic_code: EicCode
|
|
34
|
+
currency: Currency
|
|
35
|
+
direction: ImbalanceDirection
|
|
36
|
+
prices: list[ImbalancePriceRevision]
|
|
37
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
38
|
+
|
|
39
|
+
def to_dict(self) -> dict[str, Any]:
|
|
40
|
+
area: str = self.area
|
|
41
|
+
|
|
42
|
+
eic_code: str = self.eic_code
|
|
43
|
+
|
|
44
|
+
currency: str = self.currency
|
|
45
|
+
|
|
46
|
+
direction: str = self.direction
|
|
47
|
+
|
|
48
|
+
prices = []
|
|
49
|
+
for prices_item_data in self.prices:
|
|
50
|
+
prices_item = prices_item_data.to_dict()
|
|
51
|
+
prices.append(prices_item)
|
|
52
|
+
|
|
53
|
+
field_dict: dict[str, Any] = {}
|
|
54
|
+
field_dict.update(self.additional_properties)
|
|
55
|
+
field_dict.update(
|
|
56
|
+
{
|
|
57
|
+
"area": area,
|
|
58
|
+
"eicCode": eic_code,
|
|
59
|
+
"currency": currency,
|
|
60
|
+
"direction": direction,
|
|
61
|
+
"prices": prices,
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return field_dict
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
|
69
|
+
from ..models.imbalance_price_revision import ImbalancePriceRevision
|
|
70
|
+
|
|
71
|
+
d = dict(src_dict)
|
|
72
|
+
area = check_area(d.pop("area"))
|
|
73
|
+
|
|
74
|
+
eic_code = check_eic_code(d.pop("eicCode"))
|
|
75
|
+
|
|
76
|
+
currency = check_currency(d.pop("currency"))
|
|
77
|
+
|
|
78
|
+
direction = check_imbalance_direction(d.pop("direction"))
|
|
79
|
+
|
|
80
|
+
prices = []
|
|
81
|
+
_prices = d.pop("prices")
|
|
82
|
+
for prices_item_data in _prices:
|
|
83
|
+
prices_item = ImbalancePriceRevision.from_dict(prices_item_data)
|
|
84
|
+
|
|
85
|
+
prices.append(prices_item)
|
|
86
|
+
|
|
87
|
+
imbalance_price_history = cls(
|
|
88
|
+
area=area,
|
|
89
|
+
eic_code=eic_code,
|
|
90
|
+
currency=currency,
|
|
91
|
+
direction=direction,
|
|
92
|
+
prices=prices,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
imbalance_price_history.additional_properties = d
|
|
96
|
+
return imbalance_price_history
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def additional_keys(self) -> list[str]:
|
|
100
|
+
return list(self.additional_properties.keys())
|
|
101
|
+
|
|
102
|
+
def __getitem__(self, key: str) -> Any:
|
|
103
|
+
return self.additional_properties[key]
|
|
104
|
+
|
|
105
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
106
|
+
self.additional_properties[key] = value
|
|
107
|
+
|
|
108
|
+
def __delitem__(self, key: str) -> None:
|
|
109
|
+
del self.additional_properties[key]
|
|
110
|
+
|
|
111
|
+
def __contains__(self, key: str) -> bool:
|
|
112
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
from typing import TYPE_CHECKING, Any, TypeVar, cast
|
|
6
|
+
|
|
7
|
+
from attrs import define as _attrs_define
|
|
8
|
+
from attrs import field as _attrs_field
|
|
9
|
+
|
|
10
|
+
from ..types import UNSET, Unset
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..models.imbalance_price_history import ImbalancePriceHistory
|
|
14
|
+
from ..models.period import Period
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
T = TypeVar("T", bound="ImbalancePriceHistoryResponse")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@_attrs_define
|
|
21
|
+
class ImbalancePriceHistoryResponse:
|
|
22
|
+
"""
|
|
23
|
+
Attributes:
|
|
24
|
+
queried_period (Period):
|
|
25
|
+
data (list[ImbalancePriceHistory]):
|
|
26
|
+
has_more (bool): Indicates whether there are more results available
|
|
27
|
+
next_updated_since (datetime.datetime): The watermark to pass as `updated-since` on the next poll. Every page of
|
|
28
|
+
one drain reports the same value. It deliberately lags real time to cover writes that were still committing, so
|
|
29
|
+
consecutive polls overlap slightly and a record may be delivered more than once — upsert on consume. Example:
|
|
30
|
+
2025-01-02T09:15:00Z.
|
|
31
|
+
next_cursor (None | str | Unset): Cursor to fetch the next page of results. Null if no more results. Example:
|
|
32
|
+
v1:AAAAAYwBAgMEBQYHCAkKCw==.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
queried_period: Period
|
|
36
|
+
data: list[ImbalancePriceHistory]
|
|
37
|
+
has_more: bool
|
|
38
|
+
next_updated_since: datetime.datetime
|
|
39
|
+
next_cursor: None | str | Unset = UNSET
|
|
40
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
41
|
+
|
|
42
|
+
def to_dict(self) -> dict[str, Any]:
|
|
43
|
+
queried_period = self.queried_period.to_dict()
|
|
44
|
+
|
|
45
|
+
data = []
|
|
46
|
+
for data_item_data in self.data:
|
|
47
|
+
data_item = data_item_data.to_dict()
|
|
48
|
+
data.append(data_item)
|
|
49
|
+
|
|
50
|
+
has_more = self.has_more
|
|
51
|
+
|
|
52
|
+
next_updated_since = self.next_updated_since.isoformat()
|
|
53
|
+
|
|
54
|
+
next_cursor: None | str | Unset
|
|
55
|
+
if isinstance(self.next_cursor, Unset):
|
|
56
|
+
next_cursor = UNSET
|
|
57
|
+
else:
|
|
58
|
+
next_cursor = self.next_cursor
|
|
59
|
+
|
|
60
|
+
field_dict: dict[str, Any] = {}
|
|
61
|
+
field_dict.update(self.additional_properties)
|
|
62
|
+
field_dict.update(
|
|
63
|
+
{
|
|
64
|
+
"queriedPeriod": queried_period,
|
|
65
|
+
"data": data,
|
|
66
|
+
"hasMore": has_more,
|
|
67
|
+
"nextUpdatedSince": next_updated_since,
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
if next_cursor is not UNSET:
|
|
71
|
+
field_dict["nextCursor"] = next_cursor
|
|
72
|
+
|
|
73
|
+
return field_dict
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
|
77
|
+
from ..models.imbalance_price_history import ImbalancePriceHistory
|
|
78
|
+
from ..models.period import Period
|
|
79
|
+
|
|
80
|
+
d = dict(src_dict)
|
|
81
|
+
queried_period = Period.from_dict(d.pop("queriedPeriod"))
|
|
82
|
+
|
|
83
|
+
data = []
|
|
84
|
+
_data = d.pop("data")
|
|
85
|
+
for data_item_data in _data:
|
|
86
|
+
data_item = ImbalancePriceHistory.from_dict(data_item_data)
|
|
87
|
+
|
|
88
|
+
data.append(data_item)
|
|
89
|
+
|
|
90
|
+
has_more = d.pop("hasMore")
|
|
91
|
+
|
|
92
|
+
next_updated_since = datetime.datetime.fromisoformat(d.pop("nextUpdatedSince").replace("Z", "+00:00"))
|
|
93
|
+
|
|
94
|
+
def _parse_next_cursor(data: object) -> None | str | Unset:
|
|
95
|
+
if data is None:
|
|
96
|
+
return data
|
|
97
|
+
if isinstance(data, Unset):
|
|
98
|
+
return data
|
|
99
|
+
return cast(None | str | Unset, data)
|
|
100
|
+
|
|
101
|
+
next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET))
|
|
102
|
+
|
|
103
|
+
imbalance_price_history_response = cls(
|
|
104
|
+
queried_period=queried_period,
|
|
105
|
+
data=data,
|
|
106
|
+
has_more=has_more,
|
|
107
|
+
next_updated_since=next_updated_since,
|
|
108
|
+
next_cursor=next_cursor,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
imbalance_price_history_response.additional_properties = d
|
|
112
|
+
return imbalance_price_history_response
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def additional_keys(self) -> list[str]:
|
|
116
|
+
return list(self.additional_properties.keys())
|
|
117
|
+
|
|
118
|
+
def __getitem__(self, key: str) -> Any:
|
|
119
|
+
return self.additional_properties[key]
|
|
120
|
+
|
|
121
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
122
|
+
self.additional_properties[key] = value
|
|
123
|
+
|
|
124
|
+
def __delitem__(self, key: str) -> None:
|
|
125
|
+
del self.additional_properties[key]
|
|
126
|
+
|
|
127
|
+
def __contains__(self, key: str) -> bool:
|
|
128
|
+
return key in self.additional_properties
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
6
|
+
|
|
7
|
+
from attrs import define as _attrs_define
|
|
8
|
+
from attrs import field as _attrs_field
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..models.period import Period
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T", bound="ImbalancePriceRevision")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@_attrs_define
|
|
18
|
+
class ImbalancePriceRevision:
|
|
19
|
+
"""
|
|
20
|
+
Attributes:
|
|
21
|
+
period (Period):
|
|
22
|
+
price_per_mwh (float): Price per MWh in the specified currency Example: 45.5.
|
|
23
|
+
observed_at (datetime.datetime): When this revision was recorded (UTC) Example: 2026-08-04T10:07:31Z.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
period: Period
|
|
27
|
+
price_per_mwh: float
|
|
28
|
+
observed_at: datetime.datetime
|
|
29
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> dict[str, Any]:
|
|
32
|
+
period = self.period.to_dict()
|
|
33
|
+
|
|
34
|
+
price_per_mwh = self.price_per_mwh
|
|
35
|
+
|
|
36
|
+
observed_at = self.observed_at.isoformat()
|
|
37
|
+
|
|
38
|
+
field_dict: dict[str, Any] = {}
|
|
39
|
+
field_dict.update(self.additional_properties)
|
|
40
|
+
field_dict.update(
|
|
41
|
+
{
|
|
42
|
+
"period": period,
|
|
43
|
+
"pricePerMwh": price_per_mwh,
|
|
44
|
+
"observedAt": observed_at,
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return field_dict
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
|
|
52
|
+
from ..models.period import Period
|
|
53
|
+
|
|
54
|
+
d = dict(src_dict)
|
|
55
|
+
period = Period.from_dict(d.pop("period"))
|
|
56
|
+
|
|
57
|
+
price_per_mwh = d.pop("pricePerMwh")
|
|
58
|
+
|
|
59
|
+
observed_at = datetime.datetime.fromisoformat(d.pop("observedAt").replace("Z", "+00:00"))
|
|
60
|
+
|
|
61
|
+
imbalance_price_revision = cls(
|
|
62
|
+
period=period,
|
|
63
|
+
price_per_mwh=price_per_mwh,
|
|
64
|
+
observed_at=observed_at,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
imbalance_price_revision.additional_properties = d
|
|
68
|
+
return imbalance_price_revision
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def additional_keys(self) -> list[str]:
|
|
72
|
+
return list(self.additional_properties.keys())
|
|
73
|
+
|
|
74
|
+
def __getitem__(self, key: str) -> Any:
|
|
75
|
+
return self.additional_properties[key]
|
|
76
|
+
|
|
77
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
78
|
+
self.additional_properties[key] = value
|
|
79
|
+
|
|
80
|
+
def __delitem__(self, key: str) -> None:
|
|
81
|
+
del self.additional_properties[key]
|
|
82
|
+
|
|
83
|
+
def __contains__(self, key: str) -> bool:
|
|
84
|
+
return key in self.additional_properties
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "balancing-services"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "Official Python client for accessing European electricity balancing market data via the Balancing Services REST API"
|
|
9
9
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
10
10
|
requires-python = ">=3.10"
|