Skip to content
ChartDeck ChartScript docs Account Open the terminal

Types

The value types of ChartScript (int, float, bool, color, string, drawing ids, collections), literals, na, conversions and how numbers behave.

Every value has a type. Most of the time the compiler infers it from what you write (const x = 1.5 is a float), so you only spell a type out when there is nothing to infer from, such as a variable that starts as na. Types catch mistakes early: adding a number to a piece of text, or passing a color where a length is expected, fails when you compile instead of drawing nonsense.

#The basic types

TypeHoldsLiteralsCan be na
intwhole numbers0, 14, -3yes
floatnumbers with a fraction1.5, .5, 2., 1e3, 2.5E-4yes
booltrue or falsetrue, falseno
colora color with transparency#FF8800, #FF880080, color.redyes
stringtext"RSI", 'RSI'yes

A few details:

  • Number literals are decimal. There are no _ separators and no hexadecimal numbers, so 0x10 is an error (CS1025).
  • A color literal is #RRGGBB or #RRGGBBAA. The last pair is the alpha: FF is solid, 00 is invisible, 80 is about half see-through.
  • Strings use double or single quotes and end on the same line. Text between backticks, `…`, is a template literal: it may span lines and can insert values with ${…}. Escapes are \\, \", \', \n, \t and \uXXXX. A string can be at most 40,960 characters. See Strings and formatting.
  • bool is never na. An if without else that yields a bool gives false on bars where it does not run.

#Object and collection types

Besides plain values, a script can hold references to things it creates:

TypeWhat it refers toCreated with
label, line, box, table, linefill, polylinea drawing on the chartlabel.new, line.new, …
chart.pointa point on the chart: time, bar index and pricechart.point.new
array<T> (also written T[])a listarray.new<float>(), array.from(…)
map<K, V>a lookup tablemap.new<string, float>()
matrix<T>a grid of rows and columnsmatrix.new<float>(rows, cols)
your own typesrecords with named fieldstype Level { … }, see User types, enums and methods
enumsa fixed set of named choicesenum Side { … }

Plots and levels also have handles: const p = plot(…) and const h = hline(…) give values you pass to fill. You do not do anything else with them.

All of these can be na (also written null), meaning "nothing yet". A drawing variable typically starts as na and gets a drawing later:

ChartScriptOpen in editor
//@chartscript 1
indicator("Last close label", { overlay: true })
state tag: label = na
if (barstate.islast) {
    label.delete(tag)  // deleting an na label does nothing, so this is safe
    tag = label.new(bar_index, close, str.tostring(close, format.mintick), { style: label.style_label_left })
}
plot(close, "Close", color.muted)

#Declaring a type

Put the type after the name, with a colon, when you declare a variable:

ChartScriptFragmentOpen in editor
const level: float = na  // a float that starts empty
const count: int = 0
const note: string = ""
const tint: color = color.new(color.blue, 80)
const closes: array<float> = array.new<float>()
const highs: float[] = array.new<float>()  // the same kind of type as array<float>
plot(level)

number is accepted as another name for float, and boolean for bool; int stays its own type. The editor writes float and bool.

You must give a type when the value alone does not say it. na has no type, so state x = na is refused (CS2201):

ChartScriptError: CS2201
//@chartscript 1
indicator("Untyped na")
state x = na
plot(x)

Write state x: float = na instead.

An annotation can also carry a qualifier in front of the type, for the rare cases where you want to say when a value is known: let n: simple int = 5. Function parameters take annotations the same way: function band(src: float, len: simple int = 20) { … }.

#Conversions

ChartScript converts on its own in exactly one direction: an int can be used where a float is expected. Everything else needs an explicit cast.

You haveYou wantWrite
intfloatnothing: const x: float = 1 is fine
floatintint(x): drops the fraction, toward zero (int(-2.7) is -2)
a numbera rounded numbermath.round(x), math.floor, math.ceil
a numberboola comparison: x != 0
anythingstringstr.tostring(x)
stringfloatstr.tonumber(s) (na if the text is not a number)
naa typed nafloat(na), int(na), string(na), color(na)

A typed na is handy in expressions: let nearest = float(na) declares a float that starts empty, the same as let nearest: float = na. For drawing types, use a typed declaration (let tag: label = na); the drawing types have no cast functions.

ChartScriptError: CS2405
//@chartscript 1
indicator("Float into int")
const half: int = bar_index / 2  // bar_index / 2 can have a fraction, so it is a float
plot(half)

Write const half: int = int(bar_index / 2), or math.floor(bar_index / 2) if you want rounding down for negative numbers too.

Mixing text and numbers also needs a conversion; + on a string only joins strings:

ChartScriptError: CS2008
//@chartscript 1
indicator("Text plus number")
const msg = "Close: " + close
plot(close)

Write "Close: " + str.tostring(close), or use a template literal: `Close: ${close}`.

#Numbers

  • Both int and float are stored as 64-bit floating point numbers. Whole numbers are exact up to about 9 × 10^15.
  • Dividing two ints keeps the fraction: 7 / 2 is 3.5, while 4 / 2 is 2 (an int). Use int(a / b) when you need whole-number division. Operators has the full rule.
  • % (remainder) takes the sign of the left side: -7 % 3 is -1.
  • Division by zero gives na, not infinity. So does x % 0, and any result that would overflow to infinity.
  • Comparisons of floats are exact. 0.1 + 0.2 == 0.3 is false, as in most languages; compare with a tolerance (math.abs(a - b) < 1e-9) or round first.
  • For display, round to the market's tick size with math.round_to_mintick or format with format.mintick.

#Good to know

  • A bool cannot hold "unknown". If you need three states (yes / no / not yet), use an int (1, -1, na) or an enum.
  • Collections and objects are passed by reference: a function that pushes onto an array you gave it changes your array. Plain values (numbers, strings, colors, bools) are copied.
  • Types also decide what you can call: close.size() fails because a float has no method size, the same check that stops ta.sma("abc", 10).

The ChartScript documentation is in English for now; translations will follow.