diff --git a/pkg/indicator/ema.go b/pkg/indicator/ewma.go similarity index 90% rename from pkg/indicator/ema.go rename to pkg/indicator/ewma.go index 0a5b368267..d3e06044fb 100644 --- a/pkg/indicator/ema.go +++ b/pkg/indicator/ewma.go @@ -6,10 +6,13 @@ import ( "github.com/c9s/bbgo/pkg/types" ) +//go:generate callbackgen -type EWMA type EWMA struct { types.IntervalWindow - Values Float64Slice - EndTime time.Time + Values Float64Slice + EndTime time.Time + + UpdateCallbacks []func(value float64) } func (inc *EWMA) Last() float64 { @@ -32,18 +35,20 @@ func (inc *EWMA) calculateAndUpdate(kLines []types.KLine) { return } + inc.EndTime = kLines[index].EndTime + var recentK = kLines[index-(inc.Window-1) : index+1] if len(inc.Values) > 0 { var previousEWMA = inc.Values[len(inc.Values)-1] var ewma = lastK.Close*multiplier + previousEWMA*(1-multiplier) inc.Values.Push(ewma) + inc.EmitUpdate(ewma) } else { // The first EWMA is actually SMA var sma = calculateSMA(recentK) inc.Values.Push(sma) + inc.EmitUpdate(sma) } - - inc.EndTime = kLines[index].EndTime } type KLineWindowUpdater interface { diff --git a/pkg/indicator/ewma_callbacks.go b/pkg/indicator/ewma_callbacks.go new file mode 100644 index 0000000000..a0458ee7c4 --- /dev/null +++ b/pkg/indicator/ewma_callbacks.go @@ -0,0 +1,15 @@ +// Code generated by "callbackgen -type EWMA"; DO NOT EDIT. + +package indicator + +import () + +func (inc *EWMA) OnUpdate(cb func(value float64)) { + inc.UpdateCallbacks = append(inc.UpdateCallbacks, cb) +} + +func (inc *EWMA) EmitUpdate(value float64) { + for _, cb := range inc.UpdateCallbacks { + cb(value) + } +} diff --git a/pkg/indicator/sma.go b/pkg/indicator/sma.go index 10901a0755..256e0d7de5 100644 --- a/pkg/indicator/sma.go +++ b/pkg/indicator/sma.go @@ -14,10 +14,14 @@ func (s *Float64Slice) Push(v float64) { var zeroTime time.Time + +//go:generate callbackgen -type SMA type SMA struct { types.IntervalWindow Values Float64Slice EndTime time.Time + + UpdateCallbacks []func(value float64) } func (inc *SMA) Last() float64 { @@ -40,6 +44,8 @@ func (inc *SMA) calculateAndUpdate(kLines []types.KLine) { var sma = calculateSMA(recentK) inc.Values.Push(sma) inc.EndTime = kLines[index].EndTime + + inc.EmitUpdate(sma) } func (inc *SMA) handleKLineWindowUpdate(interval types.Interval, window types.KLineWindow) { diff --git a/pkg/indicator/sma_callbacks.go b/pkg/indicator/sma_callbacks.go new file mode 100644 index 0000000000..cdf26e618e --- /dev/null +++ b/pkg/indicator/sma_callbacks.go @@ -0,0 +1,15 @@ +// Code generated by "callbackgen -type SMA"; DO NOT EDIT. + +package indicator + +import () + +func (inc *SMA) OnUpdate(cb func(value float64)) { + inc.UpdateCallbacks = append(inc.UpdateCallbacks, cb) +} + +func (inc *SMA) EmitUpdate(value float64) { + for _, cb := range inc.UpdateCallbacks { + cb(value) + } +} diff --git a/pkg/strategy/movingstop/strategy.go b/pkg/strategy/movingstop/strategy.go index 7e03935dde..a998fa2429 100644 --- a/pkg/strategy/movingstop/strategy.go +++ b/pkg/strategy/movingstop/strategy.go @@ -141,6 +141,8 @@ func (s *Strategy) place(ctx context.Context, orderExecutor *bbgo.ExchangeOrderE stopPrice = stopPrice * s.StopPriceRatio.Float64() } + log.Infof("placing movingstop order %s at stop price %f, quantity %f", s.Symbol, stopPrice, quantity.Float64()) + retOrders, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ Symbol: s.Symbol, Side: types.SideTypeSell,