mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
[Feature] Add IMF Provider Extension and Extend obb.economic.indicators (#6666)
* add imf provider extension and extend economic.indicators * ruff * mypy * more mypy * provider.json
This commit is contained in:
8
assets/extensions/provider.json
vendored
8
assets/extensions/provider.json
vendored
@@ -145,6 +145,14 @@
|
||||
"credentials": [],
|
||||
"website": "https://data.gov"
|
||||
},
|
||||
{
|
||||
"packageName": "openbb-imf",
|
||||
"optional": false,
|
||||
"reprName": "International Monetary Fund (IMF) Public Data API",
|
||||
"description": "This provider allows you to access International Monetary Fund data through the IMF Public Data API.",
|
||||
"credentials": [],
|
||||
"website": "https://datahelp.imf.org/knowledgebase/articles/667681-using-json-restful-web-service"
|
||||
},
|
||||
{
|
||||
"packageName": "openbb-intrinio",
|
||||
"optional": false,
|
||||
|
||||
@@ -16,10 +16,6 @@ from openbb_core.provider.utils.descriptions import (
|
||||
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", "")
|
||||
|
||||
@@ -28,6 +28,7 @@ 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 }
|
||||
openbb-imf = { path = "./providers/imf", develop = true }
|
||||
openbb-intrinio = { path = "./providers/intrinio", develop = true }
|
||||
openbb-oecd = { path = "./providers/oecd", develop = true }
|
||||
openbb-polygon = { path = "./providers/polygon", develop = true }
|
||||
|
||||
@@ -609,6 +609,26 @@ def test_economy_fred_regional(params, headers):
|
||||
"frequency": "quarter",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "imf",
|
||||
"country": "us,uk,jp",
|
||||
"symbol": "gold_reserves",
|
||||
"start_date": "2022-01-01",
|
||||
"end_date": "2023-12-31",
|
||||
"frequency": "annual",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "imf",
|
||||
"country": "all",
|
||||
"symbol": "derivative_assets",
|
||||
"start_date": "2022-01-01",
|
||||
"end_date": "2023-12-31",
|
||||
"frequency": "annual",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
|
||||
@@ -629,6 +629,26 @@ def test_economy_available_indicators(params, obb):
|
||||
"frequency": "quarter",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "imf",
|
||||
"country": "us,uk,jp",
|
||||
"symbol": "gold_reserves",
|
||||
"start_date": "2022-01-01",
|
||||
"end_date": "2023-12-31",
|
||||
"frequency": "annual",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "imf",
|
||||
"country": "all",
|
||||
"symbol": "derivative_assets",
|
||||
"start_date": "2022-01-01",
|
||||
"end_date": "2023-12-31",
|
||||
"frequency": "annual",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
|
||||
@@ -411,6 +411,29 @@ async def available_indicators(
|
||||
description="Use the `main` symbol to get the group of main indicators for a country.",
|
||||
parameters={"provider": "econdb", "symbol": "main", "country": "eu"},
|
||||
),
|
||||
APIEx(
|
||||
description="When the provider is 'imf', the absence of a symbol will default to 'irfcl_top_lines'."
|
||||
+ " Use 'IRFCL' to get all the data from the set of indicators.",
|
||||
parameters={"provider": "imf"},
|
||||
),
|
||||
APIEx(
|
||||
description="When the provider is 'imf', complete tables are returned by using a 'preset'."
|
||||
+ " Refer to the function's docstring for descriptions of each preset."
|
||||
+ " When no country is supplied, the data is returned for all countries.",
|
||||
parameters={"provider": "imf", "symbol": "gold_reserves"},
|
||||
),
|
||||
APIEx(
|
||||
description="When the provider is 'imf', multiple countries and symbols can be supplied."
|
||||
+ " Enter countries as a two-letter ISO country code, or the country name in lower_snake_case.",
|
||||
parameters={
|
||||
"provider": "imf",
|
||||
"symbol": "RAFA_USD,RAPFA_USD,RAFA_RAPFA_RO",
|
||||
"country": "us,china,jp,4f,gb",
|
||||
"start_date": "2010-01-01",
|
||||
"end_date": "2020-12-31",
|
||||
"frequency": "annual",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def indicators(
|
||||
|
||||
351
openbb_platform/openbb/assets/reference.json
vendored
351
openbb_platform/openbb/assets/reference.json
vendored
@@ -26,6 +26,7 @@
|
||||
"federal_reserve@1.3.2",
|
||||
"fmp@1.3.2",
|
||||
"fred@1.3.2",
|
||||
"imf@1.0.0b0",
|
||||
"intrinio@1.3.2",
|
||||
"oecd@1.3.2",
|
||||
"polygon@1.3.2",
|
||||
@@ -7050,7 +7051,8 @@
|
||||
"optional": true,
|
||||
"choices": null
|
||||
}
|
||||
]
|
||||
],
|
||||
"imf": []
|
||||
},
|
||||
"returns": {
|
||||
"OBBject": [
|
||||
@@ -7061,7 +7063,7 @@
|
||||
},
|
||||
{
|
||||
"name": "provider",
|
||||
"type": "Optional[Literal['econdb']]",
|
||||
"type": "Optional[Literal['econdb', 'imf']]",
|
||||
"description": "Provider name."
|
||||
},
|
||||
{
|
||||
@@ -7197,6 +7199,32 @@
|
||||
"optional": true,
|
||||
"choices": null
|
||||
}
|
||||
],
|
||||
"imf": [
|
||||
{
|
||||
"name": "table",
|
||||
"type": "str",
|
||||
"description": "The name of the table associated with the symbol.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "level",
|
||||
"type": "int",
|
||||
"description": "The indentation level of the data, relative to the table and symbol_root",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "order",
|
||||
"type": "int",
|
||||
"description": "Order of the data, relative to the table.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"model": "AvailableIndicators"
|
||||
@@ -7207,24 +7235,237 @@
|
||||
"message": null
|
||||
},
|
||||
"description": "Get economic indicators by country and indicator.",
|
||||
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.indicators(provider='econdb', symbol='PCOCO')\n# Enter the country as the full name, or iso code. Use `available_indicators()` to get a list of supported indicators from EconDB.\nobb.economy.indicators(symbol='CPI', country='united_states,jp', provider='econdb')\n# Use the `main` symbol to get the group of main indicators for a country.\nobb.economy.indicators(provider='econdb', symbol='main', country='eu')\n```\n\n",
|
||||
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.indicators(provider='econdb', symbol=PCOCO)\n# Enter the country as the full name, or iso code. Use `available_indicators()` to get a list of supported indicators from EconDB.\nobb.economy.indicators(symbol=CPI, country='united_states,jp', provider='econdb')\n# Use the `main` symbol to get the group of main indicators for a country.\nobb.economy.indicators(provider='econdb', symbol=main, country='eu')\n# When the provider is 'imf', the absence of a symbol will default to 'irfcl_top_lines'. Use 'IRFCL' to get all the data from the set of indicators.\nobb.economy.indicators(provider='imf')\n# When the provider is 'imf', complete tables are returned by using a 'preset'. Refer to the function's docstring for descriptions of each preset. When no country is supplied, the data is returned for all countries.\nobb.economy.indicators(provider='imf', symbol=gold_reserves)\n# When the provider is 'imf', multiple countries and symbols can be supplied. Enter countries as a two-letter ISO country code, or the country name in lower_snake_case.\nobb.economy.indicators(provider='imf', symbol=RAFA_USD,RAPFA_USD,RAFA_RAPFA_RO, country='us,china,jp,4f,gb', start_date='2010-01-01', end_date='2020-12-31', frequency=annual)\n```\n\n",
|
||||
"parameters": {
|
||||
"standard": [
|
||||
{
|
||||
"name": "symbol",
|
||||
"type": "Union[str, List[str]]",
|
||||
"description": "Symbol to get data for. The base symbol for the indicator (e.g. GDP, CPI, etc.). Multiple items allowed for provider(s): econdb.",
|
||||
"default": "",
|
||||
"optional": false,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "country",
|
||||
"type": "Union[str, List[str]]",
|
||||
"description": "The country to get data. The country represented by the indicator, if available. Multiple items allowed for provider(s): econdb.",
|
||||
"description": "The country to get data. The country represented by the indicator, if available. Multiple items allowed for provider(s): econdb, imf.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
"choices": [
|
||||
"all",
|
||||
"afghanistan",
|
||||
"albania",
|
||||
"algeria",
|
||||
"american_samoa",
|
||||
"angola",
|
||||
"anguilla",
|
||||
"antigua_and_barbuda",
|
||||
"argentina",
|
||||
"armenia",
|
||||
"aruba",
|
||||
"australia",
|
||||
"austria",
|
||||
"azerbaijan",
|
||||
"bahamas",
|
||||
"bahrain",
|
||||
"bangladesh",
|
||||
"barbados",
|
||||
"belarus",
|
||||
"belgium",
|
||||
"belize",
|
||||
"benin",
|
||||
"bermuda",
|
||||
"bhutan",
|
||||
"bolivia",
|
||||
"bosnia_and_herzegovina",
|
||||
"botswana",
|
||||
"brazil",
|
||||
"brunei_darussalam",
|
||||
"bulgaria",
|
||||
"burkina_faso",
|
||||
"burundi",
|
||||
"cabo_verde",
|
||||
"cambodia",
|
||||
"cameroon",
|
||||
"canada",
|
||||
"cayman_islands",
|
||||
"central_african_republic",
|
||||
"chad",
|
||||
"chile",
|
||||
"hong_kong",
|
||||
"macao",
|
||||
"china",
|
||||
"colombia",
|
||||
"comoros",
|
||||
"congo",
|
||||
"cook_islands",
|
||||
"costa_rica",
|
||||
"cote_divoire",
|
||||
"croatia",
|
||||
"cuba",
|
||||
"curacao",
|
||||
"cyprus",
|
||||
"czech_republic",
|
||||
"denmark",
|
||||
"djibouti",
|
||||
"dominica",
|
||||
"dominican_republic",
|
||||
"ecuador",
|
||||
"egypt",
|
||||
"el_salvador",
|
||||
"equatorial_guinea",
|
||||
"eritrea",
|
||||
"estonia",
|
||||
"eswatini",
|
||||
"ethiopia",
|
||||
"ecb",
|
||||
"falkland_islands",
|
||||
"faroe_islands",
|
||||
"fiji",
|
||||
"finland",
|
||||
"france",
|
||||
"french_polynesia",
|
||||
"gabon",
|
||||
"gambia",
|
||||
"georgia",
|
||||
"germany",
|
||||
"ghana",
|
||||
"gibraltar",
|
||||
"greece",
|
||||
"greenland",
|
||||
"grenada",
|
||||
"guadeloupe",
|
||||
"guam",
|
||||
"guatemala",
|
||||
"french_guiana",
|
||||
"guinea",
|
||||
"guyana",
|
||||
"haiti",
|
||||
"honduras",
|
||||
"hungary",
|
||||
"iceland",
|
||||
"india",
|
||||
"indonesia",
|
||||
"iran",
|
||||
"iraq",
|
||||
"ireland",
|
||||
"israel",
|
||||
"italy",
|
||||
"jamaica",
|
||||
"japan",
|
||||
"jordan",
|
||||
"kazakhstan",
|
||||
"kenya",
|
||||
"kiribati",
|
||||
"korea",
|
||||
"kosovo",
|
||||
"kuwait",
|
||||
"kyrgyzstan",
|
||||
"lao_peoples_democratic_republic",
|
||||
"latvia",
|
||||
"lebanon",
|
||||
"lesotho",
|
||||
"liberia",
|
||||
"libya",
|
||||
"lithuania",
|
||||
"luxembourg",
|
||||
"madagascar",
|
||||
"malawi",
|
||||
"malaysia",
|
||||
"maldives",
|
||||
"mali",
|
||||
"malta",
|
||||
"marshall_islands",
|
||||
"martinique",
|
||||
"mauritania",
|
||||
"mauritius",
|
||||
"mexico",
|
||||
"micronesia",
|
||||
"moldova",
|
||||
"mongolia",
|
||||
"montenegro",
|
||||
"montserrat",
|
||||
"morocco",
|
||||
"mozambique",
|
||||
"myanmar",
|
||||
"namibia",
|
||||
"nauru",
|
||||
"nepal",
|
||||
"netherlands_antilles",
|
||||
"netherlands",
|
||||
"new_caledonia",
|
||||
"new_zealand",
|
||||
"nicaragua",
|
||||
"niger",
|
||||
"nigeria",
|
||||
"north_macedonia",
|
||||
"norway",
|
||||
"oman",
|
||||
"pakistan",
|
||||
"palau",
|
||||
"panama",
|
||||
"papua_new_guinea",
|
||||
"paraguay",
|
||||
"peru",
|
||||
"philippines",
|
||||
"poland",
|
||||
"portugal",
|
||||
"qatar",
|
||||
"reunion",
|
||||
"romania",
|
||||
"russian_federation",
|
||||
"rwanda",
|
||||
"saint_helena",
|
||||
"saint_pierre_and_miquelon",
|
||||
"samoa",
|
||||
"san_marino",
|
||||
"sao_tome_and_principe",
|
||||
"saudi_arabia",
|
||||
"senegal",
|
||||
"serbia_and_montenegro",
|
||||
"serbia",
|
||||
"seychelles",
|
||||
"sierra_leone",
|
||||
"singapore",
|
||||
"sint_maarten",
|
||||
"slovakia",
|
||||
"slovenia",
|
||||
"solomon_islands",
|
||||
"somalia",
|
||||
"south_africa",
|
||||
"south_sudan",
|
||||
"spain",
|
||||
"sri_lanka",
|
||||
"saint_kitts_and_nevis",
|
||||
"saint_lucia",
|
||||
"saint_vincent_and_the_grenadines",
|
||||
"sudan",
|
||||
"suriname",
|
||||
"sweden",
|
||||
"switzerland",
|
||||
"syrian_arab_republic",
|
||||
"taiwan",
|
||||
"tajikistan",
|
||||
"tanzania",
|
||||
"thailand",
|
||||
"timor",
|
||||
"timor-leste",
|
||||
"togo",
|
||||
"tonga",
|
||||
"trinidad_and_tobago",
|
||||
"tunisia",
|
||||
"turkey",
|
||||
"turkmenistan",
|
||||
"tuvalu",
|
||||
"uganda",
|
||||
"ukraine",
|
||||
"united_arab_emirates",
|
||||
"united_kingdom",
|
||||
"united_states",
|
||||
"uruguay",
|
||||
"uzbekistan",
|
||||
"vanuatu",
|
||||
"venezuela",
|
||||
"viet_nam",
|
||||
"palestine",
|
||||
"yemen",
|
||||
"zambia",
|
||||
"zimbabwe",
|
||||
"euro_area"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "start_date",
|
||||
@@ -7244,6 +7485,14 @@
|
||||
}
|
||||
],
|
||||
"econdb": [
|
||||
{
|
||||
"name": "symbol",
|
||||
"type": "Union[str, List[str]]",
|
||||
"description": "Symbol to get data for. The base symbol for the indicator (e.g. GDP, CPI, etc.). Use `available_indicators()` to get a list of available symbols. Multiple items allowed for provider(s): econdb.",
|
||||
"default": "",
|
||||
"optional": false,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "transform",
|
||||
"type": "Literal['toya', 'tpop', 'tusd', 'tpgp']",
|
||||
@@ -7268,6 +7517,28 @@
|
||||
"optional": true,
|
||||
"choices": null
|
||||
}
|
||||
],
|
||||
"imf": [
|
||||
{
|
||||
"name": "symbol",
|
||||
"type": "Union[str, List[str]]",
|
||||
"description": "Symbol to get data for. Use `available_indicators()` to get the list of available symbols. Use 'IRFCL' to get all the data from the set of indicators. Complete tables are available only by single country, and are keyed as described below. The default is 'irfcl_top_lines'. Available presets not listed in `available_indicators()` are:\n\n 'IRFCL': All the data from the set of indicators. Not compatible with multiple countries.\n 'irfcl_top_lines': The default, top line items from the IRFCL data. Compatible with multiple countries.\n 'reserve_assets_and_other_fx_assets': Table I of the IRFCL data. Not compatible with multiple countries.\n 'predetermined_drains_on_fx_assets': Table II of the IRFCL data. Not compatible with multiple countries.\n 'contingent_drains_fx_assets': Table III of the IRFCL data. Not compatible with multiple countries.\n 'memorandum_items': The memorandum items table of the IRFCL data. Not compatible with multiple countries.\n 'gold_reserves': Gold reserves as value in USD and Fine Troy Ounces. Compatible with multiple countries.\n 'derivative_assets': Net derivative assets as value in USD. Compatible with multipile countries. Multiple items allowed for provider(s): imf.",
|
||||
"default": "irfcl_top_lines",
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "frequency",
|
||||
"type": "Literal['annual', 'quarter', 'month']",
|
||||
"description": "Frequency of the data.",
|
||||
"default": "quarter",
|
||||
"optional": true,
|
||||
"choices": [
|
||||
"annual",
|
||||
"quarter",
|
||||
"month"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"returns": {
|
||||
@@ -7279,7 +7550,7 @@
|
||||
},
|
||||
{
|
||||
"name": "provider",
|
||||
"type": "Optional[Literal['econdb']]",
|
||||
"type": "Optional[Literal['econdb', 'imf']]",
|
||||
"description": "Provider name."
|
||||
},
|
||||
{
|
||||
@@ -7342,7 +7613,57 @@
|
||||
"choices": null
|
||||
}
|
||||
],
|
||||
"econdb": []
|
||||
"econdb": [],
|
||||
"imf": [
|
||||
{
|
||||
"name": "scale",
|
||||
"type": "str",
|
||||
"description": "The scale of the value.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "table",
|
||||
"type": "str",
|
||||
"description": "The name of the table associated with the symbol.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "level",
|
||||
"type": "int",
|
||||
"description": "The indentation level of the data, relative to the table and symbol_root",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "order",
|
||||
"type": "int",
|
||||
"description": "Order of the data, relative to the table.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "reference_sector",
|
||||
"type": "str",
|
||||
"description": "The reference sector for the data.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"type": "str",
|
||||
"description": "The title of the series associated with the symbol.",
|
||||
"default": null,
|
||||
"optional": true,
|
||||
"choices": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"model": "EconomicIndicators"
|
||||
},
|
||||
|
||||
@@ -39,6 +39,7 @@ Extensions:
|
||||
- federal_reserve@1.3.2
|
||||
- fmp@1.3.2
|
||||
- fred@1.3.2
|
||||
- imf@1.0.0b0
|
||||
- intrinio@1.3.2
|
||||
- oecd@1.3.2
|
||||
- polygon@1.3.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ from openbb_core.provider.standard_models.economic_indicators import (
|
||||
EconomicIndicatorsData,
|
||||
EconomicIndicatorsQueryParams,
|
||||
)
|
||||
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from pydantic import Field, field_validator
|
||||
|
||||
@@ -25,6 +26,12 @@ class EconDbEconomicIndicatorsQueryParams(EconomicIndicatorsQueryParams):
|
||||
"country": {"multiple_items_allowed": True},
|
||||
}
|
||||
|
||||
symbol: str = Field(
|
||||
description=QUERY_DESCRIPTIONS.get("symbol", "")
|
||||
+ " The base symbol for the indicator (e.g. GDP, CPI, etc.)."
|
||||
+ " Use `available_indicators()` to get a list of available symbols.",
|
||||
)
|
||||
|
||||
transform: Union[None, Literal["toya", "tpop", "tusd", "tpgp"]] = Field(
|
||||
default=None,
|
||||
description="The transformation to apply to the data, default is None."
|
||||
|
||||
31
openbb_platform/providers/imf/README.md
vendored
Normal file
31
openbb_platform/providers/imf/README.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# OpenBB IMF Provider Extension
|
||||
|
||||
This package adds the `openbb-imf` provider extension to the OpenBB Platform.
|
||||
|
||||
## Installation
|
||||
|
||||
Install from PyPI with:
|
||||
|
||||
```sh
|
||||
pip install openbb-imf
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
The extension utilizes the JSON RESTful Web Service ((https://datahelp.imf.org/knowledgebase/articles/630877-data-services)[https://datahelp.imf.org/knowledgebase/articles/630877-data-services])
|
||||
|
||||
No authorization is required to use, but IP addresses are bound by the limitations described in the link above.
|
||||
|
||||
## Coverage
|
||||
|
||||
- Databases:
|
||||
- International Reserves and Foreign Currency Liquidity
|
||||
|
||||
Coverage:
|
||||
- All IRFCL tables.
|
||||
- Individual, or multiple, time series from single or multiple countries.
|
||||
|
||||
### Endpoints
|
||||
|
||||
- `obb.economy.available_indicators`
|
||||
- `obb.economy.indicators`
|
||||
17
openbb_platform/providers/imf/openbb_imf/__init__.py
Normal file
17
openbb_platform/providers/imf/openbb_imf/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""OpenBB IMF Provider Module."""
|
||||
|
||||
from openbb_core.provider.abstract.provider import Provider
|
||||
|
||||
from openbb_imf.models.available_indicators import ImfAvailableIndicatorsFetcher
|
||||
from openbb_imf.models.economic_indicators import ImfEconomicIndicatorsFetcher
|
||||
|
||||
imf_provider = Provider(
|
||||
name="imf",
|
||||
website="https://datahelp.imf.org/knowledgebase/articles/667681-using-json-restful-web-service",
|
||||
description="This provider allows you to access International Monetary Fund data through the IMF Public Data API.",
|
||||
fetcher_dict={
|
||||
"AvailableIndicators": ImfAvailableIndicatorsFetcher,
|
||||
"EconomicIndicators": ImfEconomicIndicatorsFetcher,
|
||||
},
|
||||
repr_name="International Monetary Fund (IMF) Public Data API",
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
"""IMF Static Assets."""
|
||||
252
openbb_platform/providers/imf/openbb_imf/assets/imf_country_map.json
vendored
Normal file
252
openbb_platform/providers/imf/openbb_imf/assets/imf_country_map.json
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
{
|
||||
"AF": "Afghanistan",
|
||||
"AL": "Albania",
|
||||
"DZ": "Algeria",
|
||||
"AS": "American Samoa",
|
||||
"AO": "Angola",
|
||||
"AI": "Anguilla",
|
||||
"AG": "Antigua and Barbuda",
|
||||
"5M": "AMF (Arab Monetary Fund)",
|
||||
"AR": "Argentina",
|
||||
"AM": "Armenia",
|
||||
"AW": "Aruba",
|
||||
"AU": "Australia",
|
||||
"AT": "Austria",
|
||||
"AZ": "Azerbaijan",
|
||||
"BS": "Bahamas",
|
||||
"BH": "Bahrain",
|
||||
"BD": "Bangladesh",
|
||||
"5W": "BEAC (Banque des Etats de l`Afrique Centrale)",
|
||||
"5B": "BIS (Bank for International Settlements)",
|
||||
"BB": "Barbados",
|
||||
"BY": "Belarus",
|
||||
"BE": "Belgium",
|
||||
"R1": "Belgo-Luxembourg Economic Union",
|
||||
"BZ": "Belize",
|
||||
"BJ": "Benin",
|
||||
"BM": "Bermuda",
|
||||
"BT": "Bhutan",
|
||||
"BO": "Bolivia",
|
||||
"BA": "Bosnia and Herzegovina",
|
||||
"BW": "Botswana",
|
||||
"BR": "Brazil",
|
||||
"BN": "Brunei Darussalam",
|
||||
"BG": "Bulgaria",
|
||||
"BF": "Burkina Faso",
|
||||
"BI": "Burundi",
|
||||
"CV": "Cabo Verde",
|
||||
"KH": "Cambodia",
|
||||
"CM": "Cameroon",
|
||||
"CA": "Canada",
|
||||
"KY": "Cayman Islands",
|
||||
"CF": "Central African Republic",
|
||||
"1C_752": "Central Bank West Africa",
|
||||
"TD": "Chad",
|
||||
"CL": "Chile",
|
||||
"HK": "Hong Kong, China",
|
||||
"MO": "Macao",
|
||||
"CN": "China",
|
||||
"CO": "Colombia",
|
||||
"KM": "Comoros",
|
||||
"CD": "Congo, the Democratic Republic of the",
|
||||
"CG": "Congo",
|
||||
"CK": "Cook Islands",
|
||||
"CR": "Costa Rica",
|
||||
"CI": "Cote d`Ivoire",
|
||||
"HR": "Croatia",
|
||||
"CU": "Cuba",
|
||||
"1C_355": "Curacao & St. Maarten",
|
||||
"CW": "Curacao",
|
||||
"CY": "Cyprus",
|
||||
"CZ": "Czech Republic",
|
||||
"CSH": "Former Czechoslovakia",
|
||||
"DK": "Denmark",
|
||||
"DJ": "Djibouti",
|
||||
"DM": "Dominica",
|
||||
"DO": "Dominican Republic",
|
||||
"5I": "ECCB (Eastern Caribbean Central Bank)",
|
||||
"EC": "Ecuador",
|
||||
"EG": "Egypt",
|
||||
"SV": "El Salvador",
|
||||
"GQ": "Equatorial Guinea",
|
||||
"ER": "Eritrea",
|
||||
"EE": "Estonia",
|
||||
"SZ": "Eswatini",
|
||||
"ET": "Ethiopia",
|
||||
"4F": "ECB (European Central Bank)",
|
||||
"1C_977": "European Monetary Institution",
|
||||
"FK": "Falkland Islands (Malvinas)",
|
||||
"FO": "Faroe Islands",
|
||||
"FJ": "Fiji",
|
||||
"FI": "Finland",
|
||||
"FR": "France",
|
||||
"PF": "French Polynesia",
|
||||
"GA": "Gabon",
|
||||
"GM": "Gambia",
|
||||
"GE": "Georgia",
|
||||
"DE": "Germany",
|
||||
"GH": "Ghana",
|
||||
"GI": "Gibraltar",
|
||||
"GR": "Greece",
|
||||
"GL": "Greenland",
|
||||
"GD": "Grenada",
|
||||
"GP": "Guadeloupe",
|
||||
"GU": "Guam",
|
||||
"GT": "Guatemala",
|
||||
"GF": "French Guiana",
|
||||
"GN": "Guinea",
|
||||
"GW": "Guinea-Bissau",
|
||||
"GY": "Guyana",
|
||||
"HT": "Haiti",
|
||||
"HN": "Honduras",
|
||||
"HU": "Hungary",
|
||||
"IS": "Iceland",
|
||||
"IN": "India",
|
||||
"ID": "Indonesia",
|
||||
"1E": "IBRD (International Bank for Reconstruction and Development)",
|
||||
"X0": "IMF Member Countries (IMF)",
|
||||
"IR": "Iran, Islamic Republic of",
|
||||
"IQ": "Iraq",
|
||||
"IE": "Ireland",
|
||||
"7B": "IDB (Islamic Development Bank)",
|
||||
"IL": "Israel",
|
||||
"IT": "Italy",
|
||||
"JM": "Jamaica",
|
||||
"JP": "Japan",
|
||||
"JO": "Jordan",
|
||||
"KZ": "Kazakhstan",
|
||||
"KE": "Kenya",
|
||||
"KI": "Kiribati",
|
||||
"KR": "Korea, Republic of",
|
||||
"XK": "Kosovo, Republic of",
|
||||
"KW": "Kuwait",
|
||||
"KG": "Kyrgyzstan",
|
||||
"LA": "Lao People`s Democratic Republic",
|
||||
"LV": "Latvia",
|
||||
"LB": "Lebanon",
|
||||
"LS": "Lesotho",
|
||||
"LR": "Liberia",
|
||||
"LY": "Libya",
|
||||
"LT": "Lithuania",
|
||||
"LU": "Luxembourg",
|
||||
"MG": "Madagascar",
|
||||
"MW": "Malawi",
|
||||
"MY": "Malaysia",
|
||||
"MV": "Maldives",
|
||||
"ML": "Mali",
|
||||
"MT": "Malta",
|
||||
"MH": "Marshall islands",
|
||||
"MQ": "Martinique",
|
||||
"MR": "Mauritania",
|
||||
"MU": "Mauritius",
|
||||
"MX": "Mexico",
|
||||
"FM": "Micronesia, Federated States of",
|
||||
"MD": "Moldova, Republic of",
|
||||
"MN": "Mongolia",
|
||||
"ME": "Montenegro",
|
||||
"MS": "Montserrat",
|
||||
"MA": "Morocco",
|
||||
"MZ": "Mozambique",
|
||||
"MM": "Myanmar",
|
||||
"NA": "Namibia",
|
||||
"NR": "Nauru",
|
||||
"NP": "Nepal",
|
||||
"AN": "Netherlands Antilles",
|
||||
"NL": "Netherlands",
|
||||
"NC": "New Caledonia",
|
||||
"NZ": "New Zealand",
|
||||
"NI": "Nicaragua",
|
||||
"NE": "Niger",
|
||||
"NG": "Nigeria",
|
||||
"5H": "NIB (Nordic Investment Bank)",
|
||||
"MK": "North Macedonia, Republic of",
|
||||
"NO": "Norway",
|
||||
"OM": "Oman",
|
||||
"PK": "Pakistan",
|
||||
"PW": "Palau",
|
||||
"PA": "Panama",
|
||||
"1C_356": "Panama Canal Zone",
|
||||
"PG": "Papua New Guinea",
|
||||
"PY": "Paraguay",
|
||||
"PE": "Peru",
|
||||
"PH": "Philippines",
|
||||
"PL": "Poland",
|
||||
"PT": "Portugal",
|
||||
"QA": "Qatar",
|
||||
"RE": "Reunion",
|
||||
"RO": "Romania",
|
||||
"RU": "Russian Federation",
|
||||
"RW": "Rwanda",
|
||||
"1C_568": "Ryukyus",
|
||||
"SH": "Saint Helena",
|
||||
"PM": "Saint Pierre and Miquelon",
|
||||
"WS": "Samoa",
|
||||
"SM": "San Marino",
|
||||
"ST": "Sao Tome and Principe",
|
||||
"SA": "Saudi Arabia",
|
||||
"SN": "Senegal",
|
||||
"CS": "Serbia and Montenegro",
|
||||
"RS": "Serbia",
|
||||
"SC": "Seychelles",
|
||||
"SL": "Sierra Leone",
|
||||
"SG": "Singapore",
|
||||
"SX": "Sint Maarten (Dutch part)",
|
||||
"SK": "Slovakia",
|
||||
"SI": "Slovenia",
|
||||
"SB": "Solomon Islands",
|
||||
"SO": "Somalia",
|
||||
"ZA": "South Africa",
|
||||
"SS": "South Sudan",
|
||||
"ES": "Spain",
|
||||
"LK": "Sri Lanka",
|
||||
"KN": "Saint Kitts and Nevis",
|
||||
"LC": "Saint Lucia",
|
||||
"VC": "Saint Vincent and the Grenadines",
|
||||
"SD": "Sudan",
|
||||
"SR": "Suriname",
|
||||
"SE": "Sweden",
|
||||
"CH": "Switzerland",
|
||||
"SY": "Syrian Arab Republic",
|
||||
"TW": "Taiwan, Province of China",
|
||||
"TJ": "Tajikistan",
|
||||
"TZ": "Tanzania, United Republic of",
|
||||
"TH": "Thailand",
|
||||
"TP": "Timor",
|
||||
"TL": "Timor-Leste",
|
||||
"TG": "Togo",
|
||||
"TO": "Tonga",
|
||||
"TT": "Trinidad and Tobago",
|
||||
"TN": "Tunisia",
|
||||
"TR": "Turkey",
|
||||
"TM": "Turkmenistan",
|
||||
"TV": "Tuvalu",
|
||||
"UG": "Uganda",
|
||||
"UA": "Ukraine",
|
||||
"AE": "United Arab Emirates",
|
||||
"GB": "United Kingdom",
|
||||
"US": "United States",
|
||||
"UY": "Uruguay",
|
||||
"UZ": "Uzbekistan",
|
||||
"VU": "Vanuatu",
|
||||
"VE": "Venezuela, Bolivarian Republic",
|
||||
"VN": "Viet Nam",
|
||||
"PS": "Palestine, State of",
|
||||
"1C_473": "Yemen Arab Rep.",
|
||||
"1C_459": "Yemen, P.D. Rep.",
|
||||
"YE": "Yemen",
|
||||
"YUC": "Former Yugoslavia",
|
||||
"ZM": "Zambia",
|
||||
"ZW": "Zimbabwe",
|
||||
"1C_ALLC": "All Countries",
|
||||
"1C_ALL": "All Countries and Country Groups",
|
||||
"1C_ALLG": "All Country Groups",
|
||||
"1C_All_Reporting_Countries_Data": "All Reporting Countries, Data",
|
||||
"1C_All_Reporting_Countries_Metadata": "All Reporting Countries, Metadata",
|
||||
"1C_Daily_Reporters": "Daily Reporters",
|
||||
"1C_Dual_Reporters": "Dual Reporters",
|
||||
"U2": "Euro area (Member States and Institutions of the Euro Area) changing composition",
|
||||
"B00": "EU (Member States of the European Union) changing composition, excluding EU Institutions",
|
||||
"1C_Monthly_Reporters": "Monthly Reporters",
|
||||
"1C_Single_Reporters": "Single Reporters",
|
||||
"1C_Single_Reporters_USA_and_Peru": "Single Reporters - USA and Peru"
|
||||
}
|
||||
2058
openbb_platform/providers/imf/openbb_imf/assets/imf_symbols.json
vendored
Normal file
2058
openbb_platform/providers/imf/openbb_imf/assets/imf_symbols.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
"""OpenBB IMF Provider Models."""
|
||||
@@ -0,0 +1,81 @@
|
||||
"""IMF Available Indicators."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.standard_models.available_indicators import (
|
||||
AvailableIndicatorsData,
|
||||
AvailableIndicesQueryParams,
|
||||
)
|
||||
from pydantic import Field
|
||||
|
||||
|
||||
class ImfAvailableIndicatorsQueryParams(AvailableIndicesQueryParams):
|
||||
"""IMF Available Indicators Query Parameters."""
|
||||
|
||||
|
||||
class ImfAvailableIndicatorsData(AvailableIndicatorsData):
|
||||
"""IMF Available Indicators Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"symbol_root": "parent",
|
||||
"description": "title",
|
||||
}
|
||||
|
||||
table: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The name of the table associated with the symbol.",
|
||||
)
|
||||
level: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The indentation level of the data, relative to the table and symbol_root",
|
||||
)
|
||||
order: Optional[int] = Field(
|
||||
default=None,
|
||||
description="Order of the data, relative to the table.",
|
||||
)
|
||||
|
||||
|
||||
class ImfAvailableIndicatorsFetcher(
|
||||
Fetcher[ImfAvailableIndicatorsQueryParams, List[ImfAvailableIndicatorsData]]
|
||||
):
|
||||
"""IMF Available Indicators Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: Dict[str, Any]) -> ImfAvailableIndicatorsQueryParams:
|
||||
"""Transform the query."""
|
||||
return ImfAvailableIndicatorsQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
def extract_data(
|
||||
query: ImfAvailableIndicatorsQueryParams,
|
||||
credentials: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
"""Fetch the data."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_imf.utils.irfcl_helpers import load_irfcl_symbols
|
||||
|
||||
try:
|
||||
irfcl_symbols = load_irfcl_symbols()
|
||||
except OpenBBError as e:
|
||||
raise OpenBBError(f"Failed to load IMF IRFCL symbols: {e}") from e
|
||||
|
||||
records: List = []
|
||||
for key, value in irfcl_symbols.items():
|
||||
value["symbol"] = key
|
||||
records.append(value)
|
||||
|
||||
return records
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: ImfAvailableIndicatorsQueryParams,
|
||||
data: List[Dict],
|
||||
**kwargs: Any,
|
||||
) -> List[ImfAvailableIndicatorsData]:
|
||||
"""Transform the data."""
|
||||
return [ImfAvailableIndicatorsData.model_validate(d) for d in data]
|
||||
@@ -0,0 +1,197 @@
|
||||
"""IMF Economic Indicators Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.standard_models.economic_indicators import (
|
||||
EconomicIndicatorsData,
|
||||
EconomicIndicatorsQueryParams,
|
||||
)
|
||||
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from pydantic import Field
|
||||
|
||||
from openbb_imf.utils.constants import IRFCL_PRESET, IRFCL_TABLES
|
||||
from openbb_imf.utils.irfcl_helpers import (
|
||||
load_country_to_code_map,
|
||||
load_irfcl_symbols,
|
||||
validate_countries,
|
||||
)
|
||||
|
||||
|
||||
class ImfEconomicIndicatorsQueryParams(EconomicIndicatorsQueryParams):
|
||||
"""IMF Economic Indicators Query."""
|
||||
|
||||
__json_schema_extra__ = {
|
||||
"symbol": {
|
||||
"multiple_items_allowed": True,
|
||||
},
|
||||
"country": {
|
||||
"multiple_items_allowed": True,
|
||||
"choices": ["all"] + list(list(load_country_to_code_map())),
|
||||
},
|
||||
"frequency": {
|
||||
"choices": ["annual", "quarter", "month"],
|
||||
},
|
||||
}
|
||||
symbol: str = Field(
|
||||
default="irfcl_top_lines",
|
||||
description=QUERY_DESCRIPTIONS.get("symbol", "")
|
||||
+ " Use `available_indicators()` to get the list of available symbols."
|
||||
+ " Use 'IRFCL' to get all the data from the set of indicators."
|
||||
+ " Complete tables are available only by single country, and are keyed as described below."
|
||||
+ " The default is 'irfcl_top_lines'. Available presets not listed in `available_indicators()` are:"
|
||||
+ """\n
|
||||
'IRFCL': All the data from the set of indicators. Not compatible with multiple countries.
|
||||
'irfcl_top_lines': The default, top line items from the IRFCL data. Compatible with multiple countries.
|
||||
'reserve_assets_and_other_fx_assets': Table I of the IRFCL data. Not compatible with multiple countries.
|
||||
'predetermined_drains_on_fx_assets': Table II of the IRFCL data. Not compatible with multiple countries.
|
||||
'contingent_drains_fx_assets': Table III of the IRFCL data. Not compatible with multiple countries.
|
||||
'memorandum_items': The memorandum items table of the IRFCL data. Not compatible with multiple countries.
|
||||
'gold_reserves': Gold reserves as value in USD and Fine Troy Ounces. Compatible with multiple countries.
|
||||
'derivative_assets': Net derivative assets as value in USD. Compatible with multipile countries.
|
||||
""",
|
||||
)
|
||||
frequency: Literal["annual", "quarter", "month"] = Field(
|
||||
default="quarter",
|
||||
description="Frequency of the data.",
|
||||
)
|
||||
|
||||
|
||||
class ImfEconomicIndicatorsData(EconomicIndicatorsData):
|
||||
"""IMF Economic Indicators Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"symbol_root": "parent",
|
||||
}
|
||||
|
||||
scale: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The scale of the value.",
|
||||
)
|
||||
table: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The name of the table associated with the symbol.",
|
||||
)
|
||||
level: Optional[int] = Field(
|
||||
default=None,
|
||||
description="The indentation level of the data, relative to the table and symbol_root",
|
||||
)
|
||||
order: Optional[int] = Field(
|
||||
default=None,
|
||||
description="Order of the data, relative to the table.",
|
||||
)
|
||||
reference_sector: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The reference sector for the data.",
|
||||
)
|
||||
title: Optional[str] = Field(
|
||||
default=None,
|
||||
description="The title of the series associated with the symbol.",
|
||||
)
|
||||
|
||||
|
||||
class ImfEconomicIndicatorsFetcher(
|
||||
Fetcher[ImfEconomicIndicatorsQueryParams, List[ImfEconomicIndicatorsData]]
|
||||
):
|
||||
"""IMF Economic Indicators Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: Dict[str, Any]) -> ImfEconomicIndicatorsQueryParams:
|
||||
"""Transform the query."""
|
||||
symbols = params.get("symbol", "")
|
||||
countries = params.get("country")
|
||||
now = datetime.now().date()
|
||||
symbols = "IRFCL" if ("all" in symbols or "IRFCL" in symbols) else symbols
|
||||
if symbols == "IRFCL" and not (countries or countries == "all"):
|
||||
raise OpenBBError(
|
||||
f"The selected symbol(s), {params.get('symbol')}, requires a single country for the 'country' parameter."
|
||||
)
|
||||
|
||||
if countries:
|
||||
params["country"] = validate_countries(countries)
|
||||
|
||||
if symbols and symbols in IRFCL_PRESET:
|
||||
params["symbol"] = IRFCL_PRESET[symbols]
|
||||
if symbols in IRFCL_TABLES and countries and countries.split(",") > 1:
|
||||
raise OpenBBError(
|
||||
f"Symbol '{symbols}' is a table and can only be used with one country."
|
||||
)
|
||||
elif symbols:
|
||||
params["symbol"] = symbols
|
||||
|
||||
if not params.get("start_date") and (not countries or countries == "all"):
|
||||
params["start_date"] = now.replace(
|
||||
year=now.year - 1, month=1, day=1
|
||||
).strftime("%Y-%m-%d")
|
||||
|
||||
if not params.get("end_date"):
|
||||
params["end_date"] = now.replace(month=12, day=31).strftime("%Y-%m-%d")
|
||||
|
||||
if (not symbols or symbols == "all") and not params.get("start_date"):
|
||||
params["start_date"] = now.replace(year=now.year - 1).strftime("%Y-%m-%d")
|
||||
|
||||
return ImfEconomicIndicatorsQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: ImfEconomicIndicatorsQueryParams,
|
||||
credentials: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
"""Extract the data."""
|
||||
# pylint: disable = import-outside-toplevel
|
||||
from openbb_imf.utils.irfcl_helpers import _get_irfcl_data
|
||||
|
||||
try:
|
||||
res = await _get_irfcl_data(**query.model_dump(exclude_none=True))
|
||||
except OpenBBError as e:
|
||||
raise e from e
|
||||
if not res:
|
||||
raise EmptyDataError("No results returned for the query.")
|
||||
return res
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: ImfEconomicIndicatorsQueryParams,
|
||||
data: List[Dict],
|
||||
**kwargs: Any,
|
||||
) -> List[ImfEconomicIndicatorsData]:
|
||||
"""Transform the data."""
|
||||
# pylint: disable = import-outside-toplevel
|
||||
from pandas import Categorical, DataFrame
|
||||
|
||||
if not data:
|
||||
raise EmptyDataError("The data is empty.")
|
||||
|
||||
all_symbols = load_irfcl_symbols()
|
||||
df = DataFrame(data)
|
||||
|
||||
if df.empty:
|
||||
raise EmptyDataError("The data is empty.")
|
||||
|
||||
df = df[df["symbol"].isin(all_symbols)]
|
||||
|
||||
if len(df) == 0:
|
||||
raise OpenBBError("The data has a length of 0.")
|
||||
|
||||
df["symbol"] = Categorical(
|
||||
df["symbol"],
|
||||
categories=all_symbols,
|
||||
ordered=True,
|
||||
)
|
||||
df["parent"] = Categorical(
|
||||
df["parent"],
|
||||
categories=all_symbols,
|
||||
ordered=True,
|
||||
)
|
||||
df = df.sort_values(
|
||||
by=["date", "symbol", "parent", "value"],
|
||||
ascending=[True, True, True, False],
|
||||
).reset_index(drop=True)
|
||||
|
||||
return [ImfEconomicIndicatorsData(**d) for d in df.to_dict(orient="records")]
|
||||
@@ -0,0 +1 @@
|
||||
"""IMF Utilities."""
|
||||
93
openbb_platform/providers/imf/openbb_imf/utils/constants.py
Normal file
93
openbb_platform/providers/imf/openbb_imf/utils/constants.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""IMF Constants."""
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
# flake8: noqa: E501
|
||||
|
||||
IRFCL_HEADLINE = "RAF_USD,RAFA_USD,RAFAFX_USD,RAOFA_USD,RAPFA_USD,RAFAIMF_USD,RAFASDR_USD,RAFAGOLD_USD,RACFA_USD,RAMDCD_USD,RAMFIFC_USD,RAMSR_USD"
|
||||
|
||||
RESERVE_ASSETS_AND_OTHER_FX_ASSETS = "RAF_USD,RAFA_USD,RAFAFX_USD,RAFAFXS_USD,RAFAFXSI_USD,RAFAFXCD_USD,RAFAFXCDN_USD,RAFAFXCDBI_USD,RAFAFXCDBIA_USD,RAFAFXCDBO_USD,RAFAFXCDBOA_USD,RAFAIMF_USD,RAFASDR_USD,RAFAGOLD_USD,RAFAGOLDV_OZT,RAFAO_USD,RAFAOF_USD,RAFAOL_USD,RAFAOO_USD,RAOFA_USD,RAOFAS_USD,RAOFAD_USD,RAOFAL_USD,RAOFAF_USD,RAOFAG_USD"
|
||||
|
||||
PREDETERMINED_DRAINS_ON_FX_ASSETS = "RAPFA_USD,RAPFALSD_USD,RAPFALSD_1M_USD,RAPFALSD_1M_3M_USD,RAPFALSD_3M_1Y_USD,RAPFALSDOP_USD,RAPFALSDOP_1M_USD,RAPFALSDOP_1M_3M_USD,RAPFALSDOP_3M_1Y_USD,RAPFALSDOI_USD,RAPFALSDOI_1M_USD,RAPFALSDOI_1M_3M_USD,RAPFALSDOI_3M_1Y_USD,RAPFALSDIP_USD,RAPFALSDIP_1M_USD,RAPFALSDIP_1M_3M_USD,RAPFALSDIP_3M_1Y_USD,RAPFALSDII_USD,RAPFALSDII_1M_USD,RAPFALSDII_1M_3M_USD,RAPFALSDII_3M_1Y_USD,RAPFAFFS_USD,RAPFAFFS_1M_USD,RAPFAFFS_1M_3M_USD,RAPFAFFS_3M_1Y_USD,RAPFAFFL_USD,RAPFAFFL_1M_USD,RAPFAFFL_1M_3M_USD,RAPFAFFL_3M_1Y_USD,RAPFAO_USD,RAPFAO_1M_USD,RAPFAO_1M_3M_USD,RAPFAO_3M_1Y_USD,RAPFAOOR_USD,RAPFAOOR_1M_USD,RAPFAOOR_1M_3M_USD,RAPFAOOR_3M_1Y_USD,RAPFAOIRR_USD,RAPFAOIRR_1M_USD,RAPFAOIRR_1M_3M_USD,RAPFAOIRR_3M_1Y_USD,RAPFAOOC_USD,RAPFAOOC_1M_USD,RAPFAOOC_1M_3M_USD,RAPFAOOC_3M_1Y_USD,RAPFAOIC_USD,RAPFAOIC_1M_USD,RAPFAOIC_1M_3M_USD,RAPFAOIC_3M_1Y_USD,RAPFAOOP_USD,RAPFAOOP_1M_USD,RAPFAOOP_1M_3M_USD,RAPFAOOP_3M_1Y_USD,RAPFAOIR_USD,RAPFAOIR_1M_USD,RAPFAOIR_1M_3M_USD,RAPFAOIR_3M_1Y_USD,RAFA_RAPFA_RO"
|
||||
|
||||
CONTINGENT_DRAINS_FX_ASSETS = "RACFA_USD,RACFAL_USD,RACFAL_1M_USD,RACFAL_1M_3M_USD,RACFAL_3M_1Y_USD,RACFALG_USD,RACFALG_1M_USD,RACFALG_1M_3M_USD,RACFALO_USD,RACFALO_1M_USD,RACFALO_1M_3M_USD,RACFALO_3M_1Y_USD,RACFAS_USD,RACFACB_USD,RACFACB_1M_USD,RACFACB_1M_3M_USD,RACFACB_3M_1Y_USD,RACFACBA_USD,RACFACBA_1M_USD,RACFACBA_1M_3M_USD,RACFACBA_3M_1Y_USD,RACFACBAOI_USD,RACFACBAOI_1M_USD,RACFACBAOI_1M_3M_USD,RACFACBAON_USD,RACFACBAON_1M_USD,RACFACBAON_1M_3M_USD,RACFACBAON_3M_1Y_USD,RACFACBABIS_USD,RACFACBAIMF_1M_USD,RACFACBAIMF_1M_3M_USD,RACFACBAIMF_3M_1Y_USD,RACFACBAIMF_USD,RACFACBFIR_USD,RACFACBFIR_1M_USD,RACFACBFIR_1M_3M_USD,RACFACBFIR_3M_1Y_USD,RACFACBFIO_USD,RACFACBFIO_1M_USD,RACFACBFIO_1M_3M_USD,RACFACBFIO_3M_1Y_USD,RACFACT_USD,RACFACT_1M_USD,RACFACT_1M_3M_USD,RACFACT_3M_1Y_USD,RACFACTA_USD,RACFACTA_1M_USD,RACFACTA_1M_3M_USD,RACFACTA_3M_1Y_USD,RACFACTAOI_USD,RACFACTAOI_1M_USD,RACFACTAOI_1M_3M_USD,RACFACTAOI_3M_1Y_USD,RACFACTAON_USD,RACFACTAON_1M_USD,RACFACTAON_1M_3M_USD,RACFACTAON_3M_1Y_USD,RACFACTABIS_USD,RACFACTABIS_1M_USD,RACFACTABIS_1M_3M_USD,RACFACTABIS_3M_1Y_USD,RACFACTAIMF_USD,RACFACTAIMF_1M_USD,RACFACTFIR_USD,RACFACTFIR_1M_USD,RACFACTFIR_1M_3M_USD,RACFACTFIR_3M_1Y_USD,RACFACTFIO_USD,RACFACTFIO_1M_USD,RACFACTFIO_1M_3M_USD,RACFACTFIO_3M_1Y_USD,RACFAPPS_USD,RACFAPPS_1M_USD,RACFAPPS_1M_3M_USD,RACFAPPS_3M_1Y_USD,RACFAPPSBP_USD,RACFAPPSBP_1M_USD,RACFAPPSBP_1M_3M_USD,RACFAPPSBP_3M_1Y_USD,RACFAPPSWC_USD,RACFAPPSWC_1M_USD,RACFAPPSWC_1M_3M_USD,RACFAPPSWC_3M_1Y_USD,RACFAPPL_USD,RACFAPPL_1M_USD,RACFAPPL_1M_3M_USD,RACFAPPL_3M_1Y_USD,RACFAPPLBC_USD,RACFAPPLBC_1M_USD,RACFAPPLBC_1M_3M_USD,RACFAPPLBC_3M_1Y_USD,RACFAPPLWP_USD,RACFAPPLWP_1M_USD,RACFAPPLWP_1M_3M_USD,RACFAPPLWP_3M_1Y_USD,RACFAMPAS_USD,RACFAMPAS_1M_USD,RACFAMPAS_1M_3M_USD,RACFAMPAS_3M_1Y_USD,RACFAMPAL_USD,RACFAMPAL_1M_USD,RACFAMPAL_1M_3M_USD,RACFAMPAL_3M_1Y_USD,RACFAMPBS_USD,RACFAMPBS_1M_USD,RACFAMPBS_1M_3M_USD,RACFAMPBS_3M_1Y_USD,RACFAMPBL_USD,RACFAMPBL_1M_USD,RACFAMPBL_1M_3M_USD,RACFAMPBL_3M_1Y_USD,RACFAMPCS_USD,RACFAMPCS_1M_USD,RACFAMPCS_1M_3M_USD,RACFAMPCS_3M_1Y_USD,RACFAMPCL_USD,RACFAMPCL_1M_USD,RACFAMPCL_1M_3M_USD,RACFAMPCL_3M_1Y_USD,RACFAMPDS_USD,RACFAMPDS_1M_USD,RACFAMPDS_1M_3M_USD,RACFAMPDS_3M_1Y_USD,RACFAMPDL_USD,RACFAMPDL_1M_USD,RACFAMPDL_1M_3M_USD,RACFAMPDL_3M_1Y_USD,RACFAMPES_USD,RACFAMPES_1M_USD,RACFAMPES_1M_3M_USD,RACFAMPES_3M_1Y_USD,RACFAMPEL_USD,RACFAMPEL_1M_USD,RACFAMPEL_1M_3M_USD,RACFAMPEL_3M_1Y_USD,RACFAMPFS_USD,RACFAMPFS_1M_USD,RACFAMPFS_1M_3M_USD,RACFAMPFS_3M_1Y_USD,RACFAMPFL_USD,RACFAMPFL_1M_USD,RACFAMPFL_1M_3M_USD,RACFAMPFL_3M_1Y_USD"
|
||||
|
||||
IRFCL_MEMORANDUM_ITEMS = "RAMDCD_USD,RAMFIFC_USD,RAMPA_USD,RAMFFS_USD,RAMPAOA_USD,RAMSR_USD,RAMSRLRI_USD,RAMSRLRN_USD,RAMSRBRI_USD,RAMSRBAN_USD,RAMFDA_USD,RAMFDAF_USD,RAMFDAU_USD,RAMFDAW_USD,RAMFDAP_USD,RAMFDAO_USD,RAMFFL_USD,RAMPPS_USD,RAMPPSBP_USD,RAMPPSWC_USD,RAMPPL_USD,RAMPPLBP_USD,RAMPPLWC_USD,RAMCR_USD,RAMCRISDR_USD,RAMCRIC_USD_USD,RAMCRIC_EUR_USD,RAMCRIC_CNY_USD,RAMCRIC_JPY_USD,RAMCRIC_GBP_USD,RAMCROSDR_USD"
|
||||
|
||||
IRFCL_TABLES = {
|
||||
"reserve_assets_and_other_fx_assets": RESERVE_ASSETS_AND_OTHER_FX_ASSETS,
|
||||
"predetermined_drains_on_fx_assets": PREDETERMINED_DRAINS_ON_FX_ASSETS,
|
||||
"contingent_drains_fx_assets": CONTINGENT_DRAINS_FX_ASSETS,
|
||||
"memorandum_items": IRFCL_MEMORANDUM_ITEMS,
|
||||
}
|
||||
|
||||
IRFCL_PRESET = {
|
||||
"irfcl_top_lines": IRFCL_HEADLINE,
|
||||
**IRFCL_TABLES,
|
||||
"gold_reserves": "RAFAGOLD_USD,RAFAGOLDV_OZT",
|
||||
"derivative_assets": "RAMFDA_USD",
|
||||
}
|
||||
|
||||
FREQUENCY_DICT = {
|
||||
"month": "M",
|
||||
"quarter": "Q",
|
||||
"annual": "A",
|
||||
}
|
||||
REF_SECTORS_DICT = {
|
||||
"government_ex_social_security": "S1311",
|
||||
"central_bank": "S121",
|
||||
"monetary_authorities": "S1X",
|
||||
"all_sectors": "",
|
||||
}
|
||||
|
||||
SECTOR_MAP = {v: k for k, v in REF_SECTORS_DICT.items()}
|
||||
|
||||
UNIT_MULTIPLIERS_MAP = {
|
||||
"0": "Units",
|
||||
"2": "Hundreds",
|
||||
"3": "Thousands",
|
||||
"6": "Millions",
|
||||
"9": "Billions",
|
||||
"12": "Trillions",
|
||||
"N15": "Quadrillionths",
|
||||
"N14": "Hundred Trillionths",
|
||||
"N13": "Ten Trillionths",
|
||||
"N12": "Trillionths",
|
||||
"N11": "Hundred Billionths",
|
||||
"N10": "Ten Billionths",
|
||||
"N9": "Billionths",
|
||||
"N8": "Hundred Millionths",
|
||||
"N7": "Ten Millionths",
|
||||
"N6": "Millionths",
|
||||
"N5": "Hundred Thousandths",
|
||||
"N4": "Ten Thousandths",
|
||||
"N3": "Thousandths",
|
||||
"N2": "Hundredths",
|
||||
"N1": "Tenths",
|
||||
"1": "Tens",
|
||||
"4": "Ten Thousands",
|
||||
"5": "Hundred Thousands",
|
||||
"7": "Ten Millions",
|
||||
"8": "Hundred Millions",
|
||||
"10": "Ten Billions",
|
||||
"11": "Hundred Billions",
|
||||
"13": "Ten Trillions",
|
||||
"14": "Hundred Trillions",
|
||||
"15": "Quadrillions",
|
||||
}
|
||||
|
||||
TIME_FORMAT_MAP = {
|
||||
"P1Y": "Annual",
|
||||
"P6M": "Bi-annual",
|
||||
"P3M": "Quarterly",
|
||||
"P1M": "Monthly",
|
||||
"P7D": "Weekly",
|
||||
"P1D": "Daily",
|
||||
}
|
||||
|
||||
REF_SECTOR_MAP = {
|
||||
"S1311": "Central government excluding social security",
|
||||
"S121": "Central Bank",
|
||||
"S1X": "Monetary Authorities",
|
||||
"1C_AS": "All Sectors",
|
||||
"AllSectorsIncludingAllSectors": "All Sectors Including All Sectors",
|
||||
}
|
||||
306
openbb_platform/providers/imf/openbb_imf/utils/irfcl_helpers.py
Normal file
306
openbb_platform/providers/imf/openbb_imf/utils/irfcl_helpers.py
Normal file
@@ -0,0 +1,306 @@
|
||||
"""IMF IRFCL Data Set Helpers."""
|
||||
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
|
||||
def load_irfcl_symbols() -> Dict:
|
||||
"""Load IMF IRFCL symbols."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import json # noqa
|
||||
from json.decoder import JSONDecodeError
|
||||
from pathlib import Path
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
|
||||
try:
|
||||
symbols_file = Path(__file__).parents[1].joinpath("assets", "imf_symbols.json")
|
||||
with symbols_file.open(encoding="utf-8") as file:
|
||||
symbols = json.load(file)
|
||||
except (FileNotFoundError, JSONDecodeError) as e:
|
||||
raise OpenBBError(f"Failed to load IMF IRFCL symbols: {e}") from e
|
||||
|
||||
return {k: v for k, v in symbols.items() if v["dataset"] == "IRFCL"}
|
||||
|
||||
|
||||
def load_country_map() -> Dict:
|
||||
"""Load IMF IRFCL country map."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import json # noqa
|
||||
from json.decoder import JSONDecodeError
|
||||
from pathlib import Path
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
|
||||
try:
|
||||
country_map_file = (
|
||||
Path(__file__).parents[1].joinpath("assets", "imf_country_map.json")
|
||||
)
|
||||
with country_map_file.open(encoding="utf-8") as file:
|
||||
country_map_dict = json.load(file)
|
||||
except (FileNotFoundError, JSONDecodeError) as e:
|
||||
raise OpenBBError(f"Failed to load IMF IRFCL country map: {e}") from e
|
||||
|
||||
return {
|
||||
k: v.replace("`", "").split(",")[0].split("_(")[0]
|
||||
for k, v in country_map_dict.items()
|
||||
if len(k) == 2 and k[0] not in ("5", "1", "7") and k not in ("X0", "R1", "GW")
|
||||
}
|
||||
|
||||
|
||||
def load_country_to_code_map() -> Dict:
|
||||
"""Load a map of lowercase country name to 2-letter ISO symbol."""
|
||||
return {
|
||||
(
|
||||
"euro_area"
|
||||
if k == "U2"
|
||||
else v.lower()
|
||||
.replace(" ", "_")
|
||||
.replace("`", "")
|
||||
.split(",")[0]
|
||||
.split("_(")[0]
|
||||
): k
|
||||
for k, v in load_country_map().items()
|
||||
}
|
||||
|
||||
|
||||
def validate_countries(countries) -> str:
|
||||
"""Validate the country and convert to a 2-letter ISO country code."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from warnings import warn # noqa
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
|
||||
country_map_dict = load_country_to_code_map()
|
||||
|
||||
if isinstance(countries, str):
|
||||
countries = countries.split(",")
|
||||
elif not isinstance(countries, list):
|
||||
raise OpenBBError("Invalid countries list.")
|
||||
|
||||
new_countries: List = []
|
||||
|
||||
if "all" in countries or "ALL" in countries:
|
||||
return "all"
|
||||
|
||||
for country in countries:
|
||||
if country.lower() not in country_map_dict and country.upper() not in list(
|
||||
country_map_dict.values()
|
||||
):
|
||||
warn(f"Invalid IMF IRFCL country: {country}")
|
||||
continue
|
||||
|
||||
if country.upper() in list(country_map_dict.values()):
|
||||
new_countries.append(country.upper())
|
||||
else:
|
||||
new_countries.append(country_map_dict.get(country, country).upper())
|
||||
|
||||
new_countries = [c for c in new_countries if c]
|
||||
|
||||
if not new_countries:
|
||||
raise OpenBBError("No valid countries found in the supplied list.")
|
||||
|
||||
return ",".join(new_countries)
|
||||
|
||||
|
||||
def validate_symbols(symbols) -> str:
|
||||
"""Validate the IMF IRFCL symbols."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from warnings import warn # noqa
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
|
||||
irfcl_symbols = load_irfcl_symbols()
|
||||
|
||||
if isinstance(symbols, str):
|
||||
symbols = symbols.split(",")
|
||||
elif not isinstance(symbols, list):
|
||||
raise OpenBBError("Invalid symbols list.")
|
||||
|
||||
if "IRFCL" in symbols or "all" in symbols:
|
||||
return "all"
|
||||
|
||||
new_symbols: List = []
|
||||
|
||||
for symbol in symbols:
|
||||
if symbol.upper() not in irfcl_symbols:
|
||||
warn(f"Invalid IMF IRFCL symbol: {symbol}")
|
||||
new_symbols.append(symbol.upper())
|
||||
|
||||
return "+".join(new_symbols) if len(new_symbols) > 1 else new_symbols[0]
|
||||
|
||||
|
||||
# We use this as a helper to allow future expansion of the supported IMF indicators.
|
||||
# Each database has its own nuances with URL construction and schemas.
|
||||
# In the future, we will check the supported symbols map and direct the call
|
||||
# to the appropriate dtatabase's function.
|
||||
|
||||
|
||||
# pylint: disable=too-many-branches,too-many-statements,too-many-locals
|
||||
async def _get_irfcl_data(**kwargs) -> List[Dict]:
|
||||
"""Get IMF IRFCL data.
|
||||
This function is not intended to be called directly,
|
||||
but through the `ImfEconomicIndicatorsFetcher` class.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from json.decoder import JSONDecodeError # noqa
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_imf.utils import constants
|
||||
from pandas import to_datetime
|
||||
from pandas.tseries import offsets
|
||||
|
||||
countries = kwargs.get("country", "")
|
||||
countries = (
|
||||
"" if countries == "all" else countries.replace(",", "+") if countries else ""
|
||||
)
|
||||
|
||||
frequency = constants.FREQUENCY_DICT.get(kwargs.get("frequency", "quarter"), "Q")
|
||||
sector = kwargs.get("sector", "monetary_authorities")
|
||||
sector = constants.REF_SECTORS_DICT.get(sector, "")
|
||||
start_date = kwargs.get("start_date", "")
|
||||
end_date = kwargs.get("end_date", "")
|
||||
|
||||
# Adjust the dates to the date relative to frequency.
|
||||
# The API does not accept arbitrary dates, so we need to adjust them.
|
||||
if start_date:
|
||||
start_date = to_datetime(start_date)
|
||||
if frequency == "Q":
|
||||
# offset = offsets.QuarterBegin(startingMonth=1)
|
||||
# start_date = start_date + offset
|
||||
start_date = offsets.QuarterBegin(startingMonth=1).rollback(start_date)
|
||||
elif frequency == "A":
|
||||
start_date = offsets.YearBegin().rollback(start_date)
|
||||
else:
|
||||
start_date = offsets.MonthBegin().rollback(start_date)
|
||||
start_date = start_date.strftime("%Y-%m-%d")
|
||||
|
||||
if end_date:
|
||||
end_date = to_datetime(end_date)
|
||||
if frequency == "Q":
|
||||
end_date = offsets.QuarterEnd().rollforward(end_date)
|
||||
elif frequency == "A":
|
||||
end_date = offsets.YearEnd().rollforward(end_date)
|
||||
else:
|
||||
end_date = offsets.MonthEnd().rollforward(end_date)
|
||||
end_date = end_date.strftime("%Y-%m-%d")
|
||||
|
||||
indicator = kwargs.get("symbol")
|
||||
indicator = validate_symbols(indicator) if indicator else ""
|
||||
indicator = "" if indicator == "all" else indicator
|
||||
|
||||
if not indicator and not countries:
|
||||
raise OpenBBError("Country is required when returning the complete dataset.")
|
||||
|
||||
date_range = (
|
||||
f"?startPeriod={start_date}&endPeriod={end_date}"
|
||||
if start_date and end_date
|
||||
else ""
|
||||
)
|
||||
|
||||
base_url = "http://dataservices.imf.org/REST/SDMX_JSON.svc/"
|
||||
key = f"CompactData/IRFCL/{frequency}.{countries}.{indicator}.{sector}"
|
||||
url = f"{base_url}{key}{date_range}"
|
||||
|
||||
try:
|
||||
response = await amake_request(url, timeout=20)
|
||||
except JSONDecodeError as e:
|
||||
raise OpenBBError(
|
||||
"Error fetching data; This might be rate-limiting. Try again later."
|
||||
) from e
|
||||
|
||||
if "ErrorDetails" in response:
|
||||
raise OpenBBError(
|
||||
f"{response['ErrorDetails'].get('Code')} -> {response['ErrorDetails'].get('Message')}" # type: ignore
|
||||
)
|
||||
|
||||
series = response.get("CompactData", {}).get("DataSet", {}).pop("Series", {}) # type: ignore
|
||||
|
||||
if not series:
|
||||
raise OpenBBError(f"No time series data found -> {response}")
|
||||
|
||||
# If there is only one series, they ruturn a dict instead of a list.
|
||||
if series and isinstance(series, dict):
|
||||
series = [series]
|
||||
|
||||
data: List = []
|
||||
all_symbols = load_irfcl_symbols()
|
||||
country_map_dict = {
|
||||
v: k.replace("_", " ").title().replace("Ecb", "ECB")
|
||||
for k, v in load_country_to_code_map().items()
|
||||
}
|
||||
# Iterate over the series to extract observations and map the metadata.
|
||||
for s in series:
|
||||
if "Obs" not in s:
|
||||
continue
|
||||
meta = {
|
||||
k.replace("@", "").lower(): (
|
||||
constants.UNIT_MULTIPLIERS_MAP.get(str(v), v)
|
||||
if k == "@UNIT_MULT"
|
||||
else v
|
||||
)
|
||||
for k, v in s.items()
|
||||
if k != "Obs"
|
||||
}
|
||||
_symbol = meta.get("indicator")
|
||||
_parent: Optional[str] = None
|
||||
_order: Optional[str] = None
|
||||
_level: Optional[str] = None
|
||||
_table: Optional[str] = None
|
||||
_title: Optional[str] = None
|
||||
|
||||
if _symbol in all_symbols:
|
||||
_table = all_symbols.get(_symbol, {}).get("table")
|
||||
_parent = all_symbols.get(_symbol, {}).get("parent", "")
|
||||
_order = all_symbols.get(_symbol, {}).get("order", "")
|
||||
_level = all_symbols.get(_symbol, {}).get("level", "")
|
||||
_title = all_symbols.get(_symbol, {}).get("title", "")
|
||||
|
||||
_data = s.pop("Obs", [])
|
||||
|
||||
if isinstance(_data, dict):
|
||||
_data = [_data]
|
||||
|
||||
for d in _data:
|
||||
_date = d.pop("@TIME_PERIOD", None)
|
||||
val = d.pop("@OBS_VALUE", None)
|
||||
|
||||
if not val:
|
||||
continue
|
||||
|
||||
if _date:
|
||||
offset = (
|
||||
offsets.QuarterEnd
|
||||
if "Q" in _date
|
||||
else offsets.YearEnd if len(str(_date)) == 4 else offsets.MonthEnd
|
||||
)
|
||||
_date = to_datetime(_date)
|
||||
_date = _date + offset(0)
|
||||
_date = _date.strftime("%Y-%m-%d")
|
||||
vals = {
|
||||
k: v
|
||||
for k, v in {
|
||||
"date": _date,
|
||||
"table": _table,
|
||||
"symbol": _symbol,
|
||||
"parent": _parent,
|
||||
"order": _order,
|
||||
"level": _level,
|
||||
"country": country_map_dict.get(
|
||||
meta.get("ref_area"), meta.get("ref_area")
|
||||
),
|
||||
"reference_sector": constants.SECTOR_MAP.get(
|
||||
meta.get("ref_sector"), meta.get("ref_sector")
|
||||
),
|
||||
"title": _title,
|
||||
"value": float(val) if val else None,
|
||||
"scale": meta.get("unit_mult"),
|
||||
}.items()
|
||||
if v
|
||||
}
|
||||
|
||||
if vals.get("value") and vals.get("date"):
|
||||
d.update(vals)
|
||||
|
||||
if _data:
|
||||
data.extend([d for d in _data if d])
|
||||
|
||||
if not data:
|
||||
raise OpenBBError("No data found.")
|
||||
|
||||
return data
|
||||
1997
openbb_platform/providers/imf/poetry.lock
generated
vendored
Normal file
1997
openbb_platform/providers/imf/poetry.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
19
openbb_platform/providers/imf/pyproject.toml
vendored
Normal file
19
openbb_platform/providers/imf/pyproject.toml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
[tool.poetry]
|
||||
name = "openbb-imf"
|
||||
version = "1.0.0b"
|
||||
description = "https://datahelp.imf.org/knowledgebase/articles/630877-api"
|
||||
authors = ["OpenBB Team <hello@openbb.co>"]
|
||||
license = "AGPL-3.0-only"
|
||||
readme = "README.md"
|
||||
packages = [{ include = "openbb_imf" }]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
openbb-core = "^1.3.2"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry.plugins."openbb_provider_extension"]
|
||||
imf = "openbb_imf:imf_provider"
|
||||
1
openbb_platform/providers/imf/tests/__init__.py
Normal file
1
openbb_platform/providers/imf/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""IMF Provider Fetcher Tests."""
|
||||
@@ -0,0 +1,54 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/IRFCL/M.JP.RAMFDA_USD.S1X?startPeriod=2023-01-01&endPeriod=2023-12-31
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAEA6SSX4+aQBTFv4qhL226yICiC09S/qQ0oBawMfaBTJmrkggYZlZtzH733hlNttuk
|
||||
zSZ9nHPP7557Z+aq+V1zpJUIqKCae9Vml+bQcvfCa83V9kIcXcM4n8/D82jY9TvDIsQ01mmSV3to
|
||||
qF63XNC2Au3hBWRvAJWf1y5XbZKuoqLu2tdgHqRrldkD7576CrghpTQxbhQ3TlZJjAY4pzsYyFk5
|
||||
DtvDruai/znkrLko/pVdtbghwwtnCkOK4foc+lONMcO62Sqwul2NEWeRn7zdKfuqBeVN/s9O2OQz
|
||||
UAa9fJg4wFbjEXu02cTW2eN2pI8dRnUHto5Ox4wSx7bNCiykCuAC3Vt64PJplj0caQ8MJYtYY504
|
||||
ukkKc+qatmvZ6M+hvafMaukyfYLqnDYgk+WXcA+03SEPLRbeCbgIPMRppD0/aH7XCvxB0rrKYtT3
|
||||
L9/mfpUIFXCA475rAQ0fB+bgPY7yYTCxRvrEsoj2jI0yqKA+gVp3VjM0bjYbmRBQQXMQcYCSeozf
|
||||
RBkrJ2w5Fu/JDP38n6+JA+XQ14DQVZtFWfgV6RTVWRZGpZeFHp6/LKUQz4PY94pFhkrmpVHglas8
|
||||
kBVpzUP/VsrNtdRW87go01VSoHsihSJOwzJaZKknpaUpQxY/MPc7BqviMsziRYB+i+BtEFNSi095
|
||||
+c1LViHK+tQZ48J/sVt/2m0y/dXnHNwADIMwFN2l90oBAnGG6SjZvTmDjM9P1ufaslYfXM+ssY1r
|
||||
z1pMGx6Fo2tZhesCj0HhNjfnu3BfQbmMwrt3kcwxJj/XrF8NPOc7dz97tJr2sAUAAA==
|
||||
headers:
|
||||
Cache-Control:
|
||||
- private
|
||||
Connection:
|
||||
- Keep-Alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Length:
|
||||
- '619'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Tue, 10 Sep 2024 21:15:25 GMT
|
||||
Set-Cookie: null
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Permitted-Cross-Domain-Policies:
|
||||
- none
|
||||
X-XSS-Protection:
|
||||
- 1; mode=block
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -0,0 +1,54 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/IRFCL/M.JP.RAMFDA_USD.S1X?startPeriod=2023-01-01&endPeriod=2023-12-31
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAEA6SSXY+aQBSG/4qhN226yDB+ULmS8pHSgFrAxtgLMg5HJREwDKs2Zv97z4w27W6y
|
||||
zSa95J3nPe/54Kq5TXVkvPNYxzT7qk0v1aEW9kWUmq3tu+5oG8b5fO6fB/2m3RmUENNYxVHK91Ax
|
||||
vaxFx2oO2sMfY/EGo+JFaQtVJmo468qmfm5MvXilMlsQzWPLQRhSiiPj5hLGiebEqEAItoOe7FVg
|
||||
sy3sStG1P/uiqC7K/wxXJW6W/kUUyoauAscX0J5KjOmX1VYZ+W01RpgEbvR2UtZVA8pN/s9MWOQL
|
||||
sAJaeZjQw1IFZeaWTLjOh9ZAH47ISN8UfKOTicVhY32a8BFFVwaiQ3rLDkKeZtHCkbVQoEQJHSKt
|
||||
EyszB/aQ2qMx8inU95RpKSnTJajOWAUyWf4S9oHVO/RDjQ/vOrh0+BHGgfb0oLlN3TGOwlVbJiHq
|
||||
8hS4U/nb3FeJpgwOcNw3NSDwsWf23mMrH3pjOtDHlBLtCQslwKE8gRp3WhYIrtdrmeDhdVLo1ArU
|
||||
Mf4Sf3dYC+TvyQXy4p/XxIZSaEtA01WbBon/Dd0xqtPED3In8R38/rqQQjjzQtfJ5gkqiRMHnpMv
|
||||
U0++SDT13dtTaq6ktpyFWR4vowzpsRSyMPbzYJ7EjpQWpgyZbzD3Bwarx4WfhHMPeUpwG8SUrvnn
|
||||
NP/uREsfZd2aDHHgV3D6Eh8R63V68JL+1eecmwAMxEAU7cW5QfdRjEvZ3r2xhDTxY/ikMGupOpJn
|
||||
rVUj08Kt8dhavHHymGOicZaceTaubiNHaHx7R6w8QOZzqvoli+d85+4HilPlVbAFAAA=
|
||||
headers:
|
||||
Cache-Control:
|
||||
- private
|
||||
Connection:
|
||||
- Keep-Alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Length:
|
||||
- '620'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Sat, 07 Sep 2024 17:42:56 GMT
|
||||
Set-Cookie: null
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Permitted-Cross-Domain-Policies:
|
||||
- none
|
||||
X-XSS-Protection:
|
||||
- 1; mode=block
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
60
openbb_platform/providers/imf/tests/test_imf_fetchers.py
Normal file
60
openbb_platform/providers/imf/tests/test_imf_fetchers.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""IMF Fetcher Tests."""
|
||||
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
|
||||
from openbb_imf.models.available_indicators import ImfAvailableIndicatorsFetcher
|
||||
from openbb_imf.models.economic_indicators import ImfEconomicIndicatorsFetcher
|
||||
from openbb_core.app.service.user_service import UserService
|
||||
|
||||
test_credentials = UserService().default_user_settings.credentials.model_dump(
|
||||
mode="json"
|
||||
)
|
||||
|
||||
|
||||
def scrub_string(key):
|
||||
"""Scrub a string from the response."""
|
||||
|
||||
def before_record_response(response):
|
||||
response["headers"][key] = response["headers"].update({key: None})
|
||||
return response
|
||||
|
||||
return before_record_response
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vcr_config():
|
||||
"""VCR configuration."""
|
||||
return {
|
||||
"filter_headers": [("User-Agent", None)],
|
||||
"before_record_response": [
|
||||
scrub_string("Set-Cookie"),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_imf_economic_indicators_fetcher(credentials=test_credentials):
|
||||
"""Test the IMF EconomicIndicators fetcher."""
|
||||
params = {
|
||||
"country": "JP",
|
||||
"frequency": "month",
|
||||
"symbol": "RAMFDA_USD",
|
||||
"start_date": date(2023, 1, 1),
|
||||
"end_date": date(2023, 12, 31),
|
||||
}
|
||||
|
||||
fetcher = ImfEconomicIndicatorsFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
# The data for this request are local files, so we can't record them.
|
||||
def test_imf_available_indicators_fetcher(credentials=test_credentials):
|
||||
"""Test the IMF Available Indicators fetcher."""
|
||||
params = {}
|
||||
|
||||
fetcher = ImfAvailableIndicatorsFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
1
openbb_platform/pyproject.toml
vendored
1
openbb_platform/pyproject.toml
vendored
@@ -18,6 +18,7 @@ openbb-econdb = "^1.2.2"
|
||||
openbb-federal-reserve = "^1.3.2"
|
||||
openbb-fmp = "^1.3.2"
|
||||
openbb-fred = "^1.3.2"
|
||||
openbb-imf = "^1.0.0b"
|
||||
openbb-intrinio = "^1.3.2"
|
||||
openbb-oecd = "^1.3.2"
|
||||
openbb-polygon = "^1.3.2"
|
||||
|
||||
Reference in New Issue
Block a user