Adaptive Spectral Forecast [WillyAlgoTrader]📡 Adaptive Spectral Forecast is an overlay indicator that applies Goertzel spectral analysis to decompose price into its dominant cyclical components, reconstructs them as a harmonic sum, and then extrapolates the resulting waveform forward in time to generate a visual forecast with confidence bands. Signals fire when the forecast direction changes with sufficient signal-to-noise ratio and trend alignment — projecting where price is likely to oscillate next based on the cycles detected in recent history.
This is a fundamentally different approach from trend-following or momentum-based indicators. Instead of asking "where is price going based on its direction and speed?", spectral analysis asks "what recurring cycles exist in this price data, and where do they project to next?" The Goertzel algorithm is a targeted frequency detector — it scans a range of cycle periods, measures the power (amplitude²) at each frequency, identifies the dominant peaks, computes their exact phase and amplitude via DFT projection, and recombines them into a multi-harmonic forecast that decays toward the adaptive trend as it extends into the future.
🧩 WHY THESE COMPONENTS WORK TOGETHER
Raw price is a mix of trend, cycles, and noise. Attempting to forecast raw price directly fails because trend and cycles require different extrapolation methods: trend continues linearly, cycles repeat sinusoidally, and noise should not be extrapolated at all.
This indicator solves the problem through decomposition and reassembly:
EMA trend extraction → Hann-windowed detrending → Goertzel spectral scan → SNR peak detection → DFT coefficient extraction → Harmonic recombination with decay → Trend re-addition → Confidence bands
Each stage addresses a specific challenge:
— Trend extraction separates the slow directional component so it can be extrapolated linearly (via slope), not sinusoidally
— Hann windowing reduces spectral leakage — without it, the finite data window creates false frequency peaks that contaminate the analysis
— Goertzel scanning efficiently measures power at each candidate frequency without computing a full FFT — enabling targeted, adaptive-resolution frequency detection
— SNR filtering ensures only cycles with meaningful signal strength are included — weak noise-level frequencies are discarded
— DFT coefficient extraction computes the exact amplitude and phase of each selected cycle on un-windowed data (the Hann window is only for spectral scanning, not for coefficient calculation — this preserves correct amplitudes)
— Harmonic decay causes the cyclic component to gradually fade toward the trend as the forecast extends forward — reflecting the reality that detected cycles have limited persistence
— Confidence bands widen with √(bars ahead) × ATR, showing that forecast uncertainty grows with distance
Removing any component breaks the pipeline: without detrending, the Goertzel scan detects the trend as a low-frequency "cycle". Without Hann windowing, spectral leakage creates phantom peaks. Without SNR filtering, the forecast includes noise-level harmonics that produce random oscillations. Without decay, the harmonic projection repeats forever at full amplitude (unrealistic). The full pipeline is required.
🔍 WHAT MAKES IT ORIGINAL
1️⃣ Goertzel spectral analysis for cycle detection.
The Goertzel algorithm is a single-frequency DFT that computes the power at one specific period using a recursive formula:
s0 = data + 2×cos(2π/period) × s1 − s2
After iterating through all N data points, the power is: (s1 − s2×cos(ω))² + (s2×sin(ω))², normalized by N² for cross-period comparability.
The indicator scans every integer period from Min Cycle Period (default 8) up to N/2, with an adaptive step size: every period for fast cycles (≤30 bars), step of 2 for longer cycles (reducing computation without losing resolution where it matters most). For each period, the Goertzel power is computed, producing a power spectrum — a map of which cycle lengths carry the most energy in the current price data.
This is fundamentally more targeted than an FFT. An FFT computes power at all frequencies simultaneously but at fixed resolution (determined by window size). The Goertzel approach allows scanning exactly the frequency range of interest with customizable resolution.
2️⃣ SNR-based peak detection with fallback.
From the power spectrum, the indicator identifies local peaks (frequencies where power is higher than both neighbors) and computes the Signal-to-Noise Ratio for each: SNR = peak_power / mean_power_across_all_frequencies. Only peaks with SNR ≥ Min Cycle SNR (default 2.0) are accepted as genuine cycles — the rest are considered noise-level fluctuations.
If no peaks pass the SNR filter (possible in highly random or trend-dominated price action), the algorithm falls back to the single strongest frequency. In this case, the dashboard displays "Weak*" strength and buy/sell signals are suppressed — the forecast is shown for visual reference only, but the indicator acknowledges that no reliable cyclical structure was found.
The top N peaks (sorted by power, N = Harmonics Count, default 5) are selected as the dominant cycles.
3️⃣ DFT coefficient extraction on un-windowed data.
For each selected cycle period, the indicator computes exact sine and cosine coefficients using standard DFT projection:
a = (2/N) × Σ data × sin(2π × i / period)
b = (2/N) × Σ data × cos(2π × i / period)
Critically, this computation uses the raw detrended data (without Hann windowing). The Hann window was only applied for the spectral scan (to identify which frequencies are dominant). Using windowed data for coefficient extraction would distort the amplitude of the harmonics. This two-pass approach — windowed scan for detection, raw data for coefficients — is a key design choice that preserves forecast accuracy.
4️⃣ Harmonic extrapolation with configurable decay.
The forecast is constructed by evaluating the harmonic sum at each future bar:
forecast = trend_projection + Σ (a_k × sin(ω_k × t) + b_k × cos(ω_k × t)) × decay^(t − t_base)
Where trend_projection = trend_last + trend_slope × bars_ahead (linear extrapolation of the EMA trend). The decay factor (default 0.97) causes harmonic amplitude to reduce by 3% per bar, so the cyclic component gradually fades and the forecast converges toward the trend line.
At decay = 1.0, harmonics repeat at full amplitude forever (pure cycle projection). At decay = 0.95, they fade rapidly (forecast becomes trend-only within ~20 bars). Default 0.97 provides meaningful oscillation for the first 20–30 bars before fading. The forecast line is colored by segment: green segments where the forecast is rising, red where falling. Reversal dots mark predicted peaks and troughs.
5️⃣ ATR-based confidence bands with √t scaling.
Uncertainty in the forecast grows with distance. The confidence band width is calculated as:
band_width = ATR(14) × confidence_multiplier × √(bars_ahead)
The √t scaling follows the mathematical principle that forecast variance grows linearly with time horizon (standard deviation grows with square root). The ATR provides the natural volatility scale of the instrument. At bar +1, the band is approximately ATR × multiplier. At bar +25, it's 5× wider. This gives a realistic visual envelope of where price might actually be, not just the central harmonic forecast.
6️⃣ 3-bar consensus forecast direction.
Instead of using a simple "is the next bar higher or lower?" check (which is noisy), the forecast direction is determined by majority vote over 3 bars:
The indicator evaluates the forecast at t+0, t+1, t+2, t+3 and counts upward moves: upVotes = (y1>y0 ? 1:0) + (y2>y1 ? 1:0) + (y3>y2 ? 1:0). If ≥2 of 3 transitions are upward → forecast direction is bullish. If ≤1 → bearish. This consensus approach prevents a single-bar oscillation from flipping the forecast direction.
7️⃣ Trend alignment filter for signal quality.
When enabled (default on), buy signals require the EMA trend slope to be positive, and sell signals require negative slope. This prevents the indicator from generating counter-trend signals when a cycle oscillation temporarily points against the broader trend — which is the most common source of false signals in cycle-based systems.
If the trend filter blocks a direction change, the forecast visualization still updates (you can see the cycle projection) but no signal label is emitted. Additionally, signals are suppressed when the SNR is below the minimum threshold or when the spectral scan fell back to a single non-significant frequency.
8️⃣ Adaptive trend extraction with linear extrapolation.
The trend component is extracted using an EMA with configurable smoothing (default 30 bars), applied forward using the buildTrendArray function. The trend's slope is computed via weighted linear regression over the last 5 points of the trend array — providing a stable slope estimate that isn't dominated by a single bar.
The trend is extrapolated linearly into the forecast: trend_forecast = trend_last + slope × i. This linear projection is appropriate for the short-term forecast horizon (15–55 bars) where trend curvature is typically negligible.
9️⃣ Historical fit visualization.
The reconstructed harmonic sum + trend is plotted over historical data as a polyline, showing how well the detected cycles explain the actual price movement. This serves as an immediate visual validation: if the fit tracks price well, the detected cycles are meaningful. If the fit diverges significantly, the current market regime may not have strong cyclical structure (reflected in low SNR scores in the dashboard).
The fit line is colored by trend direction (green for bullish slope, red for bearish) and decimated for performance (every 1–3 bars depending on lookback length).
🔟 Four presets with coordinated parameter scaling.
— Conservative : lookback ≥ 150, harmonics ≤ 3, forecast ≥ 40 bars — stable, long-term cycles, less overfitting risk
— Default : user settings unchanged
— Aggressive : lookback ≤ 80, harmonics +1, forecast ≤ 25 — faster adaptation, more cycles included
— Scalping : lookback ≤ 50, harmonics +2, forecast ≤ 15 — shortest window, most harmonics, very short projection
Each preset adjusts lookback (spectral window), harmonics count (complexity), and forecast length (projection horizon) as a coordinated unit. Longer lookback needs fewer harmonics (the cycles are more stable). Shorter lookback needs more harmonics (to capture the faster fluctuations within the compressed window).
⚙️ HOW IT WORKS — CALCULATION FLOW
Step 1 — Data collection: The last N bars (Analysis Lookback, default 144) of the selected price source are collected into an array, oldest first.
Step 2 — Trend extraction: An EMA with the Trend Smoothing period (default 30) is applied across the array using a forward-pass recursive formula: trend = α × price + (1−α) × trend . This produces a smooth trend array.
Step 3 — Detrending + Hann window: Each bar's trend value is subtracted from its price. The residual is multiplied by a Hann window: w = 0.5 × (1 − cos(2π×i/(N−1))). This isolates the cyclical component while minimizing spectral leakage at the data boundaries.
Step 4 — Goertzel spectral scan: For each candidate period from minPeriod to N/2 (adaptive step: 1 for periods ≤30, 2 for longer), the Goertzel algorithm computes power. The result is a power spectrum across all scanned frequencies.
Step 5 — Peak detection: Local maxima in the power spectrum are identified (power > both neighbors). Each peak's SNR is computed against the mean power. Peaks with SNR ≥ threshold are accepted. If none pass, the strongest single frequency is used as fallback (with "Weak*" marking).
Step 6 — Coefficient extraction: For the top N peaks (by power), sine and cosine coefficients are computed via DFT projection on raw (un-windowed) detrended data. This gives exact amplitude and phase for each cycle.
Step 7 — Forecast generation: The trend is extrapolated linearly using its 5-bar regression slope. Each harmonic is evaluated at future time steps with decay applied. The sum of trend + decayed harmonics produces the central forecast line. Confidence bands = ATR × multiplier × √(bars_ahead).
Step 8 — Direction and signals: 3-bar consensus determines forecast direction. Trend filter and SNR check gate signal emission. Buy/sell labels appear on bar-close confirmation.
📖 HOW TO USE
🎯 Quick start:
1. Add the indicator — the historical fit and forecast line appear on the last bar
2. The colored dotted line extending right is the forecast (green = rising, red = falling)
3. Colored dots (●) on the forecast mark predicted peaks and troughs
4. Dotted lines above and below = confidence bands (forecast uncertainty zone)
5. ▲/▼ labels = buy/sell signals when the forecast direction changes
👁️ Reading the chart:
— 🟢 Green solid line on history = harmonic fit (uptrend slope)
— 🔴 Red solid line on history = harmonic fit (downtrend slope)
— 🟢🔴 Dotted line extending right = forecast (colored by direction: green rising, red falling)
— 🔵 Upper/lower dotted lines = confidence bands (uncertainty grows with distance)
— 🟢 ● dots = predicted troughs (potential support)
— 🔴 ● dots = predicted peaks (potential resistance)
— 🟢 ▲ below bar = buy signal (forecast changed to bullish)
— 🔴 ▼ above bar = sell signal (forecast changed to bearish)
📊 Dashboard fields:
— Trend: current EMA trend direction (Bullish / Bearish / Neutral)
— Forecast: predicted direction (▲ Up / ▼ Down / — Flat)
— Signal: current state (BUY / SELL / Bullish Bias / Bearish Bias / Wait)
— Strength: cycle quality based on average SNR (Strong > 5.0 / Medium > 2.5 / Weak / Weak* = fallback)
— Dom. Cycle: dominant cycle period in bars (e.g., "34 bars")
— Cycles: how many cycles passed SNR filter vs. requested (e.g., "3 / 5")
— Timeframe, preset, version
🔧 Tuning guide:
— Forecast too noisy: reduce Harmonics Count (3), increase Min SNR (3.0+), increase Trend Smoothing
— Forecast too smooth: increase Harmonics Count (5–7), decrease Min SNR (1.5), decrease Trend Smoothing
— Cycles don't match price: increase Analysis Lookback (200+) for more stable cycle detection, or decrease for faster adaptation
— Forecast fades too fast: increase Decay Rate toward 0.99–1.0
— Forecast unrealistic long-term: decrease Decay Rate toward 0.95, reduce Forecast Bars
— Too many false signals: enable Trend Alignment Filter, increase Min SNR
— Scalping 1–5M: use Scalping preset (lookback ≤50, 7 harmonics, 15-bar forecast)
— Swing 4H–1D: use Conservative preset (lookback ≥150, 3 harmonics, 40-bar forecast)
⚙️ KEY SETTINGS REFERENCE
⚙️ Main:
— Analysis Lookback (default 144): spectral analysis window — the last N bars analyzed
— Harmonics Count (default 5): how many dominant cycles to include in the forecast
— Min Cycle Period (default 8): shortest cycle to scan for (bars)
— Preset (default Default): Conservative / Default / Aggressive / Scalping
— Trend Alignment Filter (default On): require trend-forecast agreement for signals
🔮 Forecast:
— Forecast Bars (default 55): projection length into the future
— Confidence Band Width (default 1.5× ATR): band multiplier
— Trend Smoothing (default 30): EMA period for trend component
— Harmonic Decay Rate (default 0.97): amplitude reduction per bar (1.0 = no decay)
— Min Cycle SNR (default 2.0): signal-to-noise threshold for cycle acceptance
🎨 Visual:
— Historical fit, trend line, reversal dots, confidence bands (all toggleable)
— Auto / Dark / Light theme
🔔 Alerts
— 🟢 BUY — ticker, price, timeframe, time
— 🔴 SELL — same fields
Both support plain text and JSON webhook format. Signals are bar-close confirmed, direction-locked, trend-filtered, and SNR-gated.
⚠️ IMPORTANT NOTES
— 📐 This is spectral analysis, not trend following. The indicator detects and projects recurring cycles. In markets with strong cyclical structure (commodities, forex majors, crypto with regular oscillations), it performs well. In news-driven or momentum-dominated markets with no cyclical structure, the SNR will be low and the forecast unreliable — the dashboard reflects this via the Strength reading.
— 🚫 No repainting of signals. The spectral analysis runs on barstate.islast (updating the forecast in real time on the current forming bar). Signals only fire on the next barstate.isconfirmed bar, after the forecast direction has been set. This means the forecast line itself updates in real time (by design — it's a live projection), but buy/sell signals are confirmed and do not change retroactively.
— 📊 The forecast is a projection, not a prediction. It shows where price would go if the detected cycles continue with their current amplitude and phase. Real markets introduce new information that disrupts cycles. The confidence bands reflect this growing uncertainty. Treat the forecast as a probabilistic zone, not a target.
— 🔄 "Weak*" strength means no cycles passed the SNR filter and the indicator fell back to the single strongest frequency. In this state, signals are suppressed. The forecast is still shown for visual reference but should not be trusted for trading decisions.
— ⚖️ The Hann window is applied only for spectral scanning , not for coefficient extraction. This is deliberate: the window prevents spectral leakage during frequency detection, but the un-windowed data preserves correct harmonic amplitudes for the forecast.
— 📏 The forecast extends a fixed number of bars into the future. Accuracy degrades with distance — the first 10–15 bars are typically the most reliable. The confidence bands quantify this degradation visually.
— 🛠️ This is a spectral analysis and forecasting tool , not an automated trading bot. It detects cycles, projects them forward, and generates directional signals — trade decisions remain yours.
— 🌐 Works on all markets and timeframes. Cycle periods adapt automatically to whatever timeframe you apply it on.
אינדיקטור Pine Script®






















