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 (
"time"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
@ -14,6 +15,8 @@ type BboMonitor struct {
Ask types.PriceVolume
UpdatedTime time.Time
priceImpactRatio fixedpoint.Value
updateCallbacks []func(bid, ask types.PriceVolume)
}
@ -21,6 +24,10 @@ func NewBboMonitor() *BboMonitor {
return &BboMonitor{}
}
func (m *BboMonitor) SetPriceImpactRatio(ratio fixedpoint.Value) {
m.priceImpactRatio = ratio
}
func (m *BboMonitor) UpdateFromBook(book *types.StreamOrderBook) bool {
bestBid, ok1 := book.BestBid()
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 {
changed := false
if m.Bid.Price.Compare(bid.Price) != 0 || m.Bid.Volume.Compare(bid.Volume) != 0 {
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.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

View File

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