Skip to content

Commit

Permalink
[Feature] Add Direction Of Trade Statistics From IMF (OpenBB-finance#…
Browse files Browse the repository at this point in the history
…6683)

* add direction of trade statistics from IMF

* update readme

* linting

* linting
  • Loading branch information
deeleeramone authored Sep 22, 2024
1 parent 39e30e8 commit 12b4863
Show file tree
Hide file tree
Showing 15 changed files with 2,515 additions and 1,783 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Direction Of Trade Standard Model."""

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

from pydantic import Field

from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS,
)


class DirectionOfTradeQueryParams(QueryParams):
"""Direction Of Trade Query."""

__json_schema_extra__ = {
"direction": {
"choices": ["exports", "imports", "balance", "all"],
},
"frequency": {
"choices": ["month", "quarter", "annual"],
},
}

country: Optional[str] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("country", "")
+ " None is an equiavlent to 'all'. If 'all' is used, the counterpart field cannot be 'all'.",
)
counterpart: Optional[str] = Field(
default=None,
description="Counterpart country to the trade. None is an equiavlent to 'all'."
+ " If 'all' is used, the country field cannot be 'all'.",
)
direction: Literal["exports", "imports", "balance", "all"] = Field(
default="balance",
description="Trade direction. Use 'all' to get all data for this dimension.",
)
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", "")
)
frequency: Literal["month", "quarter", "annual"] = Field(
default="month", description=QUERY_DESCRIPTIONS.get("frequency", "")
)


class DirectionOfTradeData(Data):
"""Direction Of Trade Data."""

date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", ""))
symbol: Optional[str] = Field(
default=None, description=DATA_DESCRIPTIONS.get("symbol", "")
)
country: str = Field(description=DATA_DESCRIPTIONS.get("country", ""))
counterpart: str = Field(description="Counterpart country or region to the trade.")
title: Optional[str] = Field(
default=None, description="Title corresponding to the symbol."
)
value: float = Field(description="Trade value.")
scale: Optional[str] = Field(default=None, description="Scale of the value.")
28 changes: 28 additions & 0 deletions openbb_platform/extensions/economy/integration/test_economy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,3 +1200,31 @@ def test_economy_port_volume(params, headers):
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@parametrize(
"params",
[
(
{
"provider": "imf",
"country": "us",
"counterpart": "world,eu",
"frequency": "annual",
"direction": "exports",
"start_date": "2020-01-01",
"end_date": "2023-01-01",
}
),
],
)
@pytest.mark.integration
def test_economy_direction_of_trade(params, headers):
"""Test the economy direction of trade endpoint."""
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/direction_of_trade?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
Original file line number Diff line number Diff line change
Expand Up @@ -1155,3 +1155,30 @@ def test_economy_port_volume(params, obb):
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0


@parametrize(
"params",
[
(
{
"provider": "imf",
"country": "us",
"counterpart": "world,eu",
"frequency": "annual",
"direction": "exports",
"start_date": "2020-01-01",
"end_date": "2023-01-01",
}
),
],
)
@pytest.mark.integration
def test_economy_direction_of_trade(params, obb):
"""Test the economy direction of trade endpoint"""
params = {p: v for p, v in params.items() if v}

result = obb.economy.direction_of_trade(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
Original file line number Diff line number Diff line change
Expand Up @@ -735,3 +735,40 @@ async def port_volume(
) -> OBBject:
"""Get average dwelling times and TEU volumes from the top ports."""
return await OBBject.from_query(Query(**locals()))


@router.command(
model="DirectionOfTrade",
examples=[
APIEx(parameters={"provider": "imf", "country": "all", "counterpart": "china"}),
APIEx(
description="Select multiple countries or counterparts by entering a comma-separated list."
+ " The direction of trade can be 'exports', 'imports', 'balance', or 'all'.",
parameters={
"provider": "imf",
"country": "us",
"counterpart": "world,eu",
"frequency": "annual",
"direction": "exports",
},
),
],
)
async def direction_of_trade(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get Direction Of Trade Statistics from the IMF database.
The Direction of Trade Statistics (DOTS) presents the value of merchandise exports and
imports disaggregated according to a country's primary trading partners.
Area and world aggregates are included in the display of trade flows between major areas of the world.
Reported data is supplemented by estimates whenever such data is not available or current.
Imports are reported on a cost, insurance and freight (CIF) basis
and exports are reported on a free on board (FOB) basis.
Time series data includes estimates derived from reports of partner countries
for non-reporting and slow-reporting countries.
"""
return await OBBject.from_query(Query(**locals()))
Loading

0 comments on commit 12b4863

Please sign in to comment.