Не блог, просто пишу заметки для себя :)

Почему бы не использовать БПФ или преобразование Фурье для извлечения закономерностей или компонентов в данных о ценах на акции вместо прямого использования вейвлет-преобразования?

Преобразование Фурье будет работать очень хорошо, когда частотный спектр является стационарным. То есть частоты, присутствующие в сигнале, не зависят от времени; если сигнал содержит частоту x Гц, эта частота должна одинаково присутствовать в любом месте сигнала.
Чем более нестационарным / динамичным является сигнал, тем хуже будут результаты.

Наши данные о запасах динамичны по своей природе. Намного лучший подход к анализу динамических сигналов - использовать вейвлет-преобразование вместо преобразования Фурье.

В чем разница между преобразованием Фурье и вейвлет-преобразованием?

Таким образом, вейвлет-преобразование также преобразует сигнал в его частотную область, как и преобразование Фурье. Разница в преобразовании Фурье имеет очень высокое разрешение в частотной области и нулевое разрешение во временной области.

в то время как выходные данные вейвлет-преобразования имеют высокое разрешение как по частоте, так и во временной области.

Проще говоря: преобразование Фурье (FT) расскажет, какие частоты присутствуют в вашем сигнале. Вейвлет-преобразование (WT) сообщит вам, какие частоты присутствуют и где (или в каком масштабе). Если бы у вас был сигнал, который менялся во времени, FT не сказал бы вам, когда (время) это произошло. Вы также можете подумать о замене временной переменной пространственной переменной по аналогичной аналогии.

Итак, используя преобразование Фурье, мы узнаем, какие частоты присутствуют в сигнале, но не в какое время эта частота колеблется, поэтому Как ученый преодолеть эту проблему?

Кратковременное преобразование Фурье. В этом подходе исходный сигнал разделяется на несколько частей равной длины (которые могут перекрываться, а могут и не иметь) с помощью скользящего окна перед применением преобразования Фурье. Идея довольно проста: если мы разделим наш сигнал на 10 частей, и преобразование Фурье обнаружит определенную частоту во второй части, то мы точно знаем, что эта частота возникла между 2/10 и 3/10 нашей исходный сигнал.

Основная проблема этого подхода заключается в том, что вы попадаете в теоретические пределы преобразования Фурье, известного как принцип неопределенности. Чем меньше мы сделаем размер окна, тем больше мы будем знать о том, где в сигнале возникла частота, но меньше о самом значении частоты. Чем больше мы сделаем размер окна, тем больше мы будем знать о значении частоты и меньше о времени.

Вейвлет-преобразование имеет:

для малых значений частоты высокое разрешение в частотной области, низкое разрешение во временной области,
для больших значений частоты низкое разрешение в частотной области, высокое разрешение во временной области.

Как работает вейвлет-преобразование?

Преобразование Фурье использует серию синусоидальных волн с разными частотами для анализа сигнала. То есть сигнал представлен в виде линейной комбинации синусоидальных волн.
Вейвлет-преобразование использует серию функций, называемых вейвлетами, каждая с разным масштабом. Слово вейвлет означает небольшую волну, и именно это вейвлет.

Таким образом, синусоидальная волна находится в диапазоне от -inf до + inf, в то время как вейвлет существует в течение определенной продолжительности, которая имеет нулевое среднее значение.

Есть много типов вейвлетов на выбор.

import pywt
print(pywt.families(short=False))
['Haar', 'Daubechies', 'Symlets', 'Coiflets', 'Biorthogonal', 'Reverse biorthogonal', 
'Discrete Meyer (FIR Approximation)', 'Gaussian', 'Mexican hat wavelet', 'Morlet wavelet', 
'Complex Gaussian wavelets', 'Shannon wavelets', 'Frequency B-Spline wavelets', 'Complex Morlet wavelets']

Итак, вейвлет имеет две основные концепции.

1. Масштабирование. Масштабирование - это процесс растяжения и сжатия сигнала во времени. Он представлен как φ (t / s), где φ (t) - сигнал, а s - коэффициент масштабирования и соответствует тому, насколько сигнал масштабируется во времени, а масштаб обратно пропорционален частоте.

  • Итак, сигнал с большим масштабом / окном (растянутый вейвлет) и анализ `` больших '' характеристик (что соответствует более низкой частоте), а затем мы смотрим на сигнал с меньшими масштабами (сжатый вейвлет), чтобы проанализировать более мелкие особенности (что соответствует более высокая частота).
  • Растянутый вейвлет помогает фиксировать медленно меняющиеся изменения сигнала, а сжатый вейвлет помогает фиксировать резкие изменения.

