|
8 | 8 | import pandas as pd
|
9 | 9 | from openbb_core.app.model.charts.chart import ChartFormat
|
10 | 10 | from openbb_core.app.utils import basemodel_to_df
|
| 11 | +from openbb_core.provider.abstract.data import Data |
11 | 12 | from plotly.graph_objs import Figure
|
12 | 13 |
|
13 | 14 | from openbb_charting.core.chart_style import ChartStyle
|
|
19 | 20 | from openbb_charting.utils.generic_charts import bar_chart
|
20 | 21 | from openbb_charting.utils.helpers import (
|
21 | 22 | calculate_returns,
|
| 23 | + duration_sorter, |
22 | 24 | heikin_ashi,
|
23 | 25 | should_share_axis,
|
24 | 26 | z_score_standardization,
|
@@ -406,7 +408,7 @@ def equity_price_historical( # noqa: PLR0912
|
406 | 408 | name=data[col].name,
|
407 | 409 | mode="lines",
|
408 | 410 | hovertemplate=hovertemplate,
|
409 |
| - line=dict(width=1, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), |
| 411 | + line=dict(width=2, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), |
410 | 412 | yaxis=yaxis,
|
411 | 413 | )
|
412 | 414 |
|
@@ -608,7 +610,7 @@ def _ta_ma(**kwargs):
|
608 | 610 | name=name,
|
609 | 611 | mode="lines",
|
610 | 612 | hovertemplate=f"{name}: %{{y}}<extra></extra>",
|
611 |
| - line=dict(width=1, color=LARGE_CYCLER[color]), |
| 613 | + line=dict(width=2, color=LARGE_CYCLER[color]), |
612 | 614 | showlegend=True,
|
613 | 615 | )
|
614 | 616 | color += 1
|
@@ -1119,7 +1121,7 @@ def economy_fred_series( # noqa: PLR0912
|
1119 | 1121 | name=df_ta[col].name,
|
1120 | 1122 | mode="lines",
|
1121 | 1123 | hovertemplate=f"{df_ta[col].name}: %{{y}}<extra></extra>",
|
1122 |
| - line=dict(width=1, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), |
| 1124 | + line=dict(width=2, color=LARGE_CYCLER[i % len(LARGE_CYCLER)]), |
1123 | 1125 | yaxis="y1" if kwargs.get("same_axis") is True else yaxes,
|
1124 | 1126 | )
|
1125 | 1127 |
|
@@ -1292,3 +1294,156 @@ def technical_relative_rotation(
|
1292 | 1294 | content = figure.to_plotly_json()
|
1293 | 1295 |
|
1294 | 1296 | return figure, content
|
| 1297 | + |
| 1298 | + |
| 1299 | +def fixedincome_government_yield_curve( # noqa: PLR0912 |
| 1300 | + **kwargs, |
| 1301 | +) -> Tuple[OpenBBFigure, Dict[str, Any]]: |
| 1302 | + """Government Yield Curve Chart.""" |
| 1303 | + data = kwargs.get("data", None) |
| 1304 | + df: pd.DataFrame = pd.DataFrame() |
| 1305 | + if data: |
| 1306 | + if isinstance(data, pd.DataFrame) and not data.empty: # noqa: SIM108 |
| 1307 | + df = data |
| 1308 | + elif isinstance(data, (list, Data)): |
| 1309 | + df = basemodel_to_df(data, index=None) # type: ignore |
| 1310 | + else: |
| 1311 | + pass |
| 1312 | + else: |
| 1313 | + df = pd.DataFrame([d.model_dump() for d in kwargs["obbject_item"]]) # type: ignore |
| 1314 | + |
| 1315 | + if df.empty: |
| 1316 | + raise ValueError("Error: No data to plot.") |
| 1317 | + |
| 1318 | + if "maturity" not in df.columns: |
| 1319 | + raise ValueError("Error: Maturity column not found in the data.") |
| 1320 | + |
| 1321 | + if "rate" not in df.columns: |
| 1322 | + raise ValueError("Error: Rate column not found in the data.") |
| 1323 | + |
| 1324 | + if "date" not in df.columns: |
| 1325 | + raise ValueError("Error: Date column not found in the data.") |
| 1326 | + |
| 1327 | + provider = kwargs.get("provider") |
| 1328 | + df["date"] = df["date"].astype(str) |
| 1329 | + maturities = duration_sorter(df["maturity"].unique().tolist()) |
| 1330 | + |
| 1331 | + # Use the supplied colors, if any. |
| 1332 | + colors = kwargs.get("colors", []) |
| 1333 | + if not colors: |
| 1334 | + colors = LARGE_CYCLER |
| 1335 | + color_count = 0 |
| 1336 | + |
| 1337 | + figure = OpenBBFigure().create_subplots(shared_xaxes=False) |
| 1338 | + figure.update_layout(ChartStyle().plotly_template.get("layout", {})) |
| 1339 | + |
| 1340 | + def create_fig(figure, df, dates, color_count, country: Optional[str] = None): |
| 1341 | + """Create a scatter for each date in the data.""" |
| 1342 | + for date in dates: |
| 1343 | + color = colors[color_count % len(colors)] |
| 1344 | + plot_df = df[df["date"] == date].copy() |
| 1345 | + plot_df["rate"] = plot_df["rate"].apply(lambda x: x * 100) |
| 1346 | + plot_df = ( |
| 1347 | + plot_df.drop(columns=["date"]) |
| 1348 | + .set_index("maturity") |
| 1349 | + .filter(items=maturities, axis=0) |
| 1350 | + .reset_index() |
| 1351 | + .rename(columns={"maturity": "Maturity", "rate": "Yield"}) |
| 1352 | + ) |
| 1353 | + plot_df["Maturity"] = [ |
| 1354 | + ( |
| 1355 | + d.split("_")[1] + " " + d.split("_")[0].title() |
| 1356 | + if d != "long_term" |
| 1357 | + else "Long Term" |
| 1358 | + ) |
| 1359 | + for d in plot_df["Maturity"] |
| 1360 | + ] |
| 1361 | + figure.add_scatter( |
| 1362 | + x=plot_df["Maturity"], |
| 1363 | + y=plot_df["Yield"], |
| 1364 | + # fill=fill, |
| 1365 | + mode="lines+markers", |
| 1366 | + name=f"{country} - {date}" if country else date, |
| 1367 | + line=dict(width=3, color=color), |
| 1368 | + marker=dict(size=10, color=color), |
| 1369 | + hovertemplate=( |
| 1370 | + "Maturity: %{x}<br>Yield: %{y}%<extra></extra>" |
| 1371 | + if len(dates) == 1 |
| 1372 | + else "%{fullData.name}<br>Maturity: %{x}<br>Yield: %{y}%<extra></extra>" |
| 1373 | + ), |
| 1374 | + ) |
| 1375 | + color_count += 1 |
| 1376 | + return figure, color_count |
| 1377 | + |
| 1378 | + dates = df.date.unique().tolist() |
| 1379 | + figure, color_count = create_fig(figure, df, dates, color_count) |
| 1380 | + |
| 1381 | + # Set the title for the chart |
| 1382 | + country: str = "" |
| 1383 | + if provider in ("federal_reserve", "fmp"): |
| 1384 | + country = "United States" |
| 1385 | + elif provider == "ecb": |
| 1386 | + curve_type = ( |
| 1387 | + getattr(kwargs["extra_params"], "yield_curve_type", "") |
| 1388 | + .replace("_", " ") |
| 1389 | + .title() |
| 1390 | + ) |
| 1391 | + grade = getattr(kwargs["extra_params"], "rating", "").replace("_", " ") |
| 1392 | + grade = grade.upper() if grade == "aaa" else "All Ratings" |
| 1393 | + country = f"Euro Area ({grade}) {curve_type}" |
| 1394 | + elif provider == "fred": |
| 1395 | + curve_type = getattr(kwargs["extra_params"], "yield_curve_type", "") |
| 1396 | + curve_type = ( |
| 1397 | + "Real Rates" |
| 1398 | + if curve_type == "real" |
| 1399 | + else curve_type.replace("_", " ").title() |
| 1400 | + ) |
| 1401 | + country = f"United States {curve_type}" |
| 1402 | + elif provider == "econdb": |
| 1403 | + country = kwargs["standard_params"].get("country") |
| 1404 | + country = country.replace("_", " ").title() if country else "United States" |
| 1405 | + country = country + " " if country else "" |
| 1406 | + title = kwargs.get("title", "") |
| 1407 | + if not title: |
| 1408 | + title = f"{country}Yield Curve" |
| 1409 | + if len(dates) == 1: |
| 1410 | + title = f"{country} Yield Curve - {dates[0]}" |
| 1411 | + |
| 1412 | + # Update the layout of the figure. |
| 1413 | + figure.update_layout( |
| 1414 | + title=dict(text=title, x=0.5, font=dict(size=20)), |
| 1415 | + plot_bgcolor="rgba(0,0,0,0)", |
| 1416 | + xaxis=dict( |
| 1417 | + title="Maturity", |
| 1418 | + ticklen=0, |
| 1419 | + showgrid=False, |
| 1420 | + ), |
| 1421 | + yaxis=dict( |
| 1422 | + title="Yield (%)", |
| 1423 | + ticklen=0, |
| 1424 | + showgrid=True, |
| 1425 | + gridcolor="rgba(128,128,128,0.3)", |
| 1426 | + ), |
| 1427 | + legend=dict( |
| 1428 | + orientation="v", |
| 1429 | + yanchor="top", |
| 1430 | + xanchor="right", |
| 1431 | + y=0.95, |
| 1432 | + x=0, |
| 1433 | + xref="paper", |
| 1434 | + font=dict(size=12), |
| 1435 | + bgcolor="rgba(0,0,0,0)", |
| 1436 | + ), |
| 1437 | + margin=dict( |
| 1438 | + b=25, |
| 1439 | + t=10, |
| 1440 | + ), |
| 1441 | + ) |
| 1442 | + |
| 1443 | + layout_kwargs = kwargs.get("layout_kwargs", {}) |
| 1444 | + if layout_kwargs: |
| 1445 | + figure.update_layout(layout_kwargs) |
| 1446 | + |
| 1447 | + content = figure.show(external=True) |
| 1448 | + |
| 1449 | + return figure, content |
0 commit comments