iir

首发版本:2.00.19/3.00.6

语法

iir(X, b, a)

详情

对输入数据 X 应用 IIR(无限脉冲响应)滤波器,返回滤波后的结果。IIR 滤波器利用了过去的输出值作为反馈,因此可以用比 FIR 低得多的阶数实现陡峭的过渡带。

其数学表达式为:a[0]·y[n] = (b[0]·x[n] + b[1]·x[n-1] + … + b[M]·x[n-M]) - (a[1]·y[n-1] + … + a[N]·y[n-N]),其中 b 为分子系数,a 为分母系数。

注:
  • 输入数据中的前导空值不参与计算,对应位置的输出也为空值。除前导空值外,后续出现的空值按 0 处理。

  • 该函数与 Python scipy.signal.lfilter(b, a, X) 功能相同,但两者对缺失值的处理方式不同。scipy.signal.lfilter 不会对 NaN 进行特殊处理,因此 NaN 会参与滤波运算并传播到后续结果中。

参数

X 数值类型的常规向量,表示待滤波的数据。

b 非空数值类型的常规向量,表示 IIR 滤波器的分子系数。

a 非空数值类型的常规向量,表示 IIR 滤波器的分母系数。

返回值

返回与输入 X 相同形式且长度一致的结果。

例子

例1. 对向量应用 IIR 滤波。

x = 1 2 3 4 5
b = 0.2 0.2
a = 1 -0.5
iir(x, b, a)
// output: [0.2,0.7,1.35,2.075,2.8375]

x = [1, 2, NULL, 4]  // 等价于 [1, 2, 0, 4]
b = 0.2 0.2
a = 1 -0.5
iir(x, b, a)
// output: [0.2,0.7,0.75,1.175]

例2. 在量化策略回测中,双均线交叉是最经典的趋势跟踪策略之一:用一条快速 EMA 和一条慢速 EMA,当快线上穿慢线时产生买入信号,下穿时产生卖出信号。EMA 本质上就是一个一阶 IIR 滤波器—— iir(X, [α], [1, -(1-α)]),其中 α = 2/(N+1)。相比用 FIR 实现同等平滑度,IIR 只需 2 个系数,在对数百只股票做全市场回测时,计算效率优势显著。

下面的示例模拟了某只股票一个交易日的 1 分钟 K 线数据,分别用 alphaFast(对应 10 周期 EMA)和 alphaSlow(对应 30 周期 EMA)两个一阶 IIR 滤波器提取快慢趋势线,并生成交叉信号。

// 1. 建 catalog、库、表
if(!existsCatalog("FinanceData")){
    createCatalog("FinanceData")
}
go
use catalog FinanceData

if(!existsDatabase("FinanceData.kline")){
    create database kline
    partitioned by VALUE(2026.06.01..2026.06.30),
    engine='TSDB'
}
go
if(!existsTable("FinanceData.kline", "min1")){
    create table kline.min1 (
        SecurityID SYMBOL,
        TradeDate DATE,
        BarTime TIMESTAMP,
        Open DOUBLE,
        High DOUBLE,
        Low DOUBLE,
        Close DOUBLE,
        Volume LONG
    )
    partitioned by TradeDate,
    sortColumns = [`SecurityID, `BarTime],
    keepDuplicates = ALL
}

// 2. 造数据:模拟 600519.SH 当日 240 根 1 分钟 K 线
n = 240
idx = 0..(n - 1)

baseTime = 2026.06.02T09:30:00.000
barTime = baseTime + idx * 60000

trendComponent = 1800.0 + 10.0 * sin(2.0 * pi * idx / n * 2.0) + cumsum(rand(0.2, n) - 0.1)
noise = norm(0.0, 1.0, n)

closePrice = round(trendComponent + noise, 2)
openPrice  = round(closePrice + norm(0.0, 0.5, n), 2)

highBase = iif(openPrice > closePrice, openPrice, closePrice)
lowBase  = iif(openPrice < closePrice, openPrice, closePrice)

highPrice = round(highBase + abs(norm(0.0, 0.3, n)), 2)
lowPrice  = round(lowBase  - abs(norm(0.0, 0.3, n)), 2)

volume = long(rand(10000, n) + 100)

t = table(
    symbol(take("600519.SH", n)) as SecurityID,
    take(2026.06.02, n) as TradeDate,
    barTime as BarTime,
    openPrice as Open,
    highPrice as High,
    lowPrice as Low,
    closePrice as Close,
    volume as Volume
)

// 3. 插入数据
kline.min1.append!(t)

// 4. 读取原始 K 线数据
raw = select BarTime, Close
      from kline.min1
      where SecurityID = `600519.SH
        and TradeDate = 2026.06.02
      order by BarTime

// 5. IIR 计算 EMA 快慢线
alphaFast = 2.0 / (10 + 1)
alphaSlow = 2.0 / (30 + 1)

emaResult = select
                BarTime,
                Close,
                iir(Close, [alphaFast], [1.0, -(1.0 - alphaFast)]) as emaFast,
                iir(Close, [alphaSlow], [1.0, -(1.0 - alphaSlow)]) as emaSlow
            from raw

// 6. 生成交叉信号
signals = select
              BarTime,
              Close,
              emaFast,
              emaSlow,
              iif(
                  emaFast > emaSlow and prev(emaFast) <= prev(emaSlow),
                  "BUY",
                  iif(
                      emaFast < emaSlow and prev(emaFast) >= prev(emaSlow),
                      "SELL",
                      "HOLD"
                  )
              ) as signal
          from emaResult
          order by BarTime

// 7. 查看所有买卖信号
select *
from signals
where signal != "HOLD"
order by BarTime

相关函数:fir