Complete thin Dx-composition wrapper indicators with full test coverage: - PlusDi/MinusDi: Directional Indicator wrappers (DiPlus/DiMinus from Dx) - PlusDm/MinusDm: Directional Movement wrappers (DmPlus/DmMinus from Dx) - Individual validation tests per indicator directory (TALib, Skender, bounds) - Combined unit tests (DiDm.Tests.cs) and validation tests (DiDm.Validation.Tests.cs) - Quantower wrappers + tests for all 4 indicators - PineScript v6 implementations with compensated RMA - Normalized .md documentation for all indicators and categories - 182 tests passing, 0 failures
8.6 KiB
ERI: Elder Ray Index
The job of the indicator is to separate the bulls from the bears. If you can measure their power independently, you can see who is winning before the trend changes.
| Property | Value |
|---|---|
| Category | Oscillator |
| Inputs | Bar series (High, Low, Close) |
| Parameters | period (default 13) |
| Outputs | Dual: Bull Power (primary), Bear Power (property) |
| Output range | Unbounded (centered around 0) |
| Warmup | period bars |
| PineScript | eri.pine |
Key takeaways
- Decomposes buying and selling pressure relative to an EMA trend line: Bull Power = High
-EMA, Bear Power = Low-EMA. - Primary output (
Last) is Bull Power; Bear Power is accessible via theBearPowerproperty. - Uses EMA with exponential warmup compensation for bias-free early values.
- Bull Power positive means buyers pushed price above the trend; Bear Power negative means sellers pulled price below.
- Best used with a trend filter: take longs when EMA is rising and Bear Power is recovering from below zero.
Historical Context
Dr. Alexander Elder introduced Bull Power and Bear Power in Trading for a Living (1993). Elder, a psychiatrist turned trader, designed the indicators to measure the balance of power between buyers and sellers relative to the prevailing trend, represented by an EMA.
The logic is clinical. The highest price of a bar reflects the maximum power of the bulls. The lowest price reflects the maximum power of the bears. Measuring each against the EMA (the consensus value) yields two independent readings of buying and selling pressure. Elder recommended a 13-period EMA, though any reasonable period works.
Elder Ray is typically plotted as two separate histograms below the price chart. The name "Elder Ray" is a visual metaphor: like X-rays revealing bone structure beneath flesh, the indicator reveals the hidden power structure beneath price action.
What It Measures and Why It Matters
Bull Power measures how far above the EMA the bulls managed to push price during the bar. Positive Bull Power means buyers controlled the session. Negative Bull Power means even the high of the bar was below the trend line, a deeply bearish condition.
Bear Power measures how far below the EMA the bears managed to push price. Negative Bear Power is normal in uptrends (the low is below the average). When Bear Power turns positive, it means even the low of the bar was above the trend, an extremely bullish condition.
The two powers are complementary. Strong uptrends show large positive Bull Power and small negative Bear Power (recovering toward zero). Strong downtrends show large negative Bear Power and small positive Bull Power (declining toward zero). Divergence between price and either power reading signals potential trend exhaustion.
Mathematical Foundation
Core Formula
\text{EMA}_t = \alpha \cdot C_t + (1 - \alpha) \cdot \text{EMA}_{t-1}
\text{Bull Power}_t = H_t - \text{EMA}_t
\text{Bear Power}_t = L_t - \text{EMA}_t
where:
C_t= close price at bartH_t= high price at bartL_t= low price at bart\alpha = \frac{2}{N + 1}= EMA smoothing factorN= period (default 13)
Warmup Compensation
During warmup, the EMA uses exponential decay correction:
e_t = e_{t-1} \cdot (1 - \alpha), \quad e_0 = 1
\text{EMA}_t^{\text{compensated}} = \frac{\text{EMA}_t^{\text{raw}}}{1 - e_t}
This eliminates startup bias without requiring a seed SMA.
Parameter Mapping
| Parameter | Symbol | Default | Constraint |
|---|---|---|---|
period |
N |
13 | N \geq 1 |
Warmup Period
W = N
Architecture & Physics
1. EMA with FMA Optimization
The core EMA update uses Math.FusedMultiplyAdd for the standard IIR recursion:
\text{EMA}_t = \text{FMA}(\text{EMA}_{t-1}, \beta, \alpha \cdot C_t) \quad \text{where } \beta = 1 - \alpha
Precomputed _alpha and _decay constants avoid repeated division in the hot path.
2. Multi-Channel NaN Guard
Three independent last-valid substitution channels track Close, High, and Low separately. A NaN high does not contaminate the close or low channels.
3. State Management
A record struct State holds Ema, E (warmup decay), Warmup flag, Index, and three LastValid fields plus BearPower. The _s / _ps local-copy pattern enables bar correction and JIT struct promotion.
4. TBar vs TValue Input
Update(TBar): Full H/L/C decomposition for proper Bull and Bear Power.Update(TValue): Treats input as close with high = low = close. Useful for chaining but produces degenerate results (Bull Power = Bear Power = value-EMA).
5. Edge Cases
| Condition | Behavior |
|---|---|
period < 1 |
ArgumentException with nameof(period) |
NaN / Infinity input |
Per-channel last-valid substitution |
| First bar | EMA = close, Bull Power = high - close, Bear Power = low - close |
| TValue input | Wraps as TBar with OHLC = value |
Interpretation and Signals
Signal Patterns
- Bull divergence: Price makes lower lows, but Bear Power makes higher lows. Selling pressure is weakening despite new price lows. Bullish signal.
- Bear divergence: Price makes higher highs, but Bull Power makes lower highs. Buying pressure is weakening despite new price highs. Bearish signal.
- Long entry (Elder's rules): EMA rising, Bear Power negative but increasing, Bull Power's latest peak exceeds the prior peak.
- Short entry (Elder's rules): EMA declining, Bull Power positive but decreasing, Bear Power's latest trough is lower than the prior trough.
Practical Notes
Elder recommended combining Bull/Bear Power with a 13-period EMA slope as a trend filter. The indicator works best in trending markets where the power decomposition reveals which side is gaining or losing strength. In range-bound conditions, both powers oscillate around zero without clear directional bias.
Related Indicators
- Fi: Force Index, another Elder creation that measures buying/selling pressure using price change times volume.
- Stoch: Also measures position within a range, but uses high-low range rather than EMA deviation.
Validation
| Library | Batch | Streaming | Span | Notes |
|---|---|---|---|---|
| TA-Lib | -- | -- | -- | No direct ERI function |
| Skender | -- | -- | -- | GetElderRay() available but not yet validated |
| Tulip | -- | -- | -- | Not available |
| Ooples | -- | -- | -- | Not available |
Internal consistency validated across streaming, batch, span, and eventing modes.
Performance Profile
Key Optimizations
- FMA in EMA:
Math.FusedMultiplyAdd(ema, decay, alpha * close)replaces separate multiply-and-add. - Local state copy: JIT promotes
var s = _sto registers, avoiding repeated memory loads. - Zero allocation: All state in
record struct; no heap allocations inUpdate. - Aggressive inlining:
[MethodImpl(AggressiveInlining)]onUpdate(TBar).
Operation Count (Streaming Mode)
| Operation | Count per bar |
|---|---|
| FMA | 1 (EMA update) |
| MUL | 1 (alpha * close) |
| SUB | 2 (Bull Power, Bear Power) |
| NaN checks | 3 (high, low, close) |
| Conditional | 1 (warmup check) |
| Total | ~8 ops |
Common Pitfalls
- Primary output is Bull Power only:
Last.Valuereturns Bull Power. Bear Power requires accessing theBearPowerproperty separately. Forgetting this leads to incomplete analysis. - TValue input is degenerate: Passing single values (not TBar) sets H = L = C, making Bull Power = Bear Power = C
-EMA. Use TBar input for proper decomposition. - Warmup affects EMA quality: Early EMA values use exponential warmup compensation, but the first few bars are still adapting. Allow at least
2Nbars for stable readings. - Not bounded: Unlike oscillators clamped to
[0, 100], Bull and Bear Power can take any value. Visual scaling on charts requires attention. - Trend filter is essential: Elder explicitly designed this as a component of a system. Using Bull/Bear Power without checking EMA direction defeats the design intent.
- Bear Power is normally negative: In healthy uptrends, Bear Power is negative (low is below EMA). It becomes concerning only when it turns increasingly negative during what should be an uptrend.
References
- Elder, A. Trading for a Living. John Wiley & Sons, 1993. Chapter on Elder-Ray.
- Elder, A. Come Into My Trading Room. John Wiley & Sons, 2002.
- Achelis, S. B. Technical Analysis from A to Z. McGraw-Hill, 2000.