Skip to content

Commit

Permalink
[GH-154] Add Elder-Ray Index (#155)
Browse files Browse the repository at this point in the history
The Elder-Ray Index contains the bull and the bear power.
Both are calculated based on the EMA of the close price.

The default window is 13.

Formular:
* Bulls Power = High - EMA
* Bears Power = Low - EMA
* EMA is exponential moving average of close of N periods

Examples:
* `df['eribull']` retrieves the 13 periods bull power
* `df['eribear']` retrieves the 13 periods bear power
* `df['eribull_5']` retrieves the 5 periods bull power
* `df['eribear_5']` retrieves the 5 periods bear power
  • Loading branch information
jealous committed Jun 23, 2023
1 parent b912fa5 commit e1708ee
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Supported statistics/indicators are:
* Ichimoku: Ichimoku Cloud
* CTI: Correlation Trend Indicator
* LRMA: Linear Regression Moving Average
* ERI: Elder-Ray Index

## Installation

Expand Down Expand Up @@ -670,6 +671,23 @@ Examples:
* `df['mfi']` retrieves the 14 periods MFI
* `df['mfi_6']` retrieves the 6 periods MFI

#### [ERI - Elder-Ray Index](https://admiralmarkets.com/education/articles/forex-indicators/bears-and-bulls-power-indicator)

The Elder-Ray Index contains the bull and the bear power.
Both are calculated based on the EMA of the close price.

The default window is 13.

Formular:
* Bulls Power = High - EMA
* Bears Power = Low - EMA
* EMA is exponential moving average of close of N periods

Examples:
* `df['eribull']` retrieves the 13 periods bull power
* `df['eribear']` retrieves the 13 periods bear power
* `df['eribull_5']` retrieves the 5 periods bull power
* `df['eribear_5']` retrieves the 5 periods bear power

#### [KER - Kaufman's efficiency ratio](https://strategyquant.com/codebase/kaufmans-efficiency-ratio-ker/)

Expand Down
42 changes: 39 additions & 3 deletions stockstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ class StockDataFrame(pd.DataFrame):

CTI = 12

ERI = 13

MULTI_SPLIT_INDICATORS = ("kama",)

# End of options
Expand Down Expand Up @@ -1040,12 +1042,12 @@ def _get_roc(self, column, window):
self[column_name] = self.roc(self[column], window)

@staticmethod
def ema(series, window):
def ema(series, window, *, adjust=True):
return series.ewm(
ignore_na=False,
span=window,
min_periods=0,
adjust=True).mean()
min_periods=1,
adjust=adjust).mean()

@staticmethod
def _rolling(series, window):
Expand Down Expand Up @@ -1210,6 +1212,39 @@ def _get_ppo(self):
self['ppos'] = self.ema(self['ppo'], self.PPO_EMA_SIGNAL)
self['ppoh'] = self['ppo'] - self['ppos']

def _get_eribull(self, windows=None):
return self._get_eri(windows)

def _get_eribear(self, windows=None):
return self._get_eri(windows)

def _get_eri(self, windows=None):
""" The bull line of Elder-Ray Index
The Elder-Ray Index contains the bull and the bear power.
Both are calculated based on the EMA of the close price.
The default window is 13.
https://admiralmarkets.com/education/articles/forex-indicators/bears-and-bulls-power-indicator
Formular:
* Bulls Power = High - EMA
* Bears Power = Low - EMA
* EMA is exponential moving average of close of N periods
"""
if windows is None:
window = self.ERI
bull_name = 'eribull'
bear_name = 'eribear'
else:
window = self.get_int_positive(windows)
bull_name = 'eribull_{}'.format(window)
bear_name = 'eribear_{}'.format(window)
ema = self.ema(self['close'], window, adjust=False)
self[bull_name] = self['high'] - ema
self[bear_name] = self['low'] - ema

def _get_coppock(self, windows=None):
""" Get Coppock Curve
Expand Down Expand Up @@ -1714,6 +1749,7 @@ def handler(self):
('ichimoku',): self._get_ichimoku,
('cti',): self._get_cti,
('ker',): self._get_ker,
('eribull', 'eribear'): self._get_eri,
}

def __init_not_exist_column(self, key):
Expand Down
21 changes: 21 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,27 @@ def test_ppo(self):
assert_that(stock['ppos'].loc[20110331], near_to(0.6840))
assert_that(stock['ppoh'].loc[20110331], near_to(0.4349))

def test_eri(self):
stock = self.get_stock_90days()
bull = stock['eribull']
bear = stock['eribear']
assert_that(bull[20110104], near_to(0.070))
assert_that(bear[20110104], near_to(-0.309))
assert_that(bull[20110222], near_to(0.099))
assert_that(bear[20110222], near_to(-0.290))

bull = stock['eribull_13']
bear = stock['eribear_13']
assert_that(bull[20110104], near_to(0.070))
assert_that(bear[20110104], near_to(-0.309))
assert_that(bull[20110222], near_to(0.099))
assert_that(bear[20110222], near_to(-0.290))

bull = stock['eribull_10']
bear = stock['eribear_10']
assert_that(bull[20110222], near_to(0.092))
assert_that(bear[20110222], near_to(-0.297))

def test_column_mstd(self):
stock = self.get_stock_20days()
mstd_3 = stock['close_3_mstd']
Expand Down

0 comments on commit e1708ee

Please sign in to comment.