qbtrade/pkg/types/series.go
2024-06-27 22:42:38 +08:00

124 lines
3.2 KiB
Go

package types
import (
"reflect"
"git.qtrade.icu/lychiyu/qbtrade/pkg/datatype/floats"
)
// The interface maps to pinescript basic type `series`
// Access the internal historical data from the latest to the oldest
// Index(0) always maps to Last()
type Series interface {
Last(i int) float64
Index(i int) float64
Length() int
}
type SeriesExtend interface {
Series
Sum(limit ...int) float64
Mean(limit ...int) float64
Abs() SeriesExtend
Predict(lookback int, offset ...int) float64
NextCross(b Series, lookback int) (int, float64, bool)
CrossOver(b Series) BoolSeries
CrossUnder(b Series) BoolSeries
Highest(lookback int) float64
Lowest(lookback int) float64
Add(b interface{}) SeriesExtend
Minus(b interface{}) SeriesExtend
Div(b interface{}) SeriesExtend
Mul(b interface{}) SeriesExtend
Dot(b interface{}, limit ...int) float64
Array(limit ...int) (result []float64)
Reverse(limit ...int) (result floats.Slice)
Change(offset ...int) SeriesExtend
PercentageChange(offset ...int) SeriesExtend
Stdev(params ...int) float64
Rolling(window int) *RollingResult
Shift(offset int) SeriesExtend
Skew(length int) float64
Variance(length int) float64
Covariance(b Series, length int) float64
Correlation(b Series, length int, method ...CorrFunc) float64
AutoCorrelation(length int, lag ...int) float64
Rank(length int) SeriesExtend
Sigmoid() SeriesExtend
Softmax(window int) SeriesExtend
Entropy(window int) float64
CrossEntropy(b Series, window int) float64
Filter(b func(i int, value float64) bool, length int) SeriesExtend
}
func NewSeries(a Series) SeriesExtend {
return &SeriesBase{
Series: a,
}
}
type UpdatableSeries interface {
Series
Update(float64)
}
type UpdatableSeriesExtend interface {
SeriesExtend
Update(float64)
}
func Clone(u UpdatableSeriesExtend) UpdatableSeriesExtend {
method, ok := reflect.TypeOf(u).MethodByName("Clone")
if ok {
out := method.Func.Call([]reflect.Value{reflect.ValueOf(u)})
return out[0].Interface().(UpdatableSeriesExtend)
}
panic("method Clone not exist")
}
func TestUpdate(u UpdatableSeriesExtend, input float64) UpdatableSeriesExtend {
method, ok := reflect.TypeOf(u).MethodByName("TestUpdate")
if ok {
out := method.Func.Call([]reflect.Value{reflect.ValueOf(u), reflect.ValueOf(input)})
return out[0].Interface().(UpdatableSeriesExtend)
}
panic("method TestUpdate not exist")
}
// The interface maps to pinescript basic type `series` for bool type
// Access the internal historical data from the latest to the oldest
// Index(0) always maps to Last()
type BoolSeries interface {
Last() bool
Index(int) bool
Length() int
}
// Calculate sum of the series
// if limit is given, will only sum first limit numbers (a.Index[0..limit])
// otherwise will sum all elements
func Sum(a Series, limit ...int) (sum float64) {
l := a.Length()
if len(limit) > 0 && limit[0] < l {
l = limit[0]
}
for i := 0; i < l; i++ {
sum += a.Last(i)
}
return sum
}
// Calculate the average value of the series
// if limit is given, will only calculate the average of first limit numbers (a.Index[0..limit])
// otherwise will operate on all elements
func Mean(a Series, limit ...int) (mean float64) {
l := a.Length()
if l == 0 {
return 0
}
if len(limit) > 0 && limit[0] < l {
l = limit[0]
}
return Sum(a, l) / float64(l)
}