[Feature] Add PCE (Personal Consumption Expenditures) reports to Economy (#6578)

* add PCE reports to Economy

* query.date

---------

Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
This commit is contained in:
Danglewood
2024-07-11 08:28:28 -07:00
committed by GitHub
parent afb8a53b82
commit 0c601d2c3c
11 changed files with 736 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
"""Personal Consumption Expenditures Standard Model."""
from datetime import date as dateType
from typing import Optional, Union
from pydantic import Field
from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS,
)
class PersonalConsumptionExpendituresQueryParams(QueryParams):
"""Personal Consumption Expenditures Query."""
date: Optional[Union[dateType, str]] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("date", "")
+ " Default is the latest report.",
)
class PersonalConsumptionExpendituresData(Data):
"""Personal Consumption Expenditures Data."""
date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", ""))
symbol: str = Field(description=DATA_DESCRIPTIONS.get("symbol", ""))
value: float = Field(description=DATA_DESCRIPTIONS.get("value", ""))

View File

@@ -973,3 +973,27 @@ def test_economy_survey_nonfarm_payrolls(params, headers):
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@parametrize(
"params",
[
(
{
"provider": "fred",
"date": "2024-05-01,2024-04-01,2023-05-01",
"category": "pce_price_index",
}
),
],
)
@pytest.mark.integration
def test_economy_pce(params, headers):
"""Test the economy pce endpoint"""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/pce?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -921,3 +921,26 @@ def test_economy_survey_nonfarm_payrolls(params, obb):
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@parametrize(
"params",
[
(
{
"provider": "fred",
"date": "2024-05-01,2024-04-01,2023-05-01",
"category": "pce_price_index",
}
),
],
)
@pytest.mark.integration
def test_economy_pce(params, obb):
"""Test the economy pce endpoint"""
params = {p: v for p, v in params.items() if v}
result = obb.economy.pce(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -539,3 +539,27 @@ async def primary_dealer_positioning(
) -> OBBject:
"""Get Primary dealer positioning statistics."""
return await OBBject.from_query(Query(**locals()))
@router.command(
model="PersonalConsumptionExpenditures",
examples=[
APIEx(parameters={"provider": "fred"}),
APIEx(
description="Get reports for multiple dates, entered as a comma-separated string.",
parameters={
"provider": "fred",
"date": "2024-05-01,2024-04-01,2023-05-01",
"category": "pce_price_index",
},
),
],
)
async def pce(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get Personal Consumption Expenditures (PCE) reports."""
return await OBBject.from_query(Query(**locals()))

View File

@@ -7955,6 +7955,160 @@
},
"model": "PrimaryDealerPositioning"
},
"/economy/pce": {
"deprecated": {
"flag": null,
"message": null
},
"description": "Get Personal Consumption Expenditures (PCE) reports.",
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.pce(provider='fred')\n# Get reports for multiple dates, entered as a comma-separated string.\nobb.economy.pce(provider='fred', date='2024-05-01,2024-04-01,2023-05-01', category=pce_price_index)\n```\n\n",
"parameters": {
"standard": [
{
"name": "date",
"type": "Union[Union[Union[str, date], str], List[Union[Union[str, date], str]]]",
"description": "A specific date to get data for. Default is the latest report. Multiple items allowed for provider(s): fred.",
"default": null,
"optional": true,
"choices": null
},
{
"name": "provider",
"type": "Literal['fred']",
"description": "The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: fred.",
"default": null,
"optional": true
}
],
"fred": [
{
"name": "category",
"type": "Literal['personal_income', 'wages_by_industry', 'real_pce_percent_change', 'real_pce_quantity_index', 'pce_price_index', 'pce_dollars', 'real_pce_chained_dollars', 'pce_price_percent_change']",
"description": "The category to query.",
"default": "personal_income",
"optional": true,
"choices": [
"personal_income",
"wages_by_industry",
"real_pce_percent_change",
"real_pce_quantity_index",
"pce_price_index",
"pce_dollars",
"real_pce_chained_dollars",
"pce_price_percent_change"
]
}
]
},
"returns": {
"OBBject": [
{
"name": "results",
"type": "List[PersonalConsumptionExpenditures]",
"description": "Serializable results."
},
{
"name": "provider",
"type": "Optional[Literal['fred']]",
"description": "Provider name."
},
{
"name": "warnings",
"type": "Optional[List[Warning_]]",
"description": "List of warnings."
},
{
"name": "chart",
"type": "Optional[Chart]",
"description": "Chart object."
},
{
"name": "extra",
"type": "Dict[str, Any]",
"description": "Extra info."
}
]
},
"data": {
"standard": [
{
"name": "date",
"type": "date",
"description": "The date of the data.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "symbol",
"type": "str",
"description": "Symbol representing the entity requested in the data.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "value",
"type": "float",
"description": "",
"default": "",
"optional": false,
"choices": null
}
],
"fred": [
{
"name": "name",
"type": "str",
"description": "The name of the series.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "element_id",
"type": "str",
"description": "The element id in the parent/child relationship.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "parent_id",
"type": "str",
"description": "The parent id in the parent/child relationship.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "children",
"type": "str",
"description": "The element_id of each child, as a comma-separated string.",
"default": null,
"optional": true,
"choices": null
},
{
"name": "level",
"type": "int",
"description": "The indentation level of the element.",
"default": "",
"optional": false,
"choices": null
},
{
"name": "line",
"type": "int",
"description": "The line number of the series in the table.",
"default": "",
"optional": false,
"choices": null
}
]
},
"model": "PersonalConsumptionExpenditures"
},
"/equity/calendar/ipo": {
"deprecated": {
"flag": null,

View File

@@ -29,6 +29,7 @@ class ROUTER_economy(Container):
indicators
long_term_interest_rate
money_measures
pce
primary_dealer_positioning
retail_prices
risk_premium
@@ -1806,6 +1807,96 @@ class ROUTER_economy(Container):
)
)
@exception_handler
@validate
def pce(
self,
date: Annotated[
Union[str, datetime.date, None, List[Union[str, datetime.date, None]]],
OpenBBField(
description="A specific date to get data for. Default is the latest report. Multiple comma separated items allowed for provider(s): fred."
),
] = None,
provider: Annotated[
Optional[Literal["fred"]],
OpenBBField(
description="The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: fred."
),
] = None,
**kwargs
) -> OBBject:
"""Get Personal Consumption Expenditures (PCE) reports.
Parameters
----------
date : Union[str, datetime.date, None, List[Union[str, datetime.d...
A specific date to get data for. Default is the latest report. Multiple comma separated items allowed for provider(s): fred.
provider : Optional[Literal['fred']]
The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: fred.
category : Literal['personal_income', 'wages_by_industry', 'real_pce_percent_change', 'real_pce_quantity_index', 'pce_price_index', 'pce_dollars', 'real_pce_chained_dollars', 'pce_price_percent_change']
The category to query. (provider: fred)
Returns
-------
OBBject
results : List[PersonalConsumptionExpenditures]
Serializable results.
provider : Optional[Literal['fred']]
Provider name.
warnings : Optional[List[Warning_]]
List of warnings.
chart : Optional[Chart]
Chart object.
extra : Dict[str, Any]
Extra info.
PersonalConsumptionExpenditures
-------------------------------
date : date
The date of the data.
symbol : str
Symbol representing the entity requested in the data.
value : float
name : Optional[str]
The name of the series. (provider: fred)
element_id : Optional[str]
The element id in the parent/child relationship. (provider: fred)
parent_id : Optional[str]
The parent id in the parent/child relationship. (provider: fred)
children : Optional[str]
The element_id of each child, as a comma-separated string. (provider: fred)
level : Optional[int]
The indentation level of the element. (provider: fred)
line : Optional[int]
The line number of the series in the table. (provider: fred)
Examples
--------
>>> from openbb import obb
>>> obb.economy.pce(provider='fred')
>>> # Get reports for multiple dates, entered as a comma-separated string.
>>> obb.economy.pce(provider='fred', date='2024-05-01,2024-04-01,2023-05-01', category='pce_price_index')
""" # noqa: E501
return self._run(
"/economy/pce",
**filter_inputs(
provider_choices={
"provider": self._get_provider(
provider,
"economy.pce",
("fred",),
)
},
standard_params={
"date": date,
},
extra_params=kwargs,
info={"date": {"fred": {"multiple_items_allowed": True}}},
)
)
@exception_handler
@validate
def primary_dealer_positioning(

View File

@@ -28,6 +28,9 @@ from openbb_fred.models.non_farm_payrolls import FredNonFarmPayrollsFetcher
from openbb_fred.models.overnight_bank_funding_rate import (
FredOvernightBankFundingRateFetcher,
)
from openbb_fred.models.personal_consumption_expenditures import (
FredPersonalConsumptionExpendituresFetcher,
)
from openbb_fred.models.regional import FredRegionalDataFetcher
from openbb_fred.models.retail_prices import FredRetailPricesFetcher
from openbb_fred.models.search import (
@@ -78,6 +81,7 @@ Research division of the Federal Reserve Bank of St. Louis that has more than
"MortgageIndices": FredMortgageIndicesFetcher,
"NonFarmPayrolls": FredNonFarmPayrollsFetcher,
"OvernightBankFundingRate": FredOvernightBankFundingRateFetcher,
"PersonalConsumptionExpenditures": FredPersonalConsumptionExpendituresFetcher,
"CommercialPaper": FREDCommercialPaperFetcher,
"FredSearch": FredSearchFetcher,
"FredSeries": FredSeriesFetcher,

View File

@@ -0,0 +1,246 @@
"""FRED Personal Consumption Expenditures Model."""
# pylint: disable=unused-argument
from datetime import date as dateType
from typing import Any, Dict, List, Literal, Optional
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.personal_consumption_expenditures import (
PersonalConsumptionExpendituresData,
PersonalConsumptionExpendituresQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from pydantic import Field, field_validator
PCE_CATEGORY_TO_EID = {
"personal_income": "155443",
"wages_by_industry": "3151",
"real_pce_percent_change": "3160",
"real_pce_quantity_index": "3196",
"pce_price_index": "3208",
"pce_dollars": "3220",
"real_pce_chained_dollars": "3232",
"pce_price_percent_change": "3172",
}
class FredPersonalConsumptionExpendituresQueryParams(
PersonalConsumptionExpendituresQueryParams
):
"""FRED Personal Consumption Expenditures Query."""
__json_schema_extra__ = {"date": {"multiple_items_allowed": True}}
category: Literal[
"personal_income",
"wages_by_industry",
"real_pce_percent_change",
"real_pce_quantity_index",
"pce_price_index",
"pce_dollars",
"real_pce_chained_dollars",
"pce_price_percent_change",
] = Field(
default="personal_income",
description="The category to query.",
json_schema_extra={"choices": list(PCE_CATEGORY_TO_EID)},
)
@field_validator("date", mode="before", check_fields=False)
@classmethod
def validate_date(cls, v):
"""Validate the dates entered."""
if v is None:
return None
if isinstance(v, (list, dateType)):
return v
new_dates: List = []
date_param = v
if isinstance(date_param, str):
new_dates = date_param.split(",")
elif isinstance(date_param, dateType):
new_dates.append(date_param.strftime("%Y-%m-%d"))
elif isinstance(date_param, list) and isinstance(date_param[0], dateType):
new_dates = [d.strftime("%Y-%m-%d") for d in new_dates]
else:
new_dates = date_param
return ",".join(new_dates) if len(new_dates) > 1 else new_dates[0]
class FredPersonalConsumptionExpendituresData(PersonalConsumptionExpendituresData):
"""FRED Personal Consumption Expenditures Data."""
__alias_dict__ = {
"date": "observation_date",
"value": "observation_value",
"symbol": "series_id",
}
name: str = Field(
description="The name of the series.",
)
element_id: str = Field(
description="The element id in the parent/child relationship.",
)
parent_id: str = Field(
description="The parent id in the parent/child relationship.",
)
children: Optional[str] = Field(
default=None,
description="The element_id of each child, as a comma-separated string.",
)
level: int = Field(
description="The indentation level of the element.",
)
line: int = Field(
description="The line number of the series in the table.",
)
class FredPersonalConsumptionExpendituresFetcher(
Fetcher[
FredPersonalConsumptionExpendituresQueryParams,
List[FredPersonalConsumptionExpendituresData],
]
):
"""FRED Personal Consumption Expenditures Fetcher."""
@staticmethod
def transform_query(
params: Dict[str, Any]
) -> FredPersonalConsumptionExpendituresQueryParams:
"""Transform query."""
return FredPersonalConsumptionExpendituresQueryParams(**params)
@staticmethod
async def aextract_data(
query: FredPersonalConsumptionExpendituresQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> List[Dict]:
"""Extract data."""
# pylint: disable=import-outside-toplevel
import asyncio # noqa
from openbb_core.provider.utils.helpers import amake_request
from numpy import nan
from pandas import DataFrame, to_datetime
api_key = credentials.get("fred_api_key") if credentials else ""
element_id = PCE_CATEGORY_TO_EID[query.category]
dates: List = [""]
if query.date:
if isinstance(query.date, dateType):
query.date = query.date.strftime("%Y-%m-%d")
dates = query.date.split(",") # type: ignore
dates = [d.replace(d[-2:], "01") if len(d) == 10 else d for d in dates]
dates = list(set(dates))
dates = (
[f"&observation_date={date}" for date in dates if date] if dates else "" # type: ignore
)
URLS = [
f"https://api.stlouisfed.org/fred/release/tables?release_id=54&element_id={element_id}"
+ f"{date}&include_observation_values=true&api_key={api_key}"
+ "&file_type=json"
for date in dates
]
results: List = []
async def get_one(URL):
"""Get the observations for a single date."""
response = await amake_request(URL)
data = [
v
for v in response.get("elements", {}).values() # type: ignore
if v.get("observation_value") != "." and v.get("type") != "header"
]
if data:
df = (
DataFrame(data)
.set_index(["line", "element_id", "parent_id"])
.sort_index()[
[
"level",
"series_id",
"name",
"observation_date",
"observation_value",
]
]
.reset_index()
)
df["parent_id"] = df.parent_id.astype(str)
df["element_id"] = df.element_id.astype(str)
df["observation_value"] = df.observation_value.str.replace(
",", ""
).astype(float)
df["line"] = df.line.astype(int)
df["observation_date"] = to_datetime(
df["observation_date"], format="%b %Y"
).dt.date
children = (
df.groupby("parent_id")["element_id"]
.apply(lambda x: x.sort_values().unique().tolist())
.to_dict()
)
children = {k: ",".join(v) for k, v in children.items()}
df["children"] = df.element_id.map(children)
df = (
df.set_index(
["line", "element_id", "children", "parent_id", "level"]
)
.sort_index()
.reset_index()
.replace({nan: None})
)
if query.category == "personal_income":
df = df.set_index("line").sort_index()
df["units"] = "Bil. of $"
df.loc[35, "units"] = "%"
df.loc[36:37, "units"] = "Bil. of Chn. 2017 $"
df.loc[38, "units"] = "$"
df.loc[39, "units"] = "Chn. 2017"
df.loc[40, "units"] = "Thous."
df = df.reset_index()
elif query.category in ["wages_by_industry", "pce_dollars"]:
df["units"] = "Bil. of $"
elif query.category in [
"real_pce_percent_change",
"pce_price_percent_change",
]:
df["units"] = "%"
elif query.category in ["real_pce_quantity_index", "pce_price_index"]:
df["units"] = "Index 2017=100"
elif query.category == "real_pce_chained_dollars":
df["units"] = "Bil. of Chn. 2017 $"
else:
pass
results.extend(df.to_dict("records"))
await asyncio.gather(*[get_one(URL) for URL in URLS])
return results
@staticmethod
def transform_data(
query: FredPersonalConsumptionExpendituresQueryParams,
data: List[Dict],
**kwargs: Any,
) -> List[FredPersonalConsumptionExpendituresData]:
"""Transform data."""
if not data:
raise EmptyDataError("The request was returned empty.")
return [
FredPersonalConsumptionExpendituresData.model_validate(d)
for d in sorted(
data,
key=lambda x: (
x["observation_date"],
x["line"],
),
)
]

View File

@@ -0,0 +1,63 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://api.stlouisfed.org/fred/release/tables?api_key=MOCK_API_KEY&element_id=3208&file_type=json&include_observation_values=true&observation_date=2024-05-01&release_id=54
response:
body:
string: !!binary |
H4sIAAAAAAAEA6pWykvMTVWyUgpJTMpJVTDSs9Az0VMIKMpMTlXwzEtJrUgtVkjLL1IISC0qzs9L
zFFwzs8rLs0tKMnMz1NwrShIzUvJLCktSi1WSKpU8E3Myi9SCKksSFXIT1MIKMpPKU0uUdJRSs1J
zU3NK4nPTFGyMjYysNBRKkrNSU0sTgWLKJmaINQUK1lVKxkbWlqCaBR9hpaWqPpMTXSUilOLMlOL
IcYEOLsGeCrpKBUkFqFalpOZB/KhoZKOUkllAYgJ0aakA/M83HfJSL5LRfadRoCzq6aSjlJOallq
jpKVEsiw/KTi1KKyRFBQxJcl5pSCTDY0MtYzsDRT0lFClk1JLAFJ+iZWKhgZGIG8m5yRmZNSlJqn
ZBVdrYTiTyMDM/z+dHF3CQ5yN/Y1sDALdnJ1RPMxOJigPjbC7WP3/PyUYiT/gJQiuxjuH0MTPXMj
dN+S5h9TAv5xCQ3C7R9wcED9Y4zbPy6lRYmgBJyO5i+QFqz+MjDVM7I0ICWeYmt10KLK0NKcgNf8
XNyJ8xooTeBInH75eSmk+s7IQM/QGGQmst/xxlpsLab/jAwMCfgv2BVP1CEnRVPcURecWlSWmZxK
VGo0MtczMiYpd2HzlTFeX+WV5uSgliJIHoFIQmMqIzUxJbUIUYw4pqSk5qUkomUrfFndAK9LlMBF
mo+bK1oeNzIw1lGC5glQYECdUwwuDBHOCXB2VUitSM4pTcnMS1dIy89PUUjMS1FIzUstSq9EciTO
PGJkpGdgAoo5ElIReh4xMjDC70cXtwhHfHkE4VVz3GnILT8/hSgfmemZmIPMochHBHN9EN5cj/CR
BW4fuYJjSQFcnoGjDVTXoGUTnBFnbKlnAa5VKfCmoSVaPY1e37oEOPsSF3GWuL3pm1iUnVqim5RY
nJqiEOAMSumwKhan74wM9UyNQEFHge+MDEwIJMsA5wjifGcIqkVwZEF071GYHw30DMxAgUmCx8Hl
upKxkYEZRosKXLUit8QwYni0pWEFbWIiStXRlkZmfh5Se5e8lgYoRZpiSZHDp60I6sWYY/hweDUZ
dUDRaIjhyWHSbgR5zhiL50abj6PNR6SuP4FuFWaDeLT5mKJkpTTafIQOSw3y5iO4jDfAUgwOw74r
qMQ3wuLVId+FBXkMszFiZDA8iyJQ08sCIxqHWYcWFKUmGJ4cMf1awGprAQvEx5q7GAAA
headers:
Cache-Control:
- max-age=0, no-cache
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '906'
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 10 Jul 2024 19:41:44 GMT
Expires:
- Wed, 10 Jul 2024 19:41:44 GMT
Last-Modified:
- Wed, 10 Jul 2024 19:41:44 GMT
Pragma:
- no-cache
Server:
- Apache
Set-Cookie:
- ak_bmsc=ABFEAA8641E1BF996D74FB74B04DBDC3~000000000000000000000000000000~YAAQxh/XF8UFi1OQAQAAIYMqnhg/yyojpFlH4BQfnilsu/2nL61PsqhE7/HIvFDBnHF6a4CRV147sHTyL8ah1S9e6AWdh5xIA1Hf1BbjuWoT9Bn3Qo3ek8sKArQY57My8I/5md27Z8hGTaD6vJ/KKpSN9/YOO0DA0zuaT0QMxW2B6sdpLhwiMFgo3EghciTj6Gtdg6LJPcd2fPAWGJvDEby4u1rh8NjPnbhCb6aYYNhnqoifkaKOYUS8ip8fPLbTiWf/QSqG1gFH0tkurM6AXl14gTkYf5dLGF9k7rNacFxT3FlDoWeOUm7HggmBGGNsdp0deIryWVeoXW1zjaznR5V7s23DLtcM9746oIn8QB0CNOES1dBZLCm95xihjp61;
Domain=.stlouisfed.org; Path=/; Expires=Wed, 10 Jul 2024 21:41:44 GMT; Max-Age=7200
Strict-Transport-Security:
- max-age=86400
Vary:
- Accept-Encoding
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,60 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://api.stlouisfed.org/fred/release/tables?api_key=MOCK_API_KEY&element_id=3208&file_type=json&include_observation_values=true&observation_date=2024-05-01&release_id=54
response:
body:
string: !!binary |
H4sIAAAAAAAEA6pWykvMTVWyUgpJTMpJVTDSs9Az0VMIKMpMTlXwzEtJrUgtVkjLL1IISC0qzs9L
zFFwzs8rLs0tKMnMz1NwrShIzUvJLCktSi1WSKpU8E3Myi9SCKksSFXIT1MIKMpPKU0uUdJRSs1J
zU3NK4nPTFGyMjYysNBRKkrNSU0sTgWLKJmaINQUK1lVKxkbWlqCaBR9hpaWqPpMTXSUilOLMlOL
IcYEOLsGeCrpKBUkFqFalpOZB/KhoZKOUkllAYgJ0aakA/M83HfJSL5LRfadRoCzq6aSjlJOallq
jpKVEsiw/KTi1KKyRFBQxJcl5pSCTDY0MtYzsDRT0lFClk1JLAFJ+iZWKhgZGIG8m5yRmZNSlJqn
ZBVdrYTiTyMDM/z+dHF3CQ5yN/Y1sDALdnJ1RPMxOJigPjbC7WP3/PyUYiT/gJQiuxjuH0MTPXMj
dN+S5h9TAv5xCQ3C7R9wcED9Y4zbPy6lRYmgBJyO5i+QFqz+MjDVM7I0ICWeYmt10KLK0NKcgNf8
XNyJ8xooTeBInH75eSmk+s7IQM/QGGQmst/xxlpsLab/jAwMCfgv2BVP1CEnRVPcURecWlSWmZxK
VGo0MtczMiYpd2HzlTFeX+WV5uSgliJIHoFIQmMqIzUxJbUIUYw4pqSk5qUkomUrfFndAK9LlMBF
mo+bK1oeNzIw1lGC5glQYECdUwwuDBHOCXB2VUitSM4pTcnMS1dIy89PUUjMS1FIzUstSq9EciTO
PGJkpGdgAoo5ElIReh4xMjDC70cXtwhHfHkE4VVz3GnILT8/hSgfmemZmIPMochHBHN9EN5cj/CR
BW4fuYJjSQFcnoGjDVTXoGUTnBFnbKlnAa5VKfCmoSVaPY1e37oEOPsSF3GWuL3pm1iUnVqim5RY
nJqiEOAMSumwKhan74wM9UyNQEFHge+MDEwIJMsA5wjifGcIqkVwZEF071GYHw30DMxAgUmCx8Hl
upKxkYEZRosKXLUit8QwYni0pWEFbWIiStXRlkZmfh5Se5e8lgYoRZpiSZHDp60I6sWYY/hweDUZ
dUDRaIjhyWHSbgR5zhiL50abj6PNR6SuP4FuFWaDeLT5mKJkpTTafIQOSw3y5iO4jDfAUgwOw74r
qMQ3wuLVId+FBXkMszFiZDA8iyJQ08sCIxqHWYcWFKUmGJ4cMf1awGprAQvEx5q7GAAA
headers:
Cache-Control:
- max-age=0, no-cache
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '906'
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 10 Jul 2024 19:43:08 GMT
Expires:
- Wed, 10 Jul 2024 19:43:08 GMT
Last-Modified:
- Wed, 10 Jul 2024 19:41:44 GMT
Pragma:
- no-cache
Server:
- Apache
Strict-Transport-Security:
- max-age=86400
Vary:
- Accept-Encoding
status:
code: 200
message: OK
version: 1

View File

@@ -31,6 +31,9 @@ from openbb_fred.models.non_farm_payrolls import FredNonFarmPayrollsFetcher
from openbb_fred.models.overnight_bank_funding_rate import (
FredOvernightBankFundingRateFetcher,
)
from openbb_fred.models.personal_consumption_expenditures import (
FredPersonalConsumptionExpendituresFetcher,
)
from openbb_fred.models.regional import FredRegionalDataFetcher
from openbb_fred.models.retail_prices import FredRetailPricesFetcher
from openbb_fred.models.search import (
@@ -487,3 +490,16 @@ def test_fred_non_farm_payrolls_fetcher(credentials=test_credentials):
fetcher = FredNonFarmPayrollsFetcher()
result = fetcher.test(params, credentials)
assert result is None
@pytest.mark.record_http
def test_fred_personal_consumption_expenditures_fetcher(credentials=test_credentials):
"""Test FRED Personal Consumption Expenditures Fetcher."""
params = {
"date": "2024-05-01",
"category": "pce_price_index",
}
fetcher = FredPersonalConsumptionExpendituresFetcher()
result = fetcher.test(params, credentials)
assert result is None