aemo-to-tariff 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aemo_to_tariff-0.1.0/LICENSE +21 -0
- aemo_to_tariff-0.1.0/PKG-INFO +14 -0
- aemo_to_tariff-0.1.0/README.md +22 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff/__init__.py +3 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff/ausgrid.py +29 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff/convert.py +31 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff/energex.py +65 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff/evoenergy.py +61 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff.egg-info/PKG-INFO +14 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff.egg-info/SOURCES.txt +14 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff.egg-info/dependency_links.txt +1 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff.egg-info/requires.txt +1 -0
- aemo_to_tariff-0.1.0/aemo_to_tariff.egg-info/top_level.txt +1 -0
- aemo_to_tariff-0.1.0/setup.cfg +4 -0
- aemo_to_tariff-0.1.0/setup.py +21 -0
- aemo_to_tariff-0.1.0/test/test_convert.py +68 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ian Connor
|
|
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.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: aemo_to_tariff
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert spot prices from $/MWh to c/kWh for different networks and tariffs
|
|
5
|
+
Author: Ian Connor
|
|
6
|
+
Author-email: ian@powston.com
|
|
7
|
+
License: MIT
|
|
8
|
+
Platform: UNKNOWN
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
|
|
14
|
+
UNKNOWN
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# aemo_to_tariff
|
|
2
|
+
|
|
3
|
+
This Python package converts spot prices from $/MWh to c/kWh for different networks and tariffs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install aemo_to_tariff
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from aemo_to_tariff import spot_to_tariff
|
|
15
|
+
|
|
16
|
+
price_c_kwh = spot_to_tariff('2024-07-05 14:00', 'Energex', '6970', 100)
|
|
17
|
+
print(price_c_kwh)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## License
|
|
21
|
+
|
|
22
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# aemo_to_tariff/ausgrid.py
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pytz import timezone
|
|
4
|
+
|
|
5
|
+
def time_zone():
|
|
6
|
+
return 'Australia/Sydney'
|
|
7
|
+
|
|
8
|
+
def convert(interval_time: datetime, tariff: str, rrp: float):
|
|
9
|
+
"""
|
|
10
|
+
Convert RRP from $/MWh to c/kWh for Ausgrid.
|
|
11
|
+
|
|
12
|
+
Parameters:
|
|
13
|
+
- interval_time (str): The interval time.
|
|
14
|
+
- network (str): The name of the network.
|
|
15
|
+
- tariff (str): The tariff code.
|
|
16
|
+
- rrp (float): The Regional Reference Price in $/MWh.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
- float: The price in c/kWh.
|
|
20
|
+
"""
|
|
21
|
+
interval_time = interval_time.astimezone(timezone(time_zone()))
|
|
22
|
+
rrp_c_kwh = rrp / 10
|
|
23
|
+
if tariff == 'N70':
|
|
24
|
+
return rrp_c_kwh + 14.40 # Todo: Update this value
|
|
25
|
+
else:
|
|
26
|
+
# Terrible approximation
|
|
27
|
+
slope = 1.037869032618134
|
|
28
|
+
intecept = 5.586606750833143
|
|
29
|
+
return rrp_c_kwh * slope + intecept
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# aemo_to_tariff/convert.py
|
|
2
|
+
|
|
3
|
+
from aemo_to_tariff.energex import convert as energex_convert
|
|
4
|
+
from aemo_to_tariff.ausgrid import convert as ausgrid_convert
|
|
5
|
+
from aemo_to_tariff.evoenergy import convert as evoenergy_convert
|
|
6
|
+
|
|
7
|
+
def spot_to_tariff(interval_time, network, tariff, rrp, dlf=1.05905, mlf=1.0154):
|
|
8
|
+
"""
|
|
9
|
+
Convert spot price from $/MWh to c/kWh for a given network and tariff.
|
|
10
|
+
|
|
11
|
+
Parameters:
|
|
12
|
+
- interval_time (str): The interval time.
|
|
13
|
+
- network (str): The name of the network (e.g., 'Energex', 'Ausgrid', 'Evoenergy').
|
|
14
|
+
- tariff (str): The tariff code (e.g., '6970', '017').
|
|
15
|
+
- rrp (float): The Regional Reference Price in $/MWh.
|
|
16
|
+
- dlf (float): The Distribution Loss Factor.
|
|
17
|
+
- mlf (float): The Metering Loss Factor.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
- float: The price in c/kWh.
|
|
21
|
+
"""
|
|
22
|
+
adjusted_rrp = rrp * dlf * mlf
|
|
23
|
+
network = network.lower()
|
|
24
|
+
if network == 'energex':
|
|
25
|
+
return energex_convert(interval_time, tariff, adjusted_rrp)
|
|
26
|
+
elif network == 'ausgrid':
|
|
27
|
+
return ausgrid_convert(interval_time, tariff, adjusted_rrp)
|
|
28
|
+
elif network == 'evoenergy':
|
|
29
|
+
return evoenergy_convert(interval_time, tariff, adjusted_rrp)
|
|
30
|
+
else:
|
|
31
|
+
raise ValueError(f"Unknown network: {network}")
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# aemo_to_tariff/energex.py
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pytz import timezone
|
|
4
|
+
|
|
5
|
+
def time_zone():
|
|
6
|
+
return 'Australia/Brisbane'
|
|
7
|
+
|
|
8
|
+
NOUS = (0.02840, 0.15936, 0.03513)
|
|
9
|
+
|
|
10
|
+
def daily():
|
|
11
|
+
return 32.757 + 15.500
|
|
12
|
+
|
|
13
|
+
def peak_hours():
|
|
14
|
+
# Peak Energy 4pm-9pm every day
|
|
15
|
+
return [16, 17, 18, 19, 20]
|
|
16
|
+
|
|
17
|
+
def peak_cost():
|
|
18
|
+
return 15.936
|
|
19
|
+
|
|
20
|
+
def off_peak_hours():
|
|
21
|
+
# Off-peak Energy 9pm-4pm every day
|
|
22
|
+
return [10, 11, 12, 13, 14, 15]
|
|
23
|
+
|
|
24
|
+
def off_peak_cost():
|
|
25
|
+
return 2.840
|
|
26
|
+
|
|
27
|
+
def shoulder_hours():
|
|
28
|
+
# Not peak or off-peak
|
|
29
|
+
return [21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
30
|
+
|
|
31
|
+
def shoulder_cost():
|
|
32
|
+
return 3.513
|
|
33
|
+
|
|
34
|
+
def convert(interval_time: datetime, tariff: str, rrp: float):
|
|
35
|
+
"""
|
|
36
|
+
Convert RRP from $/MWh to c/kWh for Evoenergy.
|
|
37
|
+
|
|
38
|
+
Parameters:
|
|
39
|
+
- interval_time (str): The interval time.
|
|
40
|
+
- tariff (str): The tariff code.
|
|
41
|
+
- rrp (float): The Regional Reference Price in $/MWh.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
- float: The price in c/kWh.
|
|
45
|
+
"""
|
|
46
|
+
interval_time = interval_time.astimezone(timezone(time_zone()))
|
|
47
|
+
hour = interval_time.hour
|
|
48
|
+
rrp_c_kwh = rrp / 10
|
|
49
|
+
if tariff == '6970':
|
|
50
|
+
if hour in peak_hours():
|
|
51
|
+
price_c_kwh = peak_cost()
|
|
52
|
+
elif hour in shoulder_hours():
|
|
53
|
+
price_c_kwh = shoulder_cost()
|
|
54
|
+
elif hour in off_peak_hours():
|
|
55
|
+
price_c_kwh = off_peak_cost()
|
|
56
|
+
else:
|
|
57
|
+
price_c_kwh = off_peak_cost()
|
|
58
|
+
price_c_kwh += rrp_c_kwh
|
|
59
|
+
else:
|
|
60
|
+
# Terrible approximation
|
|
61
|
+
slope = 1.037869032618134
|
|
62
|
+
intecept = 5.586606750833143
|
|
63
|
+
return rrp_c_kwh * slope + intecept
|
|
64
|
+
|
|
65
|
+
return price_c_kwh + rrp_c_kwh
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# aemo_to_tariff/evoenergy.py
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from pytz import timezone
|
|
4
|
+
|
|
5
|
+
def time_zone():
|
|
6
|
+
return 'Australia/ACT'
|
|
7
|
+
|
|
8
|
+
def daily():
|
|
9
|
+
return 32.757 + 15.500
|
|
10
|
+
|
|
11
|
+
def peak_hours():
|
|
12
|
+
# Peak Energy 7am-9am and 5pm-9pm every day
|
|
13
|
+
return [7, 8, 17, 18, 19, 20]
|
|
14
|
+
|
|
15
|
+
def peak_cost():
|
|
16
|
+
return 14.109
|
|
17
|
+
|
|
18
|
+
def solar_soak_hours():
|
|
19
|
+
# Solar Soak Energy 11am-3pm every day
|
|
20
|
+
return [11, 12, 13, 14]
|
|
21
|
+
|
|
22
|
+
def solar_soak_cost():
|
|
23
|
+
return 1.757
|
|
24
|
+
|
|
25
|
+
def off_peak_hours():
|
|
26
|
+
# Off-peak Energy 9pm-7am, 9am-11am and 3pm-5pm every day
|
|
27
|
+
return [21, 22, 23, 9, 10, 15, 16]
|
|
28
|
+
|
|
29
|
+
def off_peak_cost():
|
|
30
|
+
return 3.918
|
|
31
|
+
|
|
32
|
+
def convert(interval_time: datetime, tariff: str, rrp: float):
|
|
33
|
+
"""
|
|
34
|
+
Convert RRP from $/MWh to c/kWh for Evoenergy.
|
|
35
|
+
|
|
36
|
+
Parameters:
|
|
37
|
+
- interval_time (str): The interval time.
|
|
38
|
+
- tariff (str): The tariff code.
|
|
39
|
+
- rrp (float): The Regional Reference Price in $/MWh.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
- float: The price in c/kWh.
|
|
43
|
+
"""
|
|
44
|
+
interval_time = interval_time.astimezone(timezone(time_zone()))
|
|
45
|
+
hour = interval_time.hour
|
|
46
|
+
rrp_c_kwh = rrp / 10
|
|
47
|
+
if tariff == '017':
|
|
48
|
+
if hour in peak_hours():
|
|
49
|
+
price_c_kwh = peak_cost()
|
|
50
|
+
elif hour in solar_soak_hours():
|
|
51
|
+
price_c_kwh = solar_soak_cost()
|
|
52
|
+
elif hour in off_peak_hours():
|
|
53
|
+
price_c_kwh = off_peak_cost()
|
|
54
|
+
else:
|
|
55
|
+
price_c_kwh = off_peak_cost()
|
|
56
|
+
return price_c_kwh + rrp_c_kwh
|
|
57
|
+
else:
|
|
58
|
+
# Terrible approximation
|
|
59
|
+
slope = 1.037869032618134
|
|
60
|
+
intecept = 5.586606750833143
|
|
61
|
+
return rrp_c_kwh * slope + intecept
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: aemo-to-tariff
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert spot prices from $/MWh to c/kWh for different networks and tariffs
|
|
5
|
+
Author: Ian Connor
|
|
6
|
+
Author-email: ian@powston.com
|
|
7
|
+
License: MIT
|
|
8
|
+
Platform: UNKNOWN
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
|
|
14
|
+
UNKNOWN
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
aemo_to_tariff/__init__.py
|
|
5
|
+
aemo_to_tariff/ausgrid.py
|
|
6
|
+
aemo_to_tariff/convert.py
|
|
7
|
+
aemo_to_tariff/energex.py
|
|
8
|
+
aemo_to_tariff/evoenergy.py
|
|
9
|
+
aemo_to_tariff.egg-info/PKG-INFO
|
|
10
|
+
aemo_to_tariff.egg-info/SOURCES.txt
|
|
11
|
+
aemo_to_tariff.egg-info/dependency_links.txt
|
|
12
|
+
aemo_to_tariff.egg-info/requires.txt
|
|
13
|
+
aemo_to_tariff.egg-info/top_level.txt
|
|
14
|
+
test/test_convert.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pytz
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aemo_to_tariff
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# setup.py
|
|
2
|
+
|
|
3
|
+
from setuptools import setup, find_packages
|
|
4
|
+
|
|
5
|
+
setup(
|
|
6
|
+
name='aemo_to_tariff',
|
|
7
|
+
version='0.1.0',
|
|
8
|
+
description='Convert spot prices from $/MWh to c/kWh for different networks and tariffs',
|
|
9
|
+
author='Ian Connor',
|
|
10
|
+
author_email='ian@powston.com',
|
|
11
|
+
license='MIT',
|
|
12
|
+
packages=find_packages(),
|
|
13
|
+
install_requires=[
|
|
14
|
+
'pytz',
|
|
15
|
+
],
|
|
16
|
+
classifiers=[
|
|
17
|
+
'Programming Language :: Python :: 3',
|
|
18
|
+
'License :: OSI Approved :: MIT License',
|
|
19
|
+
'Operating System :: OS Independent',
|
|
20
|
+
],
|
|
21
|
+
)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# test/test_convert.py
|
|
2
|
+
|
|
3
|
+
import unittest
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from aemo_to_tariff import spot_to_tariff
|
|
6
|
+
|
|
7
|
+
class TestSpotToTariff(unittest.TestCase):
|
|
8
|
+
|
|
9
|
+
def test_energex_tariff_6970(self):
|
|
10
|
+
# Off peak
|
|
11
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
12
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Energex', '6970', 100, 1, 1), 22.84, 2)
|
|
13
|
+
|
|
14
|
+
# Peak
|
|
15
|
+
interval_time = datetime.strptime('2024-07-05 17:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
16
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Energex', '6970', 100, 1, 1), 35.936, 2)
|
|
17
|
+
|
|
18
|
+
#Shoulder
|
|
19
|
+
interval_time = datetime.strptime('2024-07-05 02:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
20
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Energex', '6970', 100, 1, 1), 23.51, 2)
|
|
21
|
+
|
|
22
|
+
# With loss factor
|
|
23
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
24
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Energex', '6970', 200, 1.05, 1.01), 45.26)
|
|
25
|
+
|
|
26
|
+
def test_energex_tariff_017(self):
|
|
27
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
28
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Energex', '017', 100, 1, 1), 15.965, 2)
|
|
29
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
30
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Energex', '017', 200, 1, 1), 26.343, 2)
|
|
31
|
+
|
|
32
|
+
def test_ausgrid_tariff_6970(self):
|
|
33
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
34
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Ausgrid', '6970', 100, 1, 1), 15.965, 2)
|
|
35
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
36
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Ausgrid', '6970', 200, 1, 1), 26.343, 2)
|
|
37
|
+
|
|
38
|
+
def test_ausgrid_tariff_017(self):
|
|
39
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
40
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Ausgrid', '017', 100, 1, 1), 15.965, 2)
|
|
41
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
42
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Ausgrid', '017', 200, 1, 1), 26.343, 2)
|
|
43
|
+
|
|
44
|
+
def test_evoenergy_tariff_6970(self):
|
|
45
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
46
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Evoenergy', '6970', 100, 1, 1), 15.965, 2)
|
|
47
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
48
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Evoenergy', '6970', 200, 1, 1), 26.34, 2)
|
|
49
|
+
|
|
50
|
+
def test_evoenergy_tariff_017(self):
|
|
51
|
+
# Off peak
|
|
52
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
53
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Evoenergy', '017', 100, 1, 1), 11.757, 2)
|
|
54
|
+
|
|
55
|
+
# Peak
|
|
56
|
+
interval_time = datetime.strptime('2024-07-05 17:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
57
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Evoenergy', '017', 100, 1, 1), 24.109, 2)
|
|
58
|
+
|
|
59
|
+
#Shoulder
|
|
60
|
+
interval_time = datetime.strptime('2024-07-05 02:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
61
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Evoenergy', '017', 100, 1, 1), 13.918, 2)
|
|
62
|
+
|
|
63
|
+
interval_time = datetime.strptime('2024-07-05 14:00+10:00', '%Y-%m-%d %H:%M%z')
|
|
64
|
+
self.assertAlmostEqual(spot_to_tariff(interval_time, 'Evoenergy', '017', 200), 23.264, 2)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if __name__ == '__main__':
|
|
68
|
+
unittest.main()
|