ButterworthFilter#
- class cultivars.spectral.filters.ButterworthFilter(*, period=32.0, order=2)[source]#
Gomez’s (2001) Butterworth sine low-pass filter, stated by cutoff period and order.
The trend is the minimizer of
\[\sum_t (y_t - \tau_t)^2 + \lambda \sum_t (\Delta^n \tau_t)^2, \qquad \lambda = \bigl(2 \sin(\pi / P)\bigr)^{-2n},\]whose two-sided gain is the Butterworth form
\[G(\omega) = \frac{1}{1 + \bigl(\sin(\omega/2) / \sin(\omega_c/2)\bigr)^{2n}}, \qquad \omega_c = 2\pi / P,\]equal to one half at the cutoff period \(P\) for every order and falling from one to zero more sharply as \(n\) grows. Unlike
HodrickPrescottFilterthe user states the frequency, not the weight:period=32, order=2is HP at \(\lambda = 677\), andperiod=39.7, order=2is HP at 1600. The penalty grows as \(P^{2n}\), so the same cutoff at order 3 is \(\lambda \approx 17620\) and at order 4 \(\lambda \approx 4.6 \times 10^5\).- Variables:
_period – The cutoff period \(P\) in observations per cycle.
_order – The differences penalized, \(n\).
- Parameters:
- Raises:
SpecificationError – If the period is 2 or below, or the order is not an integer of at least 1.
Note
The order buys sharpness at two costs. The trend’s null space is polynomials of degree \(n - 1\), so order 3 lets a quadratic through as trend where HP would bend it into the cycle. And the smoother is solved as \((I + \lambda D'D)\tau = y\) in banded form, whose conditioning degrades with \(\lambda\): the gain matches the closed form to three decimals through order 7 at period 32 and is visibly wrong at order 8 (0.86 where it should be 1.00), so treat orders above 6 as outside the filter’s reliable range. The end-point problem worsens with order as well, and the result flags the same
ceil(period)rows at each edge as provisional regardless.See also
DecompositionFilterResult– the container returned.HodrickPrescottFilter– the order-2 member stated by weight.BaxterKingFilter– a band-pass rather than a low-pass, for isolating the cycle between two periods.
References
Gomez, V. (2001). The use of Butterworth filters for trend and cycle estimation in economic time series. Journal of Business & Economic Statistics, 19(3), 365-373.
Example
>>> rng = np.random.default_rng(0) >>> y = np.cumsum(rng.standard_normal(200)) >>> res = ButterworthFilter(period=32, order=3).filter(y) >>> res.trend.shape, round(res.cutoff, 1), round(res.penalty) ((200, 1), 32.0, 17620)
Order 2 at the HP cutoff period is the HP filter, and the gain at a period half the cutoff falls from 0.20 at order 1 to 0.004 at order 4:
>>> hp = HodrickPrescottFilter().filter(y) >>> same = ButterworthFilter(period=hp.cutoff, order=2).filter(y) >>> bool(np.allclose(same.trend, hp.trend)) True >>> t = np.arange(4000.0) >>> wave = np.cos(2 * np.pi * t / 16) >>> gain = lambda n: ButterworthFilter(period=32, order=n).filter(wave).trend[1000:3000, 0] >>> [round(float(gain(n).std() / wave[1000:3000].std()), 3) for n in (1, 2, 4)] [0.202, 0.06, 0.004]
Methods#
|
Filter a panel. |