millionchart
فارسی

Text and number formatting

Write text with quotes, build messages with formatted text, control decimals, signs, percentages and times, and know which braces belong to the alert server.

Text appears in labels, tables, alert messages and plot titles. This page shows how to write it, how to put numbers in it, and how to make the numbers look right.

Quotes and escapes#

A text is written in double or single quotes. Either kind may hold the other. A backslash starts an escape:

WriteMeans
\na new line
\ta tab
\" \' \\the quote or the backslash itself
\u{1F600}the character with this code (one to six hex digits)

Triple quotes hold several lines and anything inside them:

Cuprel
indicator "Text in labels"
    edition = 1
    display = price

if bar.is_last
    label.new(
        bar.index,
        high,
        """Last bar
Quotes "like this" and 'this' are fine""",
        style = label_down,
    )
plot(close)

Join texts with +. A number joined to a text becomes its plain text ("a" + 1 is a1); to choose the decimals or the sign, use a formatted text.

Formatted text#

f"..." is a text with expressions inside braces. After a colon you say how to write the value.

Cuprel
indicator "Formatted text"
    edition = 1
    display = price

let change = close - close[1]
let share = close / close[1] - 1
if bar.is_last
    let t = table.new(top_right, 2, 4)
    table.cell(t, 0, 0, "Close")
    table.cell(t, 1, 0, f"{close:price}")
    table.cell(t, 0, 1, "Change")
    table.cell(t, 1, 1, f"{change:+.2f}")
    table.cell(t, 0, 2, "Change %")
    table.cell(t, 1, 2, f"{share:+.2%}")
    table.cell(t, 0, 3, "Bar")
    table.cell(t, 1, 3, f"{bar.index:06}")
plot(close)
FormatValueResult
{x:.2f}3.141593.14
{x:.0f}4318.084318
{x:,.2f}1234567.8911,234,567.89
{x:+.1f}0.5+0.5
{x:.1%}0.25625.6%
{x:03}7007
{x:price}a pricethe price with the symbol's own number of decimals
{x}any valuethe value as plain text (true, 2999)

A missing number (na) is written na. Give a fallback after a question mark:

FormatValueResult
{x:.1f}nana
{x:.1f?'n/a'}nan/a

A time is written with the format time(...), which takes a pattern and a time zone:

Cuprel
indicator "Time in text"
    edition = 1
    display = price

input zone: text = "Asia/Tehran", name = "Clock zone"
if bar.is_last
    label.new(
        bar.index,
        high,
        f"{bar.time:time('HH:mm', zone)} {bar.time:time('yyyy-MM-dd', 'UTC')}",
    )
plot(close)

An unknown format is an error and names the format:

Cuprel · error E2021
indicator "Unknown format"
    edition = 1
if bar.is_last
    label.new(bar.index, high, f"{close:10.2f}")
plot(close)

Braces for the character itself are doubled: f"{{x}}" is the text {x}. A brace that is neither closed nor doubled is E1010.

A text in single or double quotes must be closed on the same line (E1001); only a triple-quoted text may span lines. A quote of the other kind may nest inside the braces: f"{'a'}".

Alert placeholders are not f-text#

The alert server fills words in double braces, {{ticker}} and the like, in a plain text. (Alerts on your own scripts are switched off in this release, but the rule holds for the text you write.) Inside an f-text the double brace is the character itself, so f"{{ticker}}" is {ticker}. The checker warns about it:

Cuprel · warning W-FTEXT-PLACEHOLDER
indicator "Placeholder in an f-text"
    edition = 1
    display = price

alert.when(close > open, "Up", message = f"{{ticker}} closed up")
plot(close)

Write the placeholder as a plain text: "{{ticker}} closed up". Alert keys and options lists the placeholders.

Text functions#

The text group has the usual helpers. Most can also be written with a dot.

Cuprel
indicator "Text functions"
    edition = 1
    display = price

let clock = "10:30"
let parts = clock.split(":")
let hours = text.to_number(parts.at(0))
let minutes = text.to_number(parts.at(1))
plot(hours * 60 + minutes, name = "Minutes since midnight")
if bar.is_last
    label.new(bar.index, high, text.upper("done") + " " + text.of(close, tick))
FunctionGives
text.length(s)the number of characters
text.upper(s) text.lower(s)the text in capitals or lower case
text.contains(s, part)true if part is in s
text.replace(s, from, to)s with the first from replaced
text.slice(s, start, end)the characters from start up to, not including, end
text.split(s, separator)an array of the pieces
text.match(s, pattern)the first part of s that fits the pattern, or an empty text (see Patterns, below)
text.to_number(s)the number written in s, or na
text.fmt(x, format)a number written with a format such as ".2f" or ",.2f"; an unknown format is E-FMT-SPEC
text.of(x, format)a number as text, with a pattern such as "#.##" or tick

A text one call builds may hold at most 1,000,000 characters.

Patterns#

text.match(s, pattern) looks in s for the first part that fits a pattern and gives that part as a text. When nothing fits, it gives an empty text. A pattern that is only a word, such as "USD", is a plain search.

Cuprel
indicator "A pattern"
    edition = 1

let digits = text.match("order-2048-x", "[0-9]+")
plot(text.to_number(digits), name = "The number in the text")

The pattern reader of the chart knows:

  • ordinary characters, and . for any character except the end of a line;
  • classes such as [a-z] and [^0-9], and the shorthands \d, \w, \s and their opposites \D, \W, \S;
  • ^ and $ for the start and the end of the text, and \b and \B for a word boundary;
  • groups ( ) and (?: ), which only group: the call always gives the whole match;
  • | for a choice, and the repeats *, +, ?, {n}, {n,} and {n,m}, each with a ? after it to take as little as possible.

It does not read back-references, look-ahead, look-behind, named groups, \p{…} or \cX; a pattern that uses one is E-REGEX-FEATURE. A pattern past the limits on Limits and budgets is E-LIMIT-REGEX. A pattern that is only malformed, an open bracket for example, gives an empty text. Every step of the reader counts towards the steps of the bar, so a pattern on a very long text ends in E-LIMIT-OPS and can never keep a script busy beyond its budget.

See also: Alert keys and options, Tables, Units and literals.