openbb-charting 2.0.2__tar.gz → 2.1.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.
Files changed (49) hide show
  1. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/PKG-INFO +4 -2
  2. openbb_charting-2.1.0/openbb_charting/__init__.py +553 -0
  3. openbb_charting-2.1.0/openbb_charting/charting_router.py +1294 -0
  4. openbb_charting-2.1.0/openbb_charting/core/__init__.py +1 -0
  5. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/backend.py +8 -2
  6. openbb_charting-2.1.0/openbb_charting/core/config/__init__.py +1 -0
  7. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/config/openbb_styles.py +53 -17
  8. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/dummy_backend.py +7 -5
  9. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/openbb_figure.py +17 -19
  10. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly.html +7 -7
  11. openbb_charting-2.1.0/openbb_charting/core/plotly_ta/__init__.py +1 -0
  12. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/base.py +4 -2
  13. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/data_classes.py +1 -1
  14. openbb_charting-2.1.0/openbb_charting/core/plotly_ta/plugins/__init__.py +1 -0
  15. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/plugins/custom_indicators_plugin.py +14 -11
  16. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/plugins/momentum_plugin.py +48 -45
  17. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/plugins/overlap_plugin.py +6 -3
  18. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/plugins/trend_indicators_plugin.py +4 -1
  19. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/plugins/volatility_plugin.py +8 -8
  20. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/plugins/volume_plugin.py +6 -3
  21. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/ta_class.py +102 -38
  22. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/plotly_ta/ta_helpers.py +3 -2
  23. openbb_charting-2.1.0/openbb_charting/core/table.html +326 -0
  24. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/to_chart.py +1 -2
  25. openbb_charting-2.1.0/openbb_charting/query_params.py +834 -0
  26. openbb_charting-2.1.0/openbb_charting/styles/__init__.py +1 -0
  27. openbb_charting-2.1.0/openbb_charting/styles/colors.py +39 -0
  28. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/styles/default/dark.pltstyle.json +33 -22
  29. openbb_charting-2.1.0/openbb_charting/styles/default/light.pltstyle.json +142 -0
  30. openbb_charting-2.1.0/openbb_charting/utils/generic_charts.py +606 -0
  31. openbb_charting-2.1.0/openbb_charting/utils/helpers.py +94 -0
  32. openbb_charting-2.1.0/openbb_charting/utils/relative_rotation.py +582 -0
  33. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/pyproject.toml +3 -2
  34. openbb_charting-2.0.2/openbb_charting/__init__.py +0 -214
  35. openbb_charting-2.0.2/openbb_charting/charting_router.py +0 -538
  36. openbb_charting-2.0.2/openbb_charting/core/__init__.py +0 -0
  37. openbb_charting-2.0.2/openbb_charting/core/config/__init__.py +0 -0
  38. openbb_charting-2.0.2/openbb_charting/core/plotly_ta/__init__.py +0 -0
  39. openbb_charting-2.0.2/openbb_charting/core/table.html +0 -2159
  40. openbb_charting-2.0.2/openbb_charting/query_params.py +0 -105
  41. openbb_charting-2.0.2/openbb_charting/styles/default/light.pltstyle.json +0 -871
  42. openbb_charting-2.0.2/openbb_charting/utils/helpers.py +0 -21
  43. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/README.md +0 -0
  44. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/builder.py +0 -0
  45. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/assets/Terminal_icon.png +0 -0
  46. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/assets/plotly-2.24.2.min.js +0 -0
  47. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/core/chart_style.py +0 -0
  48. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/styles/default/tables.pltstyle.json +0 -0
  49. {openbb_charting-2.0.2 → openbb_charting-2.1.0}/openbb_charting/utils/__init__.py +0 -0
@@ -1,17 +1,19 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openbb-charting
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: Charting extension for OpenBB
5
+ License: AGPL-3.0-only
5
6
  Author: OpenBB Team
6
7
  Author-email: hello@openbb.co
7
8
  Requires-Python: >=3.8,<3.12
