Files

49 lines
1.8 KiB
Plaintext

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Harmonic Mean (HARMEAN)", "HARMEAN", overlay=false, precision=6)
//@function Calculates the Harmonic Mean of a series over a lookback period.
//@param src series float Input data series (must contain positive values).
//@param len simple int Lookback period (must be > 0).
//@returns series float The Harmonic Mean, or na if data is not suitable (e.g., non-positive values, insufficient data).
//@optimized for performance and dirty data
harmean(series float src, simple int len) =>
if len <= 0
runtime.error("Period must be greater than 0. Found: " + str.tostring(len))
var float sum_reciprocal_src = 0.0
var int n_valid = 0
var float[] src_buffer = array.new_float(len, na)
var int current_index = 0
float current_val = src
bool current_val_is_valid = false
if not na(current_val) and current_val > 0
current_val_is_valid := true
float old_val_from_buffer = array.get(src_buffer, current_index)
if not na(old_val_from_buffer) and old_val_from_buffer > 0
sum_reciprocal_src -= (1.0 / old_val_from_buffer)
n_valid -= 1
if current_val_is_valid
sum_reciprocal_src += (1.0 / current_val)
n_valid += 1
array.set(src_buffer, current_index, current_val)
else
array.set(src_buffer, current_index, na)
current_index := (current_index + 1) % len
if n_valid > 0 and sum_reciprocal_src > 1e-10
n_valid / sum_reciprocal_src
else
float(na)
// ---------- Main loop ----------
// Inputs
i_source = input.source(close, title="Source (must be positive values)")
i_length = input.int(14, title="Lookback Period", minval=1)
// Calculation
harmean_value = harmean(i_source, i_length)
// Plot
plot(harmean_value, "HARMEAN", color=color.yellow, linewidth=2)