Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-939] MISO API Pricing Data #493

Merged
merged 14 commits into from
Dec 11, 2024
Merged

[ENG-939] MISO API Pricing Data #493

merged 14 commits into from
Dec 11, 2024

Conversation

WillKoehrsen
Copy link
Collaborator

@WillKoehrsen WillKoehrsen commented Dec 2, 2024

Summary

  • Adds initial support for the MISO API, specifically the pricing product
  • Adds Methods for retrieving real time and day ahead LMP prices

Details

  • Methods
  1. get_lmp_day_ahead_hourly_ex_ante
  2. get_lmp_day_ahead_hourly_ex_post
  3. get_lmp_real_time_hourly_ex_post_prelim
  4. get_lmp_real_time_hourly_ex_post_final
  5. get_lmp_real_time_5_min_ex_ante
  6. get_lmp_real_time_5_min_ex_post_prelim
  7. get_lmp_real_time_5_min_ex_post_final

if verbose:
logger.info(f"Getting data from {url}")

response = requests.get(url, headers=headers, verify=False)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this doesn't work unless verify=False. The error is:

(Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)')))

I've tried using verify=certifi.where() which fails with the same error. We don't want to skip validation so I'm looking into other solutions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running a test against the server shows an incomplete chain of certificates. It seems that a browser is able to find those missing certificates, but requests does not.

https://www.ssllabs.com/ssltest/analyze.html?d=apim.misoenergy.org
https://stackoverflow.com/a/66111417/5755357

Screenshot 2024-12-01 at 20 25 37

@@ -11,3 +11,7 @@ PJM_API_KEY=
ERCOT_API_USERNAME=
ERCOT_API_PASSWORD=
ERCOT_API_SUBSCRIPTION_KEY=

# Sign up here and subscribe to the pricing product
# https://data-exchange.misoenergy.org/apis
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Sign Up link here just redirects to the Sign In page so I don't actually know how to create a new account.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i remember it was bit confusing. it's fine. we dont need to leave documentation here about how to sign up

@WillKoehrsen WillKoehrsen requested a review from kmax12 December 2, 2024 00:45
Comment on lines +107 to +110
# NOTE: this method does not use the support_date_range decorator. Instead
# it takes the output of a decorated function and processes that output all at once
# which is more efficient than processing each iteration of the decorator
Copy link
Collaborator Author

@WillKoehrsen WillKoehrsen Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully, this is clear. We don't want to call process_pricing_data on each loop of the decorated function, so, we return the raw data lists, then combine them into one list and do all the processing at once.

@WillKoehrsen WillKoehrsen changed the title MISO API Pricing Data [ENG-939] MISO API Pricing Data Dec 9, 2024
Copy link
Collaborator

@kmax12 kmax12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice job - code is very easily to follow! some comments below

@@ -40,10 +40,11 @@ def date_range_maker(start, end, freq, inclusive="neither"):
# current or latest endpoints that are automatically handled. Currently cannot refactor this confidently
# without improved testing since it touches many methods
class support_date_range:
def __init__(self, frequency, update_dates=None):
def __init__(self, frequency, update_dates=None, convert_to_dataframe=True):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe call convert_to_dataframe-->return_raw. basically, this option returns a list of exactly what the decorated function return.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to return_raw=False

@@ -11,3 +11,7 @@ PJM_API_KEY=
ERCOT_API_USERNAME=
ERCOT_API_PASSWORD=
ERCOT_API_SUBSCRIPTION_KEY=

# Sign up here and subscribe to the pricing product
# https://data-exchange.misoenergy.org/apis
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i remember it was bit confusing. it's fine. we dont need to leave documentation here about how to sign up


node_to_type_mapping = (
MISO()
._get_node_to_type_mapping()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our approach here is to query the {today}_da_expost_lmp.csv file for to obtain node maps. this feels unreliable for historical days when nodes may have been different. that file seems to have data going back to 20220101. perhaps we can can pass the date of the end of the requested range (but not earlier than 20220101) to this function to get a better file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled the data from 2022-01-01 and 2024-12-11 and compared the mapping of Node to Type. There were no differences. (The 2024 data has more nodes but none of the mappings have changed).

REAL_TIME_15_MIN = "REAL_TIME_15_MIN"
REAL_TIME_HOURLY = "REAL_TIME_HOURLY"

REAL_TIME_HOURLY_EX_POST_PRELIM = "REAL_TIME_HOURLY_EX_POST_PRELIM"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we update MISO to correctly use these new market names rather than Markets.REAL_TIME_HOURLY_FINAL, Markets.REAL_TIME_HOURLY_PRELIM, Markets.DAY_AHEAD_HOURLY?

perhaps we also consider making a breaking change downstream in our api to just get the "market" column and the dataset names correct

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we update MISO to correctly use these new market names

Based on our discussion, it sounds like no.

@WillKoehrsen WillKoehrsen merged commit 33f9026 into main Dec 11, 2024
12 of 16 checks passed
@WillKoehrsen WillKoehrsen deleted the miso-api-lmp branch December 11, 2024 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants