Repository: cinar/indicatorts (ts)

Issue:
Trend: Mass Index (MI)
Mass index is a form of technical analysis that examines the range between high and low stock prices over a period of time. Mass index, developed by Donald Dorsey in the early 1990s, suggests that a reversal of the current trend will likely take place when the range widens beyond a certain point and then contracts. 

https://www.investopedia.com/terms/m/mass-index.asp


Pull request description:
Cinar/issue9
# Describe Request

Mass Index (MI) added.

Fixed #9

# Change Type

New indicator.


Patch:
diff --git a/README.md b/README.md
index 63cdd50..50c1483 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,7 @@ The following list of indicators are currently supported by this package:
 - [Community Channel Index (CMI)](src/indicator/trend/index.md#community-channel-index-cmi)
 - [Double Exponential Moving Average (DEMA)](src/indicator/trend/index.md#double-exponential-moving-average-dema)
 - [Exponential Moving Average (EMA)](src/indicator/trend/index.md#exponential-moving-average-ema)
+- [Mass Index (MI)](src/indicator/trend/index.md#mass-index-mi)
 - [Moving Average Convergence Divergence (MACD)](src/indicator/trend/index.md#moving-average-convergence-divergence-macd)
 - [Moving Max](src/indicator/trend/index.md#moving-max)
 - [Moving Min](src/indicator/trend/index.md#moving-min)
diff --git a/src/index.ts b/src/index.ts
index 7bad7e0..24d667a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -30,6 +30,7 @@ export * from './indicator/trend/dema';
 export * from './indicator/trend/ema';
 export * from './indicator/trend/kdj';
 export * from './indicator/trend/macd';
+export * from './indicator/trend/massIndex';
 export * from './indicator/trend/mmax';
 export * from './indicator/trend/mmin';
 export * from './indicator/trend/msum';
diff --git a/src/indicator/trend/index.md b/src/indicator/trend/index.md
index 26d4208..3f0ddfb 100644
--- a/src/indicator/trend/index.md
+++ b/src/indicator/trend/index.md
@@ -9,6 +9,7 @@ Trend indicators measure the direction and strength of a trend.
 - [Community Channel Index (CMI)](#community-channel-index-cmi)
 - [Double Exponential Moving Average (DEMA)](#double-exponential-moving-average-dema)
 - [Exponential Moving Average (EMA)](#exponential-moving-average-ema)
+- [Mass Index (MI)](#mass-index-mi)
 - [Moving Average Convergence Divergence (MACD)](#moving-average-convergence-divergence-macd)
 - [Moving Max](#moving-max)
 - [Moving Min](#moving-min)
@@ -139,6 +140,23 @@ import {ema} from 'indicatorts';
 const result = ema(period, values);
 ```
 
+#### Mass Index (MI)
+
+The [massIndex](./massIndex.ts) uses the high-low range to identify trend reversals based on range expansions.
+
+```
+Singe EMA = EMA(9, Highs - Lows)
+Double EMA = EMA(9, Single EMA)
+Ratio = Single EMA / Double EMA
+MI = Sum(25, Ratio)
+```
+
+```TypeScript
+import {massIndex} from 'indicatorts';
+
+const result = massIndex(highs, lows);
+```
+
 #### Moving Average Convergence Divergence (MACD)
 
 The [macd](./macd.ts) function calculates a trend-following momentum indicator that shows the relationship between two moving averages of price.
diff --git a/src/indicator/trend/massIndex.ts b/src/indicator/trend/massIndex.ts
new file mode 100644
index 0000000..f79aa28
--- /dev/null
+++ b/src/indicator/trend/massIndex.ts
@@ -0,0 +1,28 @@
+// Copyright (c) 2022 Onur Cinar. All Rights Reserved.
+// https://github.com/cinar/indicatorts
+
+import { divide, substract } from '../../helper/numArray';
+import { ema } from './ema';
+import { msum } from './msum';
+
+/**
+ * The Mass Index (MI) uses the high-low range to identify trend reversals
+ * based on range expansions.
+ *
+ * Singe EMA = EMA(9, Highs - Lows)
+ * Double EMA = EMA(9, Single EMA)
+ * Ratio = Single EMA / Double EMA
+ * MI = Sum(25, Ratio)
+ *
+ * @param highs high values.
+ * @param lows low values.
+ * @returns mi values.
+ */
+export function massIndex(highs: number[], lows: number[]): number[] {
+  const ema1 = ema(9, substract(highs, lows));
+  const ema2 = ema(9, ema1);
+  const ratio = divide(ema1, ema2);
+  const mi = msum(25, ratio);
+
+  return mi;
+}


Test patch:
diff --git a/src/indicator/trend/massIndex.test.ts b/src/indicator/trend/massIndex.test.ts
new file mode 100644
index 0000000..d3009c8
--- /dev/null
+++ b/src/indicator/trend/massIndex.test.ts
@@ -0,0 +1,16 @@
+// Copyright (c) 2022 Onur Cinar. All Rights Reserved.
+// https://github.com/cinar/indicatorts
+
+import { roundDigitsAll } from '../../helper/numArray';
+import { massIndex } from './massIndex';
+
+describe('Mass Index', () => {
+  it('should be able to compute MI', () => {
+    const highs = [10, 9, 12, 14, 12];
+    const lows = [6, 7, 9, 12, 10];
+    const expected = [1, 1.92, 2.83, 3.69, 4.52];
+
+    const actual = massIndex(highs, lows);
+    expect(roundDigitsAll(2, actual)).toStrictEqual(expected);
+  });
+});