close()
,close_all()
and exit()
as the meaning of the three functions is quite similar. Furthermore, he noted that they all do provide a method of closing a position. Hopefully, this article will help clear up some of that confusion as we will have a little look at each function and its ideal usage.The Documentation:
Before we do that though, we should take a look at the official documentation. Don’t forget you can control + click (or command + click for Mac users) on any function whilst in the Pine editor to bring up the relevant info. In general, the documents do tend to provide enough information. However, if you are a beginner, you might find some terms used or the large blocks of text a little daunting to read and decipher.
As such, it can sometimes ease digestion if we break down the key statements into simple bullet points.
strategy.close
- If there were multiple entry orders with the same ID, all of them are exited at once.
- If there are no open entries with the specified ID by the moment the command is triggered, the command will not come into effect.
- The command uses a market order.
- Every entry is closed by a separate market order.
Usage: strategy.close(id, when) → void
- If there is no open market position by the moment the command is triggered, the command will not come into effect.
strategy.close_all(when) → void
strategy.exit
- If an order with the same ID is already pending, it is possible to modify the order.
- If an entry order was not filled, but an exit order is generated, the exit order will wait till entry order is filled and then the exit order is placed.
- To deactivate an exit order, the command strategy.cancel or strategy.cancel_all should be used.
- If the function strategy.exit is called once, it exits a position only once.
- If you want to exit multiple times, the command strategy.exit should be called multiple times.
- If you use a stop loss and a trailing stop, their order type is ‘stop’, so only one of them is placed (the one that is supposed to be filled first).
- If all the following parameters ‘profit’, ‘limit’, ‘loss’, ‘stop’, ‘trail_points’, ‘trail_offset’ are ‘NaN’, the command will fail.
To use a market order to exit, the command strategy.close or strategy.close_all should be used.
strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, oca_name, comment, when) → void
Summary
After breaking the documentation down into bullet points, we can see the key takeaways are:
strategy.close()
should be used if you want to use a market order to exit a specific entry of a position.strategy.close_all()
should be used if you want to use a market order to exit the WHOLE position.strategy.exit()
should be used if you want to use astop
orlimit
order to exit a position.
The tutorial doesn’t end there though. After all, it wouldn’t be much of a tutorial if this article just regurgitated the documentation and told you how to read it! Instead, we shall scratch beneath the surface and show an example of each.
Before continuing it is worth noting that strategy.exit()
has been covered in some detail previously as part of the Stop Losses tutorial.
Example Notes:
All of the following examples are designed to run on the daily timeframe. We will simply use the dayofweek
variable to determine whether to enter a position. Furthermore, we will enter different positions on different days of the week, allowing us to have more than one long position open at a time. Finally, for the eagle-eyed readers, it should be pointed out that we don’t actually enter on the day of the week in which we triggered the trade. For example, in the snippets below, we refer to a Monday trade, hower this actually enters on Tuesday morning because the entry order is sent after the close on Monday.
close() vs close_all()
Let’s start simple. strategy.close()
will close a single entry whereas strategy.close_all()
will close all entries for the whole position. In practical terms, if you do not allow more than one entry in the same direction, the two functions will do the same thing. It is only if we have multiple entries where we can start to see the difference.
Take the following example:
//@version=3 // Simple Example Code // Designed to play around with Tradingview's close, close_all and exit functions strategy("Close and Exit Testing", overlay=true) testStartYear = input(2018, "Backtest Start Year") testStartMonth = input(08, "Backtest Start Month") testStartDay = input(01, "Backtest Start Day") testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0) longCondition = time >= testPeriodStart and dayofweek == monday if (longCondition) strategy.entry("Monday", strategy.long) strategy.close("Monday", when=dayofweek == friday) //strategy.close_all(when=dayofweek == friday)
The example contains both close methods. However, strategy.close_all()
is commented out. We will un-comment that in a moment for comparison. Our code will just buy on Monday and sell on Friday. It shall only enter one position. As such, you will be able to see that the two methods essentially do the same thing.
Running The Example
With the default code above, we should see a chart that looks like this (of course, the price data will change according to the stock/asset you are looking at!)
Next, comment out the strategy.close()
line and replace it with the strategy.close_all()
line like so:
//strategy.close("Monday", when=dayofweek == friday) strategy.close_all(when=dayofweek == friday)
Then run the script again:
You will see that only the purple text actually changes between the two. One is telling us that it is an order to close the Monday entry whilst the other is telling us it is an order to close the position. Again, because we have only one entry, they are essentially the same.
Adding a second entry
When we add a second entry, we can begin to see the difference between the two methods. In the following example, we add a second entry on Wednesday and allow pyramiding. We then compare the results between the two we can see that strategy.close()
only ever closes out our Monday order. Our Wednesday order is filled at the start and is never closed.
//@version=3 // Simple Example Code // Designed to play around with Tradingview's close, close_all and exit functions strategy("Close Example", overlay=true, pyramiding=2) testStartYear = input(2018, "Backtest Start Year") testStartMonth = input(09, "Backtest Start Month") testStartDay = input(01, "Backtest Start Day") testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0) // Stop us from entering two wednesday positions when pyramiding is on // This would prevent us entering a monday position. wedEntered = na wedEntered := nz(wedEntered[1], false) monCondition = time >= testPeriodStart and dayofweek == monday wedCondition = time >= testPeriodStart and dayofweek == wednesday and (not wedEntered[1]) if (monCondition) strategy.entry("Monday", strategy.long) if (wedCondition) wedEntered := true strategy.entry("Wednesday", strategy.long) strategy.close("Monday", when=dayofweek == friday)
Note that in the code above a wedEntered
variable has also been added. This is to combat the mechanics of pyramiding. Essentially, if you don’t prevent a second Wednesday entry after the first, we can end up with two Wednesday entries and no Monday entries. This is because there might be a bank holiday on a Monday. Therefore, we would close the Monday position and Friday and miss the chance to re-open it on Monday. Wednesday then rolls around and we enter our second position. Now we have two Wednesday positions and order to close Monday will never trigger because there are no Monday entries. This gives the illusion that the script is no longer buying or selling.
If you are a little lost reading the above paragraph, don’t worry too much. The key to all this is to simply understand that the Wednesday order is never closed by our strategy.close()
order!
Note: You can run the example above without the wedEntered
parts and it will run as you might expect for a few weeks until a bank holiday appears.
As we can see in the first example, we only ever close a Monday position. Wednesday always remains open. Conversely, in the second example, both positions are closed at the end of the week.
Now we can switch to using close_all(). We can also remove the wedEntered
code as it is no longer needed. This is because we expect both positions to be closed at the end of the week and therefore there is no chance of getting stuck like in the first example.
//@version=3 // Simple Example Code // Designed to play around with Tradingview's close, close_all and exit functions strategy("Close Example", overlay=true, pyramiding=2) testStartYear = input(2018, "Backtest Start Year") testStartMonth = input(09, "Backtest Start Month") testStartDay = input(01, "Backtest Start Day") testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0) monCondition = time >= testPeriodStart and dayofweek == monday wedCondition = time >= testPeriodStart and dayofweek == wednesday if (monCondition) strategy.entry("Monday", strategy.long) if (wedCondition) strategy.entry("Wednesday", strategy.long) strategy.close_all(when=dayofweek == friday)
After running the above code, we can see that both entries are closed together on a Friday and are subsequently re-entered the following week.
strategy.exit() vs strategy.close()
As noted above, strategy.exit()
should be used for sending limit and stop orders rather than market orders. Other than that, it works the same way as strategy.close()
in that you can target a specific entry to be closed out by a stop/limit order.
Let’s take a look.
//@version=3 // Simple Example Code // Designed to play around with Tradingview's close, close_all and exit functions strategy("Close Example", overlay=true, pyramiding=2) testStartYear = input(2018, "Backtest Start Year") testStartMonth = input(09, "Backtest Start Month") testStartDay = input(01, "Backtest Start Day") testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0) // Stop us from entering two wednesday positions when pyramiding is on // This would prevent us entering a monday position. wedEntered = na wedEntered := nz(wedEntered[1], false) monCondition = time >= testPeriodStart and dayofweek == monday wedCondition = time >= testPeriodStart and dayofweek == wednesday and (not wedEntered[1]) if (monCondition) strategy.entry("Monday", strategy.long) strategy.exit("Monday TP", "Monday", limit=high) // Set a TP at the high of the signal candle. if (wedCondition) wedEntered := true strategy.entry("Wednesday", strategy.long)
The code above results in the following chart:
Just like the chart from the strategy.close()
example, we can see that the Wednesday entry is bought and held. We are simply taking out our Monday entry when the take profit is hit.
It is worth noting that the example above is for illustration only. The logic is a little flawed because when we use the high
of the signal candle as the take profit level. As such, it can result in the take profit being hit immediately after entering because we are already above it. Naturally, you would not want this in real life.
That should just about cover the basic differences between the three types of close. For a detailed look at the using strategy.exit()
with stop losses, you can take a look at this tutorial.
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.
Backtest Rookies is a registered with Brave publisher!
Brave users can drop us a tip.
Alternatively, support us by switching to Brave using this referral link and we will receive some BAT!
Referral Link
Enjoying the content and thinking of subscribing to Tradingview? Support this site by clicking the referral link before you sign up!
3HxNVyh5729ieTfPnTybrtK7J7QxJD9gjD
0x9a2f88198224d59e5749bacfc23d79507da3d431
M8iUBnb8KamHR18gpgi2sSG7jopddFJi8S
In a simple strategy I am working on, I buy when the MACD indicator crosses bullish and trail a stop below swing lows. Using the strategy.exit command works for this trailing stop method, however, I notice sometimes stops are triggered while the MACD indicator is still bullish and I rebuy back in on the next candle, causing some needless exiting.
To fix this, I was experimenting with swapping strategy.exit with strategy.close (or close_all) and adding a condition to the exit that MACD should be bearish for the close to happen in addition to the swing low being broken. This works, but what I am noticing is that my sell orders happen at the close of the candle and not at the stop level (swing low) as it passes through it. Ideally it would know MACD is currently bearish at the time it passes through the stop level and exit immediately.
Is there a way to have the strategy.close command happen instantly and not wait for the candle close? If it should close instantly after breaking that stop level, what do you think could be wrong with my code to make it wait for the candle closing? Maybe how I have MACD defined? It references the close (shown below)
fastMA = ema(close, fastLength)
slowMA = ema(close, slowLength)
macd = fastMA – slowMA
signal = sma(macd, signalLength)
Hi Ryan,
Unfortunately not during backtesting.
When forward testing, you could probably do this by setting “recalcuate every tick” on the strategy. It should then detect you have broken the level and close the order as soon as you tick below the level. However, your strategy will repaint when you refresh the browser as all the live data you received becomes historical so take a note of your performance.
The other option is to backtest on the 1-minute chart but import your MACD from an upper timeframe. Then when you cross below on the one minute chart, you can close it. This should be much closer to the level (but still not spot on). Also, note that when you are working with upper timeframe data, you need to be careful about repainting again with live data. There is another tutorial on the site that covers this.
Good luck!
Hi guys,
I am really struggling with exiting the position. How would I exit this after lets say 10 points profit or 5 points loss?
//@version=2
strategy(title=”Engulfing”, shorttitle=”Lng_Eng”, overlay=false)
t_close = close
t_open = open
y_close = security(“LSE:TSCO”, “D”, close[1])
y_open = security(“LSE:TSCO”, “D”, open[1])
if (t_close > y_open) and (t_open = 2018) and (t_close > t_open) and (y_open > y_close)
strategy.order(“My Long”, strategy.long, 1)
Hi people from BTR
Is it possible to get data from an indicator plotted on another time frame , lets say a sell signal plotted on the 6H time-frame and use it for direction on the 15m time-frame ? I saw that I could do this already using platforms like 3Commas. But there is time I want to know this..
thank you