UltimateOscillator — Ultimate Oscillator
תוכן זה אינו זמין עדיין בשפה שלך.
Buying pressure measured against true range, blended across three horizons (7/14/28, weighted 4/2/1) so a single lookback cannot dominate. Reads 0–100; divergences at extremes are the classic signal.
Signature
UltimateOscillator(fast, mid, slow, on=<source>)| Argument | Type | Required | Notes |
|---|---|---|---|
fast |
int Param or literal | Yes | Short horizon. Convention 7. Bounds 1–100. |
mid |
int Param or literal | Yes | Middle horizon. Convention 14. Bounds 1–200. |
slow |
int Param or literal | Yes | Long horizon; also the buffer size. Convention 28. Bounds 1–400. |
on= |
symbol | No | Source symbol. Defaults to the trade symbol. Reads high, low, close. |
Formula
$$ BP = C - \min(L, C_{prev}), \quad TR = \max(H, C_{prev}) - \min(L, C_{prev}) $$ $$ \text{UO} = 100 \cdot \frac{4,\frac{\sum BP_7}{\sum TR_7} + 2,\frac{\sum BP_{14}}{\sum TR_{14}} + \frac{\sum BP_{28}}{\sum TR_{28}}}{7} $$
Warmup
slow + 1 bars; 50 (neutral) until then, and 50 on a fully flat stretch where a true-range sum
is zero.
Reading the value
uo.valueuo < 30uo.crossed_above(50)Example
class UoOversold(Strategy): """Buy an Ultimate Oscillator dip under 30, exit above 50.""" trade = Symbol() sizing = FixedCapital()
def execute(self): uo = UltimateOscillator(7, 14, 28, on=self.trade) if uo.value < 30 and self.trade.is_flat: self.buy(self.trade, reason=f"UO {uo.value:.0f}") if uo.value > 50 and self.trade.is_long: self.sell(self.trade, self.trade.position, reason="UO recovered")Notes
- Larry Williams (1976). The weights 4/2/1 and horizons n, 2n, 4n are his.
- Proven by an assert-via-trade run on SPY daily (matched a strategy-side BP/TR reference to 0.01 on every bar, including the sub-window sums; zero alarm trades; canary fired on this assertion).
- The three horizons scale from
slow; keepfast < mid < slow— the code does not reorder them for you.