Parabolic SAR

Haiyue
11min

Parabolic SAR (Parabolic Stop and Reverse)

Indicator Overview
  • Category: Trend — Overlay Indicator
  • Default Parameters: step=0.02, max=0.2
  • Output: A series of dots (above or below price)
  • Applicable Markets: Stocks, Futures, Forex, Cryptocurrencies

I. What is Parabolic SAR

The Parabolic Stop and Reverse indicator (commonly known as Parabolic SAR or PSAR) was introduced by American technical analysis pioneer J. Welles Wilder Jr. in 1978 in his classic book New Concepts in Technical Trading Systems. The same book also introduced RSI, ATR, and ADX, all of which remain widely used today.

The word “Parabolic” refers to the arc-shaped trajectory the indicator traces on a chart — as a trend continues, the SAR dots accelerate toward the price, forming a parabola-like curve. When the price finally touches the SAR dot, the indicator reverses direction (Stop and Reverse), signaling a potential trend reversal.

Core Design Philosophy

Parabolic SAR is essentially a dynamic trailing stop system:

  1. In an uptrend, SAR dots sit below the price, gradually moving up as a stop-loss level
  2. In a downtrend, SAR dots sit above the price, gradually moving down as a stop-loss level
  3. The Acceleration Factor (AF) causes SAR to approach the price at an increasing rate, ensuring profits are not given back excessively
Naming Explained
  • Stop: The SAR dot itself serves as the suggested stop-loss level
  • Reverse: When price crosses the SAR, the system considers the trend reversed

II. Mathematical Principles and Calculation

Core Variables

  • SARtSAR_t: The SAR value at period tt
  • AFAF: Acceleration Factor
  • EPEP: Extreme Point — the highest high in an uptrend, or the lowest low in a downtrend

Recursive Formula

SARt=SARt1+AF×(EPSARt1)SAR_{t} = SAR_{t-1} + AF \times (EP - SAR_{t-1})

Acceleration Factor Rules

  1. When a trend begins, AFAF is initialized to stepstep (default 0.02)
  2. Each time a new extreme point appears (new high in uptrend / new low in downtrend), AFAF increases by stepstep
  3. AFAF has a maximum value of maxmax (default 0.2)

AF=min(AFprev+step, max)AF = \min(AF_{prev} + step, \ max)

Reversal Conditions

In an uptrend: If LowtSARtLow_t \leq SAR_t, the trend reverses to bearish. In a downtrend: If HightSARtHigh_t \geq SAR_t, the trend reverses to bullish.

Reset on Reversal

When a reversal occurs:

  1. The new SARSAR is set to the EPEP from the previous trend
  2. AFAF is reset to stepstep
  3. EPEP is reset to the current price extreme

Constraint Rules

In an uptrend, SARtSAR_t must not exceed the lowest lows of the previous two periods:

SARt=min(SARt, Lowt1, Lowt2)SAR_t = \min(SAR_t, \ Low_{t-1}, \ Low_{t-2})

In a downtrend, SARtSAR_t must not fall below the highest highs of the previous two periods:

SARt=max(SARt, Hight1, Hight2)SAR_t = \max(SAR_t, \ High_{t-1}, \ High_{t-2})

Calculation Steps

  1. Determine the initial trend direction (using the first few periods’ price movement)
  2. Set the initial SARSAR, EPEP, and AFAF
  3. For each new bar, update SAR using the recursive formula
  4. Check whether the reversal condition is met; if so, reverse and reset parameters
  5. Apply constraint rules to ensure SAR does not cross recent prices

III. Python Implementation

import numpy as np
import pandas as pd

def parabolic_sar(df: pd.DataFrame,
                  step: float = 0.02,
                  max_af: float = 0.2) -> pd.DataFrame:
    """
    Calculate Parabolic SAR.

    Parameters
    ----------
    df : DataFrame, must contain 'high', 'low', 'close' columns
    step : Acceleration factor step size, default 0.02
    max_af : Maximum acceleration factor, default 0.2

    Returns
    ----------
    DataFrame with 'psar', 'psar_up', 'psar_down', 'trend' columns
    trend: 1 indicates uptrend, -1 indicates downtrend
    """
    high = df['high'].values
    low = df['low'].values
    close = df['close'].values
    n = len(df)

    psar = np.full(n, np.nan)
    trend = np.zeros(n, dtype=int)
    af = np.full(n, np.nan)
    ep = np.full(n, np.nan)

    # ---------- Initialization (use first two periods to determine trend) ----------
    if close[1] > close[0]:
        trend[1] = 1          # Uptrend
        psar[1] = low[0]      # Initial SAR = previous period's low
        ep[1] = high[1]       # Initial EP = current period's high
    else:
        trend[1] = -1         # Downtrend
        psar[1] = high[0]     # Initial SAR = previous period's high
        ep[1] = low[1]        # Initial EP = current period's low
    af[1] = step

    # ---------- Recursive calculation ----------
    for i in range(2, n):
        prev_trend = trend[i - 1]
        prev_sar = psar[i - 1]
        prev_af = af[i - 1]
        prev_ep = ep[i - 1]

        # Calculate new SAR
        new_sar = prev_sar + prev_af * (prev_ep - prev_sar)

        # Apply constraints
        if prev_trend == 1:
            new_sar = min(new_sar, low[i - 1], low[i - 2])
        else:
            new_sar = max(new_sar, high[i - 1], high[i - 2])

        # Check for reversal
        reverse = False
        if prev_trend == 1 and low[i] <= new_sar:
            reverse = True
            new_trend = -1
            new_sar = prev_ep          # On reversal, SAR = previous trend's EP
            new_ep = low[i]
            new_af = step
        elif prev_trend == -1 and high[i] >= new_sar:
            reverse = True
            new_trend = 1
            new_sar = prev_ep
            new_ep = high[i]
            new_af = step
        else:
            new_trend = prev_trend
            # Update EP and AF
            if new_trend == 1:
                if high[i] > prev_ep:
                    new_ep = high[i]
                    new_af = min(prev_af + step, max_af)
                else:
                    new_ep = prev_ep
                    new_af = prev_af
            else:
                if low[i] < prev_ep:
                    new_ep = low[i]
                    new_af = min(prev_af + step, max_af)
                else:
                    new_ep = prev_ep
                    new_af = prev_af

        psar[i] = new_sar
        trend[i] = new_trend
        af[i] = new_af
        ep[i] = new_ep

    # Separate uptrend/downtrend SAR for charting
    psar_up = np.where(trend == 1, psar, np.nan)
    psar_down = np.where(trend == -1, psar, np.nan)

    result = pd.DataFrame({
        'psar': psar,
        'psar_up': psar_up,
        'psar_down': psar_down,
        'trend': trend,
        'af': af,
        'ep': ep
    }, index=df.index)

    return result


