-
Notifications
You must be signed in to change notification settings - Fork 44
Plugins in chart.py
chart.py supports custom chart indicators through plugins.
A plugin is a small Python file inside renderer/plugins/ that calculates an indicator and adds it to the chart.
Plugins are enabled from the user configuration file:
defs/user.json
Once enabled, each plugin becomes a command-line option such as:
python chart.py --sym RELIANCE --rsiThe project already includes these plugin files:
renderer/plugins/rsi.py
renderer/plugins/atr.py
renderer/plugins/macd.py
renderer/plugins/bollinger_bands.py
renderer/plugins/supertrend.py
To enable them, add a CHART_PLUGINS block to defs/user.json.
If defs/user.json already has a CHART_PLUGINS section, merge these entries into it. Do not delete unrelated plugins.
Note: In practice, only include plugins you actually need in daily analysis.
{
"CHART_PLUGINS": {
"RSI": {
"name": "rsi",
"option": "rsi",
"help": "Add RSI indicator.",
"lookback": 100,
"panel": {
"kind": "lower",
"axes": 1,
"share": true,
"preferred_axis": "any",
"allow_volume_panel": true
},
"period": 14,
"source": "Close",
"line_color": "#0F766E",
"overbought": 70,
"oversold": 30,
"overbought_color": "#64748B",
"oversold_color": "#64748B"
},
"ATR": {
"name": "atr",
"option": "atr",
"help": "Add ATR indicator.",
"lookback": 100,
"panel": {
"kind": "lower",
"axes": 1,
"share": true,
"preferred_axis": "any",
"allow_volume_panel": true
},
"period": 14,
"line_color": "firebrick",
"width": 1.5,
"ylabel": "ATR"
},
"MACD": {
"name": "macd",
"option": "macd",
"help": "Add MACD indicator.",
"lookback": 100,
"panel": {
"kind": "lower",
"axes": 2,
"share": false
},
"source": "Close",
"fastlen": 12,
"slowlen": 26,
"siglen": 9,
"line_color": "royalblue",
"signal_color": "red",
"hist_positive_color": "darkgray",
"hist_negative_color": "darkgray"
},
"BOLLINGER_BANDS": {
"name": "bollinger_bands",
"option": "bb",
"help": "Add Bollinger Bands.",
"lookback": 100,
"panel": {
"kind": "price"
},
"source": "Close",
"length": 20,
"mult": 2.0,
"basis_color": "dodgerblue",
"upper_color": "gray",
"lower_color": "gray",
"basis_width": 1.2,
"band_width": 1.0
},
"SUPERTREND": {
"name": "supertrend",
"option": "supertrend",
"help": "Add Supertrend indicator.",
"lookback": 100,
"panel": {
"kind": "price"
},
"factor": 3,
"atr_length": 10,
"up_color": "mediumseagreen",
"down_color": "crimson",
"width": 1.2
}
}
}python chart.py --sym RELIANCE --rsipython chart.py --sym RELIANCE --rsi --macdpython chart.py --sym RELIANCE --tf w -volume --rsiEach plugin entry in defs/user.json has an option field.
Example:
"option": "rsi"This creates the command-line flag:
--rsiAnother example:
"option": "bb"This creates:
--bbThe name field must match the Python file name inside renderer/plugins/, without .py.
Example:
"name": "bollinger_bands"This loads:
renderer/plugins/bollinger_bands.py
A chart has one main price panel and optional lower panels.
The main price panel is always:
Panel 0
Lower panels start at:
Panel 1
A plugin can be placed in one of three ways:
- On the price chart
- In a lower panel that may share space with another indicator
- In its own lower panel
Use a price panel when the indicator belongs directly on the candles.
Examples:
Bollinger Bands
Supertrend
VWAP
Moving averages
Donchian Channels
Keltner Channels
Configuration:
"panel": {
"kind": "price"
}This tells chart.py to plot the plugin on the main candle chart.
Equivalent values are:
price
main
overlay
Use this style when the indicator uses the same price scale as the candles.
Use a lower panel when the indicator has its own scale.
Examples:
RSI
ATR
MACD
Stochastic
ADX
Momentum oscillators
A lower panel plugin may either share a panel or take its own panel.
A shareable lower panel is suitable for simple indicators, usually one line on one scale.
Example:
"panel": {
"kind": "lower",
"axes": 1,
"share": true,
"preferred_axis": "any",
"allow_volume_panel": true
}This means:
kind: lower
Place the plugin below the price chart.
axes: 1
The plugin needs one y-axis.
share: true
The plugin can share a panel with another compatible indicator.
preferred_axis: any
The plugin can use either the left or right y-axis.
allow_volume_panel: true
The plugin may share the volume panel if volume is enabled and space is available.
This is a good fit for RSI, ATR, or a simple momentum line.
Some indicators should get their own panel.
Use this when the indicator has multiple parts or when sharing would make the chart hard to read.
Example:
"panel": {
"kind": "lower",
"axes": 2,
"share": false
}This is a good fit for MACD because MACD has:
MACD line
Signal line
Histogram
The MACD plugin uses both axes internally: one for the lines and one for the histogram.
chart.py automatically decides panel numbers at runtime.
The allocation order is:
- Volume
- Volume moving averages
- Built-in RS indicators
- Plugins
If --volume is used, volume is always assigned to panel 1.
python chart.py --sym RELIANCE --volumePanel layout:
Panel 0: Price
Panel 1: Volume
If --vol-sma is used with --volume, the volume moving average is drawn on the volume panel.
python chart.py --sym RELIANCE --volume --vol-sma 20Panel layout:
Panel 0: Price
Panel 1: Volume + volume moving average
A shareable plugin looks for an available panel and axis.
If volume is enabled and the plugin allows sharing the volume panel, it may be placed on the available axis of panel 1.
Example:
python chart.py --sym RELIANCE --volume --rsiPossible layout:
Panel 0: Price
Panel 1: Volume + RSI
If no suitable panel is available, chart.py creates a new lower panel.
An exclusive plugin always gets a new lower panel.
Example:
python chart.py --sym RELIANCE --volume --macdPossible layout:
Panel 0: Price
Panel 1: Volume
Panel 2: MACD
Price overlay plugins always go on panel 0.
Example:
python chart.py --sym RELIANCE --bb --supertrendLayout:
Panel 0: Price + Bollinger Bands + Supertrend
A custom plugin needs two parts:
- A Python file in
renderer/plugins/ - A config entry in
defs/user.json
Create a new file:
renderer/plugins/my_indicator.py
Every plugin must define an apply() function with this signature:
from __future__ import annotations
from typing import Any
import pandas as pd
def apply(
df: pd.DataFrame,
plot_args: dict[str, Any],
options: dict[str, Any],
display_period: int,
) -> None:
...The plugin receives the full chart data as df.
Typical columns are:
Open
High
Low
Close
Volume
Calculate your indicator on the full dataset, then plot only the visible section:
indicator.iloc[-display_period:]Plugins add lines, bars, or scatter markers through mplfinance.make_addplot.
A simple lower-panel example:
from __future__ import annotations
from typing import Any
import pandas as pd
from mplfinance import make_addplot
def apply(
df: pd.DataFrame,
plot_args: dict[str, Any],
options: dict[str, Any],
display_period: int,
) -> None:
length = int(options.get("length", 20))
source_name = str(options.get("source", "Close"))
line_color = str(options.get("line_color", "royalblue"))
width = float(options.get("width", 1.5))
label = str(options.get("label", f"SMA {length}"))
ylabel = str(options.get("ylabel", "SMA"))
panel = options.get("plot_panel", "lower")
secondary_y = bool(options.get("secondary_y", False))
indicator = df[source_name].rolling(length).mean()
addplots = plot_args.setdefault("addplot", list())
addplots.append(
make_addplot(
indicator.iloc[-display_period:],
label=label,
panel=panel,
secondary_y=secondary_y,
color=line_color,
ylabel=ylabel,
width=width,
)
)Add this inside the top-level CHART_PLUGINS object in:
defs/user.json
{
"CHART_PLUGINS": {
"MY_INDICATOR": {
"name": "my_indicator",
"option": "my-indicator",
"help": "Add My Indicator.",
"lookback": 100,
"panel": {
"kind": "lower",
"axes": 1,
"share": true,
"preferred_axis": "any",
"allow_volume_panel": true
},
"length": 20,
"source": "Close",
"line_color": "royalblue",
"width": 1.5,
"label": "My Indicator",
"ylabel": "My Indicator"
}
}
}This creates the CLI option:
--my-indicatorRun it with:
python chart.py --sym RELIANCE --my-indicatorEach plugin config should include these fields:
"name": "my_indicator"The Python module name inside renderer/plugins/.
"option": "my-indicator"The command-line option used to enable the plugin.
"help": "Add My Indicator."The help text shown in the CLI.
"lookback": 100Extra history loaded before the visible chart period. Use a value larger than the longest calculation period in the indicator.
"panel": {
"kind": "lower"
}Controls where the indicator is plotted.
Other fields are passed into the plugin through the options dictionary. You can use them for periods, colors, widths, labels, and source columns.
Common indicator calculations are available in:
renderer/plugins/utils.py
Available helpers include:
simple_moving_average(source, length)
exponential_moving_average(source, length)
wilders_moving_average(source, length)
average_true_range(high, low, close, length=14)
relative_strength_index(source, length=14)
macd(source, fastlen=12, slowlen=26, siglen=9)
bollinger_bands(source, length=20, mult=2.0)
supertrend(high, low, close, factor=3.0, atr_length=10)Import helpers like this:
from .utils import relative_strength_indexExample:
rsi = relative_strength_index(source=df["Close"], length=14)Use these helpers when possible. It keeps plugins shorter and more consistent.
Use a price overlay when the indicator belongs on the candles.
Use a shareable lower panel for one-line indicators.
Use an exclusive lower panel for indicators with histograms, multiple scales, or several parts.
Set lookback high enough for the longest calculation. For example, if the indicator uses a 200-period average, use:
"lookback": 250Keep plugin option names short and easy to type.
Good examples:
--rsi
--macd
--bb
--supertrend
Avoid editing core chart files when adding a new indicator. In most cases, only these two files are needed:
renderer/plugins/<your_plugin>.py
defs/user.json
