mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-27 17:27:43 +00:00
59 lines
2.3 KiB
Plaintext
59 lines
2.3 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Deviation-Scaled Moving Average (DSMA)", "DSMA", overlay=true)
|
|
|
|
//@function Calculates DSMA using standard deviation to scale the averaging factor
|
|
//@param source Series to calculate DSMA from
|
|
//@param period Length of the lookback period for both average and deviation calculation
|
|
//@param scaleFactor Combined scaling/smoothing factor (0.01-0.9)
|
|
//@returns DSMA value that adapts to market volatility through deviation scaling
|
|
//@optimized Uses circular buffer for RMS calculation and adaptive alpha for O(1) complexity
|
|
dsma(series float source, simple int period, simple float scaleFactor=0.5) =>
|
|
float a1 = math.exp(-1.414 * math.pi / (period * 0.5))
|
|
float b1 = 2.0 * a1 * math.cos(1.414 * math.pi / (period * 0.5))
|
|
float c1 = 1.0 - b1 + (a1 * a1)
|
|
float c1Half = c1 * 0.5
|
|
float periodRecip = 1.0 / period
|
|
float scaleAdjustment = scaleFactor * 5.0 * periodRecip
|
|
var float result = na
|
|
var float filt = 0.0
|
|
var float filt1 = 0.0
|
|
var float filt2 = 0.0
|
|
var float zeros1 = 0.0
|
|
var float sumSquared = 0.0
|
|
var array<float> filtSquared = array.new_float(period, 0.0)
|
|
var int bufferIndex = 0
|
|
if na(source)
|
|
result
|
|
else
|
|
if na(result)
|
|
result := source
|
|
else
|
|
float zeros = source - result
|
|
filt := c1Half * (zeros + zeros1) + b1 * filt1 - (a1 * a1) * filt2
|
|
float filtSq = filt * filt
|
|
sumSquared := sumSquared + filtSq - array.get(filtSquared, bufferIndex)
|
|
array.set(filtSquared, bufferIndex, filtSq)
|
|
bufferIndex := (bufferIndex + 1) % period
|
|
float rms = math.sqrt(math.max(sumSquared * periodRecip, 1e-10))
|
|
float alpha = math.min(scaleAdjustment * math.abs(filt / rms), 1.0)
|
|
result := alpha * source + (1 - alpha) * result
|
|
zeros1 := zeros
|
|
filt2 := filt1
|
|
filt1 := filt
|
|
result
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_source = input.source(close, "Source")
|
|
i_period = input.int(25, "Period", minval=2)
|
|
i_scale = input.float(0.9, "Scale Factor", minval=0.01, maxval=0.9, step=0.01)
|
|
|
|
// Calculation
|
|
dsma_value = dsma(i_source, i_period, i_scale)
|
|
|
|
// Plot
|
|
plot(dsma_value, "DSMA", color=color.yellow, linewidth=2)
|