Andean Oscillator — Indie Version
Table of Contents
Andean Oscillator — Indie Version
This is a refined version of the Andean Oscillator by © alexgrover, designed specifically for the Indie platform.
The Andean Oscillator uses an online algorithm to analyze price trends through exponential envelope smoothing. This version adds structural and visual improvements for better clarity and usability.
Features:
- Exponential Smoothing Envelopes: Captures trend dynamics by combining high-res envelope tracking of price and squared price.
- Bullish/Bearish Variability Analysis: Calculates standard deviation-like metrics for upward and downward price components.
- Dual Histogram: Market condition is shown via color-coded histogram bars — green for bullish, red for bearish — as a symmetrical “waveform”.
- Compact: Histogram amplitude is scaled and centered to reduce visual distortion and preserve chart readability on lower-volatility assets.
- Clear Signal Line: EMA-based signal on max volatility metric to aid in crossover strategies.
- Indie v5 compatible: Fully compliant with latest Indie scripting, uses MutSeriesF, plot.columns and parameterized config.
Good for momentum and trend following strategies, this version of the Andean Oscillator has a cleaner, more usable visual structure while keeping the math of the original.
Indie script V5 source code:
# This work is licensed under the Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
# https://creativecommons.org/licenses/by-nc-sa/4.0/
# Inspired by the original concept by © alexgrover
# Indie version rewritten and enhanced by Pavel Medd
# Education purposes
# indie:lang_version = 5
from indie import indicator, param, plot, color, MutSeriesF
from indie.algorithms import Ema
from math import sqrt
# Indicator declaration and parameters
@indicator('Dynamic Andean Oscillator')
@param.int('length', default=50) # Base length for smoothing
@param.int('sig_length', default=9, title='Signal Length') # EMA period for signal line
# Plotting configuration
@plot.line('bull_line', title='Bullish Component', color=color.GREEN, line_width=2)
@plot.line('bear_line', title='Bearish Component', color=color.RED, line_width=2)
@plot.line(title='Signal', color=color.YELLOW, line_width=2)
@plot.columns('bull_hist', title='Bull Histogram', color=color.rgba(204, 255, 0, 0.3), base_value=0.0)
@plot.columns('bear_hist', title='Bear Histogram', color=color.rgba(246, 45, 174, 0.3), base_value=0.0)
def Main(self, length, sig_length):
# Core smoothing coefficient for exponential update
alpha = 2 / (length + 1)
# Mutable time series to retain recursive envelope values
up1 = MutSeriesF.new(self.close[0]) # Exponential smoothing of max(close, open)
up2 = MutSeriesF.new(self.close[0] * self.close[0]) # Squared smoothing (for variance-like calc)
dn1 = MutSeriesF.new(self.close[0])
dn2 = MutSeriesF.new(self.close[0] * self.close[0])
# Previous values (time index -1)
prev_up1 = up1[1]
prev_up2 = up2[1]
prev_dn1 = dn1[1]
prev_dn2 = dn2[1]
# Recursive exponential envelope update (upper band)
up1[0] = max(self.close[0], self.open[0], prev_up1 - (prev_up1 - self.close[0]) * alpha)
up2[0] = max(self.close[0]**2, self.open[0]**2, prev_up2 - (prev_up2 - self.close[0]**2) * alpha)
# Recursive exponential envelope update (lower band)
dn1[0] = min(self.close[0], self.open[0], prev_dn1 + (self.close[0] - prev_dn1) * alpha)
dn2[0] = min(self.close[0]**2, self.open[0]**2, prev_dn2 + (self.close[0]**2 - prev_dn2) * alpha)
# Deviation from the envelope mean (bull/bear volatility proxy)
bull_var = dn2[0] - dn1[0] * dn1[0]
bear_var = up2[0] - up1[0] * up1[0]
# Square root of variance, safely clamped to avoid math domain errors
bull = sqrt(bull_var) if bull_var > 0 else 0.0
bear = sqrt(bear_var) if bear_var > 0 else 0.0
# Signal line: EMA of the max component (trend highlight)
signal_input = MutSeriesF.new(max(bull, bear))
signal = Ema.new(signal_input, sig_length)[0]
# Amplitude: difference in bull/bear strengths
amp = abs(bull - bear)
# Colored histogram: green if bull > bear, red otherwise
hist_green = amp if bull > bear else 0.0
hist_red = amp if bear > bull else 0.0
return bull, bear, signal, hist_green, hist_red