In TradingView, we can choose a colour from one of the basic colour variables or use a hexadecimal colour value. But how do we apply colours so that we get a gradient-like colouring effect?

In this article:

Shades of colours: applying gradient-like colours in TradingView

In TradingView we can work with basic TradingView colours and hexadecimal colour values. And after we’ve used one of those colours in our Pine script, we can also change the script’s colours by hand. But what about gradient-like colours?

The idea behind gradient colours is to have different colour tints to highlight different values, like a pronounced colour when the value is high while a light shade accompanies low values. To start with the bad news, there currently isn’t a TradingView function that generates a colour that ranges from dark to light depending on how high or low a number is.

However, we can create our own function that returns different colour shades. One kind of colours that we can use with such a function are monochromatic colours, which are the different tints, tones, and shades from a single colour (Wikipedia, 2016). For example, with the ColorHexa website we can generate a few of these colours (including their hexadecimal values) for green and red:

Examples of the monochromatic red and green colours

The middle squares here are the main green (hexadecimal #00ff00) and red (#ff0000) colours, while the colours on the left have darker tint while a progressively lighter tint is shown in the right squares. Now, let’s see how we can use these colour shades in TradingView.

Using gradient-like colours with a custom function in TradingView

In the example below we create a histogram that plots the number of ticks in a price bar. Whenever the bar closed higher, we make the histogram bar green; otherwise, it’s given a shade of red. We use two custom functions that return one of the colours from the image above. We’ll also look at how the indicator displays on the chart, but first the code:

study(title="Gradient-like colours", overlay=false, precision=0)

// Input
useWholePips = input(title="Base ticks on whole pips (fx)?", 
    type=bool, defval=false)

// Custom functions
GreenShade(value) =>
    value >= 75 ? #00b300 : // dark green
     value > 50 ? #00cc00 :
     value > 30 ? #00e600 :
     value > 20 ? #00ff00 : // green
     value > 15 ? #1aff1a :
     value > 10 ? #33ff33 :
        #4dff4d             // light green

RedShade(value) =>
    value >= 75 ? #b30000 : // dark red
     value > 50 ? #cc0000 :
     value > 30 ? #e60000 :
     value > 20 ? #ff0000 : // red
     value > 15 ? #ff1a1a :
     value > 10 ? #ff3333 :
        #ff4d4d             // light red

// Calculate the ticks in the bar
tickCorrection = useWholePips ? 0.1 : 1

ticksInBar = ((high - low) / syminfo.mintick) * 
    tickCorrection

// Determine plot colour
plotColour = (close > open) ? 
    GreenShade(ticksInBar) :
    RedShade(ticksInBar)

// Perform the plotting
plot(series=ticksInBar, style=histogram, linewidth=4,
     color=plotColour)
hline(price=0, linestyle=dotted)

We start with study(), a function that’s required for every indicator (TradingView, n.d.). We set three of its arguments here: title (which specifies the indicator’s name), overlay (that, when set to false, displays the indicator in a subchart), and precision. That argument specifies how many digits to show after the decimal point of the indicator’s values (TradingView, n.d.).

Then we add an input option to the script:

useWholePips = input(title="Base ticks on whole pips (fx)?", 
    type=bool, defval=false)

Inputs are made with input(), and this function also returns the input’s value (TradingView, n.d.). We create a true/false checkbox here by setting the function’s type argument to bool (Pine Script Language Tutorial, n.d.). The title argument specifies the name that’s placed before the input option (see image below), and here we set that name to “Base ticks on whole pips (fx)?”.

We’re going to calculate the number of ticks in the price bar later on, and with this input option we’ll differentiate between whether we should use pips or fractional pips as the measure of ‘ticks’ in forex. For now, we set the input’s checkbox to disabled by default (defval=false) and assign the input’s value to the useWholePips variable for use later on.

Next we create the first custom function:

GreenShade(value) =>
    value >= 75 ? #00b300 : // dark green
     value > 50 ? #00cc00 :
     value > 30 ? #00e600 :
     value > 20 ? #00ff00 : // green
     value > 15 ? #1aff1a :
     value > 10 ? #33ff33 :
        #4dff4d             // light green

We create multi-line functions by typing in the name of the function (GreenShade here) and then place any argument(s) that the function uses in the parentheses behind the function’s name (here we have one argument: value). Then we type the function declaration operator (=>) followed by the function’s code that we indent with four spaces or one tab (Pine Script Language Tutorial, n.d.). The function’s returned value is the last expression or variable declaration. In our case, this is the multi-line expression that compares the value argument against several hard-coded numbers.

Our GreenShade() function returns a green colour from the image shown above. In the function itself we use several conditional (ternary) operators (?:) that evaluate the function’s value argument. This operator works on a true/false condition as well as a second and third value. Whenever that true/false condition is true, the conditional operator returns its second value. And when the condition is false, its third value is returned (Pine Script Language Tutorial, n.d.).

In the function we’ve combined a whole series of conditional operators to compare the function’s value argument against the literal values of 75, 50, 30, 20, 15, and 10. These numbers are an arbitrary chosen amount of ticks per bar, ranging from a ‘high’ amount to a ‘low’ amount of ticks.

The first conditional operator evaluates whether value is greater than or equal to (>=) 75. When it is, this operator returns #00b300. That hexadecimal colour value is the darkest shade of green from the image above. When value is not 75 or greater, the next conditional operator is processed.

That one checks whether value is greater than (>) 50. When that’s true, this conditional operator returns #00cc00 (our second darkest shade of green). When this condition is false, the next conditional operator is executed.

That third one evaluates if value is above (>) 30 and returns the #00e600 hexadecimal colour when that’s the case. Should this condition also be false, then code execution continues to the fourth conditional operator. The condition of that operator looks to see if value is greater than 20. If it is, then the operator returns #00ff00. That hexadecimal colour value is the middle shade of green from the image above.

Now when the function’s argument is also not above 20, the next conditional operator executes. It true/false condition is value > 15 and, when true, returns the #1aff1a hexadecimal colour. Should the condition of this conditional operator also be false, then TradingView Pine processes the last conditional operator.

That one evaluates whether value is greater than (>) 10. When it is, this conditional operator returns #33ff33. However, when value is below 10, then the last conditional operator returns #4dff4d. That value is the hexadecimal colour value of the lightest shade of green in the image above.

The value that’s returned by one of these conditional operators is also the value that’s returned by the GreenShade() function.

The second custom function returns a red colour and is much like the first:

RedShade(value) =>
    value >= 75 ? #b30000 : // dark red
     value > 50 ? #cc0000 :
     value > 30 ? #e60000 :
     value > 20 ? #ff0000 : // red
     value > 15 ? #ff1a1a :
     value > 10 ? #ff3333 :
        #ff4d4d             // light red

The RedShade() function also requires one argument (value), and compares this argument against several literal integers (75, 50, 30, 20, 15, and 10) with a range of conditional (ternary) operators (?:). The only difference between this function and GreenShade() is that now the red colours from the previous image are returned, from the darkest red (#b30000) up to regular red (#ff0000) and ending with light red tint (#ff4d4d).

Whichever condition of the conditional operators here evaluates to true and whichever hexadecimal colour value is returned, that returned value is also the outcome of the RedShade() function.

After creating the custom functions we figure out how many ticks there are in the current bar:

tickCorrection = useWholePips ? 0.1 : 1

ticksInBar = ((high - low) / syminfo.mintick) * 
    tickCorrection

The tickCorrection variable is assigned, with the help of a conditional (ternary) operator (?:), a value of 0.1 or 1 depending on useWholePips. That input variable holds a value of true whenever its checkbox is enabled and a value of false when this input option is disabled.

We use the tickCorrection variable with the next statement, which computes the value for the ticksInBar variable. That variable is set to the bar’s range (high - low) divided by syminfo.mintick, a built-in variable that returns the minimum tick size for a symbol (TradingView, n.d.). For instance, the EuroStoxx 50 Index CFD has a minimum price change of 1 point while the S&P 500 index, as well as many stocks, have a minimum price fluctuation of 0.01.

With forex symbols, however, the equivalent of a tick is a ‘pip’ which are based on quotes with four (like 1.4586) or two decimals in the case of Yen crossrates (Babypips.com, n.d.). However, most forex brokers nowadays quote forex in 5 or 3 decimals, and these minimum price changes are called ‘fractional pips’ or ‘pipettes’ (Babypips.com, n.d.).

We’ve added the “Base ticks on whole pips?” input option so that the bar’s range can be displayed in pips (and not fractional pips). When that input is enabled, the ticksCorrection variable is set to 0.1. The bar’s range is then multiplied by that value and stored in the ticksInBar variable. That way the minimum price change of forex symbols is converted from fractional pips to regular pips. Thanks to the input option, this is an optional feature of our example script. This means that, when GBP/USD has a high of 1.45860 and low of 1.44750, we wouldn’t calculate that range as 1110 ticks but as the more familiar 111 pips.

After calculating the bar’s range we determine the histogram’s colour:

plotColour = (close > open) ? 
    GreenShade(ticksInBar) :
    RedShade(ticksInBar)

The plotColour variable is assigned a value with the conditional (ternary) operator (?:). The condition that’s evaluated is whether the bar closed higher (close > open). When it did, we call the GreenShade() function and use the ticksInBars variable with the bar’s range as the function’s argument. The shade of green returned by this function is then stored in the plotColour variable for use later.

If the bar didn’t close higher (the ‘else’ portion of the conditional operator), then the RedShade() function is executed with the bar’s range (ticksInBar) as the function’s argument. This function call returns a shade of red, and that colour is stored in plotColour then.

With the plot colour determined, it’s time to plot the histogram itself:

plot(series=ticksInBar, style=histogram, linewidth=4,
     color=plotColour)
hline(price=0, linestyle=dotted)

The plot() function displays the data of its series argument on the chart (TradingView, n.d.). Here we set that argument to ticksInBar, our variable with the bar’s range in number of ticks. These values are plotted as a histogram by setting the style argument to histogram. The linewidth argument, which sets the plot’s size (TradingView, n.d.), is set to 4 to create the thickest histogram bars possible. The colour of these bars is set to the different shades of green and red that we’ve stored in the plotColour variable.

Then we use hline(), a function that creates a horizontal line at a fixed price level (TradingView, n.d.). We place that line at 0 and set its style to dotted. This gives a nice visual effect since the histogram bars now seem to be placed on the zero line.

Applying gradient-like colours to a TradingView histogram

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

Example of gradient colours in TradingView Pine

While the colour differences are modest, the two highest histogram bars have a darker tint while a less pronounced colour is used for histogram values between 25 and 50. The smallest histogram bars are displayed with the lightest colours.

If we switch from the 30-minute time frame to 2-hour bars, the gradient-like histogram looks like:

Gradient colours applied to the EuroStoxx 50 chart in TradingView

When we add the example indicator to a 30-minute GBP/USD chart, it looks like:

Gradient colours on a TradingView forex chart

The colour of the histogram bars isn’t that differentiated now with nearly all bars having the same green or red shade. This happens because the script treats fractional pips as ticks by default, and nearly all of the bars score above 75 – which is the ‘cutoff value’ for applying the darkest shade of green and red by our functions.

To change this behaviour, we need to enable the script’s input option. That would make the ticks calculate on whole pips:

Input options of our TradingView Pine script

After enabling that input, the script considers 10 fractional pips as one tick. Now the gradient-like colours of the GBP/USD histogram are more pronounced:

Example of a TradingView Pine script that uses gradient colours

For other applications of colours in TradingView, see using a ‘random’ colour in TradingView and ‘turning off’ a colour in Pine programmatically. The colours that we can code with in TradingView are the basic TradingView colours as well as the hexadecimal colour values.

Summary

With hexadecimal colour values it’s possible to use gradient-like colours in TradingView. For this we need to order colours in a way, like from light to dark, and then return one of those colours based on a value or range of values. One way to implement this is with a custom function that evaluates its argument against other values, and then returns a certain colour based on that comparison. Such an evaluation can be done with the iff() function, if/else statements, or the conditional (ternary) operator. That operator evaluates a condition and, when the condition is true, returns its second value while its third value is returned whenever the condition is false.


References

Babypips.com (n.d.). What is a Pip in Forex? Retrieved on February 9, 2016, from http://www.babypips.com/school/preschool/how-to-trade-forex/pips-and-pipettes.html

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 9, 2016, from https://www.tradingview.com/study-script-reference/

Wikipedia (2016, January 17). Monochromatic color. Retrieved on February 8, 2016, from https://en.wikipedia.org/wiki/Monochromatic_color