mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-29 05:21:48 +00:00
* merge branch develop with main * bump desktop version * fix the merge * sync Cargo.lock to desktop 2.0.0 * fix cli conftest.py --------- Co-authored-by: deeleeramone <>
1854 lines
65 KiB
Python
1854 lines
65 KiB
Python
"""Test FRED API endpoints."""
|
|
|
|
import base64
|
|
from datetime import date
|
|
from math import inf, isfinite
|
|
from statistics import median
|
|
|
|
import pytest
|
|
import requests
|
|
from openbb_core.env import Env
|
|
from openbb_core.provider.utils.helpers import get_querystring
|
|
|
|
from openbb_fred.models.ameribor import MATURITY_TO_FRED_ID, FredAmeriborData
|
|
from openbb_fred.models.balance_of_payments import FredBalanceOfPaymentsData
|
|
from openbb_fred.models.bond_indices import BAML_CATEGORIES, FredBondIndicesData
|
|
from openbb_fred.models.commercial_paper import CP_SERIES_IDS, FREDCommercialPaperData
|
|
from openbb_fred.models.commodity_spot_prices import (
|
|
SERIES_MAP,
|
|
FredCommoditySpotPricesData,
|
|
)
|
|
from openbb_fred.models.consumer_price_index import FREDConsumerPriceIndexData
|
|
from openbb_fred.models.dwpcr_rates import FREDDiscountWindowPrimaryCreditRateData
|
|
from openbb_fred.models.ecb_interest_rates import (
|
|
FREDEuropeanCentralBankInterestRatesData,
|
|
)
|
|
from openbb_fred.models.economic_calendar import FredEconomicCalendarData
|
|
from openbb_fred.models.euro_short_term_rate import FredEuroShortTermRateData
|
|
from openbb_fred.models.fed_projections import FREDPROJECTIONData
|
|
from openbb_fred.models.federal_funds_rate import FredFederalFundsRateData
|
|
from openbb_fred.models.ffrmc import FREDSelectedTreasuryConstantMaturityData
|
|
from openbb_fred.models.high_quality_market import (
|
|
FredHighQualityMarketCorporateBondData,
|
|
)
|
|
from openbb_fred.models.iorb_rates import FREDIORBData
|
|
from openbb_fred.models.manufacturing_outlook_ny import FredManufacturingOutlookNYData
|
|
from openbb_fred.models.manufacturing_outlook_texas import (
|
|
FredManufacturingOutlookTexasData,
|
|
)
|
|
from openbb_fred.models.mortgage_indices import (
|
|
MORTGAGE_CHOICES_TO_ID,
|
|
FredMortgageIndicesData,
|
|
)
|
|
from openbb_fred.models.non_farm_payrolls import FredNonFarmPayrollsData
|
|
from openbb_fred.models.overnight_bank_funding_rate import (
|
|
FredOvernightBankFundingRateData,
|
|
)
|
|
from openbb_fred.models.personal_consumption_expenditures import (
|
|
FredPersonalConsumptionExpendituresData,
|
|
)
|
|
from openbb_fred.models.regional import FredRegionalData
|
|
from openbb_fred.models.release_table import FredReleaseTableData
|
|
from openbb_fred.models.retail_prices import FredRetailPricesData
|
|
from openbb_fred.models.search import FredSearchData
|
|
from openbb_fred.models.senior_loan_officer_survey import (
|
|
SLOOS_CATEGORIES,
|
|
FredSeniorLoanOfficerSurveyData,
|
|
)
|
|
from openbb_fred.models.series import FredSeriesData
|
|
from openbb_fred.models.sofr import FREDSOFRData
|
|
from openbb_fred.models.sonia_rates import FREDSONIAData
|
|
from openbb_fred.models.spot import FREDSpotRateData
|
|
from openbb_fred.models.survey_of_economic_conditions_chicago import (
|
|
FredSurveyOfEconomicConditionsChicagoData,
|
|
)
|
|
from openbb_fred.models.tbffr import FREDSelectedTreasuryBillData
|
|
from openbb_fred.models.tips_yields import FredTipsYieldsData
|
|
from openbb_fred.models.tmc import FREDTreasuryConstantMaturityData
|
|
from openbb_fred.models.university_of_michigan import FredUofMichiganData
|
|
from openbb_fred.models.yield_curve import FREDYieldCurveData
|
|
from openbb_fred.utils.api import observation_dates
|
|
from openbb_fred.utils.fred_helpers import YIELD_CURVES
|
|
|
|
PERCENT_BAND = (-100.0, 100.0)
|
|
POSITIVE_BAND = (0.0, 1.0e6)
|
|
INDEX_BAND = (0.0, 1.0e5)
|
|
COUNT_BAND = (0.0, 1.0e12)
|
|
WIDE_BAND = (-1.0e15, 1.0e15)
|
|
TRANSFORMS = ("chg", "ch1", "pch", "pc1", "pca", "cch", "cca", "log")
|
|
|
|
|
|
def results_of(result, data_class, minimum=1):
|
|
"""Return the rows one endpoint served, asserting the model shape they carry.
|
|
|
|
Parameters
|
|
----------
|
|
result : requests.Response
|
|
The endpoint response.
|
|
data_class : type
|
|
The provider Data model the rows are expected to carry.
|
|
minimum : int
|
|
The fewest rows the parameters can legitimately return.
|
|
|
|
Returns
|
|
-------
|
|
list
|
|
The rows the response envelope carries.
|
|
"""
|
|
assert isinstance(result, requests.Response)
|
|
assert result.status_code == 200
|
|
|
|
payload = result.json()
|
|
|
|
assert isinstance(payload, dict)
|
|
|
|
rows = payload["results"]
|
|
|
|
assert isinstance(rows, list)
|
|
assert len(rows) >= minimum
|
|
assert all(isinstance(row, dict) for row in rows)
|
|
assert set(data_class.model_fields) <= set(rows[0])
|
|
|
|
return rows
|
|
|
|
|
|
def dates_of(rows, field="date"):
|
|
"""Return one date per row, asserting every one of them parses as a date."""
|
|
dates = [date.fromisoformat(str(row[field])[:10]) for row in rows]
|
|
assert dates
|
|
|
|
return dates
|
|
|
|
|
|
def values_of(rows, *fields):
|
|
"""Return every value the rows carry under the named fields."""
|
|
return [row.get(field) for field in fields for row in rows]
|
|
|
|
|
|
def assert_oldest_first(dates):
|
|
"""Assert the observations are ordered oldest first."""
|
|
assert list(dates) == sorted(dates)
|
|
|
|
|
|
def assert_newest_first(dates):
|
|
"""Assert the observations are ordered newest first."""
|
|
assert list(dates) == sorted(dates, reverse=True)
|
|
|
|
|
|
def assert_inside_window(dates, params):
|
|
"""Assert every observation falls inside the window the query asked for."""
|
|
start = params.get("start_date")
|
|
end = params.get("end_date")
|
|
|
|
if start:
|
|
assert min(dates) >= date.fromisoformat(start)
|
|
|
|
if end:
|
|
assert max(dates) <= date.fromisoformat(end)
|
|
|
|
|
|
def assert_finite(values, low, high):
|
|
"""Assert the served numbers are finite and inside a plausible band.
|
|
|
|
Parameters
|
|
----------
|
|
values : list
|
|
The values read off the rows, nulls included.
|
|
low : float
|
|
The lowest value the field can plausibly carry.
|
|
high : float
|
|
The highest value the field can plausibly carry.
|
|
|
|
Returns
|
|
-------
|
|
list
|
|
The values that were actually served.
|
|
"""
|
|
seen = [value for value in values if value is not None]
|
|
assert all(isinstance(value, (int, float)) for value in seen)
|
|
assert all(isfinite(value) for value in seen)
|
|
assert all(low <= value <= high for value in seen)
|
|
|
|
return seen
|
|
|
|
|
|
def assert_months(dates, requested):
|
|
"""Assert every observation falls in one of the months the query asked for."""
|
|
months = {tuple(entry[:7].split("-")) for entry in observation_dates(requested)}
|
|
assert {(f"{value.year:04d}", f"{value.month:02d}") for value in dates} <= months
|
|
|
|
|
|
def median_gap(dates):
|
|
"""Return the median number of days between consecutive observations."""
|
|
ordered = sorted(set(dates))
|
|
assert len(ordered) > 1
|
|
|
|
return median(
|
|
(later - earlier).days for earlier, later in zip(ordered, ordered[1:])
|
|
)
|
|
|
|
|
|
def band_for(params, tight):
|
|
"""Return the band a field sits in, widened when the query transforms it."""
|
|
return WIDE_BAND if params.get("transform") in TRANSFORMS else tight
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def headers():
|
|
"""Get the headers for the API request."""
|
|
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
|
|
userpass_bytes = userpass.encode("ascii")
|
|
base64_bytes = base64.b64encode(userpass_bytes)
|
|
|
|
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
|
|
|
|
|
|
class TestCommodityPrice:
|
|
"""Test the commodity price commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"commodity": "all",
|
|
"start_date": None,
|
|
"end_date": None,
|
|
"frequency": None,
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"commodity": "wti",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "avg",
|
|
"transform": "pc1",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_commodity_spot_prices_are_served(self, params, headers):
|
|
"""Test the commodity price spot endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/commodity/price/spot?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
commodity = params.get("commodity", "all")
|
|
rows = results_of(result, FredCommoditySpotPricesData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["symbol"] for row in rows} <= set(SERIES_MAP[commodity].split(","))
|
|
assert all(row["commodity"] for row in rows)
|
|
assert assert_finite(values_of(rows, "price"), *band_for(params, POSITIVE_BAND))
|
|
|
|
if params.get("frequency") == "m":
|
|
assert len(rows) <= 13
|
|
else:
|
|
assert len(rows) > 100
|
|
|
|
|
|
class TestEconomy:
|
|
"""Test the economy commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"country": "united_states",
|
|
"start_date": None,
|
|
"end_date": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"country": "japan",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2023-12-31",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_balance_of_payments_is_served(self, params, headers):
|
|
"""Test the economy balance_of_payments endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = (
|
|
f"http://localhost:8000/api/v1/fred/economy/balance_of_payments?{query_str}"
|
|
)
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredBalanceOfPaymentsData)
|
|
periods = dates_of(rows, "period")
|
|
|
|
assert_newest_first(periods)
|
|
assert_inside_window(periods, params)
|
|
assert median_gap(periods) >= 80
|
|
assert assert_finite(
|
|
values_of(rows, "balance_total", "credits_total", "debits_total"),
|
|
*WIDE_BAND,
|
|
)
|
|
assert_finite(values_of(rows, "balance_percent_of_gdp"), -200.0, 200.0)
|
|
|
|
if params.get("start_date"):
|
|
assert len(rows) <= 24
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2025-07-01",
|
|
"end_date": "2025-07-02",
|
|
"release_id": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2024-01-02",
|
|
"end_date": "2024-01-09",
|
|
"release_id": 10,
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_calendar_is_served(self, params, headers):
|
|
"""Test the economy calendar endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/calendar?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=60)
|
|
rows = results_of(result, FredEconomicCalendarData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_inside_window(dates, params)
|
|
assert all(row["event"] for row in rows)
|
|
assert all(isinstance(row["release_id"], int) for row in rows)
|
|
|
|
if params.get("release_id"):
|
|
assert {row["release_id"] for row in rows} == {params["release_id"]}
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"country": "united_states", "provider": "fred"},
|
|
{
|
|
"country": "spain",
|
|
"transform": "yoy",
|
|
"frequency": "annual",
|
|
"harmonized": False,
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2023-06-06",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"country": "portugal,spain",
|
|
"transform": "period",
|
|
"frequency": "monthly",
|
|
"harmonized": True,
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_cpi_is_served(self, params, headers):
|
|
"""Test the economy cpi endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/cpi?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDConsumerPriceIndexData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["country"] for row in rows} <= set(params["country"].split(","))
|
|
assert assert_finite(values_of(rows, "value"), *PERCENT_BAND)
|
|
|
|
if params.get("frequency") == "annual":
|
|
assert len(rows) <= 8
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"symbol": "NYUR", "provider": "fred"},
|
|
{
|
|
"symbol": "CAICLAIMS",
|
|
"is_series_group": False,
|
|
"start_date": "1990-01-01",
|
|
"end_date": "2010-01-01",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"symbol": "156241",
|
|
"is_series_group": True,
|
|
"start_date": "2000-01-01",
|
|
"end_date": None,
|
|
"frequency": "w",
|
|
"units": "Number",
|
|
"region_type": "state",
|
|
"season": "nsa",
|
|
"aggregation_method": "eop",
|
|
"transform": "ch1",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_fred_regional_is_served(self, params, headers):
|
|
"""Test the economy fred_regional endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/fred_regional?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=60)
|
|
rows = results_of(result, FredRegionalData)
|
|
dates = dates_of(rows)
|
|
|
|
assert all(isinstance(row["region"], str) and row["region"] for row in rows)
|
|
assert all(row["series_id"] for row in rows)
|
|
assert all(row["code"] not in (None, "") for row in rows)
|
|
assert assert_finite(values_of(rows, "value"), *WIDE_BAND)
|
|
|
|
if params.get("end_date"):
|
|
assert max(dates) <= date.fromisoformat(params["end_date"])
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"release_id": "50", "provider": "fred"},
|
|
{"release_id": "14", "element_id": "7930", "provider": "fred"},
|
|
{
|
|
"release_id": "53",
|
|
"element_id": "12883",
|
|
"date": "2023-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_fred_release_table_is_served(self, params, headers):
|
|
"""Test the economy fred_release_table endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = (
|
|
f"http://localhost:8000/api/v1/fred/economy/fred_release_table?{query_str}"
|
|
)
|
|
result = requests.get(url, headers=headers, timeout=60)
|
|
rows = results_of(result, FredReleaseTableData)
|
|
keys = [
|
|
(str(row["date"] or ""), inf if row["line"] is None else row["line"])
|
|
for row in rows
|
|
]
|
|
|
|
assert keys == sorted(keys)
|
|
assert all(row["element_id"] for row in rows)
|
|
assert all(row["name"] for row in rows)
|
|
assert_finite(values_of(rows, "value"), *WIDE_BAND)
|
|
|
|
observed = [row for row in rows if row["symbol"]]
|
|
|
|
if observed:
|
|
assert dates_of(observed)
|
|
assert all(row["value"] is not None for row in observed)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{"query": "gdp", "provider": "fred"},
|
|
{
|
|
"query": "GDP*",
|
|
"search_type": "series_id",
|
|
"release_id": None,
|
|
"offset": 0,
|
|
"limit": 10,
|
|
"order_by": "observation_end",
|
|
"sort_order": "desc",
|
|
"filter_variable": None,
|
|
"filter_value": None,
|
|
"tag_names": None,
|
|
"exclude_tag_names": None,
|
|
"series_id": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"query": None,
|
|
"search_type": "release",
|
|
"release_id": 10,
|
|
"limit": 10,
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
{"series_id": "NYICLAIMS", "provider": "fred"},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_fred_search_is_served(self, params, headers):
|
|
"""Test the economy fred_search endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/fred_search?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredSearchData)
|
|
ends = [row["observation_end"] for row in rows]
|
|
|
|
if params.get("limit"):
|
|
assert len(rows) <= params["limit"]
|
|
|
|
if all(end is not None for end in ends):
|
|
assert ends == sorted(ends, reverse=True)
|
|
|
|
if params.get("series_id"):
|
|
assert {row["series_id"] for row in rows} == {params["series_id"]}
|
|
assert all(row["series_group"] for row in rows)
|
|
elif params.get("release_id"):
|
|
assert all(row["series_id"] for row in rows)
|
|
elif params.get("query"):
|
|
assert all(row["series_id"] for row in rows)
|
|
|
|
if params.get("search_type") != "series_id":
|
|
term = params["query"].lower()
|
|
assert all(
|
|
term in " ".join(str(v) for v in row.values()).lower()
|
|
for row in rows
|
|
)
|
|
else:
|
|
assert all(row["release_id"] for row in rows)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"symbol": "GDP", "provider": "fred"},
|
|
{
|
|
"symbol": "SP500",
|
|
"start_date": None,
|
|
"end_date": None,
|
|
"limit": 10000,
|
|
"frequency": "q",
|
|
"aggregation_method": "eop",
|
|
"transform": "chg",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"symbol": "GDP,UNRATE",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_fred_series_is_served(self, params, headers):
|
|
"""Test the economy fred_series endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/fred_series?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredSeriesData)
|
|
dates = dates_of(rows)
|
|
symbols = params["symbol"].split(",")
|
|
carried = {key.lower().replace("_", "") for key in rows[0]}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {symbol.lower().replace("_", "") for symbol in symbols} <= carried
|
|
assert assert_finite(
|
|
[value for row in rows for key, value in row.items() if key != "date"],
|
|
*WIDE_BAND,
|
|
)
|
|
|
|
if params.get("limit"):
|
|
assert len(rows) <= params["limit"]
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"date": "2024-05-01,2024-04-01,2023-05-01",
|
|
"category": "pce_price_index",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"date": "2024-06-01",
|
|
"category": "real_pce_percent_change",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_pce_is_served(self, params, headers):
|
|
"""Test the economy pce endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/pce?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredPersonalConsumptionExpendituresData)
|
|
dates = dates_of(rows)
|
|
keys = [(row["date"], row["line"]) for row in rows]
|
|
|
|
assert keys == sorted(keys)
|
|
assert all(row["symbol"] and row["name"] and row["units"] for row in rows)
|
|
assert all(row["element_id"] and row["parent_id"] for row in rows)
|
|
assert all(isinstance(row["level"], int) for row in rows)
|
|
assert assert_finite(values_of(rows, "value"), *WIDE_BAND)
|
|
|
|
if params.get("date"):
|
|
assert_months(dates, params["date"])
|
|
assert len(set(dates)) <= len(observation_dates(params["date"]))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{},
|
|
{"release_id": "9", "element_id": "201241"},
|
|
{
|
|
"release_id": "9",
|
|
"element_id": "201241",
|
|
"frequency": "monthly",
|
|
"limit": 4,
|
|
"use_cache": False,
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_release_table_is_served(self, params, headers):
|
|
"""Test the economy release_table endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/release_table?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=60)
|
|
|
|
assert isinstance(result, requests.Response)
|
|
assert result.status_code == 200
|
|
|
|
served = result.json()
|
|
fixed = {"series", "symbol", "units", "trend"}
|
|
|
|
assert isinstance(served, list)
|
|
assert len(served) > 0
|
|
assert all(isinstance(row, dict) for row in served)
|
|
assert all(fixed <= set(row) for row in served)
|
|
assert all(row["series"] for row in served)
|
|
|
|
periods = [key for key in served[0] if key not in fixed]
|
|
|
|
assert periods
|
|
assert len(periods) <= params.get("limit", 8)
|
|
assert all(date.fromisoformat(period) for period in periods)
|
|
assert all(set(row) - fixed == set(periods) for row in served)
|
|
|
|
observed = [row for row in served if row["symbol"]]
|
|
|
|
assert observed
|
|
assert all(isinstance(row["trend"], list) and row["trend"] for row in observed)
|
|
assert assert_finite(
|
|
[value for row in observed for value in row["trend"]], *WIDE_BAND
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"country": "united_states",
|
|
"item": "meats",
|
|
"region": "all_city",
|
|
"frequency": "annual",
|
|
"start_date": "2022-01-01",
|
|
"end_date": "2024-04-01",
|
|
"transform": "pc1",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"item": "eggs",
|
|
"region": "northeast",
|
|
"frequency": "monthly",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_retail_prices_are_served(self, params, headers):
|
|
"""Test the economy retail_prices endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/retail_prices?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredRetailPricesData)
|
|
dates = dates_of(rows)
|
|
keys = [(row["date"], row["description"]) for row in rows]
|
|
|
|
assert keys == sorted(keys)
|
|
assert_inside_window(dates, params)
|
|
assert {row["country"] for row in rows} == {"united_states"}
|
|
assert all(row["symbol"] and row["description"] for row in rows)
|
|
assert assert_finite(values_of(rows, "value"), *band_for(params, POSITIVE_BAND))
|
|
|
|
|
|
class TestEconomySurvey:
|
|
"""Test the economy survey commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2024-01-01",
|
|
"end_date": "2024-04-01",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "quarter",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_economic_conditions_chicago_is_served(self, params, headers):
|
|
"""Test the economy survey economic_conditions_chicago endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/survey/economic_conditions_chicago?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredSurveyOfEconomicConditionsChicagoData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(
|
|
values_of(rows, "activity_index", "one_year_outlook", "current_hiring"),
|
|
*band_for(params, PERCENT_BAND),
|
|
)
|
|
|
|
if params.get("frequency") == "quarter":
|
|
assert len(rows) <= 20
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"topic": "new_orders",
|
|
"start_date": "2024-01-01",
|
|
"end_date": "2024-04-01",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"topic": "business_outlook,employment",
|
|
"seasonally_adjusted": True,
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "quarter",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_manufacturing_outlook_ny_is_served(self, params, headers):
|
|
"""Test the economy survey manufacturing_outlook_ny endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/survey/manufacturing_outlook_ny?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredManufacturingOutlookNYData)
|
|
dates = dates_of(rows)
|
|
topics = params.get("topic", "new_orders").split(",")
|
|
expected = {
|
|
f"{side}_{topic}" for topic in topics for side in ("current", "future")
|
|
}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["topic"] for row in rows} <= expected
|
|
assert assert_finite(
|
|
values_of(rows, "diffusion_index"), *band_for(params, PERCENT_BAND)
|
|
)
|
|
assert_finite(
|
|
values_of(
|
|
rows,
|
|
"percent_reporting_increase",
|
|
"percent_reporting_decrease",
|
|
"percent_reporting_no_change",
|
|
),
|
|
*band_for(params, (0.0, 100.0)),
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"topic": "new_orders",
|
|
"start_date": "2024-01-01",
|
|
"end_date": "2024-04-01",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"topic": "business_activity,production",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "annual",
|
|
"aggregation_method": "eop",
|
|
"transform": "ch1",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_manufacturing_outlook_texas_is_served(self, params, headers):
|
|
"""Test the economy survey manufacturing_outlook_texas endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/survey/manufacturing_outlook_texas?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredManufacturingOutlookTexasData)
|
|
dates = dates_of(rows)
|
|
topics = params.get("topic", "new_orders_growth").split(",")
|
|
expected = {
|
|
f"{side}_{topic}" for topic in topics for side in ("current", "future")
|
|
}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["topic"] for row in rows} <= expected
|
|
assert assert_finite(
|
|
values_of(rows, "diffusion_index"), *band_for(params, PERCENT_BAND)
|
|
)
|
|
|
|
if params.get("frequency") == "annual":
|
|
assert len(rows) <= 5 * len(expected)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"date": "2024-06-01,2023-06-01",
|
|
"category": "avg_earnings_hourly",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"date": "2024-06-01",
|
|
"category": "employees_sa",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_nonfarm_payrolls_are_served(self, params, headers):
|
|
"""Test the economy survey nonfarm_payrolls endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/survey/nonfarm_payrolls?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredNonFarmPayrollsData)
|
|
dates = dates_of(rows)
|
|
category = params.get("category", "employees_nsa")
|
|
|
|
assert_oldest_first(dates)
|
|
assert all(row["symbol"] and row["name"] for row in rows)
|
|
assert all(row["element_id"] and row["parent_id"] for row in rows)
|
|
assert all(isinstance(row["level"], int) for row in rows)
|
|
|
|
if category.startswith("employees") and not category.endswith("percent"):
|
|
assert assert_finite(values_of(rows, "value"), *COUNT_BAND)
|
|
else:
|
|
assert assert_finite(values_of(rows, "value"), *WIDE_BAND)
|
|
|
|
if params.get("date"):
|
|
assert_months(dates, params["date"])
|
|
assert len(set(dates)) <= len(observation_dates(params["date"]))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"category": "auto",
|
|
"start_date": "2022-01-01",
|
|
"end_date": "2024-04-01",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"category": "credit_card",
|
|
"transform": "pch",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_sloos_is_served(self, params, headers):
|
|
"""Test the economy survey sloos endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/survey/sloos?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredSeniorLoanOfficerSurveyData)
|
|
dates = dates_of(rows)
|
|
wanted = SLOOS_CATEGORIES[params.get("category", "spreads")].split(",")
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["symbol"] for row in rows} <= set(wanted)
|
|
assert all(row["title"] for row in rows)
|
|
assert assert_finite(values_of(rows, "value"), *band_for(params, PERCENT_BAND))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"frequency": None,
|
|
"start_date": "2022-01-01",
|
|
"end_date": "2024-04-01",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"frequency": "quarter",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_university_of_michigan_is_served(self, params, headers):
|
|
"""Test the economy survey university_of_michigan endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/economy/survey/university_of_michigan?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredUofMichiganData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(
|
|
values_of(rows, "consumer_sentiment"), *band_for(params, (0.0, 200.0))
|
|
)
|
|
assert assert_finite(
|
|
values_of(rows, "inflation_expectation"),
|
|
*band_for(params, PERCENT_BAND),
|
|
)
|
|
|
|
if params.get("frequency") == "quarter":
|
|
assert len(rows) <= 20
|
|
|
|
|
|
class TestFixedIncome:
|
|
"""Test the top-level fixed income commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"category": "high_yield",
|
|
"index": "us,europe,emerging",
|
|
"index_type": "total_return",
|
|
"start_date": "2023-05-31",
|
|
"end_date": "2024-06-01",
|
|
"transform": None,
|
|
"frequency": None,
|
|
"aggregation_method": "avg",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"category": "us",
|
|
"index": "corporate",
|
|
"index_type": "oas",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "eop",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_bond_indices_are_served(self, params, headers):
|
|
"""Test the fixedincome bond_indices endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/bond_indices?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredBondIndicesData)
|
|
dates = dates_of(rows)
|
|
index = params.get("index", "yield_curve")
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert all(row["title"] for row in rows)
|
|
|
|
if index == "yield_curve":
|
|
maturities = set(BAML_CATEGORIES[params.get("category", "us")][index])
|
|
assert {row["maturity"] for row in rows} <= maturities
|
|
else:
|
|
assert {row["maturity"] for row in rows} == {None}
|
|
|
|
if params.get("index_type") == "total_return":
|
|
assert assert_finite(values_of(rows, "value"), *INDEX_BAND)
|
|
else:
|
|
assert assert_finite(values_of(rows, "value"), *PERCENT_BAND)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"index": "usda_30y,fha_30y",
|
|
"start_date": "2023-05-31",
|
|
"end_date": "2024-06-01",
|
|
"transform": None,
|
|
"frequency": None,
|
|
"aggregation_method": "avg",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"index": "conforming_30y",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "eop",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_mortgage_indices_are_served(self, params, headers):
|
|
"""Test the fixedincome mortgage_indices endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/mortgage_indices?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredMortgageIndicesData)
|
|
dates = dates_of(rows)
|
|
wanted = {
|
|
symbol
|
|
for index in params.get("index", "primary").split(",")
|
|
for symbol in MORTGAGE_CHOICES_TO_ID[index].split(",")
|
|
}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["symbol"] for row in rows} <= wanted
|
|
assert all(row["name"] for row in rows)
|
|
assert assert_finite(values_of(rows, "rate"), *band_for(params, PERCENT_BAND))
|
|
|
|
|
|
class TestFixedIncomeCorporate:
|
|
"""Test the corporate bond commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"maturity": "overnight",
|
|
"category": "financial",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"maturity": "30d",
|
|
"category": "asset_backed",
|
|
"frequency": "m",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_commercial_paper_is_served(self, params, headers):
|
|
"""Test the fixedincome corporate commercial_paper endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/corporate/commercial_paper?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDCommercialPaperData)
|
|
dates = dates_of(rows)
|
|
maturity = params.get("maturity", "all")
|
|
category = params.get("category", "all")
|
|
published = {
|
|
(entry["maturity"], entry["asset"]) for entry in CP_SERIES_IDS.values()
|
|
}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {(row["maturity"], row["asset_type"]) for row in rows} <= published
|
|
assert all(row["title"] for row in rows)
|
|
assert assert_finite(values_of(rows, "rate"), *band_for(params, PERCENT_BAND))
|
|
|
|
if category != "all":
|
|
assert {row["asset_type"] for row in rows} == set(category.split(","))
|
|
|
|
if maturity != "all":
|
|
assert {row["maturity"] for row in rows} == {
|
|
entry if entry == "overnight" else f"day_{entry.rstrip('d')}"
|
|
for entry in maturity.split(",")
|
|
}
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{"date": "2023-01-01", "yield_curve": "spot", "provider": "fred"},
|
|
{
|
|
"date": "2023-01-01,2024-01-01",
|
|
"yield_curve": "par",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_hqm_is_served(self, params, headers):
|
|
"""Test the fixedincome corporate hqm endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/corporate/hqm?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredHighQualityMarketCorporateBondData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert all(row["maturity"].startswith("year_") for row in rows)
|
|
assert all(float(row["maturity"][len("year_") :]) > 0 for row in rows)
|
|
assert assert_finite(values_of(rows, "rate"), *PERCENT_BAND)
|
|
assert 1 <= len(set(dates)) <= len(observation_dates(params.get("date")))
|
|
|
|
if params.get("date"):
|
|
assert_months(dates, params["date"])
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"maturity": "10",
|
|
"category": "spot_rate",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": None,
|
|
"end_date": None,
|
|
"maturity": "1,5.5,10",
|
|
"category": "spot_rate,par_yield",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_spot_rates_are_served(self, params, headers):
|
|
"""Test the fixedincome corporate spot_rates endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/corporate/spot_rates?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDSpotRateData)
|
|
dates = dates_of(rows)
|
|
labels = {"spot_rate": "Spot Rate", "par_yield": "Par Yield"}
|
|
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(values_of(rows, "rate"), *PERCENT_BAND)
|
|
assert all("High Quality Market (HQM)" in row["title"] for row in rows)
|
|
|
|
if params.get("maturity"):
|
|
heads = tuple(
|
|
f"{entry}-Year" for entry in str(params["maturity"]).split(",")
|
|
)
|
|
assert all(row["title"].startswith(heads) for row in rows)
|
|
|
|
if params.get("category"):
|
|
wanted = {labels[entry] for entry in str(params["category"]).split(",")}
|
|
assert {row["title"].rsplit("Bond ", 1)[-1] for row in rows} == wanted
|
|
|
|
|
|
class TestFixedIncomeGovernment:
|
|
"""Test the government bond commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"maturity": None,
|
|
"start_date": None,
|
|
"end_date": None,
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"maturity": "10",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "eop",
|
|
"transform": "pc1",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_tips_yields_are_served(self, params, headers):
|
|
"""Test the fixedincome government tips_yields endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/government/tips_yields?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=60)
|
|
rows = results_of(result, FredTipsYieldsData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert all(row["symbol"].startswith("DTP") for row in rows)
|
|
assert dates_of(rows, "due")
|
|
assert all(row["name"] for row in rows)
|
|
assert assert_finite(values_of(rows, "value"), *band_for(params, PERCENT_BAND))
|
|
|
|
if params.get("maturity"):
|
|
assert all(
|
|
row["symbol"].rsplit("DTP", 1)[-1].startswith(params["maturity"])
|
|
for row in rows
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"yield_curve_type": "nominal",
|
|
"date": "2023-05-01,2024-05-01",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"yield_curve_type": "real",
|
|
"date": None,
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_yield_curve_is_served(self, params, headers):
|
|
"""Test the fixedincome government yield_curve endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/government/yield_curve?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDYieldCurveData)
|
|
dates = dates_of(rows)
|
|
curve = params.get("yield_curve_type", "nominal")
|
|
maturities = set(YIELD_CURVES[curve].values())
|
|
wanted = len(str(params["date"]).split(",")) if params.get("date") else 1
|
|
served = [
|
|
value
|
|
for value in values_of(rows, "rate")
|
|
if value is not None and isfinite(value)
|
|
]
|
|
|
|
assert_oldest_first(dates)
|
|
assert {row["maturity"] for row in rows} <= maturities
|
|
assert len(set(dates)) == wanted
|
|
assert len(rows) == wanted * len({row["maturity"] for row in rows})
|
|
assert served
|
|
assert all(PERCENT_BAND[0] <= value <= PERCENT_BAND[1] for value in served)
|
|
|
|
|
|
class TestFixedIncomeRate:
|
|
"""Test the reference rate commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"maturity": "overnight",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"maturity": "average_30d,term_90d",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_ameribor_is_served(self, params, headers):
|
|
"""Test the fixedincome rate ameribor endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/ameribor?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredAmeriborData)
|
|
dates = dates_of(rows)
|
|
wanted = {
|
|
symbol
|
|
for entry in params.get("maturity", "all").split(",")
|
|
for symbol in MATURITY_TO_FRED_ID[entry].split(",")
|
|
}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert {row["symbol"] for row in rows} <= wanted
|
|
assert {row["maturity"] for row in rows} <= {"overnight", "day_30", "day_90"}
|
|
assert all(row["title"] for row in rows)
|
|
assert assert_finite(values_of(rows, "rate"), *band_for(params, PERCENT_BAND))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"parameter": "daily_excl_weekend",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"parameter": "weekly",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_dpcredit_is_served(self, params, headers):
|
|
"""Test the fixedincome rate dpcredit endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/dpcredit?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDDiscountWindowPrimaryCreditRateData)
|
|
dates = dates_of(rows)
|
|
cadence = {"daily_excl_weekend": (1, 4), "weekly": (6, 8)}
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
assert assert_finite(values_of(rows, "rate"), 0.0, 25.0)
|
|
|
|
low, high = cadence[params.get("parameter", "daily_excl_weekend")]
|
|
assert low <= median_gap(dates) <= high
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"interest_rate_type": "lending",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"interest_rate_type": "deposit",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_ecb_is_served(self, params, headers):
|
|
"""Test the fixedincome rate ecb endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/ecb?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDEuropeanCentralBankInterestRatesData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
assert assert_finite(values_of(rows, "rate"), -5.0, 25.0)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"frequency": "w",
|
|
"transform": None,
|
|
"aggregation_method": "avg",
|
|
"effr_only": False,
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"effr_only": True,
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_effr_is_served(self, params, headers):
|
|
"""Test the fixedincome rate effr endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/effr?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredFederalFundsRateData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(values_of(rows, "rate"), *PERCENT_BAND)
|
|
|
|
if params.get("effr_only"):
|
|
assert {row["target_range_upper"] for row in rows} == {None}
|
|
assert {row["volume"] for row in rows} == {None}
|
|
else:
|
|
assert assert_finite(
|
|
values_of(rows, "target_range_upper", "target_range_lower"),
|
|
*PERCENT_BAND,
|
|
)
|
|
assert assert_finite(
|
|
values_of(rows, "volume"), *band_for(params, COUNT_BAND)
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{"long_run": False, "provider": "fred"},
|
|
{"long_run": True, "use_cache": False, "provider": "fred"},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_effr_forecast_is_served(self, params, headers):
|
|
"""Test the fixedincome rate effr_forecast endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = (
|
|
f"http://localhost:8000/api/v1/fred/fixedincome/rate/effr_forecast?"
|
|
f"{query_str}"
|
|
)
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDPROJECTIONData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert assert_finite(
|
|
values_of(rows, "median", "range_high", "range_low"), -5.0, 25.0
|
|
)
|
|
assert all(
|
|
row["range_low"] <= row["median"] <= row["range_high"]
|
|
for row in rows
|
|
if None not in (row["range_low"], row["median"], row["range_high"])
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_estr_is_served(self, params, headers):
|
|
"""Test the fixedincome rate estr endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/estr?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredEuroShortTermRateData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(values_of(rows, "rate"), *band_for(params, PERCENT_BAND))
|
|
assert_finite(
|
|
values_of(rows, "number_of_banks"), *band_for(params, (0.0, 1000.0))
|
|
)
|
|
assert_finite(values_of(rows, "transactions"), *band_for(params, COUNT_BAND))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{"start_date": "2023-01-01", "end_date": "2023-06-06", "provider": "fred"},
|
|
{
|
|
"start_date": "2021-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_iorb_is_served(self, params, headers):
|
|
"""Test the fixedincome rate iorb endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/iorb?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDIORBData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
assert assert_finite(values_of(rows, "rate"), 0.0, 25.0)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"frequency": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "eop",
|
|
"transform": "chg",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_overnight_bank_funding_is_served(self, params, headers):
|
|
"""Test the fixedincome rate overnight_bank_funding endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/overnight_bank_funding?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FredOvernightBankFundingRateData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(values_of(rows, "rate"), *band_for(params, PERCENT_BAND))
|
|
assert_finite(
|
|
values_of(rows, "percentile_1", "percentile_99"),
|
|
*band_for(params, PERCENT_BAND),
|
|
)
|
|
assert_finite(values_of(rows, "volume"), *band_for(params, COUNT_BAND))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"frequency": None,
|
|
"transform": None,
|
|
"aggregation_method": None,
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2024-01-01",
|
|
"frequency": "m",
|
|
"aggregation_method": "avg",
|
|
"transform": "pch",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_sofr_is_served(self, params, headers):
|
|
"""Test the fixedincome rate sofr endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/sofr?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDSOFRData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert assert_finite(values_of(rows, "rate"), *band_for(params, PERCENT_BAND))
|
|
assert_finite(
|
|
values_of(rows, "average_30d", "average_180d"),
|
|
*band_for(params, PERCENT_BAND),
|
|
)
|
|
assert_finite(values_of(rows, "volume"), *band_for(params, COUNT_BAND))
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"parameter": "rate",
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"parameter": "index",
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_sonia_is_served(self, params, headers):
|
|
"""Test the fixedincome rate sonia endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/rate/sonia?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDSONIAData)
|
|
dates = dates_of(rows)
|
|
rates = values_of(rows, "rate")
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
|
|
if params.get("parameter") == "index":
|
|
assert assert_finite(rates, 0.0, 1.0e6)
|
|
else:
|
|
assert assert_finite(rates, -5.0, 25.0)
|
|
|
|
|
|
class TestFixedIncomeSpreads:
|
|
"""Test the rate spread commands the FRED router serves."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"maturity": "3m",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"maturity": "2y",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_tcm_is_served(self, params, headers):
|
|
"""Test the fixedincome spreads tcm endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/spreads/tcm?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDTreasuryConstantMaturityData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
assert assert_finite(values_of(rows, "rate"), -25.0, 25.0)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"maturity": "10y",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"maturity": "6m",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_tcm_effr_is_served(self, params, headers):
|
|
"""Test the fixedincome spreads tcm_effr endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/spreads/tcm_effr?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDSelectedTreasuryConstantMaturityData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
assert assert_finite(values_of(rows, "rate"), -25.0, 25.0)
|
|
|
|
@pytest.mark.parametrize(
|
|
"params",
|
|
[
|
|
{"provider": "fred"},
|
|
{
|
|
"start_date": "2023-01-01",
|
|
"end_date": "2023-06-06",
|
|
"maturity": "3m",
|
|
"provider": "fred",
|
|
},
|
|
{
|
|
"start_date": "2020-01-01",
|
|
"end_date": "2024-01-01",
|
|
"maturity": "6m",
|
|
"use_cache": False,
|
|
"provider": "fred",
|
|
},
|
|
],
|
|
)
|
|
@pytest.mark.integration
|
|
def test_treasury_effr_is_served(self, params, headers):
|
|
"""Test the fixedincome spreads treasury_effr endpoint."""
|
|
params = {p: v for p, v in params.items() if v is not None}
|
|
|
|
query_str = get_querystring(params, [])
|
|
url = f"http://localhost:8000/api/v1/fred/fixedincome/spreads/treasury_effr?{query_str}"
|
|
result = requests.get(url, headers=headers, timeout=30)
|
|
rows = results_of(result, FREDSelectedTreasuryBillData)
|
|
dates = dates_of(rows)
|
|
|
|
assert_oldest_first(dates)
|
|
assert_inside_window(dates, params)
|
|
assert len(set(dates)) == len(dates)
|
|
assert assert_finite(values_of(rows, "rate"), -25.0, 25.0)
|