mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-09 22:40:57 +00:00
86fe32a682
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat> Co-authored-by: Warp <agent@warp.dev>
45 lines
2.3 KiB
Plaintext
45 lines
2.3 KiB
Plaintext
// The MIT License (MIT)
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Garman-Klass Volatility (GKV)", "GKV", overlay=false)
|
|
|
|
//@function Calculates Garman-Klass Volatility.
|
|
//@param length The period length for smoothing the Garman-Klass estimator.
|
|
//@param annualize Boolean to indicate if the volatility should be annualized. Default is true.
|
|
//@param annualPeriods Number of periods in a year for annualization. Default is 252 for daily data.
|
|
//@returns float The Garman-Klass Volatility value.
|
|
//@optimized for performance and dirty data
|
|
gkv(simple int length, simple bool annualize = true, simple int annualPeriods = 252) =>
|
|
if length <= 0
|
|
runtime.error("Length must be greater than 0")
|
|
if annualize and annualPeriods <= 0
|
|
runtime.error("Annual periods must be greater than 0 if annualizing")
|
|
float lnH = math.log(high), float lnL = math.log(low), float lnO = math.log(open), float lnC = math.log(close)
|
|
float C_2LN2_1 = 0.3862941611 // 2 * math.log(2) - 1
|
|
float term1 = 0.5 * math.pow(lnH - lnL, 2)
|
|
float term2 = C_2LN2_1 * math.pow(lnC - lnO, 2)
|
|
float gkEstimator = term1 - term2
|
|
var float raw_rma_gk = 0.0, var float e_rma = 1.0
|
|
float rma_alpha = 1.0 / float(length)
|
|
if not na(gkEstimator)
|
|
raw_rma_gk := na(raw_rma_gk[1]) ? gkEstimator : (nz(raw_rma_gk[1], gkEstimator) * (length - 1) + gkEstimator) / length
|
|
e_rma := na(e_rma[1]) ? (1.0 - rma_alpha) : (1.0 - rma_alpha) * nz(e_rma[1], 1.0)
|
|
float EPSILON = 1e-10
|
|
float corrected_rma_gk = e_rma > EPSILON and not na(raw_rma_gk) ? raw_rma_gk / (1.0 - e_rma) : raw_rma_gk
|
|
float smoothedGkEstimator = nz(corrected_rma_gk, gkEstimator)
|
|
float volatility = smoothedGkEstimator < 0 ? na : math.sqrt(smoothedGkEstimator)
|
|
annualize and not na(volatility) ? volatility * math.sqrt(float(annualPeriods)) : volatility
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_length = input.int(20, "Length", minval=1, tooltip="Period for smoothing the Garman-Klass estimator")
|
|
i_annualize = input.bool(true, "Annualize Volatility", tooltip="Annualize the volatility output")
|
|
i_annualPeriods = input.int(252, "Annual Periods", minval=1, tooltip="Number of periods in a year for annualization (e.g., 252 for daily, 52 for weekly)")
|
|
|
|
// Calculation
|
|
gkvValue = gkv(i_length, i_annualize, i_annualPeriods)
|
|
|
|
// Plot
|
|
plot(gkvValue, "GKV", color=color.yellow, linewidth=2)
|