security函数报错:'expression'参数不可有副作用,筛选器趋势线求解
解决方案
问题根源在于security()函数要求传入的表达式不能有副作用,而你在screenerFunc()里调用line.new()创建线条属于副作用操作(会生成绘图对象),因此触发报错。要解决这个矛盾,需要把信号计算逻辑和绘图逻辑完全分离:
核心思路
- 绘图逻辑只在当前图表执行,不需要进入
security()调用; security()只负责计算突破信号,用数学方法直接计算趋势线价格,避免创建实际线条对象。
修改后的代码示例
//@version=5 indicator("筛选器趋势线突破", overlay=true) // 假设你已经定义了这些变量,根据实际情况替换 triangle_h_x1 = 10 triangle_h_x2 = 5 hdot1 = ta.highest(high, 10) triangle_h_y2 = ta.highest(high, 5) triangle_l_x1 = 10 triangle_l_x2 = 5 ldot1 = ta.lowest(low, 10) triangle_l_y2 = ta.lowest(low, 5) // 1. 仅计算突破信号的函数(无副作用,可安全传入security) calculateBreakout() => // 用数学方法计算趋势线在当前bar的价格(替代line.get_price) // 趋势线两点坐标:(x1,y1)=(bar_index - triangle_h_x1, hdot1),(x2,y2)=(bar_index - triangle_h_x2, triangle_h_y2) slope_top = (triangle_h_y2 - hdot1) / (triangle_h_x2 - triangle_h_x1) intercept_top = hdot1 - slope_top * (bar_index - triangle_h_x1) line_top_price = slope_top * bar_index + intercept_top slope_bot = (triangle_l_y2 - ldot1) / (triangle_l_x2 - triangle_l_x1) intercept_bot = ldot1 - slope_bot * (bar_index - triangle_l_x1) line_bot_price = slope_bot * bar_index + intercept_bot isTrueTop = close > line_top_price ? 1 : 0 isTrueBot = close < line_bot_price ? 1 : 0 [isTrueTop, isTrueBot] // 2. 获取其他标的/周期的突破信号(无副作用,安全调用security) t1 = "AAPL" // 替换为你的标的 [isTrueTop, isTrueBot] = security(t1, timeframe.period, calculateBreakout()) // 3. 单独处理当前图表的绘图逻辑(仅在本地执行,不进入security) if barstate.islast line.new(bar_index - triangle_h_x1, hdot1, bar_index - triangle_h_x2, triangle_h_y2, color=color.red, width=2, extend=extend.right) line.new(bar_index - triangle_l_x1, ldot1, bar_index - triangle_l_x2, triangle_l_y2, color=color.green, width=2, extend=extend.right) // 输出信号 plotshape(isTrueTop, title="上突破", location=location.belowbar, color=color.red, style=shape.triangleup, size=size.small) plotshape(isTrueBot, title="下突破", location=location.abovebar, color=color.green, style=shape.triangledown, size=size.small)
关键说明
- 用数学公式计算趋势线价格,替代
line.new()+line.get_price()的组合,避免了创建线条的副作用; - 绘图逻辑单独放在
barstate.islast条件下,只在当前图表最后一根K线绘制线条,不会影响security()的执行; calculateBreakout()函数仅做数值计算,没有任何绘图或状态修改操作,可以安全传入security()。
内容的提问来源于stack exchange,提问作者Exlusivité Web
相关产品推荐
相关产品推荐

