diff --git a/helper/is_rising.go b/helper/is_rising.go new file mode 100644 index 0000000..0c85e6d --- /dev/null +++ b/helper/is_rising.go @@ -0,0 +1,27 @@ +// Copyright (c) 2021-2026 Onur Cinar. +// The source code is provided under GNU AGPLv3 License. +// https://github.com/cinar/indicator + +package helper + +// IsRising returns 1 if the current value is strictly greater than the value +// n periods ago, and 0 otherwise. +// +// Example: +// +// input := []int{1, 2, 5, 5, 8, 2, 1, 1, 3, 4} +// output := helper.IsRising(helper.SliceToChan(input), 2) +// fmt.Println(helper.ChanToSlice(output)) // [1, 1, 1, 0, 0, 0, 1, 1] +func IsRising[T Number](c <-chan T, period int) <-chan T { + cs := Duplicate(c, 2) + cs[0] = Buffered(cs[0], period) + cs[1] = Skip(cs[1], period) + + return Operate(cs[1], cs[0], func(current, previous T) T { + if current > previous { + return 1 + } + + return 0 + }) +} diff --git a/helper/is_rising_test.go b/helper/is_rising_test.go new file mode 100644 index 0000000..9694dfc --- /dev/null +++ b/helper/is_rising_test.go @@ -0,0 +1,71 @@ +// Copyright (c) 2021-2026 Onur Cinar. +// The source code is provided under GNU AGPLv3 License. +// https://github.com/cinar/indicator + +package helper_test + +import ( + "testing" + + "github.com/cinar/indicator/v2/helper" +) + +func TestIsRising(t *testing.T) { + input := helper.SliceToChan([]int{1, 2, 5, 5, 8, 2, 1, 1, 3, 4}) + expected := helper.SliceToChan([]int{1, 1, 1, 0, 0, 0, 1, 1}) + + actual := helper.IsRising(input, 2) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +} + +func TestIsRisingDefaultPeriod(t *testing.T) { + input := helper.SliceToChan([]int{1, 3, 2, 5, 4}) + expected := helper.SliceToChan([]int{1, 0, 1, 0}) + + actual := helper.IsRising(input, 1) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +} + +func TestIsRisingAllRising(t *testing.T) { + input := helper.SliceToChan([]int{1, 2, 3, 4, 5}) + expected := helper.SliceToChan([]int{1, 1, 1, 1}) + + actual := helper.IsRising(input, 1) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +} + +func TestIsRisingNoneRising(t *testing.T) { + input := helper.SliceToChan([]int{5, 4, 3, 2, 1}) + expected := helper.SliceToChan([]int{0, 0, 0, 0}) + + actual := helper.IsRising(input, 1) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +} + +func TestIsRisingEqual(t *testing.T) { + input := helper.SliceToChan([]int{3, 3, 3, 3}) + expected := helper.SliceToChan([]int{0, 0, 0}) + + actual := helper.IsRising(input, 1) + + err := helper.CheckEquals(actual, expected) + if err != nil { + t.Fatal(err) + } +}