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倍下轨")
关键修正点
- 用
var关键字替换普通变量定义,确保状态变量在K线间持久化,不会被逐K线重置 - 简化逻辑判断:用
not in_long1替代in_long1 == false,代码更简洁 - 优化中文注释,提升代码可读性
内容的提问来源于stack exchange,提问作者M.wol
相关产品推荐
相关产品推荐

