Investment Studio > Expressions > Functions > DSP > NOTCH

Short form: float array[*][data_columns] notch(float array[1][4] filter_parameters, float amplification, float array[*][data_columns] data)

Returns the data array, with all columns passed through the notch filter specified by the filter_parameters and multiplied by the amplification factor. Each data column is filtered separately.

Long form: float array[*][data_columns] notch(float array[1][4] filter_parameters, float amplification, float array[*][data_columns] data, integer first_column, integer last_column = first_column)

Returns the data array, with columns first_column through last_column passed through the notch filter specified by the filter_parameters and multiplied by the amplification factor. Each data column is filtered separately.

If last_column is omitted, it defaults to first_column (i.e. only first_column is convolved).

All arguments (including all array elements) are converted to float. If conversion fails, the default value 0.0 is used.

The filter_parameters describe a second order IIR (Infinite Impulse Response) filter implementing the difference equation

y[n] = b0 * x[n] + b1 * x[n - 1] + b0 * x[n - 2] + a1 * y[n - 1] + a2 * y[n - 2]

where x[n] is the input sequence and y[n] is the filter's output. The filter coefficients are listed in the order {b0, b1, a1, a2}. They can be specified manually or created with make_notch (recommended).

Tip: The frequency response of any linear, time-invariant filter is just the Fourier transform of the filter's impulse response (the filter's output when the input sequence is a unit impulse, i.e. a single 1 followed by zeros) so to visualize the filter's frequency response, all you have to do is pass a unit impulse through the filter, apply fftp to the output and plot the result. See make_notch for examples.

Examples

The 100-point column vector

_data = mop("sin()", makevector(100, 0, 29 * PI / 100)) + mop("sin()", makevector(100, 0, 32 * PI / 100))

contains a sine wave with period 100 / 14.5 (normalized frequency 0.145) mixed with a sine wave with period 100 / 16 (normalized frequency 0.16).

The two frequency components are too close to be distinguishable in a graph. If we plug the above expression into a graph source, what we see is an interference pattern (beats) with normalized frequency 0.16 - 0.145 = 0.015 (or period 1 / 0.015 » 67):

To filter out the longer wave, we can use a notch filter tuned to its frequency (0.145):

=notch(make_notch(0.145, 0.90), 1, array(_data))

Plotted (in blue) over the input sequence (in gray), the result looks like this:

Once it settles down (not coincidentally, after roughly half a period of the interference pattern), the notch filter can be seen to do a good job of shutting out the unwanted frequency component, resulting in a stable output amplitude at the higher frequency.

The amplitude is 0.7 (not 1) because of the finite width of the stopband (see make_notch); roughly 30% of the higher frequency component is being filtered out too. We could try to improve on this by increasing the radius parameter which we feed to make_notch, but given the low resolution of the input sequence (only 100 samples) we can only make the notch filter so narrow if we don't want it to miss the target frequency.

See also hipass, lopass, make_ema, make_notch, resonate.