use ATR to adjust spread ratio

This commit is contained in:
narumi 2023-03-16 03:15:07 +08:00
parent 52b2ffebd1
commit 939427c81f

View File

@ -9,6 +9,7 @@ import (
"github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/indicator"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
) )
@ -37,6 +38,10 @@ type Strategy struct {
SkewFactor fixedpoint.Value `json:"skewFactor"` SkewFactor fixedpoint.Value `json:"skewFactor"`
TargetWeight fixedpoint.Value `json:"targetWeight"` TargetWeight fixedpoint.Value `json:"targetWeight"`
// replace halfSpreadRatio by ATR
ATRMultiplier fixedpoint.Value `json:"atrMultiplier"`
ATRWindow int `json:"atrWindow"`
// persistence fields // persistence fields
Position *types.Position `json:"position,omitempty" persistence:"position"` Position *types.Position `json:"position,omitempty" persistence:"position"`
ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"` ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"`
@ -44,12 +49,17 @@ type Strategy struct {
session *bbgo.ExchangeSession session *bbgo.ExchangeSession
orderExecutor *bbgo.GeneralOrderExecutor orderExecutor *bbgo.GeneralOrderExecutor
activeOrderBook *bbgo.ActiveOrderBook activeOrderBook *bbgo.ActiveOrderBook
atr *indicator.ATR
} }
func (s *Strategy) Defaults() error { func (s *Strategy) Defaults() error {
if s.OrderType == "" { if s.OrderType == "" {
s.OrderType = types.OrderTypeLimitMaker s.OrderType = types.OrderTypeLimitMaker
} }
if s.ATRWindow == 0 {
s.ATRWindow = 14
}
return nil return nil
} }
func (s *Strategy) Initialize() error { func (s *Strategy) Initialize() error {
@ -72,6 +82,18 @@ func (s *Strategy) Validate() error {
if s.HalfSpreadRatio.Float64() <= 0 { if s.HalfSpreadRatio.Float64() <= 0 {
return fmt.Errorf("halfSpreadRatio should be positive") return fmt.Errorf("halfSpreadRatio should be positive")
} }
if s.SkewFactor.Float64() < 0 {
return fmt.Errorf("skewFactor should be non-negative")
}
if s.ATRMultiplier.Float64() < 0 {
return fmt.Errorf("atrMultiplier should be non-negative")
}
if s.ATRWindow < 0 {
return fmt.Errorf("atrWindow should be non-negative")
}
return nil return nil
} }
@ -109,6 +131,8 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
bbgo.Sync(ctx, s) bbgo.Sync(ctx, s)
}) })
s.atr = s.StandardIndicatorSet.ATR(types.IntervalWindow{Interval: s.Interval, Window: s.ATRWindow})
session.UserDataStream.OnStart(func() { session.UserDataStream.OnStart(func() {
// you can place orders here when bbgo is started, this will be called only once. // you can place orders here when bbgo is started, this will be called only once.
}) })
@ -192,6 +216,13 @@ func (s *Strategy) generateSubmitOrders(ctx context.Context) ([]types.SubmitOrde
baseWeight := baseValue.Div(baseValue.Add(quoteBalance.Total())) baseWeight := baseValue.Div(baseValue.Add(quoteBalance.Total()))
skew := s.SkewFactor.Mul(baseWeight.Sub(s.TargetWeight)) skew := s.SkewFactor.Mul(baseWeight.Sub(s.TargetWeight))
if s.ATRMultiplier.Float64() > 0 {
atr := fixedpoint.NewFromFloat(s.atr.Last())
log.Infof("atr: %s", atr.String())
s.HalfSpreadRatio = s.ATRMultiplier.Mul(atr).Div(midPrice)
log.Infof("half spread ratio: %s", s.HalfSpreadRatio.String())
}
// calculate bid and ask price // calculate bid and ask price
// bid price = mid price * (1 - max(r + skew, 0)) // bid price = mid price * (1 - max(r + skew, 0))
bidSpreadRatio := fixedpoint.Max(s.HalfSpreadRatio.Add(skew), fixedpoint.Zero) bidSpreadRatio := fixedpoint.Max(s.HalfSpreadRatio.Add(skew), fixedpoint.Zero)