Download the accompanying IPython Notebook for this Tutorial from Github.
Python streamlines tasks requiring multiple steps in a single block of code. For this reason, it is a great tool for querying and performing analysis on data.
Last Tutorial, we outlined steps for calculating Commodity Channel Index (CCI).
In this Tutorial, we introduce a new technical indicator, the Mass Index.
Developed by Donald Dorsey, the Mass Index uses the high-low range to identify trend reversals based on range expansions. In this sense, the Mass Index is a volatility indicator that does not have a directional bias. Instead, the Mass Index identifies range bulges that can foreshadow a reversal of the current trend.
The Mass Index is calculated as follows:
Single EMA = 9-period exponential moving average (EMA) of the high-low differential
Double EMA = 9-period EMA of the 9-period EMA of the high-low differential
EMA Ratio = Single EMA divided by Double EMA
Mass Index = 25-period sum of the EMA Ratio
First, the Single EMA provides the average for the high-low range.
Second, the Double EMA provides a second smoothing of this volatility measure.
Using a ratio of these two exponential moving averages normalizes the data series. This ratio shows when the Single EMA becomes large relative to the Double EMA.
The final step, a 25-period summation, acts like a moving average to further smooth the data series.
Overall, the Mass Index rises as the high-low range widens and falls as the high-low range narrows.
Donald Dorsey looked for “reversal bulges” to signal a trend reversal. According to Dorsey, a bulge occurs when the Mass Index moves above 27. This initial bulge does not complete the signal though. Dorsey waited for this bulge to reverse with a move back below 26.50. Once the reversal bulge is complete, traders should use other analysis techniques to determine the direction of the next move. Ideally, a downtrend followed by a reversal bulge would suggest a bullish trend reversal. Conversely, an uptrend followed by a reversal bulge would suggest a bearish trend reversal.
Let’s use Python to compute the Mass Index.
1.) Import modules.
import pandas as pd
import numpy as np
from pandas_datareader import data as web
import matplotlib.pyplot as plt
%matplotlib inline
2.a.) Define function for querying daily close.
def get_stock(stock,start,end):
return web.DataReader(stock,'google',start,end)['Close']
2.b.) Define function for querying daily high.
def get_high(stock,start,end):
return web.DataReader(stock,'google',start,end)['High']
2.c.) Define function for querying daily low.
def get_low(stock,start,end):
return web.DataReader(stock,'google',start,end)['Low']
3.) Define function for Mass Index.
def MassIndex(high, low):
Range = high - low
EX1 = pd.ewma(Range, span = 9, min_periods = 8)
EX2 = pd.ewma(EX1, span = 9, min_periods = 8)
Mass = EX1 / EX2
MassIndex = pd.Series(pd.rolling_sum(Mass, 25), name = 'Mass Index')
return MassIndex
How does the Mass Index function work?
3.a.) Function calculates the difference between the high and the low, and sets this value to variable Range.
#Range = high - low
3.b.) Function takes a 9 period Exponential Moving Average of the Range, and sets this value to variable EX1.
#EX1 = pd.ewma(Range, span = 9, min_periods = 8)
3.c.) Function takes a 9 period Exponential Moving Average of the EX1, to smooth volatility, and sets this value to variable EX2.
#EX2 = pd.ewma(EX1, span = 9, min_periods = 8)
3.d.) Function takes the ratio of EX1 to EX2, and sets this value to variable Mass.
#Mass = EX1 / EX2
3.e.) Function calculates the 25 period rolling sum of Mass, and sets this value to variable MassIndex.
#MassIndex = pd.Series(pd.rolling_sum(Mass, 25), name = 'Mass Index')
3.f.) Function returns MassIndex.
#return MassIndex
4.) Query daily close, high, and low for ‘FB’ during 2016.
df = pd.DataFrame(get_stock('FB', '1/1/2016', '12/31/2016'))
df['High'] = get_high('FB', '1/1/2016', '12/31/2016')
df['Low'] = get_low('FB', '1/1/2016', '12/31/2016')
5.) Run daily high and low through Mass Index function. Save series to new column in dataframe.
df['MassIndex'] = MassIndex(df['High'], df['Low'])
df.tail()
6.) Plot daily close and Mass Index.
df.plot(y=['Close'])
df.plot(y=['MassIndex'])
There you have it! We created our Mass Index indicator. Here’s the full code:
import pandas as pd
import numpy as np
from pandas_datareader import data as web
import matplotlib.pyplot as plt
%matplotlib inline
def get_stock(stock,start,end):
return web.DataReader(stock,'google',start,end)['Close']
def get_high(stock,start,end):
return web.DataReader(stock,'google',start,end)['High']
def get_low(stock,start,end):
return web.DataReader(stock,'google',start,end)['Low']
def MassIndex(high, low):
Range = high - low
EX1 = pd.ewma(Range, span = 9, min_periods = 8)
EX2 = pd.ewma(EX1, span = 9, min_periods = 8)
Mass = EX1 / EX2
MassIndex = pd.Series(pd.rolling_sum(Mass, 25), name = 'Mass Index')
return MassIndex
df = pd.DataFrame(get_stock('FB', '1/1/2016', '12/31/2016'))
df['High'] = get_high('FB', '1/1/2016', '12/31/2016')
df['Low'] = get_low('FB', '1/1/2016', '12/31/2016')
df['MassIndex'] = MassIndex(df['High'], df['Low'])
df.tail()