2023-07-10 08:54:22 +00:00
|
|
|
package indicatorv2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/c9s/bbgo/pkg/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
const MaxNumOfRMA = 1000
|
|
|
|
const MaxNumOfRMATruncateSize = 500
|
2023-05-30 03:35:24 +00:00
|
|
|
|
|
|
|
type RMAStream struct {
|
|
|
|
// embedded structs
|
2023-07-10 08:54:22 +00:00
|
|
|
*types.Float64Series
|
2023-05-30 03:35:24 +00:00
|
|
|
|
|
|
|
// config fields
|
|
|
|
Adjust bool
|
|
|
|
|
2023-05-30 04:29:50 +00:00
|
|
|
window int
|
2023-05-30 04:13:55 +00:00
|
|
|
counter int
|
|
|
|
sum, previous float64
|
2023-05-30 03:35:24 +00:00
|
|
|
}
|
|
|
|
|
2023-07-10 08:54:22 +00:00
|
|
|
func RMA2(source types.Float64Source, window int, adjust bool) *RMAStream {
|
2023-05-30 03:35:24 +00:00
|
|
|
s := &RMAStream{
|
2023-07-10 08:54:22 +00:00
|
|
|
Float64Series: types.NewFloat64Series(),
|
2023-05-30 04:29:50 +00:00
|
|
|
window: window,
|
|
|
|
Adjust: adjust,
|
2023-05-30 03:35:24 +00:00
|
|
|
}
|
|
|
|
|
2023-05-31 23:58:58 +00:00
|
|
|
s.Bind(source, s)
|
2023-05-30 03:35:24 +00:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2023-05-31 23:58:58 +00:00
|
|
|
func (s *RMAStream) Calculate(x float64) float64 {
|
2023-05-30 04:29:50 +00:00
|
|
|
lambda := 1 / float64(s.window)
|
2023-05-30 04:13:55 +00:00
|
|
|
tmp := 0.0
|
2023-05-30 03:35:24 +00:00
|
|
|
if s.counter == 0 {
|
|
|
|
s.sum = 1
|
2023-05-30 04:13:55 +00:00
|
|
|
tmp = x
|
2023-05-30 03:35:24 +00:00
|
|
|
} else {
|
|
|
|
if s.Adjust {
|
|
|
|
s.sum = s.sum*(1-lambda) + 1
|
2023-05-30 04:13:55 +00:00
|
|
|
tmp = s.previous + (x-s.previous)/s.sum
|
2023-05-30 03:35:24 +00:00
|
|
|
} else {
|
2023-05-30 04:13:55 +00:00
|
|
|
tmp = s.previous*(1-lambda) + x*lambda
|
2023-05-30 03:35:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
s.counter++
|
|
|
|
|
2023-05-30 04:29:50 +00:00
|
|
|
if s.counter < s.window {
|
2023-05-30 04:13:55 +00:00
|
|
|
// we can use x, but we need to use 0. to make the same behavior as the result from python pandas_ta
|
2023-07-10 08:54:22 +00:00
|
|
|
s.Slice.Push(0)
|
2023-05-30 03:35:24 +00:00
|
|
|
}
|
|
|
|
|
2023-07-10 08:54:22 +00:00
|
|
|
s.Slice.Push(tmp)
|
2023-05-30 04:13:55 +00:00
|
|
|
s.previous = tmp
|
|
|
|
|
|
|
|
return tmp
|
|
|
|
}
|
2023-05-30 03:35:24 +00:00
|
|
|
|
2023-05-31 23:58:58 +00:00
|
|
|
func (s *RMAStream) Truncate() {
|
2023-07-10 08:54:22 +00:00
|
|
|
if len(s.Slice) > MaxNumOfRMA {
|
|
|
|
s.Slice = s.Slice[MaxNumOfRMATruncateSize-1:]
|
2023-05-30 03:35:24 +00:00
|
|
|
}
|
|
|
|
}
|