Skip to content

Commit

Permalink
[Feature] ICE BofAML Bond Indices (FRED) (#6486)
Browse files Browse the repository at this point in the history
* fred bond indices

* maturity dict

* review items
  • Loading branch information
deeleeramone authored Jun 7, 2024
1 parent a52b24c commit d7a9e66
Show file tree
Hide file tree
Showing 12 changed files with 1,303 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Bond Indices Standard Model."""

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

from pydantic import Field, field_validator

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


class BondIndicesQueryParams(QueryParams):
"""Bond Indices Query."""

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", ""),
)
index_type: Literal["yield", "yield_to_worst", "total_return", "oas"] = Field(
default="yield",
description="The type of series. OAS is the option-adjusted spread. Default is yield.",
json_schema_extra={
"choices": ["yield", "yield_to_worst", "total_return", "oas"]
},
)

@field_validator("index_type", mode="before", check_fields=False)
@classmethod
def to_lower(cls, v: Optional[str]) -> Optional[str]:
"""Convert field to lowercase."""
return v.lower() if v else v


class BondIndicesData(Data):
"""Bond Indices Data."""

date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", ""))
symbol: Optional[str] = Field(
default=None,
description=DATA_DESCRIPTIONS.get("symbol", ""),
)
value: float = Field(description="Index values.")
Original file line number Diff line number Diff line change
Expand Up @@ -666,3 +666,31 @@ def test_fixedincome_government_yield_curve(params, headers):
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@parametrize(
"params",
[
{
"provider": "fred",
"category": "high_yield",
"index": "us,europe,emerging",
"index_type": "total_return",
"start_date": "2023-05-31",
"end_date": "2024-06-01",
"transform": None,
"frequency": None,
"aggregation_method": "avg",
},
],
)
@pytest.mark.integration
def test_fixedincome_bond_indices(params, headers):
"""Test the bond indices 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/fixedincome/bond_indices?{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 @@ -620,3 +620,30 @@ def test_fixedincome_government_yield_curve(params, obb):
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0


@parametrize(
"params",
[
{
"provider": "fred",
"category": "high_yield",
"index": "us,europe,emerging",
"index_type": "total_return",
"start_date": "2023-05-31",
"end_date": "2024-06-01",
"transform": None,
"frequency": None,
"aggregation_method": "avg",
},
],
)
@pytest.mark.integration
def test_fixedincome_bond_indices(params, obb):
"""Test the bond indices endpoint."""
params = {p: v for p, v in params.items() if v}

result = obb.fixedincome.bond_indices(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Fixed Income Corporate Router."""

from openbb_core.app.deprecation import OpenBBDeprecationWarning
from openbb_core.app.model.command_context import CommandContext
from openbb_core.app.model.example import APIEx
from openbb_core.app.model.obbject import OBBject
Expand All @@ -22,6 +23,12 @@
APIEx(parameters={"provider": "fred"}),
APIEx(parameters={"index_type": "yield_to_worst", "provider": "fred"}),
],
deprecated=True,
deprecation=OpenBBDeprecationWarning(
message="This endpoint is deprecated; use `/fixedincome/bond_indices` instead.",
since=(4, 2),
expected_removal=(4, 5),
),
)
async def ice_bofa(
cc: CommandContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,40 @@ async def sofr(
borrowing cash overnight collateralizing by Treasury securities.
"""
return await OBBject.from_query(Query(**locals()))


@router.command(
model="BondIndices",
examples=[
APIEx(
description="The default state for FRED are series for constructing the US Corporate Bond Yield Curve.",
parameters={"provider": "fred"},
),
APIEx(
description="Multiple indices, from within the same 'category', can be requested.",
parameters={
"category": "high_yield",
"index": "us,europe,emerging",
"index_type": "total_return",
"provider": "fred",
},
),
APIEx(
description="From FRED, there are three main categories, 'high_yield', 'us', and 'emerging_markets'."
+ " Emerging markets is a broad category.",
parameters={
"category": "emerging_markets",
"index": "corporate,private_sector,public_sector",
"provider": "fred",
},
),
],
)
async def bond_indices(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject: # type: ignore
"""Bond Indices."""
return await OBBject.from_query(Query(**locals()))
Loading

0 comments on commit d7a9e66

Please sign in to comment.