# ========== Usage Example ==========
if __name__ == "__main__":
    np.random.seed(42)
    n = 100
    dates = pd.date_range('2024-01-01', periods=n, freq='B')

    # Simulate OHLCV data
    price = 50 + np.cumsum(np.random.randn(n) * 0.6)
    df = pd.DataFrame({
        'open':  price + np.random.uniform(-0.3, 0.3, n),
        'high':  price + np.abs(np.random.randn(n)) * 1.0,
        'low':   price - np.abs(np.random.randn(n)) * 1.0,
        'close': price + np.random.uniform(-0.2, 0.2, n),
        'volume': np.random.randint(1000, 5000, n)
    }, index=dates)

    sar = parabolic_sar(df, step=0.02, max_af=0.2)
    merged = df.join(sar)

    print("SAR data for the last 15 periods:")
    print(merged[['close', 'psar', 'trend', 'af', 'ep']].tail(15).to_string())

    # Count reversals
    reversals = (merged['trend'].diff().abs() > 0).sum()
    print(f"\nNumber of trend reversals: {reversals}")

IV. Problems the Indicator Solves

1. Dynamic Stop-Loss

The most essential function of Parabolic SAR is providing an automatic trailing stop-loss for open positions. As the trend progresses, the stop-loss level continuously moves in the favorable direction, protecting existing profits while giving price enough room to fluctuate.

2. Trend Direction Identification

SAR PositionTrend Assessment
SAR below price (dots below bars)Uptrend
SAR above price (dots above bars)Downtrend
SAR reversalTrend reversal signal

3. Entry/Exit Timing

  • Buy signal: SAR flips from above price to below (bearish to bullish)
  • Sell signal: SAR flips from below price to above (bullish to bearish)

4. Trend Acceleration Confirmation

By observing the AF (Acceleration Factor) value, you can gauge trend strength:

  • AFAF near its initial value of 0.02 —> Trend has just started
  • AFAF reaching the 0.2 maximum —> Trend has persisted for a long time and may be nearing exhaustion
Important Reminder

Parabolic SAR is an “always-in-the-market” system, meaning it always assumes a long or short position is held. In ranging markets, this characteristic leads to frequent false reversal signals, causing consecutive losses.

V. Advantages, Disadvantages, and Use Cases

Advantages

  1. Simple to use: Signals are clear — SAR above means short, SAR below means long
  2. Built-in stop-loss: Provides a clear stop-loss level at every period, enforcing trading discipline
  3. Time-sensitive: AF increases over time, embodying the principle that “the longer a trend persists, the tighter the stop should be”
  4. Visually intuitive: Small dots on the chart are easy to read at a glance

Disadvantages

  1. Devastating in choppy markets: Repeated reversals in sideways ranges produce many false signals
  2. Cannot quantify trend strength: Only provides direction, unlike ADX which measures trend intensity
  3. Parameter sensitive: A step that is too large makes it overly sensitive; too small makes it sluggish
  4. Poor with gaps: Large price gaps can cause SAR to be too far from the current price

Use Cases

ScenarioSuitabilityNotes
Strong trending marketsHighAccurate signals with tight trailing stops
Exit management for trend tradesHighNaturally suited as a trailing stop
Narrow range consolidationLowFrequent false reversals, cumulative losses
News-driven market eventsLowGaps can cause SAR to malfunction

Comparison with Similar Indicators

DimensionParabolic SARSuperTrendMoving Average
Stop-loss functionBuilt-inBuilt-inRequires additional design
Signal frequencyRelatively highMediumRelatively low
Performance in ranging marketsPoorMediumMedium
Parameter complexity221
Acceleration mechanismYesNoNo
Best Practices
  • Combine with ADX filtering: Use SAR signals when ADX > 25; ignore reversal signals when ADX < 20
  • Adjust parameters: For highly volatile instruments, reduce the step (e.g., 0.01) to minimize false signals
  • Use only as an exit tool: Use other indicators for entry; let SAR handle trailing stops exclusively
  • Multi-timeframe confirmation: Confirm trend direction on higher timeframes, then use SAR on lower timeframes for entry