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 ProfitsIn Pine Script send stop loss and take profit orders by using the
limitparameters for the
strategy.order()functions. In fact, the
strategy.entry()function also supports sending
limitorders. 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 OrdersThere are a couple of the reasons why people can sometimes find plotting the stop loss and take profit lines a little challenging:
- They are using the
lossparameters instead of
- They calculate the stop loss and/or profit level once at the time of entry.
lossare 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
stopof a long entry at
ATR(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.
ExampleBefore we move into a solution, let’s run through a quick example of placing
ifstatement in case you are having trouble visualizing it. The example below will calculate the
stoplevel and only send the order once when a
//@version=3 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:
Plotting SolutionThe 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
seriesat 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.
//@version=3 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 long_profit_level := longCondition ? close + ATR : long_profit_level short_stop_level = na short_profit_level = na short_stop_level := shortCondition ? high + ATR : short_stop_level short_profit_level := shortCondition ? close - ATR : short_profit_level 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)
CommentaryBefore 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
long_stop_level = nafirst. This is because the code is written in version 3 of pinescript and if we want to reference a previous value of the same
long_stop_level), 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
- If not, keep the previous value.
On the ChartsOnce plotted, the chart should look like this:
A Simple Alternative for Fixed % Stops / ProfitsIf 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)
//@version=3 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 CommentaryWhen we don’t have a position in the market the
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.
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.