Awesome Oscillator in Python — Coding It from Scratch (pandas)

The 5/34 median-price difference and the green/red bars

Awesome Oscillator computed in Python
Awesome Oscillator computed in Python

The Awesome Oscillator is a two-line indicator in disguise — a difference of two simple moving averages of the bar midpoint, as the explainer covered. Here it is in pandas, including the momentum bar colours and a saucer signal.

What you’ll need

  • Python 3.9+, pandas
  • high, low series.

From scratch

import pandas as pd


def awesome_oscillator(high, low, fast: int = 5, slow: int = 34):
    median = (high + low) / 2
    return (median.rolling(fast).mean()
            - median.rolling(slow).mean()).rename("ao")

That’s the whole indicator: median price (H+L)/2, then the 5-period SMA minus the 34-period SMA. No EMA, no signal line, no close — the three things that make it an AO rather than a MACD.

Bar colours and signals

The classic display colours each bar by whether AO rose or fell:

ao = awesome_oscillator(df["high"], df["low"])
rising = ao > ao.shift(1)          # green when momentum increased, else red

# Zero-line cross.
df["ao_bull"] = (ao > 0) & (ao.shift(1) <= 0)

# Bull saucer: AO above zero, two falling bars then a rising bar.
above = ao > 0
two_down = (ao.shift(1) < ao.shift(2)) & (ao.shift(2) < ao.shift(3))
df["ao_saucer"] = above & two_down & (ao > ao.shift(1))

ao_bull and ao_saucer are concrete signals to test in AlgoGen — the saucer especially benefits from a backtest, since it fires often.

Gotchas

  • Median price, not close. (high + low) / 2. Using close turns it into something closer to a plain MACD variant.
  • SMA, not EMA. The AO uses simple moving averages; swapping in EMAs changes the line.
  • Fixed 5/34. These are the indicator’s identity; changing them makes it a generic SMA-difference oscillator, not “the AO.”

Bonus: the Accelerator Oscillator

Williams’ companion indicator is one more line — the AO minus a 5-SMA of itself:

def accelerator(high, low):
    ao = awesome_oscillator(high, low)
    return (ao - ao.rolling(5).mean()).rename("ac")

The AC measures the acceleration of momentum (the change in the AO), coloured the same green/red way. Rising AC above zero is Williams’ strongest “go” condition.

The lazy one-liner

import pandas_ta as ta
df["ao"] = ta.ao(df["high"], df["low"])   # 5/34 by default

Same indicator elsewhere: MQL5, Pine Script, EasyLanguage, NinjaScript.


This post is educational, not financial advice. Indicators describe the past; they don’t predict the future. Backtest anything before you risk real money on it.

Sources and further reading

  1. Windowing operations (pandas documentation)

Historical research from the Algogen archive. Not investment advice.

Blog

Have a strategy idea?

Describe it in plain English, preview where your rules fire, then decide whether the evidence is worth a backtest.

Keep me postedHow it works