Drawing — lines & bars

15 functions

Draw calls are statements, not values. Writing A: DRAWICON(…) is not supported — call them bare.

STICKLINE(COND, PRICE1, PRICE2, WIDTH, EMPTY)

Vertical bar between PRICE1 and PRICE2 where COND holds. WIDTH 10 is one bar slot; EMPTY non-zero draws it hollow.

COND(condition)
Which bars to draw on.
PRICE1(series)
One end of the bar.
PRICE2(series)
The other end. Order does not matter.
WIDTH(integer)
Bar width; 10 fills one whole bar slot.
EMPTY(integer)
0 solid, non-zero hollow.
// hand-drawn candles: body first, then the wick as a thin bar
STICKLINE(CLOSE > OPEN, CLOSE, OPEN, 8, 1), COLORRED;
STICKLINE(CLOSE > OPEN, HIGH,  LOW,  0, 1), COLORRED;

// or use it to shade a whole bar as a background highlight
SQUEEZE := STD(CLOSE, 20) < LLV(STD(CLOSE, 20), 60) * 1.1;
STICKLINE(SQUEEZE, HIGH, LOW, 10, 1), COLORLIBLUE;
POLYLINE(COND, PRICE)

Connect the PRICE points of every bar where COND holds with a polyline.

COND(condition)
Which bars contribute a point.
PRICE(series)
The value each of those points sits at.

Also written as PLOYLINE

// connect the swing highs — a trend line that follows structure
// rather than a fixed formula
POLYLINE(HIGH >= HHV(HIGH, 20), HIGH), COLORYELLOW;
POLYLINE(LOW  <= LLV(LOW,  20), LOW),  COLORLIBLUE;
PARTLINE(PRICE, COND1, COLOR1, COND2, COLOR2, …)

Draw PRICE, colouring each segment by the first matching condition. Up to ten pairs; bars matching none are not drawn.

PRICE(series)
The line to draw.
COND1(condition)
First condition, tested first.
COLOR1(color)
Colour used where COND1 holds.
COND2(condition)
Next condition. Up to ten pairs; put a bare 1 last to catch the rest.
COLOR2(color)
Colour used where COND2 holds.
// one line, two colours — the trailing 1 catches every
// remaining bar, otherwise those segments go undrawn
PARTLINE(CLOSE, CLOSE > OPEN, RGB(38,166,120),
                1,            RGB(239,83,80));

// three states, ordered from most specific to least
MA20 := MA(CLOSE, 20);
PARTLINE(MA20, CLOSE > MA20 * 1.05, COLORYELLOW,
               CLOSE > MA20,        COLORGREEN,
               1,                   COLORGRAY);
DRAWLINE(COND1, PRICE1, COND2, PRICE2, EXPAND)

Straight line from where COND1 holds at PRICE1 to where COND2 holds at PRICE2. EXPAND = 1 extends it to the right.

COND1(condition)
Where the line starts.
PRICE1(series)
Value at the start point.
COND2(condition)
Where the line ends.
PRICE2(series)
Value at the end point.
EXPAND(integer)
1 extends the line past its end point to the right, 0 stops there.
// connect a swing high to a swing low, extended to the right
DRAWLINE(HIGH >= HHV(HIGH, 20), HIGH,
         LOW  <= LLV(LOW,  20), LOW, 1), COLORYELLOW;

// a projection you can actually trade off needs EXPAND = 1;
// with 0 the line simply stops at the second point
DRAWBAND(VAL1, COLOR1, VAL2, COLOR2)

Fill between two series, using COLOR1 where VAL1 > VAL2 and COLOR2 where it is below.

VAL1(series)
First boundary series.
COLOR1(color)
Fill colour where VAL1 is on top.
VAL2(series)
Second boundary series.
COLOR2(color)
Fill colour where VAL2 is on top.
// a ribbon that flips colour when the averages cross —
// the crossover reads at a glance without any icons
DRAWBAND(MA(CLOSE, 5),  RGB(38,166,120),
         MA(CLOSE, 20), RGB(239,83,80));
DRAWSL(COND, PRICE, SLOPE, LEN, DIRECT)

Sloped line from PRICE. SLOPE is the price change per bar, LEN the length in bars, DIRECT 0 right / 1 left / 2 both.

SLOPE 0 gives a horizontal line; SLOPE 10000 gives a vertical one where LEN is a pixel height. Both accept series.

COND(condition)
Where each line starts.
PRICE(series)
Value the line starts at.
SLOPE(series)
Price change per bar. 0 is horizontal, 10000 is the special vertical case.
LEN(integer)
Length in bars — or in pixels when SLOPE is 10000.
DIRECT(integer)
0 draws to the right, 1 to the left, 2 both ways.
// project the current regression slope 20 bars forward
SLP := SLOPE(CLOSE, 20);
DRAWSL(ISLASTBAR, CLOSE, SLP, 20, 0), COLORYELLOW;

// SLOPE 0 gives a plain support line from each swing low
DRAWSL(LOW <= LLV(LOW, 20), LOW, 0, 30, 0), COLORGRAY;
VERTLINE(COND, TYPE)

Full-height vertical line where COND holds. TYPE 0 solid, 1 dashed, 2 dotted, 3 dash-dot, 4 dash-dot-dot.

COND(condition)
Which bars get a line.
TYPE(integer)
Line style: 0 solid, 1 dashed, 2 dotted, 3 dash-dot, 4 dash-dot-dot.
// mark session boundaries on an intraday chart
NEWDAY := DATE <> REF(DATE, 1);
VERTLINE(NEWDAY, 1), COLORGRAY;

// or mark every signal, so you can line it up against
// what other panes were doing at the time
VERTLINE(CROSS(MA5, MA20), 2), COLORYELLOW;
HORLINE(COND, PRICE, TYPE, EXTEND)

Horizontal line at PRICE where COND holds. TYPE as VERTLINE; EXTEND 1 left, 2 right, 3 both.

COND(condition)
Where each line originates.
PRICE(series)
Level the line sits at.
TYPE(integer)
Line style, same codes as VERTLINE.
EXTEND(integer)
1 extends left, 2 right, 3 both.
// resistance from each new 20-bar high, extended right
HORLINE(HIGH >= HHV(HIGH, 20), HIGH, 1, 2), COLORYELLOW;

// yesterday's close as a reference level on an intraday chart
NEWDAY := DATE <> REF(DATE, 1);
HORLINE(NEWDAY, REF(CLOSE, 1), 2, 2), COLORGRAY;
DRAWCHANNEL(COND, TOP, BOTTOM, BORDERCOLOR, BORDERWIDTH, DOTTED, AREACOLOR)

Shaded channel between TOP and BOTTOM. DOTTED is a dash pattern string such as '3,4'; omit a colour to skip that part.

COND(condition)
Where the channel is drawn.
TOP(series)
Upper boundary.
BOTTOM(series)
Lower boundary.
BORDERCOLOR(color)
Border colour. Omit to draw no border.
BORDERWIDTH(integer)
Border width in pixels.
DOTTED(string)
Dash pattern, e.g. '3,4'. Empty for a solid border.
AREACOLOR(color)
Fill colour. Omit to leave the channel unfilled.
// Bollinger channel with a dashed border and a soft fill
MID := MA(CLOSE, 20);
DEV := STD(CLOSE, 20);
DRAWCHANNEL(1, MID + 2 * DEV, MID - 2 * DEV,
            COLORYELLOW, 1, '3,4', RGBA(255,198,0,0.08));
DRAWOVERLAYLINE(DATA, MAINDATA, TITLE)

Overlay DATA on the main pane rescaled to MAINDATA as a percentage — for comparing two symbols.

DATA(series)
The series to overlay.
MAINDATA(series)
The series it is rescaled against — usually CLOSE.
TITLE(string)
Label shown in the legend.
// compare a weekly close against the daily chart on one axis;
// the percentage rescale is what makes two different price
// levels comparable in the same pane
DRAWOVERLAYLINE(COVER_C('WEEK'), CLOSE, 'weekly'), COLORYELLOW;
DRAWKLINE(HIGH, OPEN, LOW, CLOSE)

Draw a candle series from four arbitrary series. Note the argument order.

HIGH(series)
High of each candle. Note this comes FIRST, not third.
OPEN(series)
Open of each candle.
LOW(series)
Low of each candle.
CLOSE(series)
Close of each candle.

Also written as DRAWKLINE1

// smoothed "Heikin-Ashi style" candles built from averages —
// the argument order is H, O, L, C, not O, H, L, C
HA_C := (OPEN + HIGH + LOW + CLOSE) / 4;
HA_O := MA(HA_C, 2);
DRAWKLINE(MAX(HIGH, HA_O), HA_O, MIN(LOW, HA_O), HA_C);
DRAWKLINE_IF(COND, HIGH, OPEN, LOW, CLOSE)

As DRAWKLINE but only on bars where COND holds.

COND(condition)
Which bars get a candle.
HIGH(series)
High of each candle — again first in the order.
OPEN(series)
Open of each candle.
LOW(series)
Low of each candle.
CLOSE(series)
Close of each candle.
// draw candles only inside the session you care about
INSESSION := TIMETOSEC(TIME) >= TIMETOSEC(93000);
DRAWKLINE_IF(INSESSION, HIGH, OPEN, LOW, CLOSE);
DRAWOVERLAYKLINE(OPEN, HIGH, LOW, CLOSE)

Overlay a second candle series on top of the existing chart.

OPEN(series)
Open of each candle. This one DOES take O, H, L, C order.
HIGH(series)
High of each candle.
LOW(series)
Low of each candle.
CLOSE(series)
Close of each candle.
// weekly candles laid over the daily ones — note the argument
// order here is O, H, L, C, unlike DRAWKLINE
DRAWOVERLAYKLINE(COVER_O('WEEK'), COVER_H('WEEK'),
                 COVER_L('WEEK'), COVER_C('WEEK'));
DRAWCOLORKLINE(COND, COLOR, EMPTY)

Repaint the real candles in COLOR where COND holds. EMPTY non-zero makes them hollow.

COND(condition)
Which candles to repaint.
COLOR(color)
The colour to paint them.
EMPTY(integer)
0 solid, non-zero hollow.
// colour-coded candles instead of a separate indicator pane
DRAWCOLORKLINE(CLOSE > MA(CLOSE, 20), COLORMINT, 0);
DRAWCOLORKLINE(CLOSE < MA(CLOSE, 60), COLORCORAL, 0);
// later calls win where the conditions overlap, so order matters
KLINETYPE(TYPE)

Modifier for DRAWKLINE that selects the candle rendering style.

TYPE(integer)
Rendering style for the candles drawn by the statement it is attached to.
// a modifier, so it goes after the comma on a DRAWKLINE line —
// on its own it draws nothing
HA_C := (OPEN + HIGH + LOW + CLOSE) / 4;
HA_O := MA(HA_C, 2);
DRAWKLINE(MAX(HIGH, HA_O), HA_O, MIN(LOW, HA_O), HA_C), KLINETYPE(1);