Pjm
========================

.. py:module:: gridstatus.pjm


Module Contents
---------------

Classes Summary
~~~~~~~~~~~~~~~

.. autoapisummary::

   gridstatus.pjm.PJM





Contents
~~~~~~~~~~~~~~~~~~~
.. py:class:: PJM(api_key: str | None = None, retries: int = DEFAULT_RETRIES)

   Bases: :py:obj:`gridstatus.base.ISOBase`

   PJM

   :param api_key: PJM API key. Alternatively, can be set
                   in PJM_API_KEY environment variable. Register for an API key
                   at https://www.pjm.com/
   :type api_key: str, optional


   **Attributes**

   .. list-table::
      :widths: 15 85
      :header-rows: 0

      * - **api_key**
        - None
      * - **AS_MARKET_RESULTS_GRANULARITY_CHANGE_DATE**
        - '2022-09-01'
      * - **AS_MARKET_RESULTS_START_DATE**
        - '2013-06-14'
      * - **default_timezone**
        - 'US/Eastern'
      * - **hub_node_ids**
        - ('51217', '116013751', '35010337', '34497151', '34497127', '34497125', '33092315', '33092313', '33092311', '4669664', '51288', '51287')
      * - **interconnection_homepage**
        - 'https://www.pjm.com/planning/service-requests/services-request-status'
      * - **iso_id**
        - 'pjm'
      * - **load_forecast_5_min_endpoint_name**
        - 'very_short_load_frcst'
      * - **load_forecast_endpoint_name**
        - 'load_frcstd_7_day'
      * - **load_forecast_historical_endpoint_name**
        - 'load_frcstd_hist'
      * - **locale_abbreviated_to_full**
        - None
      * - **location_types**
        - ('ZONE', 'LOAD', 'GEN', 'AGGREGATE', 'INTERFACE', 'EXT', 'HUB', 'EHV', 'TIE', 'RESIDUAL_METERED_EDC')
      * - **markets**
        - None
      * - **name**
        - 'PJM'
      * - **price_node_ids**
        - ('5021703', '5021704', '5021723', '5021724', '93354015', '93354017', '93354019', '34887765', '34887767', '34887769', '34887771', '34887773', '34887775', '34887777', '2156111970', '34887779', '34887781', '34887783', '34887787', '34887789', '34887791', '34887793', '74008711', '34887819', '34887821', '34887823', '2156112027', '34887845', '1439658151', '34887847', '34887849', '74008743', '34887851', '34887853', '1123180720', '34887857', '1123180722', '34887859', '1123180723', '34887861', '1123180721', '34887871', '34887873', '34887887', '34887889', '34887891', '34887893', '34887895', '1207075032', '34887897', '34887899', '34887901', '34887911', '34887913', '34887915', '34887917', '34887923', '1097732340', '34887925', '34887927', '34887929', '34887935', '34887937', '34887939', '34887941', '34887949', '34887951', '34887953', '34887955', '1552845076', '34887957', '1552845077', '34887959', '1552845078', '34887961', '34887963', '34887965', '34887967', '34887969', '34887971', '1305131304', '34887977', '1305131306', '34887993', '34887997', '34887999', '34888001', '119118151', '2156114262', '1379266905', '1379266906', '1097732449', '1292915048', '1132294512', '1132294513', '1132294514', '1132294515', '1552845186', '106856851', '2156112284', '1305131444', '119118263', '119118265', '119118267', '119118269', '119118271', '106856905', '2156110343', '40243747', '71856675', '40243749', '71856677', '40243751', '40243753', '40243755', '40243757', '40243759', '40243761', '40243763', '40243765', '40243767', '40243769', '40243771', '40243773', '40243775', '40243777', '40243779', '1248991825', '1248991826', '1248991827', '40243801', '40243803', '40243805', '40243807', '135389793', '135389819', '40243837', '1666116222', '1666116223', '1666116224', '1666116225', '40243839', '1356163765', '38367965', '38367967', '38367969', '1218915048', '1218915049', '1218915050', '1218915051', '1388614399', '2156110624', '32418611', '32418613', '32418615', '32418617', '1388614460', '1084390238', '1218915186', '1218915187', '1369011076', '1369011077', '1369011078', '1268571042', '98370477', '1084390354', '93140', '93141', '93142', '93143', '93144', '93145', '98370523', '98370525', '98370527', '98370529', '98370531', '98370533', '98370535', '1552843818', '57967665', '1552843913', '1552843915', '1552843916', '1356162213', '1356162214', '50401', '48934161', '48934163', '48934165', '48934167', '48934169', '36181299', '50488', '50489', '50490', '36181325', '2156113262', '50542', '50543', '50557', '50558', '2156113284', '50578', '50579', '50581', '50621', '50622', '87901631', '50628', '50629', '50654', '50655', '50659', '50660', '50661', '50662', '2156111333', '1048047', '1048049', '1048050', '1048051', '1048052', '21601782', '21601783', '21601784', '21601785', '21601786', '50695', '50696', '50697', '50698', '50699', '2041990671', '123901459', '123901461', '123901463', '123901465', '123901467', '50715', '50716', '50717', '50727', '50728', '50729', '50730', '2156113457', '2156113469', '50764', '2156113488', '50769', '50770', '50771', '50777', '50778', '50779', '123901537', '123901539', '123901543', '31020649', '123901545', '31020651', '31020653', '50809', '50810', '50811', '50812', '50813', '50814', '50817', '50818', '1165479564', '2156109456', '50887', '50888', '50893', '50894', '50911', '50915', '32417525', '32417527', '2156111608', '1218914041', '1218914042', '1218914043', '32417545', '32417547', '1183231801', '32417599', '32417601', '32417603', '32417605', '51019', '51020', '51021', '1348263767', '32417625', '32417627', '32417629', '32417631', '32417633', '32417635', '1379268471', '1379268472', '1379268473', '1379268474', '1379268475', '1379268476', '63381383', '63381385', '2156111770', '2156109760', '2156109763', '2156109765', '2156109768', '2156109772', '2156109777', '5021665', '5021666', '5021667', '2156111847', '93353961', '93353963', '93353965')
      * - **retries**
        - 3
      * - **service_type_abbreviated_to_full**
        - None
      * - **zone_node_ids**
        - ('1', '3', '51291', '51292', '51293', '51295', '51296', '51297', '51298', '51299', '51300', '51301', '7633629', '8394954', '8445784', '33092371', '34508503', '34964545', '37737283', '116013753', '124076095', '970242670', '1709725933')


   **Methods**

   .. autoapisummary::
      :nosignatures:

      gridstatus.pjm.PJM.get_actual_and_scheduled_interchange_summary
      gridstatus.pjm.PJM.get_actual_operational_statistics
      gridstatus.pjm.PJM.get_area_control_error
      gridstatus.pjm.PJM.get_as_market_results_real_time_hourly
      gridstatus.pjm.PJM.get_cleared_virtuals_daily
      gridstatus.pjm.PJM.get_dam_as_market_results
      gridstatus.pjm.PJM.get_day_ahead_demand_bids
      gridstatus.pjm.PJM.get_dispatched_reserves_prelim
      gridstatus.pjm.PJM.get_dispatched_reserves_verified
      gridstatus.pjm.PJM.get_emergency_postings
      gridstatus.pjm.PJM.get_forecasted_generation_outages
      gridstatus.pjm.PJM.get_fuel_mix
      gridstatus.pjm.PJM.get_gen_outages_by_type
      gridstatus.pjm.PJM.get_generation_capacity_daily
      gridstatus.pjm.PJM.get_hourly_net_exports_by_state
      gridstatus.pjm.PJM.get_hourly_transfer_limits_and_flows
      gridstatus.pjm.PJM.get_inc_and_dec_bids_day_ahead_hourly
      gridstatus.pjm.PJM.get_instantaneous_dispatch_rates
      gridstatus.pjm.PJM.get_interconnection_queue
      gridstatus.pjm.PJM.get_interface_flows_and_limits_day_ahead
      gridstatus.pjm.PJM.get_it_sced_lmp_5_min
      gridstatus.pjm.PJM.get_lmp
      gridstatus.pjm.PJM.get_lmp_real_time_unverified_5_min
      gridstatus.pjm.PJM.get_lmp_real_time_unverified_hourly
      gridstatus.pjm.PJM.get_load
      gridstatus.pjm.PJM.get_load_forecast
      gridstatus.pjm.PJM.get_load_forecast_5_min
      gridstatus.pjm.PJM.get_load_forecast_historical
      gridstatus.pjm.PJM.get_load_metered_hourly
      gridstatus.pjm.PJM.get_marginal_emission_rates_5_min
      gridstatus.pjm.PJM.get_marginal_value_day_ahead_hourly
      gridstatus.pjm.PJM.get_marginal_value_real_time_5_min
      gridstatus.pjm.PJM.get_operational_reserves
      gridstatus.pjm.PJM.get_pai_intervals_5_min
      gridstatus.pjm.PJM.get_pnode_ids
      gridstatus.pjm.PJM.get_pricing_nodes
      gridstatus.pjm.PJM.get_projected_area_statistics_at_peak
      gridstatus.pjm.PJM.get_projected_peak_tie_flow
      gridstatus.pjm.PJM.get_projected_rto_statistics_at_peak
      gridstatus.pjm.PJM.get_raw_interconnection_queue
      gridstatus.pjm.PJM.get_real_time_as_market_results
      gridstatus.pjm.PJM.get_regulation_market_monthly
      gridstatus.pjm.PJM.get_regulation_prices_5_min
      gridstatus.pjm.PJM.get_reserve_subzone_buses
      gridstatus.pjm.PJM.get_reserve_subzone_resources
      gridstatus.pjm.PJM.get_scheduled_interchange_real_time
      gridstatus.pjm.PJM.get_settlements_verified_lmp_5_min
      gridstatus.pjm.PJM.get_settlements_verified_lmp_hourly
      gridstatus.pjm.PJM.get_solar_forecast_5_min
      gridstatus.pjm.PJM.get_solar_forecast_hourly
      gridstatus.pjm.PJM.get_solar_generation_5_min
      gridstatus.pjm.PJM.get_solar_generation_by_area
      gridstatus.pjm.PJM.get_sync_reserve_events
      gridstatus.pjm.PJM.get_tie_flows_5_min
      gridstatus.pjm.PJM.get_transfer_interface_information_5_min
      gridstatus.pjm.PJM.get_transmission_constraints_day_ahead_hourly
      gridstatus.pjm.PJM.get_transmission_limits
      gridstatus.pjm.PJM.get_voltage_limits
      gridstatus.pjm.PJM.get_weight_average_aggregation_definition
      gridstatus.pjm.PJM.get_wind_forecast_5_min
      gridstatus.pjm.PJM.get_wind_forecast_hourly
      gridstatus.pjm.PJM.get_wind_generation_by_area
      gridstatus.pjm.PJM.get_wind_generation_instantaneous
      gridstatus.pjm.PJM.to_local_datetime

   .. py:method:: get_actual_and_scheduled_interchange_summary(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the actual and scheduled interchange summary data from:
      https://dataminer2.pjm.com/feed/actual_and_scheduled_interchange_summary/definition


   .. py:method:: get_actual_operational_statistics(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the actual operational statistics data from:
      https://dataminer2.pjm.com/feed/ops_sum_prev_period/definition


   .. py:method:: get_area_control_error(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the area control error data from:
      https://dataminer2.pjm.com/feed/area_control_error/definition


   .. py:method:: get_as_market_results_real_time_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False)

      Retrieves hourly real-time ancillary service market results prior to 2022-09-01.

      This method queries historical data before the granularity changed from hourly
      to 5-minute intervals. For data on or after September 1, 2022, use
      get_real_time_as_market_results().

      :param date: Start date. Must be between 2013-06-14 and 2022-08-31.
      :param end: End date. Must be before 2022-09-01.
      :param verbose: Print verbose output.

      :returns: DataFrame with hourly AS market results.


   .. py:method:: get_cleared_virtuals_daily(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the daily cleared virtual transactions data from:
      https://dataminer2.pjm.com/feed/day_inc_dec_utc/definition


   .. py:method:: get_dam_as_market_results(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False)

      Retrieves the day-ahead ancillary service market results from :
      https://dataminer2.pjm.com/feed/da_reserve_market_results/definition
      Data is published daily.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with day-ahead ancillary service
                market results.
      :rtype: pandas.DataFrame


   .. py:method:: get_day_ahead_demand_bids(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the day ahead demand bids data from:
      https://dataminer2.pjm.com/feed/hrl_dmd_bids/definition


   .. py:method:: get_dispatched_reserves_prelim(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the dispatched reserves preliminary data from:
      https://dataminer2.pjm.com/feed/dispatched_reserves/definition


   .. py:method:: get_dispatched_reserves_verified(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the dispatched reserves verified data from:
      https://dataminer2.pjm.com/feed/rt_dispatch_reserves/definition


   .. py:method:: get_emergency_postings(url: str | None = None) -> pandas.DataFrame

      Retrieves PJM emergency procedure postings by triggering the public
      "Export To XML" button on the guest dashboard.

      Two-step flow (no credentials required):
        1. GET the guest dashboard to obtain a session cookie and JSF ViewState.
        2. POST ``frmButtons:lnkDownload`` to download the XML export.

      The XML contains Publish Time, Canceled Time, proper UTC start/end
      timestamps, and individual Region elements (one DataFrame row per
      message-region pair).


   .. py:method:: get_forecasted_generation_outages(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False)

      Retrieves the forecasted generation outages for the next 90 days from:

      https://dataminer2.pjm.com/feed/frcstd_gen_outages/definition


   .. py:method:: get_fuel_mix(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Get fuel mix for a date or date range  in hourly intervals


   .. py:method:: get_gen_outages_by_type(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the generation outage data
      From: https://dataminer2.pjm.com/feed/gen_outages_by_type/definition


   .. py:method:: get_generation_capacity_daily(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the daily generation capacity data from:
      https://dataminer2.pjm.com/feed/day_gen_capacity/definition


   .. py:method:: get_hourly_net_exports_by_state(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the hourly net exports by state data from:
      https://dataminer2.pjm.com/feed/state_net_interchange/definition


   .. py:method:: get_hourly_transfer_limits_and_flows(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the hourly transfer limits and flows data from:
      https://dataminer2.pjm.com/feed/transfer_limits_and_flows/definition


   .. py:method:: get_inc_and_dec_bids_day_ahead_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the hourly day-ahead increment and decrement bids data from:
      https://dataminer2.pjm.com/feed/hrl_da_incs_decs/definition

      Note: This data has a 4-month publication delay.


   .. py:method:: get_instantaneous_dispatch_rates(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the instantaneous dispatch rate data from:
      https://dataminer2.pjm.com/feed/inst_dispatch_rate/definition


   .. py:method:: get_interconnection_queue(verbose: bool = False) -> pandas.DataFrame

   .. py:method:: get_interface_flows_and_limits_day_ahead(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the interface flows and limit day ahead data from:
      https://dataminer2.pjm.com/feed/da_interface_flows_and_limits/definition


   .. py:method:: get_it_sced_lmp_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Get 5 minute LMPs from the Integrated Forward Market (IFM)


   .. py:method:: get_lmp(date: str | pandas.Timestamp, market: str, end: str | pandas.Timestamp | None = None, locations: str = 'hubs', location_type: str | None = None, verbose: bool = False) -> pandas.DataFrame

      Returns LMP at a previous date.

      .. note::

         If start date is prior to the PJM archive date, all data must be
         downloaded before location filtering can be performed due to
         limitations of PJM API. The archive date is 186 days (~6 months)
         before today for the 5 minute real time market and 731 days
         (~2 years) before today for the Hourly Real Time and Day Ahead
         Hourly markets. Node type filter can be performed for Real Time
         Hourly and Day Ahead Hourly markets.
         
         If location_type is provided, it is filtered after data is
         retrieved for Real Time 5 Minute market regardless of the date.
         This is due to PJM api limitations.
         
         Returns ``Location Id``, ``Location Name``, ``Location Short Name``.

      :param date: Date to get LMPs for.
      :param end: End date to get LMPs for.
      :param market: Supported Markets: REAL_TIME_5_MIN, REAL_TIME_HOURLY,
                     DAY_AHEAD_HOURLY.
      :param locations: List of pnodeid to get LMPs for. Defaults to "hubs".
                        Use get_pnode_ids() to get a list of possible pnode ids.
                        If "all", will return data from all p nodes (warning: there
                        are over 10,000 unique pnodes, so expect millions of rows!).
      :param location_type: If specified, will only return data for nodes of
                            this type. Defaults to None. Possible location types are:
                            'ZONE', 'LOAD', 'GEN', 'AGGREGATE', 'INTERFACE', 'EXT',
                            'HUB', 'EHV', 'TIE', 'RESIDUAL_METERED_EDC'.


   .. py:method:: get_lmp_real_time_unverified_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, locations: str | list | None = 'hubs', location_type: str | None = None, verbose: bool = False) -> pandas.DataFrame

      Get real-time unverified 5-minute LMPs for a date range.

      Mirrors the output shape of ``get_lmp(market=REAL_TIME_5_MIN)`` but
      always hits ``rt_unverified_fivemin_lmps`` so callers can pull the
      freshest data (verified is delayed ~25 minutes).


   .. py:method:: get_lmp_real_time_unverified_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, locations: str | None = None, location_type: str | None = None, verbose: bool = False) -> pandas.DataFrame

      Get real-time unverified hourly LMPs


   .. py:method:: get_load(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Returns load at a previous date at 5 minute intervals.

      :param date: Date to get load for. Must be in last 30 days.

      :returns: Load data time series. Columns include Time, Load, and all areas.
                Load columns represent PJM-wide load. Returns data for the following
                areas: AE, AEP, APS, ATSI, BC, COMED, DAYTON, DEOK, DOM, DPL, DUQ,
                EKPC, JC, ME, PE, PEP, PJM MID ATLANTIC REGION, PJM RTO,
                PJM SOUTHERN REGION, PJM WESTERN REGION, PL, PN, PS, RECO.


   .. py:method:: get_load_forecast(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Load forecast made today extending for six days in hourly intervals.

      Today's forecast updates every every half hour on the quarter E.g. 1:15 and 1:45


   .. py:method:: get_load_forecast_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Load forecast made today extending for 2 hours in 5 minute intervals.


   .. py:method:: get_load_forecast_historical(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Historical load forecast in hourly intervals. Historical forecasts include all
      vintages of the forecast but has fewer regions than the current forecast.


   .. py:method:: get_load_metered_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False)

      Retrieves the hourly metered load data from:

      https://dataminer2.pjm.com/feed/hrl_load_metered/definition


   .. py:method:: get_marginal_emission_rates_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the 5-minute marginal emission rates data from PJM.

      PJM estimates marginal emissions every five minutes for load zones across the grid.
      These estimates include CO₂, SO₂, and NOₓ, expressed in lbs/MWh. The calculation
      reflects the physical costs of power flows, capturing the impact of congestion on
      nodal emissions. When imports are marginal at a node, PJM assigns them zero emissions
      because the fuel source is unknown.

      Source: https://dataminer2.pjm.com/feed/fivemin_marginal_emissions/definition

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with 5-minute marginal emission rates data.
      :rtype: pandas.DataFrame


   .. py:method:: get_marginal_value_day_ahead_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the marginal value data from:
      https://dataminer2.pjm.com/feed/da_marginal_value/definition


   .. py:method:: get_marginal_value_real_time_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the marginal value data from:
      https://dataminer2.pjm.com/feed/rt_marginal_value/definition


   .. py:method:: get_operational_reserves(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the reserve market quantities in Megawatts from:
      https://dataminer2.pjm.com/feed/operational_reserves/definition
      Only available in past 15 days.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns:

                A DataFrame with reserve market quantities
                    in 15 second intervals.
      :rtype: pandas.DataFrame


   .. py:method:: get_pai_intervals_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the 5-minute Performance Assessment Intervals (PAI) data from PJM.

      This dataset contains information on the status of Performance Assessment Intervals
      (PAIs) across PJM and subzones, updated every 5 minutes. Performance during these
      PAIs is used by PJM to determine potential penalties, or compensation, for capacity
      obligations. This dataset has 3 potential responses in the Performance Assessment
      Interval column: "No PAI", "PAI in Active Subzone", and "PAI in RTO and Active Subzone".

      Source: https://dataminer2.pjm.com/feed/fivemin_pai_interval/definition

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with 5-minute PAI intervals data.
      :rtype: pandas.DataFrame


   .. py:method:: get_pnode_ids() -> pandas.DataFrame

   .. py:method:: get_pricing_nodes(as_of: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the pricing nodes data from:
      https://dataminer2.pjm.com/feed/pnode/definition


   .. py:method:: get_projected_area_statistics_at_peak(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Area projected data for the peak of the day

      https://dataminer2.pjm.com/feed/ops_sum_frcst_peak_area/definition


   .. py:method:: get_projected_peak_tie_flow(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the projected peak tie flow data from:
      https://dataminer2.pjm.com/feed/ops_sum_prjctd_tie_flow/definition


   .. py:method:: get_projected_rto_statistics_at_peak(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      RTO-wide projected data for the peak of the day

      https://dataminer2.pjm.com/feed/ops_sum_frcst_peak_rto/definition


   .. py:method:: get_raw_interconnection_queue(verbose: bool = False) -> BinaryIO

   .. py:method:: get_real_time_as_market_results(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False)

      Retrieves the real-time ancillary service market results from :
      https://dataminer2.pjm.com/feed/reserve_market_results/definition
      Data for the previous day is published daily on business days,
      typically between 11am and 12pm market time.

      Data granularity changed on Sep 1, 2022 so when querying data,
      start and end dates must both be before or both after that date.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with real-time ancillary service
                market results.
      :rtype: pandas.DataFrame


   .. py:method:: get_regulation_market_monthly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the PJM Regulation Market Monthly data from:
      https://dataminer2.pjm.com/feed/reg_market_results/definition


   .. py:method:: get_regulation_prices_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves 5-minute regulation pricing data from:
      https://api.pjm.com/api/v1/reg_prices


   .. py:method:: get_reserve_subzone_buses(as_of: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the reserve subzone buses data from:
      https://dataminer2.pjm.com/feed/sync_pri_reserves_buses_list/definition


   .. py:method:: get_reserve_subzone_resources(as_of: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the reserve subzone resources data from:
      https://dataminer2.pjm.com/feed/sync_pri_reserves_resources_list/definition


   .. py:method:: get_scheduled_interchange_real_time(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the scheduled interchange real time data from:
      https://dataminer2.pjm.com/feed/rt_scheduled_interchange/definition


   .. py:method:: get_settlements_verified_lmp_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

   .. py:method:: get_settlements_verified_lmp_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

   .. py:method:: get_solar_forecast_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the 5-min solar forecast including behind the meter solar forecast.
      From: https://dataminer2.pjm.com/feed/five_min_solar_power_forecast/definition
      Only available in past 30 days

      :param date: Start datetime for data
      :type date: str | pd.Timestamp
      :param end: End datetime for data. Defaults to None.
      :type end: str | pd.Timestamp | None, optional
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with the solar forecast data.
      :rtype: pd.DataFrame


   .. py:method:: get_solar_forecast_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the hourly solar forecast including behind the meter solar forecast.
      From: https://dataminer2.pjm.com/feed/hourly_solar_power_forecast/definition
      Only available in past 30 days

      :param date: Start datetime for data
      :type date: str | pd.Timestamp
      :param end: End datetime for data. Defaults to None.
      :type end: str | pd.Timestamp | None, optional
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with the solar forecast data.
      :rtype: pd.DataFrame


   .. py:method:: get_solar_generation_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the 5 min solar generation data from:
      https://dataminer2.pjm.com/feed/five_min_solar_generation/definition
      Only available in past 30 days.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with 5 minute solar generation data.
      :rtype: pandas.DataFrame


   .. py:method:: get_solar_generation_by_area(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the current solar generation information from:
      https://dataminer2.pjm.com/feed/solar_gen/definition
      Data is published daily around 7am market time.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with solar generation information.
      :rtype: pandas.DataFrame


   .. py:method:: get_sync_reserve_events(verbose: bool = False) -> pandas.DataFrame

      Retrieves the synchronized reserve events data from:
      https://dataminer2.pjm.com/feed/sync_reserve_events/definition


   .. py:method:: get_tie_flows_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the PJM Tie Flows 5 Minute data from:
      https://dataminer2.pjm.com/feed/tie_flows/definition


   .. py:method:: get_transfer_interface_information_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the transfer interface information from:
      https://dataminer2.pjm.com/feed/transfer_interface_infor/definition
      Only available in past 30 days.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with transfer interface information
                in 5 minute intervals.
      :rtype: pandas.DataFrame


   .. py:method:: get_transmission_constraints_day_ahead_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the transmission constraints data from:
      https://dataminer2.pjm.com/feed/da_transconstraints/definition


   .. py:method:: get_transmission_limits(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the current transmission limit information from:
      https://dataminer2.pjm.com/feed/transfer_interface_infor/definition
      Only available in past 30 days. Data is published only when constraints
      exist for that five minute interval.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with transmission limit information
                in 5 minute intervals, when data is available.
      :rtype: pandas.DataFrame


   .. py:method:: get_voltage_limits(verbose: bool = False) -> str

      Downloads the raw voltage limits CSV file from EDART.

      The URL returns a ZIP file containing the CSV. This method extracts and returns
      the CSV content as a string.

      Source: https://edart.pjm.com/reports/voltagelimits.csv

      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: The CSV content as a string.
      :rtype: str

      :raises NoDataFoundException: If the server returns a rate limit message.


   .. py:method:: get_weight_average_aggregation_definition(as_of: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the weight average aggregation definition data from:
      https://dataminer2.pjm.com/feed/agg_definitions/definition


   .. py:method:: get_wind_forecast_5_min(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the 5-min wind forecast
      From: https://dataminer2.pjm.com/feed/five_min_wind_power_forecast/definition
      Only available in past 30 days

      :param date: Start datetime for data
      :type date: str | pd.Timestamp
      :param end: End datetime for data. Defaults to None.
      :type end: Optional[str  |  pd.Timestamp], optional
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with the wind forecast data.
      :rtype: pd.DataFrame


   .. py:method:: get_wind_forecast_hourly(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the hourly wind forecast
      From: https://dataminer2.pjm.com/feed/hourly_wind_power_forecast/definition
      Only available in past 30 days

      :param date: Start datetime for data
      :type date: str | pd.Timestamp
      :param end: End datetime for data. Defaults to None.
      :type end: Optional[str  |  pd.Timestamp], optional
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with the wind forecast data.
      :rtype: pd.DataFrame


   .. py:method:: get_wind_generation_by_area(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False)

      Retrieves the current wind generation information from:
      https://dataminer2.pjm.com/feed/wind_gen/definition
      Data is published daily around 7am market time.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns: A DataFrame with wind generation information.
      :rtype: pandas.DataFrame


   .. py:method:: get_wind_generation_instantaneous(date: str | pandas.Timestamp, end: str | pandas.Timestamp | None = None, verbose: bool = False) -> pandas.DataFrame

      Retrieves the instantaneous wind generation data from:
      https://dataminer2.pjm.com/feed/instantaneous_wind_gen/definition
      Only available in past 30 days.

      :param date: Start datetime for data
      :type date: str or pandas.Timestamp
      :param end: (str or pandas.Timestamp, optional): End datetime for data.
                  Defaults to one day past `date` if not specified.
      :param verbose: print verbose output. Defaults to False.
      :type verbose: bool, optional

      :returns:

                A DataFrame with instantaneous wind generation data
                    in 15 second intervals.
      :rtype: pandas.DataFrame


   .. py:method:: to_local_datetime(df: pandas.DataFrame, column_name: str) -> pandas.Series


