diff --git a/openbb_sdk/extensions/economy/openbb_economy/economy_router.py b/openbb_sdk/extensions/economy/openbb_economy/economy_router.py index e0483e96053..16dd5cac97d 100644 --- a/openbb_sdk/extensions/economy/openbb_economy/economy_router.py +++ b/openbb_sdk/extensions/economy/openbb_economy/economy_router.py @@ -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, diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/global_news.py b/openbb_sdk/providers/fmp/openbb_fmp/models/global_news.py index 4699adaeb3c..b7e0e58d0b2 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/models/global_news.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/global_news.py @@ -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, diff --git a/openbb_sdk/providers/fred/openbb_fred/models/cpi.py b/openbb_sdk/providers/fred/openbb_fred/models/cpi.py index be16ff234e5..ade8922c77d 100644 --- a/openbb_sdk/providers/fred/openbb_fred/models/cpi.py +++ b/openbb_sdk/providers/fred/openbb_fred/models/cpi.py @@ -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 diff --git a/openbb_sdk/sdk/core/openbb_core/app/model/command_output.py b/openbb_sdk/sdk/core/openbb_core/app/model/command_output.py index 9d3f9ba7c80..03930369243 100644 --- a/openbb_sdk/sdk/core/openbb_core/app/model/command_output.py +++ b/openbb_sdk/sdk/core/openbb_core/app/model/command_output.py @@ -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 diff --git a/openbb_sdk/sdk/core/openbb_core/app/utils.py b/openbb_sdk/sdk/core/openbb_core/app/utils.py index 03ab2f84ac6..637279f8e62 100644 --- a/openbb_sdk/sdk/core/openbb_core/app/utils.py +++ b/openbb_sdk/sdk/core/openbb_core/app/utils.py @@ -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 diff --git a/openbb_sdk/sdk/provider/openbb_provider/map.py b/openbb_sdk/sdk/provider/openbb_provider/map.py index 811b00c2fa8..98b57e4a81e 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/map.py +++ b/openbb_sdk/sdk/provider/openbb_provider/map.py @@ -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 diff --git a/openbb_sdk/sdk/provider/openbb_provider/models/cpi.py b/openbb_sdk/sdk/provider/openbb_provider/models/cpi.py index a20ad37a2e9..7604f696abd 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/models/cpi.py +++ b/openbb_sdk/sdk/provider/openbb_provider/models/cpi.py @@ -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]]