利用傅立叶变换(FFT)预测股价
一、数学原理假设股价的对数收益率为什么用对数收益率呢是因为对数收益率更能满足平稳性要求是随时间周期变化的函数用表示根据傅立叶变换的原理可以表示成如下形式为复数欧拉公式傅立叶变换一般用复数表示因为复数表示更简洁。上式中是从变化到也就是说由无穷多个线性组合而成实际中不可能无穷而是由数据集大小而定若为奇数(odd)则的取值限定为若为偶数(even)则的取值限定为其中序号为的系数项实际为。即股票的连续N个对数收益率可以看成是N个的函数值即注上面连加号中的范围按为奇数时写的为偶数时替换成为偶数时的下标范围即可。由上面的个方程可以唯一解出N个的值记为。有了这N个就得到了的近似表示根据这个近似表示就可以预测接下来时间点上的对数收益率取二、代码import numpy as np import pandas as pd import matplotlib.pyplot as plt # 原始收盘价数据 df pd.DataFrame({close: [41660, 40680.9, 36445.3, 35071.4, 36244.6, 36660.4, 36958.3, 36809.3, 37160.1, 37716.6, 38166.8, 37881.8, 38466.9, 38694.6, 36896.4, 37311.6, 41574.2, 41382.6, 42380.9, 43840, 44043, 44372.7, 43495.4, 42373.7, 42217.9, 42053.7, 42535.9, 44544.9, 43873.6, 40515.7, 39974.4, 40079.2, 38386.9, 37008.2, 38230.3, 37250, 38327.2, 39219.2, 39116.7, 37699.1, 43160, 44421.2, 43893, 42454, 39148.7, 39398, 38420.8, 37988, 38730.6, 41941.7, 39422, 38729.6, 38807.4, 37777.3, 39671.4, 39280.3, 41114, 40917.9, 41757.5, 42201.1, 41262.1, 41002.2, 42364.1, 42882.8, 43991.5, 44313.2, 44511.3, 46827.8, 47122.2, 47434.8, 47068, 45510.3, 46283.5, 45811, 46407.4, 46580.5, 45497.6, 43170.5, 43444.2, 42252, 42754, 42158.9, 39530.4, 40074.9, 41147.8, 39942.4, 40551.9, 40378.7, 39678.1, 40801.1, 41493.2, 41358.2, 40480, 39709.2, 39441.6, 39450.1, 40426.1, 38112.6, 39235.7, 39742.1, 38596.1, 37630.8, 38468.4, 38525.2, 37728.9, 39690, 36553, 36013.8, 35472.4, 34038.4, 30076.3, 31017.1, 29103.9, 29029.8, 29287.1, 30086.7, 31328.9, 29874, 30444.9, 28715.3, 30319.2, 29201, 29445.1, 30293.9, 29109.2, 29654.6, 29542.2, 29201.3, 28629.8, 29031.3, 29468.1, 31734.2, 31801, 29805.8, 30452.6, 29700.2, 29864, 29919.2, 31373.1, 31125.3, 30204.8, 30109.9, 29091.9, 28424.7, 26574.5, 22487.4, 22136.4, 22583.7, 20401.3, 20468.8]}) # 计算对数收益率 df[log_return] np.log(df[close]).diff() df df.dropna().reset_index(dropTrue) # 选取前N个数据来计算傅立叶变换的系数训练数据 N int(len(df) * 0.95) df_train df.iloc[0 : N].copy() # 傅立叶变换 coefficients np.fft.fft(df_train[log_return].values) coefficients / N frequances np.fft.fftfreq(coefficients.size, d1) # 选取主要频率这里根据振幅大小选取可以试验不同阀值的效果也可以试验其他选取条件 amplitude np.sqrt(coefficients.real**2 coefficients.imag**2) amplitude_mean amplitude.mean() amplitude_stdev amplitude.std() dominant_frequance_flags amplitude (amplitude_mean - 3.0*amplitude_stdev) # 由频域数据生成时域数据包括前N个训练数据和后续的预测数据 ret np.zeros(len(df), dtypenp.complex_) for k in range(coefficients.size): if dominant_frequance_flags[k]: ret np.array([coefficients[k] * complex(np.cos(frequances[k] * 2.0 * np.pi * n), np.sin(frequances[k] * 2.0 * np.pi * n)) for n in range(len(df))]) ret_recovered np.real(ret) # 可视化 fig plt.figure(numfLog Return, figsize(17, 6)) plt.plot(df[log_return].values, b, labelOriginal) plt.plot(ret_recovered, r--, labelRecovered) plt.vlines(N - 1, ymindf[log_return].min(), ymaxdf[log_return].max(), colorpurple, linewidth1, linestyle--) plt.legend() plt.show()三、解释1、代码中np.fft.fft函数的返回值与傅立叶变换公式中的相差了倍所以需要coefficients / N这样代码中的coefficients[k]就是。2、np.fft.fftfreq函数的返回值是与对应的频率即代码中的frequances[k]的值为。四、可视化结果五、参考资料1、关于傅立叶变换的知识可以参考mazonex的系列视频2、numpy中傅立叶变换相关的函数可以参考官方文档
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2443508.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!