How to calculate the number of bars since `strategy.entry`

Viewed 2666

I just started to code with PineScript and after several tries, I would like to ask for help.

I tried to calculate how many bars intercurred from the last long position entry. The question (or a similar one) has been asked several times, but I found that barssince() does not solve the problem. Simply, it does not work at all.

The strategy that I would like to test is the following: I would like to close a long position if the price goes down of 2.5% from the previous high. The previous high is not to be evaluated in a fixed length window (for example, in the last 10 bars or so) but it needs to be evaluated since the bar in which the long entry was done.

I tried to close a long position (opened with its id "buy") as following:

npastdays=barssince(strategy.position_size > 0)
    
prevHigh=highest(close, npastdays)
if (close < 0.975*prevHigh)
    strategy.close("buy")

I even tried something else, for example setting a "op" variable to a non-zero value when the long position is opened and than using "change(op > 0)" or, similarly, "crossover(op, value)". The "npastdays" variable is not calculated, either way, it stays undefined (n.d.).

Edit #1: I tried again to set op:=6.5 (any number would do it, or a bool value) when the long position is opened, and then:

npastdays=barssince(op==6.5)
if (npastdays!=0)   // else, I just opened a long position
    prevHigh=highest(close, npastdays)
    if (close < 0.975*prevHigh)
        strategy.close("buy")

I obtained a different error, "Pine cannot determine the referencing length of a series. Try using max_bars_back in the study or strategy function.". Still unsolved.

Edit #2: I tried, without success, to use the built-in "bar_index" with the instrucion "posLong := bar_index" when a long entry is done. However, the code works only with a fixed number of bars: even if I try to catch a negative nPastDays value (its first value appears to be -1096 but posLong should be > posLong[1]...)

// Determine trail stop loss prices
float longStopPrice = 0.0
int nPastDays = 4
float prevHigh = 0.0
longStopPrice := if (strategy.position_size > 0)
    nPastDays := posLong - posLong[1]
    if nPastDays > 0
        prevHigh := highest(close, nPastDays)
    else
        prevHigh := highest(close, 4)
    
    prevHigh * 0.975
    
//    stopValue = close * (1 - longTrailPerc)
//    max(stopValue, longStopPrice[1])
else
    0

// Submit exit orders for trail stop loss price
if (strategy.position_size > 0)
    strategy.exit(id="buy", stop=longStopPrice)

The interpreter gives an error about a negative nPastDays value or gives an error while suggesting to use max_bars_back. But I already set "max_bars_back=50" in the strategy declaration. Still unsolved.

3 Answers

There is a shortcut to what you want with barssince.

ta.barssince(strategy.position_size == 0)

Finally I solved the issue as follows. Right after "strategy.entry", I wrote:

var int nPastDays=0
if (strategy.position_size>0)
    nPastDays:=nPastDays+1

and then, right after "strategy.exit", I wrote:

if (strategy.position_size == 0)    
    nPastDays:=0

It works :-) without "using bar_index".

this might work

a = strategy.position_size != strategy.position_size[1]
barssince(a)
Related