You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pine Script中计算KDJ时排除特定时段数据?

如何计算排除特定时段数据的KDJ指标

嘿,我明白你要的效果了——在1130-1430这段时间里,KDJ的计算不跟着这段的K线更新,而是保持和1130时刻一致的数据源;等过了1430之后,再逐步把这段排除的K线一个个加回计算池,直到10个周期后完全用新的时段数据。咱们来一步步实现这个需求:

核心思路

要实现这个逻辑,我们需要:

  1. 识别出需要排除的时段(1130-1430)
  2. 在进入排除时段时,保存当时的KDJ计算数据源(最近10个有效K线的数据)
  3. 排除时段内,复用保存的旧数据源进行计算
  4. 退出排除时段后,逐步用排除时段的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:02:13