Search code examples
pine-scriptpine-script-v5tradingview-api

Stop Losses with unique Entry IDs close other entries


I'm trying to create a strategy that keeps a separate stop loss for each entry. To achieve this, I append consecutive numbers to each entry name.

Here's an example strategy:

//@version=5
strategy(title="Example Strategy", overlay=true, pyramiding=5)

// Entries storage.
var longId = 1
var longs = array.new<string>()

// These are just for the sake of creating a reasonable number of entries for the testing.
// They shouldn't matter for the problem itself.
backtestStartDate = timestamp("1 Jan 2020")
backtestEndDate = timestamp("1 Jan 2021")
inTradeWindow = time >= backtestStartDate and time < backtestEndDate
var currentOrder = 1
var ordersLimit = 5
var barsBetweenEntries = 5
var barsSinceLastEntry = barsBetweenEntries
// -----------------------------------------------------

if inTradeWindow
    if currentOrder <= ordersLimit and barsSinceLastEntry == barsBetweenEntries
        stopLossPrice = low*0.8

        entryName = "LE#" + str.tostring(longId)

        strategy.entry(entryName, strategy.long)
        strategy.exit(entryName + "#SL", from_entry=entryName, stop=stopLossPrice)

        log.info("Entry " + entryName + " @ " + str.tostring(close) + ", SL " + str.tostring(stopLossPrice))
        
        longs.push(entryName)
        longId += 1
        currentOrder += 1
        barsSinceLastEntry := 0
    else
        barsSinceLastEntry += 1
else if inTradeWindow[1]
    strategy.cancel_all()
    strategy.close_all(comment="Date Range Exit")

Here's the log for BTCUSDT 1D:

[2020-01-01T01:00:00.000+01:00]: Entry LE#1 @ 7200.85, SL 5740.12
[2020-01-07T01:00:00.000+01:00]: Entry LE#2 @ 8145.28, SL 6178.968
[2020-01-13T01:00:00.000+01:00]: Entry LE#3 @ 8110.34, SL 6444.712
[2020-01-19T01:00:00.000+01:00]: Entry LE#4 @ 8701.7, SL 6772.8
[2020-01-25T01:00:00.000+01:00]: Entry LE#5 @ 8340.58, SL 6603.92

And here's the chart for BTCUSDT 1D:

enter image description here

In "List of Trades" panel, I get the following trades:

List of Trades

As you can see, stop losses are all over the place: reaching LE#4#SL closes LE#1, reaching LE#5#SL closes LE#2 etc.

I assume it has something to do with pyramiding since such issues could not occur with only one trade at a time.

I have no idea what might be causing this. I thought these two lines should keep the connection between an entry and its stop loss:

strategy.entry(entryName, strategy.long)
strategy.exit(entryName + "#SL", from_entry=entryName, stop=stopLossPrice)

Clearly, this is not the case so I must be missing something.

Also, in my actual strategy I had the same problem when stop losses were called on different bars (in the test above, they are all called on the same bar).


Solution

  • You are on the right track. If you want to close trades individually, you need to specify individual trade ids.

    However, by default, the trades will be closed on FIFO based. You need to set close_entries_rule parameter of strategy() to "ANY".

    Then all you need to do is make sure you areusing the correct trade ids for from_entry of strategy.exit().

    close_entries_rule (const string) Determines the order in which trades are closed. Possible values are: "FIFO" (First-In, First-Out) if the earliest exit order must close the earliest entry order, or "ANY" if the orders are closed based on the from_entry parameter of the strategy.exit function. "FIFO" can only be used with stocks, futures and US forex (NFA Compliance Rule 2-43b), while "ANY" is allowed in non-US forex. Optional. The default is "FIFO".