Wavelet bandpass indicator for backtrader

Hi,
Here's a wavelet bandpass filter indicator using the pywt (python wavelets) library. I haven't found the backtrader_contrib github so I'll just leave this here in case anyone wants to use it. GPL3. No support, warranties, either expressed or implied. No guarantee that this will have efficacy for your particular application.
With minimal (or no) changes this should support:
Haar (haar)
Daubechies (db)
Symlets (sym)
Coiflets (coif)
Biorthogonal (bior)
Reverse biorthogonal (rbio)
“Discrete” FIR approximation of Meyer wavelet (dmey)
Gaussian wavelets (gaus)
Mexican hat wavelet (mexh)
Morlet wavelet (morl)
Complex Gaussian wavelets (cgau)
Shannon wavelets (shan)
Frequency BSpline wavelets (fbsp)
Complex Morlet wavelets (cmor)Good luck,
B. Bradford#!/usr/bin/env python # * coding: utf8; pyindentoffset:4 * ############################################################################## # # Copyright (C) 2017 Benjamin Bradford (bigdavediode2 (at ) yahoo.com) # Wavelet deconstruction to specified subband/level # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################### from __future__ import (absolute_import, division, print_function, unicode_literals) import backtrader.indicators as btind import backtrader as bt import pywt class bbDWT(bt.Indicator): # Approximation, detail coefficient lines if wanted: lines = ('cA2', 'cD2', 'cD1', ) params = (('wavelettype', 'db2'), ('coefflevels', 5), ('coeffpick', 0), ) def once(self, start, end): super(bbDWT, self).__init__() lstinputdata = self.data.array coeffs = pywt.wavedecn(lstinputdata, self.params.wavelettype, level=self.params.coefflevels) # Use if you wish to graph spectrum bands/coefficients: # coeffcA2, coeffcD2, coeffcD1 = coeffs # print(coeffs) print(len(coeffs)) arr, coeff_slices = pywt.coeffs_to_array(coeffs) print(coeff_slices) # Zero out all but selected wavelet coeff level (avoids having to pad arrays): for i in range(0, len(coeff_slices)): if i != self.params.coeffpick: #Remove the "slice" portion of the returned slices up to the bracket to run as a slice command: s1 = str(coeff_slices[i]) s1 = s1[s1.find('slice'):s1.find(')')+1] execstring = 's1 = ' + s1 print(execstring) exec(execstring) arr[s1] = 0 print(arr) coeffs_from_array = pywt.array_to_coeffs(arr, coeff_slices) dummy_array = pywt.waverecn(coeffs_from_array, self.params.wavelettype) self.lines.cA2.array = dummy_array

@bigdavediode said in Wavelet bandpass indicator for backtrader:
wavelet bandpass filter
This looks really interesting. I'll be honest I never even heard of this before. I've done a bit of googling around the subject just now. Could you explain how this could be used in trading? Cheers mate

Hi,
You can, with minimal changes to the code, use it in two ways: smoothing of the function by zeroing out certain frequency bands (a bandpass filter and thus noise reduction), or like I've implemented it here to extract any particular frequency band and chart it. If you're a shortterm trader you would, perhaps, extract highfrequency bands. If you're more long term then you select those longerterm frequencies.
Good luck,
B.

@bigdavediode hmm..When you saying smoothing of function. Could I use to eg with price as input to look for cycles? Or would I apply this to e.g. an indicator to again look for key frequencies within that. Any chance you could upload a simple example demonstrating? Perhaps with a visulisation/plot before and after? Sounds highly interesting.

@RichardO'Regan Yes, you could smooth the price by zeroing out the highfrequency bands (noise) by changing the "for" loop if from != to >. This would remove the highest frequencies. This might reveal (as an example) low frequency seasonal cycles.
Choose your wavelet type carefully (perhaps start with Haar wavelets) and also please keep in mind that low frequencies have lower "temporal resolution"  ie. they are less timespecific, so if you are looking for tomorrow's signals with EOD data inputted, low frequency bands will have "leaks" of the next day's completed data into the previous day's signal. That wouldn't happen (as significantly) with higher frequencies more appropriate to daily prediction. Translation: use the right tool for the job.
Here's a simple example strategy:
import backtrader.indicators as btind from bbwavelet import bbDWT class firstStrategy(bt.Strategy): def __init__(self): self.dwt = bbDWT(self.data, wavelettype='haar', coefflevels = 3, coeffpick = 1)

@bigdavediode Could you kindly suggest some introductory material about wawelets? That would help me in the effort of understanding how to use your code. Many thanks in advance, and thank you for sharing your work.

@lvaghi Mathlab has some good introductory videos: https://www.youtube.com/watch?v=QX1xGVFqmw
I found this site interesting, but I haven't read it entirely: http://www.bearcave.com/misl/misl_tech/wavelets/
One thing that is a benefit with wavelets is their orthogonality. Information in one signal level is, for the most part, independent of the other signal bands.
B.

heya Dave, just invested an hour reading your links. Interesting stuff. I think there is probably a number of people in this forum also interested in this subject. I have a bit of an overview from reading up on this, though I feel it would take me weeks to get up to speed with this subject! I'm wondering how money could be made using these techniques, i.e. where is the edge?
 Perhaps I could look for reversions of actual price with the filtered price.. e.g. when filtered price was less than market price sell market etc..
 Or perhaps I could use filtered line to do trend calculations in the hope that I could predict trend a bit quicker before others in market did ..catch a move earlier etc.
You have given some code examples on how to use, if you have time, would you be able to provide a basic visual example e.g. a line of close of a stock and the wavelet filtered line, and what the line means . etc? Would be really helpful to see something visual  aids understanding).
Cheers mate
Rich

@RichardO'Regan Any type of indicator that you use a moving average for, crossover, for example, results in a loss of information from the original signal, autocorrelation, and lag. https://www.researchgate.net/post/What_are_the_disadvantages_of_moving_average_filter_when_using_it_with_time_series_data Wavelets address some of these issues if used properly.
I recommend deciding what your average hold time for a trade is (seconds, minutes, days) and use wavelet levels that correspond to the frequency that you are interested in to examine if there is a cyclical nature at the frequency that you trade within.
 depends on whether you are a meanreversion trader and 2) depends on whether you are trend following. Whatever your predilections are wavelets can remove the noise definitely better than MA's and, imo, more usefully than FFT's.
Hope that helps,
B.