millionchart
فارسی

Drawing and marks

Plots, levels, shading, labels, boxes, lines, tables and marks drawn on the chart, in tested programs.

Everything a script shows is drawn by a call: lines and levels, shaded areas, marks on bars, and objects such as labels, boxes, lines and tables.

RSI zones#

The built-in RSI with levels, a shaded band and marks when it leaves a zone.

Cuprel
// The built-in RSI with two levels, a shaded middle band and a mark each time it leaves a zone.
indicator "RSI zones"
    edition = 1
    display = pane

input length: int = 14, name = "Length", min = 2
input upper: float = 70, name = "Upper level"
input lower: float = 30, name = "Lower level"
let value = tech.rsi(close, length)
let top = level(upper, name = "Upper", color = color.red, style = dashed)
let bottom = level(lower, name = "Lower", color = color.green, style = dashed)
shade(top, bottom, color = color.fade(color.purple, 92), name = "Middle band")
plot(value, name = "RSI", color = color.purple, width = 2)
mark.shape(
    tech.crosses_below(value, upper),
    name = "Leaves overbought",
    shape = triangle_down,
    place = above,
    color = color.red,
)
mark.shape(
    tech.crosses_above(value, lower),
    name = "Leaves oversold",
    shape = triangle_up,
    place = below,
    color = color.green,
)

Swing pivots#

Swing highs and lows found with a left and a right window, labelled on the bar where they happened.

Cuprel
// Swing structure: a swing high is a bar whose high is the highest of `left` bars before it and `right` bars after it.
// The pivot is only known `right` bars later, so the label is placed back on the bar where the swing happened.
indicator "Swing pivots"
    edition = 1
    display = price
    max_labels = 200

input left: int = 5, name = "Bars on the left", min = 1
input right: int = 5, name = "Bars on the right", min = 1
let swing_high = tech.pivot_high(high, left, right)
let swing_low = tech.pivot_low(low, left, right)
if not is_na(swing_high)
    label.new(
        bar.index - right,
        swing_high,
        f"{swing_high:price}",
        style = label_down,
        color = color.red,
    )
if not is_na(swing_low)
    label.new(
        bar.index - right,
        swing_low,
        f"{swing_low:price}",
        style = label_up,
        color = color.green,
    )
plot(close, name = "Close", color = color.gray)

Status table#

A table written on the last bar, with formatted numbers and a fallback text.

Cuprel
// A small table in the corner of the chart, written on the last bar only.
indicator "Status table"
    edition = 1
    display = price

input length: int = 14, name = "Length", min = 2
let strength = tech.rsi(close, length)
let volatility = tech.atr(length)
if bar.is_last
    let t = table.new(
        top_right,
        2,
        3,
        background = color.fade(color.black, 70),
        border_color = color.gray,
        border_width = 1,
    )
    table.cell(t, 0, 0, "Close", text_color = color.silver, h_align = left)
    table.cell(t, 1, 0, f"{close:price}", text_color = color.white)
    table.cell(t, 0, 1, "RSI", text_color = color.silver, h_align = left)
    table.cell(t, 1, 1, f"{strength:.1f?'n/a'}", text_color = color.white)
    table.cell(t, 0, 2, "ATR", text_color = color.silver, h_align = left)
    table.cell(t, 1, 2, f"{volatility:price?'n/a'}", text_color = color.white)
plot(close, name = "Close", color = color.gray)

Recent range drawing#

A box, a dashed line and a label drawn on the last bar.

Cuprel
// Drawing objects on the last bar: a box around the recent range, a dashed line at the close and a label at the high.
indicator "Recent range"
    edition = 1
    display = price

input length: int = 30, name = "Length", min = 2
let top = tech.highest(high, length)
let bottom = tech.lowest(low, length)
if bar.is_last
    box.new(
        bar.index - length + 1,
        top,
        bar.index,
        bottom,
        border_color = color.blue,
        background = color.fade(color.blue, 90),
    )
    line.new(
        bar.index - length + 1,
        close,
        bar.index,
        close,
        extend = right,
        style = dashed,
        color = color.orange,
    )
    label.new(bar.index, top, f"High {top:price}", style = label_down)
plot(close, name = "Close", color = color.gray)

Trend background#

A chart background coloured by the side of a moving average.

Cuprel
// A background that follows the trend: green above the moving average, red below it, nothing while it is not known yet.
indicator "Trend background"
    edition = 1
    display = price

input length: int = 50, name = "Length", min = 2
let trend = tech.sma(close, length)
let tint = if close > trend then color.fade(color.green, 88) else color.fade(color.red, 88)
chart.background(if is_na(trend) then na else tint, name = "Trend")
plot(trend, name = "Trend line", color = color.gray)

Swing high path#

Swing highs collected as chart points in an array and drawn as one polyline on the last bar.

Cuprel
// A polyline through the latest swing highs. Each confirmed swing high becomes a chart point (a bar number and a price) kept in an array,
// and on the last bar polyline.new draws one line through the twelve most recent points.
indicator "Swing high path"
    edition = 1
    display = price
    max_polylines = 5

input side: int = 5, name = "Bars on each side", min = 1
let pivot = tech.pivot_high(high, side, side)
state points: array<chart.point> = array<chart.point>()
if not is_na(pivot)
    points.push(chart.point.at_index(bar.index - side, pivot))
    if points.size() > 12
        points.shift()
if bar.is_last and points.size() > 1
    polyline.new(points, color = color.orange, width = 2)
plot(close, name = "Close", color = color.gray)