Indicator outputs and styles¶
An indicator returns one number per output on each bar (or None for
“nothing here”). Everything about how that number looks on a chart is declared
once, in the indicator’s outputs and levels. A chart reads it from
describe().
This keeps the math simple and the data small: the per-bar values never carry colors or text, so the same indicator works in a backtest, in a live strategy and on any chart that understands these options.
Quick reference¶
Option |
What it does |
|---|---|
|
How the values draw: |
|
|
|
Pixels, above 0 and at most 10. For |
|
|
|
A color per bar, picked by another output’s value. |
|
Shift the drawing left (negative) or right (positive) by whole bars. |
|
|
|
Decimals shown for the value, 0 to 10. |
|
|
|
A dotted line across the pane at the newest value. |
|
Markers for |
|
The two outputs or levels a |
|
The open, high, low and close outputs a |
Every option is checked when the class is defined (for a single output) or
when the indicator is created (for references between outputs). A typo raises
ValueError that names the output and the allowed values.
Kinds¶
lineA line. Where the value is
Nonethe line breaks; it never joins across a gap.stepA line that moves in steps: flat until the next bar, then straight up or down.
areaA line with the space under it filled in the line’s color. Use a color with opacity (
#2962FF33) for a light fill.histogramBars from zero, thin.
columnsBars from zero, full bar width.
circles,crossA dot or a cross on each bar with a value.
line_widthsets the size.scatterDots, like
circles, kept for older indicators.markersReserved for marker-only outputs some charts read separately; prefer
shape.shapeA mark on every bar whose value is set and not 0. See Markers.
fillShades the space between two outputs or two levels. See Fills.
backgroundColors the bar’s whole column of its pane. See Background zones.
bar_colorRecolors the price candles. See Candle colors.
candleDraws candles from four other outputs. See Candles of your own.
Width and line style¶
outputs = [
OutputSpec("fast", "Fast", "line", "#2962FF", line_width=2),
OutputSpec("slow", "Slow", "line", "#FF6D00", line_width=1, line_style="dashed"),
OutputSpec("signal", "Signal", "step", "#AB47BC", line_style="dotted"),
]
Colors and opacity¶
A color is #RRGGBB or #RRGGBBAA. The last pair is opacity in hex:
FF is solid, 80 is half, 1A is about a tenth, 00 is invisible:
OutputSpec("cloud", "Cloud", "area", "#26A69A33") # a light green area
Theme colors¶
chart.fg is the chart’s text color and chart.bg its background color.
They change with the chart’s light or dark theme, so a line drawn in
chart.fg is always readable:
OutputSpec("basis", "Basis", "line", "chart.fg")
A person viewing the chart can still choose their own color, width and style for each output in the chart’s settings; their choice wins over the class.
A color per bar¶
Give the output a palette and name another output in color_by. On each
bar, that output’s value picks the color:
without
gradient, the value is an index into the palette (0 is the first color, 1 the second…). Values are rounded and kept inside the palette.with
gradient=(low, high), the value is a position:lowgets the first color,highthe last, and values in between are blended across the palette.Noneon a bar uses the output’s owncolor.
Hide the helper output with display="none". A four-color histogram:
outputs = [
OutputSpec("hist", "Histogram", "histogram", line_width=4,
palette=("#26A69A", "#B2DFDB", "#FF5252", "#FFCDD2"),
color_by="hist_color"),
OutputSpec("hist_color", "Histogram color", "line", display="none"),
]
def step(self, state, bar):
...
return {"hist": value, "hist_color": 0 if rising_above_zero else 1}
A line colored by its own value:
outputs = [
OutputSpec("rsi", "RSI", "line", palette=("#FF5252", "#7E57C2", "#00E676"),
color_by="rsi_shade", gradient=(0, 100)),
OutputSpec("rsi_shade", "RSI shade", "line", display="none"),
]
# step(): return {"rsi": rsi, "rsi_shade": rsi}
Fills¶
A fill output shades between two things. Each side is an output id or a
level value. Its color (and palette / color_by) works like any other
output. step does not need to return a value for it.
Between two outputs:
OutputSpec("cloud", "Cloud", "fill", "#2962FF26", between=("upper", "lower"))
Between two levels, like a shaded 30 to 70 band:
OutputSpec("band", "Band", "fill", "#7E57C21A", between=(70.0, 30.0))
Where either side is None on a bar, that bar is not shaded.
Background zones¶
A background output colors the whole height of its pane on bars where its
value is set. With a palette, the value picks the color; without one, any
value uses color. An indicator that overlays the price colors the price
chart’s background:
OutputSpec("zone", "Zone", "background", palette=("#FF525226", "#00E67626"), display="pane")
# step(): return {"zone": 0 if overbought else 1 if oversold else None}
Candle colors¶
A bar_color output recolors the price candles on bars where its value is
set, the same way as a background:
OutputSpec("trend", "Trend color", "bar_color", palette=("#00C853", "#FF1744"), display="pane")
Markers¶
A shape output puts a mark on each bar whose value is set and not 0.
shapecircle,square,diamond,cross,xcross,triangle_up,triangle_down,arrow_up,arrow_down,label_up,label_down(a tag pointing at the bar, with the text inside it) andflag.locationabove_bar,below_bar,absolute(at the output’s value),toporbottomof the pane.sizeauto,tiny,small,normal,large,huge.text,text_colorUp to 40 characters drawn with the mark. One character with a small shape works like a character marker:
OutputSpec("buy", "Buy", "shape", "#00C853", shape="label_up", location="below_bar", text="Buy", text_color="#FFFFFF", size="small") OutputSpec("pivot", "Pivot", "shape", "#FFB74D", shape="circle", location="absolute", size="tiny") # step() returns the pivot price
Candles of your own¶
A candle output draws candles from four other outputs (usually hidden with
display="none"). palette and color_by color each candle:
outputs = [
OutputSpec("o", "Open", display="none"),
OutputSpec("h", "High", display="none"),
OutputSpec("l", "Low", display="none"),
OutputSpec("c", "Close", display="none"),
OutputSpec("dir", "Direction", display="none"),
OutputSpec("candles", "Candles", "candle", candle=("o", "h", "l", "c"),
palette=("#26A69A", "#EF5350"), color_by="dir", pane="own"),
]
Panes¶
The indicator’s overlay decides where its outputs draw: True on the
price chart, False in a pane of its own under it. One output can go the
other way with pane:
class Trend(Indicator):
overlay = False # oscillator in its own pane
outputs = [
OutputSpec("osc", "Oscillator"),
OutputSpec("flip", "Flip", "shape", shape="triangle_up",
location="below_bar", pane="price"), # marks on the candles
]
What shows where¶
display controls where an output appears:
allDrawn, and its value is shown in the chart’s status line.
paneDrawn, value not shown. Good for fills, zones and markers.
status_lineValue shown, nothing drawn.
data_windowOnly in a chart’s data window, where it has one.
noneNot shown at all. Use it for helper outputs such as the one
color_byreads.
precision sets how many decimals the value shows.
Shift and price line¶
offset moves an output by whole bars: offset=-5 draws each value five
bars earlier, offset=5 five bars later. A chart only draws the part that
falls on bars it has.
track_price=True draws a dotted line across the pane at the output’s
newest value, so the latest reading is easy to see.
Levels¶
A Level is a fixed horizontal guide line. style is solid,
dashed (default) or dotted. color and line_width are optional;
without a color the chart uses its own:
levels = [
Level(70, "Upper", "dashed", color="#787B86"),
Level(50, "Middle", "dotted", color="#787B8680"),
Level(30, "Lower", "dashed", color="#787B86"),
]
Shade between two levels with a fill (see Fills).
Complete examples¶
These ship with LumiBot in lumibot/example_indicators/ and run in the test
suite. Each is small and shows several options together.
momentum_histogram.pyFour-color histogram (
palette+color_by), cross marks on the zero line colored by a second helper, a dotted zero level.trailing_band.pyTwo lines that break where the trend flips, half-transparent fills between the price middle and the band,
Buy/Selltag markers, and candle colors.oscillator_zones.pyA line colored by a gradient, a fill between two levels, background zones,
track_priceandprecision.smoothed_candles.pyCandles of its own in a separate pane (
candle+pane="own") and a dashed step line on the price chart.
Load one and look at its schema:
from lumibot.example_indicators import oscillator_zones
oscillator_zones.OscillatorZones.describe()
What is not an output¶
Some charting tools also let a script create free-standing objects: lines between two points, text labels, boxes, tables pinned to a corner of the chart, or horizontal bars growing from the side of the chart (volume at each price). These are not one number per bar, so they are not outputs. They are not part of the indicator contract yet.