mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-01 19:27:44 +00:00
24e86d762a
- Updated BBWN, BBWP, CCV, CV, CVI, EWMA, GKV, HLV, HV, Jvolty, JVOLTYN, MASSI, NATR, RSV, RV, RVI, TR, UI, VOV, VR, YZV indicators with documentation links. - Added documentation links for Aberration, Acceleration Bands, Andrews' Pitchfork, Adaptive Price Zone, ATR Bands, Bollinger Bands, Center of Gravity, Donchian Channels, Decay Min-Max Channel, Detrended Synthetic Price, EACP, EBSW, HOMOD, Jurik Volatility Bands, Keltner Channel, MA Envelope, Min-Max Channel, Price Channel, Regression Channels, Standard Deviation Channel, Stoller Average Range Channel, Super Trend Bands, Ultimate Bands, Ultimate Channel, VWAP Bands, and VWAP with Standard Deviation Bands.
69 lines
2.5 KiB
Plaintext
69 lines
2.5 KiB
Plaintext
// The MIT License (MIT)
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Pearson's Correlation (CORRELATION)", "CORRELATION", overlay=false)
|
|
|
|
//@function Calculates Pearson correlation coefficient using single pass with circular buffer
|
|
//@param src1 series float First series to analyze
|
|
//@param src2 series float Second series to analyze
|
|
//@param len simple int Lookback period for calculation
|
|
//@returns float Pearson correlation coefficient between -1 and 1
|
|
//@optimized for performance using combined covariance and variance calculation
|
|
correlation(series float src1, series float src2, simple int len) =>
|
|
if len <= 0
|
|
runtime.error("Period must be greater than 0")
|
|
var int p = math.max(1, len)
|
|
var array<float> buffer1 = array.new_float(p, na)
|
|
var array<float> buffer2 = array.new_float(p, na)
|
|
var int head = 0, var int count = 0
|
|
var float sum1 = 0.0, var float sum2 = 0.0
|
|
var float sumSq1 = 0.0, var float sumSq2 = 0.0
|
|
var float sumProd = 0.0
|
|
float oldest1 = array.get(buffer1, head)
|
|
float oldest2 = array.get(buffer2, head)
|
|
if not na(oldest1) and not na(oldest2)
|
|
sum1 -= oldest1, sum2 -= oldest2
|
|
sumSq1 -= oldest1 * oldest1, sumSq2 -= oldest2 * oldest2
|
|
sumProd -= oldest1 * oldest2
|
|
count -= 1
|
|
if not na(src1) and not na(src2)
|
|
sum1 += src1, sum2 += src2
|
|
sumSq1 += src1 * src1, sumSq2 += src2 * src2
|
|
sumProd += src1 * src2
|
|
count += 1
|
|
array.set(buffer1, head, src1)
|
|
array.set(buffer2, head, src2)
|
|
else
|
|
array.set(buffer1, head, na)
|
|
array.set(buffer2, head, na)
|
|
head := (head + 1) % p
|
|
if count > 1
|
|
mean1 = sum1 / count, mean2 = sum2 / count
|
|
cov = (sumProd / count) - mean1 * mean2
|
|
var1 = (sumSq1 / count) - mean1 * mean1
|
|
var2 = (sumSq2 / count) - mean2 * mean2
|
|
stddev1 = math.sqrt(math.max(0.0, var1))
|
|
stddev2 = math.sqrt(math.max(0.0, var2))
|
|
denominator = stddev1 * stddev2
|
|
if denominator != 0
|
|
cov / denominator
|
|
else
|
|
na
|
|
else
|
|
na
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_source1 = input.source(close, "Source 1")
|
|
i_source2_ticker = input.symbol("SPY", "Source 2 Ticker (e.g., SPY, AAPL)")
|
|
i_period = input.int(20, "Period", minval=2)
|
|
|
|
i_source2 = request.security(i_source2_ticker, timeframe.period, close, lookahead=barmerge.lookahead_off)
|
|
|
|
// Calculation
|
|
correlation_value = correlation(i_source1, i_source2, i_period)
|
|
|
|
// Plot
|
|
plot(correlation_value, "Correlation", color=color.yellow, linewidth=2)
|