Skip to content

Commit

Permalink
indicator: clean up and update calculator method names
Browse files Browse the repository at this point in the history
  • Loading branch information
c9s committed Jul 14, 2022
1 parent c27f416 commit 2a3118a
Show file tree
Hide file tree
Showing 44 changed files with 291 additions and 173 deletions.
8 changes: 4 additions & 4 deletions pkg/bbgo/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type StandardIndicatorSet struct {
ewma map[types.IntervalWindow]*indicator.EWMA
boll map[types.IntervalWindowBandWidth]*indicator.BOLL
stoch map[types.IntervalWindow]*indicator.STOCH
volatility map[types.IntervalWindow]*indicator.VOLATILITY
volatility map[types.IntervalWindow]*indicator.Volatility

store *MarketDataStore
}
Expand All @@ -55,7 +55,7 @@ func NewStandardIndicatorSet(symbol string, store *MarketDataStore) *StandardInd
ewma: make(map[types.IntervalWindow]*indicator.EWMA),
boll: make(map[types.IntervalWindowBandWidth]*indicator.BOLL),
stoch: make(map[types.IntervalWindow]*indicator.STOCH),
volatility: make(map[types.IntervalWindow]*indicator.VOLATILITY),
volatility: make(map[types.IntervalWindow]*indicator.Volatility),
store: store,
}

Expand Down Expand Up @@ -146,10 +146,10 @@ func (set *StandardIndicatorSet) STOCH(iw types.IntervalWindow) *indicator.STOCH
}

