Skip to content

Commit

Permalink
fix: series not been updated
Browse files Browse the repository at this point in the history
  • Loading branch information
zenixls2 committed Apr 11, 2022
1 parent be0755d commit af61952
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 82 deletions.
21 changes: 11 additions & 10 deletions pkg/bbgo/marketdatastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,26 @@ type MarketDataStore struct {
Symbol string

// KLineWindows stores all loaded klines per interval
KLineWindows map[types.Interval]types.KLineWindow `json:"-"`
KLineWindows map[types.Interval]*types.KLineWindow `json:"-"`

kLineWindowUpdateCallbacks []func(interval types.Interval, kline types.KLineWindow)
kLineWindowUpdateCallbacks []func(interval types.Interval, klines types.KLineWindow)
}

func NewMarketDataStore(symbol string) *MarketDataStore {
return &MarketDataStore{
Symbol: symbol,

// KLineWindows stores all loaded klines per interval
KLineWindows: make(map[types.Interval]types.KLineWindow, len(types.SupportedIntervals)), // 12 interval, 1m,5m,15m,30m,1h,2h,4h,6h,12h,1d,3d,1w
KLineWindows: make(map[types.Interval]*types.KLineWindow, len(types.SupportedIntervals)), // 12 interval, 1m,5m,15m,30m,1h,2h,4h,6h,12h,1d,3d,1w
}
}

