Skip to content

Commit

Permalink
[Feature] EconDB Provider Extension With New Economy Endpoints. (#6313)
Browse files Browse the repository at this point in the history
* economy router

* router endpoints

* update available_indicators

* add econdb provider extension

* black

* fetcher test

* country description

* recapture tests and router examples

* black

* codespell

* codespell skip

* codespell skip...?

* use . instead of * in codespell.skip?

* this is supposed to skip the file from codespell

* try another thing for codespell

* unused import

* pylint

* doc page example - df.filter needs axis

* unused argument

* more pylint

* mypy

* insert image to doc page

* recapture test

* description

* mypy

* Update .codespell.skip

* black

* linting..

* more linters

* black

* init docstring

* static files

---------

Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
  • Loading branch information
deeleeramone and IgorWounds authored Apr 22, 2024
1 parent f18680a commit ee42241
Show file tree
Hide file tree
Showing 36 changed files with 16,017 additions and 387 deletions.
1 change: 1 addition & 0 deletions .codespell.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ shold
shs
statics
te
tha
toke
vai
varian
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Available Indicators Standard Model."""

from typing import 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


class AvailableIndicesQueryParams(QueryParams):
"""Available Indicators Query."""


class AvailableIndicatorsData(Data):
"""Available Indicators Data.
Returns the list of available economic indicators from a provider.
"""

symbol_root: Optional[str] = Field(
default=None, description="The root symbol representing the indicator."
)
symbol: Optional[str] = Field(
default=None,
description=DATA_DESCRIPTIONS.get("symbol", "")
+ " The root symbol with additional codes.",
)
country: Optional[str] = Field(
default=None,
description="The name of the country, region, or entity represented by the symbol.",
)
iso: Optional[str] = Field(
default=None,
description="The ISO code of the country, region, or entity represented by the symbol.",
)
description: Optional[str] = Field(
default=None, description="The description of the indicator."
)
frequency: Optional[str] = Field(
default=None, description="The frequency of the indicator data."
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""Country Profile Standard Model."""

from typing import 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 CountryProfileQueryParams(QueryParams):
"""Country Profile Query."""

country: str = Field(description=QUERY_DESCRIPTIONS.get("country", ""))

@field_validator("country", mode="before", check_fields=False)
@classmethod
def to_lower(cls, v: str) -> str:
"""Convert the country to lowercase."""
return v.lower().replace(" ", "_")


class CountryProfileData(Data):
"""Country Profile Data."""

country: str = Field(description=DATA_DESCRIPTIONS.get("country", ""))
population: Optional[int] = Field(default=None, description="Population.")
gdp_usd: Optional[float] = Field(
default=None, description="Gross Domestic Product, in billions of USD."
)
gdp_qoq: Optional[float] = Field(
default=None,
description="GDP growth quarter-over-quarter change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
gdp_yoy: Optional[float] = Field(
default=None,
description="GDP growth year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
cpi_yoy: Optional[float] = Field(
default=None,
description="Consumer Price Index year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
core_yoy: Optional[float] = Field(
default=None,
description="Core Consumer Price Index year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
retail_sales_yoy: Optional[float] = Field(
default=None,
description="Retail Sales year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
industrial_production_yoy: Optional[float] = Field(
default=None,
description="Industrial Production year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
policy_rate: Optional[float] = Field(
default=None,
description="Short term policy rate, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
yield_10y: Optional[float] = Field(
default=None,
description="10-year government bond yield, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
govt_debt_gdp: Optional[float] = Field(
default=None,
description="Government debt as a percent (normalized) of GDP.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
current_account_gdp: Optional[float] = Field(
default=None,
description="Current account balance as a percent (normalized) of GDP.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
jobless_rate: Optional[float] = Field(
default=None,
description="Unemployment rate, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Economic Indicators Standard Model."""

from datetime import date as dateType
from typing import Optional, Union

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 EconomicIndicatorsQueryParams(QueryParams):
"""Economic Indicators Query."""

symbol: str = Field(
description=QUERY_DESCRIPTIONS.get("symbol", "")
+ " The base symbol for the indicator (e.g. GDP, CPI, etc.).",
)
country: Optional[str] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("country", "")
+ " The country represented by the indicator, if available.",
)
start_date: Optional[dateType] = Field(
description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None
)
end_date: Optional[dateType] = Field(
description=QUERY_DESCRIPTIONS.get("end_date", ""), default=None
)

@field_validator("symbol", mode="before", check_fields=False)
@classmethod
def to_upper(cls, v: str) -> str:
"""Convert field to uppercase."""
return v.upper()


class EconomicIndicatorsData(Data):
"""Economic Indicators Data."""

date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", ""))
symbol_root: Optional[str] = Field(
default=None, description="The root symbol for the indicator (e.g. GDP)."
)
symbol: Optional[str] = Field(
default=None, description=DATA_DESCRIPTIONS.get("symbol", "")
)
country: Optional[str] = Field(
default=None, description="The country represented by the data."
)
value: Optional[Union[int, float]] = Field(
default=None, description=DATA_DESCRIPTIONS.get("value", "")
)
1 change: 1 addition & 0 deletions openbb_platform/dev_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
openbb-core = { path = "./core", develop = true }
openbb-benzinga = { path = "./providers/benzinga", develop = true }
openbb-econdb = { path = "./providers/econdb", develop = true }
openbb-federal-reserve = { path = "./providers/federal_reserve", develop = true }
openbb-fmp = { path = "./providers/fmp", develop = true }
openbb-fred = { path = "./providers/fred", develop = true }
Expand Down
71 changes: 71 additions & 0 deletions openbb_platform/extensions/economy/integration/test_economy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,3 +562,74 @@ def test_economy_fred_regional(params, headers):
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"symbol": "GDP,GDEBT",
"transform": None,
"start_date": "2022-01-01",
"end_date": "2024-01-01",
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_indicators(params, headers):
"""Test the economy indicators."""
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/indicators?{query_str}"
result = requests.get(url, headers=headers, timeout=20)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@parametrize(
"params",
[
({"provider": "econdb", "use_cache": False}),
],
)
@pytest.mark.integration
def test_economy_available_indicators(params, headers):
"""Test the economy available indicators."""
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/available_indicators?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"latest": True,
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_country_profile(params, headers):
"""Test the economy country profile."""
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/country_profile?{query_str}"
result = requests.get(url, headers=headers, timeout=30)
assert isinstance(result, requests.Response)
assert result.status_code == 200
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,71 @@ def test_economy_fred_regional(params, obb):
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0


@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"latest": True,
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_country_profile(params, obb):
"""Test economy country profile."""
params = {p: v for p, v in params.items() if v}

result = obb.economy.country_profile(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0


@parametrize(
"params",
[
({"provider": "econdb", "use_cache": False}),
],
)
@pytest.mark.integration
def test_economy_available_indicators(params, obb):
"""Test economy available indicators."""
params = {p: v for p, v in params.items() if v}

result = obb.economy.available_indicators(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0


@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"symbol": "GDP,GDEBT",
"transform": None,
"start_date": "2022-01-01",
"end_date": "2024-01-01",
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_indicators(params, obb):
"""Test economy indicators."""
params = {p: v for p, v in params.items() if v}

result = obb.economy.indicators(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
Loading

0 comments on commit ee42241

Please sign in to comment.