Files
tradingview/close_fft_spectrum.pine
2025-11-19 10:35:13 +08:00

47 lines
1.7 KiB
Plaintext

//@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)