openbb-charting 2.3.2__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/PKG-INFO +7 -7
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charting.py +74 -12
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/generic_charts.py +185 -15
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/helpers.py +1 -1
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/relative_rotation.py +146 -61
- openbb_charting-2.4.0/openbb_charting/core/assets/plotly-3.1.0.min.js +3882 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/backend.py +1 -17
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/openbb_figure.py +32 -64
- openbb_charting-2.4.0/openbb_charting/core/plotly.html +4031 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/data_classes.py +3 -1
- openbb_charting-2.4.0/openbb_charting/core/table.html +165 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/styles/default/dark.pltstyle.json +1 -20
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/styles/default/light.pltstyle.json +1 -21
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/pyproject.toml +5 -5
- openbb_charting-2.3.2/openbb_charting/core/assets/plotly-3.0.0.min.js +0 -3879
- openbb_charting-2.3.2/openbb_charting/core/plotly.html +0 -4033
- openbb_charting-2.3.2/openbb_charting/core/table.html +0 -173
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/README.md +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/correlation_matrix.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/price_historical.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/charts/price_performance.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/assets/Terminal_icon.png +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/chart_style.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/config/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/config/openbb_styles.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/dummy_backend.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/base.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/custom_indicators_plugin.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/momentum_plugin.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/overlap_plugin.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/trend_indicators_plugin.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/volatility_plugin.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/plugins/volume_plugin.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/ta_class.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/plotly_ta/ta_helpers.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/core/to_chart.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/query_params.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/styles/__init__.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/styles/colors.py +0 -0
- {openbb_charting-2.3.2 → openbb_charting-2.4.0}/openbb_charting/styles/default/tables.pltstyle.json +0 -0
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: openbb-charting
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: Charting extension for OpenBB
|
|
5
5
|
License: AGPL-3.0-only
|
|
6
6
|
Author: OpenBB Team
|
|
7
7
|
Author-email: hello@openbb.co
|
|
8
|
-
Requires-Python: >=3.9,<3.
|
|
8
|
+
Requires-Python: >=3.9.21,<3.14
|
|
9
9
|
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
15
|
Provides-Extra: pywry
|
|
16
16
|
Requires-Dist: nbformat (>=5.10.0,<6.0.0)
|
|
17
|
-
Requires-Dist: openbb-core (>=1.
|
|
18
|
-
Requires-Dist: pandas-ta-openbb (>=0.4.
|
|
19
|
-
Requires-Dist: plotly (>=
|
|
17
|
+
Requires-Dist: openbb-core (>=1.5.1,<2.0.0)
|
|
18
|
+
Requires-Dist: pandas-ta-openbb (>=0.4.22,<0.5.0)
|
|
19
|
+
Requires-Dist: plotly (>=6.3.1,<7.0.0)
|
|
20
20
|
Requires-Dist: pywry (>=0.6.2,<0.7.0) ; extra == "pywry"
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
|
|
@@ -18,6 +18,7 @@ from typing import (
|
|
|
18
18
|
from warnings import warn
|
|
19
19
|
|
|
20
20
|
from importlib_metadata import entry_points
|
|
21
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
21
22
|
from openbb_core.app.model.charts.chart import Chart
|
|
22
23
|
from openbb_core.app.model.obbject import OBBject
|
|
23
24
|
from openbb_core.provider.abstract.data import Data
|
|
@@ -122,8 +123,8 @@ class Charting:
|
|
|
122
123
|
|
|
123
124
|
create_backend(self._charting_settings)
|
|
124
125
|
backend = get_backend()
|
|
125
|
-
backend.start(debug=self._charting_settings.debug_mode)
|
|
126
|
-
return backend
|
|
126
|
+
backend.start(debug=self._charting_settings.debug_mode) # type: ignore
|
|
127
|
+
return backend # type: ignore
|
|
127
128
|
|
|
128
129
|
def _get_chart_function(self, route: str) -> Callable:
|
|
129
130
|
"""Given a route, it returns the chart function. The module must contain the given route."""
|
|
@@ -178,9 +179,9 @@ class Charting:
|
|
|
178
179
|
else None
|
|
179
180
|
)
|
|
180
181
|
data_as_df: DataFrame = (
|
|
181
|
-
basemodel_to_df(convert_to_basemodel(data), index=index)
|
|
182
|
+
basemodel_to_df(convert_to_basemodel(data), index=index) # type: ignore
|
|
182
183
|
if has_data
|
|
183
|
-
else self._obbject.to_dataframe(index=index)
|
|
184
|
+
else self._obbject.to_dataframe(index=index) # type: ignore
|
|
184
185
|
)
|
|
185
186
|
if "date" in data_as_df.columns:
|
|
186
187
|
data_as_df = data_as_df.set_index("date")
|
|
@@ -369,6 +370,65 @@ class Charting:
|
|
|
369
370
|
|
|
370
371
|
return fig
|
|
371
372
|
|
|
373
|
+
def create_3d_surface(
|
|
374
|
+
self,
|
|
375
|
+
X: "Series",
|
|
376
|
+
Y: "Series",
|
|
377
|
+
Z: "Series",
|
|
378
|
+
xtitle: Optional[str] = "DTE",
|
|
379
|
+
ytitle: Optional[str] = "Strike",
|
|
380
|
+
ztitle: Optional[str] = "IV",
|
|
381
|
+
colorscale: Optional[Union[str, list]] = None,
|
|
382
|
+
title: Optional[str] = None,
|
|
383
|
+
layout_kwargs: Optional[dict[str, Any]] = None,
|
|
384
|
+
theme: Optional[Literal["dark", "light"]] = None,
|
|
385
|
+
) -> Union["OpenBBFigure", "Figure"]:
|
|
386
|
+
"""Create a 3D surface chart.
|
|
387
|
+
|
|
388
|
+
Parameters
|
|
389
|
+
----------
|
|
390
|
+
X : pd.Series
|
|
391
|
+
The x-axis data.
|
|
392
|
+
Y : pd.Series
|
|
393
|
+
The y-axis data.
|
|
394
|
+
Z : pd.Series
|
|
395
|
+
The z-axis data.
|
|
396
|
+
xtitle : str, optional
|
|
397
|
+
The title for the x-axis, by default "DTE".
|
|
398
|
+
ytitle : str, optional
|
|
399
|
+
The title for the y-axis, by default "Strike".
|
|
400
|
+
ztitle : str, optional
|
|
401
|
+
The title for the z-axis, by default "IV".
|
|
402
|
+
colorscale : Union[str, list], optional
|
|
403
|
+
The colorscale to use for the surface, by default None.
|
|
404
|
+
title : str, optional
|
|
405
|
+
The title of the chart, by default None.
|
|
406
|
+
layout_kwargs : Optional[dict[str, Any]], optional
|
|
407
|
+
Additional keyword arguments to apply with figure.update_layout(), by default None.
|
|
408
|
+
|
|
409
|
+
Returns
|
|
410
|
+
-------
|
|
411
|
+
OpenBBFigure
|
|
412
|
+
The OpenBBFigure object.
|
|
413
|
+
"""
|
|
414
|
+
# pylint: disable=import-outside-toplevel
|
|
415
|
+
from openbb_charting.charts.generic_charts import surface3d
|
|
416
|
+
|
|
417
|
+
fig = surface3d(
|
|
418
|
+
X=X,
|
|
419
|
+
Y=Y,
|
|
420
|
+
Z=Z,
|
|
421
|
+
xtitle=xtitle,
|
|
422
|
+
ytitle=ytitle,
|
|
423
|
+
ztitle=ztitle,
|
|
424
|
+
colorscale=colorscale,
|
|
425
|
+
title=title,
|
|
426
|
+
layout_kwargs=layout_kwargs,
|
|
427
|
+
theme=theme,
|
|
428
|
+
)
|
|
429
|
+
fig = self._set_chart_style(fig)
|
|
430
|
+
return fig
|
|
431
|
+
|
|
372
432
|
def create_correlation_matrix(
|
|
373
433
|
self,
|
|
374
434
|
data: Union[
|
|
@@ -417,7 +477,6 @@ class Charting:
|
|
|
417
477
|
fig = self._set_chart_style(fig)
|
|
418
478
|
return fig
|
|
419
479
|
|
|
420
|
-
# pylint: disable=inconsistent-return-statements
|
|
421
480
|
def show(self, render: bool = True, **kwargs):
|
|
422
481
|
"""Display chart and save it to the OBBject."""
|
|
423
482
|
try:
|
|
@@ -435,24 +494,27 @@ class Charting:
|
|
|
435
494
|
kwargs["provider"] = self._obbject.provider
|
|
436
495
|
kwargs["extra"] = self._obbject.extra
|
|
437
496
|
fig, content = charting_function(**kwargs)
|
|
438
|
-
fig = self._set_chart_style(fig)
|
|
439
|
-
content = fig.show(external=True, **kwargs).to_plotly_json()
|
|
440
497
|
self._obbject.chart = Chart(fig=fig, content=content, format=self._format)
|
|
441
498
|
if render:
|
|
442
499
|
fig.show(**kwargs)
|
|
500
|
+
|
|
501
|
+
except (RuntimeError, OpenBBError) as e:
|
|
502
|
+
raise e from e
|
|
503
|
+
|
|
443
504
|
except Exception: # pylint: disable=W0718
|
|
444
505
|
try:
|
|
445
506
|
fig = self.create_line_chart(data=self._obbject.results, render=False, **kwargs) # type: ignore
|
|
446
|
-
fig = self._set_chart_style(fig)
|
|
507
|
+
fig = self._set_chart_style(fig) # type: ignore
|
|
447
508
|
content = fig.show(external=True, **kwargs).to_plotly_json() # type: ignore
|
|
448
509
|
self._obbject.chart = Chart(
|
|
449
510
|
fig=fig, content=content, format=self._format
|
|
450
511
|
)
|
|
451
512
|
if render:
|
|
452
|
-
|
|
513
|
+
fig.show(**kwargs) # type: ignore
|
|
453
514
|
except Exception as e:
|
|
454
515
|
raise RuntimeError(
|
|
455
516
|
"Failed to automatically create a generic chart with the data provided."
|
|
517
|
+
+ f" -> {e} -> {e.args}"
|
|
456
518
|
) from e
|
|
457
519
|
|
|
458
520
|
# pylint: disable=too-many-locals,inconsistent-return-statements
|
|
@@ -556,7 +618,7 @@ class Charting:
|
|
|
556
618
|
except Exception: # pylint: disable=W0718
|
|
557
619
|
try:
|
|
558
620
|
fig = self.create_line_chart(data=data_as_df, render=False, **kwargs)
|
|
559
|
-
fig = self._set_chart_style(fig)
|
|
621
|
+
fig = self._set_chart_style(fig) # type: ignore
|
|
560
622
|
content = fig.show(external=True, **kwargs).to_plotly_json() # type: ignore
|
|
561
623
|
self._obbject.chart = Chart(
|
|
562
624
|
fig=fig, content=content, format=self._format
|
|
@@ -590,11 +652,11 @@ class Charting:
|
|
|
590
652
|
new = "light" if current == "dark" else "dark"
|
|
591
653
|
self._charting_settings.chart_style = new
|
|
592
654
|
figure = self._obbject.chart.fig # type: ignore[union-attr]
|
|
593
|
-
updated_figure = self._set_chart_style(figure)
|
|
655
|
+
updated_figure = self._set_chart_style(figure) # type: ignore[union-attr]
|
|
594
656
|
self._obbject.chart.fig = updated_figure # type: ignore[union-attr]
|
|
595
657
|
self._obbject.chart.content = updated_figure.show( # type: ignore[union-attr]
|
|
596
658
|
external=True
|
|
597
|
-
).to_plotly_json()
|
|
659
|
+
).to_plotly_json() # type: ignore[union-attr]
|
|
598
660
|
|
|
599
661
|
@staticmethod
|
|
600
662
|
def _convert_to_string(x):
|
|
@@ -58,7 +58,7 @@ def line_chart( # noqa: PLR0912
|
|
|
58
58
|
raise ValueError("Error: Data is a required field.")
|
|
59
59
|
|
|
60
60
|
auto_layout = False
|
|
61
|
-
index = (
|
|
61
|
+
index = ( # type: ignore
|
|
62
62
|
data.index.name
|
|
63
63
|
if isinstance(data, (DataFrame, Series))
|
|
64
64
|
else index if index is not None else x if x is not None else "date"
|
|
@@ -88,11 +88,13 @@ def line_chart( # noqa: PLR0912
|
|
|
88
88
|
if found_index is False:
|
|
89
89
|
df.set_index(df.iloc[:, 0], inplace=True)
|
|
90
90
|
|
|
91
|
+
target = target if target else "close"
|
|
92
|
+
|
|
91
93
|
if "symbol" in df.columns and len(df.symbol.unique()) > 1:
|
|
92
|
-
df = df.pivot(columns="symbol", values=target
|
|
94
|
+
df = df.pivot(columns="symbol", values=target)
|
|
93
95
|
|
|
94
96
|
if "symbol" not in df.columns and target in df.columns:
|
|
95
|
-
df = df[[target]]
|
|
97
|
+
df = df[[target]] # type: ignore
|
|
96
98
|
|
|
97
99
|
y = y.split(",") if isinstance(y, str) else y
|
|
98
100
|
|
|
@@ -104,11 +106,11 @@ def line_chart( # noqa: PLR0912
|
|
|
104
106
|
auto_layout = False
|
|
105
107
|
|
|
106
108
|
if returns is True:
|
|
107
|
-
df = df.apply(calculate_returns)
|
|
109
|
+
df = df.apply(calculate_returns) # type: ignore
|
|
108
110
|
auto_layout = False
|
|
109
111
|
|
|
110
112
|
if normalize is True:
|
|
111
|
-
df = df.apply(z_score_standardization)
|
|
113
|
+
df = df.apply(z_score_standardization) # type: ignore
|
|
112
114
|
auto_layout = False
|
|
113
115
|
|
|
114
116
|
if layout_kwargs is None:
|
|
@@ -147,7 +149,7 @@ def line_chart( # noqa: PLR0912
|
|
|
147
149
|
sorted_columns = diff.sort_values(ascending=False).index
|
|
148
150
|
if sorted_columns is None or len(sorted_columns) == 0:
|
|
149
151
|
raise ValueError("Error: expected data with numeric values.")
|
|
150
|
-
df = df[sorted_columns]
|
|
152
|
+
df = df[sorted_columns] # type: ignore
|
|
151
153
|
|
|
152
154
|
for i, col in enumerate(df.columns):
|
|
153
155
|
|
|
@@ -459,7 +461,7 @@ def bar_chart( # noqa: PLR0912
|
|
|
459
461
|
"rgba(0,0,0,0)" if text_color == "white" else "rgba(255,255,255,0)"
|
|
460
462
|
),
|
|
461
463
|
plot_bgcolor=(
|
|
462
|
-
"rgba(0,0,0,0)" if text_color == "white" else "
|
|
464
|
+
"rgba(0,0,0,0)" if text_color == "white" else "rgba(255,255,255,0)"
|
|
463
465
|
),
|
|
464
466
|
legend=dict(
|
|
465
467
|
orientation="v",
|
|
@@ -480,8 +482,7 @@ def bar_chart( # noqa: PLR0912
|
|
|
480
482
|
),
|
|
481
483
|
ticklen=0,
|
|
482
484
|
showgrid=orientation == "h",
|
|
483
|
-
|
|
484
|
-
tickfont=dict(size=12),
|
|
485
|
+
tickfont=dict(size=12, family="sans-serif"),
|
|
485
486
|
categoryorder="array" if orientation == "v" else None,
|
|
486
487
|
categoryarray=bar_df.index if orientation == "v" else None,
|
|
487
488
|
),
|
|
@@ -589,20 +590,20 @@ def bar_increasing_decreasing( # pylint: disable=W0102
|
|
|
589
590
|
except Exception as e:
|
|
590
591
|
raise ValueError(f"Error: {e}") from e
|
|
591
592
|
|
|
592
|
-
if not increasing_data.empty:
|
|
593
|
+
if not increasing_data.empty: # type: ignore
|
|
593
594
|
figure.add_bar(
|
|
594
|
-
x=increasing_data.index if orientation == "v" else increasing_data,
|
|
595
|
-
y=increasing_data if orientation == "v" else increasing_data.index,
|
|
595
|
+
x=increasing_data.index if orientation == "v" else increasing_data, # type: ignore
|
|
596
|
+
y=increasing_data if orientation == "v" else increasing_data.index, # type: ignore
|
|
596
597
|
marker=dict(color=colors[0]),
|
|
597
598
|
orientation=orientation,
|
|
598
599
|
showlegend=False,
|
|
599
600
|
width=0.95 / len(keys) * 0.75 if barmode == "group" else 0.95,
|
|
600
601
|
hoverinfo="y" if orientation == "v" else "x",
|
|
601
602
|
)
|
|
602
|
-
if not decreasing_data.empty:
|
|
603
|
+
if not decreasing_data.empty: # type: ignore
|
|
603
604
|
figure.add_bar(
|
|
604
|
-
x=decreasing_data.index if orientation == "v" else decreasing_data,
|
|
605
|
-
y=decreasing_data if orientation == "v" else decreasing_data.index,
|
|
605
|
+
x=decreasing_data.index if orientation == "v" else decreasing_data, # type: ignore
|
|
606
|
+
y=decreasing_data if orientation == "v" else decreasing_data.index, # type: ignore
|
|
606
607
|
marker=dict(color=colors[1]),
|
|
607
608
|
orientation=orientation,
|
|
608
609
|
showlegend=False,
|
|
@@ -653,3 +654,172 @@ def bar_increasing_decreasing( # pylint: disable=W0102
|
|
|
653
654
|
)
|
|
654
655
|
|
|
655
656
|
return figure
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
def surface3d(
|
|
660
|
+
X: "Series",
|
|
661
|
+
Y: "Series",
|
|
662
|
+
Z: "Series",
|
|
663
|
+
xtitle: Optional[str] = "DTE",
|
|
664
|
+
ytitle: Optional[str] = "Strike",
|
|
665
|
+
ztitle: Optional[str] = "IV",
|
|
666
|
+
colorscale: Optional[Union[str, list]] = None,
|
|
667
|
+
title: Optional[str] = None,
|
|
668
|
+
layout_kwargs: Optional[dict[str, Any]] = None,
|
|
669
|
+
theme: Optional[Literal["dark", "light"]] = None,
|
|
670
|
+
) -> Union["OpenBBFigure", "Figure"]:
|
|
671
|
+
"""Create a 3D surface chart.
|
|
672
|
+
|
|
673
|
+
Parameters
|
|
674
|
+
----------
|
|
675
|
+
X : pd.Series
|
|
676
|
+
The x-axis data.
|
|
677
|
+
Y : pd.Series
|
|
678
|
+
The y-axis data.
|
|
679
|
+
Z : pd.Series
|
|
680
|
+
The z-axis data.
|
|
681
|
+
xtitle : str, optional
|
|
682
|
+
The title for the x-axis, by default "DTE".
|
|
683
|
+
ytitle : str, optional
|
|
684
|
+
The title for the y-axis, by default "Strike".
|
|
685
|
+
ztitle : str, optional
|
|
686
|
+
The title for the z-axis, by default "IV".
|
|
687
|
+
colorscale : Union[str, list], optional
|
|
688
|
+
The colorscale to use for the surface, by default None.
|
|
689
|
+
title : str, optional
|
|
690
|
+
The title of the chart, by default None.
|
|
691
|
+
layout_kwargs : Optional[dict[str, Any]], optional
|
|
692
|
+
Additional keyword arguments to apply with figure.update_layout(), by default None.
|
|
693
|
+
|
|
694
|
+
Returns
|
|
695
|
+
-------
|
|
696
|
+
OpenBBFigure
|
|
697
|
+
The OpenBBFigure object.
|
|
698
|
+
"""
|
|
699
|
+
# pylint: disable=import-outside-toplevel
|
|
700
|
+
from openbb_core.app.model.abstract.error import OpenBBError # noqa
|
|
701
|
+
from openbb_charting.core.openbb_figure import OpenBBFigure
|
|
702
|
+
from numpy import vstack
|
|
703
|
+
from scipy.spatial import Delaunay
|
|
704
|
+
import numpy as np
|
|
705
|
+
|
|
706
|
+
try:
|
|
707
|
+
points3D = vstack((X, Y, Z)).T
|
|
708
|
+
points2D = points3D[:, :2]
|
|
709
|
+
tri = Delaunay(points2D)
|
|
710
|
+
II, J, K = tri.simplices.T
|
|
711
|
+
except Exception as e:
|
|
712
|
+
raise OpenBBError(f"Not enough points to render 3D: {e}") from e
|
|
713
|
+
|
|
714
|
+
fig = OpenBBFigure(create_backend=False)
|
|
715
|
+
chart_style = ChartStyle()
|
|
716
|
+
if theme:
|
|
717
|
+
chart_style.plt_style = theme
|
|
718
|
+
fig.update_layout(chart_style.plotly_template.get("layout", {}))
|
|
719
|
+
text_color = "white" if chart_style.plt_style == "dark" else "black"
|
|
720
|
+
fig.set_title(f"{title if title and title != 'OpenBB Platform' else ''}")
|
|
721
|
+
fig_kwargs = dict(z=Z, x=X, y=Y, i=II, j=J, k=K, intensity=Z)
|
|
722
|
+
customdata = np.array([[xtitle, ytitle, ztitle]] * len(X))
|
|
723
|
+
|
|
724
|
+
fig.add_mesh3d(
|
|
725
|
+
**fig_kwargs,
|
|
726
|
+
alphahull=0,
|
|
727
|
+
opacity=1,
|
|
728
|
+
contour=dict(color="black", show=True, width=15),
|
|
729
|
+
colorscale=(
|
|
730
|
+
colorscale
|
|
731
|
+
if colorscale
|
|
732
|
+
else [
|
|
733
|
+
[0, "darkred"],
|
|
734
|
+
[0.001, "crimson"],
|
|
735
|
+
[0.005, "red"],
|
|
736
|
+
[0.0075, "orangered"],
|
|
737
|
+
[0.015, "darkorange"],
|
|
738
|
+
[0.025, "orange"],
|
|
739
|
+
[0.04, "goldenrod"],
|
|
740
|
+
[0.055, "gold"],
|
|
741
|
+
[0.11, "magenta"],
|
|
742
|
+
[0.15, "plum"],
|
|
743
|
+
[0.4, "lightblue"],
|
|
744
|
+
[0.7, "royalblue"],
|
|
745
|
+
[0.9, "blue"],
|
|
746
|
+
[1, "darkblue"],
|
|
747
|
+
]
|
|
748
|
+
),
|
|
749
|
+
colorbar=dict(
|
|
750
|
+
len=0.66,
|
|
751
|
+
y=0.5,
|
|
752
|
+
thickness=15,
|
|
753
|
+
),
|
|
754
|
+
customdata=customdata,
|
|
755
|
+
hovertemplate="<b>%{customdata[0]}</b>: %{x} <br>"
|
|
756
|
+
"<b>%{customdata[1]}</b>: %{y} <br>"
|
|
757
|
+
"<b>%{customdata[2]}</b>: %{z}<extra></extra>",
|
|
758
|
+
showscale=True,
|
|
759
|
+
flatshading=True,
|
|
760
|
+
lighting=dict(
|
|
761
|
+
ambient=0.95,
|
|
762
|
+
diffuse=0.9,
|
|
763
|
+
roughness=0.8,
|
|
764
|
+
specular=0.9,
|
|
765
|
+
fresnel=0.001,
|
|
766
|
+
vertexnormalsepsilon=0.0001,
|
|
767
|
+
facenormalsepsilon=0.0001,
|
|
768
|
+
),
|
|
769
|
+
)
|
|
770
|
+
fig.update_layout(
|
|
771
|
+
scene=dict(
|
|
772
|
+
xaxis=dict(
|
|
773
|
+
backgroundcolor="rgb(94, 94, 94)",
|
|
774
|
+
gridcolor="white",
|
|
775
|
+
showbackground=True,
|
|
776
|
+
zerolinecolor="white",
|
|
777
|
+
title=dict(text=xtitle if xtitle else "DTE", font=dict(size=18)),
|
|
778
|
+
autorange="reversed",
|
|
779
|
+
tickfont=dict(size=12),
|
|
780
|
+
),
|
|
781
|
+
yaxis=dict(
|
|
782
|
+
backgroundcolor="rgb(94, 94, 94)",
|
|
783
|
+
gridcolor="white",
|
|
784
|
+
showbackground=True,
|
|
785
|
+
zerolinecolor="white",
|
|
786
|
+
title=dict(text=ytitle if ytitle else "Strike", font=dict(size=18)),
|
|
787
|
+
tickfont=dict(size=12),
|
|
788
|
+
),
|
|
789
|
+
zaxis=dict(
|
|
790
|
+
backgroundcolor="rgb(94, 94, 94)",
|
|
791
|
+
gridcolor="white",
|
|
792
|
+
showbackground=True,
|
|
793
|
+
zerolinecolor="white",
|
|
794
|
+
title=dict(text=ztitle if ztitle else "IV", font=dict(size=18)),
|
|
795
|
+
tickfont=dict(size=12),
|
|
796
|
+
),
|
|
797
|
+
domain=dict(y=[0.0125, 0.95], x=[0.0125, 1]),
|
|
798
|
+
),
|
|
799
|
+
title_x=0.5,
|
|
800
|
+
title_y=0.98,
|
|
801
|
+
scene_camera=dict(
|
|
802
|
+
up=dict(x=0, y=0, z=0.75),
|
|
803
|
+
center=dict(x=-0.01, y=0, z=-0.3),
|
|
804
|
+
eye=dict(x=1.75, y=1.75, z=0.69),
|
|
805
|
+
),
|
|
806
|
+
paper_bgcolor=(
|
|
807
|
+
"rgba(21,21,21,1)" if text_color == "white" else "rgba(255,255,255,1)"
|
|
808
|
+
),
|
|
809
|
+
plot_bgcolor=(
|
|
810
|
+
"rgba(21,21,21,1)" if text_color == "white" else "rgba(255,255,255,1)"
|
|
811
|
+
),
|
|
812
|
+
font=dict(color=text_color),
|
|
813
|
+
# margin=dict(t=100, b=10, r=10, l=10),
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
fig.update_scenes(
|
|
817
|
+
aspectmode="manual",
|
|
818
|
+
aspectratio=dict(x=1.5, y=2.0, z=0.75),
|
|
819
|
+
dragmode="turntable",
|
|
820
|
+
)
|
|
821
|
+
|
|
822
|
+
if layout_kwargs:
|
|
823
|
+
fig.update_layout(layout_kwargs, overwrite=False)
|
|
824
|
+
|
|
825
|
+
return fig
|
|
@@ -38,7 +38,7 @@ def z_score_standardization(data: "Series") -> "Series":
|
|
|
38
38
|
|
|
39
39
|
def calculate_returns(data: "Series") -> "Series":
|
|
40
40
|
"""Calculate the returns of a column."""
|
|
41
|
-
return ((1 + data.pct_change().
|
|
41
|
+
return ((1 + data.pct_change(fill_method=None).fillna(0)).cumprod() - 1) * 100
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
def should_share_axis(
|