mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-31 22:41:19 +00:00
139 lines
4.5 KiB
Python
139 lines
4.5 KiB
Python
"""FRED Search Model."""
|
|
|
|
from typing import Any, Dict, List, Literal, Optional, Union
|
|
|
|
from openbb_core.provider.abstract.fetcher import Fetcher
|
|
from openbb_core.provider.standard_models.fred_search import (
|
|
SearchData,
|
|
SearchQueryParams,
|
|
)
|
|
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
|
|
from openbb_core.provider.utils.helpers import (
|
|
amake_request,
|
|
get_querystring,
|
|
)
|
|
from pydantic import Field, NonNegativeInt
|
|
|
|
|
|
class FredSearchQueryParams(SearchQueryParams):
|
|
"""FRED Search Query Params."""
|
|
|
|
__alias_dict__ = {
|
|
"query": "search_text",
|
|
}
|
|
|
|
is_release: Optional[bool] = Field(
|
|
default=False,
|
|
description="Is release? If True, other search filter variables are ignored."
|
|
+ " If no query text or release_id is supplied, this defaults to True.",
|
|
)
|
|
release_id: Optional[Union[str, int]] = Field(
|
|
default=None,
|
|
description="A specific release ID to target.",
|
|
)
|
|
limit: Optional[int] = Field(
|
|
default=None,
|
|
description=QUERY_DESCRIPTIONS.get("limit", "") + " (1-1000)",
|
|
)
|
|
offset: Optional[NonNegativeInt] = Field(
|
|
default=0,
|
|
description="Offset the results in conjunction with limit.",
|
|
)
|
|
filter_variable: Literal[None, "frequency", "units", "seasonal_adjustment"] = Field(
|
|
default=None, description="Filter by an attribute."
|
|
)
|
|
filter_value: Optional[str] = Field(
|
|
default=None,
|
|
description="String value to filter the variable by. Used in conjunction with filter_variable.",
|
|
)
|
|
tag_names: Optional[str] = Field(
|
|
default=None,
|
|
description="A semicolon delimited list of tag names that series match all of. Example: 'japan;imports'",
|
|
)
|
|
exclude_tag_names: Optional[str] = Field(
|
|
default=None,
|
|
description="A semicolon delimited list of tag names that series match none of. Example: 'imports;services'."
|
|
+ " Requires that variable tag_names also be set to limit the number of matching series.",
|
|
)
|
|
|
|
|
|
class FredSearchData(SearchData):
|
|
"""FRED Search Data."""
|
|
|
|
__alias_dict__ = {"url": "link"}
|
|
|
|
popularity: Optional[int] = Field(
|
|
default=None,
|
|
description="Popularity of the series",
|
|
)
|
|
group_popularity: Optional[int] = Field(
|
|
default=None,
|
|
description="Group popularity of the release",
|
|
)
|
|
|
|
|
|
class FredSearchFetcher(
|
|
Fetcher[
|
|
FredSearchQueryParams,
|
|
List[FredSearchData],
|
|
]
|
|
):
|
|
"""FRED Search Fetcher."""
|
|
|
|
@staticmethod
|
|
def transform_query(params: Dict[str, Any]) -> FredSearchQueryParams:
|
|
"""Transform query."""
|
|
transformed_params = FredSearchQueryParams(**params)
|
|
if transformed_params.query is None and transformed_params.release_id is None:
|
|
transformed_params.is_release = True
|
|
|
|
return transformed_params
|
|
|
|
@staticmethod
|
|
async def aextract_data(
|
|
query: FredSearchQueryParams,
|
|
credentials: Optional[Dict[str, str]],
|
|
**kwargs: Any,
|
|
) -> List[Dict]:
|
|
"""Extract the raw data."""
|
|
api_key = credentials.get("fred_api_key") if credentials else ""
|
|
|
|
if query.is_release is True:
|
|
url = f"https://api.stlouisfed.org/fred/releases?api_key={api_key}&file_type=json"
|
|
|
|
response = await amake_request(url, timeout=5, **kwargs)
|
|
|
|
return response.get("releases") # type: ignore[return-value, union-attr]
|
|
|
|
url = (
|
|
"https://api.stlouisfed.org/fred/release/series?"
|
|
if query.release_id is not None
|
|
else "https://api.stlouisfed.org/fred/series/search?"
|
|
)
|
|
|
|
exclude = (
|
|
["is_release", "search_text"]
|
|
if query.release_id is not None
|
|
else ["is_release"]
|
|
)
|
|
|
|
querystring = get_querystring(query.model_dump(), exclude).replace(" ", "+")
|
|
|
|
url = url + querystring + f"&file_type=json&api_key={api_key}"
|
|
response = await amake_request(url, timeout=5, **kwargs)
|
|
|
|
return response.get("seriess") # type: ignore[return-value, union-attr]
|
|
|
|
@staticmethod
|
|
def transform_data(
|
|
query: FredSearchQueryParams, data: List[Dict], **kwargs: Any
|
|
) -> List[FredSearchData]:
|
|
"""Transform data."""
|
|
for observation in data:
|
|
id_column_name = "release_id" if query.is_release is True else "series_id"
|
|
observation[id_column_name] = observation.pop("id")
|
|
observation.pop("realtime_start", None)
|
|
observation.pop("realtime_end", None)
|
|
|
|
return [FredSearchData.model_validate(d) for d in data]
|