-
-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Describe Request Added support for Smoothed Moving Average (SMMA). Fixed #246 # Change Type New Indicator. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced the Smoothed Moving Average (SMMA) indicator to enhance trend analysis capabilities. - Added documentation for the SMMA indicator in the README file. - **Tests** - Implemented a new test suite to validate the functionality of the SMMA computation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
Showing
5 changed files
with
464 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright (c) 2021-2024 Onur Cinar. | ||
// The source code is provided under GNU AGPLv3 License. | ||
// https://github.com/cinar/indicator | ||
|
||
package trend | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cinar/indicator/v2/helper" | ||
) | ||
|
||
const ( | ||
// DefaultSmmaPeriod is the default SMMA period of 7. | ||
DefaultSmmaPeriod = 7 | ||
) | ||
|
||
// Smma represents the parameters for calculating the Smoothed Moving Average (SMMA). | ||
// | ||
// SMMA[0] = SMA(N) | ||
// SMMA[i] = ((SMMA[i-1] * (N - 1)) + Close[i]) / N | ||
// | ||
// Example: | ||
// | ||
// smma := trend.NewSmma[float64]() | ||
// smma.Period = 10 | ||
// | ||
// result := smma.Compute(c) | ||
type Smma[T helper.Number] struct { | ||
// Time period. | ||
Period int | ||
} | ||
|
||
// NewSmma function initializes a new SMMA instance with the default parameters. | ||
func NewSmma[T helper.Number]() *Smma[T] { | ||
return NewSmmaWithPeriod[T](DefaultSmmaPeriod) | ||
} | ||
|
||
// NewSmmaWithPeriod function initializes a new SMMA instance with the given period. | ||
func NewSmmaWithPeriod[T helper.Number](period int) *Smma[T] { | ||
return &Smma[T]{ | ||
Period: period, | ||
} | ||
} | ||
|
||
// Compute function takes a channel of numbers and computes the SMMA over the specified period. | ||
func (s *Smma[T]) Compute(c <-chan T) <-chan T { | ||
result := make(chan T, cap(c)) | ||
|
||
go func() { | ||
defer close(result) | ||
|
||
// Initial SMMA value is the SMA. | ||
sma := NewSmaWithPeriod[T](s.Period) | ||
|
||
before := <-sma.Compute(helper.Head(c, s.Period)) | ||
result <- before | ||
|
||
for n := range c { | ||
before = ((before * (T(s.Period) - 1)) + n) / T(s.Period) | ||
result <- before | ||
} | ||
}() | ||
|
||
return result | ||
} | ||
|
||
// IdlePeriod is the initial period that SMMA yield any results. | ||
func (s *Smma[T]) IdlePeriod() int { | ||
return s.Period - 1 | ||
} | ||
|
||
// String is the string representation of the SMMA. | ||
func (s *Smma[T]) String() string { | ||
return fmt.Sprintf("SMMA(%d)", s.Period) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) 2021-2024 Onur Cinar. | ||
// The source code is provided under GNU AGPLv3 License. | ||
// https://github.com/cinar/indicator | ||
|
||
package trend_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/cinar/indicator/v2/helper" | ||
"github.com/cinar/indicator/v2/trend" | ||
) | ||
|
||
func TestSmma(t *testing.T) { | ||
type Data struct { | ||
Close float64 | ||
Smma float64 | ||
} | ||
|
||
input, err := helper.ReadFromCsvFile[Data]("testdata/smma.csv", true) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
inputs := helper.Duplicate(input, 2) | ||
closing := helper.Map(inputs[0], func(d *Data) float64 { return d.Close }) | ||
expected := helper.Map(inputs[1], func(d *Data) float64 { return d.Smma }) | ||
|
||
smma := trend.NewSmma[float64]() | ||
|
||
actual := smma.Compute(closing) | ||
actual = helper.RoundDigits(actual, 2) | ||
|
||
expected = helper.Skip(expected, smma.IdlePeriod()) | ||
|
||
err = helper.CheckEquals(actual, expected) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
func TestSmmaString(t *testing.T) { | ||
expected := "SMMA(10)" | ||
actual := trend.NewSmmaWithPeriod[float64](10).String() | ||
|
||
if actual != expected { | ||
t.Fatalf("actual %v expected %v", actual, expected) | ||
} | ||
} |
Oops, something went wrong.