使用for循环时如何正确向Pine Script数组存入不同值?
问题:Pine Script循环中数组元素值异常的解决方法
在Pine Script中尝试用for循环将每次迭代生成的cumDistance值存入cumDistances数组时,出现异常:数组内所有元素均为最后一次迭代的cumDistance值(如-43.41588)。但不用for循环,手动将代码中的i替换为1-5依次执行,能得到正确序列值(0.02016、-10.83885、-21.69786、-32.55687、-43.41588)。
原问题代码
var inTrade = false var entry = 0. var exit = 0. distance = 0. entryCon = ta.crossover(ta.rsi(close, 10), 20) and not inTrade exitCon = ta.crossunder(ta.rsi(close, 10), 80) and inTrade cumDistances = array.new_float() for i=1 to 5 if entryCon[1] entry := close[1] inTrade := true if exitCon[1] exit := close[1] inTrade := false distance := exit - entry*i cumDistance = ta.cum(distance) array.push(cumDistances, cumDistance)
后续尝试的问题代码
改用array.sum实现累计逻辑时,若在循环内清空distances数组,结果会全部变为NaN,相关代码如下:
cumDistances = array.new_float() for i=1 to 5 var distances = array.new_float() if entryCon[1] entry := close[1] inTrade := true if exitCon[1] exit := close[1] inTrade := false distance := exit - entry*i array.push(distances, distance) cumDistance = array.sum(distances) array.push(cumDistances, cumDistance) //array.clear(distances) <---- placing this here, I will get NaN,NaN,NaN,NaN,Nan as result plot(array.size(cumDistances), "no. of index", display=display.data_window) table1 = table.new(position.top_right, 10, 10) table.cell(table1, 0, 0, str.tostring(array.get(cumDistances, 0)) + ", " + str.tostring(array.get(cumDistances, 1)) + ", " + str.tostring(array.get(cumDistances, 2)) + ", " + str.tostring(array.get(cumDistances, 3)) + ", " + str.tostring(array.get(cumDistances, 4)))
问题原因分析
原代码问题:
ta.cum()是序列函数,基于历史K线计算累计值,而for循环在单根K线内完成5次迭代,所有迭代共享同一个distance变量的最终值,导致每次push的都是最后一次迭代的累计结果。- 循环内直接修改
entry、inTrade等全局变量,会导致迭代过程中变量被覆盖,所有迭代都使用最后一次修改后的变量值。
array.sum版本问题:
var distances = array.new_float()定义的是全局数组,循环内push后不清空会累计所有迭代的distance值;但如果在循环内清空,每次迭代时数组为空,array.sum()返回NaN。
解决方案
修正后的代码(手动累计逻辑)
var inTrade = false var entry = 0. var exit = 0. entryCon = ta.crossover(ta.rsi(close, 10), 20) and not inTrade exitCon = ta.crossunder(ta.rsi(close, 10), 80) and inTrade // 仅在信号触发时更新全局变量,避免循环内覆盖 if entryCon[1] entry := close[1] inTrade := true if exitCon[1] exit := close[1] inTrade := false cumDistances = array.new_float() var float runningCum = 0. // 用于单循环内的手动累计变量 for i=1 to 5 // 每次迭代使用独立的局部变量计算distance float currentDistance = 0. if exitCon[1] currentDistance := exit - entry * i // 手动实现循环内的累计,替代ta.cum() runningCum := runningCum + currentDistance array.push(cumDistances, runningCum) // 新K线开始时重置累计值,避免跨K线污染 if barstate.isnew runningCum := 0. // 结果展示 plot(array.size(cumDistances), "no. of index", display=display.data_window) table1 = table.new(position.top_right, 10, 10) table.cell(table1, 0, 0, str.tostring(array.get(cumDistances, 0)) + ", " + str.tostring(array.get(cumDistances, 1)) + ", " + str.tostring(array.get(cumDistances, 2)) + ", " + str.tostring(array.get(cumDistances, 3)) + ", " + str.tostring(array.get(cumDistances, 4)))
关键修正点
- 将全局变量的更新逻辑移到循环外,确保变量只在信号触发时更新一次。
- 使用局部变量
runningCum手动实现单K线内的循环累计,替代序列函数ta.cum()。 - 每次迭代使用独立的
currentDistance变量,避免全局变量被覆盖。 - 在新K线开始时重置累计变量,避免跨K线的累计值污染。
内容的提问来源于stack exchange,提问作者bbnm
相关产品推荐
相关产品推荐

