In TradingView we can use a basic colour as well as a hexadecimal colour value. But how do we apply colours in such a way that we get a random-like colour?

In this article:

Colouring in TradingView based on random-like numbers

Typically, when colouring something like a plot or background in TradingView we pick a basic colour or a hexadecimal colour. Another approach is to have TradingView Pine randomly choose from a list of colours to get a nice visual effect. However, TradingView currently doesn’t have a function that can generate random-like numbers.

Luckily, we can generate our own pseudo-random numbers. A pseudo-random number is a number that’s predictable (because, for instance, it’s generated by a mathematical formula) but that appears unpredictable. But for practical purposes, pseudo-randomness more than suffices.

One approach that generates such numbers is with the Linear Congruential Generator (LCG), which in its classical form looks like (Wikipedia, 2016):

Formula of the classical Linear Congruential Generator

For convenience we can drop the addition with c; the formula then simply becomes n = a * n mod m. What this formula does is taking a starting value (n, which is called the seed) and performs some math on it. The outcome is the random number that becomes the seed for generating the next random number. This shows that these numbers are not truly random since they partly depend on the previous value.

The trick with using this formula is choosing the right numbers that we multiply and perform modulus by; with the wrong numbers, the resulting sequence is not random-like but has a repeating pattern instead. Luckily, researchers looked into this and found that 16708 (for a) and 2,147,483,647 (for m) are the ‘best’ numbers (Pinder, n.d.). Now, let’s see how we can use this formula in TradingView.

Quick example: generating random-like numbers in TradingView

We can implement the classical LCG in TradingView as follows:

study(title="Random numbers example", overlay=false)

x = 16708 * nz(x[1], 1) % 2147483647

plot(series=x % 17, style=histogram, linewidth=3)

This example starts with the study() function to define the indicator’s name and to set the overlay argument. That argument with a value of false makes the script display in a separate chart panel (TradingView, n.d.).

Then we declare the x variable and assign it a random value based on the formula discussed above. We use x as the variable name instead of n because this latter is already used by TradingView itself. In the formula we reference the random value on the previous bar by using the history referencing operator: x[1].

Since that can return a NaN (“not a number”) value when we try to reference a previous bar value when there’s no previous bar (Pine Script Language Tutorial, n.d.), we use the nz() function to replace those invalid values with 1 (TradingView, n.d.). And so nz(x[1], 1) returns the previous value of x unless that value is NaN, in which case it returns 1. This way we prevent our computations from being messed up by a single NaN value that propagates itself on every bar through the calculations.

Then we call the plot() function to display the values on the chart. Instead of setting this function’s series argument to the x variable with the random value, we set it to x % 17. We use the modulus operator (%) here since there are 17 basic TradingView colours and x modulo 17 returns a value that’s between 0 and 16. This way we can implement random colours by matching each of those 17 numbers to one of the 17 colour variables.

We set the style argument of the plot() function to histogram to display the data as histogram bars. And with the linewidth argument set to 3 these bars displays with almost the thickest size possible.

Note: A conditional colour, like the one that we use here with plot(), cannot be used with every TradingView function. The fill() and hline() functions don’t accept conditional colours, while the barcolor(), bgcolor(), plot(), plotarrow(), plotbar(), plotcandle(), plotchar(), and plotshape() functions do accept a colour value that can change per bar (TradingView, n.d.).

When we add the above example to the chart, it looks like:

Example of random values in TradingView A TradingView histogram with randomly generated values

As we can see here, the values plotted in the histogram look quite random. Now let’s look at how we can use this approach to do some random colouring.

Applying colours in TradingView randomly

The above example is expanded on below as follows: whenever a new 20-bar high or 20-bar low occurs, we’ll colour the chart’s background with one of the 17 colour variable. Which colour is used depends on the value of the pseudo-random number. After going through the example’s code we’ll look at charts showing the indicator.

study(title="Random colouring", overlay=true)

// Inputs
highLen = input(title="Highest high period", type=integer, defval=20)
lowLen  = input(title="Lowest low period", type=integer, defval=20)

// Determine random value
x = 16708 * nz(x[1], 1) % 2147483647

