Lesson 4: Signals, arrows and zones
Mark the bars where two averages cross, tint the background by condition, and draw level lines with a shaded zone between them.
Lesson 4 of 18. An indicator becomes useful when it marks the moments that matter. This lesson shows a signal as an arrow, a condition as a coloured background, and a zone between two levels.
A condition is a yes or no#
A comparison such as fast > slow gives true or false on every bar. Functions such as tech.crosses_above(a, b) answer a sharper question: did a rise above b on this bar, when it was not above on the bar before?
indicator "Cross arrows"
edition = 1
display = price
input fast_length: int = 10, name = "Fast length", min = 1
input slow_length: int = 30, name = "Slow length", min = 2
let fast = tech.sma(close, fast_length)
let slow = tech.sma(close, slow_length)
let buy = tech.crosses_above(fast, slow)
let sell = tech.crosses_below(fast, slow)
plot(fast, name = "Fast", color = color.blue)
plot(slow, name = "Slow", color = color.red)
mark.shape(buy, name = "Buy", shape = triangle_up, place = below, color = color.green)
mark.shape(sell, name = "Sell", shape = triangle_down, place = above, color = color.red)mark.shape(condition, ...) draws a shape on every bar where the condition is true. shape picks the shape, place puts it below or above the bar. tech.crosses_above remembers the previous bar, and it can only remember the bars on which it ran. Call it at the top of the script, on every bar, as here, and keep the if for what you do with the answer. Variables shows what goes wrong otherwise.
Choose between two values#
if ... then ... else ... is an expression: it has a value. Both branches are required, because the expression must always have an answer.
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(tint, name = "Trend")
plot(trend, name = "Trend line", color = color.gray)color.fade(color, percent) makes a transparent copy of a colour: 0 is solid and 100 is invisible. chart.background paints the background of every bar with the colour it is given. A bar for which the colour is na is left unpainted:
indicator "Only strong bars"
edition = 1
display = price
let range = high - low
let strong = range > tech.sma(range, 20) * 1.5
chart.background(if strong then color.fade(color.orange, 80) else na, name = "Strong bar")If you leave out the else, the editor stops you:
indicator "Missing else"
edition = 1
let tint = if close > open then color.green
plot(close)Levels and a shaded zone#
level(price) draws a horizontal line at a fixed level. shade(a, b) shades the space between two plots or two levels. Keep the result of level or plot in a name to hand it to shade.
indicator "RSI with 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 = "Zone")
plot(value, name = "RSI", color = color.purple, width = 2)
chart.background(
if value > upper then color.fade(color.red, 85) else if value < lower then color.fade(
color.green,
85,
) else na,
)The RSI (relative strength index) is a measure of momentum, a number between 0 and 100, so the script has its own pane (display = pane). The last line chains two if ... then ... else: the first branch that is true wins.
Try changing#
- In "Cross arrows", replace
tech.smawithtech.emain both averages: the crossings come a little earlier. - Change the buy mark to
shape = circle, place = bottom: the circles move to the bottom of the pane instead of under the bars. - Add a letter as well:
mark.char(buy, name = "B", char = "B", place = below, color = color.green). - In "Only strong bars", change
1.5to2.0: fewer bars are painted. - In "RSI with zones", set the upper and lower levels to 80 and 20 from the settings panel and watch the background tint less often.
Checkpoint#
- You can turn a comparison or a crossing into a
true/falsecondition. - You can mark the bars where a condition holds with
mark.shapeandmark.char. - You can choose a value with
if ... then ... else, and you know why theelseis required. - You can draw two levels and shade the zone between them.
See also: Plots and drawings, Choices and loops, Values and types.