bolster.data_sources.boe_base_rate ================================== .. py:module:: bolster.data_sources.boe_base_rate .. autoapi-nested-parse:: Bank of England official Bank Rate (base rate). Wraps the Bank of England's published base-rate spreadsheet to provide standardised access to the UK policy interest rate: - A **unified daily rate** series back to 1973, formed by coalescing the successive rate regimes the BoE has used (Minimum Lending Rate, Minimum Band 1 Dealing Rate, Repo Rate and the current Official Bank Rate) into a single continuous level. - An **event-based history of rate changes** back to 1694, exposed via :func:`get_rate_changes`. The base rate is a *level* (a standing interest rate), not a flow, so when it is resampled to coarser resolutions the **last observation** in each period is used rather than a sum or mean. This is the second of three macroeconomic context modules and emits the same **fixed output schema** as :mod:`bolster.data_sources.ons_cpi`, so that the macro series can be joined and resampled against one another: ========== ========================================================== Column Description ========== ========================================================== date ``datetime64[ns]`` period-start (Jan 2024 -> 2024-01-01, Q1 2024 -> 2024-01-01, year 2024 -> 2024-01-01, a daily observation keeps its own date) year ``int`` calendar year quarter ``str`` "Q1".."Q4", or ``pd.NA`` for annual/monthly/daily month ``int`` 1-12, or ``pd.NA`` for quarterly/annual/daily resolution ``str`` "daily" | "monthly" | "quarterly" | "annual" series ``str`` always "base_rate" value ``float`` rate in per-cent unit ``str`` always "%" geography ``str`` always "UK" source ``str`` always "BoE" ========== ========================================================== .. note:: The Bank of England's dynamic statistics API (``/boe-apps/statistics-api/``, ``/boe-apps/sdw/``) returns HTTP 403 for automated requests. The static spreadsheet linked below is the only reliable programmatic route and is what this module uses. Source: https://www.bankofengland.co.uk/boeapps/database/Bank-Rate.asp .. rubric:: Example >>> from bolster.data_sources import boe_base_rate >>> df = boe_base_rate.get_latest_data(resolution="annual") # doctest: +SKIP >>> sorted(df.columns) # doctest: +SKIP ['date', 'geography', 'month', 'quarter', 'resolution', 'series', 'source', 'unit', 'value', 'year'] Attributes ---------- .. autoapisummary:: bolster.data_sources.boe_base_rate.logger bolster.data_sources.boe_base_rate.DATA_URL bolster.data_sources.boe_base_rate.RAW_DATA_SHEET bolster.data_sources.boe_base_rate.HISTORICAL_SHEET bolster.data_sources.boe_base_rate.GEOGRAPHY bolster.data_sources.boe_base_rate.SOURCE bolster.data_sources.boe_base_rate.SERIES bolster.data_sources.boe_base_rate.UNIT bolster.data_sources.boe_base_rate.SCHEMA_COLUMNS bolster.data_sources.boe_base_rate.RATE_CHANGES_COLUMNS bolster.data_sources.boe_base_rate.RESOLUTIONS Exceptions ---------- .. autoapisummary:: bolster.data_sources.boe_base_rate.BoEDataError bolster.data_sources.boe_base_rate.BoEValidationError Functions --------- .. autoapisummary:: bolster.data_sources.boe_base_rate.get_latest_data bolster.data_sources.boe_base_rate.get_rate_changes bolster.data_sources.boe_base_rate.validate_data Module Contents --------------- .. py:data:: logger .. py:data:: DATA_URL :value: 'https://www.bankofengland.co.uk/-/media/boe/files/monetary-policy/baserate.xls' .. py:data:: RAW_DATA_SHEET :value: 'Raw Data' .. py:data:: HISTORICAL_SHEET :value: 'HISTORICAL SINCE 1694' .. py:data:: GEOGRAPHY :value: 'UK' .. py:data:: SOURCE :value: 'BoE' .. py:data:: SERIES :value: 'base_rate' .. py:data:: UNIT :value: '%' .. py:data:: SCHEMA_COLUMNS :value: ['date', 'year', 'quarter', 'month', 'resolution', 'series', 'value', 'unit', 'geography', 'source'] .. py:data:: RATE_CHANGES_COLUMNS :value: ['date', 'year', 'series', 'value', 'unit', 'geography', 'source'] .. py:data:: RESOLUTIONS :value: ('daily', 'monthly', 'quarterly', 'annual') .. py:exception:: BoEDataError Bases: :py:obj:`Exception` Base exception for Bank of England data errors. Initialize self. See help(type(self)) for accurate signature. .. py:exception:: BoEValidationError Bases: :py:obj:`BoEDataError` Raised when a DataFrame fails :func:`validate_data`. Initialize self. See help(type(self)) for accurate signature. .. py:function:: get_latest_data(resolution = 'monthly', force_refresh = False) Fetch the unified UK base rate at a given resolution. The base rate is a standing level, so coarser resolutions take the **last observation** in each period (i.e. the rate in force at period end). :param resolution: "daily", "monthly" (default), "quarterly" or "annual". :param force_refresh: Accepted for API parity; binary downloads are not cached. :returns: DataFrame conforming to :data:`SCHEMA_COLUMNS`, sorted by ``date``. :raises ValueError: If ``resolution`` is not recognised. :raises BoEDataError: If the workbook download or parse fails. .. rubric:: Example >>> df = get_latest_data(resolution="annual") # doctest: +SKIP >>> df.iloc[-1][["series", "unit", "geography", "source"]].tolist() # doctest: +SKIP ['base_rate', '%', 'UK', 'BoE'] .. py:function:: get_rate_changes(force_refresh = False) Fetch the event-based history of base-rate changes back to 1694. Each row is a rate *change* effective on a given date (the value is the new rate). The series is irregular by nature. Where the source records only a year and month (the earliest entries pre-date daily records), the change is dated to the first of that month. :param force_refresh: Accepted for API parity; binary downloads are not cached. :returns: DataFrame with columns :data:`RATE_CHANGES_COLUMNS`, sorted by ``date``. :raises BoEDataError: If the workbook download or parse fails, or no changes could be parsed. .. rubric:: Example >>> df = get_rate_changes() # doctest: +SKIP >>> df.iloc[0][["date", "value"]].tolist() # doctest: +SKIP [Timestamp('1694-10-01 00:00:00'), 6.0] .. py:function:: validate_data(df) Validate that a DataFrame conforms to the macroeconomic schema. Checks performed: - All :data:`SCHEMA_COLUMNS` are present. - At least one row is present. - ``geography`` is exclusively "UK" and ``source`` exclusively "BoE". - ``series`` is exclusively "base_rate" and ``unit`` exclusively "%". - ``resolution`` only contains known values. - ``value`` is numeric, non-null and within a sane 0-25% range. :param df: DataFrame to validate. :returns: ``True`` if all checks pass. :raises BoEValidationError: If any check fails. .. rubric:: Example >>> df = get_latest_data(resolution="annual") # doctest: +SKIP >>> validate_data(df) # doctest: +SKIP True