// Function that returns a random colour based on the
// random value in `x`
RandomColour() =>
    y = x % 17
    y == 0 ? aqua :
     y == 1 ? black :
     y == 2 ? blue :
     y == 3 ? fuchsia :
     y == 4 ? gray :
     y == 5 ? green :
     y == 6 ? lime :
     y == 7 ? maroon :
     y == 8 ? navy :
     y == 9 ? olive :
     y == 10 ? orange :
     y == 11 ? purple :
     y == 12 ? red :
     y == 13 ? silver :
     y == 14 ? teal :
     y == 15 ? white :
        yellow
    
// Determine colour of background bars
bgColour = 
    (high == highest(high, highLen)) ? RandomColour():
    (low  == lowest(low, lowLen)) ? RandomColour() :
        na

// Colour bar background
bgcolor(color=bgColour, transp=80)

We start with the study() function that’s required for every indicator (see Pine Script Language Tutorial, n.d.). With its title argument we set the script’s name and with overlay set to true the script displays overlaid on the chart’s instrument (TradingView, n.d.).

Then we create two input options:

highLen = input(title="Highest high period", type=integer, defval=20)
lowLen  = input(title="Lowest low period", type=integer, defval=20)

Manual input options are added to the a script with input(), and this function also returns the input’s current value (TradingView, n.d.). Both inputs that we make here are numerical integer inputs, which are created by setting the input() function’s type argument to integer.

The first input is named “Highest high period” with the title argument, and this name is what’s placed before the input option in the script’s settings (see image further down below). We set the default value (defval) of this input to 20 and track its current value in the highLen variable. That variable is used later on when retrieving the highest high price for the last 20 bars.

The other input is named “Lowest low period” and also starts off with a value of 20 (defval=20). We assign this input’s value to the lowLen variable, which we’ll use later on when computing the lowest low price.

Then we calculate the random value (just like in the previous example) and create a multi-line function:

x = 16708 * nz(x[1], 1) % 2147483647

RandomColour() =>
    y = x % 17
    y == 0 ? aqua :
     y == 1 ? black :
     y == 2 ? blue :
     y == 3 ? fuchsia :
     y == 4 ? gray :
     y == 5 ? green :
     y == 6 ? lime :
     y == 7 ? maroon :
     y == 8 ? navy :
     y == 9 ? olive :
     y == 10 ? orange :
     y == 11 ? purple :
     y == 12 ? red :
     y == 13 ? silver :
     y == 14 ? teal :
     y == 15 ? white :
        yellow

We create a multi-line function by declaring the function’s name (RandomColour here) and optionally list the function’s arguments in parentheses (our function doesn’t take in arguments). Then we place the function declaration operator (=>) behind the function’s name, followed by the function’s code indented with four spaces or 1 tab. The last of these statements is the value that’s returned by the function (Pine Script Language Tutorial, n.d.).

The code of our RandomColour() function begins with setting the y variable to the remainder of diving x (our random value) with 17, a value that we compute with the modulus operator (%). With this calculation, y will hold a value that ranges from 0 (when x divides evenly into 17) to 16. With these 17 different values we can return one of the 17 basic TradingView colours for each value of y.

The code for that is in the second part of the function, which consists out of several conditional (ternary) operators (?:) that each evaluate y against one of 16 numbers. That operator works on three values. The first is a true/false condition that, when true, makes the conditional operator return the second value. And whenever that condition is false, the operator will return its third value (Pine Script Language Tutorial, n.d.).

The first conditional operator evaluates if y is equal to (==) 0. When it is, the aqua colour is returned by the operator and, since the last statement of our function is this series of conditional operator, that colour is also what’s returned by RandomColour(). But when y isn’t 0, the next conditional operator is processed.

That one checks is y equals 1. If that’s the case, the black colour is returned. Otherwise, the next conditional operator is executed. This goes on until code execution arrives at a conditional operator with a true condition, which means that this process can continue all the way down to the last conditional operator that evaluates y == 15. When that condition is true, this last conditional operator returns white. Otherwise, when this last condition is false (which also means that all the preceding ones were false too), then the last conditional operator returns yellow.

With the RandomColour() function made, we use it when setting the value of the bgColour variable:

