pine-scripttradingalgorithmic-tradingstrategy-patternback-testing

How to keep track of opened positions and close conditionally in Pine Script Bollinger Grid strategy


I want to have up to 3 longs or 3 shorts. To keep track what positions I have opened, I have control variables defined at the beginning. Description of Bollinger Grid Strategy: Use 3 Bollinger bands for 1,2 and 3 std dev. Open long at lower1, open long2 at lower2 for twice size, open long3 at lower3 for x3 size. Similarly shorts, but at upper bands. close all at middle.

in_long1 = false
in_long2 = false
in_long3 = false
in_short1 = false
in_short2 = false
in_short3 = false

and set them up to true on entry() and false on close(). This is done to prevent opening next position on the next close of bar and wait for the condition to appear. Even though, my strategy open 3 longs1 and never close them. Full script below:

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © VVolski
//@version=5
initial_capital = 1000
margin_long = 0
margin_short = 0

use_date_filter = input.bool(true, title="Begin Backtest at Start Date",
     group="Backtest Time Period")
backtest_start_date = input.time(timestamp("1 Jan 2021"), 
     title="Start Date", group="Backtest Time Period",
     tooltip="This start date is in the time zone of the exchange " + 
     "where the chart's instrument trades. It doesn't use the time " + 
     "zone of the chart or of your computer.")

strategy(
     title="BB grid", 
     overlay=true,
     precision=5,
     pyramiding=3,
     default_qty_type=strategy.percent_of_equity,
     initial_capital=initial_capital,
     margin_long=margin_long,
     margin_short=margin_short
     )

bb_tf = input.timeframe(title = "BB TF", defval = "D")
bb_length = input.int(title = "Length", defval = 20)
bb_std_dev_1 = 1
bb_std_dev_2 = 2
bb_std_dev_3 = 3

[middle1, upper1, lower1] = ta.bb(close, bb_length, bb_std_dev_1)
[middle2, upper2, lower2] = ta.bb(close, bb_length, bb_std_dev_2)
[middle3, upper3, lower3] = ta.bb(close, bb_length, bb_std_dev_3)

middle_bb = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = middle1[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
upper_bb_1 = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = upper1[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
lower_bb_1 = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = lower1[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
upper_bb_2 = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = upper2[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
lower_bb_2 = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = lower2[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
lower_bb_3 = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = lower3[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
upper_bb_3 = request.security(symbol = syminfo.tickerid, timeframe = bb_tf, expression = upper3[1], gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)

long1_id = "long1"
long2_id = "long2"
long3_id = "long3"
short1_id = "short1"
short2_id = "short2"
short3_id = "short3"

long1_size = 10
short1_size = 10
long2_size = long1_size * 2
short2_size = short1_size * 2
long3_size = long1_size * 3
short3_size = short1_size * 3

long1_entry_cnd = close[1] <= lower_bb_1
long2_entry_cnd = close[1] <= lower_bb_2
long3_entry_cnd = close[1] <= lower_bb_3
short1_entry_cnd = close[1] >= upper_bb_1
short2_entry_cnd = close[1] >= upper_bb_2
short3_entry_cnd = close[1] >= upper_bb_3

long_close_cnd = close[1] >= middle_bb
short_close_cnd = close[1] <= middle_bb

in_long1 = false
in_long2 = false
in_long3 = false
in_short1 = false
in_short2 = false
in_short3 = false

if long1_entry_cnd and in_long1 == false
    in_long1 := true
    strategy.entry(long1_id, strategy.long, qty=long1_size)


if long2_entry_cnd and in_long2 == false
    in_long2 := true
    strategy.entry(long2_id, strategy.long, qty=long2_size)


if long3_entry_cnd and in_long3 == false
    in_long3 := true
    strategy.entry(long3_id, strategy.long, qty=long3_size)

if long_close_cnd
    if in_long1 == true
        in_long1 := false
        strategy.close(id=long1_id, qty=long1_size)
    if in_long2 == true
        in_long2 := false
        strategy.close(id=long2_id, qty=long2_size)
    if in_long3 == true
        in_long3 := false
        strategy.close(id=long3_id, qty=long3_size)


if short_close_cnd
    if in_short1 == true
        in_short1 := false
        strategy.close(id=short1_id, qty=short1_size)
    if in_short2 == true
        in_short2 := false
        strategy.close(id=short2_id, qty=short2_size)
    if in_short3 == true
        in_short3 := false
        strategy.close(id=short3_id, qty=short3_size)


plot(middle_bb, color=color.white)
plot(upper_bb_1, color=color.yellow)
plot(lower_bb_1, color=color.yellow)
plot(upper_bb_2, color=color.orange)
plot(lower_bb_2, color=color.orange)
plot(upper_bb_3, color=color.red)
plot(lower_bb_3, color=color.red)

Solution

  • In pinescript,

    in_long1 = false
    

    set in_long1 to false each time the script is executed.
    You should use :

    var in_long1 = false
    

    This will initialize the in_long1 variable to false only the first time.