Tradingview: Plotting Stop Losses and Take Profits

In this article, we will take a quick look at plotting stop losses and take profits. This technique has actually been covered in a couple of posts on this site already but there has never been a dedicated article on the subject and requests for this subject still occasionally come in!

Plotting Stop Losses and Take Profits

In Pine Script send stop loss and take profit orders by using the stopandlimit parameters for the strategy.exit() and strategy.order()functions. In fact, the strategy.entry()function also supports sending stopandlimitorders. However, that would be considered an entry rather than a stop loss or take profit and thus out of the scope of this article. Having said that, the techniques used in this article can be used for entries and just about any line you want to track/plot.

Sending Orders

There are a couple of the reasons why people can sometimes find plotting the stop loss and take profit lines a little challenging:
  1. They are using the profitandlossparameters instead of stopandlimit
  2. They calculate the stop loss and/or profit level once at the time of entry.
The profitand loss are measured in ticks. As such, the numbers we use to feed these parameters do not provide a natural price level we can plot. As such, a bit more work would be required to plot the level. Note: For more information on the various stop-loss options, see this article. The second item in the list above is often utilized when users wish to use a more complex calculation for their stop and some parts of that calculation can change between bars. For example, one common request is to set the stop of a long entry at lowATR (Average True Range). If you don’t place strategy.exit() function inside an ifstatement, you can find that the stop line bounces around every bar as the ATRvalue is updated.


Before we move into a solution, let’s run through a quick example of placing strategy.exit()inside an ifstatement in case you are having trouble visualizing it. The example below will calculate the stop level and only send the order once when a longConditionorshortConditionis met.
strategy("My Strategy", overlay=true)

ATR = atr(7)

longCondition = crossover(sma(close, 100), sma(close, 200))
if (longCondition)
    stop_level = low - ATR
    profit_level = close + ATR
    strategy.entry("My Long Entry Id", strategy.long)
    strategy.exit("TP/SL", "My Long Entry Id", stop=stop_level, limit=profit_level)

shortCondition = crossunder(sma(close, 100), sma(close, 200))
if (shortCondition)
    stop_level = high + ATR
    profit_level = close - ATR
    strategy.entry("My Short Entry Id", strategy.short)
    strategy.exit("TP/SL", "My Short Entry Id", stop=stop_level, limit=profit_level)
This will result in a chart that looks something like this: Setting Stop losses and Take Profit example - Showing sending a stop / take profit once only

Plotting Solution

The key to plotting stop losses and take profits is to create a series (new line/variable) that is updated only when your stop-loss is updated. For example, if you only send a stop loss order once when the longConditionis met, then we similarly we only update our new series at that time too. Otherwise, we keep the same value as the previous bar. We can do this using something called a Ternary Conditional Operator. Click on that link for a more detailed tutorial on them. The example below will expand on the first example to both plot the lines and fix the levels.
strategy("My Strategy", overlay=true)

ATR = atr(7)

longCondition = crossover(sma(close, 100), sma(close, 200))
if (longCondition)

    strategy.entry("My Long Entry Id", strategy.long)

shortCondition = crossunder(sma(close, 100), sma(close, 200))
if (shortCondition)

    strategy.entry("My Short Entry Id", strategy.short)
long_stop_level = na
long_profit_level = na
long_stop_level := longCondition ? low - ATR : long_stop_level[1]
long_profit_level := longCondition ? close + ATR : long_profit_level[1]

short_stop_level = na
short_profit_level = na
short_stop_level := shortCondition ? high + ATR : short_stop_level[1]
short_profit_level := shortCondition ? close - ATR : short_profit_level[1]

strategy.exit("TP/SL", "My Long Entry Id", stop=long_stop_level, limit=long_profit_level) 
strategy.exit("TP/SL", "My Short Entry Id", stop=short_stop_level, limit=short_profit_level)
plot(strategy.position_size <= 0 ? na : long_stop_level, color=red, style=linebr, linewidth=2)
plot(strategy.position_size <= 0 ? na : long_profit_level, color=green, style=linebr, linewidth=2)
plot(strategy.position_size >= 0 ? na : short_stop_level, color=red, style=linebr, linewidth=2)
plot(strategy.position_size >= 0 ? na : short_profit_level, color=green, style=linebr, linewidth=2)


Before we start, It is worth noting that the example above could be achieved using valuewhen(). This is outlined in the Save a variable / store a value for later post. However, it is a good idea to become familiar with ternary conditional operators as they will allow you to create some complex and unique trailing stop losses. Although the code appears to be longer, there are actually only a few changes between the first example and this one. The first is that strategy.exit()is no longer to be placed inside an ifstatement. When we do this, we will start updating the order on every bar. However, since our value is not changing, then it doesn’t matter. Next, we calculate our levels. When we do this, we must declare each series with long_stop_level = na first. This is because the code is written in version 3 of pinescript and if we want to reference a previous value of the same series (e.g long_stop_level[1]), we will receive an error if we do not declare it first. The ternary conditional operators might seem daunting at first but they are essentially saying (for a long example):
  • If a longConditionis met, set the line at lowATR.
  • If not, keep the previous value.
Finally, we just do a little creative plotting to make sure we stop plotting the lines when we don’t want to see them. This just helps to keep things nice and tidy. Again we use a ternary conditional operator to do this.

On the Charts

Once plotted, the chart should look like this:

A Simple Alternative for Fixed % Stops / Profits

If you just simply want to set a stop loss or take profit at x% distance away from your entry level and you are NOT pyramiding (entering in the same direction multiple times), then you can just use the variable strategy.position_avg_priceto calculate the lines. (Note this example also features in the stop loss tutorial for Tradingview)
strategy("Stop Loss Example: Simple Stoploss", overlay=true)

sma_per = input(200, title='SMA Lookback Period', minval=1)
sl_inp = input(2.0, title='Stop Loss %', type=float)/100
tp_inp = input(4.0, title='Take Profit %', type=float)/100

sma = sma(close, sma_per)

stop_level = strategy.position_avg_price * (1 - sl_inp)
take_level = strategy.position_avg_price * (1 + tp_inp)

strategy.entry("Simple SMA Entry", strategy.long, when=crossover(close, sma))

strategy.exit("Stop Loss/TP","Simple SMA Entry", stop=stop_level, limit=take_level)

plot(sma, color=orange, linewidth=2)
plot(stop_level, color=red, style=linebr, linewidth=2)
plot(take_level, color=green, style=linebr, linewidth=2)
Mini Commentary
When we don’t have a position in the market the strategy.position_avg_pricevalue equals na. This is helpful for plotting because we are able to plot the stop loss line only when we are in a position. nais never plotted and therefore we don’t need to add a ternary conditional operator like in the example above. . Note: To ensure our lines are plotted tidily, the linebrstyle should be used. This will ensure that you don’t have long lines joining up gaps between when the value is na. You will see the difference if you just use a normal line style. Stop Losses: Simple Stop Loss

Find This Post Useful?

If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny.