TradingView colours can be used conditionally in indicators and trading strategies. But how do we select one of several colours with if/else statements?

In this article:

Using conditional colours in TradingView with if/else statements

In the code of TradingView scripts we can use basic TradingView colours as well as any of the millions of hexadecimal colour values. After we’ve used a colour in the code of an indicator or strategy, we can change the script’s colours by hand. It’s even possible to programmatically ‘turn off’ colouring.

The standard use of colours is to apply the same colour on every bar, like when plotting a red oscillator line or a yellow moving average. However, when we use colours conditionally it’s possible to visually communicate information, like highlighting the chart’s background when a certain event happens.

Note: Not every TradingView function accepts a colour that’s set conditionally: the fill() and hline() function’s can’t work with conditional colours, while the barcolor(), bgcolor(), plot(), plotarrow(), plotbar(), plotcandle(), plotchar(), and plotshape() functions do allow conditional colours (TradingView, n.d.).

Conditional colours can be programmed in several ways, like setting colours with the conditional operator and using the iff()function for conditional colours. Another approach is using an if/else statement.

That kind of statement evaluates a true/false expression (which is a statement that returns a value). When that expression is true, the if/else statement executes the code that’s below its if portion. Should that true/false expression be false, then the code below else is processed (Pine Script Language Tutorial, n.d.).

And so the logic of an if/else statement is: ‘if this condition is true, then execute the following statement(s); otherwise, execute the other statement(s)’ (Liberty & MacDonald, 2009).

Quick example: setting a colour with an if/else statement in TradingView

Besides executing code conditionally, TradingView’s if/else statements also make it possible to set a variable’s value conditionally. For instance, assigning a colour to a variable with an if/else statement basically looks like (see Pine Script Language Tutorial, n.d.):

colourVariable = if (condition)
    some colour
else
    another colour

Here we set colourVariable to one of two colour values, depending on whether the condition in parentheses is true or false.

A quick example that uses an if/else statement to plot in one of two colours is:

//@version=2
study(title="conditional colours with if/else - example", overlay=true)

maColour = if (volume > volume[1])
    blue
else
    yellow

plot(series=sma(close, 20), color=maColour)

We store either the blue or yellow basic TradingView colour in the maColour variable here with an if/else statement. That statement evaluates whether the current bar’s volume (volume) is greater than (>) the volume of the previous bar (volume[1]). When that’s the case, we store the blue colour in the maColour variable; otherwise, that variable is assigned yellow. Then we plot a 20-bar moving average with plot() and set that function’s color argument to the maColour variable.

Setting colours in TradingView strategy with if/else statements

An elaborative example that sets a colour with if/else statements is the example strategy below. This script goes long whenever the bar closes above the 20-bar high and opens a short position with a close below the lowest low of the last 20 bars. Once there’s an open position, the strategy submits a trailing stop-loss of 150 ticks. One of the plotted lines is conditionally coloured green, red, or orange whenever the strategy’s open position is profitable, losing, or when there’s no open position. We look at charts showing the script after discussing the following code:

//@version=2
strategy(title="Conditional colours with if/else", overlay=true)

// Inputs
lookback    = input(title="Lookback Period", type=integer, defval=20, minval=5)
trailOffset = input(title="Trail offset (ticks)", type=integer, 
     defval=150, step=10)

// Compute values
highestHigh = highest(high, lookback)[1]
lowestLow   = lowest(low, lookback)[1]
avgLine     = (highestHigh + lowestLow) / 2

// Determine strategy conditions
longSignal  = (close > highestHigh) and (close[1] < highestHigh[1])
shortSignal = crossunder(close, lowestLow)

// Enter positions
strategy.entry(id="EL", long=true, when=longSignal)
strategy.entry(id="ES", long=false, when=shortSignal)

// Submit trailing stops
strategy.exit(id="XL", from_entry="EL", trail_offset=trailOffset, 
     trail_points=-10)
strategy.exit(id="XS", from_entry="ES", trail_offset=trailOffset, 
     trail_points=-10)

// Determine middle line colour
lineColour = if (strategy.position_size != 0)
    tmpColour = if (strategy.openprofit < 0)
        red
    else
        green
    tmpColour
else 
    orange

