bbgo_origin/pkg/indicator/v2/rma.go

65 lines
1.1 KiB
Go
Raw Normal View History

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
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
}
s.Bind(source, s)
2023-05-30 03:35:24 +00:00
return s
}
func (s *RMAStream) Calculate(x float64) float64 {
2023-05-30 04:29:50 +00:00
lambda := 1 / float64(s.window)
tmp := 0.0
2023-05-30 03:35:24 +00:00
if s.counter == 0 {
s.sum = 1
tmp = x
2023-05-30 03:35:24 +00:00
} else {
if s.Adjust {
s.sum = s.sum*(1-lambda) + 1
tmp = s.previous + (x-s.previous)/s.sum
2023-05-30 03:35:24 +00:00
} else {
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 {
// 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)
s.previous = tmp
return tmp
}
2023-05-30 03:35:24 +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
}
}