Time for action – smoothing with the hanning() function

We will use the hanning() function to smooth arrays of stock returns, as shown in the following steps:

  1. Call the hanning() function to compute weights for a certain length window (in this example 8) as follows:
    N = 8
    weights = np.hanning(N)
    print("Weights", weights)

    The weights are as follows:

    Weights [ 0.          0.1882551   0.61126047  0.95048443  0.95048443  0.61126047
      0.1882551   0.        ]
    
  2. Calculate the stock returns for the BHP and VALE quotes using convolve() with normalized weights:
    bhp = np.loadtxt('BHP.csv', delimiter=',', usecols=(6,), unpack=True)
    bhp_returns = np.diff(bhp) / bhp[ : -1]
    smooth_bhp = np.convolve(weights/weights.sum(), bhp_returns)[N-1:-N+1]
    
    vale = np.loadtxt('VALE.csv', delimiter=',', usecols=(6,), unpack=True)
    vale_returns = np.diff(vale) / vale[ : -1]
    smooth_vale = np.convolve(weights/weights.sum(), vale_returns)[N-1:-N+1]
  3. Plot with matplotlib using this code:
    t = np.arange(N - 1, len(bhp_returns))
    plt.plot(t, bhp_returns[N-1:], lw=1.0)
    plt.plot(t, smooth_bhp, lw=2.0)
    plt.plot(t, vale_returns[N-1:], lw=1.0)
    plt.plot(t, smooth_vale, lw=2.0)
    plt.show()

    The chart would appear as follows:

    Time for action – smoothing with the hanning() function

    The thin lines on the preceding chart are the stock returns and the thick lines are the result of smoothing. As you can see, the lines cross a few times. These points might be important because the trend might have changed there. Or, at least, the relation of BHP to VALE might have changed. These turning inflection points probably occur often, so we might want to project into the future.

  4. Fit the result of the smoothing step to polynomials as follows:
    K = 8
    t = np.arange(N - 1, len(bhp_returns))
    poly_bhp = np.polyfit(t, smooth_bhp, K)
    poly_vale = np.polyfit(t, smooth_vale, K)
  5. Next, we need to evaluate the situation, where the polynomials we found in the previous step were equal to each other. This boils down to subtracting the polynomials and finding the roots of the resulting polynomial. Subtract the polynomials using polysub():
    poly_sub = np.polysub(poly_bhp, poly_vale)
    xpoints = np.roots(poly_sub)
    print("Intersection points", xpoints)

    The points are shown as follows:

    Intersection points [ 27.73321597+0.j          27.51284094+0.j          24.32064343+0.j
      18.86423973+0.j          12.43797190+1.73218179j  12.43797190-1.73218179j
       6.34613053+0.62519463j   6.34613053-0.62519463j]
    
  6. The numbers we get are complex, and that is not good for us (unless there is such a thing as imaginary time). Check which numbers are real with the isreal() function:
    reals = np.isreal(xpoints)
    print("Real number?", reals)

    The result is as follows:

    Real number? [ True  True  True  True False False False False]
    

    Some of the numbers are real, so select them with the select() function. The select() function forms an array by taking elements from a list of choices, based on a list of conditions:

    xpoints = np.select([reals], [xpoints])
    xpoints = xpoints.real
    print("Real intersection points", xpoints)

    The real intersection points are as follows:

    Real intersection points [ 27.73321597  27.51284094  24.32064343  18.86423973   0.           0.   0.  0.]
    
  7. We managed to pick up some zeroes. The trim_zeros() function strips the leading and trailing zeroes from a one-dimensional array. Get rid of the zeroes with the trim_zeros() function:
    print("Sans 0s", np.trim_zeros(xpoints))

    The zeroes are gone, and the output is shown as follows:

    Sans 0s [ 27.73321597  27.51284094  24.32064343  18.86423973]
    

What just happened?

We applied the hanning() function to smooth arrays containing stock returns. We subtracted two polynomials with the polysub() function. We then checked for real numbers with the isreal() function and selected the real numbers with the select() function. Finally, we stripped zeroes from an array with the trim_zeros() function (see smoothing.py):

from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt


N = 8

weights = np.hanning(N)
print("Weights", weights)

bhp = np.loadtxt('BHP.csv', delimiter=',', usecols=(6,), unpack=True)
bhp_returns = np.diff(bhp) / bhp[ : -1]
smooth_bhp = np.convolve(weights/weights.sum(), bhp_returns)[N-1:-N+1]

vale = np.loadtxt('VALE.csv', delimiter=',', usecols=(6,), unpack=True)
vale_returns = np.diff(vale) / vale[ : -1]
smooth_vale = np.convolve(weights/weights.sum(), vale_returns)[N-1:-N+1]

K = 8
t = np.arange(N - 1, len(bhp_returns))
poly_bhp = np.polyfit(t, smooth_bhp, K)
poly_vale = np.polyfit(t, smooth_vale, K)

poly_sub = np.polysub(poly_bhp, poly_vale)
xpoints = np.roots(poly_sub)
print("Intersection points", xpoints)

reals = np.isreal(xpoints)
print("Real number?", reals)

xpoints = np.select([reals], [xpoints])
xpoints = xpoints.real
print("Real intersection points", xpoints)

print("Sans 0s", np.trim_zeros(xpoints))

plt.plot(t, bhp_returns[N-1:], lw=1.0, label='BHP returns')
plt.plot(t, smooth_bhp, lw=2.0, label='BHP smoothed')

plt.plot(t, vale_returns[N-1:], '--', lw=1.0, label='VALE returns')
plt.plot(t, smooth_vale, '-.', lw=2.0, label='VALE smoothed')
plt.title('Smoothing')
plt.xlabel('Days')
plt.ylabel('Returns')
plt.grid()
plt.legend(loc='best')
plt.show()

Have a go hero – smoothing variations

Experiment with the other smoothing functions—hamming(), blackman(), bartlett(), and kaiser(). They work in more or less the same way as the hanning() function.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset