You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pine Script布林格网格策略中如何跟踪持仓并条件平仓

布林格网格策略重复开仓&未平仓问题修复

问题背景

我希望策略最多持有3个多头/空头仓位,因此定义了跟踪仓位状态的变量:

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

原本计划开仓时将变量设为true,平仓时设为false,以此避免重复开仓,但当前策略会重复开3个long1仓位且从未平仓。

布林格网格策略逻辑

使用1、2、3倍标准差的3组布林带执行交易:

  • 多头:在1倍下轨(lower1)开long1仓位,2倍下轨(lower2)开2倍仓位的long2,3倍下轨(lower3)开3倍仓位的long3
  • 空头:对应1倍上轨(upper1)、2倍上轨(upper2)、3倍上轨(upper3)开仓
  • 所有仓位触碰布林带中轨时平仓

问题根源

跟踪仓位状态的变量是普通变量,每根K线都会被重新初始化为false,导致之前的开仓状态无法保留:

  • 开仓条件每次都会被触发,重复开仓
  • 平仓条件中的状态判断失效,无法执行平仓操作

在Pine Script v5中,必须使用var关键字定义持久化变量,才能让变量值在K线之间保留,不会被重置。

修正后的完整代码

// 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="从指定日期开始回测",
     group="回测时间范围")
backtest_start_date = input.time(timestamp("1 Jan 2021"), 
     title="开始日期", group="回测时间范围",
     tooltip="该开始日期基于交易品种所在交易所的时区,而非图表或电脑时区。")

strategy(
     title="布林格网格策略", 
     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 = "布林带时间周期", defval = "D")
bb_length = input.int(title = "布林带周期长度", 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)

// 跨周期获取布林带数据(使用前一根K线值避免未来函数)
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)

// 仓位ID定义
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

// 使用var定义持久化状态变量,仅在脚本初始化时赋值一次
var in_long1 = false
var in_long2 = false
var in_long3 = false
var in_short1 = false
var in_short2 = false
var in_short3 = false

// 多头开仓逻辑
if long1_entry_cnd and not in_long1
    in_long1 := true
    strategy.entry(long1_id, strategy.long, qty=long1_size)

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

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

// 多头平仓逻辑
if long_close_cnd
    if in_long1
        in_long1 := false
        strategy.close(id=long1_id, qty=long1_size)
    if in_long2
        in_long2 := false
        strategy.close(id=long2_id, qty=long2_size)
    if in_long3
        in_long3 := false
        strategy.close(id=long3_id, qty=long3_size)

// 空头平仓逻辑
if short_close_cnd
    if in_short1
        in_short1 := false
        strategy.close(id=short1_id, qty=short1_size)
    if in_short2
        in_short2 := false
        strategy.close(id=short2_id, qty=short2_size)
    if in_short3
        in_short3 := false
        strategy.close(id=short3_id, qty=short3_size)

// 绘制布林带
plot(middle_bb, color=color.white, title="中轨")
plot(upper_bb_1, color=color.yellow, title="1倍上轨")
plot(lower_bb_1, color=color.yellow, title="1倍下轨")
plot(upper_bb_2, color=color.orange, title="2倍上轨")
plot(lower_bb_2, color=color.orange, title="2倍下轨")
plot(upper_bb_3, color=color.red, title="3倍上轨")
plot(lower_bb_3, color=color.red, title="3倍下轨")

关键修正点

  1. 用var关键字替换普通变量定义,确保状态变量在K线间持久化,不会被逐K线重置
  2. 简化逻辑判断:用not in_long1替代in_long1 == false,代码更简洁
  3. 优化中文注释,提升代码可读性

内容的提问来源于stack exchange,提问作者M.wol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:15:39