Skip to content

Commit

Permalink
Add Agile Predict and fix TZ error in Day Ahead
Browse files Browse the repository at this point in the history
  • Loading branch information
fboundy committed Jul 3, 2024
1 parent 2f7d958 commit e29b19c
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions apps/pv_opt/pvpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from datetime import datetime

OCTOPUS_PRODUCT_URL = r"https://api.octopus.energy/v1/products/"
AGILE_PREDICT_URL = r"https://agilepredict.com/api/"

TIME_FORMAT = "%d/%m %H:%M %Z"
MAX_ITERS = 3

Expand Down Expand Up @@ -76,6 +78,7 @@ def __init__(
self.eco7 = eco7
self.area = kwargs.get("area", None)
self.day_ahead = None
self.agile_predict = None
self.eco7_start = pd.Timestamp(eco7_start, tz="UTC")

if octopus:
Expand Down Expand Up @@ -200,12 +203,12 @@ def to_df(self, start=None, end=None, **kwargs):
if "AGILE" in self.name and use_day_ahead:
if self.day_ahead is not None and df.index[-1].day == end.day:
# reset the day ahead forecasts if we've got a forecast going into tomorrow
self.agile_predict = None
self.day_ahead = None
self.log("")
self.log(f"Cleared day ahead forecast for tariff {self.name}")

if pd.Timestamp.now(tz=self.tz).hour > 11 and df.index[-1].day != end.day:

# if it is after 11 but we don't have new Agile prices yet, check for a day-ahead forecast
if self.day_ahead is None:
self.day_ahead = self.get_day_ahead(df.index[0])
Expand All @@ -222,7 +225,9 @@ def to_df(self, start=None, end=None, **kwargs):
else:
factors = AGILE_FACTORS["import"][self.area]

mask = (self.day_ahead.index.hour >= 16) & (self.day_ahead.index.hour < 19)
mask = (self.day_ahead.index.tz_convert("GB").hour >= 16) & (
self.day_ahead.index.tz_convert("GB").hour < 19
)

agile = (
pd.concat(
Expand All @@ -237,7 +242,13 @@ def to_df(self, start=None, end=None, **kwargs):
)

df = pd.concat([df, agile])
# self.log(df)
else:
# Otherwise download the latest forecast from AgilePredict
if self.agile_predict is None:
self.agile_predict = self._get_agile_predict()

if self.agile_predict is not None:
df = pd.concat([df, self.agile_predict.loc[df.index[-1] + pd.Timedelta("30min") : end]])

# If the index frequency >30 minutes so we need to just extend it:
if (len(df) > 1 and ((df.index[-1] - df.index[-2]).total_seconds() / 60) > 30) or len(df) == 1:
Expand Down Expand Up @@ -285,6 +296,19 @@ def to_df(self, start=None, end=None, **kwargs):

return df

def _get_agile_predict(self):
url = f"{AGILE_PREDICT_URL}{self.area}?days=2&high_low=false"
try:
r = requests.get(url)
r.raise_for_status() # Raise an exception for unsuccessful HTTP status codes

except requests.exceptions.RequestException as e:
return

df = pd.DataFrame(r.json()[0]["prices"]).set_index("date_time")
df.index = pd.to_datetime(df.index).tz_convert("UTC")
return df["agile_pred"]

def get_day_ahead(self, start):
url = "https://www.nordpoolgroup.com/api/marketdata/page/325?currency=GBP"

Expand Down

0 comments on commit e29b19c

Please sign in to comment.