Metadata-Version: 2.5
Name: openbb-charting
Version: 4.0.0
Summary: Charting extension for OpenBB
Project-URL: Homepage, https://openbb.co
Project-URL: Repository, https://github.com/OpenBB-finance/OpenBB
Author-email: OpenBB Team <hello@openbb.co>
License: Apache-2.0
Requires-Python: <4,>=3.10
Requires-Dist: openbb-core[pandas]>=2.0.0
Requires-Dist: pandas-ta-openbb>=0.4.24
Requires-Dist: plotly>=6.3.1
Provides-Extra: pywry
Requires-Dist: pywry>=2.0.4; extra == 'pywry'
Description-Content-Type: text/markdown

# OpenBB Charting

Plotly-based charting for the OpenBB Platform. Installing this package registers a `charting` accessor on every `OBBject` command result and enables the `chart=True` argument on Platform endpoints that have a chart.

## Installation

```bash
pip install openbb-charting
```

To display charts in a native desktop window, install the PyWry extra:

```bash
pip install "openbb-charting[pywry]"
```

On Linux, PyWry requires system WebKit/GTK libraries:

- Debian / Ubuntu / Mint: `sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev`
- Arch / Manjaro: `sudo pacman -S webkit2gtk`
- Fedora: `sudo dnf install gtk3-devel webkit2gtk3-devel`

## Usage

Pass `chart=True` to an endpoint that has a chart, then call `show()` on the result:

```python
from openbb import obb

data = obb.equity.price.historical("AAPL", provider="yfinance", chart=True)
data.show()
```

The same chart is reachable through the `charting` accessor on any result, without `chart=True`:

```python
res = obb.equity.price.historical("AAPL", provider="yfinance")
res.charting.show()
```

### Which commands have a chart

Charts are contributed by the installed extensions. List the registered routes:

```python
from openbb_charting import Charting

Charting.functions()
```

### Technical-analysis overlays — `to_chart`

`to_chart` rebuilds the chart of a time-series (OHLCV) result with indicator overlays. Indicators and their parameters are passed through the `indicators` argument:

```python
res = obb.equity.price.historical("AAPL", provider="yfinance")
res.charting.to_chart(
    indicators=dict(
        sma=dict(length=[20, 50]),
        rsi=dict(length=14),
        macd=dict(fast=12, slow=26, signal=9),
    )
)
res.show()
```

List every available indicator and its parameters:

```python
res.charting.indicators()  # from a result
Charting.indicators()  # standalone
```

## Building charts directly from data

The accessor exposes builders that accept a DataFrame or a list of `Data` (such as `OBBject.results`) and return an `OpenBBFigure`. Their input signatures differ; `create_line_chart` and `create_bar_chart` also display the chart by default — pass `render=False` to build it without displaying.

```python
res = obb.equity.price.historical("AAPL", provider="yfinance")
df = res.to_dataframe()

fig = res.charting.create_line_chart(data=res.results, target="close", render=False)
fig = res.charting.create_bar_chart(
    data=res.results, x="date", y="volume", render=False
)
fig = res.charting.create_correlation_matrix(data=res.results, method="pearson")
fig = res.charting.create_3d_surface(X=df["open"], Y=df["high"], Z=df["close"])
fig.show()
```

## Adding a chart to a command

Register a charting-view class through the `openbb_charting_extension` entry-point group in your `pyproject.toml`:

```toml
[project.entry-points."openbb_charting_extension"]
my_extension = "openbb_my_extension.my_extension_views:MyExtensionViews"
```

A view method is matched to an endpoint by replacing the route's slashes with underscores: `/equity/price/historical` → `equity_price_historical`, `/technical/ema` → `technical_ema`. Each method receives the command output as `**kwargs` and returns a `tuple[OpenBBFigure, dict[str, Any]]` — the interactive figure plus the JSON content the API serializes.

```python
"""Views for MyExtension."""

from typing import Any

from openbb_charting.charts.price_historical import price_historical
from openbb_charting.core.openbb_figure import OpenBBFigure


class MyExtensionViews:
    """MyExtension Views."""

    @staticmethod
    def my_extension_price_historical(**kwargs) -> tuple[OpenBBFigure, dict[str, Any]]:
        """My Extension Price Historical Chart."""
        return price_historical(**kwargs)
```

The chart is then produced by setting `chart=True` on the command, or via `result.charting.show()`.

## Replacing the engine, hooks, and backend

The Platform interfaces (Python, API, CLI, MCP) do not depend on `openbb-charting` by name; they resolve the active engine from whichever OBBject extension registers the `charting` accessor. Three things are pluggable through entry points alone.

### Replace the engine

Ship an OBBject extension that registers the `charting` accessor:

```toml
[project.entry-points."openbb_obbject_extension"]
my_charting = "openbb_my_charting:ext"   # ext = Extension(name="charting")
```

If `openbb-charting` is uninstalled, your engine is used automatically. When both are installed, select one with `system_settings.charting_extension` (or the `OPENBB_CHARTING_EXTENSION` environment variable). An engine must expose the `functions()` classmethod, and `get_backend_class()` to be usable from the CLI.

### Chart lifecycle hooks

Register a `ChartingHook` subclass under the `openbb_charting_hooks` group. Hooks run inside chart creation, so they fire for every interface:

```toml
[project.entry-points."openbb_charting_hooks"]
my_hook = "openbb_my_pkg.hooks:MyHook"
```

```python
from openbb_core.app.charting import ChartingHook


class MyHook(ChartingHook):
    """Watermark every figure after it is built."""

    routes = ()  # empty matches all routes
    priority = 100  # lower runs first

    def post_figure(self, context):
        context.figure.add_annotation(text="INTERNAL", opacity=0.1)
        return context
```

Stages: `resolve_data`, `pre_figure`, `post_figure`, `pre_render`, `post_render`. A hook mutates `context` in place and/or returns a new one.

### Backend override

Swap the rendering backend (PyWry / browser / custom) without replacing the engine, via the `openbb_charting_backend` group:

```toml
[project.entry-points."openbb_charting_backend"]
my_backend = "openbb_my_pkg.backend:MyBackend"
```

A backend is constructed with a single `charting_settings` argument. The override is opt-in: set `system_settings.charting_backend` (or `OPENBB_CHARTING_BACKEND`) to the registered name. Without a selection, the engine keeps its built-in backend.
