xdepthmaker: add priceImpactRatio detection

This commit is contained in:
c9s 2024-09-27 20:00:48 +08:00
parent be353c533b
commit 4661ec629d
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 42 additions and 25 deletions

View File

@ -3,6 +3,7 @@ package bbgo
import ( import (
"time" "time"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
) )
@ -14,6 +15,8 @@ type BboMonitor struct {
Ask types.PriceVolume Ask types.PriceVolume
UpdatedTime time.Time UpdatedTime time.Time
priceImpactRatio fixedpoint.Value
updateCallbacks []func(bid, ask types.PriceVolume) updateCallbacks []func(bid, ask types.PriceVolume)
} }
@ -21,6 +24,10 @@ func NewBboMonitor() *BboMonitor {
return &BboMonitor{} return &BboMonitor{}
} }
func (m *BboMonitor) SetPriceImpactRatio(ratio fixedpoint.Value) {
m.priceImpactRatio = ratio
}
func (m *BboMonitor) UpdateFromBook(book *types.StreamOrderBook) bool { func (m *BboMonitor) UpdateFromBook(book *types.StreamOrderBook) bool {
bestBid, ok1 := book.BestBid() bestBid, ok1 := book.BestBid()
bestAsk, ok2 := book.BestAsk() bestAsk, ok2 := book.BestAsk()
@ -34,11 +41,23 @@ func (m *BboMonitor) UpdateFromBook(book *types.StreamOrderBook) bool {
func (m *BboMonitor) Update(bid, ask types.PriceVolume, t time.Time) bool { func (m *BboMonitor) Update(bid, ask types.PriceVolume, t time.Time) bool {
changed := false changed := false
if m.Bid.Price.Compare(bid.Price) != 0 || m.Bid.Volume.Compare(bid.Volume) != 0 { if m.Bid.Price.Compare(bid.Price) != 0 || m.Bid.Volume.Compare(bid.Volume) != 0 {
changed = true if m.priceImpactRatio.IsZero() {
changed = true
} else {
if bid.Price.Sub(m.Bid.Price).Abs().Div(m.Bid.Price).Compare(m.priceImpactRatio) >= 0 {
changed = true
}
}
} }
if m.Ask.Price.Compare(ask.Price) != 0 || m.Ask.Volume.Compare(ask.Volume) != 0 { if m.Ask.Price.Compare(ask.Price) != 0 || m.Ask.Volume.Compare(ask.Volume) != 0 {
changed = true if m.priceImpactRatio.IsZero() {
changed = true
} else {
if ask.Price.Sub(m.Ask.Price).Abs().Div(m.Ask.Price).Compare(m.priceImpactRatio) >= 0 {
changed = true
}
}
} }
m.Bid = bid m.Bid = bid

View File

@ -210,8 +210,8 @@ type Strategy struct {
// HedgeExchange session name // HedgeExchange session name
HedgeExchange string `json:"hedgeExchange"` HedgeExchange string `json:"hedgeExchange"`
UpdateInterval types.Duration `json:"updateInterval"` FastLayerUpdateInterval types.Duration `json:"fastLayerUpdateInterval"`
UpdateLayers int `json:"updateLayers"` NumOfFastLayers int `json:"numOfFastLayers"`
HedgeInterval types.Duration `json:"hedgeInterval"` HedgeInterval types.Duration `json:"hedgeInterval"`
@ -249,6 +249,8 @@ type Strategy struct {
// RecoverTrade tries to find the missing trades via the REStful API // RecoverTrade tries to find the missing trades via the REStful API
RecoverTrade bool `json:"recoverTrade"` RecoverTrade bool `json:"recoverTrade"`
PriceImpactRatio fixedpoint.Value `json:"priceImpactRatio"`
RecoverTradeScanPeriod types.Duration `json:"recoverTradeScanPeriod"` RecoverTradeScanPeriod types.Duration `json:"recoverTradeScanPeriod"`
NumLayers int `json:"numLayers"` NumLayers int `json:"numLayers"`
@ -281,6 +283,7 @@ type Strategy struct {
connectivityGroup *types.ConnectivityGroup connectivityGroup *types.ConnectivityGroup
priceSolver *pricesolver.SimplePriceSolver priceSolver *pricesolver.SimplePriceSolver
bboMonitor *bbgo.BboMonitor
} }
func (s *Strategy) ID() string { func (s *Strategy) ID() string {
@ -353,12 +356,12 @@ func (s *Strategy) Validate() error {
} }
func (s *Strategy) Defaults() error { func (s *Strategy) Defaults() error {
if s.UpdateInterval == 0 { if s.FastLayerUpdateInterval == 0 {
s.UpdateInterval = types.Duration(5 * time.Second) s.FastLayerUpdateInterval = types.Duration(5 * time.Second)
} }
if s.UpdateLayers == 0 { if s.NumOfFastLayers == 0 {
s.UpdateLayers = 5 s.NumOfFastLayers = 5
} }
if s.FullReplenishInterval == 0 { if s.FullReplenishInterval == 0 {
@ -406,8 +409,7 @@ func (s *Strategy) Defaults() error {
} }
func (s *Strategy) quoteWorker(ctx context.Context) { func (s *Strategy) quoteWorker(ctx context.Context) {
updateTicker := time.NewTicker(util.MillisecondsJitter(s.FastLayerUpdateInterval.Duration(), 200))
updateTicker := time.NewTicker(util.MillisecondsJitter(s.UpdateInterval.Duration(), 200))
defer updateTicker.Stop() defer updateTicker.Stop()
fullReplenishTicker := time.NewTicker(util.MillisecondsJitter(s.FullReplenishInterval.Duration(), 200)) fullReplenishTicker := time.NewTicker(util.MillisecondsJitter(s.FullReplenishInterval.Duration(), 200))
@ -421,8 +423,6 @@ func (s *Strategy) quoteWorker(ctx context.Context) {
s.updateQuote(ctx, 0) s.updateQuote(ctx, 0)
lastOrderReplenishTime := time.Now()
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
@ -438,7 +438,9 @@ func (s *Strategy) quoteWorker(ctx context.Context) {
case <-fullReplenishTicker.C: case <-fullReplenishTicker.C:
s.updateQuote(ctx, 0) s.updateQuote(ctx, 0)
lastOrderReplenishTime = time.Now()
case <-updateTicker.C:
s.updateQuote(ctx, s.NumOfFastLayers)
case sig, ok := <-s.sourceBook.C: case sig, ok := <-s.sourceBook.C:
// when any book change event happened // when any book change event happened
@ -446,19 +448,10 @@ func (s *Strategy) quoteWorker(ctx context.Context) {
return return
} }
if time.Since(lastOrderReplenishTime) < 10*time.Second { changed := s.bboMonitor.UpdateFromBook(s.sourceBook)
continue if changed || sig.Type == types.BookSignalSnapshot {
}
switch sig.Type {
case types.BookSignalSnapshot:
s.updateQuote(ctx, 0) s.updateQuote(ctx, 0)
case types.BookSignalUpdate:
s.updateQuote(ctx, s.UpdateLayers)
} }
lastOrderReplenishTime = time.Now()
} }
} }
} }
@ -584,6 +577,11 @@ func (s *Strategy) CrossRun(
s.priceSolver.BindStream(s.hedgeSession.MarketDataStream) s.priceSolver.BindStream(s.hedgeSession.MarketDataStream)
s.priceSolver.BindStream(s.makerSession.MarketDataStream) s.priceSolver.BindStream(s.makerSession.MarketDataStream)
s.bboMonitor = bbgo.NewBboMonitor()
if !s.PriceImpactRatio.IsZero() {
s.bboMonitor.SetPriceImpactRatio(s.PriceImpactRatio)
}
if err := s.priceSolver.UpdateFromTickers(ctx, s.makerSession.Exchange, if err := s.priceSolver.UpdateFromTickers(ctx, s.makerSession.Exchange,
s.Symbol, s.makerSession.Exchange.PlatformFeeCurrency()+"USDT"); err != nil { s.Symbol, s.makerSession.Exchange.PlatformFeeCurrency()+"USDT"); err != nil {
return err return err
@ -640,7 +638,7 @@ func (s *Strategy) CrossRun(
close(s.stopC) close(s.stopC)
// wait for the quoter to stop // wait for the quoter to stop
time.Sleep(s.UpdateInterval.Duration()) time.Sleep(s.FastLayerUpdateInterval.Duration())
if err := s.MakerOrderExecutor.GracefulCancel(ctx); err != nil { if err := s.MakerOrderExecutor.GracefulCancel(ctx); err != nil {
log.WithError(err).Errorf("graceful cancel %s order error", s.Symbol) log.WithError(err).Errorf("graceful cancel %s order error", s.Symbol)