From e387ce287f07171fce5673ac75ed1faea78d725c Mon Sep 17 00:00:00 2001 From: Onur Cinar Date: Sat, 14 Sep 2024 12:39:01 -0700 Subject: [PATCH] CommonPeriod and SyncPeriod added. (#213) # Describe Request CommonPeriod and SyncPeriod are added to help synchronize channels with varying periods. Fixed #211 # Change Type New feature. --- helper/sync.go | 37 +++++++++++++++++++++++++++++++++++++ helper/sync_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 helper/sync.go create mode 100644 helper/sync_test.go diff --git a/helper/sync.go b/helper/sync.go new file mode 100644 index 0000000..fe8a4ad --- /dev/null +++ b/helper/sync.go @@ -0,0 +1,37 @@ +// Copyright (c) 2021-2024 Onur Cinar. +// The source code is provided under GNU AGPLv3 License. +// https://github.com/cinar/indicator + +package helper + +import "slices" + +// CommonPeriod calculates the smallest period at which all data channels can be synchronized +// +// Example: +// +// // Synchronize channels with periods 4, 2, and 3. +// commonPeriod := helper.CommonPeriod(4, 2, 3) // commonPeriod = 4 +// +// // Synchronize the first channel +// c1 := helper.Sync(commonPeriod, 4, c1) +// +// // Synchronize the second channel +// c2 := helper.Sync(commonPeriod, 2, c2) +// +// // Synchronize the third channel +// c3 := helper.Sync(commonPeriod, 3, c3) +func CommonPeriod(periods ...int) int { + return slices.Max(periods) +} + +// SyncPeriod adjusts the given channel to match the given common period. +func SyncPeriod[T any](commonPeriod, period int, c <-chan T) <-chan T { + forwardPeriod := commonPeriod - period + + if forwardPeriod > 0 { + c = Skip(c, forwardPeriod) + } + + return c +} diff --git a/helper/sync_test.go b/helper/sync_test.go new file mode 100644 index 0000000..1da4f3b --- /dev/null +++ b/helper/sync_test.go @@ -0,0 +1,33 @@ +// Copyright (c) 2021-2024 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 TestSync(t *testing.T) { + input1 := helper.Skip(helper.SliceToChan([]int{0, 0, 0, 0, 1, 2, 3, 4}), 4) + input2 := helper.Skip(helper.SliceToChan([]int{0, 0, 1, 2, 3, 4, 5, 6}), 2) + input3 := helper.Skip(helper.SliceToChan([]int{0, 0, 0, 1, 2, 3, 4, 5}), 3) + + commonPeriod := helper.CommonPeriod(4, 2, 3) + + actual1 := helper.SyncPeriod(commonPeriod, 4, input1) + expected1 := helper.SliceToChan([]int{1, 2, 3, 4}) + + actual2 := helper.SyncPeriod(commonPeriod, 2, input2) + expected2 := helper.SliceToChan([]int{3, 4, 5, 6}) + + actual3 := helper.SyncPeriod(commonPeriod, 3, input3) + expected3 := helper.SliceToChan([]int{2, 3, 4, 5}) + + err := helper.CheckEquals(actual1, expected1, actual2, expected2, actual3, expected3) + if err != nil { + t.Fatal(err) + } +}