Merge pull request #778 from zenixls2/feature/series_extend

feature: add seriesExtend
This commit is contained in:
Zenix 2022-06-29 12:35:48 +09:00 committed by GitHub
commit 6b6686caa8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 145 additions and 20 deletions

View File

@ -266,7 +266,7 @@ func (s *Strategy) SetupIndicators(store *bbgo.MarketDataStore) {
return return
} }
if ema5.Length() == 0 { if ema5.Length() == 0 {
closes := types.ToReverseArray(getSource(window)) closes := types.Reverse(getSource(window))
for _, cloze := range closes { for _, cloze := range closes {
ema5.Update(cloze) ema5.Update(cloze)
ema34.Update(cloze) ema34.Update(cloze)
@ -289,7 +289,7 @@ func (s *Strategy) SetupIndicators(store *bbgo.MarketDataStore) {
return return
} }
if sma5.Length() == 0 { if sma5.Length() == 0 {
closes := types.ToReverseArray(getSource(window)) closes := types.Reverse(getSource(window))
for _, cloze := range closes { for _, cloze := range closes {
sma5.Update(cloze) sma5.Update(cloze)
sma34.Update(cloze) sma34.Update(cloze)
@ -347,7 +347,7 @@ func (s *Strategy) SetupIndicators(store *bbgo.MarketDataStore) {
if sig.Length() == 0 { if sig.Length() == 0 {
// lazy init // lazy init
ewoVals := types.ToReverseArray(s.ewo) ewoVals := types.Reverse(s.ewo)
for _, ewoValue := range ewoVals { for _, ewoValue := range ewoVals {
sig.Update(ewoValue) sig.Update(ewoValue)
} }
@ -365,7 +365,7 @@ func (s *Strategy) SetupIndicators(store *bbgo.MarketDataStore) {
if sig.Length() == 0 { if sig.Length() == 0 {
// lazy init // lazy init
ewoVals := types.ToReverseArray(s.ewo) ewoVals := types.Reverse(s.ewo)
for _, ewoValue := range ewoVals { for _, ewoValue := range ewoVals {
sig.Update(ewoValue) sig.Update(ewoValue)
} }
@ -385,7 +385,7 @@ func (s *Strategy) SetupIndicators(store *bbgo.MarketDataStore) {
} }
if sig.Length() == 0 { if sig.Length() == 0 {
// lazy init // lazy init
ewoVals := types.ToReverseArray(s.ewo) ewoVals := types.Reverse(s.ewo)
for i, ewoValue := range ewoVals { for i, ewoValue := range ewoVals {
vol := window.Volume().Index(i) vol := window.Volume().Index(i)
sig.PV.Update(ewoValue * vol) sig.PV.Update(ewoValue * vol)

View File

@ -63,6 +63,46 @@ type Series interface {
Length() int 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 Float64Slice)
Change(offset ...int) SeriesExtend
Stdev(length int) float64
}
type IndexFuncType func(int) float64
type LastFuncType func() float64
type LengthFuncType func() int
type SeriesBase struct {
index IndexFuncType
last LastFuncType
length LengthFuncType
}
func NewSeries(a Series) SeriesExtend {
return &SeriesBase{
index: a.Index,
last: a.Last,
length: a.Length,
}
}
type UpdatableSeries interface { type UpdatableSeries interface {
Series Series
Update(float64) Update(float64)
@ -125,8 +165,8 @@ func (a *AbsResult) Length() int {
} }
// Return series that having all the elements positive // Return series that having all the elements positive
func Abs(a Series) Series { func Abs(a Series) SeriesExtend {
return &AbsResult{a} return NewSeries(&AbsResult{a})
} }
var _ Series = &AbsResult{} var _ Series = &AbsResult{}
@ -291,7 +331,7 @@ type AddSeriesResult struct {
} }
// Add two series, result[i] = a[i] + b[i] // Add two series, result[i] = a[i] + b[i]
func Add(a interface{}, b interface{}) Series { func Add(a interface{}, b interface{}) SeriesExtend {
var aa Series var aa Series
var bb Series var bb Series
@ -313,7 +353,7 @@ func Add(a interface{}, b interface{}) Series {
panic("input should be either *Series or float64") panic("input should be either *Series or float64")
} }
return &AddSeriesResult{aa, bb} return NewSeries(&AddSeriesResult{aa, bb})
} }
func (a *AddSeriesResult) Last() float64 { func (a *AddSeriesResult) Last() float64 {
@ -341,10 +381,10 @@ type MinusSeriesResult struct {
} }
// Minus two series, result[i] = a[i] - b[i] // Minus two series, result[i] = a[i] - b[i]
func Minus(a interface{}, b interface{}) Series { func Minus(a interface{}, b interface{}) SeriesExtend {
aa := switchIface(a) aa := switchIface(a)
bb := switchIface(b) bb := switchIface(b)
return &MinusSeriesResult{aa, bb} return NewSeries(&MinusSeriesResult{aa, bb})
} }
func (a *MinusSeriesResult) Last() float64 { func (a *MinusSeriesResult) Last() float64 {
@ -388,13 +428,13 @@ func switchIface(b interface{}) Series {
} }
// Divid two series, result[i] = a[i] / b[i] // Divid two series, result[i] = a[i] / b[i]
func Div(a interface{}, b interface{}) Series { func Div(a interface{}, b interface{}) SeriesExtend {
aa := switchIface(a) aa := switchIface(a)
if 0 == b { if 0 == b {
panic("Divid by zero exception") panic("Divid by zero exception")
} }
bb := switchIface(b) bb := switchIface(b)
return &DivSeriesResult{aa, bb} return NewSeries(&DivSeriesResult{aa, bb})
} }
@ -423,7 +463,7 @@ func (a *DivSeriesResult) Length() int {
var _ Series = &DivSeriesResult{} var _ Series = &DivSeriesResult{}
// Multiple two series, result[i] = a[i] * b[i] // Multiple two series, result[i] = a[i] * b[i]
func Mul(a interface{}, b interface{}) Series { func Mul(a interface{}, b interface{}) SeriesExtend {
var aa Series var aa Series
var bb Series var bb Series
@ -444,7 +484,7 @@ func Mul(a interface{}, b interface{}) Series {
panic("input should be either Series or float64") panic("input should be either Series or float64")
} }
return &MulSeriesResult{aa, bb} return NewSeries(&MulSeriesResult{aa, bb})
} }
@ -482,7 +522,7 @@ func Dot(a interface{}, b interface{}, limit ...int) float64 {
// Extract elements from the Series to a float64 array, following the order of Index(0..limit) // Extract elements from the Series to a float64 array, following the order of Index(0..limit)
// if limit is given, will only take the first limit numbers (a.Index[0..limit]) // if limit is given, will only take the first limit numbers (a.Index[0..limit])
// otherwise will operate on all elements // otherwise will operate on all elements
func ToArray(a Series, limit ...int) (result []float64) { func Array(a Series, limit ...int) (result []float64) {
l := -1 l := -1
if len(limit) > 0 { if len(limit) > 0 {
l = limit[0] l = limit[0]
@ -497,12 +537,12 @@ func ToArray(a Series, limit ...int) (result []float64) {
return return
} }
// Similar to ToArray but in reverse order. // Similar to Array but in reverse order.
// Useful when you want to cache series' calculated result as float64 array // Useful when you want to cache series' calculated result as float64 array
// the then reuse the result in multiple places (so that no recalculation will be triggered) // the then reuse the result in multiple places (so that no recalculation will be triggered)
// //
// notice that the return type is a Float64Slice, which implements the Series interface // notice that the return type is a Float64Slice, which implements the Series interface
func ToReverseArray(a Series, limit ...int) (result Float64Slice) { func Reverse(a Series, limit ...int) (result Float64Slice) {
l := -1 l := -1
if len(limit) > 0 { if len(limit) > 0 {
l = limit[0] l = limit[0]
@ -546,13 +586,13 @@ func (c *ChangeResult) Length() int {
// Difference between current value and previous, a - a[offset] // Difference between current value and previous, a - a[offset]
// offset: if not given, offset is 1. // offset: if not given, offset is 1.
func Change(a Series, offset ...int) Series { func Change(a Series, offset ...int) SeriesExtend {
o := 1 o := 1
if len(offset) > 0 { if len(offset) > 0 {
o = offset[0] o = offset[0]
} }
return &ChangeResult{a, o} return NewSeries(&ChangeResult{a, o})
} }
func Stdev(a Series, length int) float64 { func Stdev(a Series, length int) float64 {

View File

@ -0,0 +1,85 @@
package types
func (s *SeriesBase) Index(i int) float64 {
return s.index(i)
}
func (s *SeriesBase) Last() float64 {
return s.last()
}
func (s *SeriesBase) Length() int {
return s.length()
}
func (s *SeriesBase) Sum(limit ...int) float64 {
return Sum(s, limit...)
}
func (s *SeriesBase) Mean(limit ...int) float64 {
return Mean(s, limit...)
}
func (s *SeriesBase) Abs() SeriesExtend {
return Abs(s)
}
func (s *SeriesBase) Predict(lookback int, offset ...int) float64 {
return Predict(s, lookback, offset...)
}
func (s *SeriesBase) NextCross(b Series, lookback int) (int, float64, bool) {
return NextCross(s, b, lookback)
}
func (s *SeriesBase) CrossOver(b Series) BoolSeries {
return CrossOver(s, b)
}
func (s *SeriesBase) CrossUnder(b Series) BoolSeries {
return CrossUnder(s, b)
}
func (s *SeriesBase) Highest(lookback int) float64 {
return Highest(s, lookback)
}
func (s *SeriesBase) Lowest(lookback int) float64 {
return Lowest(s, lookback)
}
func (s *SeriesBase) Add(b interface{}) SeriesExtend {
return Add(s, b)
}
func (s *SeriesBase) Minus(b interface{}) SeriesExtend {
return Minus(s, b)
}
func (s *SeriesBase) Div(b interface{}) SeriesExtend {
return Div(s, b)
}
func (s *SeriesBase) Mul(b interface{}) SeriesExtend {
return Mul(s, b)
}
func (s *SeriesBase) Dot(b interface{}, limit ...int) float64 {
return Dot(s, b, limit...)
}
func (s *SeriesBase) Array(limit ...int) (result []float64) {
return Array(s, limit...)
}
func (s *SeriesBase) Reverse(limit ...int) (result Float64Slice) {
return Reverse(s, limit...)
}
func (s *SeriesBase) Change(offset ...int) SeriesExtend {
return Change(s, offset...)
}
func (s *SeriesBase) Stdev(length int) float64 {
return Stdev(s, length)
}