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 MQL4:

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 versions:

  # 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

The RSI / 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.

Some decisions

  • 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 RSI mode, 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

  • The pointsize will 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(
        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
            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

!ASH View