func (store *MarketDataStore) SetKLineWindows(windows map[types.Interval]types.KLineWindow) {
func (store *MarketDataStore) SetKLineWindows(windows map[types.Interval]*types.KLineWindow) {
store.KLineWindows = windows
}

// KLinesOfInterval returns the kline window of the given interval
func (store *MarketDataStore) KLinesOfInterval(interval types.Interval) (kLines types.KLineWindow, ok bool) {
func (store *MarketDataStore) KLinesOfInterval(interval types.Interval) (kLines *types.KLineWindow, ok bool) {
kLines, ok = store.KLineWindows[interval]
return kLines, ok
}
Expand All @@ -50,14 +50,15 @@ func (store *MarketDataStore) handleKLineClosed(kline types.KLine) {
func (store *MarketDataStore) AddKLine(kline types.KLine) {
window, ok := store.KLineWindows[kline.Interval]
if !ok {
window = make(types.KLineWindow, 0, 1000)
var tmp = make(types.KLineWindow, 0, 1000)
store.KLineWindows[kline.Interval] = &tmp
window = &tmp
}
window.Add(kline)

if len(window) > MaxNumOfKLines {
window = window[MaxNumOfKLinesTruncate-1:]
if len(*window) > MaxNumOfKLines {
*window = (*window)[MaxNumOfKLinesTruncate-1:]
}

store.KLineWindows[kline.Interval] = window
store.EmitKLineWindowUpdate(kline.Interval, window)
store.EmitKLineWindowUpdate(kline.Interval, *window)
}
6 changes: 3 additions & 3 deletions pkg/bbgo/marketdatastore_callbacks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pkg/indicator/boll.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ type BOLL struct {
type BandType int

func (inc *BOLL) GetUpBand() types.Series {
return inc.UpBand
return &inc.UpBand
}

func (inc *BOLL) GetDownBand() types.Series {
return inc.DownBand
return &inc.DownBand
}

func (inc *BOLL) GetSMA() types.Series {
return inc.SMA
return &inc.SMA
}

func (inc *BOLL) GetStdDev() types.Series {
return inc.StdDev
return &inc.StdDev
}

func (inc *BOLL) LastUpBand() float64 {
Expand Down
10 changes: 10 additions & 0 deletions pkg/indicator/sma.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ func (inc *SMA) Length() int {

var _ types.Series = &SMA{}

func (inc *SMA) Update(value float64) {
length := len(inc.Values)
if length == 0 {
inc.Values = append(inc.Values, value)
return
}
newVal := (inc.Values[length-1]*float64(inc.Window-1) + value) / float64(inc.Window)
inc.Values = append(inc.Values, newVal)
}

func (inc *SMA) calculateAndUpdate(kLines []types.KLine) {
if len(kLines) < inc.Window {
return
Expand Down
4 changes: 2 additions & 2 deletions pkg/indicator/stoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ func (inc *STOCH) Bind(updater KLineWindowUpdater) {
}

func (inc *STOCH) GetD() types.Series {
return inc.D
return &inc.D
}

func (inc *STOCH) GetK() types.Series {
return inc.K
return &inc.K
}
24 changes: 15 additions & 9 deletions pkg/types/float_slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,22 +118,28 @@ 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]
func (a *Float64Slice) Last() float64 {
length := len(*a)
if length > 0 {
return (*a)[length-1]
}
return 0.0
}

func (a Float64Slice) Index(i int) float64 {
if len(a)-i < 0 || i < 0 {
func (a *Float64Slice) Index(i int) float64 {
length := len(*a)
if length-i < 0 || i < 0 {
return 0.0
}
return a[len(a)-i-1]
return (*a)[length-i-1]
}

func (a Float64Slice) Length() int {
return len(a)
func (a *Float64Slice) Length() int {
return len(*a)
}

var _ Series = Float64Slice([]float64{})
func (a Float64Slice) Addr() *Float64Slice {
return &a
}

var _ Series = Float64Slice([]float64{}).Addr()
141 changes: 104 additions & 37 deletions pkg/types/indicator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package types

import (
"fmt"
"math"
"reflect"

"gonum.org/v1/gonum/stat"
)
Expand Down Expand Up @@ -83,6 +85,25 @@ func Abs(a Series) Series {

var _ Series = &AbsResult{}

func Predict(a Series, lookback int, offset ...int) float64 {
if a.Length() < lookback {
lookback = a.Length()
}
x := make([]float64, lookback, lookback)
y := make([]float64, lookback, lookback)
var weights []float64
for i := 0; i < lookback; i++ {
x[i] = float64(i)
y[i] = a.Index(i)
}
alpha, beta := stat.LinearRegression(x, y, weights, false)
o := -1.0
if len(offset) > 0 {
o = -float64(offset[0])
}
return alpha + beta*o
}

// 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
Expand All @@ -96,14 +117,14 @@ func NextCross(a Series, b Series, lookback int) (int, float64, bool) {
if b.Length() < lookback {
lookback = b.Length()
}
x := make([]float64, 0, lookback)
y1 := make([]float64, 0, lookback)
y2 := make([]float64, 0, lookback)
x := make([]float64, lookback, lookback)
y1 := make([]float64, lookback, lookback)
y2 := make([]float64, lookback, lookback)
var weights []float64
for i := 0; i < lookback; i++ {
x = append(x, float64(i))
y1 = append(y1, a.Index(i))
y2 = append(y2, b.Index(i))
x[i] = float64(i)
y1[i] = a.Index(i)
y2[i] = b.Index(i)
}
alpha1, beta1 := stat.LinearRegression(x, y1, weights, false)
alpha2, beta2 := stat.LinearRegression(x, y2, weights, false)
Expand Down Expand Up @@ -233,12 +254,18 @@ func Add(a interface{}, b interface{}) Series {
aa = NumberSeries(a.(float64))
case Series:
aa = a.(Series)
default:
panic("input should be either *Series or float64")

}
switch b.(type) {
case float64:
bb = NumberSeries(b.(float64))
case Series:
bb = b.(Series)
default:
panic("input should be either *Series or float64")

}
return &AddSeriesResult{aa, bb}
}
Expand Down Expand Up @@ -269,21 +296,8 @@ type MinusSeriesResult struct {

// Minus two series, result[i] = a[i] - b[i]
func Minus(a interface{}, b interface{}) Series {
var aa Series
var bb Series

switch a.(type) {
case float64:
aa = NumberSeries(a.(float64))
case Series:
aa = a.(Series)
}
switch b.(type) {
case float64:
bb = NumberSeries(b.(float64))
case Series:
bb = b.(Series)
}
aa := switchIface(a)
bb := switchIface(b)
return &MinusSeriesResult{aa, bb}
}

Expand All @@ -306,26 +320,34 @@ func (a *MinusSeriesResult) Length() int {

var _ Series = &MinusSeriesResult{}

// Divid two series, result[i] = a[i] / b[i]
func Div(a interface{}, b interface{}) Series {
var aa Series
var bb Series

switch a.(type) {
case float64:
aa = NumberSeries(a.(float64))
case Series:
aa = a.(Series)
}
func switchIface(b interface{}) Series {
switch b.(type) {
case float64:
bb = NumberSeries(b.(float64))
if 0 == bb.Last() {
panic("Divid by zero exception")
}
return NumberSeries(b.(float64))
case int32:
return NumberSeries(float64(b.(int32)))
case int64:
return NumberSeries(float64(b.(int64)))
case float32:
return NumberSeries(float64(b.(float32)))
case int:
return NumberSeries(float64(b.(int)))
case Series:
bb = b.(Series)
return b.(Series)
default:
fmt.Println(reflect.TypeOf(b))
panic("input should be either *Series or float64")

}
}

// Divid two series, result[i] = a[i] / b[i]
func Div(a interface{}, b interface{}) Series {
aa := switchIface(a)
if 0 == b {
panic("Divid by zero exception")
}
bb := switchIface(b)
return &DivSeriesResult{aa, bb}

}
Expand Down Expand Up @@ -364,12 +386,17 @@ func Mul(a interface{}, b interface{}) Series {
aa = NumberSeries(a.(float64))
case Series:
aa = a.(Series)
default:
panic("input should be either Series or float64")
}
switch b.(type) {
case float64:
bb = NumberSeries(b.(float64))
case Series:
bb = b.(Series)
default:
panic("input should be either Series or float64")

}
return &MulSeriesResult{aa, bb}

Expand Down Expand Up @@ -443,3 +470,43 @@ func ToReverseArray(a Series, limit ...int) (result Float64Slice) {
}
return
}

type ChangeResult struct {
a Series
offset int
}

func (c *ChangeResult) Last() float64 {
if c.offset >= c.a.Length() {
return 0
}
return c.a.Last() - c.a.Index(c.offset)
}

func (c *ChangeResult) Index(i int) float64 {
if i+c.offset >= c.a.Length() {
return 0
}
return c.a.Index(i) - c.a.Index(i+c.offset)
}

func (c *ChangeResult) Length() int {
length := c.a.Length()
if length >= c.offset {
return length - c.offset
}
return 0
}

// Difference between current value and previous, a - a[offset]
// offset: if not given, offset is 1.
func Change(a Series, offset ...int) Series {
o := 1
if len(offset) == 0 {
o = offset[0]
}

return &ChangeResult{a, o}
}

// TODO: ta.linreg
11 changes: 10 additions & 1 deletion pkg/types/indicator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestFloat(t *testing.T) {
func TestNextCross(t *testing.T) {
var a Series = NumberSeries(1.2)

var b Series = Float64Slice{100., 80., 60.}
var b Series = &Float64Slice{100., 80., 60.}
// index 2 1 0
// predicted 40 20 0
// offset 1 2 3
Expand All @@ -24,3 +24,12 @@ func TestNextCross(t *testing.T) {
assert.Equal(t, value, 1.2)
assert.Equal(t, index, 3) // 2.94, ceil
}

func TestFloat64Slice(t *testing.T) {
var a = Float64Slice{1.0, 2.0, 3.0}
var b = Float64Slice{1.0, 2.0, 3.0}
var c Series = Minus(&a, &b)
a = append(a, 4.0)
b = append(b, 3.0)
assert.Equal(t, c.Last(), 1.)
}
Loading

0 comments on commit af61952

Please sign in to comment.