summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-05-17 13:10:33 -0700
committerDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-05-17 13:10:33 -0700
commitfbaf10f879bc2e30bd3ae6ec7507e79c193b3abc (patch)
treed195e3e222e038008da4693fbdc974cf7f3f88b2
parentb33e563dc19dcce2aaf382202c557348a98b7c3b (diff)
add balance of payments to FRED provider
-rw-r--r--openbb_platform/extensions/economy/integration/test_economy_api.py8
-rw-r--r--openbb_platform/extensions/economy/integration/test_economy_python.py8
-rw-r--r--openbb_platform/extensions/economy/openbb_economy/economy_router.py2
-rw-r--r--openbb_platform/openbb/assets/reference.json248
-rw-r--r--openbb_platform/openbb/package/economy.py109
-rw-r--r--openbb_platform/providers/fred/openbb_fred/models/balance_of_payments.py124
-rw-r--r--openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py134
-rw-r--r--openbb_platform/providers/fred/tests/record/http/test_fred_fetchers/test_fred_balance_of_payments_fetcher.yaml1810
-rw-r--r--openbb_platform/providers/fred/tests/test_fred_fetchers.py15
9 files changed, 2457 insertions, 1 deletions
diff --git a/openbb_platform/extensions/economy/integration/test_economy_api.py b/openbb_platform/extensions/economy/integration/test_economy_api.py
index f8de0ee5ca1..3f7998c14de 100644
--- a/openbb_platform/extensions/economy/integration/test_economy_api.py
+++ b/openbb_platform/extensions/economy/integration/test_economy_api.py
@@ -251,6 +251,14 @@ def test_economy_gdp_real(params, headers):
"provider": "ecb",
}
),
+ (
+ {
+ "country": "united_states",
+ "start_date": None,
+ "end_date": None,
+ "provider": "fred",
+ }
+ ),
],
)
@pytest.mark.integration
diff --git a/openbb_platform/extensions/economy/integration/test_economy_python.py b/openbb_platform/extensions/economy/integration/test_economy_python.py
index dec33dacb6e..75a01123c7b 100644
--- a/openbb_platform/extensions/economy/integration/test_economy_python.py
+++ b/openbb_platform/extensions/economy/integration/test_economy_python.py
@@ -212,6 +212,14 @@ def test_economy_gdp_real(params, obb):
"provider": "ecb",
}
),
+ (
+ {
+ "country": "united_states",
+ "start_date": None,
+ "end_date": None,
+ "provider": "fred",
+ }
+ ),
],
)
@pytest.mark.integration
diff --git a/openbb_platform/extensions/economy/openbb_economy/economy_router.py b/openbb_platform/extensions/economy/openbb_economy/economy_router.py
index 19eb403cea1..6adeaeea1ea 100644
--- a/openbb_platform/extensions/economy/openbb_economy/economy_router.py
+++ b/openbb_platform/extensions/economy/openbb_economy/economy_router.py
@@ -93,6 +93,8 @@ async def risk_premium(
@router.command(
model="BalanceOfPayments",
examples=[
+ APIEx(parameters={"provider": "fred"}),
+ APIEx(parameters={"provider": "fred", "country": "brazil"}),
APIEx(parameters={"provider": "ecb"}),
APIEx(parameters={"report_type": "summary", "provider": "ecb"}),
APIEx(
diff --git a/openbb_platform/openbb/assets/reference.json b/openbb_platform/openbb/assets/reference.json
index 0c7ed54c228..bbc14f5b00d 100644
--- a/openbb_platform/openbb/assets/reference.json
+++ b/openbb_platform/openbb/assets/reference.json
@@ -3153,6 +3153,254 @@
},
"model": "RiskPremium"
},
+ "/economy/balance_of_payments": {
+ "deprecated": {
+ "flag": null,
+ "message": null
+ },
+ "description": "Balance of Payments Reports.",
+ "examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.balance_of_payments(provider='fred')\nobb.economy.balance_of_payments(provider='fred', country=brazil)\n```\n\n",
+ "parameters": {
+ "standard": [
+ {
+ "name": "provider",
+ "type": "Literal['fred']",
+ "description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default.",
+ "default": "fred",
+ "optional": true
+ }
+ ],
+ "fred": [
+ {
+ "name": "country",
+ "type": "Literal['argentina', 'australia', 'austria', 'belgium', 'brazil', 'canada', 'chile', 'china', 'colombia', 'costa_rica', 'czechia', 'denmark', 'estonia', 'finland', 'france', 'germany', 'greece', 'hungary', 'iceland', 'india', 'indonesia', 'ireland', 'israel', 'italy', 'japan', 'korea', 'latvia', 'lithuania', 'luxembourg', 'mexico', 'netherlands', 'new_zealand', 'norway', 'poland', 'portugal', 'russia', 'saudi_arabia', 'slovak_republic', 'slovenia', 'south_africa', 'spain', 'sweden', 'switzerland', 'turkey', 'united_kingdom', 'united_states', 'g7', 'g20']",
+ "description": "The country to get data. Enter as a 3-letter ISO country code, default is USA.",
+ "default": "united_states",
+ "optional": true,
+ "choices": "argentina,australia,austria,belgium,brazil,canada,chile,china,colombia,costa_rica,czechia,denmark,estonia,finland,france,germany,greece,hungary,iceland,india,indonesia,ireland,israel,italy,japan,korea,latvia,lithuania,luxembourg,mexico,netherlands,new_zealand,norway,poland,portugal,russia,saudi_arabia,slovak_republic,slovenia,south_africa,spain,sweden,switzerland,turkey,united_kingdom,united_states,g7,g20"
+ },
+ {
+ "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
+ }
+ ]
+ },
+ "returns": {
+ "OBBject": [
+ {
+ "name": "results",
+ "type": "List[BalanceOfPayments]",
+ "description": "Serializable results."
+ },
+ {
+ "name": "provider",
+ "type": "Optional[Literal['fred']]",
+ "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": "period",
+ "type": "date",
+ "description": "The date representing the beginning of the reporting period.",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "balance_percent_of_gdp",
+ "type": "float",
+ "description": "Current Account Balance as Percent of GDP",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "balance_total",
+ "type": "float",
+ "description": "Current Account Total Balance (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "balance_total_services",
+ "type": "float",
+ "description": "Current Account Total Services Balance (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "balance_total_secondary_income",
+ "type": "float",
+ "description": "Current Account Total Secondary Income Balance (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "balance_total_goods",
+ "type": "float",
+ "description": "Current Account Total Goods Balance (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "balance_total_primary_income",
+ "type": "float",
+ "description": "Current Account Total Primary Income Balance (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_services_percent_of_goods_and_services",
+ "type": "float",
+ "description": "Current Account Credits Services as Percent of Goods and Services",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_services_percent_of_current_account",
+ "type": "float",
+ "description": "Current Account Credits Services as Percent of Current Account",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_total_services",
+ "type": "float",
+ "description": "Current Account Credits Total Services (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_total_goods",
+ "type": "float",
+ "description": "Current Account Credits Total Goods (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_total_primary_income",
+ "type": "float",
+ "description": "Current Account Credits Total Primary Income (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_total_secondary_income",
+ "type": "float",
+ "description": "Current Account Credits Total Secondary Income (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "credits_total",
+ "type": "float",
+ "description": "Current Account Credits Total (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_services_percent_of_goods_and_services",
+ "type": "float",
+ "description": "Current Account Debits Services as Percent of Goods and Services",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_services_percent_of_current_account",
+ "type": "float",
+ "description": "Current Account Debits Services as Percent of Current Account",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_total_services",
+ "type": "float",
+ "description": "Current Account Debits Total Services (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_total_goods",
+ "type": "float",
+ "description": "Current Account Debits Total Goods (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_total_primary_income",
+ "type": "float",
+ "description": "Current Account Debits Total Primary Income (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_total",
+ "type": "float",
+ "description": "Current Account Debits Total (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ },
+ {
+ "name": "debits_total_secondary_income",
+ "type": "float",
+ "description": "Current Account Debits Total Secondary Income (USD)",
+ "default": null,
+ "optional": true,
+ "choices": null
+ }
+ ],
+ "fred": []
+ },
+ "model": "BalanceOfPayments"
+ },
"/economy/fred_search": {
"deprecated": {
"flag": null,
diff --git a/openbb_platform/openbb/package/economy.py b/openbb_platform/openbb/package/economy.py
index fcf6f22d4c8..0a589831355 100644
--- a/openbb_platform/openbb/package/economy.py
+++ b/openbb_platform/openbb/package/economy.py
@@ -14,6 +14,7 @@ from typing_extensions import Annotated
class ROUTER_economy(Container):
"""/economy
available_indicators
+ balance_of_payments
calendar
composite_leading_indicator
country_profile
@@ -124,6 +125,114 @@ class ROUTER_economy(Container):
@exception_handler
@validate
+ def balance_of_payments(
+ self,
+ provider: Annotated[
+ Optional[Literal["fred"]],
+ OpenBBField(
+ description="The provider to use for the query, by default None.\n If None, the provider specified in defaults is selected or 'fred' if there is\n no default."
+ ),
+ ] = None,
+ **kwargs
+ ) -> OBBject:
+ """Balance of Payments Reports.
+
+ Parameters
+ ----------
+ provider : Optional[Literal['fred']]
+ The provider to use for the query, by default None.
+ If None, the provider specified in defaults is selected or 'fred' if there is
+ no default.
+ country : Literal['argentina', 'australia', 'austria', 'belgium', 'brazil', 'canada', 'chile', 'china', 'colombia', 'costa_rica', 'czechia', 'denmark', 'estonia', 'finland', 'france', 'germany', 'greece', 'hungary', 'iceland', 'india', 'indonesia', 'ireland', 'israel', 'italy', 'japan', 'korea', 'latvia', 'lithuania', 'luxembourg', 'mexico', 'netherlands', 'new_zealand', 'norway', 'poland', 'portugal', 'russia', 'saudi_arabia', 'slovak_republic', 'slovenia', 'south_africa', 'spain', 'sweden', 'switzerland', 'turkey', 'united_kingdom', 'united_states', 'g7', 'g20']
+ The country to get data. Enter as a 3-letter ISO country code, default is USA. (provider: fred)
+ start_date : Optional[datetime.date]
+ Start date of the data, in YYYY-MM-DD format. (provider: fred)
+ end_date : Optional[datetime.date]
+ End date of the data, in YYYY-MM-DD format. (provider: fred)
+
+ Returns
+ -------
+ OBBject
+ results : List[BalanceOfPayments]
+ Serializable results.
+ provider : Optional[Literal['fred']]
+ Provider name.
+ warnings : Optional[List[Warning_]]
+ List of warnings.
+ chart : Optional[Chart]
+ Chart object.
+ extra : Dict[str, Any]
+ Extra info.
+
+ BalanceOfPayments
+ -----------------
+ period : Optional[date]
+ The date representing the beginning of the reporting period.
+ balance_percent_of_gdp : Optional[float]
+ Current Account Balance as Percent of GDP
+ balance_total : Optional[float]
+ Current Account Total Balance (USD)
+ balance_total_services : Optional[float]
+ Current Account Total Services Balance (USD)
+ balance_total_secondary_income : Optional[float]
+ Current Account Total Secondary Income Balance (USD)
+ balance_total_goods : Optional[float]
+ Current Account Total Goods Balance (USD)
+ balance_total_primary_income : Optional[float]
+ Current Account Total Primary Income Balance (USD)
+ credits_services_percent_of_goods_and_services : Optional[float]
+ Current Account Credits Services as Percent of Goods and Services
+ credits_services_percent_of_current_account : Optional[float]
+ Current Account Credits Services as Percent of Current Account
+ credits_total_services : Optional[float]
+ Current Account Credits Total Services (USD)
+ credits_total_goods : Optional[float]
+ Current Account Credits Total Goods (USD)
+ credits_total_primary_income : Optional[float]
+ Current Account Credits Total Primary Income (USD)
+ credits_total_secondary_income : Optional[float]
+ Current Account Credits Total Secondary Income (USD)
+ credits_total : Optional[float]
+ Current Account Credits Total (USD)
+ debits_services_percent_of_goods_and_services : Optional[float]
+ Current Account Debits Services as Percent of Goods and Services
+ debits_services_percent_of_current_account : Optional[float]
+ Current Account Debits Services as Percent of Current Account
+ debits_total_services : Optional[float]
+ Current Account Debits Total Services (USD)
+ debits_total_goods : Optional[float]
+ Current Account Debits Total Goods (USD)
+ debits_total_primary_income : Optional[float]
+ Current Account Debits Total Primary Income (USD)
+ debits_total : Optional[float]
+ Current Account Debits Total (USD)
+ debits_total_secondary_income : Optional[float]
+ Current Account Debits Total Secondary Income (USD)
+
+ Examples
+ --------
+ >>> from openbb import obb
+ >>> obb.economy.balance_of_payments(provider='fred')
+ >>> obb.economy.balance_of_payments(provider='fred', country='brazil')
+ """ # noqa: E501
+
+ return self._run(
+ "/economy/balance_of_payments",
+ **filter_inputs(
+ provider_choices={
+ "provider": self._get_provider(
+ provider,
+ "/economy/balance_of_payments",
+ ("fred",),
+ )
+ },
+ standard_params={},
+ extra_params=kwargs,
+ )
+ )
+
+ @exception_handler
+ @validate
def calendar(
self,
start_date: Annotated[
diff --git a/openbb_platform/providers/fred/openbb_fred/models/balance_of_payments.py b/openbb_platform/providers/fred/openbb_fred/models/balance_of_payments.py
new file mode 100644
index 00000000000..bdfb141e2cf
--- /dev/null
+++ b/openbb_platform/providers/fred/openbb_fred/models/balance_of_payments.py
@@ -0,0 +1,124 @@
+"""FRED Balance Of Payments Model."""
+
+# pylint: disable=unused-argument
+
+from datetime import date as dateType
+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.balance_of_payments import (
+ B6BopUsdData,
+ BalanceOfPaymentsQueryParams,
+)
+from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
+from openbb_core.provider.utils.errors import EmptyDataError
+from openbb_fred.models.series import (
+ FredSeriesData,
+ FredSeriesFetcher,
+ FredSeriesQueryParams,
+)
+from openbb_fred.utils.fred_helpers import (
+ BOP_COUNTRIES,
+ BOP_COUNTRY_CHOICES,
+ get_bop_series,
+)
+from pandas import DataFrame
+from pydantic import Field, field_validator
+
+
+class FredBalanceOfPaymentsQueryParams(BalanceOfPaymentsQueryParams):
+ """FRED Balance Of Payments Query Parameters."""
+
+ country: BOP_COUNTRY_CHOICES = Field(
+ default="united_states",
+ description=QUERY_DESCRIPTIONS.get("country", "")
+ + " Enter as a 3-letter ISO country code, default is USA.",
+ json_schema_extra={"choices": ",".join(list(BOP_COUNTRIES))},
+ )
+ 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 FredBalanceOfPaymentsData(B6BopUsdData):
+ """FRED Balance Of Payments Data."""
+
+ __alias_dict__ = {"period": "date"}
+
+ @field_validator(
+ "balance_percent_of_gdp",
+ "credits_services_percent_of_goods_and_services",
+ "credits_services_percent_of_current_account",
+ "debits_services_percent_of_goods_and_services",
+ "debits_services_percent_of_current_account",
+ mode="before",
+ check_fields=False,
+ )
+ @classmethod
+ def normalize_percent(cls, v):
+ """Normalize the percent value."""
+ return float(v) / 100 if v else None
+
+
+class FredBalanceOfPaymentsFetcher(
+ Fetcher[FredBalanceOfPaymentsQueryParams, List[FredBalanceOfPaymentsData]]
+):
+ """FRED Balance Of Payments Fetcher."""
+
+ @staticmethod
+ def transform_query(params: Dict[str, Any]) -> FredBalanceOfPaymentsQueryParams:
+ """Transform query."""
+ return FredBalanceOfPaymentsQueryParams(**params)
+
+ @staticmethod
+ async def aextract_data(
+ query: FredBalanceOfPaymentsQueryParams,
+ credentials: Optional[Dict[str, str]],
+ **kwargs: Any,
+ ) -> Dict:
+ """Extract data."""
+ fred_fetcher = FredSeriesFetcher()
+ country = BOP_COUNTRIES.get(query.country) if query.country else "USA"
+ query_dict = query.model_dump(exclude_none=True)
+ query_dict["symbol"] = ",".join(list(get_bop_series(country).values()))
+ fred_query = FredSeriesQueryParams(**query_dict)
+ data = await fred_fetcher.aextract_data(fred_query, credentials)
+ return data
+
+ @staticmethod
+ def transform_data(
+ query: FredBalanceOfPaymentsQueryParams,
+ data: Dict,
+ **kwargs: Any,
+ ) -> AnnotatedResult[List[FredBalanceOfPaymentsData]]:
+ """Transform data."""
+ if not data:
+ raise EmptyDataError(f"No data was found for, {query.country}.")
+ fred_fetcher = FredSeriesFetcher()
+ country = BOP_COUNTRIES.get(query.country) if query.country else "USA"
+ query_dict = query.model_dump(exclude_none=True)
+ query_dict["symbol"] = ",".join(list(get_bop_series(country).values()))
+ fred_query = FredSeriesQueryParams(**query_dict)
+ data = fred_fetcher.transform_data(fred_query, data)
+
+ series_ids = get_bop_series(query.country)
+ col_map = {v: k for k, v in series_ids.items()}
+ result = data.result
+ df = (
+ DataFrame([d.model_dump() for d in result])
+ .set_index("date")
+ .sort_index(ascending=False)
+ )
+ df = df.rename(columns=col_map)
+ records = df.reset_index().fillna("N/A").replace("N/A", None).to_dict("records")
+
+ return AnnotatedResult(
+ result=[FredBalanceOfPaymentsData.model_validate(r) for r in records],
+ metadata=data.metadata,
+ )
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 b61cc26625e..9d2ce67d8c4 100644
--- a/openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py
+++ b/openbb_platform/providers/fred/openbb_fred/utils/fred_helpers.py
@@ -57,7 +57,7 @@ def comma_to_float_list(v: str) -> List[float]:
return [float(m) for m in v.split(",")]
except ValueError as e:
raise ValueError(
- "'maturity' must be a float or a comma-separated string of floats"
+ "maturity must be a float or a comma-separated string of floats"
) from e
@@ -216,3 +216,135 @@ def get_spot_series_id(maturity: List[float], category: List[str]) -> List[dict]
filtered_series.append(s)
return filtered_series
+
+
+BOP_COUNTRIES = {
+ "argentina": "ARG",
+ "australia": "AUS",
+ "austria": "AUT",
+ "belgium": "BEL",
+ "brazil": "BRA",
+ "canada": "CAN",
+ "chile": "CHL",
+ "china": "CHN",
+ "colombia": "COL",
+ "costa_rica": "CRI",
+ "czechia": "CZE",
+ "denmark": "DNK",
+ "estonia": "EST",
+ "finland": "FIN",
+ "france": "FRA",
+ "germany": "DEU",
+ "greece": "GRC",
+ "hungary": "HUN",
+ "iceland": "ISL",
+ "india": "IND",
+ "indonesia": "IDN",
+ "ireland": "IRL",
+ "israel": "ISR",
+ "italy": "ITA",
+ "japan": "JAP",
+ "korea": "KOR",
+ "latvia": "LVA",
+ "lithuania": "LTU",
+ "luxembourg": "LUX",
+ "mexico": "MEX",
+ "netherlands": "NLD",
+ "new_zealand": "NZL",
+ "norway": "NOR",
+ "poland": "POL",
+ "portugal": "PRT",
+ "russia": "RUS",
+ "saudi_arabia": "SAU",
+ "slovak_republic": "SVK",
+ "slovenia": "SVN",
+ "south_africa": "ZAF",
+ "spain": "ESP",
+ "sweden": "SWE",
+ "switzerland": "CHE",
+ "turkey": "TUR",
+ "united_kingdom": "GBR",
+ "united_states": "USA",
+ "g7": "G7",
+ "g20": "G20",
+}
+
+BOP_COUNTRY_CHOICES = Literal[
+ "argentina",
+ "australia",
+ "austria",
+ "belgium",
+ "brazil",
+ "canada",
+ "chile",
+ "china",
+ "colombia",
+ "costa_rica",
+