diff --git a/README.md b/README.md index a1eb7cb..a775b24 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)](trend_indicators.md#community-channel-index-cmi) - [Double Exponential Moving Average (DEMA)](trend_indicators.md#double-exponential-moving-average-dema) - [Exponential Moving Average (EMA)](trend_indicators.md#exponential-moving-average-ema) +- [Mass Index (MI)](trend_indicators.md#mass-index-mi) - [Moving Average Convergence Divergence (MACD)](trend_indicators.md#moving-average-convergence-divergence-macd) - [Moving Max](trend_indicators.md#moving-max) - [Moving Min](trend_indicators.md#moving-min) diff --git a/trend_indicators.go b/trend_indicators.go index ebeb56e..01e5fa3 100644 --- a/trend_indicators.go +++ b/trend_indicators.go @@ -178,6 +178,24 @@ func Macd(closing []float64) ([]float64, []float64) { return macd, signal } +// 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) +// +// Returns mi. +func MassIndex(high, low []float64) []float64 { + ema1 := Ema(9, substract(high, low)) + ema2 := Ema(9, ema1) + ratio := divide(ema1, ema2) + mi := Sum(25, ratio) + + return mi +} + // Moving Chande Forecast Oscillator calculates based on // the given period. // diff --git a/trend_indicators.md b/trend_indicators.md index 95e6a3b..349403d 100644 --- a/trend_indicators.md +++ b/trend_indicators.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) @@ -124,6 +125,21 @@ The [Ema](https://pkg.go.dev/github.com/cinar/indicator#Ema) function calculates result := indicator.Ema(2, []float64{2, 4, 6, 8, 12, 14, 16, 18, 20}) ``` +#### Mass Index (MI) + +The [MassIndex](https://pkg.go.dev/github.com/cinar/indicator#MassIndex) 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) +``` + +```Golang +result := indicator.MassIndex(high, low) +``` + #### Moving Average Convergence Divergence (MACD) The [Macd](https://pkg.go.dev/github.com/cinar/indicator#Macd) function calculates a trend-following momentum indicator that shows the relationship between two moving averages of price. diff --git a/trend_indicators_test.go b/trend_indicators_test.go index a87b056..7748b89 100644 --- a/trend_indicators_test.go +++ b/trend_indicators_test.go @@ -111,6 +111,26 @@ func TestEma(t *testing.T) { } } +func TestMassIndex(t *testing.T) { + high := []float64{10, 9, 12, 14, 12} + low := []float64{6, 7, 9, 12, 10} + expected := []float64{1, 1.92, 2.83, 3.69, 4.52} + + result := MassIndex(high, low) + + if len(result) != len(expected) { + t.Fatal("result not same size") + } + + for i := 0; i < len(result); i++ { + actual := math.Round(result[i]*100) / 100 + + if actual != expected[i] { + t.Fatalf("result %d actual %f expected %f", i, actual, expected[i]) + } + } +} + func TestMax(t *testing.T) { values := []float64{10, 9, 8, 7, 6, 5, 4, 3, 2, 1} expected := []float64{10, 10, 10, 10, 9, 8, 7, 6, 5}