improve price hart beat usage

This commit is contained in:
c9s 2023-11-30 13:44:35 +08:00
parent 46b3a81b07
commit e0e9876902
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
4 changed files with 42 additions and 23 deletions

View File

@ -230,7 +230,7 @@ type Strategy struct {
hedgeErrorLimiter *rate.Limiter
hedgeErrorRateReservation *rate.Reservation
askPriceHeartBeat, bidPriceHeartBeat types.PriceHeartBeat
askPriceHeartBeat, bidPriceHeartBeat *types.PriceHeartBeat
lastPrice fixedpoint.Value
@ -318,6 +318,8 @@ func (s *Strategy) Defaults() error {
}
func (s *Strategy) Initialize() error {
s.bidPriceHeartBeat = types.NewPriceHeartBeat(priceUpdateTimeout)
s.askPriceHeartBeat = types.NewPriceHeartBeat(priceUpdateTimeout)
return nil
}
@ -701,14 +703,14 @@ func (s *Strategy) updateQuote(ctx context.Context) {
bookLastUpdateTime := s.pricingBook.LastUpdateTime()
if _, err := s.bidPriceHeartBeat.Update(bestBid, priceUpdateTimeout); err != nil {
if _, err := s.bidPriceHeartBeat.Update(bestBid); err != nil {
log.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago",
s.Symbol,
time.Since(bookLastUpdateTime))
return
}
if _, err := s.askPriceHeartBeat.Update(bestAsk, priceUpdateTimeout); err != nil {
if _, err := s.askPriceHeartBeat.Update(bestAsk); err != nil {
log.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago",
s.Symbol,
time.Since(bookLastUpdateTime))

View File

@ -112,7 +112,7 @@ type Strategy struct {
orderStore *core.OrderStore
tradeCollector *core.TradeCollector
askPriceHeartBeat, bidPriceHeartBeat types.PriceHeartBeat
askPriceHeartBeat, bidPriceHeartBeat *types.PriceHeartBeat
lastPrice fixedpoint.Value
groupID uint32
@ -170,6 +170,12 @@ func aggregatePrice(pvs types.PriceVolumeSlice, requiredQuantity fixedpoint.Valu
return price
}
func (s *Strategy) Initialize() error {
s.bidPriceHeartBeat = types.NewPriceHeartBeat(priceUpdateTimeout)
s.askPriceHeartBeat = types.NewPriceHeartBeat(priceUpdateTimeout)
return nil
}
func (s *Strategy) updateQuote(ctx context.Context, orderExecutionRouter bbgo.OrderExecutionRouter) {
if err := s.activeMakerOrders.GracefulCancel(ctx, s.makerSession.Exchange); err != nil {
log.Warnf("there are some %s orders not canceled, skipping placing maker orders", s.Symbol)
@ -191,14 +197,14 @@ func (s *Strategy) updateQuote(ctx context.Context, orderExecutionRouter bbgo.Or
bookLastUpdateTime := s.book.LastUpdateTime()
if _, err := s.bidPriceHeartBeat.Update(bestBid, priceUpdateTimeout); err != nil {
if _, err := s.bidPriceHeartBeat.Update(bestBid); err != nil {
log.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago",
s.Symbol,
time.Since(bookLastUpdateTime))
return
}
if _, err := s.askPriceHeartBeat.Update(bestAsk, priceUpdateTimeout); err != nil {
if _, err := s.askPriceHeartBeat.Update(bestAsk); err != nil {
log.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago",
s.Symbol,
time.Since(bookLastUpdateTime))
@ -639,7 +645,9 @@ func (s *Strategy) Validate() error {
return nil
}
func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.OrderExecutionRouter, sessions map[string]*bbgo.ExchangeSession) error {
func (s *Strategy) CrossRun(
ctx context.Context, orderExecutionRouter bbgo.OrderExecutionRouter, sessions map[string]*bbgo.ExchangeSession,
) error {
if s.BollBandInterval == "" {
s.BollBandInterval = types.Interval1m
}

View File

@ -7,24 +7,34 @@ import (
// PriceHeartBeat is used for monitoring the price volume update.
type PriceHeartBeat struct {
PriceVolume PriceVolume
LastTime time.Time
last PriceVolume
lastUpdatedTime time.Time
timeout time.Duration
}
func NewPriceHeartBeat(timeout time.Duration) *PriceHeartBeat {
return &PriceHeartBeat{
timeout: timeout,
}
}
// Update updates the price volume object and the last update time
// It returns (bool, error), when the price is successfully updated, it returns true.
// If the price is not updated (same price) and the last time exceeded the timeout,
// Then false, and an error will be returned
func (b *PriceHeartBeat) Update(pv PriceVolume, timeout time.Duration) (bool, error) {
if b.PriceVolume.Price.IsZero() || b.PriceVolume != pv {
b.PriceVolume = pv
b.LastTime = time.Now()
func (b *PriceHeartBeat) Update(current PriceVolume) (bool, error) {
if b.last.Price.IsZero() || b.last != current {
b.last = current
b.lastUpdatedTime = time.Now()
return true, nil // successfully updated
} else if time.Since(b.LastTime) > timeout {
return false, fmt.Errorf("price %s has not been updating for %s, last update: %s, skip quoting",
b.PriceVolume.String(),
time.Since(b.LastTime),
b.LastTime)
} else {
// if price and volume is not changed
if b.last.Equals(current) && time.Since(b.lastUpdatedTime) > b.timeout {
return false, fmt.Errorf("price %s has not been updating for %s, last update: %s, skip quoting",
b.last.String(),
time.Since(b.lastUpdatedTime),
b.lastUpdatedTime)
}
}
return false, nil

View File

@ -2,7 +2,6 @@ package types
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
@ -11,19 +10,19 @@ import (
func TestPriceHeartBeat_Update(t *testing.T) {
hb := PriceHeartBeat{}
updated, err := hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(22.0), Volume: fixedpoint.NewFromFloat(100.0)}, time.Minute)
updated, err := hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(22.0), Volume: fixedpoint.NewFromFloat(100.0)})
assert.NoError(t, err)
assert.True(t, updated)
updated, err = hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(22.0), Volume: fixedpoint.NewFromFloat(100.0)}, time.Minute)
updated, err = hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(22.0), Volume: fixedpoint.NewFromFloat(100.0)})
assert.NoError(t, err)
assert.False(t, updated, "should not be updated when pv is not changed")
updated, err = hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(23.0), Volume: fixedpoint.NewFromFloat(100.0)}, time.Minute)
updated, err = hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(23.0), Volume: fixedpoint.NewFromFloat(100.0)})
assert.NoError(t, err)
assert.True(t, updated, "should be updated when the price is changed")
updated, err = hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(23.0), Volume: fixedpoint.NewFromFloat(200.0)}, time.Minute)
updated, err = hb.Update(PriceVolume{Price: fixedpoint.NewFromFloat(23.0), Volume: fixedpoint.NewFromFloat(200.0)})
assert.NoError(t, err)
assert.True(t, updated, "should be updated when the volume is changed")
}