OGT Owl Group Trading by Dr. Ken Long
Home About Learn The Loop Courses Essays Store Partners FAQ Today's Briefing
Indicator Code · Owl Group Trading

RL10 - Regression Line

The fitted endpoint of a 10-bar linear regression - a smoothed read of true price that filters candle noise.

Concept: what RL10 means →

RL10 fits a least-squares straight line to the last 10 bars and reads its value at the most recent bar (the regression endpoint). It expresses the underlying price path with the noise of individual candle wicks removed.

Traders read its slope to confirm a trend is intact, and watch for it to peak and roll over as an exhaustion signal that a move is complete. The 10-bar window is the default; a longer window (RL30) gives a slower, smoother line.

Verified. Python and JavaScript implementations agree to 7.11e-14 on a 60-bar reference price series (canonical Python (np.correlate) vs JavaScript (loop) - float64 round-off only).

Pythonpermalink →

import numpy as np

def rl10(values, n=10):
    """RL10 - the fitted value of an n-bar linear regression at the most
    recent bar (the regression-line 'endpoint'). Canonical Owl Group Trading
    implementation; vectorized with np.correlate for O(N) speed.

    Returns an array the same length as `values`; the first n-1 entries are
    NaN (not enough lookback). n defaults to 10, hence 'RL10'.
    """
    values = np.asarray(values, dtype=float)
    out = np.full(len(values), np.nan)
    if n <= 0 or len(values) < n:
        return out
    # Fixed regression weights for x = [0, 1, ..., n-1] so the endpoint value
    # equals sum(w_i * y_i) for each sliding window.
    x = np.arange(n)
    x_mean = (n - 1) / 2.0
    x_diff = x - x_mean
    denom = float(np.sum(x_diff ** 2))
    if denom == 0:
        return out
    w = 1.0 / n + x_mean * x_diff / denom
    out[n - 1:] = np.correlate(values, w, mode="valid")
    return out

JavaScriptpermalink →

// RL10 - the fitted value of an n-bar linear regression at the most recent
// bar (the regression-line 'endpoint'). Canonical Owl Group Trading
// implementation. Returns an array the same length as `closes`; the first
// n-1 entries are null (not enough lookback). n defaults to 10, hence 'RL10'.
export function rl10(closes, n = 10) {
  const len = closes.length;
  const result = new Array(len).fill(null);
  if (n <= 0 || len < n) return result;
  // Fixed sums for x = [0, 1, ..., n-1]
  const sumX = (n * (n - 1)) / 2;
  const sumX2 = (n * (n - 1) * (2 * n - 1)) / 6;
  const denom = n * sumX2 - sumX * sumX;
  if (denom === 0) return result;
  for (let end = n; end <= len; end++) {
    const start = end - n;
    let sumY = 0, sumXY = 0, hasNaN = false;
    for (let j = 0; j < n; j++) {
      const v = closes[start + j];
      if (v == null || Number.isNaN(v)) { hasNaN = true; break; }
      sumY += v;
      sumXY += j * v;
    }
    if (hasNaN) continue;
    // slope + intercept of the least-squares line, evaluated at x = n-1
    const slope = (n * sumXY - sumX * sumY) / denom;
    const intercept = (sumY - slope * sumX) / n;
    result[end - 1] = slope * (n - 1) + intercept;
  }
  return result;
}