mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-02 15:32:04 +00:00
fix cpi command and refactor
This commit is contained in:
@@ -33,11 +33,10 @@ def const(
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> CommandOutput[BaseModel]:
|
||||
""""""
|
||||
"""Get the constituents of an index."""
|
||||
return CommandOutput(results=Query(**locals()).execute())
|
||||
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
@router.command(model="CPI")
|
||||
def cpi(
|
||||
cc: CommandContext,
|
||||
|
||||
@@ -15,13 +15,15 @@ class FMPGlobalNewsQueryParams(GlobalNewsQueryParams):
|
||||
Source: https://site.financialmodelingprep.com/developer/docs/general-news-api/
|
||||
"""
|
||||
|
||||
|
||||
class FMPGlobalNewsData(GlobalNewsData):
|
||||
# publishedDate: datetime = Field(alias="date")
|
||||
class Config:
|
||||
fields = {'date': 'publishedDate'}
|
||||
fields = {"date": "publishedDate"}
|
||||
|
||||
site: str = Field(description="The site of the news.")
|
||||
|
||||
|
||||
class FMPGlobalNewsFetcher(
|
||||
Fetcher[
|
||||
GlobalNewsQueryParams,
|
||||
|
||||
@@ -6,29 +6,11 @@ from typing import Dict, List, Optional
|
||||
from openbb_fred.utils.fred_base import Fred
|
||||
from openbb_fred.utils.fred_helpers import all_cpi_options
|
||||
from openbb_provider.abstract.fetcher import Fetcher
|
||||
from openbb_provider.helpers import data_transformer
|
||||
from openbb_provider.models.cpi import CPIData, CPIDataPoint, CPIQueryParams
|
||||
from openbb_provider.models.cpi import CPIData, CPIQueryParams
|
||||
|
||||
|
||||
class FREDCPIQueryParams(CPIQueryParams):
|
||||
"""CPI query.
|
||||
When other provders are added, this will probably need less strict types
|
||||
|
||||
Parameter
|
||||
---------
|
||||
countries: List[CPI_COUNTRIES]
|
||||
The country or countries you want to see.
|
||||
units: List[CPI_UNITS]
|
||||
The units you want to see, can be "growth_previous", "growth_same" or "index_2015".
|
||||
frequency: List[CPI_FREQUENCY]
|
||||
The frequency you want to see, either "annual", monthly" or "quarterly".
|
||||
harmonized: bool
|
||||
Whether you wish to obtain harmonized data.
|
||||
start_date: Optional[date]
|
||||
Start date, formatted YYYY-MM-DD
|
||||
end_date: Optional[date]
|
||||
End date, formatted YYYY-MM-DD
|
||||
"""
|
||||
"""CPI query."""
|
||||
|
||||
|
||||
class FREDCPIData(CPIData):
|
||||
@@ -53,7 +35,7 @@ class FREDCPIFetcher(Fetcher[CPIQueryParams, CPIData, FREDCPIQueryParams, FREDCP
|
||||
@staticmethod
|
||||
def extract_data(
|
||||
query: FREDCPIQueryParams, credentials: Optional[Dict[str, str]]
|
||||
) -> FREDCPIData:
|
||||
) -> Dict[str, List[CPIData]]:
|
||||
if credentials:
|
||||
api_key = credentials.get("fred_api_key")
|
||||
|
||||
@@ -63,20 +45,17 @@ class FREDCPIFetcher(Fetcher[CPIQueryParams, CPIData, FREDCPIQueryParams, FREDCP
|
||||
step_2 = [x for x in step_1 if x["units"] == query.units]
|
||||
step_3 = [x for x in step_2 if x["frequency"] == query.frequency]
|
||||
|
||||
if not step_3:
|
||||
FREDCPIData(data={})
|
||||
|
||||
series_dict = {}
|
||||
|
||||
fred = Fred(api_key)
|
||||
for item in step_3:
|
||||
loc = f"{item['country']}-{item['frequency']}-{item['units']}"
|
||||
temp = fred.get_series(item["series_id"], query.start_date, query.end_date)
|
||||
clean_temp = [CPIDataPoint(**x) for x in temp]
|
||||
clean_temp = [FREDCPIData(**x) for x in temp]
|
||||
series_dict[loc] = clean_temp
|
||||
|
||||
return FREDCPIData(data=series_dict)
|
||||
return series_dict
|
||||
|
||||
@staticmethod
|
||||
def transform_data(data: List[FREDCPIData]) -> List[CPIData]:
|
||||
return data_transformer(data, CPIData)
|
||||
def transform_data(data: Dict[str, List[CPIData]]) -> Dict[str, List[CPIData]]:
|
||||
return data
|
||||
|
||||
@@ -10,6 +10,7 @@ from openbb_core.app.model.abstract.tagged import Tagged
|
||||
from openbb_core.app.model.abstract.warning import Warning_
|
||||
from openbb_core.app.model.charts.chart import Chart, ChartFormat
|
||||
from openbb_core.app.provider_interface import get_provider_interface
|
||||
from openbb_core.app.utils import basemodel_to_df
|
||||
|
||||
T = TypeVar("T")
|
||||
PROVIDERS = get_provider_interface().providers_literal
|
||||
@@ -60,12 +61,17 @@ class CommandOutput(GenericModel, Generic[T], Tagged):
|
||||
raise OpenBBError("Results not found.")
|
||||
|
||||
try:
|
||||
df = pd.DataFrame(self.dict()["results"])
|
||||
if "date" in df.columns:
|
||||
df = df.set_index("date")
|
||||
df.index = pd.to_datetime(df.index)
|
||||
except ValueError:
|
||||
df = pd.DataFrame(self.dict()["results"], index=["values"]).T
|
||||
if isinstance(self.results, dict) and all(
|
||||
isinstance(v, list) for v in self.results.values()
|
||||
):
|
||||
dict_of_df = {
|
||||
k: basemodel_to_df(v, "date") for k, v in self.results.items()
|
||||
}
|
||||
df = pd.concat(dict_of_df, axis=1)
|
||||
elif isinstance(self.results, list):
|
||||
df = basemodel_to_df(self.results, "date")
|
||||
else:
|
||||
df = basemodel_to_df(self.results, "date")
|
||||
except Exception as e:
|
||||
raise OpenBBError("Failed to convert results to dataframe.") from e
|
||||
|
||||
|
||||
@@ -4,9 +4,14 @@ import pandas as pd
|
||||
from openbb_provider.abstract.data import Data
|
||||
|
||||
|
||||
def basemodel_to_df(data: List[Data], index: Optional[str] = None) -> pd.DataFrame:
|
||||
def basemodel_to_df(
|
||||
data: Union[List[Data], Data], index: Optional[str] = None
|
||||
) -> pd.DataFrame:
|
||||
"""Convert list of BaseModel to a Pandas DataFrame."""
|
||||
df = pd.DataFrame([d.dict() for d in data])
|
||||
|
||||
data_list = [data] if not isinstance(data, list) else data
|
||||
|
||||
df = pd.DataFrame([d.dict() for d in data_list])
|
||||
if index and index in df.columns:
|
||||
df = df.set_index(index)
|
||||
return df
|
||||
|
||||
@@ -38,14 +38,27 @@ def _get_data_fields(fetcher) -> Tuple[Dict, Dict]:
|
||||
Tuple[Dict, Dict]
|
||||
A tuple of the provider-specific and standardized data fields.
|
||||
"""
|
||||
# TODO: this is a hacky way to get the fields, but it works for now
|
||||
# if we split data into standard and extra, should be easier
|
||||
try:
|
||||
provider_fields = (fetcher.get_provider_data_type()).__fields__
|
||||
except AttributeError:
|
||||
provider_fields = (fetcher.get_provider_data_type().__args__[0]).__fields__
|
||||
try:
|
||||
provider_fields = (fetcher.get_provider_data_type().__args__[0]).__fields__
|
||||
except AttributeError:
|
||||
provider_fields = (
|
||||
(fetcher.get_data_type().__args__[-1]).__args__[0].__fields__
|
||||
)
|
||||
|
||||
try:
|
||||
standard_fields = (fetcher.get_data_type()).__fields__
|
||||
except AttributeError:
|
||||
standard_fields = (fetcher.get_data_type().__args__[0]).__fields__
|
||||
try:
|
||||
standard_fields = (fetcher.get_data_type().__args__[0]).__fields__
|
||||
except AttributeError:
|
||||
standard_fields = (
|
||||
(fetcher.get_data_type().__args__[-1]).__args__[0].__fields__
|
||||
)
|
||||
|
||||
return provider_fields, standard_fields
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from datetime import date as dateType
|
||||
from typing import Dict, List, Optional
|
||||
from typing import List, Optional
|
||||
|
||||
from openbb_fred.utils.fred_helpers import CPI_COUNTRIES, CPI_FREQUENCY, CPI_UNITS
|
||||
from pydantic import BaseModel, validator
|
||||
from pydantic import validator
|
||||
|
||||
from openbb_provider.abstract.data import Data, QueryParams
|
||||
|
||||
@@ -35,10 +35,10 @@ class CPIQueryParams(QueryParams):
|
||||
end_date: Optional[dateType]
|
||||
|
||||
|
||||
class CPIDataPoint(BaseModel):
|
||||
class CPIData(Data):
|
||||
date: dateType
|
||||
realtime_start: dateType
|
||||
realtime_end: dateType
|
||||
date: dateType
|
||||
value: float
|
||||
|
||||
@validator("value", pre=True)
|
||||
@@ -46,8 +46,3 @@ class CPIDataPoint(BaseModel):
|
||||
if v == ".":
|
||||
return 0.0
|
||||
return float(v)
|
||||
|
||||
|
||||
class CPIData(Data):
|
||||
# I don't love this, but the keys are dynamic based on input so I don't know another way
|
||||
data: Dict[str, List[CPIDataPoint]]
|
||||
|
||||
Reference in New Issue
Block a user