Lesson 13: Finding mistakes with the log
When a script runs but draws the wrong thing. Stop it on purpose with a clear message, write log lines, and look at values with plots, marks and labels.
Lesson 13 of 18. The editor finds mistakes in the text before a script runs (Lesson 18 shows how to read them). This lesson is about the other kind: the script runs, but a number is wrong, a mark never appears, or a setting makes no sense. You will stop a script on purpose, write log lines, and put values where you can see them.
Stop on purpose when a setting makes no sense#
indicator "Two averages, checked"
edition = 1
display = price
input fast_length: int = 10, name = "Fast length", min = 1
input slow_length: int = 30, name = "Slow length", min = 2
if fast_length >= slow_length
log.abort("The fast length must be shorter than the slow length")
plot(tech.ema(close, fast_length), name = "Fast", color = color.green)
plot(tech.ema(close, slow_length), name = "Slow", color = color.red)log.abort(message) stops the run. The editor then shows Stopped on the chart with your message, so whoever changed the settings knows what to fix. Here the defaults are fine and the script runs. With defaults that break the rule, it stops on the first bar with the code E5637 and your text:
indicator "Two averages, wrong defaults"
edition = 1
display = price
input fast_length: int = 30, name = "Fast length", min = 1
input slow_length: int = 10, name = "Slow length", min = 2
if fast_length >= slow_length
log.abort("The fast length must be shorter than the slow length")
plot(tech.ema(close, fast_length), name = "Fast", color = color.green)A clear stop tells the reader what is wrong; a chart that quietly draws nonsense does not.
Log lines#
indicator "Logged crossings, short"
edition = 1
display = price
let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
let up = tech.crosses_above(fast, slow)
if up
log.info("Up cross on bar {0} at {1}", bar.index, close)
if close <= 0
log.error("A price of zero or less on bar {0}", bar.index)
plot(fast, name = "Fast", color = color.green)
plot(slow, name = "Slow", color = color.red)log.info,log.warningandlog.errorwrite a line at three levels.{0},{1}and so on in the text are filled with the values after it.- The engine keeps at most 10 lines for each bar and 5,000 for a run, each up to 500 characters; it counts the lines it had to drop (
W-ENGINE-LOG-DROPPED).
Put the value on the chart#
The quickest way to look at a number is to draw it.
indicator "Look inside"
edition = 1
display = pane
input length: int = 14, name = "Length", min = 2, max = 200
let rsi = tech.rsi(close, length)
let range = tech.atr(length)
let up = tech.crosses_above(rsi, 50)
plot(rsi, name = "RSI", color = color.purple)
mark.char(up, name = "Crossed 50", char = "x", place = above, color = color.orange)
if bar.is_last
label.new(
bar.index,
rsi,
f"RSI {rsi:.1f}, ATR {range:price}, bar {bar.index}",
style = label_down,
)- A
plotof the value shows it on every bar; the indicator's chip in the legend shows the value too (with Values switched on in the legend settings). - A
mark.charormark.shapeon a condition shows exactly where the condition is true. If a signal never appears, mark each part of the condition on its own and see which part is never true. - A
label.newon the last bar (bar.is_last) writes several values at once.f"..."puts values in the text;:.1fwrites one decimal and:priceuses the symbol's own decimals.
For many values at once, a small table works well: Lesson 9 shows one.
A checklist when the result looks wrong#
- Is the value
na? A value with too little history isna, and a plot draws nothing there. Test it withis_na(x), never withx == na. - Which bar am I on? The script runs once for each bar, oldest first.
x[1]is the value one bar back, not the next one. - Does a call keep a memory? A
tech.*call written inside a condition would skip bars; the editor refuses that (E3302), and the fix is to work it out on its own line first. - Is it a closed bar or a forming one? On the newest bar the values move until the bar closes. Lesson 16 explains what that changes.
Try changing#
- In "Two averages, checked", set the fast length to 40 in the settings. The editor shows Stopped on the chart with your message.
- In "Look inside", change
50to70in the crossing. Fewer marks appear. - Add
bar.indexto the label in a different place, or add a second label on the first bar withbar.index == 0. - Write a condition that is never true (
close < 0) and mark it withmark.char. No mark appears: that is how a condition looks when one part of it never holds.
Checkpoint#
- You can stop a script on purpose with
log.abortand a message that says what to fix. - You can write log lines and know that this release keeps them without showing them.
- You can look at a value with a plot, a mark or a label on the last bar.
- You can check the four usual causes of a wrong result:
na, the bar, a call's memory, and the forming bar.