Reputation: 2192
I managed to simplify this so I can paste a whole snippet to reproduce this problem. This script, when run on ETHUSDT.P for Binance in Trading View Strategy Tester using the 15 minute chart (important because the timestamps will fail otherwise):
//@version=5
strategy("Multiple Positions Strategy", overlay=true, pyramiding=2)
if timestamp("2023-06-10T11:00:00-07:00") <= time_close and time_close < timestamp("2023-06-10T11:15:00-07:00")
strategy.entry('id1', strategy.long, 1)
if timestamp("2023-06-10T11:00:00-07:00") <= time_close and time_close < timestamp("2023-06-10T11:15:00-07:00")
strategy.exit('id1', 'id1', limit = 1763)
if timestamp("2023-06-11T09:00:00-07:00") <= time_close and time_close < timestamp("2023-06-11T09:15:00-07:00")
strategy.entry('id2', strategy.long, 1)
if timestamp("2023-06-11T09:00:00-07:00") <= time_close and time_close < timestamp("2023-06-11T09:15:00-07:00")
strategy.exit('id2', 'id2', limit = 1751)
Will cause the following to show in the List of Trades tab:
Trade # | Type | Signal |
---|---|---|
2 | Exit Long | id1 |
Entry Long | id2 | |
1 | Exit Long | id2 |
Entry Long | id1 |
Even though both trades are wins, the strategy tester will show that the first trade is a loss (-0.48%) and the second is a larger win (1.31%) than I believe it was. This can especially affect drawdown unfairly, so it's a problem even if the overall PnL might be accurate.
I am experiencing an issue with pinescript in trading view's strategy tester where my trades are getting mixed up due to order ids not matching as expected. Here's the "list of trades"
Trade #1
Type: Entry Long
Signal: Long Trade 770
Type: Exit Long
Signal: Exit Long 772
Trade #2:
Type: Entry Long
Signal: Long Trade 772
Type: Exit Long
Signal: Exit Long 787
Trade #3:
Type: Entry Long
Signal: Long Trade 787
Type: Exit Long
Signal: Open
note that the trades should actually occur in the order (and this is reflected in the strategy tester overview):
Enter long #770
Enter long #772
Exit long #772
Enter long #778
Exit long #778
(#770 never exits because limit is never reached)
My understanding is that the entry and exit ids should match for each trade. However, as seen above, the exit for trade #1 has the same id as the entry for trade #2, which seems to be causing some confusion.
Here is the relevant part of my code:
//@version=5
strategy(title = 'My Signal', shorttitle='MY_MAIN', overlay=true, max_bars_back=300,max_boxes_count=500, max_lines_count=500, max_labels_count=500, pyramiding=5000)
...
if (bar_index == 787 or bar_index == 770 or bar_index == 772)
if (myCondition) // Defined above this snippet
candleHigh := open
exitLongLine := line.new(x1=bar_index, y1=candleHigh, x2=bar_index+1, y2=candleHigh, color=color.red, width = 1)
strategy.entry("Long Trade " + str.tostring(bar_index), strategy.long)
strategy.exit("Exit Long " + str.tostring(bar_index), "Long Trade " + str.tostring(bar_index), limit=candleHigh)
Based on the Pine Script v5 documentation for strategy.exit() and strategy.entry(), I am under the impression that the from_entry parameter in strategy.exit() should match the id of the corresponding strategy.entry() call. However, this does not seem to be the case in my script.
While the visual appears to be correct, the net profits are incorrect (consistent with the incorrect list of trades.
Can anyone help me understand what might be causing this discrepancy, and how to ensure the correct matching of trade entry and exit ids?
I tried a more understandable example using the first few candles which match. The reason I'm filtering out only certain ids is because I want to simplify it for purposes of troubleshooting, but the same issue shows up when I don't filter:
Here, I filter only 19, 20, 21, and 36:
Trade # | Type | Signal |
---|---|---|
4 | Exit Short | ShortTrade21 |
Entry Short | ShortTrade32 | |
3 | Exit Short | ShortTrade32 |
Entry Short | ShortTrade21 | |
2 | Exit Long | ShortTrade21 |
Entry Long | LongTrade20 | |
1 | Exit Long | LongTrade20 |
Entry Long | LongTrade19 |
However, when I precede each entry with a
strategy.close_all()
Then I get something more expected:
Trade # | Type | Signal |
---|---|---|
4 | Exit Short | ShortTrade32 |
Entry Short | ShortTrade32 | |
3 | Exit Short | Close Position Order |
Entry Short | ShortTrade21 | |
2 | Exit Long | LongTrade20 |
Entry Long | LongTrade20 | |
1 | Exit Long | Close Position Order |
Entry Long | LongTrade19 |
The full code looks like this:
bool longCondition = ...
bool shortCondition = ...
if (bar_index == 19 or bar_index == 20 or bar_index == 21 or bar_index == 32)
if (longCondition)
redCandleHigh := open
trade_id := "LongTrade" + str.tostring(bar_index)
strategy.close_all() // <-- Maybe
strategy.entry(trade_id, strategy.long)
strategy.exit(trade_id, trade_id, limit=candleHigh)
else if (shortCondition)
greenCandleLow := open
trade_id := "ShortTrade" + str.tostring(bar_index)
strategy.close_all() // <-- Maybe
strategy.entry(trade_id, strategy.short)
strategy.exit(trade_id, trade_id, limit=candleLow)
if (barstate.islast)
strategy.close_all()
Thanks!
Upvotes: 1
Views: 698
Reputation: 36
add close_entries_rule="ANY" to your strategy
@version=5
strategy("Multiple Positions Strategy", pyramiding=2, close_entries_rule="ANY")
to close relative entry from
Upvotes: 0
Reputation: 3108
Here is what happen with your code :
if (bar_index == 19 or bar_index == 20 or bar_index == 21 or bar_index == 32)
if (longCondition)
redCandleHigh := open
trade_id := "LongTrade" + str.tostring(bar_index)
strategy.close_all() // <-- Maybe
strategy.entry(trade_id, strategy.long)
strategy.exit(trade_id, trade_id, limit=candleHigh)
You are at bar_index == 19 and your longCondition == true :
So you will have a strategy.entry named LongTrade19
And a strategy.exit named LongTrade19
Only the strategy.entry is executed : you see Entry Long LongTrade19
Then you are at bar_index == 20 and your longCondition == true :
So you will have a strategy.entry named LongTrade20
And a strategy.exit named LongTrade20
The strategy.entry and strategy.exit are executec : you see, on the same candle your exit and entry for LongTrade20
In fact in your first array in your 'Addition' part, you misinterpret when your orders are executed, you should consider this :
Trade # | Type | Signal |
---|---|---|
4 | Exit Short | ShortTrade32 |
Entry Short | ShortTrade32 | |
3 | Exit Short | ShortTrade21 |
Entry Short | ShortTrade21 | |
2 | Exit Long | LongTrade20 |
Entry Long | LongTrade20 | |
1 | - | - |
Entry Long | LongTrade19 |
EDIT :
this part of your code :
if (barstate.islast)
strategy.close_all()
will close all your trade at each end of the bar !
Upvotes: 0