TradingView中security函数调用自定义函数的状态保持问题问询
在Pine Script的security函数中实现跨时间框架的状态保存
问题背景
我们构建的指标逻辑基于价格突破特定水平,需先在CTF(当前时间框架)验证,再应用到多个HTF(更高时间框架)。为复用逻辑编写了包含前期价格水平参数的自定义函数,该函数在CTF中运行正常,但通过request.security()调用时完全失效——HTF输出的价格水平与CTF重叠,仿佛未调用HTF。
排查过程中尝试多种方式获取HTF首根K线均未得到预期结果,编写的GetHTFHighestHigh()函数在security调用中也无法正常运行。核心需求是:如何在security调用的自定义函数中实现跨K线的数据状态保存?
测试代码
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ //@version=5 indicator("Test HTF", overlay = true) sHtfGroup = "HTF Settings" useHTF1 = input.bool(title='Use HTF', defval=true, group=sHtfGroup, tooltip='Check this if you want to use the higher time frame.') htfRes1 = input.timeframe(title=' HTF Resolution', defval='5', group=sHtfGroup, tooltip='Choose the higher time frame.') //1st try - DOESN'T WORK firstbar0()=> var barIndex = 0 if(barIndex == 0) barIndex := bar_index barIndex //2nd try - DOESN'T WORK var TheBarNumber1 = 0 firstbar1(barNumber)=> barIndex = 0 if(barNumber == 0) barIndex := bar_index barIndex //3rd try - DOESN'T WORK var TheBarNumber2 = 0 firstbar2(barNumber)=> var barIndex = 0 if(barNumber == 0) barIndex := bar_index barIndex //4th try - DOESN'T WORK IsFirstBar = false if barstate.isfirst IsFirstBar := true firstbar3(firstBar)=> barIndex = 0 if(firstBar) barIndex := bar_index barIndex //5th try - DOESN'T WORK HtfBarIndex = request.security(syminfo.tickerid, htfRes1, bar_index) mn = 0 if barstate.isfirst mn := HtfBarIndex firstbar4(firstBar)=> barIndex = 0 if(firstBar == bar_index) barIndex := bar_index barIndex //6th try - DOESN'T WORK TheTime = 0 if barstate.isfirst TheTime := time firstbar5(Time)=> barIndex = 0 if(Time == time) barIndex := bar_index barIndex //7th try - DOESN'T WORK var IsFirstBar6 = false if barstate.isfirst IsFirstBar6 := true else IsFirstBar6 := false firstbar6(firstBar)=> barIndex = 0 if(firstBar) barIndex := bar_index barIndex [HtfIsFirstBar, HtfFirstBarNumber0, HtfFirstBarNumber1, HtfFirstBarNumber2, HtfFirstBarNumber3, HtfFirstBarNumber4, HtfFirstBarNumber6, HtfBarNumber] = request.security(syminfo.tickerid, htfRes1, [barstate.isfirst, firstbar0(), firstbar1(TheBarNumber1), firstbar2(TheBarNumber2), firstbar3(IsFirstBar), firstbar4(mn), firstbar6(IsFirstBar6), bar_index]) plot(HtfIsFirstBar ? 1 : 0) plot(HtfFirstBarNumber0) plot(TheBarNumber1, color = color.red) plot(HtfFirstBarNumber1, color = color.red) plot(TheBarNumber2, color = color.lime) plot(HtfFirstBarNumber2, color = color.lime) plot(HtfFirstBarNumber3, color = color.purple) plot(HtfFirstBarNumber4, color = color.fuchsia) plot(HtfFirstBarNumber6, color = color.aqua) plot(HtfBarNumber) TheBarNumber1 := HtfFirstBarNumber1 TheBarNumber2 := HtfFirstBarNumber2
补充测试函数
GetHTFHighestHigh()=> var previousHigh = 0 if(high > previousHigh) previousHigh := high previousHigh
问题根源
在Pine Script中,request.security()调用的函数内部的var变量,是绑定在**当前时间框架(CTF)**的上下文里,而非目标HTF的上下文。这意味着每次security调用时,函数内的var变量不会在HTF的K线周期内持续保存状态,而是跟着CTF的K线重置或复用错误的状态,导致HTF的计算结果和CTF重叠。
解决方法
方法1:将状态逻辑完全封装在security调用内部
要让状态变量绑定到HTF的上下文,必须在request.security()的参数表达式内部声明var变量并编写逻辑。以下是获取HTF首根K线和最高高点的示例:
//@version=5 indicator("HTF 状态保存示例", overlay=true) htfRes = input.timeframe("D", "更高时间框架") // 获取HTF首根K线索引 htfFirstBarIndex = request.security(syminfo.tickerid, htfRes, var int firstBar = na if barstate.isfirst firstBar := bar_index firstBar ) // 获取HTF历史最高高点 htfHighestHigh = request.security(syminfo.tickerid, htfRes, var float hh = ta.low hh := math.max(hh, high) hh ) plot(htfHighestHigh, color=color.new(color.blue, 0), title="HTF 最高高点") plotshape(htfFirstBarIndex == bar_index, title="HTF首根K线", location=location.belowbar, color=color.green, style=shape.labelup, text="HTF首K")
方法2:使用varip实现多HTF状态隔离
如果需要同时处理多个不同的HTF,可使用varip(可变实例变量)创建字典结构,用时间框架字符串作为键来存储对应状态:
//@version=5 indicator("多HTF状态保存示例", overlay=true) htfRes1 = input.timeframe("4H", "HTF1") htfRes2 = input.timeframe("D", "HTF2") // 封装HTF最高高点函数,用varip字典存储不同时间框架的状态 getHtfHighestHigh(tf)=> varip dict hhDict = na if na(hhDict) hhDict := dict.new() // 获取当前HTF的最高高点 currentHh = request.security(syminfo.tickerid, tf, var float hh = ta.low hh := math.max(hh, high) hh ) // 将结果存入字典 dict.set(hhDict, tf, currentHh) currentHh // 获取两个HTF的最高高点 htf1Hh = getHtfHighestHigh(htfRes1) htf2Hh = getHtfHighestHigh(htfRes2) plot(htf1Hh, color=color.orange, title="4H 最高高点") plot(htf2Hh, color=color.blue, title="日线 最高高点")
关键注意事项
- 禁止在
security外部声明状态变量再传入函数,必须在security的参数表达式内部声明var变量,确保状态绑定到HTF上下文。 varip变量是全局可变的,适合多HTF场景下的状态隔离,Pine Script中request.security是串行执行的,无需担心线程安全问题。- 测试HTF状态时,可通过
barstate.islast或打印time戳验证,避免CTF和HTF的K线混淆。
内容的提问来源于stack exchange,提问作者Maza
相关产品推荐
相关产品推荐

