DFT和FFT
离散傅里叶变换
傅里叶变换将信号从时间域变换到频率域,但是离散傅里叶变换(discrete Fourier transform
)的缺点是计算量太大,时间复杂度太高,当采样点数量较多的时候,计算缓慢,因此有了快速傅里叶变换(FFT
)
快速傅里叶变换
计算量较小的DFT的一种实现,1-D
FFT变换公式如下
y
[
k
]
=
∑
n
=
0
N
−
1
e
−
2
π
j
k
n
N
x
[
n
]
y[k]=\sum_{n=0}^{N-1}e^{-2\pi j\frac{kn}{N}}x[n]
y[k]=n=0∑N−1e−2πjNknx[n]
傅里叶逆变换的公式如下
x
[
n
]
=
1
N
∑
k
=
0
N
−
1
e
2
π
j
k
n
N
y
[
k
]
x[n]=\frac{1}{N}\sum_{k=0}^{N-1}e^{2\pi j\frac{kn}{N}}y[k]
x[n]=N1k=0∑N−1e2πjNkny[k]
根据Fourier Transformation
的定义可以得到
y
[
0
]
=
∑
n
=
0
N
−
1
x
[
n
]
y[0]=\sum_{n=0}^{N-1}x[n]
y[0]=n=0∑N−1x[n]
Demo
两个正弦波叠加后的FFT
def FFT_demo_1():
# 两个正弦波叠加的FFT分解
# 样本点的数量
n = 600
# sample spacing
T = 1.0/800.0
x = np.linspace(0.0, n*T, n)
y = np.sin(50*2*np.pi*x)+0.5*np.sin(80*2*np.pi*x)
yf = fft(y)
xf = np.linspace(0, 1.0/(2.0*T), n//2)
plt.plot(xf, 2.0/n*np.abs(yf[0:n//2]))
plt.grid()
plt.title('two sine waves superposition')
plt.show()
The FFT input signal is inherently truncated. This truncation can be modeled as multiplication of an infinite signal with a rectangular window function. In the spectral domain this multiplication becomes convolution of the signal spectrum with the window function spectrum, being of form sin ( x ) / x \sin(x)/x sin(x)/x. This convolution is the cause of an effect called
spectral leakage
. Windowing the signal with a dedicated window function helps mitigate spectral leakage.
使用Blackman
窗口缓解spectral leakage
现象.
def FFT_demo_2_blackman():
n, T = 600, 1.0/800.0
w = blackman(n)
x = np.linspace(0.0, n*T, n)
y = np.sin(50*2*np.pi*x)+0.5*np.sin(80*2*np.pi*x)
yf = fft(y)
ywf = fft(y*w)
xf = np.linspace(0, 1.0/(2*T), n//2)
plt.semilogy(xf[1:n//2], 2.0/n*np.abs(yf[1:n//2]), '-b', lw=1.0, label='FFT')
plt.semilogy(xf[1:n//2], 2.0/n*np.abs(ywf[1:n//2]), '-r', lw=1.0, label='FFT w. window')
plt.legend(loc='best')
plt.grid()
plt.show()
收益率序列的FFT
可以将收益率序列看做是时域上的信号,使用FFT转换到频域上
from scipy.fft import fft
import matplotlib.pyplot as plt
def fft_returns_demo():
fig = plt.figure()
ax1 = fig.add_subplot(111)
t = np.arange(len(y))
y_fft = fft(y)
ax1.plot(y, 'grey', ls='-', alpha=1.0, lw=1.0, label='returns')
ax2 = ax1.twinx()
ax2.plot(np.abs(y_fft), 'b', ls='-', alpha=0.4, lw=0.5, label='fft returns')
fig.legend()
plt.show()