xmaker: refactor getInitialLayerQuantity for quantity multiplier

This commit is contained in:
c9s 2024-09-07 14:19:07 +08:00
parent 6ad16b7488
commit f24a96c8c3
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54

View File

@ -417,21 +417,48 @@ func (s *Strategy) aggregateSignal(ctx context.Context) (float64, error) {
return sum / voters, nil return sum / voters, nil
} }
func (s *Strategy) updateQuote(ctx context.Context) { // getInitialLayerQuantity returns the initial quantity for the layer
// i is the layer index, starting from 0
func (s *Strategy) getInitialLayerQuantity(i int) (fixedpoint.Value, error) {
if s.QuantityScale != nil {
qf, err := s.QuantityScale.Scale(i + 1)
if err != nil {
return fixedpoint.Zero, fmt.Errorf("quantityScale error: %w", err)
}
log.Infof("%s scaling bid #%d quantity to %f", s.Symbol, i+1, qf)
// override the default quantity
return fixedpoint.NewFromFloat(qf), nil
}
q := s.Quantity
if s.QuantityMultiplier.Sign() > 0 && i > 0 {
q = fixedpoint.NewFromFloat(
q.Float64() * math.Pow(
s.QuantityMultiplier.Float64(), float64(i+1)))
}
// fallback to the fixed quantity
return q, nil
}
func (s *Strategy) updateQuote(ctx context.Context) error {
if err := s.activeMakerOrders.GracefulCancel(ctx, s.makerSession.Exchange); err != nil { if err := s.activeMakerOrders.GracefulCancel(ctx, s.makerSession.Exchange); err != nil {
s.logger.Warnf("there are some %s orders not canceled, skipping placing maker orders", s.Symbol) s.logger.Warnf("there are some %s orders not canceled, skipping placing maker orders", s.Symbol)
s.activeMakerOrders.Print() s.activeMakerOrders.Print()
return return nil
} }
if s.activeMakerOrders.NumOfOrders() > 0 { if s.activeMakerOrders.NumOfOrders() > 0 {
s.logger.Warnf("unable to cancel all %s orders, skipping placing maker orders", s.Symbol) s.logger.Warnf("unable to cancel all %s orders, skipping placing maker orders", s.Symbol)
return return nil
} }
signal, err := s.aggregateSignal(ctx) signal, err := s.aggregateSignal(ctx)
if err != nil { if err != nil {
return return err
} }
s.logger.Infof("aggregated signal: %f", signal) s.logger.Infof("aggregated signal: %f", signal)
@ -446,14 +473,14 @@ func (s *Strategy) updateQuote(ctx context.Context) {
bbgo.Notify("Strategy %s is halted, reason: %s", ID, reason) bbgo.Notify("Strategy %s is halted, reason: %s", ID, reason)
} }
return return nil
} }
} }
bestBid, bestAsk, hasPrice := s.sourceBook.BestBidAndAsk() bestBid, bestAsk, hasPrice := s.sourceBook.BestBidAndAsk()
if !hasPrice { if !hasPrice {
s.logger.Warnf("no valid price, skip quoting") s.logger.Warnf("no valid price, skip quoting")
return return fmt.Errorf("no valid book price")
} }
bestBidPrice := bestBid.Price bestBidPrice := bestBid.Price
@ -461,11 +488,10 @@ func (s *Strategy) updateQuote(ctx context.Context) {
s.logger.Infof("%s book ticker: best ask / best bid = %v / %v", s.Symbol, bestAskPrice, bestBidPrice) s.logger.Infof("%s book ticker: best ask / best bid = %v / %v", s.Symbol, bestAskPrice, bestBidPrice)
if bestBidPrice.Compare(bestAskPrice) > 0 { if bestBidPrice.Compare(bestAskPrice) > 0 {
log.Errorf("best bid price %f is higher than best ask price %f, skip quoting", return fmt.Errorf("best bid price %f is higher than best ask price %f, skip quoting",
bestBidPrice.Float64(), bestBidPrice.Float64(),
bestAskPrice.Float64(), bestAskPrice.Float64(),
) )
return
} }
if s.EnableArbitrage { if s.EnableArbitrage {
@ -495,20 +521,20 @@ func (s *Strategy) updateQuote(ctx context.Context) {
s.logger.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago", s.logger.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago",
s.Symbol, s.Symbol,
time.Since(bookLastUpdateTime)) time.Since(bookLastUpdateTime))
return return err
} }
if _, err := s.askPriceHeartBeat.Update(bestAsk); err != nil { if _, err := s.askPriceHeartBeat.Update(bestAsk); err != nil {
s.logger.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago", s.logger.WithError(err).Errorf("quote update error, %s price not updating, order book last update: %s ago",
s.Symbol, s.Symbol,
time.Since(bookLastUpdateTime)) time.Since(bookLastUpdateTime))
return return err
} }
sourceBook := s.sourceBook.CopyDepth(10) sourceBook := s.sourceBook.CopyDepth(10)
if valid, err := sourceBook.IsValid(); !valid { if valid, err := sourceBook.IsValid(); !valid {
s.logger.WithError(err).Errorf("%s invalid copied order book, skip quoting: %v", s.Symbol, err) s.logger.WithError(err).Errorf("%s invalid copied order book, skip quoting: %v", s.Symbol, err)
return return err
} }
var disableMakerBid = false var disableMakerBid = false
@ -679,12 +705,11 @@ func (s *Strategy) updateQuote(ctx context.Context) {
if disableMakerAsk && disableMakerBid { if disableMakerAsk && disableMakerBid {
log.Warnf("%s bid/ask maker is disabled due to insufficient balances", s.Symbol) log.Warnf("%s bid/ask maker is disabled due to insufficient balances", s.Symbol)
return return nil
} }
var submitOrders []types.SubmitOrder var submitOrders []types.SubmitOrder
var accumulativeBidQuantity, accumulativeAskQuantity fixedpoint.Value var accumulativeBidQuantity, accumulativeAskQuantity fixedpoint.Value
var bidQuantity = s.Quantity
var askQuantity = s.Quantity var askQuantity = s.Quantity
var quote = &Quote{ var quote = &Quote{
@ -715,22 +740,14 @@ func (s *Strategy) updateQuote(ctx context.Context) {
bidMarginMetrics.With(s.metricsLabels).Set(quote.BidMargin.Float64()) bidMarginMetrics.With(s.metricsLabels).Set(quote.BidMargin.Float64())
askMarginMetrics.With(s.metricsLabels).Set(quote.AskMargin.Float64()) askMarginMetrics.With(s.metricsLabels).Set(quote.AskMargin.Float64())
for i := 0; i < s.NumLayers; i++ { if !disableMakerBid {
// for maker bid orders for i := 0; i < s.NumLayers; i++ {
if !disableMakerBid { bidQuantity, err := s.getInitialLayerQuantity(i)
if s.QuantityScale != nil { if err != nil {
qf, err := s.QuantityScale.Scale(i + 1) return err
if err != nil {
log.WithError(err).Errorf("quantityScale error")
return
}
log.Infof("%s scaling bid #%d quantity to %f", s.Symbol, i+1, qf)
// override the default bid quantity
bidQuantity = fixedpoint.NewFromFloat(qf)
} }
// for maker bid orders
accumulativeBidQuantity = accumulativeBidQuantity.Add(bidQuantity) accumulativeBidQuantity = accumulativeBidQuantity.Add(bidQuantity)
if s.UseDepthPrice { if s.UseDepthPrice {
@ -785,14 +802,15 @@ func (s *Strategy) updateQuote(ctx context.Context) {
bidQuantity = bidQuantity.Mul(s.QuantityMultiplier) bidQuantity = bidQuantity.Mul(s.QuantityMultiplier)
} }
} }
}
for i := 0; i < s.NumLayers; i++ {
// for maker ask orders // for maker ask orders
if !disableMakerAsk { if !disableMakerAsk {
if s.QuantityScale != nil { if s.QuantityScale != nil {
qf, err := s.QuantityScale.Scale(i + 1) qf, err := s.QuantityScale.Scale(i + 1)
if err != nil { if err != nil {
log.WithError(err).Errorf("quantityScale error") return fmt.Errorf("quantityScale error: %w", err)
return
} }
log.Infof("%s scaling ask #%d quantity to %f", s.Symbol, i+1, qf) log.Infof("%s scaling ask #%d quantity to %f", s.Symbol, i+1, qf)
@ -859,12 +877,12 @@ func (s *Strategy) updateQuote(ctx context.Context) {
if len(submitOrders) == 0 { if len(submitOrders) == 0 {
log.Warnf("no orders generated") log.Warnf("no orders generated")
return return nil
} }
formattedOrders, err := s.makerSession.FormatOrders(submitOrders) formattedOrders, err := s.makerSession.FormatOrders(submitOrders)
if err != nil { if err != nil {
return return err
} }
orderCreateCallback := func(createdOrder types.Order) { orderCreateCallback := func(createdOrder types.Order) {
@ -877,7 +895,7 @@ func (s *Strategy) updateQuote(ctx context.Context) {
createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, s.makerSession.Exchange, orderCreateCallback, formattedOrders...) createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, s.makerSession.Exchange, orderCreateCallback, formattedOrders...)
if err != nil { if err != nil {
log.WithError(err).Errorf("unable to place maker orders: %+v", formattedOrders) log.WithError(err).Errorf("unable to place maker orders: %+v", formattedOrders)
return return err
} }
openOrderBidExposureInUsdMetrics.With(s.metricsLabels).Set(bidExposureInUsd.Float64()) openOrderBidExposureInUsdMetrics.With(s.metricsLabels).Set(bidExposureInUsd.Float64())
@ -885,6 +903,7 @@ func (s *Strategy) updateQuote(ctx context.Context) {
_ = errIdx _ = errIdx
_ = createdOrders _ = createdOrders
return nil
} }
func (s *Strategy) adjustHedgeQuantityWithAvailableBalance( func (s *Strategy) adjustHedgeQuantityWithAvailableBalance(