bbgo: add ClosedKLineStop trigger

This commit is contained in:
c9s 2022-07-27 11:47:12 +08:00
parent f323e91a56
commit 7438798390
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 50 additions and 3 deletions

View File

@ -72,7 +72,9 @@ func (s *CumulatedVolumeTakeProfit) Bind(session *ExchangeSession, orderExecutor
cqv.Float64(), cqv.Float64(),
s.MinQuoteVolume.Float64(), kline.Close.Float64()) s.MinQuoteVolume.Float64(), kline.Close.Float64())
_ = orderExecutor.ClosePosition(context.Background(), fixedpoint.One, "cumulatedVolumeTakeProfit") if err := orderExecutor.ClosePosition(context.Background(), fixedpoint.One, "cumulatedVolumeTakeProfit") ; err != nil {
log.WithError(err).Errorf("close position error")
}
return return
} }
})) }))

View File

@ -19,6 +19,10 @@ type TrendEMA struct {
types.IntervalWindow types.IntervalWindow
} }
type ClosedKLineStop struct {
types.IntervalWindow
}
// BreakLow -- when price breaks the previous pivot low, we set a trade entry // BreakLow -- when price breaks the previous pivot low, we set a trade entry
type BreakLow struct { type BreakLow struct {
Symbol string Symbol string
@ -42,7 +46,13 @@ type BreakLow struct {
TrendEMA *TrendEMA `json:"trendEMA"` TrendEMA *TrendEMA `json:"trendEMA"`
lastLow fixedpoint.Value ClosedKLineStop *ClosedKLineStop `json:"closedKLineStop"`
lastLow fixedpoint.Value
// lastBreakLow is the low that the price just break
lastBreakLow fixedpoint.Value
pivotLow *indicator.PivotLow pivotLow *indicator.PivotLow
pivotLowPrices []fixedpoint.Value pivotLowPrices []fixedpoint.Value
@ -66,6 +76,10 @@ func (s *BreakLow) Subscribe(session *bbgo.ExchangeSession) {
if s.TrendEMA != nil { if s.TrendEMA != nil {
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.TrendEMA.Interval}) session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.TrendEMA.Interval})
} }
if s.ClosedKLineStop != nil {
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.ClosedKLineStop.Interval})
}
} }
func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.GeneralOrderExecutor) { func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.GeneralOrderExecutor) {
@ -113,7 +127,34 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
} }
})) }))
session.MarketDataStream.OnKLineClosed(types.KLineWith(symbol, types.Interval1m, func(kline types.KLine) { if s.ClosedKLineStop != nil {
// if the position is already opened, and we just break the low, this checks if the kline closed above the low,
// so that we can close the position earlier
session.MarketDataStream.OnKLineClosed(types.KLineWith(s.Symbol, s.ClosedKLineStop.Interval, func(k types.KLine) {
// make sure the position is opened, and it's a short position
if !position.IsOpened(k.Close) || !position.IsShort() {
return
}
// make sure we recorded the last break low
if s.lastBreakLow.IsZero() {
return
}
// the kline opened below the last break low, and closed above the last break low
if k.Open.Compare(s.lastBreakLow) < 0 && k.Close.Compare(s.lastBreakLow) > 0 {
bbgo.Notify("kLine closed above the last break low, triggering stop earlier")
if err := s.orderExecutor.ClosePosition(context.Background(), one, "kLineClosedStop"); err != nil {
log.WithError(err).Error("position close error")
}
// reset to zero
s.lastBreakLow = fixedpoint.Zero
}
}))
}
session.MarketDataStream.OnKLineClosed(types.KLineWith(s.Symbol, types.Interval1m, func(kline types.KLine) {
if len(s.pivotLowPrices) == 0 { if len(s.pivotLowPrices) == 0 {
log.Infof("currently there is no pivot low prices, can not check break low...") log.Infof("currently there is no pivot low prices, can not check break low...")
return return
@ -146,6 +187,10 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
log.Infof("%s breakLow signal detected, closed price %f < breakPrice %f", kline.Symbol, closePrice.Float64(), breakPrice.Float64()) log.Infof("%s breakLow signal detected, closed price %f < breakPrice %f", kline.Symbol, closePrice.Float64(), breakPrice.Float64())
if s.lastBreakLow.IsZero() || previousLow.Compare(s.lastBreakLow) < 0 {
s.lastBreakLow = previousLow
}
if position.IsOpened(kline.Close) { if position.IsOpened(kline.Close) {
log.Infof("position is already opened, skip short") log.Infof("position is already opened, skip short")
return return