Reputation: 13
I am having some trouble understanding the expected behavior of strategy.close()
.
After some testing/debugging of a very basic strategy, it seems that entries with strategy.entry()
are ok and are executed at the next bar open, but with strategy.close()
, the exits are happening on the bar where the exit condition is met, but they're happening as a market order at the open of that same bar instead of at the open of the next bar (which is actually what I was expecting with "process_orders_on_close = false
") or even at the close of the current bar where the exit condition is met.
Can someone please explain if what I describe above is what is expected of strategy.close()
or am I missing a setting or variable somewhere?
I am including my test strategy code below and a screenshot. It's not meant to be profitable or anything, just a demonstration of the issue.
Strategy summary:
I have added some debugging with plotshape() to understand where trades are being opened and closed.
I plot up triangles at the bottom when the long condition is met, and a trade is indeed entered on the next bar following the first triangle occurrence in each up triangle sequence below the candles.
I plot down triangles at the top when the exit condition is met, but here we observe that, although the exit condition is met at the candle where it is satisfied, we also see that the trade is closed at the open of that same candle used to evaluate the condition, before the information could technically be available. But the strategy tester is using it.
I also tried both "process_orders_on_close = true
" and "process_orders_on_close = false
", but this just shifts entries and exits by one bar and doesn't fix the issue.
//@version=5
strategy("test strategy", overlay=true, initial_capital = 10000)
// limit strategy time window
start = 0
finish = 0
start := input.time(timestamp('01 Jan 2000'), title=' ‣ From')
finish := input.time(timestamp('01 Apr 2024'), title=' ‣ To')
window() =>
time >= start and time <= finish ? true : false
o = open
h = high
l = low
c = close
activeTrade = false
longEntry = false
// Enter long when current close < previous low and no trade is active
if window() and (activeTrade == false ) and ( c < l[1] )
longEntry := true
activeTrade := true
// Exit long when currect close is above previous high and trade is active
if window() and (activeTrade == true ) and ( c > h[1] )
longEntry := false
activeTrade := false
if longEntry == true
strategy.entry("Long", direction=strategy.long)
if longEntry == false
strategy.close("Long") //immediate market close
plotshape(longEntry, style=shape.triangleup, location=location.bottom, color=color.green)
plotshape(c > h[1], style=shape.triangledown, location=location.top, color=color.red)
Dates where we can observe this using SPX on a daily timeframe:
Upvotes: 1
Views: 250
Reputation: 21294
Your understanding and the way you are trying to debug it are correct but you just need to be a little bit more careful.
Your whole market orders depend on one variable only. And that is longEntry
. If it is true
, you place your entry order. If it is false
you place your exit order. That's it. So, you just need to see what it is doing.
Whenever you don't see a triangle, it places the exit order.
There is no need to complicate things and you can use the built-in variables such as strategy.position_size
to do the same thing.
strategy.position_size
Direction and size of the current market position. If the value is > 0, the market position is long. If the value is < 0, the market position is short. The absolute value is the number of contracts/shares/lots/units in trade (position size).
You can write the same strategy as below:
time_cond = (time >= start and time <= finish)
entry_cond = time_cond and (strategy.position_size == 0) and (close < low[1])
exit_cond = time_cond and (strategy.position_size > 0) and (close > high[1])
if (entry_cond)
strategy.entry("Long", direction=strategy.long)
if (exit_cond)
strategy.close("Long") //immediate market close
Upvotes: 1