-
-
Notifications
You must be signed in to change notification settings - Fork 111
/
Copy pathcci.go
92 lines (76 loc) · 2.18 KB
/
cci.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright (c) 2021-2024 Onur Cinar.
// The source code is provided under GNU AGPLv3 License.
// https://github.com/cinar/indicator
package trend
import (
"github.com/cinar/indicator/v2/helper"
)
const (
// DefaultCciPeriod is the default time period for CCI.
DefaultCciPeriod = 20
)
// Cci represents the configuration parameters for calculating the Community Channel Index (CCI). CCI 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))
// CCI = (Typical Price - Moving Average) / (0.015 * Mean Deviation)
//
// Example:
//
// cmi := trend.NewCmi()
// cmi.Period = 20
// values = cmi.Compute(highs, lows, closings)
type Cci[T helper.Number] struct {
// Time period.
Period int
}
// NewCci function initializes a new CCI instance with the default parameters.
func NewCci[T helper.Number]() *Cci[T] {
return NewCciWithPeriod[T](DefaultCciPeriod)
}
// NewCciWithPeriod function initializes a new CCI instance with the given period.
func NewCciWithPeriod[T helper.Number](period int) *Cci[T] {
return &Cci[T]{
Period: period,
}
}
// Compute function takes a channel of numbers and computes the CCI and the signal line.
func (c *Cci[T]) Compute(highs, lows, closings <-chan T) <-chan T {
typicalPrice := NewTypicalPrice[T]()
sma1 := NewSmaWithPeriod[T](c.Period)
sma2 := NewSmaWithPeriod[T](c.Period)
tps := helper.Duplicate[T](
typicalPrice.Compute(highs, lows, closings),
3,
)
mas := helper.Duplicate[T](
sma1.Compute(tps[0]),
2,
)
tps[1] = helper.Skip(tps[1], sma1.Period-1)
tps[2] = helper.Skip(tps[2], sma1.Period-1)
md := sma2.Compute(
helper.Abs(
helper.Subtract(tps[1], mas[0]),
),
)
mas[1] = helper.Skip(mas[1], sma2.Period-1)
tps[2] = helper.Skip(tps[2], sma2.Period-1)
multiplier := 0.015
cci := helper.Divide(
helper.Subtract(
tps[2], mas[1],
),
helper.MultiplyBy[T](
md,
T(multiplier),
),
)
return cci
}
// IdlePeriod is the initial period that CCI won't yield any results.
func (c *Cci[T]) IdlePeriod() int {
return (c.Period * 2) - 2
}