fix cpi command and refactor

This commit is contained in:
Diogo Sousa
2023-07-25 18:03:41 +01:00
parent f7937f1e01
commit 591526f2bb
7 changed files with 49 additions and 50 deletions

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]]