// Plot values
plot(series=highestHigh, color=#1E90FF, title="Highest high")
plot(series=lowestLow, color=#1E90FF, title="Lowest low")
plot(series=avgLine, color=lineColour, title="Mid line", linewidth=2)

We start with a comment saying @version=2 to make it possible to use the if statement (Pine Script Language Tutorial, n.d.). Then we set the strategy’s properties with the strategy() function, which needs to be added to every strategy (TradingView, n.d.). With this function’s title argument we give our strategy a name while the overlay argument, when set to true, displays the strategy on the main price chart and not in a separate subchart.

Then we add two input options:

lookback    = input(title="Lookback Period", type=integer, defval=20, minval=5)
trailOffset = input(title="Trail offset (ticks)", type=integer, 
     defval=150, step=10)

The input() function adds an input setting to a TradingView script and also returns the input option’s current value (TradingView, n.d.). Here both inputs are numerical integer inputs, which we make by setting the function’s type argument to integer.

The first input is named “Lookback period” with the title argument, and this text is what’s placed before the input in the script’s settings (the inputs are shown in an image further down below). We set this input to a default value of 20 (defval=20) and the minval argument, which sets the minimum value of a numerical input (TradingView, n.d.), is set to 5. We assign the input’s value to the lookback variable, and we use that variable later when determining the number of bars to get the highest and lowest value of.

The second input is named “Trail offset (ticks)” and has a default value of 150. We store its value in the trailOffset variable which we use when submitting the strategy’s exit orders. The step argument, which defines the step value for incrementing and decrementing the input’s value in the settings window (TradingView, n.d.), is set to 10 here. That way each click on the input’s numerical up/down control or the arrow up/down keyboard keys changes this input with 10.

With the inputs made, we compute the script’s values:

highestHigh = highest(high, lookback)[1]
lowestLow   = lowest(low, lookback)[1]
avgLine     = (highestHigh + lowestLow) / 2

The highestHigh variable is set here to the value returned by highest(). We use that function with two arguments: a series of values (to get the highest value of) and a number that sets the number of bars to get the highest value of (TradingView, n.d.). For the first argument we use the bar’s high prices (high) while we set the second to lookback, the input variable that we set to a default value of 20.

Because the high variable also includes the current bar high, we place the history referencing operator ([]) with a value of 1 just behind the highest() function. That way we get the highest high of the last 20 bars, without the current bar’s high. We need that because, if the highest high includes the current bar, we cannot check if the current bar crossed above the highest high.

We set the value for the lowestLow variable in the same way by having the lowest() function compute on low values for a lookback amount of bars. And with the history referencing operator placed behind this function we get the lowest low without the current bar’s value.

The third variable that we make is avgLine, which is set to the average of the highest high and lowest low ((highestHigh + lowestLow) / 2). This midpoint value is what we’re going to plot later on with a conditional colour.

With the values calculated we determine the trading conditions:

longSignal  = (close > highestHigh) and (close[1] < highestHigh[1])
shortSignal = crossunder(close, lowestLow)

This longSignal variable is set to a true/false value based on two expressions. Since these are combined with the and logical operator, both expressions need to be true before the entire condition is also true (Pine Script Language Tutorial, n.d.). The first expression checks whether the close of the current bar (close) is greater than (>) the highest high of the last 20 bars (highestHigh). The second evaluates if the previous bar’s close (close[1]) was less than (<) that bar’s highest high (highestHigh[1]). When both expressions are true, then the current bar’s close crossed above the highest high of the last 20 bars.

The shortSignal variable has its true/false value set with the crossunder() function. That function returns true when its first argument is less than the second argument on the current bar, while the first argument was greater than the second argument on the previous bar (TradingView, n.d.). Since we pass the close and lowestLow variables in this function, it means that crossunder() only returns true here whenever the current bar’s close dropped below the lowest low of the preceding 20 bars.

Besides crossunder() there’s also a crossover() function. Both are a handy way to check whether some value crossed under/above another value. That’s because they don’t require the and logical operator and several comparison operators (as we did when determining the value of the longSignal variable).

With the long and short conditions defined, we open a position:

strategy.entry(id="EL", long=true, when=longSignal)
strategy.entry(id="ES", long=false, when=shortSignal)

The strategy.entry() function submits buy and sell orders to open a position and, when there’s already an open position, can reverse that position (Pine Script Language Tutorial, n.d.).

We set the order identifier of the first entry order to “EL” (enter long; id="EL"). Since the long argument is set to true, this order will open a long position (TradingView, n.d.). We specify when that order is submitted with the when argument, which is set to the longSignal variable here. And so whenever that variable is true (which happens when the bar closes above the 20-bar high) our enter long order is send.

The second strategy.entry() function call looks the same. Now we name the order “ES” (enter short) and set the long argument to false to have it submit an enter short order. The when argument is set to shortSignal, a variable that holds a value of true only when the current bar dropped below the 20-bar low.

Next up are the trailing stop-losses:

strategy.exit(id="XL", from_entry="EL", trail_offset=trailOffset, 
     trail_points=-10)
strategy.exit(id="XS", from_entry="ES", trail_offset=trailOffset, 
     trail_points=-10)

The strategy.exit() function closes market positions, and cannot submit an order when there’s no open position or active entry order (Pine Script Language Tutorial, n.d.). That means we cannot accidentally open a position with strategy.exit() in our script.

The first strategy.exit() statement has order identifier set to “XL” (exit long). The from_entry argument specifies to which entry order the exit order should be applied (TradingView, n.d.), and here we set that argument to “EL” (our enter long order). We configure the trailing stop-loss with trail_offset and trail_points. The first specifies the trailing stop price in ticks, and we set that to the trailOffset input variable with a default of 150. The second, trail_points, specifies the trailing stop activation level in ticks (TradingView, n.d.). By setting that argument to -10 here the trailing stop-loss is submitted immediately when the position is opened.

The second strategy.exit() statement is much like the first with the same trailing stop-loss configuration. We name this exit order “XS” (exit short) and apply it to our “ES” (enter short) entry order.

With the order logic coded, we’re going to plot the highest high, lowest low, and midpoint values on the chart. Before doing so, we first determine the colour for the middle line with two if/else statements:

lineColour = if (strategy.position_size != 0)
    tmpColour = if (strategy.openprofit < 0)
        red
    else
        green
    tmpColour
else 
    orange

The lineColour variable that we make here is assigned one of three basic TradingView colours (red, green, or orange) with up to two if/else statements.

The first if/else statement evaluates whether the strategy.position_size variable is unequal to (!=) 0. That variable returns zero when the strategy is flat, a positive value indicating the position size when long, and a negative value with the strategy’s position size when short (TradingView, n.d.). And so the strategy is currently in the market whenever strategy.position_size has a value different than 0.

When that happens, we create a temporarily variable (tmpColour) that’s set to a colour returned by the second if/else statement. The condition of this if/else statement checks whether the open position’s unrealised profit/loss (returned by strategy.openprofit; TradingView, n.d.) is less than (<) 0. When the open position is indeed losing money, the red colour is returned and assigned to the tmpColour variable. If the open position is break-even or profitable (the else portion of this if/else statement), then green is returned and stored in tmpColour.

Regardless of whether the open position is profitable or not, the statement directly below this second if/else statement returns the tmpColour variable so that it’s ‘passed back’ into the first if/else statement and stored into the lineColour variable. This indeed looks needlessly cryptic, but is needed because TradingView Pine currently doesn’t support if/else-if/else statements.

One condition we still need to address, and that’s when the strategy is flat. In that case the condition of the first if/else statement evaluates to false, and so the else portion then executes and returns the orange colour. So after the first, and optionally the second, if/else statement are processed, the lineColour variable holds red when the strategy is losing money, green when the open position is profitable, and orange when there’s no open position.

After determining the colour for the middle line, we can plot all three lines so we can visually verify the strategy’s trades:

plot(series=highestHigh, color=#1E90FF, title="Highest high")
plot(series=lowestLow, color=#1E90FF, title="Lowest low")
plot(series=avgLine, color=lineColour, title="Mid line", linewidth=2)

We plot those values with plot(), a function that displays whichever data its series argument is set to (TradingView, n.d.). The first of these plot() statements has that argument set to highestHigh, the variable with the 20-bar highest high. The colour of that line (plot() makes lines by default; TradingView, n.d.) is set to the hexadecimal value of dodger blue (#1E90FF). The “Highest high” string is the value of the title argument, and that name will appear in the chart’s Data Window and when configuring the script’s colours manually.

The second plot displays the lowestLow variable on the chart. Those 20-bar lowest low values are also coloured dodger blue and this plot is named “Lowest low”. With the last plot() function call we display the line between the highest high and lowest low (whose value we stored in the avgLine variable). This plot is named “Mid line” and, with the linewidth argument set to 2, made slightly thicker than default (TradingView, n.d.). The colour of this line is set to the lineColour variable that we’ve just assigned one of three possible colour values with if/else statements.

Applying TradingView colours conditionally with if/else statements

When we add the above example strategy to a S&P 500 Index CFD chart, it looks like:

Example of TradingView strategy applied to the chart

In the left part of this chart the strategy enters a short position that’s losing at first (the middle line is coloured red) but becomes profitable after a couple of bars. When this position is closed around 6:00 hour, the middle line becomes orange again.

Our example strategy has the following input options:

Input options of the TradingView strategy

When we change the ‘Lookback Period’ setting to 10 and the trailing stop offset to 100 (so 10 S&P 500 index points), the previous chart changes to:

Colouring conditionally in a TradingView strategy

The ‘Trail Offset (Ticks)’ input option depends on the instrument’s price scale: with the S&P 500 Index CFD this input’s default value of 150 equals 15 points. But when the strategy is added to the EuroStoxx 50 CFD, where one tick is one point, the trailing stop-losses won’t trigger since they’re placed too far away from the price. Instead, the strategy just reverses the positions and is always in the market:

No trailing stops triggered with this TradingView strategy

When we change the trailing stop input option to for example 20 ticks, then the stops can be triggered and the previous chart becomes:

Triggering trailing stops with this TradingView Pine strategy

Other ways to use TradingView colours are setting colours conditionally with the iff() function and using a conditional operator when determining colours. The colour values that we can choose from are basic TradingView colours and hexadecimal colours, and it’s even possible to ‘turn off’ TradingView colours conditionally.

Summary

TradingView colours can be applied with the same colour on every bar. But it’s also possible to set colours conditionally. One way to do so is with an if/else statement, which first evaluates a true/false condition and then executes the statement(s) below the if portion (when the condition is true) or the statement(s) below else when the condition is false. TradingView’s if/else statements make it possible to execute code conditionally or to return a conditional value (like a colour) which we can then store in a variable. Several if/else statements are possible too, but for that we need to place one if/else statement inside another.


References

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

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