9
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
8
10
  Classifier: Programming Language :: Python :: 3
9
11
  Classifier: Programming Language :: Python :: 3.8
10
12
  Classifier: Programming Language :: Python :: 3.9
11
13
  Classifier: Programming Language :: Python :: 3.10
12
14
  Classifier: Programming Language :: Python :: 3.11
13
15
  Requires-Dist: nbformat (>=5.9.2,<6.0.0)
14
- Requires-Dist: openbb-core (>=1.1.5,<2.0.0)
16
+ Requires-Dist: openbb-core (>=1.2.1,<2.0.0)
15
17
  Requires-Dist: pandas-ta (>=0.3.14b,<0.4.0)
16
18
  Requires-Dist: plotly (>=5.17.0,<6.0.0)
17
19
  Requires-Dist: pywry (>=0.6.1,<0.7.0)
@@ -0,0 +1,553 @@
1
+ """OpenBB OBBject extension for charting."""
2
+
3
+ # pylint: disable=too-many-arguments,unused-argument
4
+
5
+ import warnings
6
+ from typing import (
7
+ Any,
8
+ Callable,
9
+ Dict,
10
+ List,
11
+ Literal,
12
+ Optional,
13
+ Tuple,
14
+ Union,
15
+ )
16
+ from warnings import warn
17
+
18
+ import numpy as np
19
+ import pandas as pd
20
+ from openbb_core.app.model.charts.chart import Chart
21
+ from openbb_core.app.model.extension import Extension
22
+ from openbb_core.app.model.obbject import OBBject
23
+ from openbb_core.app.utils import basemodel_to_df, convert_to_basemodel
24
+ from openbb_core.provider.abstract.data import Data
25
+ from plotly.graph_objs import Figure
26
+
27
+ from openbb_charting import charting_router
28
+ from openbb_charting.core.backend import Backend, create_backend, get_backend
29
+ from openbb_charting.core.openbb_figure import OpenBBFigure
30
+ from openbb_charting.query_params import ChartParams, IndicatorsParams
31
+ from openbb_charting.utils.generic_charts import bar_chart, line_chart
32
+ from openbb_charting.utils.helpers import get_charting_functions
33
+
34
+ warnings.filterwarnings(
35
+ "ignore", category=UserWarning, module="openbb_core.app.model.extension", lineno=47
36
+ )
37
+
38
+ ext = Extension(name="charting", description="Create custom charts from OBBject data.")
39
+
40
+
41
+ @ext.obbject_accessor
42
+ class Charting:
43
+ """Charting extension.
44
+
45
+ Methods
46
+ -------
47
+ show
48
+ Display chart and save it to the OBBject.
49
+ to_chart
50
+ Redraw the chart and save it to the OBBject, with an optional entry point for Data.
51
+ functions
52
+ Return a list of Platform commands with charting functions.
53
+ get_params
54
+ Return the charting parameters for the function the OBBject was created from.
55
+ indicators
56
+ Return the list of the available technical indicators to use with the `to_chart` method and OHLC+V data.
57
+ table
58
+ Display an interactive table.
59
+ create_line_chart
60
+ Create a line chart from external data.
61
+ create_bar_chart
62
+ Create a bar chart, on a single x-axis with one or more values for the y-axis, from external data.
63
+ toggle_chart_style
64
+ Toggle the chart style, of an existing chart, between light and dark mode.
65
+ """
66
+
67
+ def __init__(self, obbject):
68
+ """Initialize Charting extension."""
69
+ # pylint: disable=import-outside-toplevel
70
+ from openbb_core.app.model.charts.charting_settings import ChartingSettings
71
+
72
+ self._obbject: OBBject = obbject
73
+ self._charting_settings = ChartingSettings(
74
+ user_settings=self._obbject._user_settings, # type: ignore
75
+ system_settings=self._obbject._system_settings, # type: ignore
76
+ )
77
+ self._backend: Backend = self._handle_backend()
78
+
79
+ @classmethod
80
+ def indicators(cls):
81
+ """Return an instance of the IndicatorsParams class, containing all available indicators and their parameters.
82
+
83
+ Without assigning to a variable, it will print the the information to the console.
84
+ """
85
+ return IndicatorsParams()
86
+
87
+ @classmethod
88
+ def functions(cls):
89
+ """Return a list of the available functions."""
90
+ return get_charting_functions()
91
+
92
+ def _handle_backend(self) -> Backend:
93
+ """Create and start the backend."""
94
+ create_backend(self._charting_settings)
95
+ backend = get_backend()
96
+ backend.start(debug=self._charting_settings.debug_mode)
97
+ return backend
98
+
99
+ @staticmethod
100
+ def _get_chart_function(route: str) -> Callable:
101
+ """Given a route, it returns the chart function. The module must contain the given route."""
102
+ if route is None:
103
+ raise ValueError("OBBject was initialized with no function route.")
104
+ adjusted_route = route.replace("/", "_")[1:]
105
+ return getattr(charting_router, adjusted_route)
106
+
107
+ def get_params(self) -> ChartParams:
108
+ """Return the ChartQueryParams class for the function the OBBject was created from.
109
+
110
+ Without assigning to a variable, it will print the docstring to the console.
111
+ """
112
+ if self._obbject._route is None: # pylint: disable=protected-access
113
+ raise ValueError("OBBject was initialized with no function route.")
114
+ charting_function = (
115
+ self._obbject._route # pylint: disable=protected-access
116
+ ).replace("/", "_")[1:]
117
+ if hasattr(ChartParams, charting_function):
118
+ return getattr(ChartParams, charting_function)()
119
+ raise ValueError(
120
+ f"Error: No chart parameters are defined for the route: {charting_function}"
121
+ )
122
+
123
+ def _prepare_data_as_df(
124
+ self, data: Optional[Union[pd.DataFrame, pd.Series]]
125
+ ) -> Tuple[pd.DataFrame, bool]:
126
+ """Convert supplied data to a DataFrame."""
127
+ has_data = (
128
+ isinstance(data, (Data, pd.DataFrame, pd.Series)) and not data.empty # type: ignore
129
+ ) or (bool(data))
130
+ index = (
131
+ data.index.name
132
+ if has_data and isinstance(data, (pd.DataFrame, pd.Series))
133
+ else None
134
+ )
135
+ data_as_df: pd.DataFrame = (
136
+ basemodel_to_df(convert_to_basemodel(data), index=index)
137
+ if has_data
138
+ else self._obbject.to_dataframe(index=index)
139
+ )
140
+ if "date" in data_as_df.columns:
141
+ data_as_df = data_as_df.set_index("date")
142
+ if "provider" in data_as_df.columns:
143
+ data_as_df.drop(columns="provider", inplace=True)
144
+ return data_as_df, has_data
145
+
146
+ # pylint: disable=too-many-locals
147
+ def create_line_chart(
148
+ self,
149
+ data: Union[
150
+ list,
151
+ dict,
152
+ pd.DataFrame,
153
+ List[pd.DataFrame],
154
+ pd.Series,
155
+ List[pd.Series],
156
+ np.ndarray,
157
+ Data,
158
+ ],
159
+ index: Optional[str] = None,
160
+ target: Optional[str] = None,
161
+ title: Optional[str] = None,
162
+ x: Optional[str] = None,
163
+ xtitle: Optional[str] = None,
164
+ y: Optional[Union[str, List[str]]] = None,
165
+ ytitle: Optional[str] = None,
166
+ y2: Optional[Union[str, List[str]]] = None,
167
+ y2title: Optional[str] = None,
168
+ layout_kwargs: Optional[dict] = None,
169
+ scatter_kwargs: Optional[dict] = None,
170
+ normalize: bool = False,
171
+ returns: bool = False,
172
+ same_axis: bool = False,
173
+ render: bool = True,
174
+ **kwargs,
175
+ ) -> Union[OpenBBFigure, Figure, None]:
176
+ """Create a line chart from external data and render a chart or return the OpenBBFigure.
177
+
178
+ Parameters
179
+ ----------
180
+ data : Union[Data, pd.DataFrame, pd.Series]
181
+ Data to be plotted (OHLCV data).
182
+ index : Optional[str], optional
183
+ Index column, by default None
184
+ target : Optional[str], optional
185
+ Target column to be plotted, by default None
186
+ title : Optional[str], optional
187
+ Chart title, by default None
188
+ x : Optional[str], optional
189
+ X-axis column, by default None
190
+ xtitle : Optional[str], optional
191
+ X-axis title, by default None
192
+ y : Optional[Union[str, List[str]]], optional
193
+ Y-axis column(s), by default None
194
+ If None are supplied, the layout is optimized for the contents of data.
195
+ Where many units/scales are present,
196
+ it will attempt to divide based on the range of values.
197
+ ytitle : Optional[str], optional
198
+ Y-axis title, by default None
199
+ y2 : Optional[Union[str, List[str]]], optional
200
+ Y2-axis column(s), by default None
201
+ y2title : Optional[str], optional
202
+ Y2-axis title, by default None
203
+ layout_kwargs : Optional[dict], optional
204
+ Additional Plotly Layout parameters for `fig.update_layout`, by default None
205
+ scatter_kwargs : Optional[dict], optional
206
+ Additional Plotly parameters applied on creation of each scatter plot, by default None
207
+ normalize : bool, optional
208
+ Normalize the data with Z-Score Standardization, by default False
209
+ returns : bool, optional
210
+ Convert the data to cumulative returns, by default False
211
+ same_axis: bool, optional
212
+ If True, forces all data onto the same Y-axis, by default False
213
+ render: bool, optional
214
+ If True, the chart will be rendered, by default True
215
+ **kwargs: Dict[str, Any]
216
+ Extra parameters to be passed to `figure.show()`
217
+ """
218
+ fig = line_chart(
219
+ data=data,
220
+ index=index,
221
+ target=target,
222
+ title=title,
223
+ x=x,
224
+ xtitle=xtitle,
225
+ y=y,
226
+ ytitle=ytitle,
227
+ y2=y2,
228
+ y2title=y2title,
229
+ layout_kwargs=layout_kwargs,
230
+ scatter_kwargs=scatter_kwargs,
231
+ normalize=normalize,
232
+ returns=returns,
233
+ same_axis=same_axis,
234
+ **kwargs,
235
+ )
236
+ fig = self._set_chart_style(fig)
237
+ if render:
238
+ return fig.show(**kwargs)
239
+
240
+ return fig
241
+
242
+ def create_bar_chart(
243
+ self,
244
+ data: Union[
245
+ list,
246
+ dict,
247
+ pd.DataFrame,
248
+ List[pd.DataFrame],
249
+ pd.Series,
250
+ List[pd.Series],
251
+ np.ndarray,
252
+ Data,
253
+ ],
254
+ x: str,
255
+ y: Union[str, List[str]],
256
+ barmode: Literal["group", "stack", "relative", "overlay"] = "group",
257
+ xtype: Literal[
258
+ "category", "multicategory", "date", "log", "linear"
259
+ ] = "category",
260
+ title: Optional[str] = None,
261
+ xtitle: Optional[str] = None,
262
+ ytitle: Optional[str] = None,
263
+ orientation: Literal["h", "v"] = "v",
264
+ colors: Optional[List[str]] = None,
265
+ layout_kwargs: Optional[Dict[str, Any]] = None,
266
+ bar_kwargs: Optional[Dict[str, Any]] = None,
267
+ render: bool = True,
268
+ **kwargs,
269
+ ) -> Union[OpenBBFigure, Figure, None]:
270
+ """Create a bar chart on a single x-axis with one or more values for the y-axis.
271
+
272
+ Parameters
273
+ ----------
274
+ data : Union[list, dict, pd.DataFrame, List[pd.DataFrame], pd.Series, List[pd.Series], np.ndarray, Data]
275
+ Data to plot.
276
+ x : str
277
+ The x-axis column name.
278
+ y : Union[str, List[str]]
279
+ The y-axis column name(s).
280
+ barmode : Literal["group", "stack", "relative", "overlay"], optional
281
+ The bar mode, by default "group".
282
+ xtype : Literal["category", "multicategory", "date", "log", "linear"], optional
283
+ The x-axis type, by default "category".
284
+ title : str, optional
285
+ The title of the chart, by default None.
286
+ xtitle : str, optional
287
+ The x-axis title, by default None.
288
+ ytitle : str, optional
289
+ The y-axis title, by default None.
290
+ colors: List[str], optional
291
+ Manually set the colors to cycle through for each column in 'y', by default None.
292
+ bar_kwargs : Dict[str, Any], optional
293
+ Additional keyword arguments to apply with figure.add_bar(), by default None.
294
+ layout_kwargs : Dict[str, Any], optional
295
+ Additional keyword arguments to apply with figure.update_layout(), by default None.
296
+ Returns
297
+ -------
298
+ OpenBBFigure
299
+ The OpenBBFigure object.
300
+ """
301
+ fig = bar_chart(
302
+ data=data,
303
+ x=x,
304
+ y=y,
305
+ barmode=barmode,
306
+ xtype=xtype,
307
+ title=title,
308
+ xtitle=xtitle,
309
+ ytitle=ytitle,
310
+ orientation=orientation,
311
+ colors=colors,
312
+ bar_kwargs=bar_kwargs,
313
+ layout_kwargs=layout_kwargs,
314
+ )
315
+ fig = self._set_chart_style(fig)
316
+ if render:
317
+ return fig.show(**kwargs)
318
+
319
+ return fig
320
+
321
+ # pylint: disable=inconsistent-return-statements
322
+ def show(self, render: bool = True, **kwargs):
323
+ """Display chart and save it to the OBBject."""
324
+ try:
325
+ charting_function = self._get_chart_function(
326
+ self._obbject._route # pylint: disable=protected-access
327
+ )
328
+ kwargs["obbject_item"] = self._obbject.results
329
+ kwargs["charting_settings"] = self._charting_settings
330
+ if (
331
+ hasattr(self._obbject, "_standard_params")
332
+ and self._obbject._standard_params # pylint: disable=protected-access
333
+ ):
334
+ kwargs["standard_params"] = (
335
+ self._obbject._standard_params.__dict__ # pylint: disable=protected-access
336
+ )
337
+ kwargs["provider"] = (
338
+ self._obbject.provider
339
+ ) # pylint: disable=protected-access
340
+ kwargs["extra"] = self._obbject.extra # pylint: disable=protected-access
341
+
342
+ if "kwargs" in kwargs:
343
+ _kwargs = kwargs.pop("kwargs")
344
+ kwargs.update(_kwargs.get("chart_params", {}))
345
+ fig, content = charting_function(**kwargs)
346
+ fig = self._set_chart_style(fig)
347
+ content = fig.show(external=True, **kwargs).to_plotly_json()
348
+ self._obbject.chart = Chart(
349
+ fig=fig, content=content, format=charting_router.CHART_FORMAT
350
+ )
351
+ if render:
352
+ fig.show(**kwargs)
353
+ except Exception: # pylint: disable=W0718
354
+ try:
355
+ fig = self.create_line_chart(data=self._obbject.results, render=False, **kwargs) # type: ignore
356
+ fig = self._set_chart_style(fig)
357
+ content = fig.show(external=True, **kwargs).to_plotly_json() # type: ignore
358
+ self._obbject.chart = Chart(
359
+ fig=fig, content=content, format=charting_router.CHART_FORMAT
360
+ )
361
+ if render:
362
+ return fig.show(**kwargs) # type: ignore
363
+ except Exception as e:
364
+ raise RuntimeError(
365
+ "Failed to automatically create a generic chart with the data provided."
366
+ ) from e
367
+
368
+ # pylint: disable=too-many-locals,inconsistent-return-statements
369
+ def to_chart(
370
+ self,
371
+ data: Optional[
372
+ Union[
373
+ list,
374
+ dict,
375
+ pd.DataFrame,
376
+ List[pd.DataFrame],
377
+ pd.Series,
378
+ List[pd.Series],
379
+ np.ndarray,
380
+ Data,
381
+ ]
382
+ ] = None,
383
+ target: Optional[str] = None,
384
+ index: Optional[str] = None,
385
+ indicators: Optional[Dict[str, Dict[str, Any]]] = None,
386
+ symbol: str = "",
387
+ candles: bool = True,
388
+ volume: bool = True,
389
+ volume_ticks_x: int = 7,
390
+ render: bool = True,
391
+ **kwargs,
392
+ ):
393
+ """Create an OpenBBFigure with user customizations (if any) and save it to the OBBject.
394
+
395
+ This function is used to populate, or re-populate, the OBBject with a chart using the data within
396
+ the OBBject or external data supplied via the `data` parameter.
397
+ This function modifies the original OBBject by overwriting the existing chart.
398
+
399
+ Parameters
400
+ ----------
401
+ data : Union[Data, pd.DataFrame, pd.Series]
402
+ Data to be plotted.
403
+ indicators : Dict[str, Dict[str, Any]], optional
404
+ Indicators to be plotted, by default None
405
+ symbol : str, optional
406
+ Symbol to be plotted. This is used for labels and titles, by default ""
407
+ candles : bool, optional
408
+ If True, candles will be plotted, by default True
409
+ volume : bool, optional
410
+ If True, volume will be plotted, by default True
411
+ volume_ticks_x : int, optional
412
+ Volume ticks, by default 7
413
+ render : bool, optional
414
+ If True, the chart will be rendered, by default True
415
+ kwargs: Dict[str, Any]
416
+ Extra parameters to be passed to the chart constructor.
417
+
418
+ Examples
419
+ --------
420
+ Plotting a time series with TA indicators
421
+
422
+ >>> from openbb import obb
423
+ >>> res = obb.equity.price.historical("AAPL")
424
+ >>> indicators = dict(
425
+ >>> sma=dict(length=[20,30,50]),
426
+ >>> adx=dict(length=14),
427
+ >>> rsi=dict(length=14),
428
+ >>> macd=dict(fast=12, slow=26, signal=9),
429
+ >>> bbands=dict(length=20, std=2),
430
+ >>> stoch=dict(length=14),
431
+ >>> ema=dict(length=[20,30,50]),
432
+ >>> )
433
+ >>> res.charting.to_chart(**{"indicators": indicators})
434
+
435
+ Get all the available indicators
436
+
437
+ >>> res = obb.equity.price.historical("AAPL")
438
+ >>> indicators = res.charting.indicators()
439
+ >>> indicators?
440
+ """
441
+ data_as_df, has_data = self._prepare_data_as_df(data) # type: ignore
442
+ if target is not None:
443
+ data_as_df = data_as_df[[target]]
444
+ kwargs["candles"] = candles
445
+ kwargs["volume"] = volume
446
+ kwargs["volume_ticks_x"] = volume_ticks_x
447
+ kwargs["indicators"] = indicators if indicators else {}
448
+ kwargs["symbol"] = symbol
449
+ kwargs["target"] = target
450
+ kwargs["index"] = index
451
+ kwargs["obbject_item"] = self._obbject.results
452
+ kwargs["charting_settings"] = self._charting_settings
453
+ if (
454
+ hasattr(self._obbject, "_standard_params")
455
+ and self._obbject._standard_params # pylint: disable=protected-access
456
+ ):
457
+ kwargs["standard_params"] = (
458
+ self._obbject._standard_params.__dict__ # pylint: disable=protected-access
459
+ )
460
+ kwargs["provider"] = self._obbject.provider # pylint: disable=protected-access
461
+ kwargs["extra"] = self._obbject.extra # pylint: disable=protected-access
462
+ if "kwargs" in kwargs:
463
+ _kwargs = kwargs.pop("kwargs")
464
+ kwargs.update(_kwargs.get("chart_params", {}))
465
+ try:
466
+ if has_data:
467
+ self.show(data=data_as_df, render=render, **kwargs)
468
+ else:
469
+ self.show(**kwargs, render=render)
470
+ except Exception: # pylint: disable=W0718
471
+ try:
472
+ fig = self.create_line_chart(data=data_as_df, render=False, **kwargs)
473
+ fig = self._set_chart_style(fig)
474
+ content = fig.show(external=True, **kwargs).to_plotly_json() # type: ignore
475
+ self._obbject.chart = Chart(
476
+ fig=fig, content=content, format=charting_router.CHART_FORMAT
477
+ )
478
+ if render:
479
+ return fig.show(**kwargs) # type: ignore
480
+ except Exception as e: # pylint: disable=W0718
481
+ raise RuntimeError(
482
+ "Failed to automatically create a generic chart with the data provided."
483
+ ) from e
484
+
485
+ def _set_chart_style(self, figure: Figure):
486
+ """Set the user preference for light or dark mode."""
487
+ style = self._charting_settings.chart_style # pylint: disable=protected-access
488
+ font_color = "black" if style == "light" else "white"
489
+ paper_bgcolor = "white" if style == "light" else "black"
490
+ figure = figure.update_layout(
491
+ dict( # pylint: disable=R1735
492
+ font_color=font_color, paper_bgcolor=paper_bgcolor
493
+ )
494
+ )
495
+ return figure
496
+
497
+ def toggle_chart_style(self): # pylint: disable=protected-access
498
+ """Toggle the chart style between light and dark mode."""
499
+ if not hasattr(self._obbject.chart, "fig"):
500
+ raise ValueError(
501
+ "Error: No chart has been created. Please create a chart first."
502
+ )
503
+ current = self._charting_settings.chart_style
504
+ new = "light" if current == "dark" else "dark"
505
+ self._charting_settings.chart_style = new
506
+ figure = self._obbject.chart.fig # type: ignore[union-attr]
507
+ updated_figure = self._set_chart_style(figure)
508
+ self._obbject.chart.fig = updated_figure # type: ignore[union-attr]
509
+ self._obbject.chart.content = updated_figure.show( # type: ignore[union-attr]
510
+ external=True
511
+ ).to_plotly_json()
512
+
513
+ def table(
514
+ self,
515
+ data: Optional[Union[pd.DataFrame, pd.Series]] = None,
516
+ title: str = "",
517
+ ):
518
+ """Display an interactive table.
519
+
520
+ Parameters
521
+ ----------
522
+ data : Optional[Union[pd.DataFrame, pd.Series]], optional
523
+ Data to be plotted, by default None.
524
+ If no data is provided the OBBject results will be used.
525
+ title : str, optional
526
+ Title of the table, by default "".
527
+ """
528
+ data_as_df, _ = self._prepare_data_as_df(data)
529
+ if isinstance(data_as_df.index, pd.RangeIndex):
530
+ data_as_df.reset_index(inplace=True, drop=True)
531
+ else:
532
+ data_as_df.reset_index(inplace=True)
533
+ if self._backend.isatty:
534
+ try:
535
+ self._backend.send_table(
536
+ df_table=data_as_df,
537
+ title=title
538
+ or self._obbject._route, # pylint: disable=protected-access
539
+ theme=self._charting_settings.table_style,
540
+ )
541
+ except Exception as e: # pylint: disable=W0718
542
+ warn(f"Failed to show figure with backend. {e}")
543
+
544
+ else:
545
+ from plotly import ( # pylint:disable=import-outside-toplevel
546
+ optional_imports,
547
+ )
548
+
549
+ ipython_display = optional_imports.get_module("IPython.display")
550
+ if ipython_display:
551
+ ipython_display.display(ipython_display.HTML(data_as_df.to_html()))
552
+ else:
553
+ warn("IPython.display is not available.")