//@version=6 indicator("Close FFT Spectrum", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500) int windowLen = input.int(64, "FFT窗口长度", minval=16, maxval=256, step=8) bool normalizeSpectrum = input.bool(true, "幅值归一化(除以窗口长度)") calcSpectrum(float[] samples, bool normalize) => int size = array.size(samples) float[] mags = array.new_float() if size == 0 mags float norm = normalize ? float(size) : 1.0 int freqLimit = size / 2 if freqLimit < 1 freqLimit := 1 float twoPi = 2.0 * math.pi for freq = 0 to freqLimit float sumReal = 0.0 float sumImag = 0.0 for n = 0 to size - 1 float sample = array.get(samples, size - 1 - n) float angle = twoPi * float(freq) * float(n) / float(size) sumReal += sample * math.cos(angle) sumImag -= sample * math.sin(angle) float magnitude = math.sqrt(sumReal * sumReal + sumImag * sumImag) / norm array.push(mags, magnitude) mags var float[] priceBuffer = array.new_float() var int lastWindowSetting = na if na(lastWindowSetting) or lastWindowSetting != windowLen lastWindowSetting := windowLen array.clear(priceBuffer) if not na(close) if array.size(priceBuffer) >= windowLen array.shift(priceBuffer) array.push(priceBuffer, close) bool ready = array.size(priceBuffer) == windowLen float[] spectrum = ready ? calcSpectrum(priceBuffer, normalizeSpectrum) : array.new_float() int freqCount = array.size(spectrum) float dcComponent = ready and freqCount > 0 ? array.get(spectrum, 0) : na plot(dcComponent, title="直流分量", color=color.orange, linewidth=2)