如何在Pine Script中计算KDJ时排除特定时段数据?
如何计算排除特定时段数据的KDJ指标
嘿,我明白你要的效果了——在1130-1430这段时间里,KDJ的计算不跟着这段的K线更新,而是保持和1130时刻一致的数据源;等过了1430之后,再逐步把这段排除的K线一个个加回计算池,直到10个周期后完全用新的时段数据。咱们来一步步实现这个需求:
核心思路
要实现这个逻辑,我们需要:
- 识别出需要排除的时段(1130-1430)
- 在进入排除时段时,保存当时的KDJ计算数据源(最近10个有效K线的数据)
- 排除时段内,复用保存的旧数据源进行计算
- 退出排除时段后,逐步用排除时段的K线替换旧数据源中的最早数据,直到完全更新为新数据
完整实现代码
study("KDJ - Exclude Specific Session", overlay=false) // 配置参数 ilong = input.int(10, title="KDJ Period") isigK = input.int(3, title="K Smoothing Period") isigD = input.int(3, title="D Smoothing Period") excludeSession = input.session("1130-1430", title="Exclude Session") // 判断当前是否在排除时段内 isExcluded() => timeframe.isintraday and time(excludeSession) != 0 // 初始化变量:保存排除前的数据源、排除时段状态、排除时段K线计数 var bool inExclusion = false var float[] preExHighs = array.new_float(ilong) var float[] preExLows = array.new_float(ilong) var float[] preExCloses = array.new_float(ilong) var int excludeBarCount = 0 // 更新排除时段计数 if isExcluded() excludeBarCount := excludeBarCount + 1 else excludeBarCount := 0 // 进入排除时段时,保存当前的有效数据源 if not inExclusion and isExcluded() inExclusion := true // 收集进入排除前的最近ilong个非排除时段的数据 var float[] tempHighs = array.new_float() var float[] tempLows = array.new_float() var float[] tempCloses = array.new_float() for i = 0 to ilong - 1 if not isExcluded()[i] array.push(tempHighs, high[i]) array.push(tempLows, low[i]) array.push(tempCloses, close[i]) // 确保数组长度符合ilong(如果不足则补最近的) while array.size(tempHighs) < ilong array.push(tempHighs, high[array.size(tempHighs)]) array.push(tempLows, low[array.size(tempLows)]) array.push(tempCloses, close[array.size(tempCloses)]) preExHighs := tempHighs preExLows := tempLows preExCloses := tempCloses // 退出排除时段时,重置状态 if inExclusion and not isExcluded() inExclusion := false // 获取当前计算用的数据源 currentHighs = array.new_float() currentLows = array.new_float() currentCloses = array.new_float() if inExclusion // 排除时段内,复用保存的旧数据源 currentHighs := preExHighs currentLows := preExLows currentCloses := preExCloses else if excludeBarCount > 0 // 刚退出排除时段,逐步替换旧数据源 postExBarCount = barssince(not isExcluded()) + 1 // 从旧数据源中去掉前postExBarCount个最早的数据 slicedHighs = array.slice(preExHighs, postExBarCount, array.size(preExHighs)) slicedLows = array.slice(preExLows, postExBarCount, array.size(preExLows)) slicedCloses = array.slice(preExCloses, postExBarCount, array.size(preExCloses)) // 从排除时段中取最近postExBarCount个数据(从1430开始的K线) excludeHighs = array.new_float() excludeLows = array.new_float() excludeCloses = array.new_float() for i = 0 to postExBarCount - 1 array.push(excludeHighs, high[excludeBarCount - i - 1]) array.push(excludeLows, low[excludeBarCount - i - 1]) array.push(excludeCloses, close[excludeBarCount - i - 1]) // 合并得到当前数据源 currentHighs := array.concat(slicedHighs, excludeHighs) currentLows := array.concat(slicedLows, excludeLows) currentCloses := array.concat(slicedCloses, excludeCloses) else // 正常时段,收集最近ilong个非排除时段的数据 if not isExcluded() array.push(currentHighs, high) array.push(currentLows, low) array.push(currentCloses, close) // 保持数组长度不超过ilong while array.size(currentHighs) > ilong array.shift(currentHighs) array.shift(currentLows) array.shift(currentCloses) // 如果数组长度不足,补最近的数据 while array.size(currentHighs) < ilong array.push(currentHighs, high[array.size(currentHighs)]) array.push(currentLows, low[array.size(currentLows)]) array.push(currentCloses, close[array.size(currentCloses)]) // 计算KDJ指标 h = array.max(currentHighs) l = array.min(currentLows) c = array.get(currentCloses, array.size(currentCloses)-1) RSV = 100 * ((c - l) / (h - l)) // 计算K值(基于有效RSV的SMA) getValidSMA(len, src) => var float[] validSrc = array.new_float() if not isExcluded() array.push(validSrc, src) while array.size(validSrc) > len array.shift(validSrc) array.size(validSrc) >= len ? ta.sma(array.concat(validSrc), len) : na pK = getValidSMA(isigK, RSV) pD = getValidSMA(isigD, pK) pJ = 3 * pK - 2 * pD // 绘图 plot(pK, color=color.red, title="K Line") plot(pD, color=color.blue, title="D Line") plot(pJ, color=color.green, title="J Line") // 标记排除时段背景 bgcolor(isExcluded() ? color.silver : na, transp=80)
代码对应你的需求示例
- 1430时刻:此时仍处于排除时段,
inExclusion为true,所以用的是进入排除前保存的1121-1130时段的数据,和1130时刻的计算依据完全一致 - 1431时刻:退出排除时段,
postExBarCount为1,会从旧数据源中去掉最早的1121数据,加入排除时段的最后一个数据(1430的K线),最终数据源是1122-1130 +1430,符合你的需求 - 1432时刻:
postExBarCount为2,去掉旧数据源的前2个数据(1121、1122),加入1430、1431的K线数据,数据源变为1123-1130 +1430-1431 - 1439时刻:
postExBarCount为9,数据源变成1130 +1430-1438,共10个数据 - 1440时刻:
postExBarCount为10,旧数据源被完全替换,变成1430-1439的10个数据,之后就会逐步用新的非排除时段数据更新
注意事项
- 代码中加入了参数配置,你可以直接调整
excludeSession来修改排除时段 - 处理了数据源长度不足的边界情况(比如刚开盘时)
- 背景色标记保留了你原来的逻辑,方便直观查看排除时段
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

