Skip to content
Meridian / OpenLL
Open source Independent implementation Daily OHLC

OpenLL

A transparent EMA and ATR market-regime indicator. Every parameter, boundary, and implementation branch is published below.

Relationship statement: OpenLL is a free, independently developed, open-source alternative to the Larsson Line indicator. It is designed to be practically identical in calculation behavior. It is not created by, affiliated with, or endorsed by CTO Larsson.

Exact calculation

Three states from one volatility-aware band.

OpenLL compares a 30-period fast EMA with a 60-period slow EMA. A 60-period ATR creates a buffer around the slow EMA so small crossovers remain neutral.

01 / INPUT

Chronological daily OHLC bars

Open, high, low, and close are required. At least 60 bars must be supplied. Rows with undefined calculated values are removed after the indicators run.

02 / EMA

Fast 30, slow 60

gap = EMA(close, 30) - EMA(close, 60)

03 / RANGE

True Range and ATR 60

TR = max(|high - low|, |high - previous close|, |low - previous close|)
threshold = ATR(TR, 60) * 0.3

04 / STATE

Strict boundaries

BULL when gap > threshold

BEAR when gap < -threshold

NEUTRAL in every other case

Equality at either boundary is NEUTRAL. A flip occurs when the integer state changes between consecutive calculated bars.

Runtime conventions

The branch behavior is part of the method.

Meridian calls pandas_ta when that optional package imports. Without it, the source uses pandas directly.

EMA fallback
close.ewm(span=period, adjust=False).mean()
ATR fallback
A rolling arithmetic mean of True Range over 60 bars, with 60 observations required.
Reproduction rule
Use the same daily OHLC source, completed-bar policy, dependency environment, and chronological warm-up window.
openll-reference.py MIT
result["ema_fast"] = _ema(close, 30)
result["ema_slow"] = _ema(close, 60)
result["atr"] = _atr(high, low, close, 60)

result["ema_gap"] = result["ema_fast"] - result["ema_slow"]
result["threshold"] = result["atr"] * 0.3
result["upper_boundary"] = result["ema_slow"] + result["threshold"]
result["lower_boundary"] = result["ema_slow"] - result["threshold"]

result["regime_id"] = 0
result.loc[result["ema_gap"] > result["threshold"], "regime_id"] = 1
result.loc[result["ema_gap"] < -result["threshold"], "regime_id"] = -1

For software agents

The same method is machine-readable.

Meridian's public About endpoint returns the OpenLL parameters, formulas, strict comparison semantics, implementation source, portfolio methodology, and evidence limits as structured JSON.