Skip to content

Commit

Permalink
Trend: Commodity Channel Index (CCI) (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
cinar authored Jan 27, 2022
1 parent 2010461 commit 63ebe2d
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The following list of indicators are currently supported by this package:
- [Aroon Indicator](trend_indicators.md#aroon-indicator)
- [Balance of Power (BOP)](trend_indicators.md#balance-of-power-bop)
- [Chande Forecast Oscillator (CFO)](trend_indicators.md#chande-forecast-oscillator-cfo)
- [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)
- [Moving Average Convergence Divergence (MACD)](trend_indicators.md#moving-average-convergence-divergence-macd)
Expand Down
11 changes: 11 additions & 0 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,14 @@ func sqrt(values []float64) []float64 {

return result
}

// Abs of given values.
func abs(values []float64) []float64 {
result := make([]float64, len(values))

for i := 0; i < len(values); i++ {
result[i] = math.Abs(values[i])
}

return result
}
23 changes: 23 additions & 0 deletions trend_indicators.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,29 @@ func ChandeForecastOscillator(closing []float64) []float64 {
return cfo
}

// The Community Channel Index (CMI) is a momentum-based oscillator
// used to help determine when an investment vehicle is reaching a
// condition of being overbought or oversold.
//
// Moving Average = Sma(Period, Typical Price)
// Mean Deviation = Sma(Period, Abs(Typical Price - Moving Average))
// CMI = (Typical Price - Moving Average) / (0.015 * Mean Deviation)
//
// Returns cmi.
func CommunityChannelIndex(period int, high, low, closing []float64) []float64 {
tp, _ := TypicalPrice(low, high, closing)
ma := Sma(period, tp)
md := Sma(period, abs(substract(tp, ma)))
cci := divide(substract(tp, ma), multiplyBy(md, 0.015))

return cci
}

// The default community channel index with the period of 20.
func DefaultCommunityChannelIndex(high, low, closing []float64) []float64 {
return CommunityChannelIndex(20, high, low, closing)
}

// Dema calculates the Double Exponential Moving Average (DEMA).
//
// DEMA = (2 * EMA(values)) - EMA(EMA(values))
Expand Down
20 changes: 20 additions & 0 deletions trend_indicators.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Trend indicators measure the direction and strength of a trend.
- [Aroon Indicator](#aroon-indicator)
- [Balance of Power (BOP)](trend_indicators.md#balance-of-power-bop)
- [Chande Forecast Oscillator (CFO)](#chande-forecast-oscillator-cfo)
- [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)
- [Moving Average Convergence Divergence (MACD)](#moving-average-convergence-divergence-macd)
Expand Down Expand Up @@ -79,6 +80,25 @@ Based on [Chande Forecast Oscillator Formula, Strategy](https://www.stockmaniacs
```golang
cfo := indicator.ChandeForecastOscillator(closing)
```
#### Community Channel Index (CMI)

The [CommunityChannelIndex](https://pkg.go.dev/github.com/cinar/indicator#CommunityChannelIndex) is a momentum-based oscillator used to help determine when an investment vehicle is reaching a condition of being overbought or oversold.

```
Moving Average = Sma(Period, Typical Price)
Mean Deviation = Sma(Period, Abs(Typical Price - Moving Average))
CMI = (Typical Price - Moving Average) / (0.015 * Mean Deviation)
```

```golang
result := indicator.CommunityChannelIndex(period, high, low, closing)
```

The [DefaultCommunityChannelIndex](https://pkg.go.dev/github.com/cinar/indicator#DefaultCommunityChannelIndex) calculates with the period of 20.

```golang
result := indicator.DefaultCommunityChannelIndex(high, low, closing)
```

#### Double Exponential Moving Average (DEMA)

Expand Down
21 changes: 21 additions & 0 deletions trend_indicators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,27 @@ func TestChandeForecastOscillator(t *testing.T) {
}
}

func TestCommunityChannelIndex(t *testing.T) {
high := []float64{10, 9, 12, 14, 12}
low := []float64{6, 7, 9, 12, 10}
closing := []float64{9, 11, 7, 10, 8}
expected := []float64{math.NaN(), 133.33, 114.29, 200, 26.32}

actual := DefaultCommunityChannelIndex(high, low, closing)

if len(actual) != len(expected) {
t.Fatal("not the same size")
}

for i := 1; i < len(expected); i++ {
a := roundDigits(actual[i], 2)

if a != expected[i] {
t.Fatalf("at %d actual %f expected %f", i, a, expected[i])
}
}
}

func TestEma(t *testing.T) {
values := []float64{2, 4, 6, 8, 12, 14, 16, 18, 20}
ema := []float64{2, 3.333, 5.111, 7.037, 10.346, 12.782, 14.927, 16.976, 18.992}
Expand Down

0 comments on commit 63ebe2d

Please sign in to comment.