mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
bollmaker: add shadow protection
This commit is contained in:
parent
71e660571d
commit
a68ad20ddc
|
@ -114,6 +114,10 @@ type Strategy struct {
|
||||||
// less than 1.0 means when placing sell order, place buy order with less quantity
|
// less than 1.0 means when placing sell order, place buy order with less quantity
|
||||||
UptrendSkew fixedpoint.Value `json:"uptrendSkew"`
|
UptrendSkew fixedpoint.Value `json:"uptrendSkew"`
|
||||||
|
|
||||||
|
// ShadowProtection is used to avoid placing bid order when price goes down strongly (without shadow)
|
||||||
|
ShadowProtection *bool `json:"shadowProtection"`
|
||||||
|
ShadowProtectionRatio fixedpoint.Value `json:"shadowProtectionRatio"`
|
||||||
|
|
||||||
session *bbgo.ExchangeSession
|
session *bbgo.ExchangeSession
|
||||||
book *types.StreamOrderBook
|
book *types.StreamOrderBook
|
||||||
market types.Market
|
market types.Market
|
||||||
|
@ -247,7 +251,7 @@ func (s *Strategy) LoadState() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExecutor, midPrice fixedpoint.Value) {
|
func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExecutor, midPrice fixedpoint.Value, kline *types.KLine) {
|
||||||
askPrice := midPrice.Mul(one + s.Spread)
|
askPrice := midPrice.Mul(one + s.Spread)
|
||||||
bidPrice := midPrice.Mul(one - s.Spread)
|
bidPrice := midPrice.Mul(one - s.Spread)
|
||||||
base := s.state.Position.GetBase()
|
base := s.state.Position.GetBase()
|
||||||
|
@ -354,17 +358,33 @@ func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExec
|
||||||
// submitOrders = append(submitOrders, buyOrder)
|
// submitOrders = append(submitOrders, buyOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
buyOrder = s.adjustOrderQuantity(buyOrder)
|
|
||||||
sellOrder = s.adjustOrderQuantity(sellOrder)
|
|
||||||
|
|
||||||
if canBuy {
|
if canBuy {
|
||||||
submitOrders = append(submitOrders, buyOrder)
|
if s.ShadowProtection != nil && *s.ShadowProtection && kline != nil {
|
||||||
|
switch kline.Direction() {
|
||||||
|
case types.DirectionUp:
|
||||||
|
|
||||||
|
case types.DirectionDown:
|
||||||
|
lowerShadowRatio := kline.GetLowerShadowRatio()
|
||||||
|
if lowerShadowRatio < s.ShadowProtectionRatio.Float64() {
|
||||||
|
log.Infof("%s shadow protection enabled, lower shadow ratio %f < %f", s.Symbol, lowerShadowRatio, s.ShadowProtectionRatio.Float64())
|
||||||
|
} else {
|
||||||
|
submitOrders = append(submitOrders, buyOrder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
submitOrders = append(submitOrders, buyOrder)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(submitOrders) == 0 {
|
if len(submitOrders) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range submitOrders {
|
||||||
|
submitOrders[i] = s.adjustOrderQuantity(submitOrders[i])
|
||||||
|
}
|
||||||
|
|
||||||
createdOrders, err := orderExecutor.SubmitOrders(ctx, submitOrders...)
|
createdOrders, err := orderExecutor.SubmitOrders(ctx, submitOrders...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Errorf("can not place ping pong orders")
|
log.WithError(err).Errorf("can not place ping pong orders")
|
||||||
|
@ -406,6 +426,16 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.DowntrendSkew = fixedpoint.NewFromFloat(1.2)
|
s.DowntrendSkew = fixedpoint.NewFromFloat(1.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enable shadow protection by default
|
||||||
|
if s.ShadowProtection == nil {
|
||||||
|
s.ShadowProtection = &[]bool{true}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ShadowProtectionRatio == 0 {
|
||||||
|
// 1%
|
||||||
|
s.ShadowProtectionRatio = fixedpoint.NewFromFloat(0.02)
|
||||||
|
}
|
||||||
|
|
||||||
// initial required information
|
// initial required information
|
||||||
s.session = session
|
s.session = session
|
||||||
|
|
||||||
|
@ -475,10 +505,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
|
|
||||||
midPrice := fixedpoint.NewFromFloat((ticker.Buy + ticker.Sell) / 2)
|
midPrice := fixedpoint.NewFromFloat((ticker.Buy + ticker.Sell) / 2)
|
||||||
s.placeOrders(ctx, orderExecutor, midPrice)
|
s.placeOrders(ctx, orderExecutor, midPrice, nil)
|
||||||
} else {
|
} else {
|
||||||
if price, ok := session.LastPrice(s.Symbol); ok {
|
if price, ok := session.LastPrice(s.Symbol); ok {
|
||||||
s.placeOrders(ctx, orderExecutor, fixedpoint.NewFromFloat(price))
|
s.placeOrders(ctx, orderExecutor, fixedpoint.NewFromFloat(price), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -504,9 +534,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
|
|
||||||
midPrice := fixedpoint.NewFromFloat((ticker.Buy + ticker.Sell) / 2)
|
midPrice := fixedpoint.NewFromFloat((ticker.Buy + ticker.Sell) / 2)
|
||||||
s.placeOrders(ctx, orderExecutor, midPrice)
|
s.placeOrders(ctx, orderExecutor, midPrice, &kline)
|
||||||
} else {
|
} else {
|
||||||
s.placeOrders(ctx, orderExecutor, fixedpoint.NewFromFloat(kline.Close))
|
s.placeOrders(ctx, orderExecutor, fixedpoint.NewFromFloat(kline.Close), &kline)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -154,9 +154,11 @@ func (k KLine) GetLowerShadowRatio() float64 {
|
||||||
|
|
||||||
func (k KLine) GetLowerShadowHeight() float64 {
|
func (k KLine) GetLowerShadowHeight() float64 {
|
||||||
low := k.Low
|
low := k.Low
|
||||||
if k.Open < k.Close {
|
if k.Open < k.Close { // uptrend
|
||||||
return k.Open - low
|
return k.Open - low
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// downtrend
|
||||||
return k.Close - low
|
return k.Close - low
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user