2. Сдвиг: смещение означает просто продвижение или задержку начала вейвлета по длине сигнала. Сдвинутый вейвлет обычно обозначается как φ (t-k). Нам нужно сдвинуть вейвлет, чтобы найти в сигнале искомую особенность.

Поскольку вейвлет локализован во времени, мы можем умножить наш сигнал на вейвлет в разных местах во времени. Мы начинаем с начала нашего сигнала и медленно перемещаем вейвлет к концу сигнала. Эта процедура также известна как свертка. После того, как мы сделали это для исходного (материнского) вейвлета, мы можем масштабировать его так, чтобы он стал больше, и повторить процесс.

Как вейвлеты могут быть полезны для извлечения функций из наших ценовых данных?

  1. Снижение шума серии

2. определение основной составляющей движения в серии

  • Снижение шума выполняется путем перекомпоновки ряда путем суммирования компонентов разложения, за вычетом последних нескольких высокочастотных компонентов. Этот шумоизолированный (или отфильтрованный) ряд, если он выбран правильно, часто дает представление об основном ценовом процессе. Предполагая, что продолжение в том же направлении, можно экстраполировать на короткий период вперед.

Итак, давайте возьмем данные о ценах MSFT и сгладим их, используя вейвлет-преобразование в качестве банка фильтров:

import yfinance as yf
import pywt
import numpy as np
import matplotlib.pyplot as plt
import copy
import pandas as pd
#define the ticker symbol
tickerSymbol = 'MSFT'
#get data on this ticker
tickerData = yf.Ticker(tickerSymbol)
#get the historical prices for this ticker
tickerDf = tickerData.history(period='1d', start='2010-1-1', end='2020-1-25')
composite_signal =  tickerDf['Close'].values
composite_signal
def filter_bank(index_list, wavefunc='db4', lv=4, m=1, n=4, plot=False):
    
    '''
    WT: Wavelet Transformation Function
    index_list: Input Sequence;
   
    lv: Decomposing Level;
 
    wavefunc: Function of Wavelet, 'db4' default;
    
    m, n: Level of Threshold Processing
   
    '''
   
    # Decomposing 
    coeff = pywt.wavedec(index_list,wavefunc,mode='sym',level=lv)   #  Decomposing by levels,cD is the details coefficient
    sgn = lambda x: 1 if x > 0 else -1 if x < 0 else 0 # sgn function
# Denoising
    # Soft Threshold Processing Method
    for i in range(m,n+1):   #  Select m~n Levels of the wavelet coefficients,and no need to dispose the cA coefficients(approximation coefficients)
        cD = coeff[i]
        Tr = np.sqrt(2*np.log2(len(cD)))  # Compute Threshold
        for j in range(len(cD)):
            if cD[j] >= Tr:
                coeff[i][j] = sgn(cD[j]) * (np.abs(cD[j]) -  Tr)  # Shrink to zero
            else:
                coeff[i][j] = 0   # Set to zero if smaller than threshold
# Reconstructing
    coeffs = {}
    for i in range(len(coeff)):
        coeffs[i] = copy.deepcopy(coeff)
        for j in range(len(coeff)):
            if j != i:
                coeffs[i][j] = np.zeros_like(coeff[j])
    
    for i in range(len(coeff)):
        coeff[i] = pywt.waverec(coeffs[i], wavefunc)
        if len(coeff[i]) > len(index_list):
            coeff[i] = coeff[i][:-1]
        
    if plot:     
        denoised_index = np.sum(coeff, axis=0)   
        data = pd.DataFrame({'CLOSE': index_list, 'denoised': denoised_index})
        data.plot(figsize=(10,10),subplots=(2,1))
        data.plot(figsize=(10,5))
   
    return coeff
coeff=filter_bank(composite_signal,plot=True)
fig, ax =  plt.subplots(len(coeff), 1, figsize=(10, 20))
for i in range(len(coeff)):
    if i == 0:
        ax[i].plot(coeff[i], label = 'cA[%.0f]'%(len(coeff)-i-1))
        ax[i].legend(loc = 'best')
    else:
        ax[i].plot(coeff[i], label = 'cD[%.0f]'%(len(coeff)-i))
        ax[i].legend(loc = 'best')

Вышеупомянутая функция также возвращает упорядоченный список массивов коэффициентов, где n обозначает уровень разложения. Первый элемент (cA_n) результата - это массив коэффициентов аппроксимации, а следующие элементы (cD_n - cD_1) - массивы коэффициентов деталей.

В следующем посте мы будем использовать другие формы вейвлет-преобразования для создания функций для наших ценовых данных.