Absolute Strengh Histogram
This is an indicator which seems to originate in the forex world, probably at http://fxcodebase.com, but it seems difficult to track what the actual origin is.
Potentially first implemented in LUA here:
Which also says that an updated and revised LUA version is available at:
The same site hosts a version in
And another version for
MQL5 can be found at:
All versions seem complex, due to the language and platform implementation,
with a whooping 227 lines in the
MQL5 version (including some comments of
course), and have slight differences, so the need arises to settle for a sound
definition. The definition in pseudo-code after looking at the different
# p0 is the current price and p1 is the previous price if mode is RSI: bulls = 0.5 * abs(p0 - p1) + p0 - p1 bears = 0.5 * abs(p0 - p1) - p0 + p1 elif mode is STOCH: bulls = p0 - lowest(period) bears = highest(period - p1 avgbulls = moving_average(bulls, period) avgbears = moving_average(bears, period) smoothedbulls = moving_average(bulls, smoothing_period) / pointsize smoothedbears = moving_average(bears, smoothing_period) / pointsize ash = smoothedbulls - smoothedbears
STOCH naming was chosen by the original implementors and
pointsize is also known as
pipsize which reflects its Forex origins. It
is unclear if the smoothing average has to be the same as the previous
moving average and some versions seem to work with an already averaged price
rather than with the standard price. And the moving averages are selected
using an integer.
The indicator will work with the raw priced passed to it in a data feed. If the user wants to run the indicator on an average price it can pass it, instead of passing the raw price.
The 0.5 multiplier in the
RSImode, will be a parameter
The moving average won't be selected with any kind of integer. In backtrader one can pass the actual desired moving average as a parameter.
The smoothing moving average, unless specified as a parameter, will be the same as the moving average already in use in the indicator
pointsizewill not be used unless the user specifies a value for it as a parameter.
And here the implementation
class ASH(bt.Indicator): alias = ('AbsoluteStrengthOscilator',) lines = ('ash', 'bulls', 'bears',) # output lines # customize the plotting of the *ash* line plotlines = dict(ash=dict(_method='bar', alpha=0.33, width=0.66)) RSI, STOCH = range(0, 2) # enum values for the parameter mode params = dict( period=9, smoothing=2, mode=RSI, rsifactor=0.5, movav=bt.ind.WMA, # WeightedMovingAverage smoothav=None, # use movav if not specified pointsize=None, # use only if specified ) def __init__(self): # Start calcs according to selected mode if self.p.mode == self.RSI: p0p1 = self.data - self.data(-1) # used twice below half_abs_p0p1 = self.p.rsifactor * abs(p0p1) # used twice below bulls = half_abs_p0p1 + p0p1 bears = half_abs_p0p1 - p0p1 else: bulls = self.data - bt.ind.Lowest(self.data, period=self.p.period) bears = bt.ind.Highest(self.data, period=self.p.period) - self.data avbulls = self.p.movav(bulls, period=self.p.period) avbears = self.p.movav(bears, period=self.p.period) # choose smoothing average and smooth the already averaged values smoothav = self.p.smoothav or self.p.movav # choose smoothav smoothbulls = smoothav(avbulls, period=self.p.smoothing) smoothbears = smoothav(avbears, period=self.p.smoothing) if self.p.pointsize: # apply only if it makes sense smoothbulls /= self.p.pointsize smoothbears /= self.p.pointsize # Assign the final values to the output lines self.l.bulls = smoothbulls self.l.bears = smoothbears self.l.ash = smoothbulls - smoothbears
And here a view of how the indicator works