// Licensed under the Apache License, Version 2.0 // © mihakralj //@version=6 indicator("Sine-weighted Moving Average (SINEMA)", "SINEMA", overlay=true) //@function Calculates SINEMA using sine-wave weighted smoothing with compensator //@param source Series to calculate SINEMA from //@param period Lookback period - FIR window size //@returns SINEMA value, calculates from first bar using available data //@optimized Uses sine wave weighting with O(n) complexity per bar due to lookback loop sinema(series float source, simple int period) => if period <= 0 runtime.error("Period must be greater than 0") int p = math.min(bar_index + 1, period) var int prev_p = 0 var array sine_weights = array.new_float(period, 0.0) if p != prev_p sine_weights := array.new_float(p, 0.0) for j = 0 to p - 1 array.set(sine_weights, j, math.sin(math.pi * (j + 1) / p)) prev_p := p float sum = 0.0 float weight = 0.0 for i = 0 to p - 1 float price = source[i] if not na(price) float w = array.get(sine_weights, i) sum += price * w weight += w nz(sum / weight, source) // ---------- Main loop ---------- // Inputs i_period = input.int(10, "Period", minval=1) i_source = input.source(close, "Source") // Calculation sinema_value = sinema(i_source, i_period) // Plot plot(sinema_value, "SINEMA", color=color.yellow, linewidth=2)