millionchart
فارسی

Cheat sheet

The syntax of the language on one page. Header, names, inputs, operators, choices and loops, functions, formats, drawing, time and orders.

The whole language at a glance. Every form here compiles on the chart; follow the links for the rules.

A whole indicator#

Cuprel
// One program that uses most of the syntax on one page.
indicator "Cheat sheet"
    edition = 1
    display = price

enum Kind
    sma = "SMA"
    ema = "EMA"

type Band
    upper: float
    lower: float

group "Average"
    /// How many bars the average reads
    input length: int = 20, name = "Length", min = 2, max = 500
    input kind: Kind = Kind.ema, name = "Kind"
    input src: source = close, name = "Source"
input width: float = 2.0, name = "Width", min = 0.1, step = 0.1
input band_color: color = #2962ff, name = "Band colour"

session london = 08:00 .. 16:30 @ "Europe/London"

fn band_of(middle: float, size: float): Band = Band(upper = middle + size, lower = middle - size)

let sma = tech.sma(src, length)
let ema = tech.ema(src, length)
let middle = match kind
    Kind.sma => sma
    Kind.ema => ema
let b = band_of(middle, width * tech.atr(length))
state above_count = 0
mut last_three = 0.0
for i in 0 until 3
    last_three += close[i]
if close > b.upper
    above_count += 1
let crossed = tech.crosses_above(close, middle)
let top = plot(b.upper, name = "Upper", color = band_color)
let bottom = plot(b.lower, name = "Lower", color = band_color)
shade(top, bottom, color = color.fade(band_color, 90), name = "Band")
plot(middle, name = "Middle", color = color.gray, width = 2)
plot(last_three / 3, name = "Mean of 3 closes", display = none)
mark.shape(crossed, name = "Cross up", shape = triangle_up, place = below, color = color.green)
chart.background(if london.active then color.fade(color.blue, 94) else na, name = "London")
let yesterday_high = prior(day).high
plot(yesterday_high, name = "Yesterday's high", style = step_break, color = color.orange)
if bar.is_last
    label.new(
        bar.index,
        b.upper,
        f"{above_count} closes above, last {close:price}",
        style = label_down,
    )

The shape of a script#

WriteMeans
indicator "Name"the header of an indicator; its settings are indented under it
strategy "Name"the header of a strategy (simulated orders)
module Namethe header of a module that other scripts import
edition = 1the edition of the language the script is written for
display = pricedraw on the price chart; without it the script gets its own pane
// texta comment, to the end of the line
/// textabove an input: its tooltip
four spacesone level of a block (if, for, fn, group …); a tab is an error

One statement a line. A long statement goes on when a line ends with an operator or a comma, or inside brackets. See Syntax and layout.

Names and values#

WriteMeans
let x = close - opena name set once on each bar, never changed
mut n = 0a value that starts again on each bar and may change: n += 1, -=, *=, /=
state count = 0a value kept from bar to bar; state day starts again each trading day
close[1]the value one bar back (history)
na, is_na(x), x ?? 0no value; the test for it; a fallback
20, 2.5, "text", truea whole number, a number, a text, a truth value
#2962ff, color.red, color.fade(c, 80)colours: a code, a name, more transparent
08:30, @2026-01-01T00:00Z, 15m, 0.5%a time of day, a moment, a duration, a percentage
[1, 2, 3], [0.0; 4]an array; four copies of 0.0
map<int, float>()an empty map from whole numbers to numbers

See let, mut and state, Values and types, Units and literals.

Inputs#

WriteShows
input length: int = 20, name = "Length", min = 1, max = 500a whole number with limits
input mult: float = 2.0, name = "Width", step = 0.1a number; step moves the field
input on: bool = true, name = "Show"a switch
input src: source = close, name = "Source"the price the script reads
input c: color = color.blue, name = "Colour"a colour picker
input tf: tf = "60", name = "Timeframe"a timeframe
input kind: text = "EMA", name = "Kind", options = ["EMA", "SMA"]a dropdown
input mode: Mode = Mode.fast, name = "Mode"a dropdown of an enum
group "Name"the inputs indented under it share a heading

See Inputs.

Operators, loose to tight#

OperatorsNote
if c then a else ba value chosen by a condition; the else is required
orthe right side runs only when the left is false
andthe right side runs only when the left is true
notlooser than a comparison: not a == b is not (a == b)
== != < <= > >=not chained: a < b < c is an error
??the right side when the left is na
+ -add, subtract (+ also joins texts)
* / %multiply, divide, remainder
-xminus
x[1], f(x), a.bhistory, a call, a member

There is no power operator: write math.pow(x, 2). A call that remembers earlier bars (tech.*, data.series) may not stand on the right of and, or, ?? or in a branch of if ... then ... else (E3302): give it a line of its own. See Lazy operators.

Choices and loops#

