MQL5 频谱分析程序:FFT 与图形对象面板
一、频谱分析在交易中的用途
价格序列可以看作一种信号。对它做傅里叶变换,能得到“哪些周期/频率成分最强”的频谱——也就是找出市场里反复出现的周期性(如某段历史里存在一个约 N 根柱的波动节律)。文章用 FFT 分析移动平均线的脉冲特性,直观展示不同均线的频率响应,帮助你理解指标的滞后与平滑本质。
二、FFT 原理简述
快速傅里叶变换(Cooley-Tukey 基 2)把时域序列转成频域。它要求序列长度为 2 的幂(文章固定用 1024=2^10)。内部用复数(实部 re / 虚部 im)运算,通过“位反转置换 + 蝶形(butterfly)运算”逐级合并,把 O(N²) 的离散傅里叶变换降到 O(N·logN)。
三、MQL5 实现:调用 FFT 函数
文章把 FFT 实现封装在外部函数 realfastfouriertransform(取自 mql4.com),指标只需准备 1024 个输入点再调用。输入可以是外部指标零缓冲的 1024 个值,也可以是 SMA/LWMA 的脉冲(前 N 点为 1、其余 0)来观测其频率特性:
void get_input_data()
{
ArrayInitialize(InpData, 0.0);
switch(InputSource)
{
case 0: CopyBuffer(ExtHandle,0,0,ArraySize(InpData),InpData); break;
case 1: for(i=0;i<3;i++) InpData[i]=1; break; // SMA(3) 脉冲
case 2: for(i=0;i<32;i++) InpData[i]=1; break; // SMA(32) 脉冲
case 3: for(i=0;i<12;i++) InpData[i]=12-i; break; // LWMA(12) 脉冲
}
}
void fft_calc()
{
realfastfouriertransform(InpData, ArraySize(InpData), false); // FFT
for(i=1;i<ArraySize(Spectrum);i++)
{
k=i*2;
Spectrum[i]=InpData[k]*InpData[k] + InpData[k+1]*InpData[k+1]; // 实部^2+虚部^2 = 功率
}
Spectrum[0]=0.0; // 清直流分量
}
四、幅度谱与显示
FFT 后每个频率点是一对 (re, im),功率谱 = re²+im²(文章直接计算平方,未开方)。频谱用面板对象(标签/趋势线/矩形)绘制,并提供线性/对数(dB)、振幅/功率四种显示模式。要找“主导周期”,就找功率谱峰值对应的谐波索引 k,周期长度 ≈ 总样本数 / k。
五、坑
六、价格序列做 FFT 的意义
快速傅里叶变换(FFT)把价格序列从「时间域」变到「频率域」,让你看到「哪些周期在价格里最 dominant」。市场常呈现季节性周期(如周内效应、月度节奏),FFT 能把这些隐藏周期挖出来。
注意:金融价格非平稳,直接对原始价格做 FFT 意义不大;通常先取收益率或去趋势后再变换,周期结构才清晰。
七、主周期检测
变换后看频谱的峰值位置,峰值对应的频率倒数就是「主导周期」(如 20 根、60 根)。这些周期可用于择时(在周期低点附近偏多)或验证当前行情是否处于某周期的特定相位。
但周期会漂移,不能刻舟求剑。把 FFT 当成「当前市场节奏的快照」,定期重算,比当成永恒真理更稳。 一个实用技巧是把 FFT 结果和「近期波动率」一起看:低波动期周期更稳定、高波动期周期易被噪音淹没,二者印证时才信周期信号。
八、实现坑:窗函数与采样长度
两大坑:一是采样长度必须是 2 的幂(FFT 要求),且长度要覆盖你关心的最小周期若干倍,太短看不出长周期;二是边界突变会产生频谱泄漏,要用窗函数(汉宁窗等)加权缓解。
九、FFT 与周期交易的结合
检测出主周期后,可直接做「周期择时」:在周期的回踩低位偏多、高位偏空,相当于用市场的节奏感替代主观判断。配合支撑阻力,命中率比盲目跟风高。
但要强调:周期择时赚的是「概率倾斜」,不是每次都对。必须配止损和仓位管理,单笔错了也不伤筋动骨,靠周期优势在样本上累积正期望。