View Raw SPL
/*****************************************************************************
*                                                                            *
*   EXPMOVAVG.SPL Copyright (C) 2012-2015 DSP Development Corporation        *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Exponential moving average                                  *
*                                                                            *
*   Revisions:   11 Jul 2012  RRR  Creation                                  *
*                17 Oct 2015  RRR  update initial condition for filteq       *
*                                                                            *
*****************************************************************************/


#if @HELP_EXPMOVAVG

    EXPMOVAVG

    Purpose: Computes an exponential moving average with a smoothing factor.

    Syntax:  EXPMOVAVG(s, a, yi)

               s - A series, the input data.

               a - Optional. A real, the smoothing factor where 0 <= a <= 1.
                   Defaults to 1.0, no averaging.

              yi - Optional. A real, the initial value. Defaults to s[1],
                   the first input value.
 
    Alternate Syntax:

             EXPMOVAVG(s, N, yi)

               s - A series, the input data.

               N - Optional. An integer, the effective number of points
                   to average where N >= 1. Defaults to 1, no averaging.

              yi - Optional. A real, the initial value. Defaults to s[1],
                   the first input value.

    Returns: A series, the exponential moving average.

    Example:
             W1: 1..5
             W2: expmovavg(w1, 0.5)

             W2 == {1.0, 1.5, 2.25, 3.125, 4.0625}

             The X offset of the result is 1.0.

    Example:
             W1: 1..5
             W2: expmovavg(w1, 3)

             W2 == {1.0, 1.5, 2.25, 3.125, 4.0625}

             Same as above except the smoothing factor is in the form of
             the effective number of points to smooth. The effective number
             of points, N is related to A, the smoothing factor by:

             N = (2 / a) - 1

   Example:
             W1: integ(gnorm(1000, 1/100))
             W2: expmovavg(w1, 0.7)
             W3: expmovavg(w1, 0.1)

             W1 contains 1000 samples of synthesized data.

             W2 performs a standard exponential moving average with a
             smoothing factor of 0.7.

             W3 performs a standard exponential moving average by with
             a smoothing factor of 0.1.

             The degree of smoothing is increased as the smoothing
             factor approaches 0.0.  The degree of smoothing is
             decreased as the smoothing factor approaches 1.0.

    Remarks:
             EXPMOVAVG computes the exponential moving average with a
             smoothing factor using the following difference equation:

             y[n] = a * x[n] + (1 - a) y[n - 1]

             EXPMOVAVG uses FILTEQ to implement the difference equation.

             By default, y[0] = yi = x[1].

             The effective number of points to average used by the
             exponential moving average is related to the smoothing
             factor by:

             N = (2 / a) - 1

             where N is the number of points to average as with the
             standard moving average.  If the smoothing parameter of
             EXPMOVAVG is an integer greater or equal to 1, it is
             assumed to be the effective number of bits as determined
             above.

             See LINEXPAVG to compute a phaseless exponential moving
             average to preserve peak locations.

    See Also:
             Filteq
             Linexpavg
             Movavg
#endif


/* exponential moving average with a smoothing factor */
expmovavg(s, a, yi)
{
        local y;

        if (argc < 3)
        {
                if (argc < 2)
                {
                        if (argc < 1) error("expmovavg - input series required");

                        a = 1.0;
                }

                yi = s[1];
        }

        if (a > 1)
        {
                /* assume number of points given */
                a = 2 / (a + 1);
        }

        /* straightforward difference equation with initial condition */        
        y = filteq({a}, {1 - a}, s, {yi} * (1 - a));

        return(y);
}