WriteDoes
if cond with an indented block, elseruns the block when the condition is true
let v = if cond then a else bchooses a value
match x then "a" => 1 lines and _ => 0chooses by value; match with no subject chooses by condition
for i in 0 to 30, 1, 2, 3 (until 3 leaves 3 out; by 2 sets the step)
for x in items, for (i, x) in itemseach item of an array, with its position
while condrepeats while the condition holds
break, continueleave the loop; go to its next pass

A loop may not hold a call that remembers earlier bars (E3301). See Choices and loops.

Functions, types and enums#

WriteMeans
fn mid(a: float, b: float): float = (a + b) / 2a one-line function
fn f(x: float) with an indented block and returna function with a block
fn scaled(x: float, k: float = 2.0): floata parameter with a default; call with scaled(close, k = 0.5)
let (a, b) = pair()take a tuple apart (_ skips a value)
type Band with indented fields upper: floata record; build it with Band(upper = 1.0, lower = 0.0)
fn Band.width(self): float = self.upper - self.lowera method, called as b.width()
enum Mode with indented fast = "Fast"a closed list of names
import Me/Name@1 as aliasone of your own modules

A function may not call itself (E3310). See Functions, types and enums, Modules and libraries.

Text and formats#

WriteGives
f"Close {close:price}"the close with the symbol's own decimals
{x:.2f}, {x:,.2f}, {x:+.1f}two decimals; with thousands; with a sign
{x:.1%}, {x:03}a percentage; padded with zeros
{x:.1f?'n/a'}n/a while x is na
text.fmt(x, ".2f"), text.length(s), text.split(s, ",")text functions

See Text and number formatting.

Drawing on the chart#

WriteDraws
plot(x, name = "A", color = color.blue, width = 2, style = histogram)a series on every bar
level(70, name = "Top", style = dashed)a horizontal line
shade(top, bottom, color = color.fade(color.purple, 90))the space between two plots or levels kept in names
mark.shape(cond, shape = triangle_up, place = below)a shape where a condition is true
mark.char(cond, char = "x", place = above), mark.arrow(x)a character; an arrow up or down by the sign
chart.background(if cond then color.fade(color.green, 90) else na)the background of a bar
chart.candles(color)recolours the chart's candles
label.new(bar.index, high, "text"), line.new(x1, y1, x2, y2), box.new(left, top, right, bottom)drawings placed by bar and price
table.new(top_right, 2, 2), table.cell(t, 0, 0, "A")a table in a corner
log.info("close {0}", close)a line in the script's log

Plot styles: line, line_break, step, step_break, step_diamond, histogram, columns, area, area_break, circles, cross. See Plots and drawings, Tables.

Time and other timeframes#

WriteGives
bar.index, bar.time, bar.is_lastthe bar's number, its time, true on the newest bar
data.series("240", tech.ema(close, 20), symbol = symbol.id)an expression on another timeframe, last closed bar
prior(day).high, current(week).openyesterday's high; this week's open (intraday charts)
session london = 08:00 .. 16:30 @ "Europe/London"a named session: london.active, .start, .end, .high, .low
clock.hour_of(bar.time, zone = "UTC")the hour of a time in a zone

See Other timeframes and symbols, Trading day and sessions.

Common built-ins#

GroupSome of its names
pricesopen high low close volume hl2 hlc3 ohlc4
techtech.sma tech.ema tech.rma tech.rsi tech.atr tech.stdev tech.highest tech.lowest tech.crosses_above tech.crosses_below tech.pivot_high tech.macd
mathmath.abs math.max math.min math.round math.floor math.sqrt math.pow math.sign
symbolsymbol.id symbol.tick symbol.pip
colorcolor.rgb color.fade color.gradient and the named colours

The Function index lists every name with its parameters, and the Function reference explains each one.

Strategies#

WriteDoes
orders.enter("Long", side.long)opens a simulated long trade with the key "Long" (side.short for a short)
orders.close("Long")closes it
orders.exit("Exit", "Long", stop = s, limit = t)a stop and a target for the trade "Long"
orders.cancel("Key"), orders.close_all()cancels an order; closes everything
position.size, position.avg_pricethe open size (positive for a long); its price
setup: with capital, size = sizing.lots(0.1), fees = fee.per_lot(3.5)money, size and commission
execution: with spread = 20 ticks, slippage = 2 ticksthe costs of a fill
Cuprel
// A strategy: orders with a key, a stop and a target, size and costs in the header.
strategy "Cheat sheet strategy"
    edition = 1
    display = price

setup:
    capital = 10000
    size = sizing.lots(0.1)
    fees = fee.per_lot(3.5)

execution:
    spread = 20 ticks
    slippage = 2 ticks

let fast = tech.ema(close, 10)
let slow = tech.ema(close, 30)
if tech.crosses_above(fast, slow)
    orders.enter("Long", side.long)
if position.size > 0
    orders.exit("Exit", "Long", stop = position.avg_price * 0.99, limit = position.avg_price * 1.02)
if tech.crosses_below(fast, slow)
    orders.close("Long")
plot(fast, name = "Fast", color = color.green)
plot(slow, name = "Slow", color = color.red)

See Your first strategy, Strategies and the header.