diff options
36 files changed, 139103 insertions, 184 deletions
diff --git a/openbb_platform/core/openbb_core/provider/standard_models/yield_curve.py b/openbb_platform/core/openbb_core/provider/standard_models/yield_curve.py new file mode 100644 index 00000000000..97909e40804 --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/yield_curve.py @@ -0,0 +1,37 @@ +"""Yield Curve Standard Model.""" + +from datetime import date as dateType +from typing import Optional + +from pydantic import Field + +from openbb_core.provider.abstract.data import Data +from openbb_core.provider.abstract.query_params import QueryParams +from openbb_core.provider.utils.descriptions import ( + DATA_DESCRIPTIONS, + QUERY_DESCRIPTIONS, +) + + +class YieldCurveQueryParams(QueryParams): + """Yield Curve Query.""" + + date: Optional[str] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("date", "") + + " By default is the current data.", + ) + + +class YieldCurveData(Data): + """Yield Curve Data.""" + + date: Optional[dateType] = Field( + default=None, + description=DATA_DESCRIPTIONS.get("date", ""), + ) + maturity: str = Field(description="Maturity length of the security.") + rate: float = Field( + description="The yield as a normalized percent (0.05 is 5%)", + json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100}, + ) diff --git a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py index da9c88c77c4..45e7c86a685 100644 --- a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py +++ b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_api.py @@ -623,3 +623,46 @@ def test_fixedincome_corporate_bond_prices(params, headers): result = requests.get(url, headers=headers, timeout=40) assert isinstance(result, requests.Response) assert result.status_code == 200 + + +@parametrize( + "params", + [ + ({"date": "2023-05-01,2024-05-01", "provider": "fmp"}), + ( + { + "date": "2023-05-01", + "country": "united_kingdom", + "provider": "econdb", + "use_cache": True, + } + ), + ( + { + "provider": "ecb", + "yield_curve_type": "par_yield", + "date": None, + "rating": "aaa", + "use_cache": True, + } + ), + ( + { + "provider": "fred", + "yield_curve_type": "nominal", + "date": "2023-05-01,2024-05-01", + } + ), + ({"provider": "federal_reserve", "date": "2023-05-01,2024-05-01"}), + ], +) +@pytest.mark.integration +def test_fixedincome_government_yield_curve(params, headers): + """Test the treasury rates 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/government/yield_curve?{query_str}" + result = requests.get(url, headers=headers, timeout=10) + assert isinstance(result, requests.Response) + assert result.status_code == 200 diff --git a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py index 57ba30d7fad..3efa8727269 100644 --- a/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py +++ b/openbb_platform/extensions/fixedincome/integration/test_fixedincome_python.py @@ -578,3 +578,45 @@ def test_fixedincome_corporate_bond_prices(params, obb): assert result assert isinstance(result, OBBject) assert len(result.results) > 0 + + +@parametrize( + "params", + [ + ({"date": "2023-05-01,2024-05-01", "provider": "fmp"}), + ( + { + "date": "2023-05-01", + "country": "united_kingdom", + "provider": "econdb", + "use_cache": True, + } + ), + ( + { + "provider": "ecb", + "yield_curve_type": "par_yield", + "date": None, + "rating": "aaa", + "use_cache": True, + } + ), + ( + { + "provider": "fred", + "yield_curve_type": "nominal", + "date": "2023-05-01,2024-05-01", + } + ), + ({"provider": "federal_reserve", "date": "2023-05-01,2024-05-01"}), + ], +) +@pytest.mark.integration +def test_fixedincome_government_yield_curve(params, obb): + """Test the government yield curve endpoint.""" + params = {p: v for p, v in params.items() if v} + + result = obb.fixedincome.government.yield_curve(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 diff --git a/openbb_platform/extensions/fixedincome/openbb_fixedincome/government/government_router.py b/openbb_platform/extensions/fixedincome/openbb_fixedincome/government/government_router.py index 7d7a325eb7a..d65fd411e46 100644 --- a/openbb_platform/extensions/fixedincome/openbb_fixedincome/government/government_router.py +++ b/openbb_platform/extensions/fixedincome/openbb_fixedincome/government/government_router.py @@ -1,5 +1,6 @@ """Fixed Income Government 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 @@ -17,7 +18,45 @@ router = Router(prefix="/government") @router.command( + model="YieldCurve", + examples=[ + APIEx(parameters={"provider": "federal_reserve"}), + APIEx(parameters={"date": "2023-05-01,2024-05-01", "provider": "fmp"}), + APIEx( + parameters={ + "date": "2023-05-01", + "country": "united_kingdom", + "provider": "econdb", + } + ), + APIEx(parameters={"provider": "ecb", "yield_curve_type": "par_yield"}), + APIEx( + parameters={ + "provider": "fred", + "yield_curve_type": "real", + "date": "2023-05-01,2024-05-01", + } + ), + ], +) +async def yield_curve( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: # type: ignore + """Get yield curve data by country and date.""" + return await OBBject.from_query(Query(**locals())) + + +@router.command( model="USYieldCurve", + deprecated=True, + deprecation=OpenBBDeprecationWarning( + message="This endpoint will be removed in a future version. Use, `/fixedincome/government/yield_curve`, instead.", + since=(4, 1), + expected_removal=(4, 3), + ), examples=[ APIEx(parameters={"provider": "fred"}), APIEx(parameters={"inflation_adjusted": True, "provider": "fred"}), @@ -35,6 +74,12 @@ async def us_yield_curve( @router.command( model="EUYieldCurve", + deprecated=True, + deprecation=OpenBBDeprecationWarning( + message="This endpoint will be removed in a future version. Use, `/fixedincome/government/yield_curve`, instead.", + since=(4, 1), + expected_removal=(4, 3), + ), examples=[ APIEx(parameters={"provider": "ecb"}), APIEx(parameters={"yield_curve_type": "spot_rate", "provider": "ecb"}), diff --git a/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py b/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py index 5066d5a40b7..fc9f2b0b646 100644 --- a/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py +++ b/openbb_platform/obbject_extensions/charting/integration/test_charting_api.py @@ -719,3 +719,42 @@ def test_charting_etf_holdings(params, headers): assert chart assert not fig assert list(chart.keys()) == ["content", "format"] + + +@parametrize( + "params", + [ + ( + { + "provider": "econdb", + "country": "united_kingdom", + "date": None, + "chart": True, + } + ), + ( + { + "provider": "fred", + "date": "2023-05-10,2024-05-10", + "chart": True, + } + ), + ], +) +@pytest.mark.integration +def test_charting_fixedincome_government_yield_curve(params, headers): + """Test chart fixedincome government yield curve.""" + params = {p: v for p, v in params.items() if v} + body = (json.dumps({"extra_params": {"chart_params": {"title": "test chart"}}}),) + query_str = get_querystring(params, []) + url = f"http://0.0.0.0:8000/api/v1/fixedincome/government/yield_curve?{query_str}" + result = requests.get(url, headers=headers, timeout=10, json=body) + assert isinstance(result, requests.Response) + assert result.status_code == 200 + + chart = result.json()["chart"] + fig = chart.pop("fig", {}) + + assert chart + assert not fig + assert list(chart.keys()) == ["content", "format"] diff --git a/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py b/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py index f8bc9275e59..b07b5792de8 100644 --- a/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py +++ b/openbb_platform/obbject_extensions/charting/integration/test_charting_python.py @@ -590,3 +590,34 @@ def test_charting_etf_holdings(params, obb): assert len(result.results) > 0 assert result.chart.content assert isinstance(result.chart.fig, OpenBBFigure) + + +@parametrize( + "params", + [ + ( + { + "provider": "econdb", + "country": "united_kingdom", + "date": None, + "chart": True, + } + ), + ( + { + "provider": "fred", + "date": "2023-05-10,2024-05-10", + "chart": True, + } + ), + ], +) +@pytest.mark.integration +def test_charting_fixedincome_government_yield_curve(params, obb): + """Test chart fixedincome government yield curve.""" + result = obb.fixedincome.government.yield_curve(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 + assert result.chart.content + assert isinstance(result.chart.fig, OpenBBFigure) diff --git a/openbb_platform/obbject_extensions/charting/openbb_charting/__init__.py b/openbb_platform/obbject_extensions/charting/openbb_charting/__init__.py index 913849cd41e..b2e5efcfd4a 100644 --- a/openbb_platform/obbject_extensions/charting/openbb_charting/__init__.py +++ b/openbb_platform/obbject_extensions/charting/openbb_charting/__init__.py @@ -459,6 +459,9 @@ class Charting: ) kwargs["provider"] = self._obbject.provider # pylint: disable=protected-access kwargs["extra"] = self._obbject.extra # pylint: disable=protected-access + kwargs["extra_params"] = kwargs["extra"]["metadata"].arguments.get( + "extra_params" + ) if "kwargs" in kwargs: _kwargs = kwargs.pop("kwargs") kwargs.update(_kwargs.get("chart_params", {})) diff --git a/openbb_platform/obbject_extensions/charting/openbb_charting/charting_router.py b/openbb_platform/obbject_extensions/charting/openbb_charting/charting_router.py index fc271fbeaa1..29253fdf8a7 100644 --- a/openbb_platform/obbject_extensions/charting/openbb_charting/charting_router.py +++ b/openbb_platform/obbject_extensions/charting/openbb_charting/charting_router.py @@ -8,6 +8,7 @@ from warnings import warn import pandas as pd from openbb_core.app.model.charts.chart import ChartFormat from openbb_core.app.utils import basemodel_to_df +from openbb_core.provider.abstract.data import Data from plotly.graph_objs import Figure from openbb_charting.core.chart_style import ChartStyle @@ -19,6 +20,7 @@ from openbb_charting.utils import relative_rotation from openbb_charting.utils.generic_charts import bar_chart from openbb_charting.utils.helpers import ( calculate_returns, + duration_sorter, heikin_ashi, should_share_axis, z_score_standardization, @@ -406,7 +408,7 @@ def equity_price_historical( # noqa: PLR0912 name=data[col].name, mode="lines", hovertemplate=hovertemplate, - line=dict(width=1, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), + line=dict(width=2, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), yaxis=yaxis, ) @@ -608,7 +610,7 @@ def _ta_ma(**kwargs): name=name, mode="lines", hovertemplate=f"{name}: %{{y}}<extra></extra>", - line=dict(width=1, color=LARGE_CYCLER[color]), + line=dict(width=2, color=LARGE_CYCLER[color]), showlegend=True, ) color += 1 @@ -1119,7 +1121,7 @@ def economy_fred_series( # noqa: PLR0912 name=df_ta[col].name, mode="lines", hovertemplate=f"{df_ta[col].name}: %{{y}}<extra></extra>", - line=dict(width=1, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), + line=dict(width=2, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), yaxis="y1" if kwargs.get("same_axis") is True else yaxes, ) @@ -1253,7 +1255,7 @@ def technical_relative_rotation( ratios_df, momentum_df, benchmark_symbol, study, date # type: ignore ) - figure = OpenBBFigure(fig) + figure = OpenBBFigure(fig) # pylint: disable=E0606 font_color = "black" if ChartStyle().plt_style == "light" else "white" figure.update_layout( paper_bgcolor="rgba(0,0,0,0)", @@ -1292,3 +1294,167 @@ def technical_relative_rotation( content = figure.to_plotly_json() return figure, content + + +def fixedincome_government_yield_curve( # noqa: PLR0912 + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + """Government Yield Curve Chart.""" + data = kwargs.get("data", None) + df: pd.DataFrame = pd.DataFrame() + if data: + if isinstance(data, pd.DataFrame) and not data.empty: # noqa: SIM108 + df = data + elif isinstance(data, (list, Data)): + df = basemodel_to_df(data, index=None) # type: ignore + else: + pass + else: + df = pd.DataFrame([d.model_dump() for d in kwargs["obbject_item"]]) # type: ignore + + if df.empty: + raise ValueError("Error: No data to plot.") + + if "maturity" not in df.columns: + raise ValueError("Error: Maturity column not found in the data.") + + if "rate" not in df.columns: + raise ValueError("Error: Rate column not found in the data.") + + if "date" not in df.columns: + raise ValueError("Error: Date column not found in the data.") + + provider = kwargs.get("provider") + df["date"] = df["date"].astype(str) + maturities = duration_sorter(df["maturity"].unique().tolist()) + + # Use the supplied colors, if any. + colors = kwargs.get("colors", []) + if not colors: + colors = LARGE_CYCLER + color_count = 0 + |