OpenBB Charting
Overview
The openbb-charting
extension provides elements for building and displaying interactive charts, tables, dashboards, and more, directly from the OpenBB Platform's Python Interface and FAST API.
It allows users to create a custom view, without any previous experience working with Plotly, from any response served by the OpenBB Platform.
The Python Interface includes a custom PyWry backend for displaying any content, in a WebKit HTML window served over localhost
. In an IDE setting, they will be rendered inline.
To install, follow the instructions here. The sections below provide a general explanation of the extension.
How Does It Work?
It works by extending the OBBject
class with a new attribute, charting
. When it is installed, every response from the OpenBB Platform will be equipped with these tools.
For functions that have pre-defined views, it serves as an intermediary between the user request and the response, activated when chart=True
. When a chart is created, it will populate the existing, chart
, attribute of the OBBject
. This is where it is served by the FAST API from the function request. In the Python Interface, charts can be generated post-request, regardless of chart=True
.
The chart
attribute in the OBBject contains three items, responses from the API have two:
fig
: The OpenBBFigure object - an extended Plotly GraphObjects class. Not included in the API response.content
: The Plotly JSON representation of the chart - Returned to the API.format
: The format of the chart - 'plotly' is currently the only charting library.
There is one OBBject class method, show()
, which will display the contents of the chart
attribute, if populated.
The new charting
attribute that binds to the OBBject also has a show()
method. This differs in that it overwrites the existing chart, effectively a 'reset' for the view.
The extension has a docstring, and it lists the class methods within charting
.
from openbb import obb
data = obb.equity.price.historical("AAPL")
data.charting?
Charting extension.
Methods
-------
show
Display chart and save it to the OBBject.
to_chart
Redraw the chart and save it to the OBBject, with an optional entry point for Data.
functions
Return a list of Platform commands with charting functions.
get_params
Return the charting parameters for the function the OBBject was created from.
indicators
Return the list of the available technical indicators to use with the `to_chart` method and OHLC+V data.
table
Display an interactive table.
create_line_chart
Create a line chart from external data.
create_bar_chart
Create a bar chart, on a single x-axis with one or more values for the y-axis, from external data.
When creating a chart directly from the OpenBB Platform endpoint, chart parameters must be passed as a nested dictionary under the name, chart_params
.
chart_params = dict(
title="AAPL 50/200 Day EMA",
indicators=dict(
ema=dict(length=[50,200]),
),
)
params = dict(
symbol="AAPL",
start_date="2022-01-01",
provider="yfinance",
chart=True,
chart_params=chart_params,
)
data = obb.equity.price.historical(**params)
chart_params
are sent in the body of the request when using the API.
Passing only chart=True
will return a default view which can be modified and drawn again post-request, via the OBBject
.
OBBject
id: 06614d74-7443-7201-8000-a65f358136a3
results: [{'date': datetime.date(2022, 1, 3), 'open': 177.8300018310547, 'high': 18...
provider: yfinance
warnings: None
chart: {'content': {'data': [{'close': [182.00999450683594, 179.6999969482422, 174....
extra: {'metadata': {'arguments': {'provider_choices': {'provider': 'yfinance'}, 's...
data.show()
No Render
The charts can be created without opening the PyWry window, and this is the default behaviour when chart=True
.
With the charting.show()
and charting.to_chart()
methods, the default is render=True
.
Setting as False
will return the chart to itself, populating the chart
attribute of OBBject.
What Endpoints Have Charts?
The OpenBB Platform router, open_api.json, function signatures, and documentation are all generated based on your specific configuration. When the openbb-charting
extension is installed, any function found in the "charting_router" adds chart: bool = False
to the command on build. For example, obb.index.price.historical?
Signature:
obb.index.price.historical(
symbol: Annotated[Union[str, List[str]], OpenBBCustomParameter(description='Symbol to get data for. Multiple comma separated items allowed for provider(s): cboe, fmp, intrinio, polygon, yfinance.')],
...
chart: typing.Annotated[bool, OpenBBCustomParameter(description='Whether to create a chart or not, by default False.')] = False,
**kwargs,
) -> openbb_core.app.model.obbject.OBBject
Charting Functions
The charting
attribute of every command output has methods for identifying the charting functions and parameters.
While able to serve JSON-serializable charts, the openbb-charting
extension is best-suited for use with the Python Interface. Much of the functionality is realized post-request.
Examine the extension by returning any command at all.
from openbb import obb
data = obb.equity.price.historical("SPY,QQQ,XLK,BTC-USD", provider="yfinance")
data.charting.functions()
['crypto_price_historical',
'currency_price_historical',
'economy_fred_series',
'equity_price_historical',
'equity_price_performance',
'etf_historical',
'etf_holdings',
'etf_price_performance',
'index_price_historical',
'technical_adx',
'technical_aroon',
'technical_cones',
'technical_ema',
'technical_hma',
'technical_macd',
'technical_rsi',
'technical_sma',
'technical_wma',
'technical_zlma']
The list above should, as shown here, should not be considered as the source of truth. It's just a sample.
If the OBBject
in question has a dedicated charting function associated with it, parameters are detailed by the get_params()
method.
EquityPriceHistoricalChartQueryParams
Parameters
----------
data : Union[Data, list[Data], NoneType]
Filtered versions of the data contained in the original `self.results`.
Columns should be the same as the original data.
Example use is to reduce the number of columns, or the length of data, to plot.
title : Union[str, NoneType]
Title of the chart.
target : Union[str, NoneType]
The specific column to target.
If supplied, this will override the candles and volume parameters.
multi_symbol : bool
Flag to indicate whether the data contains multiple symbols.
This is mostly handled automatically, but if the chart fails to generate try setting this to True.
same_axis : bool
If True, forces all data to be plotted on the same axis.
normalize : bool
If True, the data will be normalized and placed on the same axis.
returns : bool
If True, the cumulative returns for the length of the time series will be calculated and plotted.
candles : bool
If True, and OHLC exists, and there is only one symbol in the data, candles will be plotted.
heikin_ashi : bool
If True, and `candles=True`, Heikin Ashi candles will be plotted.
volume : bool
If True, and volume exists, and `candles=True`, volume will be plotted.
indicators : Union[ChartIndicators, dict[str, dict[str, Any]], NoneType]
Indicators to be plotted, formatted as a dictionary.
Data containing multiple symbols will ignore indicators.
Example:
indicators = dict(
sma=dict(length=[20,30,50]),
adx=dict(length=14),
rsi=dict(length=14),
)
Not all commands will have the same chart_params
, and some less than others, but it is always possible to redraw the chart with a different combination post-request. Here's what the default chart is from the output of the command above.
If chart=True
was not specified, it will need to be created.
data.charting.to_chart()
The extension recognized that multiple symbols were within the object, and made a determination to display cumulative returns by default.
A candlestick chart will draw only when there is one symbol in the data.
obb.equity.price.historical(
symbol="XLK",
start_date="2024-01-01",
provider="yfinance",
chart=True,
chart_params=dict(title="XLK YTD", heikin_ashi=True)
).show()
Endpoints Without Charts
Most functions do not have dedicated charts. However, it's still possible to generate one automatically. Using the data
above, we can try passing it through a quantitative analysis command.
data = obb.equity.price.historical(
symbol="XLK",
start_date="2023-01-01",
provider="yfinance",
)
qa = obb.quantitative.rolling.stdev(data.results, target="close")
qa.charting.show(title="XLK Rolling 21 Day Standard Deviation")
Charts From Any Data
There are methods for creating a generic chart from any external data. They will bypass any data contained in the parent object, unless specifically fed into itself.
- charting.create_bar_chart()
- charting.create_line_chart()
They can also be used as standalone components by initializing an empty instance of the OBBject class.
from openbb import obb
from openbb_core.app.model.obbject import OBBject
create_bar_chart = OBBject(results=None).charting.create_bar_chart
create_bar_chart?
Create a bar chart on a single x-axis with one or more values for the y-axis.
Parameters
----------
data : Union[list, dict, pd.DataFrame, List[pd.DataFrame], pd.Series, List[pd.Series], np.ndarray, Data]
Data to plot.
x : str
The x-axis column name.
y : Union[str, List[str]]
The y-axis column name(s).
barmode : Literal["group", "stack", "relative", "overlay"], optional
The bar mode, by default "group".
xtype : Literal["category", "multicategory", "date", "log", "linear"], optional
The x-axis type, by default "category".
title : Optional[str], optional
The title of the chart, by default None.
xtitle : Optional[str], optional
The x-axis title, by default None.
ytitle : Optional[str], optional
The y-axis title, by default None.
orientation : Literal["h", "v"], optional
The orientation of the chart, by default "v".
colors: Optional[List[str]], optional
Manually set the colors to cycle through for each column in 'y', by default None.
layout_kwargs : Optional[Dict[str, Any]], optional
Additional keyword arguments to apply with figure.update_layout(), by default None.
Returns
-------
OpenBBFigure
The OpenBBFigure object.
Tables
The openbb-charting
extension is equipped with interactive tables, utilizing the React framework. They are displayed by using the table
method.
data = obb.equity.price.quote("AAPL,MSFT,GOOGL,META,TSLA,AMZN", provider="yfinance")
data.charting.table()
External data can also be supplied, providing an opportunity to filter or apply Pandas operations before display.
new_df = df.to_df().T
new_df.index.name="metric"
new_df.columns = new_df.loc["symbol"]
new_df.drop("symbol", inplace=True)
data.charting.table(data=new_df)
This does not alter the contents of the original object, the displayed data is a copy.