diff --git a/openbb_platform/core/openbb_core/provider/standard_models/consumer_price_index.py b/openbb_platform/core/openbb_core/provider/standard_models/consumer_price_index.py new file mode 100644 index 000000000000..0983d13d9d74 --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/consumer_price_index.py @@ -0,0 +1,56 @@ +"""CPI Standard Model.""" + +from datetime import date as dateType +from typing import Literal, Optional + +from pydantic import Field, field_validator + +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 ConsumerPriceIndexQueryParams(QueryParams): + """CPI Query.""" + + country: str = Field( + description=QUERY_DESCRIPTIONS.get("country"), + default="united_states", + ) + transform: Literal["index", "yoy", "period"] = Field( + description="Transformation of the CPI data. Period represents the change since previous." + + " Defaults to change from one year ago (yoy).", + default="yoy", + json_schema_extra={"choices": ["index", "yoy", "period"]}, + ) + frequency: Literal["annual", "quarter", "monthly"] = Field( + default="monthly", + description=QUERY_DESCRIPTIONS.get("frequency"), + json_schema_extra={"choices": ["annual", "quarter", "monthly"]}, + ) + harmonized: bool = Field( + default=False, description="If true, returns harmonized data." + ) + start_date: Optional[dateType] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("start_date") + ) + end_date: Optional[dateType] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("end_date") + ) + + @field_validator("country", mode="before", check_fields=False) + @classmethod + def to_lower(cls, v): + """Convert country to lower case.""" + return v.replace(" ", "_").lower() + + +class ConsumerPriceIndexData(Data): + """CPI data.""" + + date: dateType = Field(description=DATA_DESCRIPTIONS.get("date")) + country: str = Field(description=DATA_DESCRIPTIONS.get("country")) + value: float = Field(description="CPI index value or period change.") diff --git a/openbb_platform/core/openbb_core/provider/standard_models/cpi.py b/openbb_platform/core/openbb_core/provider/standard_models/cpi.py deleted file mode 100644 index 472a21df2339..000000000000 --- a/openbb_platform/core/openbb_core/provider/standard_models/cpi.py +++ /dev/null @@ -1,128 +0,0 @@ -"""CPI Standard Model.""" - -from datetime import date as dateType -from typing import Literal, Optional - -from dateutil import parser -from pydantic import Field, field_validator - -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, -) -from openbb_core.provider.utils.helpers import check_item - -CPI_COUNTRIES = [ - "australia", - "austria", - "belgium", - "brazil", - "bulgaria", - "canada", - "chile", - "china", - "croatia", - "cyprus", - "czech_republic", - "denmark", - "estonia", - "euro_area", - "finland", - "france", - "germany", - "greece", - "hungary", - "iceland", - "india", - "indonesia", - "ireland", - "israel", - "italy", - "japan", - "korea", - "latvia", - "lithuania", - "luxembourg", - "malta", - "mexico", - "netherlands", - "new_zealand", - "norway", - "poland", - "portugal", - "romania", - "russian_federation", - "slovak_republic", - "slovakia", - "slovenia", - "south_africa", - "spain", - "sweden", - "switzerland", - "turkey", - "united_kingdom", - "united_states", -] - -CPI_UNITS = Literal["growth_previous", "growth_same", "index_2015"] - -CPI_FREQUENCY = Literal["monthly", "quarter", "annual"] - - -class ConsumerPriceIndexQueryParams(QueryParams): - """CPI Query.""" - - country: str = Field( - description=QUERY_DESCRIPTIONS.get("country"), - json_schema_extra={"choices": CPI_COUNTRIES}, # type: ignore[dict-item] - ) - units: CPI_UNITS = Field( - default="growth_same", - description=QUERY_DESCRIPTIONS.get("units", "") - + """ - Options: - - `growth_previous`: Percent growth from the previous period. - If monthly data, this is month-over-month, etc - - `growth_same`: Percent growth from the same period in the previous year. - If looking at monthly data, this would be year-over-year, etc. - - `index_2015`: Rescaled index value, such that the value in 2015 is 100.""", - ) - frequency: CPI_FREQUENCY = Field( - default="monthly", - description=QUERY_DESCRIPTIONS.get("frequency", "") - + """ - Options: `monthly`, `quarter`, and `annual`.""", - ) - harmonized: bool = Field( - default=False, description="Whether you wish to obtain harmonized data." - ) - start_date: Optional[dateType] = Field( - default=None, description=QUERY_DESCRIPTIONS.get("start_date") - ) - end_date: Optional[dateType] = Field( - default=None, description=QUERY_DESCRIPTIONS.get("end_date") - ) - - @field_validator("country", mode="before", check_fields=False) - def validate_country(cls, c: str): # pylint: disable=E0213 - """Validate country.""" - result = [] - values = c.replace(" ", "_").split(",") - for v in values: - check_item(v.lower(), CPI_COUNTRIES) - result.append(v.lower()) - return ",".join(result) - - -class ConsumerPriceIndexData(Data): - """CPI data.""" - - date: dateType = Field(description=DATA_DESCRIPTIONS.get("date")) - - @field_validator("date", mode="before") - @classmethod - def date_validate(cls, v): - """Validate date.""" - return parser.isoparse(v) diff --git a/openbb_platform/core/openbb_core/provider/standard_models/share_price_index.py b/openbb_platform/core/openbb_core/provider/standard_models/share_price_index.py new file mode 100644 index 000000000000..ff2d06816754 --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/share_price_index.py @@ -0,0 +1,49 @@ +"""Share Price Index Standard Model.""" + +from datetime import date as dateType +from typing import Literal, Optional + +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 SharePriceIndexQueryParams(QueryParams): + """Share Price Index Query.""" + + country: str = Field( + description=QUERY_DESCRIPTIONS.get("country", ""), + default="united_states", + ) + frequency: Literal["monthly", "quarter", "annual"] = Field( + description=QUERY_DESCRIPTIONS.get("frequency", ""), + default="monthly", + json_schema_extra={"choices": ["monthly", "quarter", "annual"]}, + ) + start_date: Optional[dateType] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("start_date") + ) + end_date: Optional[dateType] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("end_date") + ) + + +class SharePriceIndexData(Data): + """Share Price Index Data.""" + + date: Optional[dateType] = Field( + default=None, description=DATA_DESCRIPTIONS.get("date") + ) + country: Optional[str] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("country", ""), + ) + value: Optional[float] = Field( + default=None, + description="Share price index value.", + ) diff --git a/openbb_platform/extensions/economy/integration/test_economy_api.py b/openbb_platform/extensions/economy/integration/test_economy_api.py index b06ac4937e6a..556094a492ba 100644 --- a/openbb_platform/extensions/economy/integration/test_economy_api.py +++ b/openbb_platform/extensions/economy/integration/test_economy_api.py @@ -71,10 +71,10 @@ def test_economy_calendar(params, headers): ( { "country": "spain", - "units": "growth_same", - "frequency": "monthly", - "harmonized": True, - "start_date": "2023-01-01", + "transform": "yoy", + "frequency": "annual", + "harmonized": False, + "start_date": "2020-01-01", "end_date": "2023-06-06", "provider": "fred", } @@ -82,7 +82,7 @@ def test_economy_calendar(params, headers): ( { "country": "portugal,spain", - "units": "growth_same", + "transform": "period", "frequency": "monthly", "harmonized": True, "start_date": "2023-01-01", @@ -90,6 +90,18 @@ def test_economy_calendar(params, headers): "provider": "fred", } ), + ( + { + "country": "portugal,spain", + "transform": "yoy", + "frequency": "quarter", + "harmonized": False, + "start_date": "2020-01-01", + "end_date": "2023-06-06", + "provider": "oecd", + "expenditure": "transport", + } + ), ], ) @pytest.mark.integration @@ -696,3 +708,29 @@ def test_economy_central_bank_holdings(params, headers): result = requests.get(url, headers=headers, timeout=5) assert isinstance(result, requests.Response) assert result.status_code == 200 + + +@parametrize( + "params", + [ + ( + { + "country": "united_states,united_kingdom", + "frequency": "monthly", + "provider": "oecd", + "start_date": "2022-01-01", + "end_date": "2024-04-01", + } + ), + ], +) +@pytest.mark.integration +def test_economy_share_price_index(params, headers): + """Test the economy share price index.""" + 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/share_price_index?{query_str}" + result = requests.get(url, headers=headers, timeout=10) + assert isinstance(result, requests.Response) + assert result.status_code == 200 diff --git a/openbb_platform/extensions/economy/integration/test_economy_python.py b/openbb_platform/extensions/economy/integration/test_economy_python.py index 4825b504949c..9899b9b34c28 100644 --- a/openbb_platform/extensions/economy/integration/test_economy_python.py +++ b/openbb_platform/extensions/economy/integration/test_economy_python.py @@ -63,14 +63,38 @@ def test_economy_calendar(params, obb): @parametrize( "params", [ + ( + { + "country": "spain", + "transform": "yoy", + "frequency": "annual", + "harmonized": False, + "start_date": "2020-01-01", + "end_date": "2023-06-06", + "provider": "fred", + } + ), ( { "country": "portugal,spain", - "units": "growth_same", + "transform": "period", "frequency": "monthly", "harmonized": True, "start_date": "2023-01-01", "end_date": "2023-06-06", + "provider": "fred", + } + ), + ( + { + "country": "portugal,spain", + "transform": "yoy", + "frequency": "quarter", + "harmonized": False, + "start_date": "2020-01-01", + "end_date": "2023-06-06", + "provider": "oecd", + "expenditure": "transport", } ), ], @@ -644,3 +668,28 @@ def test_economy_central_bank_holdings(params, obb): assert result assert isinstance(result, OBBject) assert len(result.results) > 0 + + +@parametrize( + "params", + [ + ( + { + "country": "united_states,united_kingdom", + "frequency": "monthly", + "provider": "oecd", + "start_date": "2022-01-01", + "end_date": "2024-04-01", + } + ), + ], +) +@pytest.mark.integration +def test_economy_share_price_index(params, obb): + """Test economy share price index.""" + params = {p: v for p, v in params.items() if v} + + result = obb.economy.share_price_index(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 diff --git a/openbb_platform/extensions/economy/openbb_economy/economy_router.py b/openbb_platform/extensions/economy/openbb_economy/economy_router.py index b318d1183e6a..ade0833bd01b 100644 --- a/openbb_platform/extensions/economy/openbb_economy/economy_router.py +++ b/openbb_platform/extensions/economy/openbb_economy/economy_router.py @@ -54,11 +54,12 @@ async def calendar( examples=[ APIEx(parameters={"country": "japan,china,turkey", "provider": "fred"}), APIEx( - description="Use the `units` parameter to define the reference period for the change in values.", + description="Use the `transform` parameter to define the reference period for the change in values." + + " Default is YoY.", parameters={ "country": "united_states,united_kingdom", - "units": "growth_previous", - "provider": "fred", + "transform": "period", + "provider": "oecd", }, ), ], @@ -410,3 +411,27 @@ async def central_bank_holdings( ) -> OBBject: """Get the balance sheet holdings of a central bank.""" return await OBBject.from_query(Query(**locals())) + + +@router.command( + model="SharePriceIndex", + examples=[ + APIEx(parameters={"provider": "oecd"}), + APIEx( + description="Multiple countries can be passed in as a list.", + parameters={ + "country": "united_kingdom,germany", + "frequency": "quarterly", + "provider": "oecd", + }, + ), + ], +) +async def share_price_index( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """Get the Share Price Index by country from the OECD Short-Term Economics Statistics.""" + return await OBBject.from_query(Query(**locals())) diff --git a/openbb_platform/openbb/assets/reference.json b/openbb_platform/openbb/assets/reference.json index aae0334f071e..664b855d3938 100644 --- a/openbb_platform/openbb/assets/reference.json +++ b/openbb_platform/openbb/assets/reference.json @@ -2938,15 +2938,80 @@ "message": null }, "description": "Get Consumer Price Index (CPI).\n\nReturns either the rescaled index value, or a rate of change (inflation).", - "examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.cpi(country='japan,china,turkey', provider='fred')\n# Use the `units` parameter to define the reference period for the change in values.\nobb.economy.cpi(country='united_states,united_kingdom', units='growth_previous', provider='fred')\n```\n\n", + "examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.cpi(country='japan,china,turkey', provider='fred')\n# Use the `transform` parameter to define the reference period for the change in values. Default is YoY.\nobb.economy.cpi(country='united_states,united_kingdom', transform='period', provider='oecd')\n```\n\n", "parameters": { "standard": [ { "name": "country", "type": "Union[str, List[str]]", - "description": "The country to get data. Multiple items allowed for provider(s): fred.", - "default": "", - "optional": false, + "description": "The country to get data. Multiple items allowed for provider(s): fred, oecd.", + "default": "united_states", + "optional": true, + "choices": null + }, + { + "name": "transform", + "type": "Literal['index', 'yoy', 'period']", + "description": "Transformation of the CPI data. Period represents the change since previous. Defaults to change from one year ago (yoy).", + "default": "yoy", + "optional": true, + "choices": [ + "index", + "yoy", + "period" + ] + }, + { + "name": "frequency", + "type": "Literal['annual', 'quarter', 'monthly']", + "description": "The frequency of the data.", + "default": "monthly", + "optional": true, + "choices": [ + "annual", + "quarter", + "monthly" + ] + }, + { + "name": "harmonized", + "type": "bool", + "description": "If true, returns harmonized data.", + "default": false, + "optional": true, + "choices": null + }, + { + "name": "start_date", + "type": "Union[date, str]", + "description": "Start date of the data, in YYYY-MM-DD format.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "end_date", + "type": "Union[date, str]", + "description": "End date of the data, in YYYY-MM-DD format.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "provider", + "type": "Literal['fred', 'oecd']", + "description": "The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: f, r, e, d.", + "default": null, + "optional": true + } + ], + "fred": [ + { + "name": "country", + "type": "str", + "description": "The country to get data.", + "default": "united_states", + "optional": true, "choices": [ "australia", "austria", @@ -2998,56 +3063,111 @@ "united_kingdom", "united_states" ] - }, - { - "name": "units", - "type": "Literal['growth_previous', 'growth_same', 'index_2015']", - "description": "The unit of measurement for the data. Options: - `growth_previous`: Percent growth from the previous period. If monthly data, this is month-over-month, etc - `growth_same`: Percent growth from the same period in the previous year. If looking at monthly data, this would be year-over-year, etc. - `index_2015`: Rescaled index value, such that the value in 2015 is 100.", - "default": "growth_same", - "optional": true, - "choices": null - }, - { - "name": "frequency", - "type": "Literal['monthly', 'quarter', 'annual']", - "description": "The frequency of the data. Options: `monthly`, `quarter`, and `annual`.", - "default": "monthly", - "optional": true, - "choices": null - }, - { - "name": "harmonized", - "type": "bool", - "description": "Whether you wish to obtain harmonized data.", - "default": false, - "optional": true, - "choices": null - }, + } + ], + "oecd": [ { - "name": "start_date", - "type": "Union[date, str]", - "description": "Start date of the data, in YYYY-MM-DD format.", - "default": null, + "name": "country", + "type": "str", + "description": "Country to get CPI for. This is the list of OECD supported countries", + "default": "united_states", "optional": true, - "choices": null + "choices": [ + "G20", + "G7", + "argentina", + "australia", + "austria", + "belgium", + "brazil", + "canada", + "chile", + "china", + "colombia", + "costa_rica", + "czech_republic", + "denmark", + "estonia", + "euro_area_20", + "europe", + "european_union_27", + "finland", + "france", + "germany", + "greece", + "hungary", + "iceland", + "india", + "indonesia", + "ireland", + "israel", + "italy", + "japan", + "korea", + "latvia", + "lithuania", + "luxembourg", + "mexico", + "netherlands", + "new_zealand", + "norway", + "oecd_total", + "poland", + "portugal", + "russia", + "saudi_arabia", + "slovak_republic", + "slovenia", + "south_africa", + "spain", + "sweden", + "switzerland", + "turkey", + "united_kingdom", + "united_states", + "all" + ] }, { - "name": "end_date", - "type": "Union[date, str]", - "description": "End date of the data, in YYYY-MM-DD format.", - "default": null, + "name": "expenditure", + "type": "Literal['total', 'all', 'actual_rentals', 'alcoholic_beverages_tobacco_narcotics', 'all_non_food_non_energy', 'clothing_footwear', 'communication', 'education', 'electricity_gas_other_fuels', 'energy', 'overall_excl_energy_food_alcohol_tobacco', 'food_non_alcoholic_beverages', 'fuels_lubricants_personal', 'furniture_household_equipment', 'goods', 'housing', 'housing_excluding_rentals', 'housing_water_electricity_gas', 'health', 'imputed_rentals', 'maintenance_repair_dwelling', 'miscellaneous_goods_services', 'recreation_culture', 'residuals', 'restaurants_hotels', 'services_less_housing', 'services_less_house_excl_rentals', 'services', 'transport', 'water_supply_other_services']", + "description": "Expenditure component of CPI.", + "default": "total", "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: f, r, e, d.", - "default": null, - "optional": true + "choices": [ + "total", + "food_non_alcoholic_beverages", + "alcoholic_beverages_tobacco_narcotics", + "clothing_footwear", + "housing_water_electricity_gas", + "furniture_household_equipment", + "health", + "transport", + "communication", + "recreation_culture", + "education", + "restaurants_hotels", + "miscellaneous_goods_services", + "energy", + "goods", + "housing", + "housing_excluding_rentals", + "all_non_food_non_energy", + "services_less_housing", + "services_less_house_excl_rentals", + "services", + "overall_excl_energy_food_alcohol_tobacco", + "residuals", + "fuels_lubricants_personal", + "actual_rentals", + "imputed_rentals", + "maintenance_repair_dwelling", + "water_supply_other_services", + "electricity_gas_other_fuels", + "all" + ] } - ], - "fred": [] + ] }, "returns": { "OBBject": [ @@ -3058,7 +3178,7 @@ }, { "name": "provider", - "type": "Optional[Literal['fred']]", + "type": "Optional[Literal['fred', 'oecd']]", "description": "Provider name." }, { @@ -3087,9 +3207,35 @@ "default": "", "optional": false, "choices": null + }, + { + "name": "country", + "type": "str", + "description": "None", + "default": "", + "optional": false, + "choices": null + }, + { + "name": "value", + "type": "float", + "description": "CPI index value or period change.", + "default": "", + "optional": false, + "choices": null } ], - "fred": [] + "fred": [], + "oecd": [ + { + "name": "expenditure", + "type": "str", + "description": "Expenditure component of CPI.", + "default": "", + "optional": false, + "choices": null + } + ] }, "model": "ConsumerPriceIndex" }, @@ -4301,7 +4447,7 @@ { "name": "country", "type": "Literal['belgium', 'ireland', 'mexico', 'indonesia', 'new_zealand', 'japan', 'united_kingdom', 'france', 'chile', 'canada', 'netherlands', 'united_states', 'south_korea', 'norway', 'austria', 'south_africa', 'denmark', 'switzerland', 'hungary', 'luxembourg', 'australia', 'germany', 'sweden', 'iceland', 'turkey', 'greece', 'israel', 'czech_republic', 'latvia', 'slovenia', 'poland', 'estonia', 'lithuania', 'portugal', 'costa_rica', 'slovakia', 'finland', 'spain', 'russia', 'euro_area19', 'colombia', 'italy', 'india', 'china', 'croatia', 'all']", - "description": "Country to get GDP for.", + "description": "Country to get interest rate for.", "default": "united_states", "optional": true, "choices": null @@ -4413,7 +4559,7 @@ { "name": "country", "type": "Literal['belgium', 'ireland', 'mexico', 'indonesia', 'new_zealand', 'japan', 'united_kingdom', 'france', 'chile', 'canada', 'netherlands', 'united_states', 'south_korea', 'norway', 'austria', 'south_africa', 'denmark', 'switzerland', 'hungary', 'luxembourg', 'australia', 'germany', 'sweden', 'iceland', 'turkey', 'greece', 'israel', 'czech_republic', 'latvia', 'slovenia', 'poland', 'estonia', 'lithuania', 'portugal', 'costa_rica', 'slovakia', 'finland', 'spain', 'russia', 'euro_area19', 'colombia', 'italy', 'india', 'china', 'croatia', 'all']", - "description": "Country to get GDP for.", + "description": "Country to get interest rate for.", "default": "united_states", "optional": true, "choices": null @@ -5222,8 +5368,8 @@ { "name": "provider", "type": "Literal['federal_reserve']", - "description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'federal_reserve' if there is no default.", - "default": "federal_reserve", + "description": "The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: f, e, d, e, r, a, l, _, r, e, s, e, r, v, e.", + "default": null, "optional": true } ], @@ -5509,6 +5655,184 @@ }, "model": "CentralBankHoldings" }, + "/economy/share_price_index": { + "deprecated": { + "flag": null, + "message": null + }, + "description": "Get the Share Price Index by country from the OECD Short-Term Economics Statistics.", + "examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.share_price_index(provider='oecd')\n# Multiple countries can be passed in as a list.\nobb.economy.share_price_index(country='united_kingdom,germany', frequency='quarterly', provider='oecd')\n```\n\n", + "parameters": { + "standard": [ + { + "name": "country", + "type": "Union[str, List[str]]", + "description": "The country to get data. Multiple items allowed for provider(s): oecd.", + "default": "united_states", + "optional": true, + "choices": null + }, + { + "name": "frequency", + "type": "Literal['monthly', 'quarter', 'annual']", + "description": "The frequency of the data.", + "default": "monthly", + "optional": true, + "choices": [ + "monthly", + "quarter", + "annual" + ] + }, + { + "name": "start_date", + "type": "Union[date, str]", + "description": "Start date of the data, in YYYY-MM-DD format.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "end_date", + "type": "Union[date, str]", + "description": "End date of the data, in YYYY-MM-DD format.", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "provider", + "type": "Literal['oecd']", + "description": "The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: o, e, c, d.", + "default": null, + "optional": true + } + ], + "oecd": [ + { + "name": "country", + "type": "str", + "description": "The country to get data.", + "default": "united_states", + "optional": true, + "choices": [ + "G20", + "G7", + "argentina", + "australia", + "austria", + "belgium", + "brazil", + "canada", + "chile", + "china", + "colombia", + "costa_rica", + "czech_republic", + "denmark", + "estonia", + "euro_area_20", + "europe", + "european_union_27", + "finland", + "france", + "germany", + "greece", + "hungary", + "iceland", + "india", + "indonesia", + "ireland", + "israel", + "italy", + "japan", + "korea", + "latvia", + "lithuania", + "luxembourg", + "mexico", + "netherlands", + "new_zealand", + "norway", + "oecd_total", + "poland", + "portugal", + "russia", + "saudi_arabia", + "slovak_republic", + "slovenia", + "south_africa", + "spain", + "sweden", + "switzerland", + "turkey", + "united_kingdom", + "united_states", + "all" + ] + } + ] + }, + "returns": { + "OBBject": [ + { + "name": "results", + "type": "List[SharePriceIndex]", + "description": "Serializable results." + }, + { + "name": "provider", + "type": "Optional[Literal['oecd']]", + "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": null, + "optional": true, + "choices": null + }, + { + "name": "country", + "type": "str", + "description": "", + "default": null, + "optional": true, + "choices": null + }, + { + "name": "value", + "type": "float", + "description": "Share price index value.", + "default": null, + "optional": true, + "choices": null + } + ], + "oecd": [] + }, + "model": "SharePriceIndex" + }, "/equity/calendar/ipo": { "deprecated": { "flag": null, diff --git a/openbb_platform/openbb/package/economy.py b/openbb_platform/openbb/package/economy.py index 19191e3f4da6..64e219f7377a 100644 --- a/openbb_platform/openbb/package/economy.py +++ b/openbb_platform/openbb/package/economy.py @@ -28,6 +28,7 @@ class ROUTER_economy(Container): long_term_interest_rate money_measures risk_premium + share_price_index short_term_interest_rate unemployment """ @@ -378,7 +379,7 @@ def central_bank_holdings( provider: Annotated[ Optional[Literal["federal_reserve"]], OpenBBField( - description="The provider to use for the query, by default None.\n If None, the provider specified in defaults is selected or 'federal_reserve' if there is\n no default." + description="The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: federal_reserve." ), ] = None, **kwargs @@ -390,9 +391,7 @@ def central_bank_holdings( date : Union[datetime.date, None, str] A specific date to get data for. provider : Optional[Literal['federal_reserve']] - The provider to use for the query, by default None. - If None, the provider specified in defaults is selected or 'federal_reserve' if there is - no default. + The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: federal_reserve. holding_type : Literal['all_agency', 'agency_debts', 'mbs', 'cmbs', 'all_treasury', 'bills', 'notesbonds', 'frn', 'tips'] Type of holdings to return. (provider: federal_reserve) summary : bool @@ -488,7 +487,7 @@ def central_bank_holdings( provider_choices={ "provider": self._get_provider( provider, - "/economy/central_bank_holdings", + "economy.central_bank_holdings", ("federal_reserve",), ) }, @@ -696,74 +695,25 @@ def cpi( country: Annotated[ Union[str, List[str]], OpenBBField( - description="The country to get data. Multiple comma separated items allowed for provider(s): fred.", - choices=[ - "australia", - "austria", - "belgium", - "brazil", - "bulgaria", - "canada", - "chile", - "china", - "croatia", - "cyprus", - "czech_republic", - "denmark", - "estonia", - "euro_area", - "finland", - "france", - "germany", - "greece", - "hungary", - "iceland", - "india", - "indonesia", - "ireland", - "israel", - "italy", - "japan", - "korea", - "latvia", - "lithuania", - "luxembourg", - "malta", - "mexico", - "netherlands", - "new_zealand", - "norway", - "poland", - "portugal", - "romania", - "russian_federation", - "slovak_republic", - "slovakia", - "slovenia", - "south_africa", - "spain", - "sweden", - "switzerland", - "turkey", - "united_kingdom", - "united_states", - ], + description="The country to get data. Multiple comma separated items allowed for provider(s): fred, oecd." ), - ], - units: Annotated[ - Literal["growth_previous", "growth_same", "index_2015"], + ] = "united_states", + transform: Annotated[ + Literal["index", "yoy", "period"], OpenBBField( - description="The unit of measurement for the data.\n Options:\n - `growth_previous`: Percent growth from the previous period.\n If monthly data, this is month-over-month, etc\n - `growth_same`: Percent growth from the same period in the previous year.\n If looking at monthly data, this would be year-over-year, etc.\n - `index_2015`: Rescaled index value, such that the value in 2015 is 100." + description="Transformation of the CPI data. Period represents the change since previous. Defaults to change from one year ago (yoy).", + choices=["index", "yoy", "period"], ), - ] = "growth_same", + ] = "yoy", frequency: Annotated[ - Literal["monthly", "quarter", "annual"], + Literal["annual", "quarter", "monthly"], OpenBBField( - description="The frequency of the data.\n Options: `monthly`, `quarter`, and `annual`." + description="The frequency of the data.", + choices=["annual", "quarter", "monthly"], ), ] = "monthly", harmonized: Annotated[ - bool, OpenBBField(description="Whether you wish to obtain harmonized data.") + bool, OpenBBField(description="If true, returns harmonized data.") ] = False, start_date: Annotated[ Union[datetime.date, None, str], @@ -774,9 +724,9 @@ def cpi( OpenBBField(description="End date of the data, in YYYY-MM-DD format."), ] = None, provider: Annotated[ - Optional[Literal["fred"]], + Optional[Literal["fred", "oecd"]], OpenBBField( - description="The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: fred." + description="The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: fred, oecd." ), ] = None, **kwargs @@ -789,33 +739,28 @@ def cpi( Parameters ---------- country : Union[str, List[str]] - The country to get data. Multiple comma separated items allowed for provider(s): fred. - units : Literal['growth_previous', 'growth_same', 'index_2015'] - The unit of measurement for the data. - Options: - - `growth_previous`: Percent growth from the previous period. - If monthly data, this is month-over-month, etc - - `growth_same`: Percent growth from the same period in the previous year. - If looking at monthly data, this would be year-over-year, etc. - - `index_2015`: Rescaled index value, such that the value in 2015 is 100. - frequency : Literal['monthly', 'quarter', 'annual'] + The country to get data. Multiple comma separated items allowed for provider(s): fred, oecd. + transform : Literal['index', 'yoy', 'period'] + Transformation of the CPI data. Period represents the change since previous. Defaults to change from one year ago (yoy). + frequency : Literal['annual', 'quarter', 'monthly'] The frequency of the data. - Options: `monthly`, `quarter`, and `annual`. harmonized : bool - Whether you wish to obtain harmonized data. + If true, returns harmonized data. start_date : Union[datetime.date, None, str] Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, None, str] End date of the data, in YYYY-MM-DD format. - 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. + provider : Optional[Literal['fred', 'oecd']] + The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: fred, oecd. + expenditure : Literal['total', 'all', 'actual_rentals', 'alcoholic_beverages_tobacco_narcotics', 'all_non_food_non_energy', 'clothing_footwear', 'communication', 'education', 'electricity_gas_other_fuels', 'energy', 'overall_excl_energy_food_alcohol_tobacco', 'food_non_alcoholic_beverages', 'fuels_lubricants_personal', 'furniture_household_equipment', 'goods', 'housing', 'housing_excluding_rentals', 'housing_water_electricity_gas', 'health', 'imputed_rentals', 'maintenance_repair_dwelling', 'miscellaneous_goods_services', 'recreation_culture', 'residuals', 'restaurants_hotels', 'services_less_housing', 'services_less_house_excl_rentals', 'services', 'transport', 'water_supply_other_services'] + Expenditure component of CPI. (provider: oecd) Returns ------- OBBject results : List[ConsumerPriceIndex] Serializable results. - provider : Optional[Literal['fred']] + provider : Optional[Literal['fred', 'oecd']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -828,13 +773,19 @@ def cpi( ------------------ date : date The date of the data. + country : str + None + value : float + CPI index value or period change. + expenditure : Optional[str] + Expenditure component of CPI. (provider: oecd) Examples -------- >>> from openbb import obb >>> obb.economy.cpi(country='japan,china,turkey', provider='fred') - >>> # Use the `units` parameter to define the reference period for the change in values. - >>> obb.economy.cpi(country='united_states,united_kingdom', units='growth_previous', provider='fred') + >>> # Use the `transform` parameter to define the reference period for the change in values. Default is YoY. + >>> obb.economy.cpi(country='united_states,united_kingdom', transform='period', provider='oecd') """ # noqa: E501 return self._run( @@ -844,19 +795,24 @@ def cpi( "provider": self._get_provider( provider, "economy.cpi", - ("fred",), + ("fred", "oecd"), ) }, standard_params={ "country": country, - "units": units, + "transform": transform, "frequency": frequency, "harmonized": harmonized, "start_date": start_date, "end_date": end_date, }, extra_params=kwargs, - info={"country": {"fred": {"multiple_items_allowed": True}}}, + info={ + "country": { + "fred": ["multiple_items_allowed"], + "oecd": ["multiple_items_allowed"], + } + }, ) ) @@ -1446,7 +1402,7 @@ def long_term_interest_rate( provider : Optional[Literal['oecd']] The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: oecd. country : Literal['belgium', 'ireland', 'mexico', 'indonesia', 'new_zealand', 'japan', 'united_kingdom', 'france', 'chile', 'canada', 'netherlands', 'united_states', 'south_korea', 'norway', 'austria', 'south_africa', 'denmark', 'switzerland', 'hungary', 'luxembourg', 'australia', 'germany', 'sweden', 'iceland', 'turkey', 'greece', 'israel', 'czech_republic', 'latvia', 'slovenia', 'poland', 'estonia', 'lithuania', 'portugal', 'costa_rica', 'slovakia', 'finland', 'spain', 'russia', 'euro_area19', 'colombia', 'italy', 'india', 'china', 'croatia', 'all'] - Country to get GDP for. (provider: oecd) + Country to get interest rate for. (provider: oecd) frequency : Literal['monthly', 'quarterly', 'annual'] Frequency to get interest rate for for. (provider: oecd) @@ -1662,6 +1618,106 @@ def risk_premium( ) ) + @exception_handler + @validate + def share_price_index( + self, + country: Annotated[ + Union[str, List[str]], + OpenBBField( + description="The country to get data. Multiple comma separated items allowed for provider(s): oecd." + ), + ] = "united_states", + frequency: Annotated[ + Literal["monthly", "quarter", "annual"], + OpenBBField( + description="The frequency of the data.", + choices=["monthly", "quarter", "annual"], + ), + ] = "monthly", + start_date: Annotated[ + Union[datetime.date, None, str], + OpenBBField(description="Start date of the data, in YYYY-MM-DD format."), + ] = None, + end_date: Annotated[ + Union[datetime.date, None, str], + OpenBBField(description="End date of the data, in YYYY-MM-DD format."), + ] = None, + provider: Annotated[ + Optional[Literal["oecd"]], + OpenBBField( + description="The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: oecd." + ), + ] = None, + **kwargs + ) -> OBBject: + """Get the Share Price Index by country from the OECD Short-Term Economics Statistics. + + Parameters + ---------- + country : Union[str, List[str]] + The country to get data. Multiple comma separated items allowed for provider(s): oecd. + frequency : Literal['monthly', 'quarter', 'annual'] + The frequency of the data. + start_date : Union[datetime.date, None, str] + Start date of the data, in YYYY-MM-DD format. + end_date : Union[datetime.date, None, str] + End date of the data, in YYYY-MM-DD format. + provider : Optional[Literal['oecd']] + The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: oecd. + + Returns + ------- + OBBject + results : List[SharePriceIndex] + Serializable results. + provider : Optional[Literal['oecd']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + extra : Dict[str, Any] + Extra info. + + SharePriceIndex + --------------- + date : Optional[date] + The date of the data. + country : Optional[str] + + value : Optional[float] + Share price index value. + + Examples + -------- + >>> from openbb import obb + >>> obb.economy.share_price_index(provider='oecd') + >>> # Multiple countries can be passed in as a list. + >>> obb.economy.share_price_index(country='united_kingdom,germany', frequency='quarterly', provider='oecd') + """ # noqa: E501 + + return self._run( + "/economy/share_price_index", + **filter_inputs( + provider_choices={ + "provider": self._get_provider( + provider, + "economy.share_price_index", + ("oecd",), + ) + }, + standard_params={ + "country": country, + "frequency": frequency, + "start_date": start_date, + "end_date": end_date, + }, + extra_params=kwargs, + info={"country": {"oecd": ["multiple_items_allowed"]}}, + ) + ) + @exception_handler @validate def short_term_interest_rate( @@ -1701,7 +1757,7 @@ def short_term_interest_rate( provider : Optional[Literal['oecd']] The provider to use, by default None. If None, the priority list configured in the settings is used. Default priority: oecd. country : Literal['belgium', 'ireland', 'mexico', 'indonesia', 'new_zealand', 'japan', 'united_kingdom', 'france', 'chile', 'canada', 'netherlands', 'united_states', 'south_korea', 'norway', 'austria', 'south_africa', 'denmark', 'switzerland', 'hungary', 'luxembourg', 'australia', 'germany', 'sweden', 'iceland', 'turkey', 'greece', 'israel', 'czech_republic', 'latvia', 'slovenia', 'poland', 'estonia', 'lithuania', 'portugal', 'costa_rica', 'slovakia', 'finland', 'spain', 'russia', 'euro_area19', 'colombia', 'italy', 'india', 'china', 'croatia', 'all'] - Country to get GDP for. (provider: oecd) + Country to get interest rate for. (provider: oecd) frequency : Literal['monthly', 'quarterly', 'annual'] Frequency to get interest rate for for. (provider: oecd) diff --git a/openbb_platform/providers/fred/openbb_fred/__init__.py b/openbb_platform/providers/fred/openbb_fred/__init__.py index f8d59b1ca72d..92323baabfba 100644 --- a/openbb_platform/providers/fred/openbb_fred/__init__.py +++ b/openbb_platform/providers/fred/openbb_fred/__init__.py @@ -3,8 +3,8 @@ from openbb_core.provider.abstract.provider import Provider from openbb_fred.models.ameribor_rates import FREDAMERIBORFetcher from openbb_fred.models.balance_of_payments import FredBalanceOfPaymentsFetcher +from openbb_fred.models.consumer_price_index import FREDConsumerPriceIndexFetcher from openbb_fred.models.cp import FREDCommercialPaperFetcher -from openbb_fred.models.cpi import FREDConsumerPriceIndexFetcher from openbb_fred.models.dwpcr_rates import FREDDiscountWindowPrimaryCreditRateFetcher from openbb_fred.models.ecb_interest_rates import ( FREDEuropeanCentralBankInterestRatesFetcher, diff --git a/openbb_platform/providers/fred/openbb_fred/models/consumer_price_index.py b/openbb_platform/providers/fred/openbb_fred/models/consumer_price_index.py new file mode 100644 index 000000000000..9efd080f0a88 --- /dev/null +++ b/openbb_platform/providers/fred/openbb_fred/models/consumer_price_index.py @@ -0,0 +1,128 @@ +"""FRED Consumer Price Index Model.""" + +from typing import Any, Dict, List, Optional + +from openbb_core.provider.abstract.annotated_result import AnnotatedResult +from openbb_core.provider.abstract.fetcher import Fetcher +from openbb_core.provider.standard_models.consumer_price_index import ( + ConsumerPriceIndexData, + ConsumerPriceIndexQueryParams, +) +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS +from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.helpers import check_item +from openbb_fred.models.series import FredSeriesFetcher +from openbb_fred.utils.fred_helpers import CPI_COUNTRIES, all_cpi_options +from pandas import DataFrame +from pydantic import Field, field_validator + + +class FREDConsumerPriceIndexQueryParams(ConsumerPriceIndexQueryParams): + """FRED Consumer Price Index Query.""" + + __json_schema_extra__ = {"country": ["multiple_items_allowed"]} + + country: str = Field( + description=QUERY_DESCRIPTIONS.get("country"), + default="united_states", + json_schema_extra={"choices": CPI_COUNTRIES}, # type: ignore[dict-item] + ) + + @field_validator("country", mode="before", check_fields=False) + @classmethod + def validate_country(cls, c: str): + """Validate country.""" + result: List = [] + values = c.replace(" ", "_").split(",") + for v in values: + check_item(v.lower(), CPI_COUNTRIES) + result.append(v.lower()) + return ",".join(result) + + +class FREDConsumerPriceIndexData(ConsumerPriceIndexData): + """FRED Consumer Price Index Data.""" + + +class FREDConsumerPriceIndexFetcher( + Fetcher[FREDConsumerPriceIndexQueryParams, List[FREDConsumerPriceIndexData]] +): + """Transform the query, extract and transform the data from the FRED endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> FREDConsumerPriceIndexQueryParams: + """Transform query.""" + return FREDConsumerPriceIndexQueryParams(**params) + + @staticmethod + async def aextract_data( + query: FREDConsumerPriceIndexQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> Dict: + """Extract data.""" + frequency = "quarterly" if query.frequency == "quarter" else query.frequency + + # Convert the params to series IDs. + all_options = all_cpi_options(query.harmonized) + units_dict = { + "period": "growth_previous", + "yoy": "growth_same", + "index": "index_2015", + } + units = ( + "growth_same" + if query.transform == "period" + and frequency == "annual" + else units_dict.get(query.transform) + ) + step_1 = [x for x in all_options if x["country"] in query.country] + step_2 = [x for x in step_1 if x["units"] == units] + step_3 = [x for x in step_2 if x["frequency"] == frequency] + ids = [item["series_id"] for item in step_3] + country_map = {item["series_id"]: item["country"] for item in step_3} + item_query = dict( + symbol=",".join(ids), + start_date=query.start_date, + end_date=query.end_date, + ) + results: Dict = {} + temp = await FredSeriesFetcher.fetch_data(item_query, credentials) + result = [d.model_dump() for d in temp.result] + results["metadata"] = {country_map.get(k): v for k, v in temp.metadata.items()} + results["data"] = [ + {country_map.get(k, k): v for k, v in d.items()} for d in result + ] + + return results + + @staticmethod + def transform_data( + query: FREDConsumerPriceIndexQueryParams, + data: Dict, + **kwargs: Any, + ) -> AnnotatedResult[List[FREDConsumerPriceIndexData]]: + """Transform data and validate the model.""" + df = DataFrame.from_records(data["data"]) + if df.empty: + raise EmptyDataError( + "No data found for the given query. Try adjusting the parameters." + ) + # Flatten the data as a pivot table. + df = ( + df.melt(id_vars="date", var_name="country", value_name="value") + .query("value.notnull()") + .set_index(["date", "country"]) + .sort_index() + .reset_index() + ) + # Normalize the percent values. + if query.transform in ("period", "yoy"): + df["value"] = df["value"] / 100 + + records = df.to_dict(orient="records") + metadata = data.get("metadata", {}) + return AnnotatedResult( + result=[FREDConsumerPriceIndexData.model_validate(r) for r in records], + metadata=metadata, + ) diff --git a/openbb_platform/providers/fred/openbb_fred/models/cpi.py b/openbb_platform/providers/fred/openbb_fred/models/cpi.py deleted file mode 100644 index a7c55bb9b787..000000000000 --- a/openbb_platform/providers/fred/openbb_fred/models/cpi.py +++ /dev/null @@ -1,81 +0,0 @@ -"""FRED Consumer Price Index Model.""" - -from typing import Any, Dict, List, Optional - -from openbb_core.provider.abstract.fetcher import Fetcher -from openbb_core.provider.standard_models.cpi import ( - ConsumerPriceIndexData, - ConsumerPriceIndexQueryParams, -) -from openbb_fred.utils.fred_base import Fred -from openbb_fred.utils.fred_helpers import all_cpi_options - - -class FREDConsumerPriceIndexQueryParams(ConsumerPriceIndexQueryParams): - """FRED Consumer Price Index Query.""" - - __json_schema_extra__ = {"country": {"multiple_items_allowed": True}} - - -class FREDConsumerPriceIndexData(ConsumerPriceIndexData): - """FRED Consumer Price Index Data.""" - - -class FREDConsumerPriceIndexFetcher( - Fetcher[FREDConsumerPriceIndexQueryParams, List[FREDConsumerPriceIndexData]] -): - """Transform the query, extract and transform the data from the FRED endpoints.""" - - @staticmethod - def transform_query(params: Dict[str, Any]) -> FREDConsumerPriceIndexQueryParams: - """Transform query.""" - return FREDConsumerPriceIndexQueryParams(**params) - - @staticmethod - def extract_data( - query: FREDConsumerPriceIndexQueryParams, - credentials: Optional[Dict[str, str]], - **kwargs: Any, - ) -> Dict: - """Extract data.""" - api_key = credentials.get("fred_api_key") if credentials else "" - - all_options = all_cpi_options(query.harmonized) - - step_1 = [x for x in all_options if x["country"] in query.country] - 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] - - series_dict = {} - fred = Fred(api_key) - for item in step_3: - loc = f"{item['country']}" - temp = fred.get_series( - item["series_id"], query.start_date, query.end_date, **kwargs - ) - temp = [{"date": item["date"], "value": item["value"]} for item in temp] - series_dict[loc] = [item for item in temp if item["value"] != "."] - - return series_dict - - @staticmethod - def transform_data( - query: FREDConsumerPriceIndexQueryParams, data: Dict, **kwargs: Any - ) -> List[FREDConsumerPriceIndexData]: - """Transform data.""" - transformed_data = {} - - # Iterate over the series_dict - for country, data_list in data.items(): - for item in data_list: - # If the date is not in the dictionary, add it - if item["date"] not in transformed_data: - transformed_data[item["date"]] = {"date": item["date"]} - # Update the dictionary with the country's value data - transformed_data[item["date"]].update({country: item["value"]}) - - # Convert the dictionary to a list of dictionaries - return [ - FREDConsumerPriceIndexData.model_validate(item) - for item in list(transformed_data.values()) - ] diff --git a/openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py b/openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py index 160cd449f587..a51cf7454748 100644 --- a/openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py +++ b/openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py @@ -99,6 +99,58 @@ }, } +CPI_COUNTRIES = [ + "australia", + "austria", + "belgium", + "brazil", + "bulgaria", + "canada", + "chile", + "china", + "croatia", + "cyprus", + "czech_republic", + "denmark", + "estonia", + "euro_area", + "finland", + "france", + "germany", + "greece", + "hungary", + "iceland", + "india", + "indonesia", + "ireland", + "israel", + "italy", + "japan", + "korea", + "latvia", + "lithuania", + "luxembourg", + "malta", + "mexico", + "netherlands", + "new_zealand", + "norway", + "poland", + "portugal", + "romania", + "russian_federation", + "slovak_republic", + "slovakia", + "slovenia", + "south_africa", + "spain", + "sweden", + "switzerland", + "turkey", + "united_kingdom", + "united_states", +] + def comma_to_float_list(v: str) -> List[float]: """Convert comma-separated string to list of floats.""" diff --git a/openbb_platform/providers/fred/tests/record/http/test_fred_fetchers/test_fredcpi_fetcher.yaml b/openbb_platform/providers/fred/tests/record/http/test_fred_fetchers/test_fredcpi_fetcher.yaml index 4d6c36d2dd7f..e93090a1c372 100644 --- a/openbb_platform/providers/fred/tests/record/http/test_fred_fetchers/test_fredcpi_fetcher.yaml +++ b/openbb_platform/providers/fred/tests/record/http/test_fred_fetchers/test_fredcpi_fetcher.yaml @@ -3,324 +3,251 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - - gzip, deflate, br + - gzip, deflate Connection: - keep-alive method: GET - uri: https://api.stlouisfed.org/fred/series/observations?api_key=MOCK_API_KEY&file_type=json&series_id=CPALTT01PTM659N + uri: https://api.stlouisfed.org/fred/series/observations?aggregation_method=eop&api_key=MOCK_API_KEY&file_type=json&limit=100000&series_id=CPALTT01PTM659N response: body: string: !!binary | - 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 + 80YBAA== headers: - Accept-Ranges: - - bytes + Cache-Control: + - max-age=0, no-cache Connection: - keep-alive Content-Encoding: - gzip Content-Length: - - '16009' + - '11746' Content-Type: - application/json; charset=UTF-8 Date: - - Mon, 18 Sep 2023 09:59:44 GMT + - Tue, 28 May 2024 00:26:07 GMT Expires: - - Mon, 18 Sep 2023 10:00:44 GMT + - Tue, 28 May 2024 00:26:07 GMT Last-Modified: - - Sun, 17 Sep 2023 16:23:08 GMT + - Wed, 15 May 2024 19:07:50 GMT + Pragma: + - no-cache + Server: + - Apache Set-Cookie: - - ak_bmsc=E94554122B9744D210B4C81D0F118818~000000000000000000000000000000~YAAQFk4SAnQBZJOKAQAAd027pxVQ/Mk1EKI7tOBn3fxQGwfx1MVa2hX8YNGUUEoxpzA+GtHxUkLxWEOJyAjk9VEERzNc5/wG1Z69kLjVGZWIFwJcm8yi92NTLIMmC5vII1UiZANktC9E/r9sdmwkFCWPO0flA2ZrFfcwRhnqGZ6xR9MwD10B9cvLtLOJtIWK7sWsoFrrwsWT2BUDpyi0aALMrn+G2QFvOn+n6M3thN1O3/6mr/0q1y7iHmc+vom6VbdTjW1OZqYxYrRtr72a9ZlCwuaFL4+h9rhF9IZmNJcDtGOgMxhtQEHBMLv3Jj02n6Y7OoJvIK8wkyxAJ+9EeBHVXTf2fxC2TnxuGY08ddDPMQjIxouWDUHDlgy3NT5y; - Domain=.stlouisfed.org; Path=/; Expires=Mon, 18 Sep 2023 11:59:44 GMT; Max-Age=7200; - HttpOnly + - ak_bmsc=8CE5C9ADE7CE3614D87E785DF0893F80~000000000000000000000000000000~YAAQVl7WFz7cRbqPAQAANRCXvBd0l0Au8LeEILq/iAP3qVuDNJIgFy5ZiZpFDoIrqvvpH77kFaDLxQcOkgIV6NOqiRSdQCQWb+lONQrYODGhKu+uRtcmzHZs9F83aAHr7CtGVYpo3NITbRA6dgNkPc1Pj3z4k0KZLg5xjlwFaqoKq4V1AnMYKKLVLQTrWm31Ieo3JqtvvQe7fwHo7ozatHmW+KYuJlQa57Gfb7C4vDERDVyHpenUNbRJrELZobKs6uV0MkdfralkxV+ROskKPpdSM3hSo+niuDZBJTtSuGk7JJonKkmoxhULoeY9UxffuYqcIiMyc4CcLl+N/EypjNl5CqgNpGCKmo1UBwkEAAcZPgZR/VBEEUlaAfDcil3w; + Domain=.stlouisfed.org; Path=/; Expires=Tue, 28 May 2024 02:26:07 GMT; Max-Age=7200 + Strict-Transport-Security: + - max-age=86400 Vary: - Accept-Encoding - x-rate-limit-limit: - - '120' - x-rate-limit-remaining: - - '120' status: code: 200 message: OK @@ -328,329 +255,372 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - - gzip, deflate, br + - gzip, deflate Connection: - keep-alive method: GET - uri: https://api.stlouisfed.org/fred/series/observations?api_key=MOCK_API_KEY&file_type=json&series_id=CPALTT01ESM659N + uri: https://api.stlouisfed.org/fred/series/observations?aggregation_method=eop&api_key=MOCK_API_KEY&file_type=json&limit=100000&series_id=CPALTT01ESM659N response: body: string: !!binary | - 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 - 6v8MVQEA + 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 headers: - Accept-Ranges: - - bytes + Cache-Control: + - max-age=0, no-cache Connection: - keep-alive Content-Encoding: - gzip Content-Length: - - '16251' + - '11899' Content-Type: - application/json; charset=UTF-8 Date: - - Mon, 18 Sep 2023 09:59:45 GMT + - Tue, 28 May 2024 00:26:07 GMT Expires: - - Mon, 18 Sep 2023 10:00:45 GMT + - Tue, 28 May 2024 00:26:07 GMT Last-Modified: - - Sat, 16 Sep 2023 15:29:52 GMT + - Wed, 15 May 2024 19:01:21 GMT + Pragma: + - no-cache + Server: + - Apache Set-Cookie: - - ak_bmsc=F67F05E7B74B714025597CD578C1359A~000000000000000000000000000000~YAAQFk4SAswBZJOKAQAAI0+7pxUSDmC8TaptZ7oHduGOJ42byacA+KUJ+EJ3V/PH0crF1bE9hdv+r3KQvwdIIVqcyHKMNCWgYERW/97I4EN+noeDpl0fS0u8qIHN2I7ylLt65lqz5kz/Rp9UvbrN4NM5fjYDy6jNTBRA2E+09GzvpDg6OcnkRhFwR8mDgnMDuasstDPf5T5Tb6GkJ/1NpRuSGhnFuvjb8NLhKhMR15nnMdCszgzZXQeEJaDzDAqe6+f9a+ZZ8y62jvziXrlgIt+MqDkLmCO74vZGX9IIr0Kz0rLlhYrvs62C/3xFTIWezmkINsXKj3L7fXTrJA2dz+cUF76g21HtLthXz0A1kH+ClsNRVWIz5ET+fY1r70rD; - Domain=.stlouisfed.org; Path=/; Expires=Mon, 18 Sep 2023 11:59:44 GMT; Max-Age=7199; - HttpOnly + - ak_bmsc=4255DA0C1AF88EB2A9F6E6F4D55B8FB6~000000000000000000000000000000~YAAQVl7WFz/cRbqPAQAAPRCXvBcKX38MCynToSQkP+GVehZWwNm6wd7DMfgu+fylBq9lemaQapCyquEedEc4bHx6cGP9RiLJrPvlSeqeDiM6Z7/eWh31dkk5SR7y50ZcLvDi/BQrfvmrHcLLLR5k7ls0I9Ip+j/3FzDs+LaeU1eytKHVDz0kUiyIKTiHzI5653QLUCQHJ8MBVJa3I0u6KdGJxRg1r3cpxBEXzabURV88/gbvdpHbhQFH70X3KSYjxpNub9F7rQDze8n646C6LPaG05C1cZAjli6qsAmCChsJGt2d8FlIFRe8zMeH9u1/JrJvOkGGhsVNgFGObUGOgDgpgDfb5t+9RhjDr151HDJkzKNGiKQG6TrDfmlcOAXh; + Domain=.stlouisfed.org; Path=/; Expires=Tue, 28 May 2024 02:26:07 GMT; Max-Age=7200 + Strict-Transport-Security: + - max-age=86400 + Vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Cookie: + - ak_bmsc=4255DA0C1AF88EB2A9F6E6F4D55B8FB6~000000000000000000000000000000~YAAQVl7WFz/cRbqPAQAAPRCXvBcKX38MCynToSQkP+GVehZWwNm6wd7DMfgu+fylBq9lemaQapCyquEedEc4bHx6cGP9RiLJrPvlSeqeDiM6Z7/eWh31dkk5SR7y50ZcLvDi/BQrfvmrHcLLLR5k7ls0I9Ip+j/3FzDs+LaeU1eytKHVDz0kUiyIKTiHzI5653QLUCQHJ8MBVJa3I0u6KdGJxRg1r3cpxBEXzabURV88/gbvdpHbhQFH70X3KSYjxpNub9F7rQDze8n646C6LPaG05C1cZAjli6qsAmCChsJGt2d8FlIFRe8zMeH9u1/JrJvOkGGhsVNgFGObUGOgDgpgDfb5t+9RhjDr151HDJkzKNGiKQG6TrDfmlcOAXh + method: GET + uri: https://api.stlouisfed.org/fred/series?api_key=MOCK_API_KEY&file_type=json&series_id=CPALTT01ESM659N + response: + body: + string: !!binary | + H4sIAAAAAAAEA6pWKkpNzCnJzE2NLy5JLCpRslIyMjAy0TUw1TUyV9JByKbmpaDLFacWZaYWFytZ + RVcrZYJknQMcfUJCDAxdg33NTC39kLWTbHhJZklOqpKVknN+XnFpbmqRQkBRZnKqgmdeSmZyarGC + hnOAZ7GOgoenc0Cxpo6Cs7+ns3+AgqGlpaWVAqaW1AorhZD8ksQchbT8IoXggsTMPCUdpfyk4tSi + ssSSzPw8uOcNLU1NdQ2MdQ0M0RQg+98EIp1WlFpYmpqXXKlkpeSbn1eSkVOppKMEF40vzsgHB6iv + ko5SaV5mSbGSlZJ7UX55SYZCUWJJqkJxYm6qQkFqUWZ+ikJBUWpZZn5psUJlamIRTD3cBIK6Iov0 + lHSUilMTi/PzEnPiE1OySotLclPzQPHpl1+iEAyVyalUcATLpaZgVw+30i/YUUlHKSexuCS+tCAl + sSQVFMGwpGFoqmBoYmVgaGVkqGtgqqSjVJBfUJqTWJRZUqlkZaKjlJdfkgryrb+rs4uCS2JJooJb + Zk5JalGxlUJMXpCrW7xjkKujlYJrcEBMnq+rY3BokKuVgnOAZ0xeqJ9nSDxcKMARJB/i4e/i7+Pv + Hmml4BeT5xoR4Orn4hkC1hMfEpPn6OIVGhzi6+oXApYPCXL0C3bzD/J1DPH097NScI+MyXMLcg20 + UvCNyYvJc8zJUQA7KwXkrOKM/NKcFIWkVIXkzJLUFIXEYoW0/Jyc/PJiK4gqDVB8aOooaICUF6eW + KOQl5qbC+ArF+aVFyamaCi7+ngr5RQoZJSUFxVYx+jH6INW6qRUFOflFqUV6+anJKXr5Rekx+goa + hNVo6iloJCYnpxYXp6Yo5OeBrQYsVVNTT6k2thYAN0zNoK8DAAA= + headers: + Cache-Control: + - max-age=0, no-cache + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '665' + Content-Type: + - application/json; charset=UTF-8 + Date: + - Tue, 28 May 2024 00:26:07 GMT + Expires: + - Tue, 28 May 2024 00:26:07 GMT + Last-Modified: + - Wed, 15 May 2024 19:01:21 GMT + Pragma: + - no-cache + Server: + - Apache + Set-Cookie: + - ak_bmsc=4255DA0C1AF88EB2A9F6E6F4D55B8FB6~000000000000000000000000000000~YAAQVl7WF0DcRbqPAQAA9BCXvBd6r2wMy+luJaNud6qRsGhp60XVNwYC8oUz7uZODVUh4HdKAsap9PCkloURJ6srhvBeePpLVfBg6DL9zyxGnOJLi8oTEue7lLue7m8BknZjWM0uf6sIagFLBL6UeF6ObUGHb2Dbgg0AR+8bALty3bpebvJQypHh32L2z3ej7zKSHCbqj3O7uH1U3eX9J0BCOWzxFU7VqodC5AURUjvNsOidtg7IjiGk+1cPi6QBs9Abk5IbUKjCSWYJ5KaK+SiKho24wfGsw1P+gP1p1U/VWpkv+WNbSF0sq8Qf6dc6t3aRiIZoo0uXK/kx6aCDnuRXS8DEwoORFzvb7lgBVjNOtDbIypJh6FafKmo4AcOgnUz/bkxKbdMgiI0=; + Domain=.stlouisfed.org; Path=/; Expires=Tue, 28 May 2024 02:26:07 GMT; Max-Age=7200 + Strict-Transport-Security: + - max-age=86400 + Vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Cookie: + - ak_bmsc=8CE5C9ADE7CE3614D87E785DF0893F80~000000000000000000000000000000~YAAQVl7WFz7cRbqPAQAANRCXvBd0l0Au8LeEILq/iAP3qVuDNJIgFy5ZiZpFDoIrqvvpH77kFaDLxQcOkgIV6NOqiRSdQCQWb+lONQrYODGhKu+uRtcmzHZs9F83aAHr7CtGVYpo3NITbRA6dgNkPc1Pj3z4k0KZLg5xjlwFaqoKq4V1AnMYKKLVLQTrWm31Ieo3JqtvvQe7fwHo7ozatHmW+KYuJlQa57Gfb7C4vDERDVyHpenUNbRJrELZobKs6uV0MkdfralkxV+ROskKPpdSM3hSo+niuDZBJTtSuGk7JJonKkmoxhULoeY9UxffuYqcIiMyc4CcLl+N/EypjNl5CqgNpGCKmo1UBwkEAAcZPgZR/VBEEUlaAfDcil3w + method: GET + uri: https://api.stlouisfed.org/fred/series?api_key=MOCK_API_KEY&file_type=json&series_id=CPALTT01PTM659N + response: + body: + string: !!binary | + H4sIAAAAAAAEA6pWKkpNzCnJzE2NLy5JLCpRslIyMjAy0TUw1TUyV9JByKbmpaDLFacWZaYWFytZ + RVcrZYJknQMcfUJCDAwDQnzNTC39kLWTbHhJZklOqpKVknN+XnFpbmqRQkBRZnKqgmdeSmZyarGC + hnOAZ7GOgoenc0Cxpo6Cs7+ns3+AgqGlpaWVAqaW1AorhZD8ksQchbT8IoWA/KKS0vTEHCUdpfyk + 4tSissSSzPw8uP8NLU3NdA0MdQ0M0RQgB4EJRDqtKLWwNDUvuVLJSsk3P68kI6dSSUcJLhpfnJEP + DlNfJR2l0rzMkmIlKyX3ovzykgyFosSSVIXixNxUhYLUosz8FIWCotSyzPzSYoXK1MQimHq4CQR1 + RRbpKekoFacmFufnJebEJ6ZklRaX5KbmgaLUL79EIRgqk1Op4AiWS03Brh5upV+wo5KOUk5icUl8 + aUFKYkkqKI5hqcPQVMHQxMrA3MrUQNfAVElHqSC/oDQnsSizpFLJylBHKS+/JBXkW39XZxcFl8SS + RAW3zJyS1KJiK4WYvCBXt3jHIFdHK4WAoJCYPF9Xx+DQIFcrBecAz5i8UD/PkHi4UIAjSD7Ew9/F + 38ffPdJKwS8mzzUiwNXPxTMErCc+JCbP0cUrNDjE19UvBCwfEuToF+zmH+TrGOLp72el4B4Zk+cW + 5BpopeAbkxeT55iTowB2VgrIWcUZ+aU5KQpJqQrJmSWpKQqJxQpp+Tk5+eXFVhBVGqD40NRR0AAp + L04tUchLzE2F8RWK80uLklM1FVz8PRXyixQySkoKiq1i9GP0Qap1UysKcvKLUov08lOTU/Tyi9Jj + 9BU0CKvR1FPQSExOTi0uTk1RyM8DWw1YqqamnlJtbC0ATuXUaLIDAAA= + headers: + Cache-Control: + - max-age=0, no-cache + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '668' + Content-Type: + - application/json; charset=UTF-8 + Date: + - Tue, 28 May 2024 00:26:08 GMT + Expires: + - Tue, 28 May 2024 00:26:08 GMT + Last-Modified: + - Wed, 15 May 2024 19:07:50 GMT + Pragma: + - no-cache + Server: + - Apache + Set-Cookie: + - bm_sv=858A678B565235752CB0F5CD059F9DE7~YAAQVl7WF0HcRbqPAQAANhGXvBdAagqaDkFcO2h0qnx9LYAKQenOJ3Yvo1auCc7LiVy+vsSqJ9OTdydA+ol9AEbFl7BuIrRc4O5625NI4Dn7Prh9zQdz8ZCDzgT3WuWejoJ5uksJH7jqKeejXGu9aQ+nWOrgMO5QtHFqk8Rlnky3Byk//HPPqIG4+vYIQk6PHgg4xxXN7ZzVO4/q/dAUqeIE5pcYisF9lpxLjgBazpVhknWbvHrkX/iO7ANit36MP5BNVQ==~1; + Domain=.stlouisfed.org; Path=/; Expires=Tue, 28 May 2024 02:26:08 GMT; Max-Age=7200; + Secure + Strict-Transport-Security: + - max-age=86400 Vary: - Accept-Encoding - x-rate-limit-limit: - - '120' - x-rate-limit-remaining: - - '119' status: code: 200 message: OK diff --git a/openbb_platform/providers/fred/tests/test_fred_fetchers.py b/openbb_platform/providers/fred/tests/test_fred_fetchers.py index 36114755e250..a04936d11f36 100644 --- a/openbb_platform/providers/fred/tests/test_fred_fetchers.py +++ b/openbb_platform/providers/fred/tests/test_fred_fetchers.py @@ -6,8 +6,8 @@ from openbb_core.app.service.user_service import UserService from openbb_fred.models.ameribor_rates import FREDAMERIBORFetcher from openbb_fred.models.balance_of_payments import FredBalanceOfPaymentsFetcher +from openbb_fred.models.consumer_price_index import FREDConsumerPriceIndexFetcher from openbb_fred.models.cp import FREDCommercialPaperFetcher -from openbb_fred.models.cpi import FREDConsumerPriceIndexFetcher from openbb_fred.models.dwpcr_rates import FREDDiscountWindowPrimaryCreditRateFetcher from openbb_fred.models.ecb_interest_rates import ( FREDEuropeanCentralBankInterestRatesFetcher, diff --git a/openbb_platform/providers/oecd/openbb_oecd/__init__.py b/openbb_platform/providers/oecd/openbb_oecd/__init__.py index 49b94a9e703e..366875f4f0af 100644 --- a/openbb_platform/providers/oecd/openbb_oecd/__init__.py +++ b/openbb_platform/providers/oecd/openbb_oecd/__init__.py @@ -2,10 +2,12 @@ from openbb_core.provider.abstract.provider import Provider from openbb_oecd.models.composite_leading_indicator import OECDCLIFetcher +from openbb_oecd.models.consumer_price_index import OECDCPIFetcher from openbb_oecd.models.gdp_forecast import OECDGdpForecastFetcher from openbb_oecd.models.gdp_nominal import OECDGdpNominalFetcher from openbb_oecd.models.gdp_real import OECDGdpRealFetcher from openbb_oecd.models.long_term_interest_rate import OECDLTIRFetcher +from openbb_oecd.models.share_price_index import OECDSharePriceIndexFetcher from openbb_oecd.models.short_term_interest_rate import OECDSTIRFetcher from openbb_oecd.models.unemployment import OECDUnemploymentFetcher @@ -20,8 +22,10 @@ "GdpForecast": OECDGdpForecastFetcher, "Unemployment": OECDUnemploymentFetcher, "CLI": OECDCLIFetcher, + "SharePriceIndex": OECDSharePriceIndexFetcher, "STIR": OECDSTIRFetcher, "LTIR": OECDLTIRFetcher, + "ConsumerPriceIndex": OECDCPIFetcher, }, repr_name="Organization for Economic Co-operation and Development (OECD)", ) diff --git a/openbb_platform/providers/oecd/openbb_oecd/models/consumer_price_index.py b/openbb_platform/providers/oecd/openbb_oecd/models/consumer_price_index.py new file mode 100644 index 000000000000..51ebaecc78a7 --- /dev/null +++ b/openbb_platform/providers/oecd/openbb_oecd/models/consumer_price_index.py @@ -0,0 +1,238 @@ +"""OECD CPI Data.""" + +# pylint: disable=unused-argument + +from datetime import date +from typing import Any, Dict, List, Literal, Optional + +from openbb_core.provider.abstract.fetcher import Fetcher +from openbb_core.provider.standard_models.consumer_price_index import ( + ConsumerPriceIndexData, + ConsumerPriceIndexQueryParams, +) +from openbb_core.provider.utils.helpers import check_item +from openbb_oecd.utils import helpers +from openbb_oecd.utils.constants import ( + CODE_TO_COUNTRY_CPI, + COUNTRY_TO_CODE_CPI, +) +from pydantic import Field, field_validator +from requests.exceptions import HTTPError + +countries = tuple(CODE_TO_COUNTRY_CPI.values()) + ("all",) +CountriesList = list(countries) # type: ignore + +expenditure_dict_rev = { + "_T": "total", + "CP01": "food_non_alcoholic_beverages", + "CP02": "alcoholic_beverages_tobacco_narcotics", + "CP03": "clothing_footwear", + "CP04": "housing_water_electricity_gas", + "CP05": "furniture_household_equipment", + "CP06": "health", + "CP07": "transport", + "CP08": "communication", + "CP09": "recreation_culture", + "CP10": "education", + "CP11": "restaurants_hotels", + "CP12": "miscellaneous_goods_services", + "CP045_0722": "energy", + "GD": "goods", + "CP041T043": "housing", + "CP041T043X042": "housing_excluding_rentals" "", + "_TXCP01_NRG": "all_non_food_non_energy", + "SERVXCP041_042_0432": "services_less_housing", + "SERVXCP041_0432": "services_less_house_excl_rentals", + "SERV": "services", + "_TXNRG_01_02": "overall_excl_energy_food_alcohol_tobacco", + "CPRES": "residuals", + "CP0722": "fuels_lubricants_personal", + "CP041": "actual_rentals", + "CP042": "imputed_rentals", + "CP043": "maintenance_repair_dwelling", + "CP044": "water_supply_other_services", + "CP045": "electricity_gas_other_fuels", +} +expenditure_dict = {v: k for k, v in expenditure_dict_rev.items()} +expenditures = tuple(expenditure_dict.keys()) + ("all",) +ExpenditureChoices = Literal[ + "total", + "all", + "actual_rentals", + "alcoholic_beverages_tobacco_narcotics", + "all_non_food_non_energy", + "clothing_footwear", + "communication", + "education", + "electricity_gas_other_fuels", + "energy", + "overall_excl_energy_food_alcohol_tobacco", + "food_non_alcoholic_beverages", + "fuels_lubricants_personal", + "furniture_household_equipment", + "goods", + "housing", + "housing_excluding_rentals", + "housing_water_electricity_gas", + "health", + "imputed_rentals", + "maintenance_repair_dwelling", + "miscellaneous_goods_services", + "recreation_culture", + "residuals", + "restaurants_hotels", + "services_less_housing", + "services_less_house_excl_rentals", + "services", + "transport", + "water_supply_other_services", +] + + +class OECDCPIQueryParams(ConsumerPriceIndexQueryParams): + """OECD CPI Query. + + Source: https://data-explorer.oecd.org/?lc=en + """ + + __json_schema_extra__ = {"country": ["multiple_items_allowed"]} + + country: str = Field( + description="Country to get CPI for. This is the list of OECD supported countries", + default="united_states", + choices=CountriesList, + ) + expenditure: ExpenditureChoices = Field( + description="Expenditure component of CPI.", + default="total", + json_schema_extra={"choices": list(expenditures)}, + ) + + @field_validator("country", mode="before", check_fields=False) + def validate_country(cls, c: str): # pylint: disable=E0213 + """Validate country.""" + result: List = [] + values = c.replace(" ", "_").split(",") + for v in values: + check_item(v.lower(), CountriesList) + result.append(v.lower()) + return ",".join(result) + + +class OECDCPIData(ConsumerPriceIndexData): + """OECD CPI Data.""" + + expenditure: str = Field(description="Expenditure component of CPI.") + + +class OECDCPIFetcher(Fetcher[OECDCPIQueryParams, List[OECDCPIData]]): + """OECD CPI Fetcher.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> OECDCPIQueryParams: + """Transform the query.""" + transformed_params = params.copy() + if transformed_params.get("start_date") is None: + transformed_params["start_date"] = date(1950, 1, 1) + if transformed_params.get("end_date") is None: + transformed_params["end_date"] = date(date.today().year, 12, 31) + if transformed_params.get("country") is None: + transformed_params["country"] = "united_states" + + return OECDCPIQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: OECDCPIQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the OECD endpoint.""" + methodology = "HICP" if query.harmonized is True else "N" + query.units = "mom" if query.transform == "period" else query.transform + query.frequency = ( + "monthly" + if query.harmonized is True and query.frequency == "quarter" + else query.frequency + ) + frequency = query.frequency[0].upper() + units = { + "index": "IX", + "yoy": "PA", + "mom": "PC", + }[query.units] + expenditure = ( + "" if query.expenditure == "all" else expenditure_dict[query.expenditure] + ) + + def country_string(input_str: str): + if input_str == "all": + return "" + countries = input_str.split(",") + return "+".join([COUNTRY_TO_CODE_CPI[country] for country in countries]) + + country = country_string(query.country) + # For caching, include this in the key + query_dict = { + k: v + for k, v in query.__dict__.items() + if k not in ["start_date", "end_date"] + } + + url = ( + f"https://sdmx.oecd.org/public/rest/data/OECD.SDD.TPS,DSD_PRICES@DF_PRICES_ALL,1.0/" + f"{country}.{frequency}.{methodology}.CPI.{units}.{expenditure}.N." + ) + try: + data = helpers.get_possibly_cached_data( + url, function="economy_cpi", query_dict=query_dict + ) + except HTTPError: + raise ValueError("No data found for the given query.") + url_query = f"METHODOLOGY=='{methodology}' & UNIT_MEASURE=='{units}' & FREQ=='{frequency}'" + + if country != "all": + if "+" in country: + countries = country.split("+") + country_conditions = " or ".join( + [f"REF_AREA=='{c}'" for c in countries] + ) + url_query += f" & ({country_conditions})" + else: + url_query = url_query + f" & REF_AREA=='{country}'" + url_query = ( + url_query + f" & EXPENDITURE=='{expenditure}'" + if query.expenditure != "all" + else url_query + ) + # Filter down + data = ( + data.query(url_query) + .reset_index(drop=True)[["REF_AREA", "TIME_PERIOD", "VALUE", "EXPENDITURE"]] + .rename( + columns={ + "REF_AREA": "country", + "TIME_PERIOD": "date", + "VALUE": "value", + "EXPENDITURE": "expenditure", + } + ) + ) + data["country"] = data["country"].map(CODE_TO_COUNTRY_CPI) + data["expenditure"] = data["expenditure"].map(expenditure_dict_rev) + data["date"] = data["date"].apply(helpers.oecd_date_to_python_date) + data = data[ + (data["date"] <= query.end_date) & (data["date"] >= query.start_date) + ] + # Normalize the percent value. + if query.transform in ("yoy", "period"): + data["value"] = data["value"].astype(float) / 100 + + return data.fillna("N/A").replace("N/A", None).to_dict(orient="records") + + @staticmethod + def transform_data( + query: OECDCPIQueryParams, data: List[Dict], **kwargs: Any + ) -> List[OECDCPIData]: + """Transform the data from the OECD endpoint.""" + return [OECDCPIData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/oecd/openbb_oecd/models/long_term_interest_rate.py b/openbb_platform/providers/oecd/openbb_oecd/models/long_term_interest_rate.py index 9ac5c306eacd..e46e5af8e776 100644 --- a/openbb_platform/providers/oecd/openbb_oecd/models/long_term_interest_rate.py +++ b/openbb_platform/providers/oecd/openbb_oecd/models/long_term_interest_rate.py @@ -1,4 +1,4 @@ -"""OECD Long Term Interest Rate Rate Data.""" +"""OECD Long Term Interest Rate Data.""" # pylint: disable=unused-argument @@ -23,7 +23,7 @@ class OECDLTIRQueryParams(LTIRQueryParams): """OECD Short Term Interest Rate Query.""" country: CountriesLiteral = Field( - description="Country to get GDP for.", default="united_states" + description="Country to get interest rate for.", default="united_states" ) frequency: Literal["monthly", "quarterly", "annual"] = Field( diff --git a/openbb_platform/providers/oecd/openbb_oecd/models/share_price_index.py b/openbb_platform/providers/oecd/openbb_oecd/models/share_price_index.py new file mode 100644 index 000000000000..7eaedfce51b7 --- /dev/null +++ b/openbb_platform/providers/oecd/openbb_oecd/models/share_price_index.py @@ -0,0 +1,151 @@ +"""OECD Share Price Index Model.""" + +# pylint: disable=unused-argument + +from datetime import date +from io import StringIO +from typing import Any, Dict, List, Optional +from warnings import warn + +from openbb_core.provider.abstract.fetcher import Fetcher +from openbb_core.provider.standard_models.share_price_index import ( + SharePriceIndexData, + SharePriceIndexQueryParams, +) +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS +from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.helpers import check_item, make_request +from openbb_oecd.utils.constants import ( + CODE_TO_COUNTRY_RGDP, + COUNTRY_TO_CODE_RGDP, +) +from openbb_oecd.utils.helpers import oecd_date_to_python_date +from pandas import read_csv +from pydantic import Field, field_validator + +countries = tuple(CODE_TO_COUNTRY_RGDP.values()) + ("all",) +CountriesList = list(countries) # type: ignore +frequency_dict = { + "monthly": "M", + "quarter": "Q", + "annual": "A", +} + + +class OECDSharePriceIndexQueryParams(SharePriceIndexQueryParams): + """OECD Share Price Index Query. + + Source: https://data-explorer.oecd.org/?lc=en + """ + + __json_schema_extra__ = {"country": ["multiple_items_allowed"]} + + country: str = Field( + description=QUERY_DESCRIPTIONS.get("country", ""), + default="united_states", + choices=CountriesList, + ) + + @field_validator("country", mode="before", check_fields=False) + @classmethod + def validate_country(cls, c): + """Validate country.""" + result: List = [] + values = c.replace(" ", "_").split(",") + for v in values: + if v.upper() in CODE_TO_COUNTRY_RGDP: + result.append(CODE_TO_COUNTRY_RGDP.get(v.upper())) + continue + try: + check_item(v.lower(), CountriesList) + except Exception as e: + if len(values) == 1: + raise e from e + else: + warn(f"Invalid country: {v}. Skipping...") + continue + result.append(v.lower()) + if result: + return ",".join(result) + raise ValueError(f"No valid country found. -> {values}") + + +class OECDSharePriceIndexData(SharePriceIndexData): + """OECD Share Price Index Data.""" + + +class OECDSharePriceIndexFetcher( + Fetcher[OECDSharePriceIndexQueryParams, List[OECDSharePriceIndexData]] +): + """OECD Share Price Index Fetcher.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> OECDSharePriceIndexQueryParams: + """Transform the query.""" + transformed_params = params.copy() + if transformed_params.get("start_date") is None: + transformed_params["start_date"] = ( + date(2000, 1, 1) + if transformed_params.get("country") == "all" + else date(1958, 1, 1) + ) + if transformed_params.get("end_date") is None: + transformed_params["end_date"] = date(date.today().year, 12, 31) + if transformed_params.get("country") is None: + transformed_params["country"] = "united_states" + + return OECDSharePriceIndexQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: OECDSharePriceIndexQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the OECD endpoint.""" + frequency = frequency_dict.get(query.frequency) + + def country_string(input_str: str): + if input_str == "all": + return "" + countries = input_str.split(",") + return "+".join([COUNTRY_TO_CODE_RGDP[country] for country in countries]) + + country = country_string(query.country) + start_date = query.start_date.strftime("%Y-%m") if query.start_date else "" + end_date = query.end_date.strftime("%Y-%m") if query.end_date else "" + url = ( + "https://sdmx.oecd.org/public/rest/data/OECD.SDD.STES,DSD_STES@DF_FINMARK,4.0/" + + f"{country}.{frequency}.SHARE......?" + + f"startPeriod={start_date}&endPeriod={end_date}" + + "&dimensionAtObservation=TIME_PERIOD&detail=dataonly" + ) + headers = {"Accept": "application/vnd.sdmx.data+csv; charset=utf-8"} + response = make_request(url, headers=headers) + if response.status_code != 200: + raise Exception(f"Error: {response.status_code}") + df = read_csv(StringIO(response.text)).get( + ["REF_AREA", "TIME_PERIOD", "OBS_VALUE"] + ) + if df.empty: + raise EmptyDataError() + df = df.rename( + columns={"REF_AREA": "country", "TIME_PERIOD": "date", "OBS_VALUE": "value"} + ) + df = ( + df.query("value.notnull()") + .set_index(["date", "country"]) + .sort_index() + .reset_index() + ) + df.country = df.country.map(CODE_TO_COUNTRY_RGDP) + df.date = df.date.apply(oecd_date_to_python_date) + + return df.to_dict("records") + + @staticmethod + def transform_data( + query: OECDSharePriceIndexQueryParams, data: List[Dict], **kwargs: Any + ) -> List[OECDSharePriceIndexData]: + """Transform the data from the OECD endpoint.""" + return [OECDSharePriceIndexData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/oecd/openbb_oecd/models/short_term_interest_rate.py b/openbb_platform/providers/oecd/openbb_oecd/models/short_term_interest_rate.py index aee3e11aef55..dfe8800768a2 100644 --- a/openbb_platform/providers/oecd/openbb_oecd/models/short_term_interest_rate.py +++ b/openbb_platform/providers/oecd/openbb_oecd/models/short_term_interest_rate.py @@ -1,4 +1,4 @@ -"""OECD Short Term Interest Rate Rate Data.""" +"""OECD Short Term Interest Rate Data.""" # pylint: disable=unused-argument @@ -23,7 +23,7 @@ class OECDSTIRQueryParams(STIRQueryParams): """OECD Short Term Interest Rate Query.""" country: CountriesLiteral = Field( - description="Country to get GDP for.", default="united_states" + description="Country to get interest rate for.", default="united_states" ) frequency: Literal["monthly", "quarterly", "annual"] = Field( diff --git a/openbb_platform/providers/oecd/openbb_oecd/utils/constants.py b/openbb_platform/providers/oecd/openbb_oecd/utils/constants.py index f03885d5a835..67daa4b05313 100644 --- a/openbb_platform/providers/oecd/openbb_oecd/utils/constants.py +++ b/openbb_platform/providers/oecd/openbb_oecd/utils/constants.py @@ -169,8 +169,8 @@ CODE_TO_COUNTRY_GDP_FORECAST = {v: k for k, v in COUNTRY_TO_CODE_GDP_FORECAST.items()} COUNTRY_TO_CODE_CPI = { - "G20": "G-20", - "G7": "G-7", + "G20": "G20", + "G7": "G7", "argentina": "ARG", "australia": "AUS", "austria": "AUT", @@ -184,7 +184,7 @@ "czech_republic": "CZE", "denmark": "DNK", "estonia": "EST", - "euro_area_19": "EA19", + "euro_area_20": "EA20", "europe": "OECDE", "european_union_27": "EU27_2020", "finland": "FIN", @@ -222,6 +222,7 @@ "united_kingdom": "GBR", "united_states": "USA", } +CODE_TO_COUNTRY_CPI = {v: k for k, v in COUNTRY_TO_CODE_CPI.items()} COUNTRY_TO_CODE_BALANCE = { "australia": "AUS", @@ -581,3 +582,52 @@ } CODE_TO_COUNTRY_IR = {v: k for k, v in COUNTRY_TO_CODE_IR.items()} + +COUNTRY_TO_CODE_SHARES = { + "slovenia": "SVN", + "russia": "RUS", + "latvia": "LVA", + "korea": "KOR", + "brazil": "BRA", + "france": "FRA", + "sweden": "SWE", + "luxembourg": "LUX", + "belgium": "BEL", + "china": "CHN", + "finland": "FIN", + "euro_area19": "EA19", + "japan": "JPN", + "hungary": "HUN", + "australia": "AUS", + "switzerland": "CHE", + "portugal": "PRT", + "estonia": "EST", + "canada": "CAN", + "slovak_republic": "SVK", + "turkey": "TUR", + "croatia": "HRV", + "denmark": "DNK", + "italy": "ITA", + "india": "IND", + "south_africa": "ZAF", + "czech_republic": "CZE", + "new_zealand": "NZL", + "netherlands": "NLD", + "iceland": "ISL", + "germany": "DEU", + "indonesia": "IDN", + "ireland": "IRL", + "united_states": "USA", + "chile": "CHL", + "lithuania": "LTU", + "greece": "GRC", + "united_kingdom": "GBR", + "colombia": "COL", + "norway": "NOR", + "spain": "ESP", + "israel": "ISR", + "poland": "POL", + "austria": "AUT", + "mexico": "MEX", +} +CODE_TO_COUNTRY_SHARES = {v: k for k, v in COUNTRY_TO_CODE_SHARES.items()} diff --git a/openbb_platform/providers/oecd/openbb_oecd/utils/helpers.py b/openbb_platform/providers/oecd/openbb_oecd/utils/helpers.py index 3e11609ef3ec..b2bbaf439f45 100644 --- a/openbb_platform/providers/oecd/openbb_oecd/utils/helpers.py +++ b/openbb_platform/providers/oecd/openbb_oecd/utils/helpers.py @@ -252,12 +252,12 @@ def get_possibly_cached_data( def oecd_date_to_python_date(input_date: Union[str, int]) -> date: - """Use Darrens good idea to make the dates filterable.""" + """Date formatter helper.""" input_date = str(input_date) if "Q" in input_date: - return to_datetime(input_date).to_period("Q").to_timestamp("Q").date() + return to_datetime(input_date).to_period("Q").start_time.date() if len(input_date) == 4: - return date(int(input_date), 12, 31) + return date(int(input_date), 1, 1) if len(input_date) == 7: - return to_datetime(input_date).to_period("M").to_timestamp("M").date() + return to_datetime(input_date).to_period("M").start_time.date() raise ValueError("Date not in expected format") diff --git a/openbb_platform/providers/oecd/tests/record/http/test_oecd_fetchers/test_oecd_cpi_fetcher.yaml b/openbb_platform/providers/oecd/tests/record/http/test_oecd_fetchers/test_oecd_cpi_fetcher.yaml new file mode 100644 index 000000000000..6c0e1ce68cc0 --- /dev/null +++ b/openbb_platform/providers/oecd/tests/record/http/test_oecd_fetchers/test_oecd_cpi_fetcher.yaml @@ -0,0 +1,80 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://sdmx.oecd.org/public/rest/data/OECD.SDD.TPS,DSD_PRICES@DF_PRICES_ALL,1.0/GBR.A.N.CPI.PA._T.N. + response: + body: + string: !!binary | + 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 + headers: + Accept-Ranges: + - values + Cache-Control: + - no-store,no-cache + Content-Encoding: + - gzip + Content-Type: + - application/vnd.sdmx.genericdata+xml; charset=utf-8; version=2.1 + Date: + - Tue, 28 May 2024 19:24:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=2592000 + Transfer-Encoding: + - chunked + Vary: + - Accept,Accept-Encoding,Accept-Encoding + X-Server-Node: + - Server 2 + api-supported-versions: + - '1' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/oecd/tests/record/http/test_oecd_fetchers/test_oecd_share_price_index_fetcher.yaml b/openbb_platform/providers/oecd/tests/record/http/test_oecd_fetchers/test_oecd_share_price_index_fetcher.yaml new file mode 100644 index 000000000000..6c3951e20bf2 --- /dev/null +++ b/openbb_platform/providers/oecd/tests/record/http/test_oecd_fetchers/test_oecd_share_price_index_fetcher.yaml @@ -0,0 +1,61 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/vnd.sdmx.data+csv; charset=utf-8 + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://sdmx.oecd.org/public/rest/data/OECD.SDD.STES,DSD_STES@DF_FINMARK,4.0/GBR.M.SHARE......?detail=dataonly&dimensionAtObservation=TIME_PERIOD&endPeriod=2024-04&startPeriod=2020-01 + response: + body: + string: !!binary | + H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcpl + VmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ip4evzl+ + 9vzL745enT77/Y9fnR6Pnr06/YnRF6fHr796dTr66sXZm9/f/HF88ubsJ8/e/D6j46ff+er1my9O + X7wZvXl1/OL1sy9ffXH85uzLF6M3Z1+c/v7f/vLV2U8RiDff/vLpl8+//Pz3kY9fnr46+/Lp6Msn + r3//nzx+/tUp//b6zfGbr15rP189fzN6enpy9sXx89ejJ8ev+Z3fOPny9OTp+PVT+v+b09ePnr5+ + Sm+dvv49nz77/Z+dvfji+NXvtbU/3rkz+vzJq9EXo9ffPiZUz37v0e//U+5/L0Z7O3s72zu7o93d + /fH9h/fvjej5JiHvEeSd8cHDB/sE+BuFfG908GC88+mDnfsE+BuFvM+Q793beUiAv1HI90cPd8YE + +N4BAf5GIX86erg//vThzr1vnBoPRg/vje/vHnz6KQH+RiEfjB7ujek3Igs93yTkh6ODh+OHn97f + JbhfD3Ac8O7O6OBg/GCP+JkAf6OQdzGB9+7f3/umRXB3b/TwYHyw9+mn36wI7rLa2Nkd7+8Qven5 + JiETzg8J54cH3yzTEeR7jPPBzu43To19grxPzLH7zfIGQb5PkD8d73/6cI8Af6OQPyXID8af7u1+ + s1xHkB8Q5E/HpDW+8Rk8IMgH47373/wMPiTID8a793b3Rt8sZNIbwPnT3QffNG+Q3oCB3b3/8JvV + dQRZTDeR+ZudwT3WG7v3xp/e//SbNYMEGTjvj/c+vffNSgpBJr1B1Hi4e/DNSgpBJr1BOH+6f++b + 5Q2CTHpjd2/88OGn36x+JsikN4gan37D7EyAoTYejokzvnEyk9ogptvbvZ1Ceh/IUBsPxzs7B980 + 07HauD9+sPtNzx9rjV2yVfe+adlmrXFvfG/vG9ZH90RrPCDZ/mZRJsCE8t7OeGf34JtVRwQZSuP+ + +GD34Js1VQQZSuOA5OQbJwZ0xqfjh/sH36xTTpChMyjIPPiGRZsgk9Ignnu4++Cbm0CFDKWxR17M + Nxy+EmRSGkSNgwcH36wKvcdKg6ixv//pNy2BrDWIGvfvfdMzyFrjPnm4B9+sptsXrXF/fG/nG5YU + giw4H9wjstDzTUKG2ngwfnj//jfLzwSZ1AapuoefEvvR8xsn/w9aOOug5xIAAA== + headers: + Accept-Ranges: + - values + Cache-Control: + - no-store,no-cache + Content-Encoding: + - gzip + Content-Language: + - en,en-US + Content-Type: + - application/vnd.sdmx.data+csv; charset=utf-8 + Date: + - Wed, 29 May 2024 19:14:03 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=2592000 + Transfer-Encoding: + - chunked + Vary: + - Accept,Accept-Encoding,Accept-Encoding + X-Server-Node: + - Server 2 + api-supported-versions: + - '1' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/oecd/tests/test_oecd_fetchers.py b/openbb_platform/providers/oecd/tests/test_oecd_fetchers.py index c1e0dc618ea7..b0e3a76e06ea 100644 --- a/openbb_platform/providers/oecd/tests/test_oecd_fetchers.py +++ b/openbb_platform/providers/oecd/tests/test_oecd_fetchers.py @@ -5,10 +5,12 @@ import pytest from openbb_core.app.service.user_service import UserService from openbb_oecd.models.composite_leading_indicator import OECDCLIFetcher +from openbb_oecd.models.consumer_price_index import OECDCPIFetcher from openbb_oecd.models.gdp_forecast import OECDGdpForecastFetcher from openbb_oecd.models.gdp_nominal import OECDGdpNominalFetcher from openbb_oecd.models.gdp_real import OECDGdpRealFetcher from openbb_oecd.models.long_term_interest_rate import OECDLTIRFetcher +from openbb_oecd.models.share_price_index import OECDSharePriceIndexFetcher from openbb_oecd.models.short_term_interest_rate import OECDSTIRFetcher from openbb_oecd.models.unemployment import OECDUnemploymentFetcher @@ -28,6 +30,19 @@ def vcr_config(): } +@pytest.mark.record_http +def test_oecd_cpi_fetcher(credentials=test_credentials): + """Test the OECD CPI fetcher.""" + params = { + "country": "united_kingdom", + "frequency": "annual", + } + + fetcher = OECDCPIFetcher() + result = fetcher.test(params, credentials) + assert result is None + + @pytest.mark.record_http def test_oecd_nominal_gdp_fetcher(credentials=test_credentials): """Test the OECD Nominal GDP fetcher.""" @@ -116,3 +131,17 @@ def test_oecdltir_fetcher(credentials=test_credentials): fetcher = OECDLTIRFetcher() result = fetcher.test(params, credentials) assert result is None + + +@pytest.mark.record_http +def test_oecd_share_price_index_fetcher(credentials=test_credentials): + """Test the OECD Share Price Index fetcher.""" + params = { + "start_date": datetime.date(2020, 1, 1), + "end_date": datetime.date(2024, 4, 1), + "country": "united_kingdom", + } + + fetcher = OECDSharePriceIndexFetcher() + result = fetcher.test(params, credentials) + assert result is None