Skip to content

Commit 2816e42

Browse files
authored
Merge pull request #787 from c9s/strategy/pivotshort
strategy: pivotshort: use active orderbook to maintain the resistance orders
2 parents c8a4af9 + a4af477 commit 2816e42

File tree

2 files changed

+31
-23
lines changed

2 files changed

+31
-23
lines changed

pkg/bbgo/order_executor_general.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ func (e *GeneralOrderExecutor) Bind() {
8686
e.tradeCollector.BindStream(e.session.UserDataStream)
8787
}
8888

89+
// CancelOrders cancels the given order objects directly
8990
func (e *GeneralOrderExecutor) CancelOrders(ctx context.Context, orders ...types.Order) error {
90-
err := e.session.Exchange.CancelOrders(ctx, orders...)
91-
return err
91+
return e.session.Exchange.CancelOrders(ctx, orders...)
9292
}
9393

9494
func (e *GeneralOrderExecutor) SubmitOrders(ctx context.Context, submitOrders ...types.SubmitOrder) (types.OrderSlice, error) {
@@ -108,8 +108,9 @@ func (e *GeneralOrderExecutor) SubmitOrders(ctx context.Context, submitOrders ..
108108
return createdOrders, err
109109
}
110110

111-
func (e *GeneralOrderExecutor) GracefulCancel(ctx context.Context) error {
112-
if err := e.activeMakerOrders.GracefulCancel(ctx, e.session.Exchange); err != nil {
111+
// GracefulCancelActiveOrderBook cancels the orders from the active orderbook.
112+
func (e *GeneralOrderExecutor) GracefulCancelActiveOrderBook(ctx context.Context, activeOrders *ActiveOrderBook) error {
113+
if err := activeOrders.GracefulCancel(ctx, e.session.Exchange); err != nil {
113114
log.WithError(err).Errorf("graceful cancel order error")
114115
return err
115116
}
@@ -118,6 +119,11 @@ func (e *GeneralOrderExecutor) GracefulCancel(ctx context.Context) error {
118119
return nil
119120
}
120121

122+
// GracefulCancel cancels all active maker orders
123+
func (e *GeneralOrderExecutor) GracefulCancel(ctx context.Context) error {
124+
return e.GracefulCancelActiveOrderBook(ctx, e.activeMakerOrders)
125+
}
126+
121127
func (e *GeneralOrderExecutor) ClosePosition(ctx context.Context, percentage fixedpoint.Value, tags ...string) error {
122128
submitOrder := e.position.NewMarketCloseOrder(percentage)
123129
if submitOrder == nil {

pkg/strategy/pivotshort/strategy.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,16 @@ type ResistanceShort struct {
6868
resistancePrices []float64
6969
nextResistancePrice fixedpoint.Value
7070

71-
resistanceOrders []types.Order
71+
activeOrders *bbgo.ActiveOrderBook
7272
}
7373

7474
func (s *ResistanceShort) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.GeneralOrderExecutor) {
7575
s.session = session
7676
s.orderExecutor = orderExecutor
77+
s.activeOrders = bbgo.NewActiveOrderBook(s.Symbol)
78+
s.activeOrders.BindStream(session.UserDataStream)
7779

78-
position := orderExecutor.Position()
79-
symbol := position.Symbol
80-
store, _ := session.MarketDataStore(symbol)
80+
store, _ := session.MarketDataStore(s.Symbol)
8181

8282
s.resistancePivot = &indicator.Pivot{IntervalWindow: s.IntervalWindow}
8383
s.resistancePivot.Bind(store)
@@ -87,22 +87,25 @@ func (s *ResistanceShort) Bind(session *bbgo.ExchangeSession, orderExecutor *bbg
8787
lastKLine := preloadPivot(s.resistancePivot, store)
8888

8989
// use the last kline from the history before we get the next closed kline
90-
s.findNextResistancePriceAndPlaceOrders(lastKLine.Close)
90+
if lastKLine != nil {
91+
s.findNextResistancePriceAndPlaceOrders(lastKLine.Close)
92+
}
9193

9294
session.MarketDataStream.OnKLineClosed(func(kline types.KLine) {
9395
if kline.Symbol != s.Symbol || kline.Interval != s.Interval {
9496
return
9597
}
9698

99+
position := s.orderExecutor.Position()
100+
if position.IsOpened(kline.Close) {
101+
return
102+
}
103+
97104
s.findNextResistancePriceAndPlaceOrders(kline.Close)
98105
})
99106
}
100107

101108
func (s *ResistanceShort) findNextResistancePriceAndPlaceOrders(closePrice fixedpoint.Value) {
102-
position := s.orderExecutor.Position()
103-
if position.IsOpened(closePrice) {
104-
return
105-
}
106109

107110
minDistance := s.MinDistance.Float64()
108111
lows := s.resistancePivot.Lows
@@ -114,6 +117,7 @@ func (s *ResistanceShort) findNextResistancePriceAndPlaceOrders(closePrice fixed
114117
if len(resistancePrices) > 0 {
115118
nextResistancePrice := fixedpoint.NewFromFloat(resistancePrices[0])
116119
if nextResistancePrice.Compare(s.nextResistancePrice) != 0 {
120+
bbgo.Notify("Found next resistance price: %f", nextResistancePrice.Float64())
117121
s.nextResistancePrice = nextResistancePrice
118122
s.placeResistanceOrders(ctx, nextResistancePrice)
119123
}
@@ -134,10 +138,9 @@ func (s *ResistanceShort) placeResistanceOrders(ctx context.Context, resistanceP
134138
layerSpread := s.LayerSpread
135139
quantity := totalQuantity.Div(numLayersF)
136140

137-
if err := s.orderExecutor.CancelOrders(ctx, s.resistanceOrders...); err != nil {
138-
log.WithError(err).Errorf("can not cancel resistance orders: %+v", s.resistanceOrders)
141+
if err := s.orderExecutor.CancelOrders(ctx, s.activeOrders.Orders()...); err != nil {
142+
log.WithError(err).Errorf("can not cancel resistance orders: %+v", s.activeOrders.Orders())
139143
}
140-
s.resistanceOrders = nil
141144

142145
log.Infof("placing resistance orders: resistance price = %f, layer quantity = %f, num of layers = %d", resistancePrice.Float64(), quantity.Float64(), numLayers)
143146

@@ -179,7 +182,7 @@ func (s *ResistanceShort) placeResistanceOrders(ctx context.Context, resistanceP
179182
if err != nil {
180183
log.WithError(err).Errorf("can not place resistance order")
181184
}
182-
s.resistanceOrders = createdOrders
185+
s.activeOrders.Add(createdOrders...)
183186
}
184187

185188
type Strategy struct {
@@ -206,12 +209,11 @@ type Strategy struct {
206209
session *bbgo.ExchangeSession
207210
orderExecutor *bbgo.GeneralOrderExecutor
208211

209-
lastLow fixedpoint.Value
210-
pivot *indicator.Pivot
211-
resistancePivot *indicator.Pivot
212-
stopEWMA *indicator.EWMA
213-
pivotLowPrices []fixedpoint.Value
214-
currentBounceShortPrice fixedpoint.Value
212+
lastLow fixedpoint.Value
213+
pivot *indicator.Pivot
214+
resistancePivot *indicator.Pivot
215+
stopEWMA *indicator.EWMA
216+
pivotLowPrices []fixedpoint.Value
215217

216218
// StrategyController
217219
bbgo.StrategyController

0 commit comments

Comments
 (0)