diff --git a/README.md b/README.md
index eafef9f..da772db 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ The following list of indicators are currently supported by this package:
- [Moving Sum](trend/README.md#type-movingsum)
- Parabolic SAR
- [Random Index (KDJ)](trend/README.md#type-kdj)
-- Rolling Moving Average (RMA)
+- [Rolling Moving Average (RMA)](trend/README.md#type-rma)
- [Simple Moving Average (SMA)](trend/README.md#type-sma)
- [Since Change](helper/README.md#func-since)
- [Triple Exponential Moving Average (TEMA)](trend/README.md#type-tema)
diff --git a/trend/README.md b/trend/README.md
index 8ae3a60..1b71ad7 100644
--- a/trend/README.md
+++ b/trend/README.md
@@ -62,6 +62,9 @@ The information provided on this project is strictly for informational purposes
- [type MovingSum](<#MovingSum>)
- [func NewMovingSum\[T helper.Number\]\(\) \*MovingSum\[T\]](<#NewMovingSum>)
- [func \(m \*MovingSum\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#MovingSum[T].Compute>)
+- [type Rma](<#Rma>)
+ - [func NewRma\[T helper.Number\]\(\) \*Rma\[T\]](<#NewRma>)
+ - [func \(rma \*Rma\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#Rma[T].Compute>)
- [type Sma](<#Sma>)
- [func NewSma\[T helper.Number\]\(\) \*Sma\[T\]](<#NewSma>)
- [func \(s \*Sma\[T\]\) Compute\(c \<\-chan T\) \<\-chan T](<#Sma[T].Compute>)
@@ -169,6 +172,15 @@ const (
)
```
+
+
+```go
+const (
+ // DefaultRmaPeriod is the default RMA period.
+ DefaultRmaPeriod = 20
+)
+```
+
```go
@@ -685,6 +697,50 @@ func (m *MovingSum[T]) Compute(c <-chan T) <-chan T
Compute function takes a channel of numbers and computes the Moving Sum over the specified period.
+
+## type [Rma]()
+
+Rma represents the parameters for calculating Rolling Moving Average \(RMA\).
+
+```
+R[0] to R[p-1] is SMA(values)
+R[p] and after is R[i] = ((R[i-1]*(p-1)) + v[i]) / p
+```
+
+Example:
+
+```
+rma := trend.NewRma[float64]()
+rma.Period = 10
+
+result := rma.Compute(c)
+```
+
+```go
+type Rma[T helper.Number] struct {
+ // Time period.
+ Period int
+}
+```
+
+
+### func [NewRma]()
+
+```go
+func NewRma[T helper.Number]() *Rma[T]
+```
+
+NewRma function initializes a new RMA instance with the default parameters.
+
+
+### func \(\*Rma\[T\]\) [Compute]()
+
+```go
+func (rma *Rma[T]) Compute(c <-chan T) <-chan T
+```
+
+Compute function takes a channel of numbers and computes the RMA over the specified period.
+
## type [Sma]()
diff --git a/trend/rma.go b/trend/rma.go
new file mode 100644
index 0000000..c5b42e9
--- /dev/null
+++ b/trend/rma.go
@@ -0,0 +1,58 @@
+// Copyright (c) 2021-2023 Onur Cinar.
+// The source code is provided under GNU AGPLv3 License.
+// https://github.com/cinar/indicator
+
+package trend
+
+import "github.com/cinar/indicator/helper"
+
+const (
+ // DefaultRmaPeriod is the default RMA period.
+ DefaultRmaPeriod = 20
+)
+
+// Rma represents the parameters for calculating Rolling Moving Average (RMA).
+//
+// R[0] to R[p-1] is SMA(values)
+// R[p] and after is R[i] = ((R[i-1]*(p-1)) + v[i]) / p
+//
+// Example:
+//
+// rma := trend.NewRma[float64]()
+// rma.Period = 10
+//
+// result := rma.Compute(c)
+type Rma[T helper.Number] struct {
+ // Time period.
+ Period int
+}
+
+// NewRma function initializes a new RMA instance with the default parameters.
+func NewRma[T helper.Number]() *Rma[T] {
+ return &Rma[T]{
+ Period: DefaultRmaPeriod,
+ }
+}
+
+// Compute function takes a channel of numbers and computes the RMA over the specified period.
+func (rma *Rma[T]) Compute(c <-chan T) <-chan T {
+ result := make(chan T, cap(c))
+
+ go func() {
+ defer close(result)
+
+ // Initial RMA value is the SMA.
+ sma := NewSma[T]()
+ sma.Period = rma.Period
+
+ before := <-sma.Compute(helper.Head(c, rma.Period))
+ result <- before
+
+ for n := range c {
+ before = ((before * T(rma.Period-1)) + n) / T(rma.Period)
+ result <- before
+ }
+ }()
+
+ return result
+}
diff --git a/trend/rma_test.go b/trend/rma_test.go
new file mode 100644
index 0000000..4e5fa9a
--- /dev/null
+++ b/trend/rma_test.go
@@ -0,0 +1,41 @@
+// Copyright (c) 2021-2023 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/helper"
+ "github.com/cinar/indicator/trend"
+)
+
+func TestRma(t *testing.T) {
+ type Data struct {
+ Close float64
+ Rma float64
+ }
+
+ input, err := helper.ReadFromCsvFile[Data]("testdata/rma.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.Rma })
+
+ rma := trend.NewRma[float64]()
+ rma.Period = 15
+
+ actual := rma.Compute(closing)
+ actual = helper.RoundDigits(actual, 2)
+
+ expected = helper.Skip(expected, rma.Period-1)
+
+ err = helper.CheckEquals(actual, expected)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/trend/testdata/rma.csv b/trend/testdata/rma.csv
new file mode 100644
index 0000000..d8fbb98
--- /dev/null
+++ b/trend/testdata/rma.csv
@@ -0,0 +1,252 @@
+Close,Rma
+318.600006,0
+315.839996,0
+316.149994,0
+310.570007,0
+307.779999,0
+305.820007,0
+305.98999,0
+306.390015,0
+311.450012,0
+312.329987,0
+309.290009,0
+301.910004,0
+300,0
+300.029999,0
+302,308.28
+307.820007,308.25
+302.690002,307.88
+306.48999,307.78
+305.549988,307.63
+303.429993,307.35
+309.059998,307.47
+308.899994,307.56
+309.910004,307.72
+314.549988,308.18
+312.899994,308.49
+318.690002,309.17
+315.529999,309.59
+316.350006,310.04
+320.369995,310.73
+318.929993,311.28
+317.640015,311.7
+314.859985,311.91
+308.299988,311.67
+305.230011,311.24
+309.869995,311.15
+310.420013,311.1
+311.299988,311.12
+311.899994,311.17
+310.950012,311.15
+309.170013,311.02
+307.329987,310.78
+311.519989,310.83
+310.570007,310.81
+311.859985,310.88
+308.51001,310.72
+308.429993,310.57
+312.970001,310.73
+308.480011,310.58
+307.209991,310.35
+309.890015,310.32
+313.73999,310.55
+310.790009,310.57
+309.630005,310.5
+308.179993,310.35
+308.23999,310.21
+302.720001,309.71
+303.160004,309.27
+303.070007,308.86
+304.019989,308.54
+304.660004,308.28
+305.179993,308.07
+304.619995,307.84
+307.75,307.84
+312.450012,308.14
+316.970001,308.73
+311.119995,308.89
+311.369995,309.06
+304.820007,308.77
+303.630005,308.43
+302.880005,308.06
+305.329987,307.88
+297.880005,307.21
+302.01001,306.87
+293.51001,305.97
+301.059998,305.65
+303.850006,305.53
+299.730011,305.14
+298.369995,304.69
+298.920013,304.3
+302.140015,304.16
+302.320007,304.04
+305.299988,304.12
+305.079987,304.19
+308.769989,304.49
+310.309998,304.88
+309.070007,305.16
+310.390015,305.51
+312.51001,305.97
+312.619995,306.42
+313.700012,306.9
+314.549988,307.41
+318.049988,308.12
+319.73999,308.9
+323.790009,309.89
+324.630005,310.87
+323.089996,311.69
+323.820007,312.5
+324.329987,313.28
+326.049988,314.14
+324.339996,314.82
+320.529999,315.2
+326.230011,315.93
+328.549988,316.77
+330.170013,317.67
+325.859985,318.21
+323.220001,318.55
+320,318.64
+323.880005,318.99
+326.140015,319.47
+324.869995,319.83
+322.98999,320.04
+322.640015,320.21
+322.48999,320.36
+323.529999,320.58
+323.75,320.79
+327.390015,321.23
+329.76001,321.8
+330.390015,322.37
+329.130005,322.82
+323.109985,322.84
+320.200012,322.66
+319.019989,322.42
+320.600006,322.3
+322.190002,322.29
+321.079987,322.21
+323.119995,322.27
+329.480011,322.75
+328.579987,323.14
+333.410004,323.83
+335.420013,324.6
+335.950012,325.36
+335.290009,326.02
+333.600006,326.52
+336.390015,327.18
+335.899994,327.76
+339.820007,328.57
+338.309998,329.22
+338.670013,329.85
+338.609985,330.43
+336.959991,330.87
+335.25,331.16
+334.119995,331.36
+335.339996,331.62
+334.149994,331.79
+336.910004,332.13
+341,332.72
+342,333.34
+341.559998,333.89
+341.459991,334.39
+340.899994,334.83
+341.130005,335.25
+343.369995,335.79
+345.350006,336.43
+343.540009,336.9
+341.089996,337.18
+344.25,337.65
+345.339996,338.16
+342.429993,338.45
+346.609985,338.99
+345.76001,339.44
+349.630005,340.12
+347.579987,340.62
+349.799988,341.23
+349.309998,341.77
+349.809998,342.31
+351.959991,342.95
+352.26001,343.57
+351.190002,344.08
+353.809998,344.73
+349.98999,345.08
+362.579987,346.24
+363.730011,347.41
+358.019989,348.12
+356.980011,348.71
+358.350006,349.35
+358.480011,349.96
+354.5,350.26
+354.109985,350.52
+353.190002,350.7
+352.559998,350.82
+352.089996,350.91
+350.570007,350.88
+354.26001,351.11
+354.299988,351.32
+355.929993,351.63
+355.549988,351.89
+358.290009,352.32
+361.059998,352.9
+360.200012,353.39
+362.459991,353.99
+360.470001,354.42
+361.670013,354.91
+361.799988,355.37
+363.149994,355.88
+365.519989,356.53
+367.779999,357.28
+367.820007,357.98
+369.5,358.75
+367.859985,359.36
+370.429993,360.09
+370.480011,360.79
+366.820007,361.19
+363.279999,361.33
+360.160004,361.25
+361.709991,361.28
+359.420013,361.16
+357.779999,360.93
+357.059998,360.67
+350.299988,359.98
+348.079987,359.19
+343.040009,358.11
+343.690002,357.15
+345.059998,356.34
+346.339996,355.68
+345.450012,355
+348.559998,354.57
+348.429993,354.16
+345.660004,353.59
+345.089996,353.02
+346.230011,352.57
+345.390015,352.09
+340.890015,351.35
+338.660004,350.5
+335.859985,349.52
+336.839996,348.68
+338.630005,348.01
+336.899994,347.27
+336.160004,346.53
+331.709991,345.54
+337.410004,345
+341.329987,344.75
+343.75,344.69
+349.019989,344.98
+351.809998,345.43
+346.630005,345.51
+346.170013,345.55
+346.299988,345.6
+348.179993,345.78
+350.559998,346.1
+350.01001,346.36
+354.25,346.88
+356.790009,347.54
+359.859985,348.36
+358.929993,349.07
+361.329987,349.89
+361,350.63
+361.799988,351.37
+362.679993,352.13
+361.339996,352.74
+360.049988,353.23
+358.690002,353.59