diff --git a/trend/README.md b/trend/README.md index 8667c3e..b2b797e 100644 --- a/trend/README.md +++ b/trend/README.md @@ -25,8 +25,6 @@ The information provided on this project is strictly for informational purposes ## Index - [Constants](<#constants>) -- [func MovingMax\[T helper.Number\]\(c \<\-chan T, period int\) \<\-chan T](<#MovingMax>) -- [func MovingMin\[T helper.Number\]\(c \<\-chan T, period int\) \<\-chan T](<#MovingMin>) - [type Apo](<#Apo>) - [func NewApo\[T helper.Number\]\(\) \*Apo\[T\]](<#NewApo>) - [func \(apo \*Apo\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#Apo[T].Compute>) @@ -51,6 +49,12 @@ The information provided on this project is strictly for informational purposes - [func NewMassIndex\[T helper.Number\]\(\) \*MassIndex\[T\]](<#NewMassIndex>) - [func \(m \*MassIndex\[T\]\) Compute\(highs, lows \<\-chan T\) \<\-chan T](<#MassIndex[T].Compute>) - [func \(m \*MassIndex\[T\]\) IdlePeriod\(\) int](<#MassIndex[T].IdlePeriod>) +- [type MovingMax](<#MovingMax>) + - [func NewMovingMax\[T helper.Number\]\(\) \*MovingMax\[T\]](<#NewMovingMax>) + - [func \(m \*MovingMax\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingMax[T].Compute>) +- [type MovingMin](<#MovingMin>) + - [func NewMovingMin\[T helper.Number\]\(\) \*MovingMin\[T\]](<#NewMovingMin>) + - [func \(m \*MovingMin\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingMin[T].Compute>) - [type MovingSum](<#MovingSum>) - [func NewMovingSum\[T helper.Number\]\(\) \*MovingSum\[T\]](<#NewMovingSum>) - [func \(m \*MovingSum\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingSum[T].Compute>) @@ -139,40 +143,6 @@ const ( ) ``` - -## func [MovingMax]() - -```go -func MovingMax[T helper.Number](c <-chan T, period int) <-chan T -``` - -MovingMax function takes a channel of numbers and computes the moving maximum over the specified period. - -Example: - -``` -input := helper.SliceToChan([]int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4}) -actual := trend.MovingMax(input, 4) -fmt.Println(helper.ChanToSlice(actual)) // [20, 20, 5, 8, 10, 10, 10] -``` - - -## func [MovingMin]() - -```go -func MovingMin[T helper.Number](c <-chan T, period int) <-chan T -``` - -MovingMin function takes a channel of numbers and computes the moving minimum over the specified period. - -Example: - -``` -input := helper.SliceToChan([]int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4}) -actual := trend.MovingMin(input, 4) -fmt.Println(helper.ChanToSlice(actual)) // [-10, -5, -5, -5, 1, -20, -20] -``` - ## type [Apo]() @@ -500,6 +470,70 @@ func (m *MassIndex[T]) IdlePeriod() int IdlePeriod is the initial period that Mass Index won't yield any results. + +## type [MovingMax]() + +MovingMax represents the configuration parameters for calculating the Moving Max over the specified period. + +Example: + +```go +type MovingMax[T helper.Number] struct { + // Time period. + Period int +} +``` + + +### func [NewMovingMax]() + +```go +func NewMovingMax[T helper.Number]() *MovingMax[T] +``` + +NewMovingMax function initializes a new Moving Max instance with the default parameters. + + +### func \(\*MovingMax\[T\]\) [Compute]() + +```go +func (m *MovingMax[T]) Compute(c <-chan T) <-chan T +``` + +Compute function takes a channel of numbers and computes the Moving Max over the specified period. + + +## type [MovingMin]() + +MovingMin represents the configuration parameters for calculating the Moving Min over the specified period. + +Example: + +```go +type MovingMin[T helper.Number] struct { + // Time period. + Period int +} +``` + + +### func [NewMovingMin]() + +```go +func NewMovingMin[T helper.Number]() *MovingMin[T] +``` + +NewMovingMin function initializes a new Moving Min instance with the default parameters. + + +### func \(\*MovingMin\[T\]\) [Compute]() + +```go +func (m *MovingMin[T]) Compute(c <-chan T) <-chan T +``` + +Compute function takes a channel of numbers and computes the Moving Min over the specified period. + ## type [MovingSum]() diff --git a/trend/aroon.go b/trend/aroon.go index 72c9c9d..803be06 100644 --- a/trend/aroon.go +++ b/trend/aroon.go @@ -43,8 +43,14 @@ func NewAroon[T helper.Number]() *Aroon[T] { // Compute function takes a channel of numbers and computes the Aroon // over the specified period. func (a *Aroon[T]) Compute(high, low <-chan T) (<-chan T, <-chan T) { - sinceLastHigh := helper.Since(MovingMax(high, a.Period)) - sinceLastLow := helper.Since(MovingMin(low, a.Period)) + max := NewMovingMax[T]() + max.Period = a.Period + + min := NewMovingMin[T]() + min.Period = a.Period + + sinceLastHigh := helper.Since(max.Compute(high)) + sinceLastLow := helper.Since(min.Compute(low)) // Aroon Up = ((25 - Period Since Last 25 Period High) / 25) * 100 aroonUp := helper.MultiplyBy(sinceLastHigh, -1) diff --git a/trend/moving_max.go b/trend/moving_max.go index 1687b5d..b3d6cb2 100644 --- a/trend/moving_max.go +++ b/trend/moving_max.go @@ -6,17 +6,26 @@ package trend import "github.com/cinar/indicator/helper" -// MovingMax function takes a channel of numbers and computes the -// moving maximum over the specified period. +// MovingMax represents the configuration parameters for calculating the +// Moving Max over the specified period. // // Example: -// -// input := helper.SliceToChan([]int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4}) -// actual := trend.MovingMax(input, 4) -// fmt.Println(helper.ChanToSlice(actual)) // [20, 20, 5, 8, 10, 10, 10] -func MovingMax[T helper.Number](c <-chan T, period int) <-chan T { +type MovingMax[T helper.Number] struct { + // Time period. + Period int +} + +// NewMovingMax function initializes a new Moving Max instance +// with the default parameters. +func NewMovingMax[T helper.Number]() *MovingMax[T] { + return &MovingMax[T]{} +} + +// Compute function takes a channel of numbers and computes the +// Moving Max over the specified period. +func (m *MovingMax[T]) Compute(c <-chan T) <-chan T { cs := helper.Duplicate(c, 2) - cs[1] = helper.Shift(cs[1], period, 0) + cs[1] = helper.Shift(cs[1], m.Period, 0) bst := helper.NewBst[T]() @@ -26,5 +35,5 @@ func MovingMax[T helper.Number](c <-chan T, period int) <-chan T { return bst.Max() }) - return helper.Skip(maxs, period-1) + return helper.Skip(maxs, m.Period-1) } diff --git a/trend/moving_max_test.go b/trend/moving_max_test.go index 8849fbb..4f0da67 100644 --- a/trend/moving_max_test.go +++ b/trend/moving_max_test.go @@ -5,7 +5,6 @@ package trend_test import ( - "reflect" "testing" "github.com/cinar/indicator/helper" @@ -13,12 +12,16 @@ import ( ) func TestMovingMax(t *testing.T) { - input := []int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4} - expected := []int{20, 20, 5, 8, 10, 10, 10} + input := helper.SliceToChan([]int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4}) + expected := helper.SliceToChan([]int{20, 20, 5, 8, 10, 10, 10}) - actual := helper.ChanToSlice(trend.MovingMax(helper.SliceToChan(input), 4)) + max := trend.NewMovingMax[int]() + max.Period = 4 - if !reflect.DeepEqual(actual, expected) { - t.Fatalf("actual %v expected %v", actual, expected) + actual := max.Compute(input) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) } } diff --git a/trend/moving_min.go b/trend/moving_min.go index 18c03fa..9bb5ed6 100644 --- a/trend/moving_min.go +++ b/trend/moving_min.go @@ -6,17 +6,26 @@ package trend import "github.com/cinar/indicator/helper" -// MovingMin function takes a channel of numbers and computes the -// moving minimum over the specified period. +// MovingMin represents the configuration parameters for calculating the +// Moving Min over the specified period. // // Example: -// -// input := helper.SliceToChan([]int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4}) -// actual := trend.MovingMin(input, 4) -// fmt.Println(helper.ChanToSlice(actual)) // [-10, -5, -5, -5, 1, -20, -20] -func MovingMin[T helper.Number](c <-chan T, period int) <-chan T { +type MovingMin[T helper.Number] struct { + // Time period. + Period int +} + +// NewMovingMin function initializes a new Moving Min instance +// with the default parameters. +func NewMovingMin[T helper.Number]() *MovingMin[T] { + return &MovingMin[T]{} +} + +// Compute function takes a channel of numbers and computes the +// Moving Min over the specified period. +func (m *MovingMin[T]) Compute(c <-chan T) <-chan T { cs := helper.Duplicate(c, 2) - cs[1] = helper.Shift(cs[1], period, 0) + cs[1] = helper.Shift(cs[1], m.Period, 0) bst := helper.NewBst[T]() @@ -26,5 +35,5 @@ func MovingMin[T helper.Number](c <-chan T, period int) <-chan T { return bst.Min() }) - return helper.Skip(mins, period-1) + return helper.Skip(mins, m.Period-1) } diff --git a/trend/moving_min_test.go b/trend/moving_min_test.go index 8af669f..df25d6a 100644 --- a/trend/moving_min_test.go +++ b/trend/moving_min_test.go @@ -5,7 +5,6 @@ package trend_test import ( - "reflect" "testing" "github.com/cinar/indicator/helper" @@ -13,12 +12,16 @@ import ( ) func TestMovingMin(t *testing.T) { - input := []int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4} - expected := []int{-10, -5, -5, -5, 1, -20, -20} + input := helper.SliceToChan([]int{-10, 20, -4, -5, 1, 5, 8, 10, -20, 4}) + expected := helper.SliceToChan([]int{-10, -5, -5, -5, 1, -20, -20}) - actual := helper.ChanToSlice(trend.MovingMin(helper.SliceToChan(input), 4)) + min := trend.NewMovingMin[int]() + min.Period = 4 - if !reflect.DeepEqual(actual, expected) { - t.Fatalf("actual %v expected %v", actual, expected) + actual := min.Compute(input) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) } }