mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
feature: add mean, abs, sum, toArray, and dot operations on series. implement Float64Slice as series
This commit is contained in:
parent
d0c3390f84
commit
339d36d61b
|
@ -41,35 +41,20 @@ type BOLL struct {
|
|||
|
||||
type BandType int
|
||||
|
||||
const (
|
||||
_SMA BandType = iota
|
||||
_StdDev
|
||||
_UpBand
|
||||
_DownBand
|
||||
)
|
||||
|
||||
func (inc *BOLL) GetUpBand() types.Series {
|
||||
return &BollSeries{
|
||||
inc, _UpBand,
|
||||
}
|
||||
return inc.UpBand
|
||||
}
|
||||
|
||||
func (inc *BOLL) GetDownBand() types.Series {
|
||||
return &BollSeries{
|
||||
inc, _DownBand,
|
||||
}
|
||||
return inc.DownBand
|
||||
}
|
||||
|
||||
func (inc *BOLL) GetSMA() types.Series {
|
||||
return &BollSeries{
|
||||
inc, _SMA,
|
||||
}
|
||||
return inc.SMA
|
||||
}
|
||||
|
||||
func (inc *BOLL) GetStdDev() types.Series {
|
||||
return &BollSeries{
|
||||
inc, _StdDev,
|
||||
}
|
||||
return inc.StdDev
|
||||
}
|
||||
|
||||
func (inc *BOLL) LastUpBand() float64 {
|
||||
|
@ -163,67 +148,3 @@ func (inc *BOLL) handleKLineWindowUpdate(interval types.Interval, window types.K
|
|||
func (inc *BOLL) Bind(updater KLineWindowUpdater) {
|
||||
updater.OnKLineWindowUpdate(inc.handleKLineWindowUpdate)
|
||||
}
|
||||
|
||||
type BollSeries struct {
|
||||
*BOLL
|
||||
bandType BandType
|
||||
}
|
||||
|
||||
func (b *BollSeries) Last() float64 {
|
||||
switch b.bandType {
|
||||
case _SMA:
|
||||
return b.LastSMA()
|
||||
case _StdDev:
|
||||
return b.LastStdDev()
|
||||
case _UpBand:
|
||||
return b.LastUpBand()
|
||||
case _DownBand:
|
||||
return b.LastDownBand()
|
||||
default:
|
||||
panic("bandType wrong")
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BollSeries) Index(i int) float64 {
|
||||
switch b.bandType {
|
||||
case _SMA:
|
||||
if len(b.SMA) <= i {
|
||||
return 0
|
||||
}
|
||||
return b.SMA[len(b.SMA)-i-1]
|
||||
case _StdDev:
|
||||
if len(b.StdDev) <= i {
|
||||
return 0
|
||||
}
|
||||
return b.StdDev[len(b.StdDev)-i-1]
|
||||
case _UpBand:
|
||||
if len(b.UpBand) <= i {
|
||||
return 0
|
||||
}
|
||||
return b.UpBand[len(b.UpBand)-i-1]
|
||||
case _DownBand:
|
||||
if len(b.DownBand) <= i {
|
||||
return 0
|
||||
}
|
||||
return b.DownBand[len(b.DownBand)-i-1]
|
||||
default:
|
||||
panic("bandType wrong")
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BollSeries) Length() int {
|
||||
switch b.bandType {
|
||||
case _SMA:
|
||||
return len(b.SMA)
|
||||
case _StdDev:
|
||||
return len(b.StdDev)
|
||||
case _UpBand:
|
||||
return len(b.UpBand)
|
||||
case _DownBand:
|
||||
return len(b.DownBand)
|
||||
default:
|
||||
panic("bandType wrong")
|
||||
}
|
||||
}
|
||||
|
||||
var _ types.Series = &BollSeries{}
|
||||
|
|
|
@ -117,3 +117,23 @@ func (s Float64Slice) ElementwiseProduct(other Float64Slice) Float64Slice {
|
|||
func (s Float64Slice) Dot(other Float64Slice) float64 {
|
||||
return s.ElementwiseProduct(other).Sum()
|
||||
}
|
||||
|
||||
func (a Float64Slice) Last() float64 {
|
||||
if len(a) > 0 {
|
||||
return a[len(a)-1]
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func (a Float64Slice) Index(i int) float64 {
|
||||
if len(a)-i < 0 || i < 0 {
|
||||
return 0.0
|
||||
}
|
||||
return a[len(a)-i-1]
|
||||
}
|
||||
|
||||
func (a Float64Slice) Length() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
var _ Series = Float64Slice([]float64{})
|
||||
|
|
|
@ -29,6 +29,60 @@ type BoolSeries interface {
|
|||
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 := -1
|
||||
if len(limit) > 0 {
|
||||
l = limit[0]
|
||||
}
|
||||
if l < a.Length() {
|
||||
l = a.Length()
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
sum += a.Index(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 := -1
|
||||
if len(limit) > 0 {
|
||||
l = limit[0]
|
||||
}
|
||||
if l < a.Length() {
|
||||
l = a.Length()
|
||||
}
|
||||
return Sum(a, l) / float64(l)
|
||||
}
|
||||
|
||||
type AbsResult struct {
|
||||
a Series
|
||||
}
|
||||
|
||||
func (a *AbsResult) Last() float64 {
|
||||
return math.Abs(a.a.Last())
|
||||
}
|
||||
|
||||
func (a *AbsResult) Index(i int) float64 {
|
||||
return math.Abs(a.a.Index(i))
|
||||
}
|
||||
|
||||
func (a *AbsResult) Length() int {
|
||||
return a.a.Length()
|
||||
}
|
||||
|
||||
// Return series that having all the elements positive
|
||||
func Abs(a Series) Series {
|
||||
return &AbsResult{a}
|
||||
}
|
||||
|
||||
var _ Series = &AbsResult{}
|
||||
|
||||
// This will make prediction using Linear Regression to get the next cross point
|
||||
// Return (offset from latest, crossed value, could cross)
|
||||
// offset from latest should always be positive
|
||||
|
@ -164,28 +218,6 @@ func (a NumberSeries) Length() int {
|
|||
|
||||
var _ Series = NumberSeries(0)
|
||||
|
||||
type Float64ArrSeries []float64
|
||||
|
||||
func (a Float64ArrSeries) Last() float64 {
|
||||
if len(a) > 0 {
|
||||
return a[len(a)-1]
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func (a Float64ArrSeries) Index(i int) float64 {
|
||||
if len(a)-i < 0 || i < 0 {
|
||||
return 0.0
|
||||
}
|
||||
return a[len(a)-i-1]
|
||||
}
|
||||
|
||||
func (a Float64ArrSeries) Length() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
var _ Series = Float64ArrSeries([]float64{})
|
||||
|
||||
type AddSeriesResult struct {
|
||||
a Series
|
||||
b Series
|
||||
|
@ -366,3 +398,28 @@ func (a *MulSeriesResult) Length() int {
|
|||
}
|
||||
|
||||
var _ Series = &MulSeriesResult{}
|
||||
|
||||
// Calculate (a dot b).
|
||||
// if limit is given, will only calculate the first limit numbers (a.Index[0..limit])
|
||||
// otherwise will operate on all elements
|
||||
func Dot(a interface{}, b interface{}, limit ...int) float64 {
|
||||
return Sum(Mul(a, b), 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])
|
||||
// otherwise will operate on all elements
|
||||
func ToArray(a Series, limit ...int) (result []float64) {
|
||||
l := -1
|
||||
if len(limit) > 0 {
|
||||
l = limit[0]
|
||||
}
|
||||
if l < a.Length() {
|
||||
l = a.Length()
|
||||
}
|
||||
result = make([]float64, l, l)
|
||||
for i := 0; i < l; i++ {
|
||||
result[i] = a.Index(i)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ func TestFloat(t *testing.T) {
|
|||
func TestNextCross(t *testing.T) {
|
||||
var a Series = NumberSeries(1.2)
|
||||
|
||||
var b Series = Float64ArrSeries{100., 80., 60.}
|
||||
// index 2 1 0
|
||||
// predicted 40 20 0
|
||||
// offset 1 2 3
|
||||
var b Series = Float64Slice{100., 80., 60.}
|
||||
// index 2 1 0
|
||||
// predicted 40 20 0
|
||||
// offset 1 2 3
|
||||
|
||||
index, value, ok := NextCross(a, b, 3)
|
||||
assert.True(t, ok)
|
||||
|
|
Loading…
Reference in New Issue
Block a user