bbgo_origin/pkg/bbgo/standard_indicator_set.go
2022-07-21 01:32:09 +08:00

135 lines
3.5 KiB
Go

package bbgo
import (
"github.com/sirupsen/logrus"
"github.com/c9s/bbgo/pkg/indicator"
"github.com/c9s/bbgo/pkg/types"
"github.com/c9s/bbgo/pkg/util"
)
var (
debugEWMA = false
debugSMA = false
debugBOLL = false
)
func init() {
// when using --dotenv option, the dotenv is loaded from command.PersistentPreRunE, not init.
// hence here the env var won't enable the debug flag
util.SetEnvVarBool("DEBUG_EWMA", &debugEWMA)
util.SetEnvVarBool("DEBUG_SMA", &debugSMA)
util.SetEnvVarBool("DEBUG_BOLL", &debugBOLL)
}
type StandardIndicatorSet struct {
Symbol string
// Standard indicators
// interval -> window
sma map[types.IntervalWindow]*indicator.SMA
ewma map[types.IntervalWindow]*indicator.EWMA
boll map[types.IntervalWindowBandWidth]*indicator.BOLL
stoch map[types.IntervalWindow]*indicator.STOCH
stream types.Stream
store *MarketDataStore
}
func NewStandardIndicatorSet(symbol string, stream types.Stream, store *MarketDataStore) *StandardIndicatorSet {
return &StandardIndicatorSet{
Symbol: symbol,
sma: make(map[types.IntervalWindow]*indicator.SMA),
ewma: make(map[types.IntervalWindow]*indicator.EWMA),
boll: make(map[types.IntervalWindowBandWidth]*indicator.BOLL),
stoch: make(map[types.IntervalWindow]*indicator.STOCH),
store: store,
stream: stream,
}
}
// BOLL returns the bollinger band indicator of the given interval, the window and bandwidth
func (set *StandardIndicatorSet) BOLL(iw types.IntervalWindow, bandWidth float64) *indicator.BOLL {
iwb := types.IntervalWindowBandWidth{IntervalWindow: iw, BandWidth: bandWidth}
inc, ok := set.boll[iwb]
if !ok {
inc = &indicator.BOLL{IntervalWindow: iw, K: bandWidth}
if klines, ok := set.store.KLinesOfInterval(iw.Interval); ok {
inc.LoadK(*klines)
}
if debugBOLL {
inc.OnUpdate(func(sma float64, upBand float64, downBand float64) {
logrus.Infof("%s BOLL %s: sma=%f up=%f down=%f", set.Symbol, iw.String(), sma, upBand, downBand)
})
}
inc.BindK(set.stream, set.Symbol, iw.Interval)
set.boll[iwb] = inc
}
return inc
}
// SMA returns the simple moving average indicator of the given interval and the window size.
func (set *StandardIndicatorSet) SMA(iw types.IntervalWindow) *indicator.SMA {
inc, ok := set.sma[iw]
if !ok {
inc = &indicator.SMA{IntervalWindow: iw}
if klines, ok := set.store.KLinesOfInterval(iw.Interval); ok {
inc.LoadK(*klines)
}
if debugSMA {
inc.OnUpdate(func(value float64) {
logrus.Infof("%s SMA %s: %f", set.Symbol, iw.String(), value)
})
}
inc.BindK(set.stream, set.Symbol, iw.Interval)
set.sma[iw] = inc
}
return inc
}
// EWMA returns the exponential weighed moving average indicator of the given interval and the window size.
func (set *StandardIndicatorSet) EWMA(iw types.IntervalWindow) *indicator.EWMA {
inc, ok := set.ewma[iw]
if !ok {
inc = &indicator.EWMA{IntervalWindow: iw}
if klines, ok := set.store.KLinesOfInterval(iw.Interval); ok {
inc.LoadK(*klines)
}
if debugEWMA {
inc.OnUpdate(func(value float64) {
logrus.Infof("%s EWMA %s: value=%f", set.Symbol, iw.String(), value)
})
}
inc.BindK(set.stream, set.Symbol, iw.Interval)
set.ewma[iw] = inc
}
return inc
}
func (set *StandardIndicatorSet) STOCH(iw types.IntervalWindow) *indicator.STOCH {
inc, ok := set.stoch[iw]
if !ok {
inc = &indicator.STOCH{IntervalWindow: iw}
if klines, ok := set.store.KLinesOfInterval(iw.Interval); ok {
inc.LoadK(*klines)
}
inc.BindK(set.stream, set.Symbol, iw.Interval)
set.stoch[iw] = inc
}
return inc
}