解决TradingView多证券DIPlus值显示NaN问题的方案
TradingView多证券DI值表格展示问题与解决方案
需求说明
需要在TradingView中以表格形式展示5只证券的DI值,基于v4版本的《ADX and DI》指标编写Pine Script v5代码。初始实现中DIPlus值显示为NaN,经重构后解决该问题。
初始代码(存在NaN问题)
//@version=5 indicator("table-di-plus", overlay = true) // ---------------------------------------------------------------------- type result float close_ float high_ float low_ float DIPlus // ---------------------------------------------------------------------- // parameters // ---------------------------------------------------------------------- len = input(14) th = input(20) // ---------------------------------------------------------------------- sym1 = input.symbol('PG', 'Symbol 1') sym2 = input.symbol('MMM', 'Symbol 2') sym3 = input.symbol('CYBR', 'Symbol 3') sym4 = input.symbol('QCOM', 'Symbol 4') sym5 = input.symbol('FTNT', 'Symbol 5') obj1 = result.new() obj2 = result.new() obj3 = result.new() obj4 = result.new() obj5 = result.new() obj1.close_ := request.security(sym1, '', close) obj2.close_ := request.security(sym2, '', close) obj3.close_ := request.security(sym3, '', close) obj4.close_ := request.security(sym4, '', close) obj5.close_ := request.security(sym5, '', close) obj1.high_ := request.security(sym1, '', high) obj2.high_ := request.security(sym2, '', high) obj3.high_ := request.security(sym3, '', high) obj4.high_ := request.security(sym4, '', high) obj5.high_ := request.security(sym5, '', high) obj1.high_ := request.security(sym1, '', low) obj2.high_ := request.security(sym2, '', low) obj3.high_ := request.security(sym3, '', low) obj4.high_ := request.security(sym4, '', low) obj5.high_ := request.security(sym5, '', low) // ---------------------------------------------------------------------- calc(result obj) => close_ = obj.close_ high_ = obj.high_ low_ = obj.low_ TrueRange = math.max(math.max(high_-low_, math.abs(high_-nz(close_[1]))), math.abs(low_-nz(close_[1]))) DirectionalMovementPlus = high_-nz(high_[1]) > nz(low_[1])-low_ ? math.max(high_-nz(high_[1]), 0): 0 DirectionalMovementMinus = nz(low_[1])-low_ > high_-nz(high_[1]) ? math.max(nz(low_[1])-low_, 0): 0 SmoothedTrueRange = 0.0 SmoothedTrueRange := nz(SmoothedTrueRange[1]) - (nz(SmoothedTrueRange[1])/len) + TrueRange SmoothedDirectionalMovementPlus = 0.0 SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - (nz(SmoothedDirectionalMovementPlus[1])/len) + DirectionalMovementPlus SmoothedDirectionalMovementMinus = 0.0 SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - (nz(SmoothedDirectionalMovementMinus[1])/len) + DirectionalMovementMinus DIPlus = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100 DIMinus = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100 obj.DIPlus := DIPlus // ---------------------------------------------------------------------- calc(obj1) calc(obj2) calc(obj3) calc(obj4) calc(obj5) // ---------------------------------------------------------------------- var table tbl = table.new( position = position.top_right, columns = 20, rows = 10, bgcolor = color.white, frame_color = color.black, frame_width = 2, border_color = color.black, border_width = 2) // ---------------------------------------------------------------------- tbl.cell(0, 1, sym1) tbl.cell(0, 2, sym2) tbl.cell(0, 3, sym3) tbl.cell(0, 4, sym4) tbl.cell(0, 5, sym5) tbl.cell(1, 1, str.tostring(obj1.DIPlus)) tbl.cell(1, 2, str.tostring(obj2.DIPlus)) tbl.cell(1, 3, str.tostring(obj3.DIPlus)) tbl.cell(1, 4, str.tostring(obj4.DIPlus)) tbl.cell(1, 5, str.tostring(obj5.DIPlus)) // ----------------------------------------------------------------------
优化后代码(解决NaN问题)
//@version=5 indicator("table-di-plus", overlay = true) // ---------------------------------------------------------------------- // parameters // ---------------------------------------------------------------------- len = input(14) th = input(20) // ---------------------------------------------------------------------- di_screener_function() => TrueRange = math.max(math.max(high-low, math.abs(high-nz(close[1]))), math.abs(low-nz(close[1]))) DirectionalMovementPlus = high-nz(high[1]) > nz(low[1])-low ? math.max(high-nz(high[1]), 0): 0 DirectionalMovementMinus = nz(low[1])-low > high-nz(high[1]) ? math.max(nz(low[1])-low, 0): 0 SmoothedTrueRange = 0.0 SmoothedTrueRange := nz(SmoothedTrueRange[1]) - (nz(SmoothedTrueRange[1])/len) + TrueRange SmoothedDirectionalMovementPlus = 0.0 SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - (nz(SmoothedDirectionalMovementPlus[1])/len) + DirectionalMovementPlus SmoothedDirectionalMovementMinus = 0.0 SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - (nz(SmoothedDirectionalMovementMinus[1])/len) + DirectionalMovementMinus DIPlus = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100 DIMinus = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100 [DIPlus, DIMinus] // ---------------------------------------------------------------------- sym1 = input.symbol('PG', 'Symbol 1') sym2 = input.symbol('MMM', 'Symbol 2') sym3 = input.symbol('CYBR', 'Symbol 3') sym4 = input.symbol('QCOM', 'Symbol 4') sym5 = input.symbol('FTNT', 'Symbol 5') [sym1_DIPlus, sym1_DIMinus] = request.security(sym1, '', di_screener_function()) [sym2_DIPlus, sym2_DIMinus] = request.security(sym2, '', di_screener_function()) [sym3_DIPlus, sym3_DIMinus] = request.security(sym3, '', di_screener_function()) [sym4_DIPlus, sym4_DIMinus] = request.security(sym4, '', di_screener_function()) [sym5_DIPlus, sym5_DIMinus] = request.security(sym5, '', di_screener_function()) // ---------------------------------------------------------------------- var table tbl = table.new( position = position.top_right, columns = 20, rows = 10, bgcolor = color.white, frame_color = color.black, frame_width = 2, border_color = color.black, border_width = 2) // ---------------------------------------------------------------------- tbl.cell(0, 1, sym1) tbl.cell(0, 2, sym2) tbl.cell(0, 3, sym3) tbl.cell(0, 4, sym4) tbl.cell(0, 5, sym5) tbl.cell(1, 1, str.tostring(sym1_DIPlus)) tbl.cell(1, 2, str.tostring(sym2_DIPlus)) tbl.cell(1, 3, str.tostring(sym3_DIPlus)) tbl.cell(1, 4, str.tostring(sym4_DIPlus)) tbl.cell(1, 5, str.tostring(sym5_DIPlus)) // ----------------------------------------------------------------------
问题原因与解决方案
- 问题根源:初始代码中,通过
request.security仅获取单根K线的价格数据(close/high/low),无法获取完整的历史序列。计算DIPlus时需要调用close_[1]、high_[1]等历史值,这些值不存在导致计算结果为NaN。 - 解决方案:将DI计算逻辑封装为独立函数
di_screener_function,通过request.security在目标证券的完整数据上下文执行该函数。此时函数可以访问目标证券的全部历史序列数据,正常完成DIPlus的计算。
内容的提问来源于stack exchange,提问作者dharmatech
相关产品推荐
相关产品推荐