// VOLATILITY returns the volatility(stddev) indicator of the given interval and the window size.
func (set *StandardIndicatorSet) VOLATILITY(iw types.IntervalWindow) *indicator.VOLATILITY {
func (set *StandardIndicatorSet) VOLATILITY(iw types.IntervalWindow) *indicator.Volatility {
inc, ok := set.volatility[iw]
if !ok {
inc = &indicator.VOLATILITY{IntervalWindow: iw}
inc = &indicator.Volatility{IntervalWindow: iw}
inc.Bind(set.store)
set.volatility[iw] = inc
}
Expand Down
14 changes: 8 additions & 6 deletions pkg/indicator/cci.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package indicator
import (
"math"

"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)

Expand Down Expand Up @@ -79,17 +78,20 @@ func (inc *CCI) Length() int {

var _ types.SeriesExtend = &CCI{}

var three = fixedpoint.NewFromInt(3)

func (inc *CCI) calculateAndUpdate(allKLines []types.KLine) {
func (inc *CCI) PushK(k types.KLine) {
inc.Update(k.High.Add(k.Low).Add(k.Close).Div(three).Float64())
}

func (inc *CCI) CalculateAndUpdate(allKLines []types.KLine) {
if inc.TypicalPrice.Length() == 0 {
for _, k := range allKLines {
inc.Update(k.High.Add(k.Low).Add(k.Close).Div(three).Float64())
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
} else {
k := allKLines[len(allKLines)-1]
inc.Update(k.High.Add(k.Low).Add(k.Close).Div(three).Float64())
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
}
Expand All @@ -99,7 +101,7 @@ func (inc *CCI) handleKLineWindowUpdate(interval types.Interval, window types.KL
return
}

inc.calculateAndUpdate(window)
inc.CalculateAndUpdate(window)
}

func (inc *CCI) Bind(updater KLineWindowUpdater) {
Expand Down
10 changes: 7 additions & 3 deletions pkg/indicator/cma.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ func (inc *CA) Length() int {

var _ types.SeriesExtend = &CA{}

func (inc *CA) calculateAndUpdate(allKLines []types.KLine) {
func (inc *CA) PushK(k types.KLine) {
inc.Update(k.Close.Float64())
}

func (inc *CA) CalculateAndUpdate(allKLines []types.KLine) {
for _, k := range allKLines {
inc.Update(k.Close.Float64())
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
}
Expand All @@ -60,7 +64,7 @@ func (inc *CA) handleKLineWindowUpdate(interval types.Interval, window types.KLi
return
}

inc.calculateAndUpdate(window)
inc.CalculateAndUpdate(window)
}

func (inc *CA) Bind(updater KLineWindowUpdater) {
Expand Down
12 changes: 12 additions & 0 deletions pkg/indicator/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package indicator

import (
"time"

"github.com/c9s/bbgo/pkg/fixedpoint"
)

var three = fixedpoint.NewFromInt(3)

var zeroTime = time.Time{}

10 changes: 8 additions & 2 deletions pkg/indicator/dema.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,20 @@ func (inc *DEMA) Length() int {

var _ types.SeriesExtend = &DEMA{}

func (inc *DEMA) PushK(k types.KLine) {
inc.Update(k.Close.Float64())
}

func (inc *DEMA) calculateAndUpdate(allKLines []types.KLine) {
if inc.a1 == nil {
for _, k := range allKLines {
inc.Update(k.Close.Float64())
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
} else {
inc.Update(allKLines[len(allKLines)-1].Close.Float64())
// last k
k := allKLines[len(allKLines)-1]
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
}
Expand Down
13 changes: 9 additions & 4 deletions pkg/indicator/drift.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,19 @@ func (inc *Drift) Length() int {

var _ types.SeriesExtend = &Drift{}

func (inc *Drift) calculateAndUpdate(allKLines []types.KLine) {
func (inc *Drift) PushK(k types.KLine) {
inc.Update(k.Close.Float64())
}

func (inc *Drift) CalculateAndUpdate(allKLines []types.KLine) {
if inc.chng == nil {
for _, k := range allKLines {
inc.Update(k.Close.Float64())
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
} else {
inc.Update(allKLines[len(allKLines)-1].Close.Float64())
k := allKLines[len(allKLines)-1]
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
}
Expand All @@ -85,7 +90,7 @@ func (inc *Drift) handleKLineWindowUpdate(interval types.Interval, window types.
return
}

inc.calculateAndUpdate(window)
inc.CalculateAndUpdate(window)
}

func (inc *Drift) Bind(updater KLineWindowUpdater) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/indicator/drift_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func Test_Drift(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
drift := Drift{IntervalWindow: types.IntervalWindow{Window: 3}}
drift.calculateAndUpdate(tt.kLines)
drift.CalculateAndUpdate(tt.kLines)
assert.Equal(t, drift.Length(), tt.all)
for _, v := range drift.Values {
assert.LessOrEqual(t, v, 1.0)
Expand Down
12 changes: 8 additions & 4 deletions pkg/indicator/emv.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,21 @@ func (inc *EMV) Length() int {

var _ types.SeriesExtend = &EMV{}

func (inc *EMV) calculateAndUpdate(allKLines []types.KLine) {
func (inc *EMV) PushK(k types.KLine) {
inc.Update(k.High.Float64(), k.Low.Float64(), k.Volume.Float64())
}

func (inc *EMV) CalculateAndUpdate(allKLines []types.KLine) {
if inc.Values == nil {
for _, k := range allKLines {
inc.Update(k.High.Float64(), k.Low.Float64(), k.Volume.Float64())
inc.PushK(k)
if inc.Length() > 0 {
inc.EmitUpdate(inc.Last())
}
}
} else {
k := allKLines[len(allKLines)-1]
inc.Update(k.High.Float64(), k.Low.Float64(), k.Volume.Float64())
inc.PushK(k)
inc.EmitUpdate(inc.Last())
}
}
Expand All @@ -82,7 +86,7 @@ func (inc *EMV) handleKLineWindowUpdate(interval types.Interval, window types.KL
if inc.Interval != interval {
return
}
inc.calculateAndUpdate(window)
inc.CalculateAndUpdate(window)
}

func (inc *EMV) Bind(updater KLineWindowUpdater) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/indicator/inf.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ type KLineWindowUpdater interface {
type KLineCloseHandler interface {
OnKLineClosed(func(k types.KLine))
}

// KLinePusher provides an interface for API user to push kline value to the indicator.
// The indicator implements its own way to calculate the value from the given kline object.
type KLinePusher interface {
PushK(k types.KLine)
}

type KLineCalculator interface {
CalculateAndUpdate(allKLines []types.KLine)
}
5 changes: 3 additions & 2 deletions pkg/indicator/line.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ type Line struct {
Interval types.Interval
}

func (l *Line) handleKLineWindowUpdate(interval types.Interval, window types.KLineWindow) {
func (l *Line) handleKLineWindowUpdate(interval types.Interval, allKLines types.KLineWindow) {
if interval != l.Interval {
return
}
newTime := window.Last().EndTime.Time()

newTime := allKLines.Last().EndTime.Time()
delta := int(newTime.Sub(l.currentTime).Minutes()) / l.Interval.Minutes()
l.startIndex += delta
l.endIndex += delta
Expand Down
17 changes: 12 additions & 5 deletions pkg/indicator/macd.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,20 @@ func (inc *MACD) Update(x float64) {
inc.Histogram.Push(macd - inc.SignalLine.Last())
}

// Deprecated -- this function is not used ??? ask @narumi
func (inc *MACD) calculateMACD(kLines []types.KLine, priceF KLinePriceMapper) float64 {
for _, kline := range kLines {
inc.Update(kline.Close.Float64())
for _, k := range kLines {
inc.PushK(k)
}

return inc.Values[len(inc.Values)-1]
}

func (inc *MACD) calculateAndUpdate(kLines []types.KLine) {
func (inc *MACD) PushK(k types.KLine) {
inc.Update(k.Close.Float64())
}

func (inc *MACD) CalculateAndUpdate(kLines []types.KLine) {
if len(kLines) == 0 {
return
}
Expand All @@ -67,7 +73,8 @@ func (inc *MACD) calculateAndUpdate(kLines []types.KLine) {
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
continue
}
inc.Update(k.Close.Float64())

inc.PushK(k)
}

inc.EmitUpdate(inc.Values[len(inc.Values)-1])
Expand All @@ -79,7 +86,7 @@ func (inc *MACD) handleKLineWindowUpdate(interval types.Interval, window types.K
return
}

inc.calculateAndUpdate(window)
inc.CalculateAndUpdate(window)
}

func (inc *MACD) Bind(updater KLineWindowUpdater) {
Expand Down
33 changes: 33 additions & 0 deletions pkg/indicator/mapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package indicator

import "github.com/c9s/bbgo/pkg/types"

type KLinePriceMapper func(k types.KLine) float64

func KLineOpenPriceMapper(k types.KLine) float64 {
return k.Open.Float64()
}

func KLineClosePriceMapper(k types.KLine) float64 {
return k.Close.Float64()
}

func KLineTypicalPriceMapper(k types.KLine) float64 {
return (k.High.Float64() + k.Low.Float64() + k.Close.Float64()) / 3.
}

func KLinePriceVolumeMapper(k types.KLine) float64 {
return k.Close.Mul(k.Volume).Float64()
}

func KLineVolumeMapper(k types.KLine) float64 {
return k.Volume.Float64()
}

func MapKLinePrice(kLines []types.KLine, f KLinePriceMapper) (prices []float64) {
for _, k := range kLines {
prices = append(prices, f(k))
}

return prices
}
12 changes: 9 additions & 3 deletions pkg/indicator/obv.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,19 @@ func (inc *OBV) Index(i int) float64 {

var _ types.SeriesExtend = &OBV{}

func (inc *OBV) calculateAndUpdate(kLines []types.KLine) {
func (inc *OBV) PushK(k types.KLine) {
inc.Update(k.Close.Float64(), k.Volume.Float64())
}

func (inc *OBV) CalculateAndUpdate(kLines []types.KLine) {
for _, k := range kLines {
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
continue
}
inc.Update(k.Close.Float64(), k.Volume.Float64())

inc.PushK(k)
}

inc.EmitUpdate(inc.Last())
inc.EndTime = kLines[len(kLines)-1].EndTime.Time()
}
Expand All @@ -70,7 +76,7 @@ func (inc *OBV) handleKLineWindowUpdate(interval types.Interval, window types.KL
return
}

inc.calculateAndUpdate(window)
inc.CalculateAndUpdate(window)
}

func (inc *OBV) Bind(updater KLineWindowUpdater) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/indicator/obv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func Test_calculateOBV(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
obv := OBV{IntervalWindow: types.IntervalWindow{Window: tt.window}}
obv.calculateAndUpdate(tt.kLines)
obv.CalculateAndUpdate(tt.kLines)
assert.Equal(t, len(obv.Values), len(tt.want))
for i, v := range obv.Values {
assert.InDelta(t, v, tt.want[i], Delta)
Expand Down
4 changes: 2 additions & 2 deletions pkg/indicator/pivot.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (inc *Pivot) LastHigh() float64 {
return inc.Highs[len(inc.Highs)-1]
}

func (inc *Pivot) Update(klines []types.KLine) {
func (inc *Pivot) CalculateAndUpdate(klines []types.KLine) {
if len(klines) < inc.Window {
return
}
Expand Down Expand Up @@ -84,7 +84,7 @@ func (inc *Pivot) handleKLineWindowUpdate(interval types.Interval, window types.
return
}

inc.Update(window)
inc.CalculateAndUpdate(window)
}

func (inc *Pivot) Bind(updater KLineWindowUpdater) {
Expand Down
7 changes: 6 additions & 1 deletion pkg/indicator/rma.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,17 @@ func (inc *RMA) Length() int {

var _ types.SeriesExtend = &RMA{}

func (inc *RMA) PushK(k types.KLine) {
inc.Update(k.Close.Float64())
}

func (inc *RMA) calculateAndUpdate(kLines []types.KLine) {
for _, k := range kLines {
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
continue
}
inc.Update(k.Close.Float64())

inc.PushK(k)
}

inc.EmitUpdate(inc.Last())
Expand Down
Loading

0 comments on commit 2a3118a

Please sign in to comment.