mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-04 12:07:44 +00:00
78 lines
2.3 KiB
Plaintext
78 lines
2.3 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Double Weighted Moving Average (DWMA)", "DWMA", overlay=true)
|
|
|
|
//@function Calculates DWMA using double weighted smoothing with inline O(1) WMA
|
|
//@param source Series to calculate DWMA from
|
|
//@param period Lookback period for both smoothing passes
|
|
//@returns DWMA value, calculates from first bar using available data
|
|
//@optimized Uses two inline O(1) WMA calculations for combined O(1) complexity per bar
|
|
dwma(series float source, simple int period) =>
|
|
if period <= 0
|
|
runtime.error("Period must be greater than 0")
|
|
|
|
var array<float> buffer1 = array.new_float(period, na)
|
|
var int head1 = 0
|
|
var float sum1 = 0.0
|
|
var float weighted_sum1 = 0.0
|
|
var int count1 = 0
|
|
var float norm1 = 0.0
|
|
|
|
var array<float> buffer2 = array.new_float(period, na)
|
|
var int head2 = 0
|
|
var float sum2 = 0.0
|
|
var float weighted_sum2 = 0.0
|
|
var int count2 = 0
|
|
var float norm2 = 0.0
|
|
|
|
float oldest1 = array.get(buffer1, head1)
|
|
float current1 = nz(source)
|
|
|
|
if not na(oldest1)
|
|
float old_sum1 = sum1
|
|
sum1 -= oldest1
|
|
sum1 += current1
|
|
weighted_sum1 := weighted_sum1 - old_sum1 + (period * current1)
|
|
else
|
|
count1 += 1
|
|
sum1 += current1
|
|
weighted_sum1 := weighted_sum1 + (count1 * current1)
|
|
norm1 := count1 * (count1 + 1) * 0.5
|
|
|
|
array.set(buffer1, head1, current1)
|
|
head1 := (head1 + 1) % period
|
|
|
|
float wma1 = weighted_sum1 / norm1
|
|
|
|
float oldest2 = array.get(buffer2, head2)
|
|
float current2 = nz(wma1)
|
|
|
|
if not na(oldest2)
|
|
float old_sum2 = sum2
|
|
sum2 -= oldest2
|
|
sum2 += current2
|
|
weighted_sum2 := weighted_sum2 - old_sum2 + (period * current2)
|
|
else
|
|
count2 += 1
|
|
sum2 += current2
|
|
weighted_sum2 := weighted_sum2 + (count2 * current2)
|
|
norm2 := count2 * (count2 + 1) * 0.5
|
|
|
|
array.set(buffer2, head2, current2)
|
|
head2 := (head2 + 1) % period
|
|
|
|
weighted_sum2 / norm2
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_period = input.int(10, "Period", minval=1)
|
|
i_source = input.source(close, "Source")
|
|
|
|
// Calculation
|
|
dwma_value = dwma(i_source, i_period)
|
|
|
|
// Plot
|
|
plot(dwma_value, "DWMA", color=color.yellow, linewidth=2)
|