bgColour = 
    (high == highest(high, highLen)) ? RandomColour():
    (low  == lowest(low, lowLen)) ? RandomColour() :
        na

That bgColour variable is assigned here one of three values with the help of two conditional operators. The first evaluates whether the high of the current bar (high) equals (==) the value returned by the highest() function. We use that function with the high and highLen arguments, and that makes it return the highest high for the number of bars set by the “Highest high period” input option (up to, and including, the current bar). And so whenever the current bar’s high is the highest high, then the conditional operator calls the RandomColour() function which, in turn, returns one of the 17 colours. That colour is subsequently stored in the bgColour variable.

When the high of the current bar isn’t the highest high for the last 20 bars, the second conditional operator is processed. That one checks whether the low of the current bar (low) equals (==) the lowest low of the last 20 bars (including the current bar). We retrieve that extreme price with the lowest() function and with the low variable and lowLen input variable passed in as arguments. Now when the current bar’s low is indeed the lowest low, then this conditional operator also calls the RandomColour() function. Whichever colour that’s returned by this function is then stored in the bgColour variable.

Should the true/false condition of the second conditional operator also be false, then this last operator returns na. That built-in variable returns a “not a number” value (TradingView, n.d.) which, when used as a colour, has the effect of ‘turning off’ colouring in TradingView (Pine Script Language Tutorial, n.d.).

What this means is that the bgColour variable holds a random colour whenever the current bar reaches the 20-bar high or 20-bar low. And when the bar didn’t reach one of those extreme prices, then bgColour holds a value that performs no colour.

After setting the bgColour variable we use it for colouring:

bgcolor(color=bgColour, transp=80)

The bgcolor() function colours the chart’s background from top to bottom (TradingView, n.d.). Here we set its colour to bgColour, meaning the background is either set to a random colour or a ‘turned off’ colour (in which case we won’t see an effect). The transp argument of bgcolor(), which sets the background’s transparency with a value ranging from 0 (no transparency) to 100 for invisibility (TradingView, n.d.), is set to 80 here to create a background that’s mildly transparent.

Randomly colouring the background of TradingView bars

When we add the example script to a chart of the EuroStoxx 50 Index CFD, it looks like:

Randomly colouring the background of TradingView bars

The example indicator creates the following input options:

Input options of the TradingView example indicator

When we set the ‘Highest High Period’ input to 10 and the ‘Lowest Low Period’ to 25, then the previous chart changes to:

Random colouring in TradingView

Here we see that, while a couple of extra bars got a coloured background, the background colour for the majority of the bars remains the same. That’s because our pseudo-random number is implicitly linked to the number of bars on the chart, and that seed doesn’t change each time the script calculates again. A better seed for generating pseudo-random numbers is the current date and time (since that value changes always and is unique each time). However, we currently cannot retrieve the current time in TradingView Pine.

For more applications of colouring in TradingView, see creating gradient-like colours and ‘turning off’ colours conditionally in Pine. The kind of colours that are available in TradingView are the basic TradingView colours as well as the hexadecimal colour values that allow for thousands of colours.

Summary

TradingView currently doesn’t have a function that returns a pseudo-random number. Instead, we can calculate our own random-like numbers with formulas like the classical linear congruential generator. One way to implement this is to pass that random value into a custom function, which compares that value against several hard-coded values and returns the accompanying predefined colour as the function’s result. Those comparisons can be made with the conditional ternary operator (?:), iff() function, or if/else statements.


References

Pinder, C. (n.d.). Game Programming: Random Number Generation. Retrieved on February 10, 2016, from https://www.christianpinder.com/articles/pseudo-random-number-generation/

Pine Script Language Tutorial (n.d.). Retrieved on October 23, 2015, from https://docs.google.com/document/d/1sCfC873xJEMV7MGzt1L70JTStTE9kcG2q-LDuWWkBeY/

TradingView (n.d.). Script Language Reference Manual. Retrieved on February 10, 2016, from https://www.tradingview.com/study-script-reference/

Wikipedia (2016, February 1). Linear congruential generator. Retrieved on February 10, 2016, from https://en.wikipedia.org/wiki/Linear_congruential_generator