├── tests ├── __init__.py ├── test_unsupported_resolution.py ├── _utils.py ├── test_prices_not_available.py ├── vcr │ ├── prices_not_available.yaml │ ├── different_currency.yaml │ ├── single_area_yearly.yaml │ ├── single_area_30min.yaml │ ├── single_area_hourly.yaml │ ├── system_hourly.yaml │ ├── multiple_area_hourly.yaml │ └── single_area_15min.yaml ├── test_single_area_monthly.py ├── test_single_area_yearly.py ├── test_single_area_weekly.py ├── test_different_currency.py ├── test_system_hourly.py ├── test_single_area_hourly.py ├── test_single_area_30min.py └── test_single_area_daily.py ├── .flake8 ├── .coveragerc ├── nordpool ├── __init__.py └── elspot.py ├── examples ├── basic.py └── advanced.py ├── .github └── workflows │ ├── python-publish.yml │ └── python-test.yml ├── .gitignore ├── pyproject.toml ├── LICENSE └── README.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max_line_length = 88 3 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | relative_files = True 3 | 4 | [report] 5 | fail_under = 100 6 | -------------------------------------------------------------------------------- /nordpool/__init__.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=missing-module-docstring 2 | import importlib.metadata 3 | 4 | __version__ = importlib.metadata.version(__package__) 5 | -------------------------------------------------------------------------------- /tests/test_unsupported_resolution.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from nordpool.elspot import Prices, UnsupportedResolution 3 | 4 | 5 | class ElspotTestCase(unittest.TestCase): 6 | maxDiff = None 7 | 8 | def test_unsupported_resolution(self): 9 | elspot = Prices() 10 | with self.assertRaises(UnsupportedResolution): 11 | elspot.fetch(end_date="2025-05-07", areas=["FI"], resolution=10) 12 | -------------------------------------------------------------------------------- /tests/_utils.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | from vcr import VCR 3 | 4 | CASSETTE_LIBRARY = pathlib.Path(__file__).parent.resolve() / "vcr" 5 | vcr = VCR( 6 | serializer="yaml", 7 | cassette_library_dir=str(CASSETTE_LIBRARY), 8 | record_mode="once", # Change to "once" to record new cassettes, using "none" to avoid requests made by accident 9 | match_on=["uri", "method", "query", "raw_body"], 10 | decode_compressed_response=True, 11 | ) 12 | -------------------------------------------------------------------------------- /tests/test_prices_not_available.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from nordpool.elspot import Prices 3 | from ._utils import vcr 4 | 5 | 6 | class ElspotTestCase(unittest.TestCase): 7 | maxDiff = None 8 | 9 | def test_prices_not_available(self): 10 | with vcr.use_cassette("prices_not_available.yaml"): 11 | elspot = Prices() 12 | prices = elspot.fetch(elspot.HOURLY, end_date="2025-05-10", areas=["FI"]) 13 | self.assertIsNone(prices) 14 | -------------------------------------------------------------------------------- /examples/basic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from pprint import pprint 4 | from nordpool import elspot 5 | 6 | # Initialize class for fetching the prices. 7 | # An optional currency parameter can be provided, default is EUR. 8 | prices_spot = elspot.Prices() 9 | 10 | # Fetch tomorrow's prices for Finland and print the resulting dictionary. 11 | # If the prices are reported as None, it means that the prices fetched aren't yet available. 12 | # The library by default tries to fetch prices for tomorrow and they're released ~13:00 Swedish time. 13 | pprint(prices_spot.fetch(areas=["FI"])) 14 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Publish 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Build and publish to pypi 17 | uses: JRubics/poetry-publish@v2.0 18 | with: 19 | pypi_token: ${{ secrets.PYPI_TOKEN }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | coverage.lcov 43 | 44 | # Translations 45 | *.mo 46 | *.pot 47 | 48 | # Django stuff: 49 | *.log 50 | 51 | # Sphinx documentation 52 | docs/_build/ 53 | 54 | # PyBuilder 55 | target/ 56 | bin 57 | include 58 | local 59 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "nordpool" 3 | version = "0.5.0" 4 | description = "Python library for fetching Nord Pool spot prices." 5 | authors = ["Kimmo Huoman "] 6 | license = "MIT" 7 | readme = "README.md" 8 | homepage = "https://github.com/kipe/nordpool" 9 | repository = "https://github.com/kipe/nordpool" 10 | 11 | [tool.poetry.dependencies] 12 | python = ">=3.9,<4.0" 13 | python-dateutil = "^2.9.0.post0" 14 | requests = "^2.32.3" 15 | pytz = ">=2024.2" 16 | 17 | 18 | [tool.poetry.group.dev.dependencies] 19 | black = "^24.10.0" 20 | isort = "^5.13.2" 21 | flake8 = "^7.1.1" 22 | vcrpy = "^7.0.0" 23 | time-machine = "^2.16.0" 24 | coverage = "^7.6.3" 25 | pylint = "^3.3.1" 26 | 27 | [build-system] 28 | requires = ["poetry-core"] 29 | build-backend = "poetry.core.masonry.api" 30 | 31 | [tool.black] 32 | target-version = ['py311'] 33 | include = '\.pyi?$' 34 | 35 | [tool.isort] 36 | profile = "black" 37 | multi_line_output = 3 38 | include_trailing_comma = true 39 | force_grid_wrap = 0 40 | use_parentheses = true 41 | skip = [] 42 | known_first_party = ['nordpool'] 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Kimmo Huoman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /.github/workflows/python-test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Test 5 | 6 | on: 7 | push: 8 | branches: [main] 9 | pull_request: 10 | branches: [main] 11 | 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: 18 | - "3.9" 19 | - "3.10" 20 | - "3.11" 21 | - "3.12" 22 | - "3.13" 23 | - "3.14" 24 | 25 | steps: 26 | - uses: actions/checkout@v2 27 | - name: Set up Python ${{ matrix.python-version }} 28 | uses: actions/setup-python@v2 29 | with: 30 | python-version: ${{ matrix.python-version }} 31 | - name: Install dependencies 32 | run: | 33 | python -m pip install --upgrade pip 34 | pip install poetry 35 | poetry install --with dev 36 | - name: Lint 37 | run: | 38 | poetry run flake8 nordpool --max-line-length=88 39 | poetry run pylint nordpool 40 | - name: Run tests 41 | run: | 42 | poetry run coverage run -m unittest discover -b 43 | poetry run coverage lcov 44 | -------------------------------------------------------------------------------- /tests/vcr/prices_not_available.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-10&resolutionInMinutes=60&indexNames=FI 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-10","version":0,"updatedAt":"2025-05-07T07:47:27.3376992Z","market":"DayAhead","indexNames":["FI"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[],"multiIndexEntries":[]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 07:47:27 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746604048.336.28.514816|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 07:47:27 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '208' 38 | status: 39 | code: 200 40 | message: OK 41 | version: 1 42 | -------------------------------------------------------------------------------- /examples/advanced.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | # Import library for fetching Elspot data 4 | from datetime import date 5 | from nordpool import elspot 6 | 7 | # Initialize class for fetching Elspot prices. 8 | # An optional currency parameter can be provided, default is EUR. 9 | prices_spot = elspot.Prices("SEK") # Fetch prices in Swedish kronor 10 | 11 | # Fetch prices for today in Swedish pricing areas 2 and 4 with 15 minute resolution. 12 | price = prices_spot.fetch( 13 | # Need to specify end_date to fetch prices for today, 14 | # as otherwise the library defaults to tomorrow. 15 | end_date=date.today(), 16 | # Set areas to fetch the prices for, library defaults to all areas. 17 | areas=["SE2", "SE4"], 18 | # Set resolution to 15 minutes, library defaults to 60 minutes. 19 | resolution=15, 20 | ) 21 | 22 | # Get basic info about the price data. 23 | # Note: The timestamps are timezone-aware. 24 | start = price["start"].strftime("%Y-%m-%d %H:%M %Z") 25 | end = price["end"].strftime("%Y-%m-%d %H:%M %Z") 26 | updated = price["updated"].strftime("%Y-%m-%d %H:%M %Z") 27 | currency = price["currency"] 28 | 29 | print(f"Energy prices for the period {start} to {end}.") 30 | print(f"Last updated: {updated}.") 31 | print(f"Currency: {currency}.") 32 | print() 33 | 34 | # Loop through each area and print the prices. 35 | for area, area_data in price["areas"].items(): 36 | print(f"Area: {area}") 37 | print("-" * 40) 38 | for entry in area_data["values"]: 39 | start = entry["start"].strftime("%H:%M %Z") 40 | end = entry["end"].strftime("%H:%M %Z") 41 | value = entry["value"] 42 | print(f"{start} - {end}: {value:.2f} {currency}/MWh") 43 | print() 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nordpool 2 | 3 | ![Test Status](https://github.com/kipe/nordpool/actions/workflows/python-test.yml/badge.svg?branch=main) 4 | 5 | Python library for fetching Nord Pool Elspot prices. 6 | 7 | ## Python version 8 | 9 | The minimum supported Python version is 3.9, which receives security updates until [2025-10](https://devguide.python.org/versions/). 10 | The library won't install without trickery on older versions, so update your Python. 11 | 12 | ## Installing 13 | 14 | To install from [PyPi](https://pypi.org/project/nordpool/), use 15 | 16 | `pip install nordpool` 17 | 18 | ## To upgrade 19 | 20 | To upgrade installation from [PyPi](https://pypi.org/project/nordpool/), use 21 | 22 | `pip install -U nordpool` 23 | 24 | ## Usage example 25 | 26 | Below is a very basic example of the library usage. More advanced example(s) can be found in `examples` -directory. 27 | 28 | ```python 29 | from pprint import pprint 30 | from nordpool import elspot 31 | 32 | # Initialize class for fetching the prices. 33 | # An optional currency parameter can be provided, default is EUR. 34 | prices_spot = elspot.Prices() 35 | 36 | # Fetch tomorrow's prices for Finland and print the resulting dictionary. 37 | # If the prices are reported as None, it means that the prices fetched aren't yet available. 38 | # The library by default tries to fetch prices for tomorrow and they're released ~13:00 Swedish time. 39 | pprint(prices_spot.fetch(areas=["FI"])) 40 | ``` 41 | 42 | Output: 43 | ```python 44 | { 45 | "areas": { 46 | "FI": { 47 | "values": [ 48 | { 49 | "end": datetime.datetime(2025, 5, 12, 23, 0, tzinfo=tzutc()), 50 | "start": datetime.datetime(2025, 5, 12, 22, 0, tzinfo=tzutc()), 51 | "value": 5.11, 52 | }, 53 | { 54 | "end": datetime.datetime(2025, 5, 13, 0, 0, tzinfo=tzutc()), 55 | "start": datetime.datetime(2025, 5, 12, 23, 0, tzinfo=tzutc()), 56 | "value": 5.8, 57 | }, 58 | { 59 | "end": datetime.datetime(2025, 5, 13, 1, 0, tzinfo=tzutc()), 60 | "start": datetime.datetime(2025, 5, 13, 0, 0, tzinfo=tzutc()), 61 | "value": 4.51, 62 | }, 63 | # ... SNIP ... 64 | { 65 | "end": datetime.datetime(2025, 5, 13, 22, 0, tzinfo=tzutc()), 66 | "start": datetime.datetime(2025, 5, 13, 21, 0, tzinfo=tzutc()), 67 | "value": -10.24, 68 | }, 69 | ] 70 | } 71 | }, 72 | "currency": "EUR", 73 | "end": datetime.datetime(2025, 5, 13, 22, 0, tzinfo=tzutc()), 74 | "start": datetime.datetime(2025, 5, 12, 22, 0, tzinfo=tzutc()), 75 | "updated": datetime.datetime(2025, 5, 12, 11, 26, 3, 811220, tzinfo=tzutc()), 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /tests/test_single_area_monthly.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_single_area_monthly(self): 12 | with vcr.use_cassette("single_area_monthly.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(elspot.MONTHLY, end_date="2025-05-07", areas=["FI"]) 15 | self.assertEqual( 16 | prices, 17 | elspot.monthly("2025-05-07", areas=["FI"]), 18 | ) 19 | self.assertEqual( 20 | prices, 21 | { 22 | "areas": { 23 | "FI": { 24 | "values": [ 25 | { 26 | "end": datetime.datetime(2025, 5, 7, 0, 0), 27 | "start": datetime.datetime(2025, 5, 1, 0, 0), 28 | "value": 21.28, 29 | }, 30 | { 31 | "end": datetime.datetime(2025, 4, 30, 0, 0), 32 | "start": datetime.datetime(2025, 4, 1, 0, 0), 33 | "value": 47.75, 34 | }, 35 | { 36 | "end": datetime.datetime(2025, 3, 31, 0, 0), 37 | "start": datetime.datetime(2025, 3, 1, 0, 0), 38 | "value": 47.52, 39 | }, 40 | { 41 | "end": datetime.datetime(2025, 2, 28, 0, 0), 42 | "start": datetime.datetime(2025, 2, 1, 0, 0), 43 | "value": 47.29, 44 | }, 45 | { 46 | "end": datetime.datetime(2025, 1, 31, 0, 0), 47 | "start": datetime.datetime(2025, 1, 1, 0, 0), 48 | "value": 52.82, 49 | }, 50 | ] 51 | } 52 | }, 53 | "currency": "EUR", 54 | "end": datetime.datetime(2025, 5, 7, 0, 0), 55 | "start": datetime.datetime(2025, 1, 1, 0, 0), 56 | "updated": datetime.datetime( 57 | 2025, 5, 6, 11, 30, 47, 285765, tzinfo=utc 58 | ), 59 | }, 60 | ) 61 | -------------------------------------------------------------------------------- /tests/test_single_area_yearly.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_single_area_yearly(self): 12 | with vcr.use_cassette("single_area_yearly.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(elspot.YEARLY, end_date="2025-05-07", areas=["FI"]) 15 | self.assertEqual( 16 | prices, 17 | elspot.yearly("2025-05-07", areas=["FI"]), 18 | ) 19 | self.assertEqual( 20 | prices, 21 | { 22 | "areas": { 23 | "FI": { 24 | "values": [ 25 | { 26 | "end": datetime.datetime(2025, 5, 7, 0, 0), 27 | "start": datetime.datetime(2025, 1, 1, 0, 0), 28 | "value": 47.37, 29 | }, 30 | { 31 | "end": datetime.datetime(2024, 12, 31, 0, 0), 32 | "start": datetime.datetime(2024, 1, 1, 0, 0), 33 | "value": 45.57, 34 | }, 35 | { 36 | "end": datetime.datetime(2023, 12, 31, 0, 0), 37 | "start": datetime.datetime(2023, 1, 1, 0, 0), 38 | "value": 56.47, 39 | }, 40 | { 41 | "end": datetime.datetime(2022, 12, 31, 0, 0), 42 | "start": datetime.datetime(2022, 1, 1, 0, 0), 43 | "value": 154.04, 44 | }, 45 | { 46 | "end": datetime.datetime(2021, 12, 31, 0, 0), 47 | "start": datetime.datetime(2021, 1, 1, 0, 0), 48 | "value": 72.34, 49 | }, 50 | { 51 | "end": datetime.datetime(2020, 12, 31, 0, 0), 52 | "start": datetime.datetime(2020, 1, 1, 0, 0), 53 | "value": 28.02, 54 | }, 55 | ] 56 | } 57 | }, 58 | "currency": "EUR", 59 | "end": datetime.datetime(2025, 5, 7, 0, 0), 60 | "start": datetime.datetime(2020, 1, 1, 0, 0), 61 | "updated": datetime.datetime( 62 | 2024, 3, 26, 13, 18, 33, 301921, tzinfo=utc 63 | ), 64 | }, 65 | ) 66 | -------------------------------------------------------------------------------- /tests/vcr/different_currency.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=SEK&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=SE1 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:13.6833528Z","market":"DayAhead","indexNames":["SE1"],"currency":"SEK","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["SE1"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"SE1":243.58}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"SE1":155.37}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"SE1":137.16}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"SE1":140.54}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"SE1":211.08}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"SE1":602.94}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"SE1":1218.54}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"SE1":1569.51}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"SE1":1345.01}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"SE1":1005.82}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"SE1":661.49}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"SE1":714.27}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"SE1":622.13}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"SE1":339.85}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"SE1":290.13}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"SE1":266.36}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"SE1":335.60}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"SE1":914.56}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"SE1":1018.14}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"SE1":999.27}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"SE1":970.82}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"SE1":1024.13}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"SE1":1167.07}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"SE1":1026.75}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 07:48:01 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746604082.782.28.383746|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 07:48:01 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '2841' 38 | status: 39 | code: 200 40 | message: OK 41 | version: 1 42 | -------------------------------------------------------------------------------- /tests/vcr/single_area_yearly.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/AggregatePrices/GetAnnuals?currency=EUR&market=DayAhead&deliveryArea=FI 15 | response: 16 | body: 17 | string: '{"updatedAt":"2024-03-26T13:18:33.301921Z","prices":[{"year":2025,"deliveryStart":"2025-01-01","deliveryEnd":"2025-05-07","averagePerArea":{"FI":47.37},"maxPerArea":{"FI":382.06},"minPerArea":{"FI":-10.01}},{"year":2024,"deliveryStart":"2024-01-01","deliveryEnd":"2024-12-31","averagePerArea":{"FI":45.57},"maxPerArea":{"FI":1896},"minPerArea":{"FI":-20.01}},{"year":2023,"deliveryStart":"2023-01-01","deliveryEnd":"2023-12-31","averagePerArea":{"FI":56.47},"maxPerArea":{"FI":777.18},"minPerArea":{"FI":-500}},{"year":2022,"deliveryStart":"2022-01-01","deliveryEnd":"2022-12-31","averagePerArea":{"FI":154.04},"maxPerArea":{"FI":861.14},"minPerArea":{"FI":-2.08}},{"year":2021,"deliveryStart":"2021-01-01","deliveryEnd":"2021-12-31","averagePerArea":{"FI":72.34},"maxPerArea":{"FI":1000.07},"minPerArea":{"FI":-1.41}},{"year":2020,"deliveryStart":"2020-01-01","deliveryEnd":"2020-12-31","averagePerArea":{"FI":28.02},"maxPerArea":{"FI":254.44},"minPerArea":{"FI":-1.73}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 07:50:43 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746604244.301.29.658278|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 07:50:43 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Vary: 33 | - Accept-Encoding 34 | content-length: 35 | - '973' 36 | status: 37 | code: 200 38 | message: OK 39 | - request: 40 | body: null 41 | headers: 42 | Accept: 43 | - '*/*' 44 | Accept-Encoding: 45 | - gzip, deflate 46 | Connection: 47 | - keep-alive 48 | User-Agent: 49 | - python-requests/2.32.3 50 | method: GET 51 | uri: https://dataportal-api.nordpoolgroup.com/api/AggregatePrices/GetAnnuals?currency=EUR&market=DayAhead&deliveryArea=FI 52 | response: 53 | body: 54 | string: '{"updatedAt":"2024-03-26T13:18:33.301921Z","prices":[{"year":2025,"deliveryStart":"2025-01-01","deliveryEnd":"2025-05-07","averagePerArea":{"FI":47.37},"maxPerArea":{"FI":382.06},"minPerArea":{"FI":-10.01}},{"year":2024,"deliveryStart":"2024-01-01","deliveryEnd":"2024-12-31","averagePerArea":{"FI":45.57},"maxPerArea":{"FI":1896},"minPerArea":{"FI":-20.01}},{"year":2023,"deliveryStart":"2023-01-01","deliveryEnd":"2023-12-31","averagePerArea":{"FI":56.47},"maxPerArea":{"FI":777.18},"minPerArea":{"FI":-500}},{"year":2022,"deliveryStart":"2022-01-01","deliveryEnd":"2022-12-31","averagePerArea":{"FI":154.04},"maxPerArea":{"FI":861.14},"minPerArea":{"FI":-2.08}},{"year":2021,"deliveryStart":"2021-01-01","deliveryEnd":"2021-12-31","averagePerArea":{"FI":72.34},"maxPerArea":{"FI":1000.07},"minPerArea":{"FI":-1.41}},{"year":2020,"deliveryStart":"2020-01-01","deliveryEnd":"2020-12-31","averagePerArea":{"FI":28.02},"maxPerArea":{"FI":254.44},"minPerArea":{"FI":-1.73}}]}' 55 | headers: 56 | Connection: 57 | - keep-alive 58 | Content-Type: 59 | - application/json; charset=utf-8 60 | Date: 61 | - Wed, 07 May 2025 07:50:55 GMT 62 | Request-Context: 63 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 64 | Set-Cookie: 65 | - route=1746604256.212.29.284064|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 66 | 09-May-25 07:50:55 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 67 | Strict-Transport-Security: 68 | - max-age=31536000 69 | Transfer-Encoding: 70 | - chunked 71 | Vary: 72 | - Accept-Encoding 73 | content-length: 74 | - '973' 75 | status: 76 | code: 200 77 | message: OK 78 | version: 1 79 | -------------------------------------------------------------------------------- /tests/vcr/single_area_30min.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=30&indexNames=FI 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:10.8722033Z","market":"DayAhead","indexNames":["FI"],"currency":"EUR","resolutionInMinutes":30,"areaStates":[{"state":"Final","areas":["FI"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T22:30:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T22:30:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-06T23:30:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-06T23:30:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T00:30:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T00:30:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T01:30:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T01:30:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T02:30:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T02:30:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T03:30:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T03:30:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T04:30:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T04:30:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T05:30:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T05:30:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T06:30:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T06:30:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T07:30:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T07:30:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T08:30:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T08:30:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T09:30:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T09:30:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T10:30:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T10:30:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T11:30:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T11:30:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T12:30:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T12:30:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T13:30:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T13:30:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T14:30:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T14:30:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T15:30:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T15:30:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T16:30:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T16:30:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T17:30:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T17:30:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T18:30:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T18:30:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T19:30:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T19:30:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T20:30:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T20:30:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T21:30:00Z","entryPerArea":{"FI":94.16}},{"deliveryStart":"2025-05-07T21:30:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"FI":94.16}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 07:59:45 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746604786.113.27.28585|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 07:59:45 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '5343' 38 | status: 39 | code: 200 40 | message: OK 41 | version: 1 42 | -------------------------------------------------------------------------------- /tests/test_single_area_weekly.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_single_area_weekly(self): 12 | with vcr.use_cassette("single_area_weekly.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(elspot.WEEKLY, end_date="2025-05-07", areas=["FI"]) 15 | self.assertEqual( 16 | prices, 17 | elspot.weekly("2025-05-07", areas=["FI"]), 18 | ) 19 | self.assertEqual( 20 | prices, 21 | { 22 | "areas": { 23 | "FI": { 24 | "values": [ 25 | { 26 | "end": datetime.datetime(2025, 5, 7, 0, 0), 27 | "start": datetime.datetime(2025, 5, 5, 0, 0), 28 | "value": 43.96, 29 | }, 30 | { 31 | "end": datetime.datetime(2025, 5, 4, 0, 0), 32 | "start": datetime.datetime(2025, 4, 28, 0, 0), 33 | "value": 39.03, 34 | }, 35 | { 36 | "end": datetime.datetime(2025, 4, 27, 0, 0), 37 | "start": datetime.datetime(2025, 4, 21, 0, 0), 38 | "value": 95.07, 39 | }, 40 | { 41 | "end": datetime.datetime(2025, 4, 20, 0, 0), 42 | "start": datetime.datetime(2025, 4, 14, 0, 0), 43 | "value": 30.02, 44 | }, 45 | { 46 | "end": datetime.datetime(2025, 4, 13, 0, 0), 47 | "start": datetime.datetime(2025, 4, 7, 0, 0), 48 | "value": 30.24, 49 | }, 50 | { 51 | "end": datetime.datetime(2025, 4, 6, 0, 0), 52 | "start": datetime.datetime(2025, 3, 31, 0, 0), 53 | "value": 29.86, 54 | }, 55 | { 56 | "end": datetime.datetime(2025, 3, 30, 0, 0), 57 | "start": datetime.datetime(2025, 3, 24, 0, 0), 58 | "value": 27.18, 59 | }, 60 | { 61 | "end": datetime.datetime(2025, 3, 23, 0, 0), 62 | "start": datetime.datetime(2025, 3, 17, 0, 0), 63 | "value": 44.74, 64 | }, 65 | { 66 | "end": datetime.datetime(2025, 3, 16, 0, 0), 67 | "start": datetime.datetime(2025, 3, 10, 0, 0), 68 | "value": 88.74, 69 | }, 70 | { 71 | "end": datetime.datetime(2025, 3, 9, 0, 0), 72 | "start": datetime.datetime(2025, 3, 3, 0, 0), 73 | "value": 21.01, 74 | }, 75 | { 76 | "end": datetime.datetime(2025, 3, 2, 0, 0), 77 | "start": datetime.datetime(2025, 2, 24, 0, 0), 78 | "value": 31.02, 79 | }, 80 | { 81 | "end": datetime.datetime(2025, 2, 23, 0, 0), 82 | "start": datetime.datetime(2025, 2, 17, 0, 0), 83 | "value": 35.44, 84 | }, 85 | { 86 | "end": datetime.datetime(2025, 2, 16, 0, 0), 87 | "start": datetime.datetime(2025, 2, 10, 0, 0), 88 | "value": 86.17, 89 | }, 90 | { 91 | "end": datetime.datetime(2025, 2, 9, 0, 0), 92 | "start": datetime.datetime(2025, 2, 3, 0, 0), 93 | "value": 44.34, 94 | }, 95 | { 96 | "end": datetime.datetime(2025, 2, 2, 0, 0), 97 | "start": datetime.datetime(2025, 1, 27, 0, 0), 98 | "value": 39.64, 99 | }, 100 | { 101 | "end": datetime.datetime(2025, 1, 26, 0, 0), 102 | "start": datetime.datetime(2025, 1, 20, 0, 0), 103 | "value": 63.29, 104 | }, 105 | { 106 | "end": datetime.datetime(2025, 1, 19, 0, 0), 107 | "start": datetime.datetime(2025, 1, 13, 0, 0), 108 | "value": 10.48, 109 | }, 110 | { 111 | "end": datetime.datetime(2025, 1, 12, 0, 0), 112 | "start": datetime.datetime(2025, 1, 6, 0, 0), 113 | "value": 65.58, 114 | }, 115 | { 116 | "end": datetime.datetime(2025, 1, 5, 0, 0), 117 | "start": datetime.datetime(2024, 12, 30, 0, 0), 118 | "value": 60.28, 119 | }, 120 | ] 121 | } 122 | }, 123 | "currency": "EUR", 124 | "end": datetime.datetime(2025, 5, 7, 0, 0), 125 | "start": datetime.datetime(2024, 12, 30, 0, 0), 126 | "updated": datetime.datetime( 127 | 2025, 5, 6, 11, 30, 47, 285765, tzinfo=utc 128 | ), 129 | }, 130 | ) 131 | -------------------------------------------------------------------------------- /tests/vcr/single_area_hourly.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=FI 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:12.4833192Z","market":"DayAhead","indexNames":["FI"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["FI"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"FI":94.16}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 07:48:14 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746604095.457.28.656004|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 07:48:14 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '2791' 38 | status: 39 | code: 200 40 | message: OK 41 | - request: 42 | body: null 43 | headers: 44 | Accept: 45 | - '*/*' 46 | Accept-Encoding: 47 | - gzip, deflate 48 | Connection: 49 | - keep-alive 50 | User-Agent: 51 | - python-requests/2.32.3 52 | method: GET 53 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=FI 54 | response: 55 | body: 56 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:12.4833192Z","market":"DayAhead","indexNames":["FI"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["FI"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"FI":94.16}}]}' 57 | headers: 58 | Connection: 59 | - keep-alive 60 | Content-Type: 61 | - application/json; charset=utf-8 62 | Date: 63 | - Wed, 07 May 2025 07:48:14 GMT 64 | Request-Context: 65 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 66 | Set-Cookie: 67 | - route=1746604095.595.28.939304|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 68 | 09-May-25 07:48:14 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 69 | Strict-Transport-Security: 70 | - max-age=31536000 71 | Transfer-Encoding: 72 | - chunked 73 | Vary: 74 | - Accept-Encoding 75 | content-length: 76 | - '2791' 77 | status: 78 | code: 200 79 | message: OK 80 | version: 1 81 | -------------------------------------------------------------------------------- /tests/vcr/system_hourly.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=SYSTEM 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-07","version":2,"updatedAt":"2025-05-06T10:56:31.0120062Z","market":"DayAhead","indexNames":["SYSTEM"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["SYSTEM"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"SYSTEM":74.2}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"SYSTEM":68.4}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"SYSTEM":67.47}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"SYSTEM":68.04}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"SYSTEM":70.3}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"SYSTEM":87.57}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"SYSTEM":116.11}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"SYSTEM":143.0}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"SYSTEM":123.89}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"SYSTEM":94.98}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"SYSTEM":79.98}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"SYSTEM":74.28}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"SYSTEM":64.68}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"SYSTEM":60.92}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"SYSTEM":62.85}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"SYSTEM":67.29}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"SYSTEM":67.69}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"SYSTEM":86.97}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"SYSTEM":105.3}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"SYSTEM":121.47}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"SYSTEM":132.21}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"SYSTEM":110.74}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"SYSTEM":99.95}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"SYSTEM":86.46}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 08:40:28 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746607229.403.28.153032|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 08:40:28 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '2889' 38 | status: 39 | code: 200 40 | message: OK 41 | - request: 42 | body: null 43 | headers: 44 | Accept: 45 | - '*/*' 46 | Accept-Encoding: 47 | - gzip, deflate 48 | Connection: 49 | - keep-alive 50 | User-Agent: 51 | - python-requests/2.32.3 52 | method: GET 53 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=SYSTEM 54 | response: 55 | body: 56 | string: '{"deliveryDateCET":"2025-05-07","version":2,"updatedAt":"2025-05-06T10:56:31.0120062Z","market":"DayAhead","indexNames":["SYSTEM"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["SYSTEM"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"SYSTEM":74.2}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"SYSTEM":68.4}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"SYSTEM":67.47}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"SYSTEM":68.04}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"SYSTEM":70.3}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"SYSTEM":87.57}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"SYSTEM":116.11}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"SYSTEM":143.0}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"SYSTEM":123.89}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"SYSTEM":94.98}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"SYSTEM":79.98}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"SYSTEM":74.28}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"SYSTEM":64.68}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"SYSTEM":60.92}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"SYSTEM":62.85}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"SYSTEM":67.29}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"SYSTEM":67.69}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"SYSTEM":86.97}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"SYSTEM":105.3}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"SYSTEM":121.47}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"SYSTEM":132.21}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"SYSTEM":110.74}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"SYSTEM":99.95}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"SYSTEM":86.46}}]}' 57 | headers: 58 | Connection: 59 | - keep-alive 60 | Content-Type: 61 | - application/json; charset=utf-8 62 | Date: 63 | - Wed, 07 May 2025 08:40:28 GMT 64 | Request-Context: 65 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 66 | Set-Cookie: 67 | - route=1746607229.513.29.612483|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 68 | 09-May-25 08:40:28 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 69 | Strict-Transport-Security: 70 | - max-age=31536000 71 | Transfer-Encoding: 72 | - chunked 73 | Vary: 74 | - Accept-Encoding 75 | content-length: 76 | - '2889' 77 | status: 78 | code: 200 79 | message: OK 80 | version: 1 81 | -------------------------------------------------------------------------------- /tests/vcr/multiple_area_hourly.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=SE1%2CSE2%2CSE3%2CSE4 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:13.8160753Z","market":"DayAhead","indexNames":["SE1","SE2","SE3","SE4"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["SE1","SE2","SE3","SE4"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"SE1":22.34,"SE2":21.24,"SE3":56.85,"SE4":90.32}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"SE1":14.25,"SE2":14.33,"SE3":50.11,"SE4":84.73}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"SE1":12.58,"SE2":12.63,"SE3":48.66,"SE4":83.35}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"SE1":12.89,"SE2":11.44,"SE3":49.88,"SE4":86.24}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"SE1":19.36,"SE2":16.90,"SE3":55.97,"SE4":92.72}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"SE1":55.30,"SE2":55.11,"SE3":80.47,"SE4":105.96}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"SE1":111.76,"SE2":109.10,"SE3":119.78,"SE4":128.53}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"SE1":143.95,"SE2":143.95,"SE3":143.95,"SE4":143.95}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"SE1":123.36,"SE2":123.36,"SE3":123.37,"SE4":123.37}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"SE1":92.25,"SE2":92.03,"SE3":93.33,"SE4":94.03}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"SE1":60.67,"SE2":58.83,"SE3":70.33,"SE4":76.57}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"SE1":65.51,"SE2":64.91,"SE3":69.01,"SE4":71.28}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"SE1":57.06,"SE2":56.54,"SE3":60.46,"SE4":62.63}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"SE1":31.17,"SE2":52.66,"SE3":56.66,"SE4":61.75}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"SE1":26.61,"SE2":53.91,"SE3":59.37,"SE4":66.08}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"SE1":24.43,"SE2":53.04,"SE3":61.51,"SE4":70.10}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"SE1":30.78,"SE2":29.96,"SE3":55.26,"SE4":79.63}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"SE1":83.88,"SE2":83.89,"SE3":88.81,"SE4":93.94}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"SE1":93.38,"SE2":95.58,"SE3":107.75,"SE4":108.96}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"SE1":91.65,"SE2":97.17,"SE3":133.88,"SE4":129.36}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"SE1":89.04,"SE2":96.91,"SE3":144.53,"SE4":149.02}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"SE1":93.93,"SE2":99.59,"SE3":126.89,"SE4":124.78}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"SE1":107.04,"SE2":104.54,"SE3":106.96,"SE4":105.93}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"SE1":94.17,"SE2":91.68,"SE3":93.80,"SE4":94.29}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 07:47:37 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746604058.005.28.709883|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 07:47:37 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '3734' 38 | status: 39 | code: 200 40 | message: OK 41 | - request: 42 | body: null 43 | headers: 44 | Accept: 45 | - '*/*' 46 | Accept-Encoding: 47 | - gzip, deflate 48 | Connection: 49 | - keep-alive 50 | User-Agent: 51 | - python-requests/2.32.3 52 | method: GET 53 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=60&indexNames=SE1%2CSE2%2CSE3%2CSE4 54 | response: 55 | body: 56 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:13.8160753Z","market":"DayAhead","indexNames":["SE1","SE2","SE3","SE4"],"currency":"EUR","resolutionInMinutes":60,"areaStates":[{"state":"Final","areas":["SE1","SE2","SE3","SE4"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"SE1":22.34,"SE2":21.24,"SE3":56.85,"SE4":90.32}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"SE1":14.25,"SE2":14.33,"SE3":50.11,"SE4":84.73}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"SE1":12.58,"SE2":12.63,"SE3":48.66,"SE4":83.35}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"SE1":12.89,"SE2":11.44,"SE3":49.88,"SE4":86.24}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"SE1":19.36,"SE2":16.90,"SE3":55.97,"SE4":92.72}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"SE1":55.30,"SE2":55.11,"SE3":80.47,"SE4":105.96}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"SE1":111.76,"SE2":109.10,"SE3":119.78,"SE4":128.53}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"SE1":143.95,"SE2":143.95,"SE3":143.95,"SE4":143.95}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"SE1":123.36,"SE2":123.36,"SE3":123.37,"SE4":123.37}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"SE1":92.25,"SE2":92.03,"SE3":93.33,"SE4":94.03}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"SE1":60.67,"SE2":58.83,"SE3":70.33,"SE4":76.57}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"SE1":65.51,"SE2":64.91,"SE3":69.01,"SE4":71.28}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"SE1":57.06,"SE2":56.54,"SE3":60.46,"SE4":62.63}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"SE1":31.17,"SE2":52.66,"SE3":56.66,"SE4":61.75}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"SE1":26.61,"SE2":53.91,"SE3":59.37,"SE4":66.08}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"SE1":24.43,"SE2":53.04,"SE3":61.51,"SE4":70.10}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"SE1":30.78,"SE2":29.96,"SE3":55.26,"SE4":79.63}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"SE1":83.88,"SE2":83.89,"SE3":88.81,"SE4":93.94}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"SE1":93.38,"SE2":95.58,"SE3":107.75,"SE4":108.96}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"SE1":91.65,"SE2":97.17,"SE3":133.88,"SE4":129.36}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"SE1":89.04,"SE2":96.91,"SE3":144.53,"SE4":149.02}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"SE1":93.93,"SE2":99.59,"SE3":126.89,"SE4":124.78}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"SE1":107.04,"SE2":104.54,"SE3":106.96,"SE4":105.93}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"SE1":94.17,"SE2":91.68,"SE3":93.80,"SE4":94.29}}]}' 57 | headers: 58 | Connection: 59 | - keep-alive 60 | Content-Type: 61 | - application/json; charset=utf-8 62 | Date: 63 | - Wed, 07 May 2025 07:47:37 GMT 64 | Request-Context: 65 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 66 | Set-Cookie: 67 | - route=1746604058.171.28.54605|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 68 | 09-May-25 07:47:37 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 69 | Strict-Transport-Security: 70 | - max-age=31536000 71 | Transfer-Encoding: 72 | - chunked 73 | Vary: 74 | - Accept-Encoding 75 | content-length: 76 | - '3734' 77 | status: 78 | code: 200 79 | message: OK 80 | version: 1 81 | -------------------------------------------------------------------------------- /tests/vcr/single_area_15min.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://dataportal-api.nordpoolgroup.com/api/DayAheadPriceIndices?currency=EUR&market=DayAhead&date=2025-05-07&resolutionInMinutes=15&indexNames=FI 15 | response: 16 | body: 17 | string: '{"deliveryDateCET":"2025-05-07","version":3,"updatedAt":"2025-05-06T11:22:09.2205745Z","market":"DayAhead","indexNames":["FI"],"currency":"EUR","resolutionInMinutes":15,"areaStates":[{"state":"Final","areas":["FI"]}],"multiIndexEntries":[{"deliveryStart":"2025-05-06T22:00:00Z","deliveryEnd":"2025-05-06T22:15:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T22:15:00Z","deliveryEnd":"2025-05-06T22:30:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T22:30:00Z","deliveryEnd":"2025-05-06T22:45:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T22:45:00Z","deliveryEnd":"2025-05-06T23:00:00Z","entryPerArea":{"FI":22.34}},{"deliveryStart":"2025-05-06T23:00:00Z","deliveryEnd":"2025-05-06T23:15:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-06T23:15:00Z","deliveryEnd":"2025-05-06T23:30:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-06T23:30:00Z","deliveryEnd":"2025-05-06T23:45:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-06T23:45:00Z","deliveryEnd":"2025-05-07T00:00:00Z","entryPerArea":{"FI":14.26}},{"deliveryStart":"2025-05-07T00:00:00Z","deliveryEnd":"2025-05-07T00:15:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T00:15:00Z","deliveryEnd":"2025-05-07T00:30:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T00:30:00Z","deliveryEnd":"2025-05-07T00:45:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T00:45:00Z","deliveryEnd":"2025-05-07T01:00:00Z","entryPerArea":{"FI":12.59}},{"deliveryStart":"2025-05-07T01:00:00Z","deliveryEnd":"2025-05-07T01:15:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T01:15:00Z","deliveryEnd":"2025-05-07T01:30:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T01:30:00Z","deliveryEnd":"2025-05-07T01:45:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T01:45:00Z","deliveryEnd":"2025-05-07T02:00:00Z","entryPerArea":{"FI":13.69}},{"deliveryStart":"2025-05-07T02:00:00Z","deliveryEnd":"2025-05-07T02:15:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T02:15:00Z","deliveryEnd":"2025-05-07T02:30:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T02:30:00Z","deliveryEnd":"2025-05-07T02:45:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T02:45:00Z","deliveryEnd":"2025-05-07T03:00:00Z","entryPerArea":{"FI":19.34}},{"deliveryStart":"2025-05-07T03:00:00Z","deliveryEnd":"2025-05-07T03:15:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T03:15:00Z","deliveryEnd":"2025-05-07T03:30:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T03:30:00Z","deliveryEnd":"2025-05-07T03:45:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T03:45:00Z","deliveryEnd":"2025-05-07T04:00:00Z","entryPerArea":{"FI":55.31}},{"deliveryStart":"2025-05-07T04:00:00Z","deliveryEnd":"2025-05-07T04:15:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T04:15:00Z","deliveryEnd":"2025-05-07T04:30:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T04:30:00Z","deliveryEnd":"2025-05-07T04:45:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T04:45:00Z","deliveryEnd":"2025-05-07T05:00:00Z","entryPerArea":{"FI":111.77}},{"deliveryStart":"2025-05-07T05:00:00Z","deliveryEnd":"2025-05-07T05:15:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T05:15:00Z","deliveryEnd":"2025-05-07T05:30:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T05:30:00Z","deliveryEnd":"2025-05-07T05:45:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T05:45:00Z","deliveryEnd":"2025-05-07T06:00:00Z","entryPerArea":{"FI":143.95}},{"deliveryStart":"2025-05-07T06:00:00Z","deliveryEnd":"2025-05-07T06:15:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T06:15:00Z","deliveryEnd":"2025-05-07T06:30:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T06:30:00Z","deliveryEnd":"2025-05-07T06:45:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T06:45:00Z","deliveryEnd":"2025-05-07T07:00:00Z","entryPerArea":{"FI":123.36}},{"deliveryStart":"2025-05-07T07:00:00Z","deliveryEnd":"2025-05-07T07:15:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T07:15:00Z","deliveryEnd":"2025-05-07T07:30:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T07:30:00Z","deliveryEnd":"2025-05-07T07:45:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T07:45:00Z","deliveryEnd":"2025-05-07T08:00:00Z","entryPerArea":{"FI":92.48}},{"deliveryStart":"2025-05-07T08:00:00Z","deliveryEnd":"2025-05-07T08:15:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T08:15:00Z","deliveryEnd":"2025-05-07T08:30:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T08:30:00Z","deliveryEnd":"2025-05-07T08:45:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T08:45:00Z","deliveryEnd":"2025-05-07T09:00:00Z","entryPerArea":{"FI":62.72}},{"deliveryStart":"2025-05-07T09:00:00Z","deliveryEnd":"2025-05-07T09:15:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T09:15:00Z","deliveryEnd":"2025-05-07T09:30:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T09:30:00Z","deliveryEnd":"2025-05-07T09:45:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T09:45:00Z","deliveryEnd":"2025-05-07T10:00:00Z","entryPerArea":{"FI":66.25}},{"deliveryStart":"2025-05-07T10:00:00Z","deliveryEnd":"2025-05-07T10:15:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T10:15:00Z","deliveryEnd":"2025-05-07T10:30:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T10:30:00Z","deliveryEnd":"2025-05-07T10:45:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T10:45:00Z","deliveryEnd":"2025-05-07T11:00:00Z","entryPerArea":{"FI":57.84}},{"deliveryStart":"2025-05-07T11:00:00Z","deliveryEnd":"2025-05-07T11:15:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T11:15:00Z","deliveryEnd":"2025-05-07T11:30:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T11:30:00Z","deliveryEnd":"2025-05-07T11:45:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T11:45:00Z","deliveryEnd":"2025-05-07T12:00:00Z","entryPerArea":{"FI":31.59}},{"deliveryStart":"2025-05-07T12:00:00Z","deliveryEnd":"2025-05-07T12:15:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T12:15:00Z","deliveryEnd":"2025-05-07T12:30:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T12:30:00Z","deliveryEnd":"2025-05-07T12:45:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T12:45:00Z","deliveryEnd":"2025-05-07T13:00:00Z","entryPerArea":{"FI":27.14}},{"deliveryStart":"2025-05-07T13:00:00Z","deliveryEnd":"2025-05-07T13:15:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T13:15:00Z","deliveryEnd":"2025-05-07T13:30:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T13:30:00Z","deliveryEnd":"2025-05-07T13:45:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T13:45:00Z","deliveryEnd":"2025-05-07T14:00:00Z","entryPerArea":{"FI":25.00}},{"deliveryStart":"2025-05-07T14:00:00Z","deliveryEnd":"2025-05-07T14:15:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T14:15:00Z","deliveryEnd":"2025-05-07T14:30:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T14:30:00Z","deliveryEnd":"2025-05-07T14:45:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T14:45:00Z","deliveryEnd":"2025-05-07T15:00:00Z","entryPerArea":{"FI":30.77}},{"deliveryStart":"2025-05-07T15:00:00Z","deliveryEnd":"2025-05-07T15:15:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T15:15:00Z","deliveryEnd":"2025-05-07T15:30:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T15:30:00Z","deliveryEnd":"2025-05-07T15:45:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T15:45:00Z","deliveryEnd":"2025-05-07T16:00:00Z","entryPerArea":{"FI":83.88}},{"deliveryStart":"2025-05-07T16:00:00Z","deliveryEnd":"2025-05-07T16:15:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T16:15:00Z","deliveryEnd":"2025-05-07T16:30:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T16:30:00Z","deliveryEnd":"2025-05-07T16:45:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T16:45:00Z","deliveryEnd":"2025-05-07T17:00:00Z","entryPerArea":{"FI":110.57}},{"deliveryStart":"2025-05-07T17:00:00Z","deliveryEnd":"2025-05-07T17:15:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T17:15:00Z","deliveryEnd":"2025-05-07T17:30:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T17:30:00Z","deliveryEnd":"2025-05-07T17:45:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T17:45:00Z","deliveryEnd":"2025-05-07T18:00:00Z","entryPerArea":{"FI":150.83}},{"deliveryStart":"2025-05-07T18:00:00Z","deliveryEnd":"2025-05-07T18:15:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T18:15:00Z","deliveryEnd":"2025-05-07T18:30:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T18:30:00Z","deliveryEnd":"2025-05-07T18:45:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T18:45:00Z","deliveryEnd":"2025-05-07T19:00:00Z","entryPerArea":{"FI":158.78}},{"deliveryStart":"2025-05-07T19:00:00Z","deliveryEnd":"2025-05-07T19:15:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T19:15:00Z","deliveryEnd":"2025-05-07T19:30:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T19:30:00Z","deliveryEnd":"2025-05-07T19:45:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T19:45:00Z","deliveryEnd":"2025-05-07T20:00:00Z","entryPerArea":{"FI":138.93}},{"deliveryStart":"2025-05-07T20:00:00Z","deliveryEnd":"2025-05-07T20:15:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T20:15:00Z","deliveryEnd":"2025-05-07T20:30:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T20:30:00Z","deliveryEnd":"2025-05-07T20:45:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T20:45:00Z","deliveryEnd":"2025-05-07T21:00:00Z","entryPerArea":{"FI":109.42}},{"deliveryStart":"2025-05-07T21:00:00Z","deliveryEnd":"2025-05-07T21:15:00Z","entryPerArea":{"FI":94.16}},{"deliveryStart":"2025-05-07T21:15:00Z","deliveryEnd":"2025-05-07T21:30:00Z","entryPerArea":{"FI":94.16}},{"deliveryStart":"2025-05-07T21:30:00Z","deliveryEnd":"2025-05-07T21:45:00Z","entryPerArea":{"FI":94.16}},{"deliveryStart":"2025-05-07T21:45:00Z","deliveryEnd":"2025-05-07T22:00:00Z","entryPerArea":{"FI":94.16}}]}' 18 | headers: 19 | Connection: 20 | - keep-alive 21 | Content-Type: 22 | - application/json; charset=utf-8 23 | Date: 24 | - Wed, 07 May 2025 08:04:51 GMT 25 | Request-Context: 26 | - appId=cid-v1:ddfe5a25-b9d8-4f0e-b951-f04e01c2922f 27 | Set-Cookie: 28 | - route=1746605092.27.29.426492|9898ac1b7e0bd8fc3874537f2a76b591; Expires=Fri, 29 | 09-May-25 08:04:51 GMT; Max-Age=172800; Path=/; Secure; HttpOnly 30 | Strict-Transport-Security: 31 | - max-age=31536000 32 | Transfer-Encoding: 33 | - chunked 34 | Vary: 35 | - Accept-Encoding 36 | content-length: 37 | - '10447' 38 | status: 39 | code: 200 40 | message: OK 41 | version: 1 42 | -------------------------------------------------------------------------------- /tests/test_different_currency.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_different_currency(self): 12 | with vcr.use_cassette("different_currency.yaml"): 13 | elspot = Prices(currency="SEK") 14 | prices = elspot.fetch(elspot.HOURLY, end_date="2025-05-07", areas=["SE1"]) 15 | # pprint(prices) 16 | self.assertEqual( 17 | prices, 18 | { 19 | "areas": { 20 | "SE1": { 21 | "values": [ 22 | { 23 | "end": datetime.datetime( 24 | 2025, 5, 6, 23, 0, tzinfo=utc 25 | ), 26 | "start": datetime.datetime( 27 | 2025, 5, 6, 22, 0, tzinfo=utc 28 | ), 29 | "value": 243.58, 30 | }, 31 | { 32 | "end": datetime.datetime( 33 | 2025, 5, 7, 0, 0, tzinfo=utc 34 | ), 35 | "start": datetime.datetime( 36 | 2025, 5, 6, 23, 0, tzinfo=utc 37 | ), 38 | "value": 155.37, 39 | }, 40 | { 41 | "end": datetime.datetime( 42 | 2025, 5, 7, 1, 0, tzinfo=utc 43 | ), 44 | "start": datetime.datetime( 45 | 2025, 5, 7, 0, 0, tzinfo=utc 46 | ), 47 | "value": 137.16, 48 | }, 49 | { 50 | "end": datetime.datetime( 51 | 2025, 5, 7, 2, 0, tzinfo=utc 52 | ), 53 | "start": datetime.datetime( 54 | 2025, 5, 7, 1, 0, tzinfo=utc 55 | ), 56 | "value": 140.54, 57 | }, 58 | { 59 | "end": datetime.datetime( 60 | 2025, 5, 7, 3, 0, tzinfo=utc 61 | ), 62 | "start": datetime.datetime( 63 | 2025, 5, 7, 2, 0, tzinfo=utc 64 | ), 65 | "value": 211.08, 66 | }, 67 | { 68 | "end": datetime.datetime( 69 | 2025, 5, 7, 4, 0, tzinfo=utc 70 | ), 71 | "start": datetime.datetime( 72 | 2025, 5, 7, 3, 0, tzinfo=utc 73 | ), 74 | "value": 602.94, 75 | }, 76 | { 77 | "end": datetime.datetime( 78 | 2025, 5, 7, 5, 0, tzinfo=utc 79 | ), 80 | "start": datetime.datetime( 81 | 2025, 5, 7, 4, 0, tzinfo=utc 82 | ), 83 | "value": 1218.54, 84 | }, 85 | { 86 | "end": datetime.datetime( 87 | 2025, 5, 7, 6, 0, tzinfo=utc 88 | ), 89 | "start": datetime.datetime( 90 | 2025, 5, 7, 5, 0, tzinfo=utc 91 | ), 92 | "value": 1569.51, 93 | }, 94 | { 95 | "end": datetime.datetime( 96 | 2025, 5, 7, 7, 0, tzinfo=utc 97 | ), 98 | "start": datetime.datetime( 99 | 2025, 5, 7, 6, 0, tzinfo=utc 100 | ), 101 | "value": 1345.01, 102 | }, 103 | { 104 | "end": datetime.datetime( 105 | 2025, 5, 7, 8, 0, tzinfo=utc 106 | ), 107 | "start": datetime.datetime( 108 | 2025, 5, 7, 7, 0, tzinfo=utc 109 | ), 110 | "value": 1005.82, 111 | }, 112 | { 113 | "end": datetime.datetime( 114 | 2025, 5, 7, 9, 0, tzinfo=utc 115 | ), 116 | "start": datetime.datetime( 117 | 2025, 5, 7, 8, 0, tzinfo=utc 118 | ), 119 | "value": 661.49, 120 | }, 121 | { 122 | "end": datetime.datetime( 123 | 2025, 5, 7, 10, 0, tzinfo=utc 124 | ), 125 | "start": datetime.datetime( 126 | 2025, 5, 7, 9, 0, tzinfo=utc 127 | ), 128 | "value": 714.27, 129 | }, 130 | { 131 | "end": datetime.datetime( 132 | 2025, 5, 7, 11, 0, tzinfo=utc 133 | ), 134 | "start": datetime.datetime( 135 | 2025, 5, 7, 10, 0, tzinfo=utc 136 | ), 137 | "value": 622.13, 138 | }, 139 | { 140 | "end": datetime.datetime( 141 | 2025, 5, 7, 12, 0, tzinfo=utc 142 | ), 143 | "start": datetime.datetime( 144 | 2025, 5, 7, 11, 0, tzinfo=utc 145 | ), 146 | "value": 339.85, 147 | }, 148 | { 149 | "end": datetime.datetime( 150 | 2025, 5, 7, 13, 0, tzinfo=utc 151 | ), 152 | "start": datetime.datetime( 153 | 2025, 5, 7, 12, 0, tzinfo=utc 154 | ), 155 | "value": 290.13, 156 | }, 157 | { 158 | "end": datetime.datetime( 159 | 2025, 5, 7, 14, 0, tzinfo=utc 160 | ), 161 | "start": datetime.datetime( 162 | 2025, 5, 7, 13, 0, tzinfo=utc 163 | ), 164 | "value": 266.36, 165 | }, 166 | { 167 | "end": datetime.datetime( 168 | 2025, 5, 7, 15, 0, tzinfo=utc 169 | ), 170 | "start": datetime.datetime( 171 | 2025, 5, 7, 14, 0, tzinfo=utc 172 | ), 173 | "value": 335.6, 174 | }, 175 | { 176 | "end": datetime.datetime( 177 | 2025, 5, 7, 16, 0, tzinfo=utc 178 | ), 179 | "start": datetime.datetime( 180 | 2025, 5, 7, 15, 0, tzinfo=utc 181 | ), 182 | "value": 914.56, 183 | }, 184 | { 185 | "end": datetime.datetime( 186 | 2025, 5, 7, 17, 0, tzinfo=utc 187 | ), 188 | "start": datetime.datetime( 189 | 2025, 5, 7, 16, 0, tzinfo=utc 190 | ), 191 | "value": 1018.14, 192 | }, 193 | { 194 | "end": datetime.datetime( 195 | 2025, 5, 7, 18, 0, tzinfo=utc 196 | ), 197 | "start": datetime.datetime( 198 | 2025, 5, 7, 17, 0, tzinfo=utc 199 | ), 200 | "value": 999.27, 201 | }, 202 | { 203 | "end": datetime.datetime( 204 | 2025, 5, 7, 19, 0, tzinfo=utc 205 | ), 206 | "start": datetime.datetime( 207 | 2025, 5, 7, 18, 0, tzinfo=utc 208 | ), 209 | "value": 970.82, 210 | }, 211 | { 212 | "end": datetime.datetime( 213 | 2025, 5, 7, 20, 0, tzinfo=utc 214 | ), 215 | "start": datetime.datetime( 216 | 2025, 5, 7, 19, 0, tzinfo=utc 217 | ), 218 | "value": 1024.13, 219 | }, 220 | { 221 | "end": datetime.datetime( 222 | 2025, 5, 7, 21, 0, tzinfo=utc 223 | ), 224 | "start": datetime.datetime( 225 | 2025, 5, 7, 20, 0, tzinfo=utc 226 | ), 227 | "value": 1167.07, 228 | }, 229 | { 230 | "end": datetime.datetime( 231 | 2025, 5, 7, 22, 0, tzinfo=utc 232 | ), 233 | "start": datetime.datetime( 234 | 2025, 5, 7, 21, 0, tzinfo=utc 235 | ), 236 | "value": 1026.75, 237 | }, 238 | ] 239 | } 240 | }, 241 | "currency": "SEK", 242 | "end": datetime.datetime(2025, 5, 7, 22, 0, tzinfo=utc), 243 | "start": datetime.datetime(2025, 5, 6, 22, 0, tzinfo=utc), 244 | "updated": datetime.datetime( 245 | 2025, 5, 6, 11, 22, 13, 683352, tzinfo=utc 246 | ), 247 | }, 248 | ) 249 | -------------------------------------------------------------------------------- /tests/test_system_hourly.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_system_hourly(self): 12 | with vcr.use_cassette("system_hourly.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(elspot.HOURLY, end_date="2025-05-07", areas=["SYS"]) 15 | self.assertEqual( 16 | prices, 17 | elspot.hourly("2025-05-07", areas=["SYS"]), 18 | ) 19 | self.assertEqual( 20 | prices, 21 | { 22 | "areas": { 23 | "SYS": { 24 | "values": [ 25 | { 26 | "end": datetime.datetime( 27 | 2025, 5, 6, 23, 0, tzinfo=utc 28 | ), 29 | "start": datetime.datetime( 30 | 2025, 5, 6, 22, 0, tzinfo=utc 31 | ), 32 | "value": 74.2, 33 | }, 34 | { 35 | "end": datetime.datetime( 36 | 2025, 5, 7, 0, 0, tzinfo=utc 37 | ), 38 | "start": datetime.datetime( 39 | 2025, 5, 6, 23, 0, tzinfo=utc 40 | ), 41 | "value": 68.4, 42 | }, 43 | { 44 | "end": datetime.datetime( 45 | 2025, 5, 7, 1, 0, tzinfo=utc 46 | ), 47 | "start": datetime.datetime( 48 | 2025, 5, 7, 0, 0, tzinfo=utc 49 | ), 50 | "value": 67.47, 51 | }, 52 | { 53 | "end": datetime.datetime( 54 | 2025, 5, 7, 2, 0, tzinfo=utc 55 | ), 56 | "start": datetime.datetime( 57 | 2025, 5, 7, 1, 0, tzinfo=utc 58 | ), 59 | "value": 68.04, 60 | }, 61 | { 62 | "end": datetime.datetime( 63 | 2025, 5, 7, 3, 0, tzinfo=utc 64 | ), 65 | "start": datetime.datetime( 66 | 2025, 5, 7, 2, 0, tzinfo=utc 67 | ), 68 | "value": 70.3, 69 | }, 70 | { 71 | "end": datetime.datetime( 72 | 2025, 5, 7, 4, 0, tzinfo=utc 73 | ), 74 | "start": datetime.datetime( 75 | 2025, 5, 7, 3, 0, tzinfo=utc 76 | ), 77 | "value": 87.57, 78 | }, 79 | { 80 | "end": datetime.datetime( 81 | 2025, 5, 7, 5, 0, tzinfo=utc 82 | ), 83 | "start": datetime.datetime( 84 | 2025, 5, 7, 4, 0, tzinfo=utc 85 | ), 86 | "value": 116.11, 87 | }, 88 | { 89 | "end": datetime.datetime( 90 | 2025, 5, 7, 6, 0, tzinfo=utc 91 | ), 92 | "start": datetime.datetime( 93 | 2025, 5, 7, 5, 0, tzinfo=utc 94 | ), 95 | "value": 143.0, 96 | }, 97 | { 98 | "end": datetime.datetime( 99 | 2025, 5, 7, 7, 0, tzinfo=utc 100 | ), 101 | "start": datetime.datetime( 102 | 2025, 5, 7, 6, 0, tzinfo=utc 103 | ), 104 | "value": 123.89, 105 | }, 106 | { 107 | "end": datetime.datetime( 108 | 2025, 5, 7, 8, 0, tzinfo=utc 109 | ), 110 | "start": datetime.datetime( 111 | 2025, 5, 7, 7, 0, tzinfo=utc 112 | ), 113 | "value": 94.98, 114 | }, 115 | { 116 | "end": datetime.datetime( 117 | 2025, 5, 7, 9, 0, tzinfo=utc 118 | ), 119 | "start": datetime.datetime( 120 | 2025, 5, 7, 8, 0, tzinfo=utc 121 | ), 122 | "value": 79.98, 123 | }, 124 | { 125 | "end": datetime.datetime( 126 | 2025, 5, 7, 10, 0, tzinfo=utc 127 | ), 128 | "start": datetime.datetime( 129 | 2025, 5, 7, 9, 0, tzinfo=utc 130 | ), 131 | "value": 74.28, 132 | }, 133 | { 134 | "end": datetime.datetime( 135 | 2025, 5, 7, 11, 0, tzinfo=utc 136 | ), 137 | "start": datetime.datetime( 138 | 2025, 5, 7, 10, 0, tzinfo=utc 139 | ), 140 | "value": 64.68, 141 | }, 142 | { 143 | "end": datetime.datetime( 144 | 2025, 5, 7, 12, 0, tzinfo=utc 145 | ), 146 | "start": datetime.datetime( 147 | 2025, 5, 7, 11, 0, tzinfo=utc 148 | ), 149 | "value": 60.92, 150 | }, 151 | { 152 | "end": datetime.datetime( 153 | 2025, 5, 7, 13, 0, tzinfo=utc 154 | ), 155 | "start": datetime.datetime( 156 | 2025, 5, 7, 12, 0, tzinfo=utc 157 | ), 158 | "value": 62.85, 159 | }, 160 | { 161 | "end": datetime.datetime( 162 | 2025, 5, 7, 14, 0, tzinfo=utc 163 | ), 164 | "start": datetime.datetime( 165 | 2025, 5, 7, 13, 0, tzinfo=utc 166 | ), 167 | "value": 67.29, 168 | }, 169 | { 170 | "end": datetime.datetime( 171 | 2025, 5, 7, 15, 0, tzinfo=utc 172 | ), 173 | "start": datetime.datetime( 174 | 2025, 5, 7, 14, 0, tzinfo=utc 175 | ), 176 | "value": 67.69, 177 | }, 178 | { 179 | "end": datetime.datetime( 180 | 2025, 5, 7, 16, 0, tzinfo=utc 181 | ), 182 | "start": datetime.datetime( 183 | 2025, 5, 7, 15, 0, tzinfo=utc 184 | ), 185 | "value": 86.97, 186 | }, 187 | { 188 | "end": datetime.datetime( 189 | 2025, 5, 7, 17, 0, tzinfo=utc 190 | ), 191 | "start": datetime.datetime( 192 | 2025, 5, 7, 16, 0, tzinfo=utc 193 | ), 194 | "value": 105.3, 195 | }, 196 | { 197 | "end": datetime.datetime( 198 | 2025, 5, 7, 18, 0, tzinfo=utc 199 | ), 200 | "start": datetime.datetime( 201 | 2025, 5, 7, 17, 0, tzinfo=utc 202 | ), 203 | "value": 121.47, 204 | }, 205 | { 206 | "end": datetime.datetime( 207 | 2025, 5, 7, 19, 0, tzinfo=utc 208 | ), 209 | "start": datetime.datetime( 210 | 2025, 5, 7, 18, 0, tzinfo=utc 211 | ), 212 | "value": 132.21, 213 | }, 214 | { 215 | "end": datetime.datetime( 216 | 2025, 5, 7, 20, 0, tzinfo=utc 217 | ), 218 | "start": datetime.datetime( 219 | 2025, 5, 7, 19, 0, tzinfo=utc 220 | ), 221 | "value": 110.74, 222 | }, 223 | { 224 | "end": datetime.datetime( 225 | 2025, 5, 7, 21, 0, tzinfo=utc 226 | ), 227 | "start": datetime.datetime( 228 | 2025, 5, 7, 20, 0, tzinfo=utc 229 | ), 230 | "value": 99.95, 231 | }, 232 | { 233 | "end": datetime.datetime( 234 | 2025, 5, 7, 22, 0, tzinfo=utc 235 | ), 236 | "start": datetime.datetime( 237 | 2025, 5, 7, 21, 0, tzinfo=utc 238 | ), 239 | "value": 86.46, 240 | }, 241 | ] 242 | } 243 | }, 244 | "currency": "EUR", 245 | "end": datetime.datetime(2025, 5, 7, 22, 0, tzinfo=utc), 246 | "start": datetime.datetime(2025, 5, 6, 22, 0, tzinfo=utc), 247 | "updated": datetime.datetime( 248 | 2025, 5, 6, 10, 56, 31, 12006, tzinfo=utc 249 | ), 250 | }, 251 | ) 252 | -------------------------------------------------------------------------------- /tests/test_single_area_hourly.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_single_area_hourly(self): 12 | with vcr.use_cassette("single_area_hourly.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(elspot.HOURLY, end_date="2025-05-07", areas=["FI"]) 15 | self.assertEqual( 16 | prices, 17 | elspot.hourly("2025-05-07", areas=["FI"]), 18 | ) 19 | self.assertEqual( 20 | prices, 21 | { 22 | "areas": { 23 | "FI": { 24 | "values": [ 25 | { 26 | "end": datetime.datetime( 27 | 2025, 5, 6, 23, 0, tzinfo=utc 28 | ), 29 | "start": datetime.datetime( 30 | 2025, 5, 6, 22, 0, tzinfo=utc 31 | ), 32 | "value": 22.34, 33 | }, 34 | { 35 | "end": datetime.datetime( 36 | 2025, 5, 7, 0, 0, tzinfo=utc 37 | ), 38 | "start": datetime.datetime( 39 | 2025, 5, 6, 23, 0, tzinfo=utc 40 | ), 41 | "value": 14.26, 42 | }, 43 | { 44 | "end": datetime.datetime( 45 | 2025, 5, 7, 1, 0, tzinfo=utc 46 | ), 47 | "start": datetime.datetime( 48 | 2025, 5, 7, 0, 0, tzinfo=utc 49 | ), 50 | "value": 12.59, 51 | }, 52 | { 53 | "end": datetime.datetime( 54 | 2025, 5, 7, 2, 0, tzinfo=utc 55 | ), 56 | "start": datetime.datetime( 57 | 2025, 5, 7, 1, 0, tzinfo=utc 58 | ), 59 | "value": 13.69, 60 | }, 61 | { 62 | "end": datetime.datetime( 63 | 2025, 5, 7, 3, 0, tzinfo=utc 64 | ), 65 | "start": datetime.datetime( 66 | 2025, 5, 7, 2, 0, tzinfo=utc 67 | ), 68 | "value": 19.34, 69 | }, 70 | { 71 | "end": datetime.datetime( 72 | 2025, 5, 7, 4, 0, tzinfo=utc 73 | ), 74 | "start": datetime.datetime( 75 | 2025, 5, 7, 3, 0, tzinfo=utc 76 | ), 77 | "value": 55.31, 78 | }, 79 | { 80 | "end": datetime.datetime( 81 | 2025, 5, 7, 5, 0, tzinfo=utc 82 | ), 83 | "start": datetime.datetime( 84 | 2025, 5, 7, 4, 0, tzinfo=utc 85 | ), 86 | "value": 111.77, 87 | }, 88 | { 89 | "end": datetime.datetime( 90 | 2025, 5, 7, 6, 0, tzinfo=utc 91 | ), 92 | "start": datetime.datetime( 93 | 2025, 5, 7, 5, 0, tzinfo=utc 94 | ), 95 | "value": 143.95, 96 | }, 97 | { 98 | "end": datetime.datetime( 99 | 2025, 5, 7, 7, 0, tzinfo=utc 100 | ), 101 | "start": datetime.datetime( 102 | 2025, 5, 7, 6, 0, tzinfo=utc 103 | ), 104 | "value": 123.36, 105 | }, 106 | { 107 | "end": datetime.datetime( 108 | 2025, 5, 7, 8, 0, tzinfo=utc 109 | ), 110 | "start": datetime.datetime( 111 | 2025, 5, 7, 7, 0, tzinfo=utc 112 | ), 113 | "value": 92.48, 114 | }, 115 | { 116 | "end": datetime.datetime( 117 | 2025, 5, 7, 9, 0, tzinfo=utc 118 | ), 119 | "start": datetime.datetime( 120 | 2025, 5, 7, 8, 0, tzinfo=utc 121 | ), 122 | "value": 62.72, 123 | }, 124 | { 125 | "end": datetime.datetime( 126 | 2025, 5, 7, 10, 0, tzinfo=utc 127 | ), 128 | "start": datetime.datetime( 129 | 2025, 5, 7, 9, 0, tzinfo=utc 130 | ), 131 | "value": 66.25, 132 | }, 133 | { 134 | "end": datetime.datetime( 135 | 2025, 5, 7, 11, 0, tzinfo=utc 136 | ), 137 | "start": datetime.datetime( 138 | 2025, 5, 7, 10, 0, tzinfo=utc 139 | ), 140 | "value": 57.84, 141 | }, 142 | { 143 | "end": datetime.datetime( 144 | 2025, 5, 7, 12, 0, tzinfo=utc 145 | ), 146 | "start": datetime.datetime( 147 | 2025, 5, 7, 11, 0, tzinfo=utc 148 | ), 149 | "value": 31.59, 150 | }, 151 | { 152 | "end": datetime.datetime( 153 | 2025, 5, 7, 13, 0, tzinfo=utc 154 | ), 155 | "start": datetime.datetime( 156 | 2025, 5, 7, 12, 0, tzinfo=utc 157 | ), 158 | "value": 27.14, 159 | }, 160 | { 161 | "end": datetime.datetime( 162 | 2025, 5, 7, 14, 0, tzinfo=utc 163 | ), 164 | "start": datetime.datetime( 165 | 2025, 5, 7, 13, 0, tzinfo=utc 166 | ), 167 | "value": 25.0, 168 | }, 169 | { 170 | "end": datetime.datetime( 171 | 2025, 5, 7, 15, 0, tzinfo=utc 172 | ), 173 | "start": datetime.datetime( 174 | 2025, 5, 7, 14, 0, tzinfo=utc 175 | ), 176 | "value": 30.77, 177 | }, 178 | { 179 | "end": datetime.datetime( 180 | 2025, 5, 7, 16, 0, tzinfo=utc 181 | ), 182 | "start": datetime.datetime( 183 | 2025, 5, 7, 15, 0, tzinfo=utc 184 | ), 185 | "value": 83.88, 186 | }, 187 | { 188 | "end": datetime.datetime( 189 | 2025, 5, 7, 17, 0, tzinfo=utc 190 | ), 191 | "start": datetime.datetime( 192 | 2025, 5, 7, 16, 0, tzinfo=utc 193 | ), 194 | "value": 110.57, 195 | }, 196 | { 197 | "end": datetime.datetime( 198 | 2025, 5, 7, 18, 0, tzinfo=utc 199 | ), 200 | "start": datetime.datetime( 201 | 2025, 5, 7, 17, 0, tzinfo=utc 202 | ), 203 | "value": 150.83, 204 | }, 205 | { 206 | "end": datetime.datetime( 207 | 2025, 5, 7, 19, 0, tzinfo=utc 208 | ), 209 | "start": datetime.datetime( 210 | 2025, 5, 7, 18, 0, tzinfo=utc 211 | ), 212 | "value": 158.78, 213 | }, 214 | { 215 | "end": datetime.datetime( 216 | 2025, 5, 7, 20, 0, tzinfo=utc 217 | ), 218 | "start": datetime.datetime( 219 | 2025, 5, 7, 19, 0, tzinfo=utc 220 | ), 221 | "value": 138.93, 222 | }, 223 | { 224 | "end": datetime.datetime( 225 | 2025, 5, 7, 21, 0, tzinfo=utc 226 | ), 227 | "start": datetime.datetime( 228 | 2025, 5, 7, 20, 0, tzinfo=utc 229 | ), 230 | "value": 109.42, 231 | }, 232 | { 233 | "end": datetime.datetime( 234 | 2025, 5, 7, 22, 0, tzinfo=utc 235 | ), 236 | "start": datetime.datetime( 237 | 2025, 5, 7, 21, 0, tzinfo=utc 238 | ), 239 | "value": 94.16, 240 | }, 241 | ] 242 | } 243 | }, 244 | "currency": "EUR", 245 | "end": datetime.datetime(2025, 5, 7, 22, 0, tzinfo=utc), 246 | "start": datetime.datetime(2025, 5, 6, 22, 0, tzinfo=utc), 247 | "updated": datetime.datetime( 248 | 2025, 5, 6, 11, 22, 12, 483319, tzinfo=utc 249 | ), 250 | }, 251 | ) 252 | -------------------------------------------------------------------------------- /nordpool/elspot.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=missing-module-docstring 2 | from datetime import date, datetime, timedelta 3 | 4 | from pytz import utc 5 | import requests 6 | from dateutil.parser import parse as parse_dt 7 | 8 | 9 | class UnsupportedResolution(ValueError): 10 | """ 11 | Raised when the requested resolution is not supported. 12 | Supported resolutions are 15, 30 and 60 minutes. 13 | """ 14 | 15 | 16 | class CurrencyMismatch(ValueError): 17 | """ 18 | Raised when the currency of the data does not match the currency of the request. 19 | """ 20 | 21 | 22 | class Prices: 23 | """Class for fetching Nord Pool Elspot prices.""" 24 | 25 | HOURLY = 10 26 | DAILY = 11 27 | WEEKLY = 12 28 | MONTHLY = 13 29 | YEARLY = 14 30 | 31 | API_URL = "https://dataportal-api.nordpoolgroup.com/api" 32 | 33 | AREAS = [ 34 | # Nordics 35 | "DK1", 36 | "DK2", 37 | "FI", 38 | "NO1", 39 | "NO2", 40 | "NO3", 41 | "NO4", 42 | "NO5", 43 | "SE1", 44 | "SE2", 45 | "SE3", 46 | "SE4", 47 | # Baltic 48 | "EE", 49 | "LT", 50 | "LV", 51 | # Central Western Europe 52 | "AT", 53 | "BE", 54 | "FR", 55 | "GER", 56 | "NL", 57 | "PL", 58 | # South East Europe 59 | "BG", 60 | "TEL", 61 | # Nordic system price 62 | # NOTE: Some API endpoints use "SYSTEM" for "SYS", 63 | # this is handled internally and area "SYS" should be used by external code 64 | "SYS", 65 | ] 66 | 67 | SUPPORTED_RESOLUTIONS = [15, 30, 60] 68 | 69 | def __init__(self, currency="EUR", timeout=None): 70 | self.currency = currency 71 | self.timeout = timeout or 2 72 | 73 | def _parse_json(self, data, data_type, areas): 74 | """ 75 | Parse json response from fetcher. 76 | Returns dictionary with 77 | - start time 78 | - end time 79 | - update time 80 | - currency 81 | - dictionary of areas, based on selection 82 | - list of values (dictionary with start and endtime and value) 83 | - possible other values, such as min, max, average for hourly 84 | 85 | """ 86 | 87 | start_time = datetime( 88 | 2100, 89 | 1, 90 | 1, 91 | tzinfo=utc if data_type == self.HOURLY else None, 92 | ) 93 | end_time = datetime( 94 | 1970, 95 | 1, 96 | 1, 97 | tzinfo=utc if data_type == self.HOURLY else None, 98 | ) 99 | updated = parse_dt(data.get("updatedAt", "1970-01-01")) 100 | currency = data.get("currency", self.currency) 101 | 102 | area_prices = {} 103 | data_source = ("multiIndexEntries", "entryPerArea") # Defaults to HOURLY 104 | if data_type == self.DAILY: 105 | data_source = ("multiAreaDailyAggregates", "averagePerArea") 106 | if data_type == self.WEEKLY: 107 | data_source = ("multiAreaWeeklyAggregates", "averagePerArea") 108 | if data_type == self.MONTHLY: 109 | data_source = ("multiAreaMonthlyAggregates", "averagePerArea") 110 | if data_type == self.YEARLY: 111 | data_source = ("prices", "averagePerArea") 112 | 113 | for entry in data.get(data_source[0], []): 114 | start = parse_dt(entry["deliveryStart"]) 115 | end = parse_dt(entry["deliveryEnd"]) 116 | for area, price in entry.get(data_source[1], {}).items(): 117 | # Price indices -endpoint uses "SYSTEM" for "SYS" 118 | # -> replace it when responding 119 | if area == "SYSTEM": 120 | area = "SYS" 121 | if area not in areas: 122 | continue # pragma: no cover 123 | if area not in area_prices: 124 | area_prices[area] = {"values": []} 125 | area_prices[area]["values"].append( 126 | { 127 | "start": start, 128 | "end": end, 129 | "value": price, 130 | } 131 | ) 132 | start_time = min(start_time, start) 133 | end_time = max(end_time, end) 134 | 135 | # Ensure that the provided currency match the requested one 136 | if currency != self.currency: 137 | raise CurrencyMismatch # pragma: no cover 138 | 139 | if not area_prices: 140 | # No data found, behavior changed when moving to using price indices 141 | return None 142 | 143 | return { 144 | "start": start_time, 145 | "end": end_time, 146 | "updated": updated, 147 | "currency": currency, 148 | "areas": area_prices, 149 | } 150 | 151 | def _get_url_params_areas( 152 | self, 153 | data_type, 154 | end_date=None, 155 | areas=None, 156 | resolution=60, 157 | ): 158 | # If end_date isn't set, default to tomorrow 159 | if end_date is None: 160 | end_date = date.today() + timedelta(days=1) # pragma: no cover 161 | # If end_date isn't a date or datetime object, try to parse a string 162 | if not isinstance(end_date, date) and not isinstance(end_date, datetime): 163 | end_date = parse_dt(end_date) 164 | if areas is None: 165 | areas = self.AREAS # pragma: no cover 166 | if resolution not in self.SUPPORTED_RESOLUTIONS: 167 | raise UnsupportedResolution( 168 | f"Resolution {resolution} is not supported, " 169 | f"must be one of {self.SUPPORTED_RESOLUTIONS}" 170 | ) 171 | 172 | endpoint = "DayAheadPriceIndices" # default to hourly 173 | if data_type in [self.DAILY, self.WEEKLY, self.MONTHLY]: 174 | endpoint = "AggregatePrices" 175 | if data_type == self.YEARLY: 176 | endpoint = "AggregatePrices/GetAnnuals" 177 | 178 | api_url = f"{self.API_URL}/{endpoint}" 179 | params = { 180 | "currency": self.currency, 181 | "market": "DayAhead", 182 | } 183 | 184 | if data_type == self.HOURLY: 185 | params["date"] = end_date.strftime("%Y-%m-%d") 186 | params["resolutionInMinutes"] = resolution 187 | params["indexNames"] = ",".join( 188 | # Price indices -endpoint uses "SYSTEM" for "SYS" 189 | # -> replace it when requesting 190 | "SYSTEM" if area == "SYS" else area 191 | for area in areas 192 | ) 193 | else: 194 | params["deliveryArea"] = ",".join(areas) 195 | if data_type in [self.DAILY, self.WEEKLY, self.MONTHLY]: 196 | params["year"] = end_date.strftime("%Y") 197 | return api_url, params, areas 198 | 199 | def _fetch_json(self, data_type, end_date=None, areas=None, resolution=60): 200 | """Fetch JSON from API""" 201 | api_url, params, areas = self._get_url_params_areas( 202 | data_type, end_date, areas, resolution 203 | ) 204 | response = requests.get( 205 | api_url, 206 | params=params, 207 | timeout=self.timeout, 208 | ) 209 | response.raise_for_status() 210 | if response.status_code == 204: 211 | # "Old" API returns 204 for no data 212 | return None # pragma: no cover 213 | return self._parse_json(response.json(), data_type, areas) 214 | 215 | def fetch(self, data_type=None, end_date=None, areas=None, resolution=60): 216 | """ 217 | Fetch data from API. 218 | Inputs: 219 | - data_type 220 | one of Prices.HOURLY, Prices.DAILY etc 221 | defaults to Prices.HOURLY (used for hourly and sub-hourly data) 222 | - end_date 223 | datetime to end the data fetching 224 | defaults to tomorrow 225 | - areas 226 | list of areas to fetch, such as ['SE1', 'SE2', 'FI'] 227 | defaults to all areas 228 | 229 | Returns dictionary with 230 | - start time 231 | - end time 232 | - update time 233 | - currency 234 | - dictionary of areas, based on selection 235 | - list of values (dictionary with start and endtime and value) 236 | - possible other values, such as min, max, average for hourly 237 | """ 238 | 239 | if data_type is None: 240 | data_type = self.HOURLY 241 | 242 | return self._fetch_json(data_type, end_date, areas, resolution) 243 | 244 | def hourly(self, end_date=None, areas=None): 245 | """Helper to fetch hourly data, see Prices.fetch()""" 246 | return self.fetch(self.HOURLY, end_date, areas) 247 | 248 | def daily(self, end_date=None, areas=None): 249 | """Helper to fetch daily data, see Prices.fetch()""" 250 | return self.fetch(self.DAILY, end_date, areas) 251 | 252 | def weekly(self, end_date=None, areas=None): 253 | """Helper to fetch weekly data, see Prices.fetch()""" 254 | return self.fetch(self.WEEKLY, end_date, areas) 255 | 256 | def monthly(self, end_date=None, areas=None): 257 | """Helper to fetch monthly data, see Prices.fetch()""" 258 | return self.fetch(self.MONTHLY, end_date, areas) 259 | 260 | def yearly(self, end_date=None, areas=None): 261 | """Helper to fetch yearly data, see Prices.fetch()""" 262 | return self.fetch(self.YEARLY, end_date, areas) 263 | 264 | 265 | class AioPrices(Prices): # pragma: no cover 266 | """Class for fetching Nord Pool Elspot prices.""" 267 | 268 | # pylint: disable=invalid-overridden-method 269 | 270 | def __init__(self, currency, client): 271 | 272 | super().__init__(currency) 273 | self.client = client 274 | 275 | async def _io(self, url, params): 276 | import inspect # pylint: disable=import-outside-toplevel 277 | 278 | resp = await self.client.get(url, params=params) 279 | # aiohttp 280 | if inspect.isawaitable(resp.json()): 281 | return await resp.json() 282 | # Httpx and asks 283 | return resp.json() 284 | 285 | async def _fetch_json(self, data_type, end_date=None, areas=None, resolution=60): 286 | """Fetch JSON from API""" 287 | api_url, params, areas = self._get_url_params_areas( 288 | data_type, end_date, areas, resolution 289 | ) 290 | return await self._io( 291 | api_url, 292 | params, 293 | ) 294 | 295 | async def fetch(self, data_type=None, end_date=None, areas=None, resolution=60): 296 | """ 297 | Fetch data from API. 298 | Inputs: 299 | - data_type 300 | API page id, one of Prices.HOURLY, Prices.DAILY etc 301 | defaults to Prices.HOURLY, used for hourly and sub-hourly data 302 | - end_date 303 | datetime to end the data fetching 304 | defaults to tomorrow 305 | - areas 306 | list of areas to fetch, such as ['SE1', 'SE2', 'FI'] 307 | defaults to all areas 308 | Returns dictionary with 309 | - start time 310 | - end time 311 | - update time 312 | - currency 313 | - dictionary of areas, based on selection 314 | - list of values (dictionary with start and endtime and value) 315 | - possible other values, such as min, max, average for hourly 316 | """ 317 | if areas is None: # If no areas are provided, inherit from the parent class 318 | areas = self.AREAS 319 | if data_type is None: 320 | data_type = self.HOURLY 321 | 322 | data = await self._fetch_json( 323 | data_type, 324 | end_date, 325 | areas=areas, 326 | resolution=resolution, 327 | ) 328 | return self._parse_json(data, data_type, areas) 329 | 330 | async def hourly(self, end_date=None, areas=None): 331 | """Helper to fetch hourly data, see Prices.fetch()""" 332 | return await self.fetch(self.HOURLY, end_date, areas) 333 | 334 | async def daily(self, end_date=None, areas=None): 335 | """Helper to fetch daily data, see Prices.fetch()""" 336 | return await self.fetch(self.DAILY, end_date, areas) 337 | 338 | async def weekly(self, end_date=None, areas=None): 339 | """Helper to fetch weekly data, see Prices.fetch()""" 340 | return await self.fetch(self.WEEKLY, end_date, areas) 341 | 342 | async def monthly(self, end_date=None, areas=None): 343 | """Helper to fetch monthly data, see Prices.fetch()""" 344 | return await self.fetch(self.MONTHLY, end_date, areas) 345 | 346 | async def yearly(self, end_date=None, areas=None): 347 | """Helper to fetch yearly data, see Prices.fetch()""" 348 | return await self.fetch(self.YEARLY, end_date, areas) 349 | -------------------------------------------------------------------------------- /tests/test_single_area_30min.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_single_area_30min(self): 12 | with vcr.use_cassette("single_area_30min.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(end_date="2025-05-07", areas=["FI"], resolution=30) 15 | self.assertEqual( 16 | prices, 17 | { 18 | "areas": { 19 | "FI": { 20 | "values": [ 21 | { 22 | "end": datetime.datetime( 23 | 2025, 5, 6, 22, 30, tzinfo=utc 24 | ), 25 | "start": datetime.datetime( 26 | 2025, 5, 6, 22, 0, tzinfo=utc 27 | ), 28 | "value": 22.34, 29 | }, 30 | { 31 | "end": datetime.datetime( 32 | 2025, 5, 6, 23, 0, tzinfo=utc 33 | ), 34 | "start": datetime.datetime( 35 | 2025, 5, 6, 22, 30, tzinfo=utc 36 | ), 37 | "value": 22.34, 38 | }, 39 | { 40 | "end": datetime.datetime( 41 | 2025, 5, 6, 23, 30, tzinfo=utc 42 | ), 43 | "start": datetime.datetime( 44 | 2025, 5, 6, 23, 0, tzinfo=utc 45 | ), 46 | "value": 14.26, 47 | }, 48 | { 49 | "end": datetime.datetime( 50 | 2025, 5, 7, 0, 0, tzinfo=utc 51 | ), 52 | "start": datetime.datetime( 53 | 2025, 5, 6, 23, 30, tzinfo=utc 54 | ), 55 | "value": 14.26, 56 | }, 57 | { 58 | "end": datetime.datetime( 59 | 2025, 5, 7, 0, 30, tzinfo=utc 60 | ), 61 | "start": datetime.datetime( 62 | 2025, 5, 7, 0, 0, tzinfo=utc 63 | ), 64 | "value": 12.59, 65 | }, 66 | { 67 | "end": datetime.datetime( 68 | 2025, 5, 7, 1, 0, tzinfo=utc 69 | ), 70 | "start": datetime.datetime( 71 | 2025, 5, 7, 0, 30, tzinfo=utc 72 | ), 73 | "value": 12.59, 74 | }, 75 | { 76 | "end": datetime.datetime( 77 | 2025, 5, 7, 1, 30, tzinfo=utc 78 | ), 79 | "start": datetime.datetime( 80 | 2025, 5, 7, 1, 0, tzinfo=utc 81 | ), 82 | "value": 13.69, 83 | }, 84 | { 85 | "end": datetime.datetime( 86 | 2025, 5, 7, 2, 0, tzinfo=utc 87 | ), 88 | "start": datetime.datetime( 89 | 2025, 5, 7, 1, 30, tzinfo=utc 90 | ), 91 | "value": 13.69, 92 | }, 93 | { 94 | "end": datetime.datetime( 95 | 2025, 5, 7, 2, 30, tzinfo=utc 96 | ), 97 | "start": datetime.datetime( 98 | 2025, 5, 7, 2, 0, tzinfo=utc 99 | ), 100 | "value": 19.34, 101 | }, 102 | { 103 | "end": datetime.datetime( 104 | 2025, 5, 7, 3, 0, tzinfo=utc 105 | ), 106 | "start": datetime.datetime( 107 | 2025, 5, 7, 2, 30, tzinfo=utc 108 | ), 109 | "value": 19.34, 110 | }, 111 | { 112 | "end": datetime.datetime( 113 | 2025, 5, 7, 3, 30, tzinfo=utc 114 | ), 115 | "start": datetime.datetime( 116 | 2025, 5, 7, 3, 0, tzinfo=utc 117 | ), 118 | "value": 55.31, 119 | }, 120 | { 121 | "end": datetime.datetime( 122 | 2025, 5, 7, 4, 0, tzinfo=utc 123 | ), 124 | "start": datetime.datetime( 125 | 2025, 5, 7, 3, 30, tzinfo=utc 126 | ), 127 | "value": 55.31, 128 | }, 129 | { 130 | "end": datetime.datetime( 131 | 2025, 5, 7, 4, 30, tzinfo=utc 132 | ), 133 | "start": datetime.datetime( 134 | 2025, 5, 7, 4, 0, tzinfo=utc 135 | ), 136 | "value": 111.77, 137 | }, 138 | { 139 | "end": datetime.datetime( 140 | 2025, 5, 7, 5, 0, tzinfo=utc 141 | ), 142 | "start": datetime.datetime( 143 | 2025, 5, 7, 4, 30, tzinfo=utc 144 | ), 145 | "value": 111.77, 146 | }, 147 | { 148 | "end": datetime.datetime( 149 | 2025, 5, 7, 5, 30, tzinfo=utc 150 | ), 151 | "start": datetime.datetime( 152 | 2025, 5, 7, 5, 0, tzinfo=utc 153 | ), 154 | "value": 143.95, 155 | }, 156 | { 157 | "end": datetime.datetime( 158 | 2025, 5, 7, 6, 0, tzinfo=utc 159 | ), 160 | "start": datetime.datetime( 161 | 2025, 5, 7, 5, 30, tzinfo=utc 162 | ), 163 | "value": 143.95, 164 | }, 165 | { 166 | "end": datetime.datetime( 167 | 2025, 5, 7, 6, 30, tzinfo=utc 168 | ), 169 | "start": datetime.datetime( 170 | 2025, 5, 7, 6, 0, tzinfo=utc 171 | ), 172 | "value": 123.36, 173 | }, 174 | { 175 | "end": datetime.datetime( 176 | 2025, 5, 7, 7, 0, tzinfo=utc 177 | ), 178 | "start": datetime.datetime( 179 | 2025, 5, 7, 6, 30, tzinfo=utc 180 | ), 181 | "value": 123.36, 182 | }, 183 | { 184 | "end": datetime.datetime( 185 | 2025, 5, 7, 7, 30, tzinfo=utc 186 | ), 187 | "start": datetime.datetime( 188 | 2025, 5, 7, 7, 0, tzinfo=utc 189 | ), 190 | "value": 92.48, 191 | }, 192 | { 193 | "end": datetime.datetime( 194 | 2025, 5, 7, 8, 0, tzinfo=utc 195 | ), 196 | "start": datetime.datetime( 197 | 2025, 5, 7, 7, 30, tzinfo=utc 198 | ), 199 | "value": 92.48, 200 | }, 201 | { 202 | "end": datetime.datetime( 203 | 2025, 5, 7, 8, 30, tzinfo=utc 204 | ), 205 | "start": datetime.datetime( 206 | 2025, 5, 7, 8, 0, tzinfo=utc 207 | ), 208 | "value": 62.72, 209 | }, 210 | { 211 | "end": datetime.datetime( 212 | 2025, 5, 7, 9, 0, tzinfo=utc 213 | ), 214 | "start": datetime.datetime( 215 | 2025, 5, 7, 8, 30, tzinfo=utc 216 | ), 217 | "value": 62.72, 218 | }, 219 | { 220 | "end": datetime.datetime( 221 | 2025, 5, 7, 9, 30, tzinfo=utc 222 | ), 223 | "start": datetime.datetime( 224 | 2025, 5, 7, 9, 0, tzinfo=utc 225 | ), 226 | "value": 66.25, 227 | }, 228 | { 229 | "end": datetime.datetime( 230 | 2025, 5, 7, 10, 0, tzinfo=utc 231 | ), 232 | "start": datetime.datetime( 233 | 2025, 5, 7, 9, 30, tzinfo=utc 234 | ), 235 | "value": 66.25, 236 | }, 237 | { 238 | "end": datetime.datetime( 239 | 2025, 5, 7, 10, 30, tzinfo=utc 240 | ), 241 | "start": datetime.datetime( 242 | 2025, 5, 7, 10, 0, tzinfo=utc 243 | ), 244 | "value": 57.84, 245 | }, 246 | { 247 | "end": datetime.datetime( 248 | 2025, 5, 7, 11, 0, tzinfo=utc 249 | ), 250 | "start": datetime.datetime( 251 | 2025, 5, 7, 10, 30, tzinfo=utc 252 | ), 253 | "value": 57.84, 254 | }, 255 | { 256 | "end": datetime.datetime( 257 | 2025, 5, 7, 11, 30, tzinfo=utc 258 | ), 259 | "start": datetime.datetime( 260 | 2025, 5, 7, 11, 0, tzinfo=utc 261 | ), 262 | "value": 31.59, 263 | }, 264 | { 265 | "end": datetime.datetime( 266 | 2025, 5, 7, 12, 0, tzinfo=utc 267 | ), 268 | "start": datetime.datetime( 269 | 2025, 5, 7, 11, 30, tzinfo=utc 270 | ), 271 | "value": 31.59, 272 | }, 273 | { 274 | "end": datetime.datetime( 275 | 2025, 5, 7, 12, 30, tzinfo=utc 276 | ), 277 | "start": datetime.datetime( 278 | 2025, 5, 7, 12, 0, tzinfo=utc 279 | ), 280 | "value": 27.14, 281 | }, 282 | { 283 | "end": datetime.datetime( 284 | 2025, 5, 7, 13, 0, tzinfo=utc 285 | ), 286 | "start": datetime.datetime( 287 | 2025, 5, 7, 12, 30, tzinfo=utc 288 | ), 289 | "value": 27.14, 290 | }, 291 | { 292 | "end": datetime.datetime( 293 | 2025, 5, 7, 13, 30, tzinfo=utc 294 | ), 295 | "start": datetime.datetime( 296 | 2025, 5, 7, 13, 0, tzinfo=utc 297 | ), 298 | "value": 25.0, 299 | }, 300 | { 301 | "end": datetime.datetime( 302 | 2025, 5, 7, 14, 0, tzinfo=utc 303 | ), 304 | "start": datetime.datetime( 305 | 2025, 5, 7, 13, 30, tzinfo=utc 306 | ), 307 | "value": 25.0, 308 | }, 309 | { 310 | "end": datetime.datetime( 311 | 2025, 5, 7, 14, 30, tzinfo=utc 312 | ), 313 | "start": datetime.datetime( 314 | 2025, 5, 7, 14, 0, tzinfo=utc 315 | ), 316 | "value": 30.77, 317 | }, 318 | { 319 | "end": datetime.datetime( 320 | 2025, 5, 7, 15, 0, tzinfo=utc 321 | ), 322 | "start": datetime.datetime( 323 | 2025, 5, 7, 14, 30, tzinfo=utc 324 | ), 325 | "value": 30.77, 326 | }, 327 | { 328 | "end": datetime.datetime( 329 | 2025, 5, 7, 15, 30, tzinfo=utc 330 | ), 331 | "start": datetime.datetime( 332 | 2025, 5, 7, 15, 0, tzinfo=utc 333 | ), 334 | "value": 83.88, 335 | }, 336 | { 337 | "end": datetime.datetime( 338 | 2025, 5, 7, 16, 0, tzinfo=utc 339 | ), 340 | "start": datetime.datetime( 341 | 2025, 5, 7, 15, 30, tzinfo=utc 342 | ), 343 | "value": 83.88, 344 | }, 345 | { 346 | "end": datetime.datetime( 347 | 2025, 5, 7, 16, 30, tzinfo=utc 348 | ), 349 | "start": datetime.datetime( 350 | 2025, 5, 7, 16, 0, tzinfo=utc 351 | ), 352 | "value": 110.57, 353 | }, 354 | { 355 | "end": datetime.datetime( 356 | 2025, 5, 7, 17, 0, tzinfo=utc 357 | ), 358 | "start": datetime.datetime( 359 | 2025, 5, 7, 16, 30, tzinfo=utc 360 | ), 361 | "value": 110.57, 362 | }, 363 | { 364 | "end": datetime.datetime( 365 | 2025, 5, 7, 17, 30, tzinfo=utc 366 | ), 367 | "start": datetime.datetime( 368 | 2025, 5, 7, 17, 0, tzinfo=utc 369 | ), 370 | "value": 150.83, 371 | }, 372 | { 373 | "end": datetime.datetime( 374 | 2025, 5, 7, 18, 0, tzinfo=utc 375 | ), 376 | "start": datetime.datetime( 377 | 2025, 5, 7, 17, 30, tzinfo=utc 378 | ), 379 | "value": 150.83, 380 | }, 381 | { 382 | "end": datetime.datetime( 383 | 2025, 5, 7, 18, 30, tzinfo=utc 384 | ), 385 | "start": datetime.datetime( 386 | 2025, 5, 7, 18, 0, tzinfo=utc 387 | ), 388 | "value": 158.78, 389 | }, 390 | { 391 | "end": datetime.datetime( 392 | 2025, 5, 7, 19, 0, tzinfo=utc 393 | ), 394 | "start": datetime.datetime( 395 | 2025, 5, 7, 18, 30, tzinfo=utc 396 | ), 397 | "value": 158.78, 398 | }, 399 | { 400 | "end": datetime.datetime( 401 | 2025, 5, 7, 19, 30, tzinfo=utc 402 | ), 403 | "start": datetime.datetime( 404 | 2025, 5, 7, 19, 0, tzinfo=utc 405 | ), 406 | "value": 138.93, 407 | }, 408 | { 409 | "end": datetime.datetime( 410 | 2025, 5, 7, 20, 0, tzinfo=utc 411 | ), 412 | "start": datetime.datetime( 413 | 2025, 5, 7, 19, 30, tzinfo=utc 414 | ), 415 | "value": 138.93, 416 | }, 417 | { 418 | "end": datetime.datetime( 419 | 2025, 5, 7, 20, 30, tzinfo=utc 420 | ), 421 | "start": datetime.datetime( 422 | 2025, 5, 7, 20, 0, tzinfo=utc 423 | ), 424 | "value": 109.42, 425 | }, 426 | { 427 | "end": datetime.datetime( 428 | 2025, 5, 7, 21, 0, tzinfo=utc 429 | ), 430 | "start": datetime.datetime( 431 | 2025, 5, 7, 20, 30, tzinfo=utc 432 | ), 433 | "value": 109.42, 434 | }, 435 | { 436 | "end": datetime.datetime( 437 | 2025, 5, 7, 21, 30, tzinfo=utc 438 | ), 439 | "start": datetime.datetime( 440 | 2025, 5, 7, 21, 0, tzinfo=utc 441 | ), 442 | "value": 94.16, 443 | }, 444 | { 445 | "end": datetime.datetime( 446 | 2025, 5, 7, 22, 0, tzinfo=utc 447 | ), 448 | "start": datetime.datetime( 449 | 2025, 5, 7, 21, 30, tzinfo=utc 450 | ), 451 | "value": 94.16, 452 | }, 453 | ] 454 | } 455 | }, 456 | "currency": "EUR", 457 | "end": datetime.datetime(2025, 5, 7, 22, 0, tzinfo=utc), 458 | "start": datetime.datetime(2025, 5, 6, 22, 0, tzinfo=utc), 459 | "updated": datetime.datetime( 460 | 2025, 5, 6, 11, 22, 10, 872203, tzinfo=utc 461 | ), 462 | }, 463 | ) 464 | -------------------------------------------------------------------------------- /tests/test_single_area_daily.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | from nordpool.elspot import Prices 4 | from pytz import utc 5 | from ._utils import vcr 6 | 7 | 8 | class ElspotTestCase(unittest.TestCase): 9 | maxDiff = None 10 | 11 | def test_single_area_daily(self): 12 | with vcr.use_cassette("single_area_daily.yaml"): 13 | elspot = Prices() 14 | prices = elspot.fetch(elspot.DAILY, end_date="2025-05-07", areas=["FI"]) 15 | self.assertEqual( 16 | prices, 17 | elspot.daily("2025-05-07", areas=["FI"]), 18 | ) 19 | self.assertEqual( 20 | prices, 21 | { 22 | "areas": { 23 | "FI": { 24 | "values": [ 25 | { 26 | "end": datetime.datetime(2025, 5, 7, 0, 0), 27 | "start": datetime.datetime(2025, 5, 7, 0, 0), 28 | "value": 73.21, 29 | }, 30 | { 31 | "end": datetime.datetime(2025, 5, 6, 0, 0), 32 | "start": datetime.datetime(2025, 5, 6, 0, 0), 33 | "value": 30.73, 34 | }, 35 | { 36 | "end": datetime.datetime(2025, 5, 5, 0, 0), 37 | "start": datetime.datetime(2025, 5, 5, 0, 0), 38 | "value": 27.94, 39 | }, 40 | { 41 | "end": datetime.datetime(2025, 5, 4, 0, 0), 42 | "start": datetime.datetime(2025, 5, 4, 0, 0), 43 | "value": 1.53, 44 | }, 45 | { 46 | "end": datetime.datetime(2025, 5, 3, 0, 0), 47 | "start": datetime.datetime(2025, 5, 3, 0, 0), 48 | "value": 0.99, 49 | }, 50 | { 51 | "end": datetime.datetime(2025, 5, 2, 0, 0), 52 | "start": datetime.datetime(2025, 5, 2, 0, 0), 53 | "value": 1.19, 54 | }, 55 | { 56 | "end": datetime.datetime(2025, 5, 1, 0, 0), 57 | "start": datetime.datetime(2025, 5, 1, 0, 0), 58 | "value": 13.37, 59 | }, 60 | { 61 | "end": datetime.datetime(2025, 4, 30, 0, 0), 62 | "start": datetime.datetime(2025, 4, 30, 0, 0), 63 | "value": 155.06, 64 | }, 65 | { 66 | "end": datetime.datetime(2025, 4, 29, 0, 0), 67 | "start": datetime.datetime(2025, 4, 29, 0, 0), 68 | "value": 51.61, 69 | }, 70 | { 71 | "end": datetime.datetime(2025, 4, 28, 0, 0), 72 | "start": datetime.datetime(2025, 4, 28, 0, 0), 73 | "value": 49.47, 74 | }, 75 | { 76 | "end": datetime.datetime(2025, 4, 27, 0, 0), 77 | "start": datetime.datetime(2025, 4, 27, 0, 0), 78 | "value": 53.52, 79 | }, 80 | { 81 | "end": datetime.datetime(2025, 4, 26, 0, 0), 82 | "start": datetime.datetime(2025, 4, 26, 0, 0), 83 | "value": 29.63, 84 | }, 85 | { 86 | "end": datetime.datetime(2025, 4, 25, 0, 0), 87 | "start": datetime.datetime(2025, 4, 25, 0, 0), 88 | "value": 90.25, 89 | }, 90 | { 91 | "end": datetime.datetime(2025, 4, 24, 0, 0), 92 | "start": datetime.datetime(2025, 4, 24, 0, 0), 93 | "value": 169.18, 94 | }, 95 | { 96 | "end": datetime.datetime(2025, 4, 23, 0, 0), 97 | "start": datetime.datetime(2025, 4, 23, 0, 0), 98 | "value": 88.93, 99 | }, 100 | { 101 | "end": datetime.datetime(2025, 4, 22, 0, 0), 102 | "start": datetime.datetime(2025, 4, 22, 0, 0), 103 | "value": 183.05, 104 | }, 105 | { 106 | "end": datetime.datetime(2025, 4, 21, 0, 0), 107 | "start": datetime.datetime(2025, 4, 21, 0, 0), 108 | "value": 50.95, 109 | }, 110 | { 111 | "end": datetime.datetime(2025, 4, 20, 0, 0), 112 | "start": datetime.datetime(2025, 4, 20, 0, 0), 113 | "value": 13.38, 114 | }, 115 | { 116 | "end": datetime.datetime(2025, 4, 19, 0, 0), 117 | "start": datetime.datetime(2025, 4, 19, 0, 0), 118 | "value": 51.08, 119 | }, 120 | { 121 | "end": datetime.datetime(2025, 4, 18, 0, 0), 122 | "start": datetime.datetime(2025, 4, 18, 0, 0), 123 | "value": 26.1, 124 | }, 125 | { 126 | "end": datetime.datetime(2025, 4, 17, 0, 0), 127 | "start": datetime.datetime(2025, 4, 17, 0, 0), 128 | "value": 79.19, 129 | }, 130 | { 131 | "end": datetime.datetime(2025, 4, 16, 0, 0), 132 | "start": datetime.datetime(2025, 4, 16, 0, 0), 133 | "value": 12.84, 134 | }, 135 | { 136 | "end": datetime.datetime(2025, 4, 15, 0, 0), 137 | "start": datetime.datetime(2025, 4, 15, 0, 0), 138 | "value": 23.46, 139 | }, 140 | { 141 | "end": datetime.datetime(2025, 4, 14, 0, 0), 142 | "start": datetime.datetime(2025, 4, 14, 0, 0), 143 | "value": 4.08, 144 | }, 145 | { 146 | "end": datetime.datetime(2025, 4, 13, 0, 0), 147 | "start": datetime.datetime(2025, 4, 13, 0, 0), 148 | "value": 2.24, 149 | }, 150 | { 151 | "end": datetime.datetime(2025, 4, 12, 0, 0), 152 | "start": datetime.datetime(2025, 4, 12, 0, 0), 153 | "value": 4.03, 154 | }, 155 | { 156 | "end": datetime.datetime(2025, 4, 11, 0, 0), 157 | "start": datetime.datetime(2025, 4, 11, 0, 0), 158 | "value": 46.26, 159 | }, 160 | { 161 | "end": datetime.datetime(2025, 4, 10, 0, 0), 162 | "start": datetime.datetime(2025, 4, 10, 0, 0), 163 | "value": 39.33, 164 | }, 165 | { 166 | "end": datetime.datetime(2025, 4, 9, 0, 0), 167 | "start": datetime.datetime(2025, 4, 9, 0, 0), 168 | "value": 1.03, 169 | }, 170 | { 171 | "end": datetime.datetime(2025, 4, 8, 0, 0), 172 | "start": datetime.datetime(2025, 4, 8, 0, 0), 173 | "value": 45.97, 174 | }, 175 | { 176 | "end": datetime.datetime(2025, 4, 7, 0, 0), 177 | "start": datetime.datetime(2025, 4, 7, 0, 0), 178 | "value": 72.79, 179 | }, 180 | { 181 | "end": datetime.datetime(2025, 4, 6, 0, 0), 182 | "start": datetime.datetime(2025, 4, 6, 0, 0), 183 | "value": 50.52, 184 | }, 185 | { 186 | "end": datetime.datetime(2025, 4, 5, 0, 0), 187 | "start": datetime.datetime(2025, 4, 5, 0, 0), 188 | "value": 17.46, 189 | }, 190 | { 191 | "end": datetime.datetime(2025, 4, 4, 0, 0), 192 | "start": datetime.datetime(2025, 4, 4, 0, 0), 193 | "value": -0.49, 194 | }, 195 | { 196 | "end": datetime.datetime(2025, 4, 3, 0, 0), 197 | "start": datetime.datetime(2025, 4, 3, 0, 0), 198 | "value": -1.33, 199 | }, 200 | { 201 | "end": datetime.datetime(2025, 4, 2, 0, 0), 202 | "start": datetime.datetime(2025, 4, 2, 0, 0), 203 | "value": 0.97, 204 | }, 205 | { 206 | "end": datetime.datetime(2025, 4, 1, 0, 0), 207 | "start": datetime.datetime(2025, 4, 1, 0, 0), 208 | "value": 21.95, 209 | }, 210 | { 211 | "end": datetime.datetime(2025, 3, 31, 0, 0), 212 | "start": datetime.datetime(2025, 3, 31, 0, 0), 213 | "value": 119.93, 214 | }, 215 | { 216 | "end": datetime.datetime(2025, 3, 30, 0, 0), 217 | "start": datetime.datetime(2025, 3, 30, 0, 0), 218 | "value": 57.9, 219 | }, 220 | { 221 | "end": datetime.datetime(2025, 3, 29, 0, 0), 222 | "start": datetime.datetime(2025, 3, 29, 0, 0), 223 | "value": 1.65, 224 | }, 225 | { 226 | "end": datetime.datetime(2025, 3, 28, 0, 0), 227 | "start": datetime.datetime(2025, 3, 28, 0, 0), 228 | "value": 3.38, 229 | }, 230 | { 231 | "end": datetime.datetime(2025, 3, 27, 0, 0), 232 | "start": datetime.datetime(2025, 3, 27, 0, 0), 233 | "value": 2.97, 234 | }, 235 | { 236 | "end": datetime.datetime(2025, 3, 26, 0, 0), 237 | "start": datetime.datetime(2025, 3, 26, 0, 0), 238 | "value": 80.37, 239 | }, 240 | { 241 | "end": datetime.datetime(2025, 3, 25, 0, 0), 242 | "start": datetime.datetime(2025, 3, 25, 0, 0), 243 | "value": 32.32, 244 | }, 245 | { 246 | "end": datetime.datetime(2025, 3, 24, 0, 0), 247 | "start": datetime.datetime(2025, 3, 24, 0, 0), 248 | "value": 12.96, 249 | }, 250 | { 251 | "end": datetime.datetime(2025, 3, 23, 0, 0), 252 | "start": datetime.datetime(2025, 3, 23, 0, 0), 253 | "value": 5.54, 254 | }, 255 | { 256 | "end": datetime.datetime(2025, 3, 22, 0, 0), 257 | "start": datetime.datetime(2025, 3, 22, 0, 0), 258 | "value": 0.62, 259 | }, 260 | { 261 | "end": datetime.datetime(2025, 3, 21, 0, 0), 262 | "start": datetime.datetime(2025, 3, 21, 0, 0), 263 | "value": 97.53, 264 | }, 265 | { 266 | "end": datetime.datetime(2025, 3, 20, 0, 0), 267 | "start": datetime.datetime(2025, 3, 20, 0, 0), 268 | "value": 93.3, 269 | }, 270 | { 271 | "end": datetime.datetime(2025, 3, 19, 0, 0), 272 | "start": datetime.datetime(2025, 3, 19, 0, 0), 273 | "value": 21.98, 274 | }, 275 | { 276 | "end": datetime.datetime(2025, 3, 18, 0, 0), 277 | "start": datetime.datetime(2025, 3, 18, 0, 0), 278 | "value": 29.36, 279 | }, 280 | { 281 | "end": datetime.datetime(2025, 3, 17, 0, 0), 282 | "start": datetime.datetime(2025, 3, 17, 0, 0), 283 | "value": 64.88, 284 | }, 285 | { 286 | "end": datetime.datetime(2025, 3, 16, 0, 0), 287 | "start": datetime.datetime(2025, 3, 16, 0, 0), 288 | "value": 8.22, 289 | }, 290 | { 291 | "end": datetime.datetime(2025, 3, 15, 0, 0), 292 | "start": datetime.datetime(2025, 3, 15, 0, 0), 293 | "value": 3.28, 294 | }, 295 | { 296 | "end": datetime.datetime(2025, 3, 14, 0, 0), 297 | "start": datetime.datetime(2025, 3, 14, 0, 0), 298 | "value": 87.25, 299 | }, 300 | { 301 | "end": datetime.datetime(2025, 3, 13, 0, 0), 302 | "start": datetime.datetime(2025, 3, 13, 0, 0), 303 | "value": 172.49, 304 | }, 305 | { 306 | "end": datetime.datetime(2025, 3, 12, 0, 0), 307 | "start": datetime.datetime(2025, 3, 12, 0, 0), 308 | "value": 148.08, 309 | }, 310 | { 311 | "end": datetime.datetime(2025, 3, 11, 0, 0), 312 | "start": datetime.datetime(2025, 3, 11, 0, 0), 313 | "value": 101.76, 314 | }, 315 | { 316 | "end": datetime.datetime(2025, 3, 10, 0, 0), 317 | "start": datetime.datetime(2025, 3, 10, 0, 0), 318 | "value": 100.1, 319 | }, 320 | { 321 | "end": datetime.datetime(2025, 3, 9, 0, 0), 322 | "start": datetime.datetime(2025, 3, 9, 0, 0), 323 | "value": 75.21, 324 | }, 325 | { 326 | "end": datetime.datetime(2025, 3, 8, 0, 0), 327 | "start": datetime.datetime(2025, 3, 8, 0, 0), 328 | "value": 0.15, 329 | }, 330 | { 331 | "end": datetime.datetime(2025, 3, 7, 0, 0), 332 | "start": datetime.datetime(2025, 3, 7, 0, 0), 333 | "value": 48.59, 334 | }, 335 | { 336 | "end": datetime.datetime(2025, 3, 6, 0, 0), 337 | "start": datetime.datetime(2025, 3, 6, 0, 0), 338 | "value": 11.67, 339 | }, 340 | { 341 | "end": datetime.datetime(2025, 3, 5, 0, 0), 342 | "start": datetime.datetime(2025, 3, 5, 0, 0), 343 | "value": 1.56, 344 | }, 345 | { 346 | "end": datetime.datetime(2025, 3, 4, 0, 0), 347 | "start": datetime.datetime(2025, 3, 4, 0, 0), 348 | "value": 5.48, 349 | }, 350 | { 351 | "end": datetime.datetime(2025, 3, 3, 0, 0), 352 | "start": datetime.datetime(2025, 3, 3, 0, 0), 353 | "value": 4.39, 354 | }, 355 | { 356 | "end": datetime.datetime(2025, 3, 2, 0, 0), 357 | "start": datetime.datetime(2025, 3, 2, 0, 0), 358 | "value": 2.23, 359 | }, 360 | { 361 | "end": datetime.datetime(2025, 3, 1, 0, 0), 362 | "start": datetime.datetime(2025, 3, 1, 0, 0), 363 | "value": 78.48, 364 | }, 365 | { 366 | "end": datetime.datetime(2025, 2, 28, 0, 0), 367 | "start": datetime.datetime(2025, 2, 28, 0, 0), 368 | "value": 63.62, 369 | }, 370 | { 371 | "end": datetime.datetime(2025, 2, 27, 0, 0), 372 | "start": datetime.datetime(2025, 2, 27, 0, 0), 373 | "value": 34.53, 374 | }, 375 | { 376 | "end": datetime.datetime(2025, 2, 26, 0, 0), 377 | "start": datetime.datetime(2025, 2, 26, 0, 0), 378 | "value": 31, 379 | }, 380 | { 381 | "end": datetime.datetime(2025, 2, 25, 0, 0), 382 | "start": datetime.datetime(2025, 2, 25, 0, 0), 383 | "value": 4.9, 384 | }, 385 | { 386 | "end": datetime.datetime(2025, 2, 24, 0, 0), 387 | "start": datetime.datetime(2025, 2, 24, 0, 0), 388 | "value": 2.37, 389 | }, 390 | { 391 | "end": datetime.datetime(2025, 2, 23, 0, 0), 392 | "start": datetime.datetime(2025, 2, 23, 0, 0), 393 | "value": 2.5, 394 | }, 395 | { 396 | "end": datetime.datetime(2025, 2, 22, 0, 0), 397 | "start": datetime.datetime(2025, 2, 22, 0, 0), 398 | "value": 1.65, 399 | }, 400 | { 401 | "end": datetime.datetime(2025, 2, 21, 0, 0), 402 | "start": datetime.datetime(2025, 2, 21, 0, 0), 403 | "value": 2.17, 404 | }, 405 | { 406 | "end": datetime.datetime(2025, 2, 20, 0, 0), 407 | "start": datetime.datetime(2025, 2, 20, 0, 0), 408 | "value": 19.14, 409 | }, 410 | { 411 | "end": datetime.datetime(2025, 2, 19, 0, 0), 412 | "start": datetime.datetime(2025, 2, 19, 0, 0), 413 | "value": 75.67, 414 | }, 415 | { 416 | "end": datetime.datetime(2025, 2, 18, 0, 0), 417 | "start": datetime.datetime(2025, 2, 18, 0, 0), 418 | "value": 21.69, 419 | }, 420 | { 421 | "end": datetime.datetime(2025, 2, 17, 0, 0), 422 | "start": datetime.datetime(2025, 2, 17, 0, 0), 423 | "value": 125.23, 424 | }, 425 | { 426 | "end": datetime.datetime(2025, 2, 16, 0, 0), 427 | "start": datetime.datetime(2025, 2, 16, 0, 0), 428 | "value": 120.21, 429 | }, 430 | { 431 | "end": datetime.datetime(2025, 2, 15, 0, 0), 432 | "start": datetime.datetime(2025, 2, 15, 0, 0), 433 | "value": 60.17, 434 | }, 435 | { 436 | "end": datetime.datetime(2025, 2, 14, 0, 0), 437 | "start": datetime.datetime(2025, 2, 14, 0, 0), 438 | "value": 156.86, 439 | }, 440 | { 441 | "end": datetime.datetime(2025, 2, 13, 0, 0), 442 | "start": datetime.datetime(2025, 2, 13, 0, 0), 443 | "value": 79.96, 444 | }, 445 | { 446 | "end": datetime.datetime(2025, 2, 12, 0, 0), 447 | "start": datetime.datetime(2025, 2, 12, 0, 0), 448 | "value": 72.07, 449 | }, 450 | { 451 | "end": datetime.datetime(2025, 2, 11, 0, 0), 452 | "start": datetime.datetime(2025, 2, 11, 0, 0), 453 | "value": 41.48, 454 | }, 455 | { 456 | "end": datetime.datetime(2025, 2, 10, 0, 0), 457 | "start": datetime.datetime(2025, 2, 10, 0, 0), 458 | "value": 72.47, 459 | }, 460 | { 461 | "end": datetime.datetime(2025, 2, 9, 0, 0), 462 | "start": datetime.datetime(2025, 2, 9, 0, 0), 463 | "value": 8.83, 464 | }, 465 | { 466 | "end": datetime.datetime(2025, 2, 8, 0, 0), 467 | "start": datetime.datetime(2025, 2, 8, 0, 0), 468 | "value": 36.65, 469 | }, 470 | { 471 | "end": datetime.datetime(2025, 2, 7, 0, 0), 472 | "start": datetime.datetime(2025, 2, 7, 0, 0), 473 | "value": 9.62, 474 | }, 475 | { 476 | "end": datetime.datetime(2025, 2, 6, 0, 0), 477 | "start": datetime.datetime(2025, 2, 6, 0, 0), 478 | "value": 55.95, 479 | }, 480 | { 481 | "end": datetime.datetime(2025, 2, 5, 0, 0), 482 | "start": datetime.datetime(2025, 2, 5, 0, 0), 483 | "value": 7.03, 484 | }, 485 | { 486 | "end": datetime.datetime(2025, 2, 4, 0, 0), 487 | "start": datetime.datetime(2025, 2, 4, 0, 0), 488 | "value": 84.21, 489 | }, 490 | { 491 | "end": datetime.datetime(2025, 2, 3, 0, 0), 492 | "start": datetime.datetime(2025, 2, 3, 0, 0), 493 | "value": 108.11, 494 | }, 495 | { 496 | "end": datetime.datetime(2025, 2, 2, 0, 0), 497 | "start": datetime.datetime(2025, 2, 2, 0, 0), 498 | "value": 16, 499 | }, 500 | { 501 | "end": datetime.datetime(2025, 2, 1, 0, 0), 502 | "start": datetime.datetime(2025, 2, 1, 0, 0), 503 | "value": 10.1, 504 | }, 505 | { 506 | "end": datetime.datetime(2025, 1, 31, 0, 0), 507 | "start": datetime.datetime(2025, 1, 31, 0, 0), 508 | "value": 52.91, 509 | }, 510 | { 511 | "end": datetime.datetime(2025, 1, 30, 0, 0), 512 | "start": datetime.datetime(2025, 1, 30, 0, 0), 513 | "value": 26.39, 514 | }, 515 | { 516 | "end": datetime.datetime(2025, 1, 29, 0, 0), 517 | "start": datetime.datetime(2025, 1, 29, 0, 0), 518 | "value": 53.54, 519 | }, 520 | { 521 | "end": datetime.datetime(2025, 1, 28, 0, 0), 522 | "start": datetime.datetime(2025, 1, 28, 0, 0), 523 | "value": 61.27, 524 | }, 525 | { 526 | "end": datetime.datetime(2025, 1, 27, 0, 0), 527 | "start": datetime.datetime(2025, 1, 27, 0, 0), 528 | "value": 57.24, 529 | }, 530 | { 531 | "end": datetime.datetime(2025, 1, 26, 0, 0), 532 | "start": datetime.datetime(2025, 1, 26, 0, 0), 533 | "value": 14.71, 534 | }, 535 | { 536 | "end": datetime.datetime(2025, 1, 25, 0, 0), 537 | "start": datetime.datetime(2025, 1, 25, 0, 0), 538 | "value": 2.01, 539 | }, 540 | { 541 | "end": datetime.datetime(2025, 1, 24, 0, 0), 542 | "start": datetime.datetime(2025, 1, 24, 0, 0), 543 | "value": 29.16, 544 | }, 545 | { 546 | "end": datetime.datetime(2025, 1, 23, 0, 0), 547 | "start": datetime.datetime(2025, 1, 23, 0, 0), 548 | "value": 87.48, 549 | }, 550 | { 551 | "end": datetime.datetime(2025, 1, 22, 0, 0), 552 | "start": datetime.datetime(2025, 1, 22, 0, 0), 553 | "value": 120.31, 554 | }, 555 | { 556 | "end": datetime.datetime(2025, 1, 21, 0, 0), 557 | "start": datetime.datetime(2025, 1, 21, 0, 0), 558 | "value": 48.5, 559 | }, 560 | { 561 | "end": datetime.datetime(2025, 1, 20, 0, 0), 562 | "start": datetime.datetime(2025, 1, 20, 0, 0), 563 | "value": 140.86, 564 | }, 565 | { 566 | "end": datetime.datetime(2025, 1, 19, 0, 0), 567 | "start": datetime.datetime(2025, 1, 19, 0, 0), 568 | "value": 4.68, 569 | }, 570 | { 571 | "end": datetime.datetime(2025, 1, 18, 0, 0), 572 | "start": datetime.datetime(2025, 1, 18, 0, 0), 573 | "value": 3.39, 574 | }, 575 | { 576 | "end": datetime.datetime(2025, 1, 17, 0, 0), 577 | "start": datetime.datetime(2025, 1, 17, 0, 0), 578 | "value": 2.62, 579 | }, 580 | { 581 | "end": datetime.datetime(2025, 1, 16, 0, 0), 582 | "start": datetime.datetime(2025, 1, 16, 0, 0), 583 | "value": 1.69, 584 | }, 585 | { 586 | "end": datetime.datetime(2025, 1, 15, 0, 0), 587 | "start": datetime.datetime(2025, 1, 15, 0, 0), 588 | "value": 43.44, 589 | }, 590 | { 591 | "end": datetime.datetime(2025, 1, 14, 0, 0), 592 | "start": datetime.datetime(2025, 1, 14, 0, 0), 593 | "value": 5.63, 594 | }, 595 | { 596 | "end": datetime.datetime(2025, 1, 13, 0, 0), 597 | "start": datetime.datetime(2025, 1, 13, 0, 0), 598 | "value": 11.9, 599 | }, 600 | { 601 | "end": datetime.datetime(2025, 1, 12, 0, 0), 602 | "start": datetime.datetime(2025, 1, 12, 0, 0), 603 | "value": 62.96, 604 | }, 605 | { 606 | "end": datetime.datetime(2025, 1, 11, 0, 0), 607 | "start": datetime.datetime(2025, 1, 11, 0, 0), 608 | "value": 37.07, 609 | }, 610 | { 611 | "end": datetime.datetime(2025, 1, 10, 0, 0), 612 | "start": datetime.datetime(2025, 1, 10, 0, 0), 613 | "value": 92.49, 614 | }, 615 | { 616 | "end": datetime.datetime(2025, 1, 9, 0, 0), 617 | "start": datetime.datetime(2025, 1, 9, 0, 0), 618 | "value": 103.74, 619 | }, 620 | { 621 | "end": datetime.datetime(2025, 1, 8, 0, 0), 622 | "start": datetime.datetime(2025, 1, 8, 0, 0), 623 | "value": 63.87, 624 | }, 625 | { 626 | "end": datetime.datetime(2025, 1, 7, 0, 0), 627 | "start": datetime.datetime(2025, 1, 7, 0, 0), 628 | "value": 19.68, 629 | }, 630 | { 631 | "end": datetime.datetime(2025, 1, 6, 0, 0), 632 | "start": datetime.datetime(2025, 1, 6, 0, 0), 633 | "value": 79.23, 634 | }, 635 | { 636 | "end": datetime.datetime(2025, 1, 5, 0, 0), 637 | "start": datetime.datetime(2025, 1, 5, 0, 0), 638 | "value": 72.32, 639 | }, 640 | { 641 | "end": datetime.datetime(2025, 1, 4, 0, 0), 642 | "start": datetime.datetime(2025, 1, 4, 0, 0), 643 | "value": 95.22, 644 | }, 645 | { 646 | "end": datetime.datetime(2025, 1, 3, 0, 0), 647 | "start": datetime.datetime(2025, 1, 3, 0, 0), 648 | "value": 88.98, 649 | }, 650 | { 651 | "end": datetime.datetime(2025, 1, 2, 0, 0), 652 | "start": datetime.datetime(2025, 1, 2, 0, 0), 653 | "value": 93.6, 654 | }, 655 | { 656 | "end": datetime.datetime(2025, 1, 1, 0, 0), 657 | "start": datetime.datetime(2025, 1, 1, 0, 0), 658 | "value": 60.57, 659 | }, 660 | ] 661 | } 662 | }, 663 | "currency": "EUR", 664 | "end": datetime.datetime(2025, 5, 7, 0, 0), 665 | "start": datetime.datetime(2025, 1, 1, 0, 0), 666 | "updated": datetime.datetime( 667 | 2025, 5, 6, 11, 30, 47, 285765, tzinfo=utc 668 | ), 669 | }, 670 | ) 671 | --------------------------------------------------------------------------------