为何此Pine Script策略显示‘无数据’?已按建议修正代码
问题分析与解决方案
核心问题
- 交易逻辑执行时机错误:所有下单代码都包裹在
barstate.islastconfirmedhistory条件块中,该块仅在最后一根已确认的历史K线上执行一次,导致历史周期内无交易信号,仅最后一日触发开仓。 - 开平仓逻辑颠倒:原代码中向下箭头(▼)触发开多,向上箭头(▲)触发平仓,与需求的「向上箭头开多、向下箭头平仓」完全相反。
- 无加仓控制机制:未限制重复开仓,可能出现多次加仓情况。
- 变量声明与使用不当:
var声明的条件变量仅初始化一次,逻辑判断存在冲突。
修正后的代码
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © george10001000 //@version=5 strategy("test1", overlay=true, initial_capital=100000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, process_orders_on_close=true) backTestStart = input.time(timestamp("1 Jan 2022 12:00"), title="Start backtest") //==Nadaraya==== length = input.float(500, 'Window Size', maxval=500, minval=0) h = input.float(8., 'Bandwidth') mult = input.float(3.) src = input.source(close, 'Source') up_col = input.color(#39ff14, 'Colors', inline='col') dn_col = input.color(#ff1100, '', inline='col') //---- n = bar_index var k = 2 var upper = array.new_line(0) var lower = array.new_line(0) lset(l, x1, y1, x2, y2, col)=> line.set_xy1(l, x1, y1) line.set_xy2(l, x2, y2) line.set_color(l, col) line.set_width(l, 2) // 仅在最后K线绘制通道,不包含交易逻辑 if barstate.islastconfirmedhistory for i = 0 to length/k-1 array.push(upper, line.new(na, na, na, na)) array.push(lower, line.new(na, na, na, na)) y = array.new_float(0) sum_e = 0. for i = 0 to length-1 sum = 0. sumw = 0. for j = 0 to length-1 w = math.exp(-(math.pow(i-j,2)/(h*h*2))) sum += src[j]*w sumw += w y2 = sum/sumw sum_e += math.abs(src[i] - y2) array.push(y, y2) mae = sum_e/length*mult for i = 1 to length-1 y2 = array.get(y, i) y1 = array.get(y, i-1) up := array.get(upper, i/k) dn := array.get(lower, i/k) lset(up, n-i+1, y1 + mae, n-i, y2 + mae, up_col) lset(dn, n-i+1, y1 - mae, n-i, y2 - mae, dn_col) // 分离信号计算与交易逻辑,每根K线执行 var float[] y_array = array.new_float(0) var float mae_val = na // 预计算Nadaraya估计值与MAE,确保每根K线可调用 if barstate.isfirst y_temp = array.new_float(0) sum_e_temp = 0. for i = 0 to length-1 sum = 0. sumw = 0. for j = 0 to length-1 w = math.exp(-(math.pow(i-j,2)/(h*h*2))) sum += src[j]*w sumw += w y2 = sum/sumw sum_e_temp += math.abs(src[i] - y2) array.push(y_temp, y2) mae_val := sum_e_temp/length*mult array.copy(y_array, y_temp) // 计算当前与前一根的通道值 y_current = array.get(y_array, bar_index % length) y_prev = array.get(y_array, (bar_index - 1) % length) upper_current = y_current + mae_val upper_prev = y_prev + mae_val lower_current = y_current - mae_val lower_prev = y_prev - mae_val // 开多信号:价格上穿下通道(对应向上箭头) longCondition = ta.crossover(src, lower_prev) and time > backTestStart and strategy.position_size == 0 // 平仓信号:价格下穿上通道(对应向下箭头) closeCondition = ta.crossunder(src, upper_prev) and strategy.position_size > 0 // 执行交易 if longCondition strategy.entry("Long", strategy.long) label.new(bar_index, src, '▲', color=#00000000, style=label.style_label_up, textcolor=up_col, textalign=text.align_center) label.new(bar_index, src-30, str.tostring(close, ".#"), color=#00000000, style=label.style_label_up, textcolor=up_col, textalign=text.align_center) if closeCondition strategy.close_all() label.new(bar_index, src, '▼', color=#00000000, style=label.style_label_down, textcolor=dn_col, textalign=text.align_center) label.new(bar_index, src+30, str.tostring(close, ".#"), color=#00000000, style=label.style_label_down, textcolor=dn_col, textalign=text.align_center) // 预警条件 alertcondition(longCondition, '开多信号', '向上箭头触发开多') alertcondition(closeCondition, '平仓信号', '向下箭头触发平仓') //---- var tb = table.new(position.top_right, 1, 1 , bgcolor = #35202b)
关键修正点
- 分离绘制与交易逻辑:将通道绘制代码留在
barstate.islastconfirmedhistory块,交易逻辑移到外部,确保每根K线都能执行信号判断。 - 修正开平仓逻辑:向上箭头(价格上穿下通道)触发开多,向下箭头(价格下穿上通道)触发平仓,匹配需求。
- 控制加仓:通过
strategy.position_size == 0确保仅空仓时开多,避免重复加仓。 - 优化变量存储:预计算Nadaraya估计值并存储到数组,供每根K线调用,避免重复计算。
内容的提问来源于stack exchange,提问作者george10001000
相关产品推荐
相关产品推荐

