ParabolicSARExtended

Incremental, causal technical analysis documentation

Summary

ParabolicSARExtended is a TA-Lib SAREXT-style Parabolic Stop and Reverse with independent long/short acceleration-factor (AF) chains, an optional fixed starting SAR, and an additive price-unit offset on reversal. Each update returns the current positive SAR level.

Update API

import rtta

ind = rtta.ParabolicSARExtended(
    start=0.0,
    offset_on_reverse=0.0,
    af_init_long=0.02,
    af_long=0.02,
    af_max_long=0.2,
    af_init_short=0.02,
    af_short=0.02,
    af_max_short=0.2,
)
sar = ind.update(high, low)

If start != 0, that value seeds SAR; otherwise the first bars use high/low extremes. Long and short sides have separate AF initial values, increments, and caps.

Theory Of Operation

Wilder's Parabolic SAR trails price with a stop that accelerates toward the trend's extreme point. The extended form lets long and short trends accelerate at different rates. At the end of each bar RTTA prepares the next unconstrained candidate

\[q_{t+1}=SAR_t+AF_t(EP_t-SAR_t).\]

That next candidate is range-clamped using the current and previous bars. On the following update, the new low or high is tested against the already prepared \(q_t\) before a new clamp is applied. A crossing reverses the trend. Reversing this order would make the crossing condition unreachable.

Recurrence

Bar 0: store \(H_0,L_0\); return start when nonzero, otherwise return \(L_0\).

Bar 1: let \(u=H_1-H_0\) and \(d=L_0-L_1\). The initial direction is short only when \(d>0\) and \(d>u\); ties default to long. Unless start was supplied, initialize \(q_1=L_0\) when rising or \(q_1=H_0\) when falling. Initialize EP and AF for that side, then process bar 1 with the recurrence below.

When rising, if \(L_t\le q_t\), reverse to short and emit

\[SAR_t=\max(EP_{t-1},H_{t-1},H_t)+offset, \quad EP_t=L_t, \quad AF_t=af\_init\_short.\]

Prepare the next short-side candidate and bound it below:

\[q_{t+1}=\max\!\left( SAR_t+AF_t(EP_t-SAR_t),\,H_{t-1},\,H_t \right).\]

If no reversal occurs, emit \(SAR_t=q_t\). When \(H_t\) is a new extreme, update EP and increase the long AF up to af_max_long, then prepare

\[q_{t+1}=\min\!\left( SAR_t+AF_t(EP_t-SAR_t),\,L_{t-1},\,L_t \right).\]

When falling, if \(H_t\ge q_t\), reverse to long and emit

\[SAR_t=\min(EP_{t-1},L_{t-1},L_t)-offset, \quad EP_t=H_t, \quad AF_t=af\_init\_long.\]

Prepare the next long-side candidate and bound it above:

\[q_{t+1}=\min\!\left( SAR_t+AF_t(EP_t-SAR_t),\,L_{t-1},\,L_t \right).\]

If no reversal occurs, emit \(SAR_t=q_t\). When \(L_t\) is a new extreme, update EP and increase the short AF up to af_max_short, then prepare

\[q_{t+1}=\max\!\left( SAR_t+AF_t(EP_t-SAR_t),\,H_{t-1},\,H_t \right).\]

Implementation Notes

The recurrence is implemented in src/rtta/indicator.cpp in class ParabolicSARExtended. offset_on_reverse is additive, not a percentage, and the returned scalar remains positive on both sides.

Reference