fir
First introduced in version: 2.00.19/3.00.6
Syntax
fir(X, b)
Details
Applies a Finite Impulse Response (FIR) filter to the input data X and returns the filtered result.
A FIR filter performs linear filtering via convolution. Its output depends only on the weighted sum of the current and previous inputs, so the system is inherently stable and readily designed with linear phase.
The mathematical expression is: y[n] = b[0]·x[n] + b[1]·x[n-1] + … + b[M]·x[n-M], where b denotes the filter coefficients and M is the filter order.
-
Leading null values in the input are ignored in the calculation, and the corresponding output are also NULL. Any null values after the leading null values are treated as 0.
-
This function is equivalent to Python's
scipy.signal.lfilter(b, [1.0], X), except for its handling of missing values.scipy.signal.lfilterdoes not treat NaN values specially, so NaNs are included in the filtering process and propagate through subsequent outputs.
Parameters
X is a regular vector of numeric type specifying the data to be filtered.
b is a non-empty regular vector of numeric type specifying the numerator coefficients of the FIR filter.
Returns
Returns a result of the same form and length as the input X.
Examples
Example 1. Apply a FIR filter to a vector.
x = 1 2 3 4 5
b = 0.2 0.3 0.5
fir(x, b)
// output: [0.2,0.7,1.7,2.7,3.7]
x = [1, 2, NULL, 4] // equivalent to [1, 2, 0, 4]
b = 0.5 0.5
fir(x, b)
// output: [0.5,1.5,1,2]
Example 2. In high-frequency trading, tick-by-tick trade prices contain substantial microstructure noise. A FIR filter can smooth the price series without introducing phase distortion, making it ideal for latency-insensitive scenarios that require waveform accuracy (e.g., post-market factor computation).
The following example simulates 1,000 tick records for a stock on a single trading day. It applies a 5th-order equal-weight FIR low-pass filter (essentially a simple moving average in filter form) to denoise the price series.
// 1. Create the database and table
if(existsCatalog("financeData")){
dropCatalog("financeData")
}
createCatalog("financeData")
go
use catalog financeData
create database trades
partitioned by VALUE(2026.06.01..2026.06.30), HASH([SYMBOL, 16]),
engine='TSDB'
go
create table trades.tick (
SecurityID SYMBOL,
TradeDate DATE,
TradeTime TIMESTAMP,
TradePrice DOUBLE,
TradeVolume INT
)
partitioned by TradeDate, SecurityID,
sortColumns = [`SecurityID, `TradeTime],
keepDuplicates = ALL
// 2. Generate sample data: simulate 1,000 tick records for 600519.SH on a trading day
n = 1000
idx = 0..(n - 1)
baseTime = 2026.06.02T09:30:00.000
ts = baseTime + idx * 3000 // one tick every 3 seconds
// Simulate prices: random walk around 1800 + random noise
cumReturns = cumsum(rand(0.2, n) - 0.1)
noise = norm(0.0, 0.3, n) // overlay high-frequency noise
prices = 1800.0 + cumReturns + noise
volumes = rand(100, n) + 1
t = table(
symbol(take("600519.SH", n)) as SecurityID,
take(2026.06.02, n) as TradeDate,
ts as TradeTime,
round(prices, 2) as TradePrice,
int(volumes) as TradeVolume
)
// 3. Insert the data
trades.tick.append!(t)
// 4. Query the tick table
raw = select TradeTime, TradePrice
from trades.tick
where SecurityID = `600519.SH
and TradeDate = 2026.06.02
order by TradeTime
// 5. Apply a 5th-order equal-weight FIR low-pass filter
b = take(1.0 / 5, 5)
result = select
TradeTime,
TradePrice as rawPrice,
fir(TradePrice, b) as filteredPrice
from raw
select top 10 * from result
Related Functions: iir
