求盈亏跨越指定百分比时的Bar Index及代码问题排查
Pine Script v5 交易盈亏达标K线索引捕获问题修正
问题描述
需要捕获盈利/亏损(绝对值)跨越指定百分比(示例为2%)时的K线索引,现有代码存在两个问题:
- 出现负K线索引:未满足条件的开仓交易错误沿用了之前交易的K线索引
- 开仓同K线达标时无法捕获该K线索引
尝试过strategy.opentrades.max_runup和max_drawdown未解决,原代码如下:
//@version=5 strategy("Testing", process_orders_on_close=false) pine_dev(source, length) => mean = ta.sma(source, length) sum = 0.0 for i = 0 to length - 1 val = source[i] sum := sum + math.abs(val - mean) dev = sum/length indicator = pine_dev(close,9) percentile = (ta.percentrank(indicator,9)) if percentile <= 25 strategy.entry("Enter Trade",strategy.long) if percentile == 100 strategy.close("Enter Trade",comment="Exit Trade") var number_of_trades = 0 var max_move = 2.0 var bar_index_max_move = 0 var tradeMax1 = 0.0 var array<int> moveBars = array.new_int() maxArrb = array.new_int() for i = 0 to strategy.opentrades - 1 cost = strategy.opentrades.entry_price(i) size = strategy.opentrades.size(i) profit = strategy.opentrades.profit(i) float tradeMax = math.abs(profit/(cost*size)*100) tradeMax1 := tradeMax if ta.change(tradeMax1 >= max_move) and strategy.opentrades > 0 max_move := tradeMax1 bar_index_max_move := bar_index if strategy.closedtrades > number_of_trades number_of_trades := number_of_trades + 1 if max_move != 0 array.push(moveBars,bar_index_max_move) // Reset values max_move := 2.0 for [j, bar] in moveBars int entryBar = strategy.closedtrades.entry_bar_index(j) int barsToMaxMove = bar - entryBar array.push(maxArrb, barsToMaxMove) //Label and plot to check if the output of the bar index is correct plot(array.size(maxArrb)) maxArrb_string = str.tostring(maxArrb) debug = label.new(x = bar_index, y = close, style = label.style_label_left, text = maxArrb_string) label.delete(debug[1])
修正后的代码
//@version=5 strategy("Testing Fixed", process_orders_on_close=false) // 自定义指标计算逻辑保持不变 pine_dev(source, length) => mean = ta.sma(source, length) sum = 0.0 for i = 0 to length - 1 val = source[i] sum := sum + math.abs(val - mean) dev = sum/length indicator = pine_dev(close, 9) percentile = ta.percentrank(indicator, 9) // 交易信号逻辑保持不变 if percentile <= 25 strategy.entry("Enter Trade", strategy.long) if percentile == 100 strategy.close("Enter Trade", comment="Exit Trade") // -------------------------- 核心修正部分 -------------------------- var float target_pct = 2.0 // 目标盈亏百分比 var array<int> trade_entry_bars = array.new_int() // 存储每笔交易的开仓K线索引 var array<int> target_hit_bars = array.new_int() // 存储每笔交易首次达标K线索引 var array<bool> target_hit_flag = array.new_bool() // 标记交易是否已达标 // 处理开仓:新交易初始化追踪数据 if strategy.opentrades > array.size(trade_entry_bars) current_entry_bar = strategy.opentrades.entry_bar_index(strategy.opentrades - 1) array.push(trade_entry_bars, current_entry_bar) array.push(target_hit_bars, na) array.push(target_hit_flag, false) // 遍历所有持仓交易,检查是否达标 for i = 0 to strategy.opentrades - 1 if not array.get(target_hit_flag, i) // 仅处理未达标交易 entry_price = strategy.opentrades.entry_price(i) current_pnl_pct = math.abs((close - entry_price) / entry_price * 100) // 达标判定(包含开仓同K线情况) if current_pnl_pct >= target_pct array.set(target_hit_bars, i, bar_index) array.set(target_hit_flag, i, true) // 处理平仓:将达标数据归档,并清理已结束交易的追踪数据 var array<int> final_target_bars = array.new_int() // 最终存储所有交易的达标K线索引 var array<int> bars_to_target = array.new_int() // 存储开仓到达标所需K线数 if strategy.closedtrades > array.size(final_target_bars) closed_trade_idx = strategy.closedtrades - 1 entry_bar = strategy.closedtrades.entry_bar_index(closed_trade_idx) // 找到对应交易的达标K线索引 trade_pos = array.indexof(trade_entry_bars, entry_bar) if trade_pos != -1 hit_bar = array.get(target_hit_bars, trade_pos) // 若开仓到平仓都未达标,可根据需求处理(这里设为na) final_hit_bar = na(hit_bar) ? na : hit_bar array.push(final_target_bars, final_hit_bar) // 计算开仓到达标K线数 if not na(final_hit_bar) array.push(bars_to_target, final_hit_bar - entry_bar) // 清理已结束交易的追踪数据 array.remove(trade_entry_bars, trade_pos) array.remove(target_hit_bars, trade_pos) array.remove(target_hit_flag, trade_pos) // 调试可视化:绘制达标交易数数组大小,显示数组内容 plot(array.size(bars_to_target), title="达标交易数") bars_str = str.tostring(bars_to_target) debug_label = label.new(bar_index, close, text=bars_str, style=label.style_label_left) label.delete(debug_label[1])
修正说明
- 避免跨交易数据污染:为每笔交易单独维护
target_hit_flag、target_hit_bars等追踪变量,不再使用全局变量共享状态,彻底解决负索引问题。 - 捕获开仓同K线达标场景:在开仓后立即检查当前K线的盈亏百分比,一旦达标就记录当前K线索引,无需等待下一根K线。
- 交易生命周期管理:开仓时初始化追踪数据,平仓时归档结果并清理对应数据,确保追踪数组仅保留活跃交易的信息。
- 灵活的未达标处理:若交易全程未达到目标百分比,可自行调整
final_hit_bar的赋值逻辑(当前设为na)。
内容的提问来源于stack exchange,提问作者Daniel Dsouza
相关产品推荐
相关产品推荐

