bbgo_origin/pkg/bbgo/standard_indicator_set.go

139 lines
4.1 KiB
Go
Raw Normal View History

2022-07-20 17:04:49 +00:00
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 (
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_BOLL", &debugBOLL)
}
type StandardIndicatorSet struct {
Symbol string
2022-07-26 09:56:31 +00:00
2022-07-20 17:04:49 +00:00
// Standard indicators
// interval -> window
2022-07-26 09:56:31 +00:00
boll map[types.IntervalWindowBandWidth]*indicator.BOLL
stoch map[types.IntervalWindow]*indicator.STOCH
simples map[types.IntervalWindow]indicator.KLinePusher
2022-07-20 17:04:49 +00:00
stream types.Stream
store *MarketDataStore
}
func NewStandardIndicatorSet(symbol string, stream types.Stream, store *MarketDataStore) *StandardIndicatorSet {
return &StandardIndicatorSet{
2022-07-26 09:56:31 +00:00
Symbol: symbol,
store: store,
stream: stream,
simples: make(map[types.IntervalWindow]indicator.KLinePusher),
2022-07-26 09:56:31 +00:00
boll: make(map[types.IntervalWindowBandWidth]*indicator.BOLL),
stoch: make(map[types.IntervalWindow]*indicator.STOCH),
2022-07-20 17:04:49 +00:00
}
}
func (s *StandardIndicatorSet) initAndBind(inc indicator.KLinePusher, iw types.IntervalWindow) {
if klines, ok := s.store.KLinesOfInterval(iw.Interval); ok {
2022-07-26 09:56:31 +00:00
for _, k := range *klines {
inc.PushK(k)
2022-07-20 17:04:49 +00:00
}
2022-07-26 09:56:31 +00:00
}
2022-07-20 17:04:49 +00:00
s.stream.OnKLineClosed(types.KLineWith(s.Symbol, iw.Interval, inc.PushK))
2022-07-26 09:56:31 +00:00
}
2022-07-20 17:04:49 +00:00
func (s *StandardIndicatorSet) allocateSimpleIndicator(t indicator.KLinePusher, iw types.IntervalWindow) indicator.KLinePusher {
inc, ok := s.simples[iw]
2022-07-26 09:56:31 +00:00
if ok {
return inc
2022-07-20 17:04:49 +00:00
}
2022-07-26 09:56:31 +00:00
inc = t
s.initAndBind(inc, iw)
s.simples[iw] = inc
2022-07-26 09:56:31 +00:00
return t
2022-07-20 17:04:49 +00:00
}
2022-07-26 09:56:31 +00:00
// SMA is a helper function that returns the simple moving average indicator of the given interval and the window size.
func (s *StandardIndicatorSet) SMA(iw types.IntervalWindow) *indicator.SMA {
inc := s.allocateSimpleIndicator(&indicator.SMA{IntervalWindow: iw}, iw)
2022-07-26 09:56:31 +00:00
return inc.(*indicator.SMA)
2022-07-20 17:04:49 +00:00
}
2022-07-26 09:56:31 +00:00
// EWMA is a helper function that returns the exponential weighed moving average indicator of the given interval and the window size.
func (s *StandardIndicatorSet) EWMA(iw types.IntervalWindow) *indicator.EWMA {
inc := s.allocateSimpleIndicator(&indicator.EWMA{IntervalWindow: iw}, iw)
2022-07-26 09:56:31 +00:00
return inc.(*indicator.EWMA)
}
2022-07-20 17:04:49 +00:00
func (s *StandardIndicatorSet) PivotLow(iw types.IntervalWindow) *indicator.PivotLow {
inc := s.allocateSimpleIndicator(&indicator.PivotLow{IntervalWindow: iw}, iw)
2022-07-26 09:56:31 +00:00
return inc.(*indicator.PivotLow)
}
2022-07-20 17:04:49 +00:00
func (s *StandardIndicatorSet) ATR(iw types.IntervalWindow) *indicator.ATR {
inc := s.allocateSimpleIndicator(&indicator.ATR{IntervalWindow: iw}, iw)
return inc.(*indicator.ATR)
}
func (s *StandardIndicatorSet) ATRP(iw types.IntervalWindow) *indicator.ATRP {
inc := s.allocateSimpleIndicator(&indicator.ATRP{IntervalWindow: iw}, iw)
return inc.(*indicator.ATRP)
}
func (s *StandardIndicatorSet) EMV(iw types.IntervalWindow) *indicator.EMV {
2022-07-26 10:04:57 +00:00
inc := s.allocateSimpleIndicator(&indicator.EMV{IntervalWindow: iw}, iw)
return inc.(*indicator.EMV)
}
2022-07-26 10:04:57 +00:00
func (s *StandardIndicatorSet) CCI(iw types.IntervalWindow) *indicator.CCI {
inc := s.allocateSimpleIndicator(&indicator.CCI{IntervalWindow: iw}, iw)
return inc.(*indicator.CCI)
}
func (s *StandardIndicatorSet) HULL(iw types.IntervalWindow) *indicator.HULL {
inc := s.allocateSimpleIndicator(&indicator.HULL{IntervalWindow: iw}, iw)
return inc.(*indicator.HULL)
}
func (s *StandardIndicatorSet) STOCH(iw types.IntervalWindow) *indicator.STOCH {
inc, ok := s.stoch[iw]
2022-07-26 09:56:31 +00:00
if !ok {
inc = &indicator.STOCH{IntervalWindow: iw}
s.initAndBind(inc, iw)
s.stoch[iw] = inc
2022-07-20 17:04:49 +00:00
}
return inc
}
2022-07-26 09:56:31 +00:00
// BOLL returns the bollinger band indicator of the given interval, the window and bandwidth
func (s *StandardIndicatorSet) BOLL(iw types.IntervalWindow, bandWidth float64) *indicator.BOLL {
2022-07-26 09:56:31 +00:00
iwb := types.IntervalWindowBandWidth{IntervalWindow: iw, BandWidth: bandWidth}
inc, ok := s.boll[iwb]
2022-07-20 17:04:49 +00:00
if !ok {
2022-07-26 09:56:31 +00:00
inc = &indicator.BOLL{IntervalWindow: iw, K: bandWidth}
s.initAndBind(inc, iw)
2022-07-20 17:04:49 +00:00
2022-07-26 09:56:31 +00:00
if debugBOLL {
inc.OnUpdate(func(sma float64, upBand float64, downBand float64) {
logrus.Infof("%s BOLL %s: sma=%f up=%f down=%f", s.Symbol, iw.String(), sma, upBand, downBand)
2022-07-26 09:56:31 +00:00
})
2022-07-20 17:04:49 +00:00
}
s.boll[iwb] = inc
2022-07-20 17:04:49 +00:00
}
return inc
}