mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 06:53:52 +00:00
xdepthmaker: support partial maker order replenish
This commit is contained in:
parent
f21170aa5d
commit
888a550c80
|
@ -2,6 +2,7 @@ package xdepthmaker
|
|||
|
||||
import (
|
||||
"context"
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -381,8 +382,10 @@ func (s *Strategy) CrossRun(
|
|||
|
||||
switch sig.Type {
|
||||
case types.BookSignalSnapshot:
|
||||
case types.BookSignalUpdate:
|
||||
s.updateQuote(ctx, 0)
|
||||
|
||||
case types.BookSignalUpdate:
|
||||
s.updateQuote(ctx, 5)
|
||||
}
|
||||
|
||||
case <-posTicker.C:
|
||||
|
@ -581,7 +584,7 @@ func (s *Strategy) runTradeRecover(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Strategy) generateMakerOrders(pricingBook *types.StreamOrderBook) ([]types.SubmitOrder, error) {
|
||||
func (s *Strategy) generateMakerOrders(pricingBook *types.StreamOrderBook, maxLayer int) ([]types.SubmitOrder, error) {
|
||||
bestBid, bestAsk, hasPrice := pricingBook.BestBidAndAsk()
|
||||
if !hasPrice {
|
||||
return nil, nil
|
||||
|
@ -600,8 +603,12 @@ func (s *Strategy) generateMakerOrders(pricingBook *types.StreamOrderBook) ([]ty
|
|||
|
||||
dupPricingBook := pricingBook.CopyDepth(0)
|
||||
|
||||
if maxLayer == 0 || maxLayer > s.NumLayers {
|
||||
maxLayer = s.NumLayers
|
||||
}
|
||||
|
||||
for _, side := range []types.SideType{types.SideTypeBuy, types.SideTypeSell} {
|
||||
for i := 1; i <= s.NumLayers; i++ {
|
||||
for i := 1; i <= maxLayer; i++ {
|
||||
requiredDepthFloat, err := s.DepthScale.Scale(i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "depthScale scale error")
|
||||
|
@ -679,11 +686,31 @@ func (s *Strategy) generateMakerOrders(pricingBook *types.StreamOrderBook) ([]ty
|
|||
return submitOrders, nil
|
||||
}
|
||||
|
||||
func (s *Strategy) updateQuote(ctx context.Context) {
|
||||
if err := s.MakerOrderExecutor.GracefulCancel(ctx); err != nil {
|
||||
log.Warnf("there are some %s orders not canceled, skipping placing maker orders", s.Symbol)
|
||||
s.MakerOrderExecutor.ActiveMakerOrders().Print()
|
||||
return
|
||||
func (s *Strategy) partiallyCancelOrders(ctx context.Context, maxLayer int) error {
|
||||
buyOrders, sellOrders := s.MakerOrderExecutor.ActiveMakerOrders().Orders().SeparateBySide()
|
||||
buyOrders = types.SortOrdersByPrice(buyOrders, true)
|
||||
sellOrders = types.SortOrdersByPrice(sellOrders, false)
|
||||
|
||||
buyOrdersToCancel := buyOrders[0:min(maxLayer, len(buyOrders))]
|
||||
sellOrdersToCancel := sellOrders[0:min(maxLayer, len(sellOrders))]
|
||||
|
||||
err1 := s.MakerOrderExecutor.GracefulCancel(ctx, buyOrdersToCancel...)
|
||||
err2 := s.MakerOrderExecutor.GracefulCancel(ctx, sellOrdersToCancel...)
|
||||
return stderrors.Join(err1, err2)
|
||||
}
|
||||
|
||||
func (s *Strategy) updateQuote(ctx context.Context, maxLayer int) {
|
||||
if maxLayer == 0 {
|
||||
if err := s.MakerOrderExecutor.GracefulCancel(ctx); err != nil {
|
||||
log.WithError(err).Warnf("there are some %s orders not canceled, skipping placing maker orders", s.Symbol)
|
||||
s.MakerOrderExecutor.ActiveMakerOrders().Print()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := s.partiallyCancelOrders(ctx, maxLayer); err != nil {
|
||||
log.WithError(err).Warnf("%s partial order cancel failed", s.Symbol)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
numOfMakerOrders := s.MakerOrderExecutor.ActiveMakerOrders().NumOfOrders()
|
||||
|
@ -719,7 +746,7 @@ func (s *Strategy) updateQuote(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
submitOrders, err := s.generateMakerOrders(s.pricingBook)
|
||||
submitOrders, err := s.generateMakerOrders(s.pricingBook, maxLayer)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("generate order error")
|
||||
return
|
||||
|
@ -771,3 +798,11 @@ func averageDepthPrice(pvs types.PriceVolumeSlice) (price fixedpoint.Value, err
|
|||
price = totalQuoteAmount.Div(totalQuantity)
|
||||
return price, nil
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func TestStrategy_generateMakerOrders(t *testing.T) {
|
|||
Time: time.Now(),
|
||||
})
|
||||
|
||||
orders, err := s.generateMakerOrders(pricingBook)
|
||||
orders, err := s.generateMakerOrders(pricingBook, 0)
|
||||
assert.NoError(t, err)
|
||||
AssertOrdersPriceSideQuantity(t, []PriceSideQuantityAssert{
|
||||
{Side: types.SideTypeBuy, Price: Number("25000"), Quantity: Number("0.04")}, // =~ $1000.00
|
||||
|
|
|
@ -243,3 +243,16 @@ func (m *SyncOrderMap) Orders() (slice OrderSlice) {
|
|||
}
|
||||
|
||||
type OrderSlice []Order
|
||||
|
||||
func (s OrderSlice) SeparateBySide() (buyOrders, sellOrders []Order) {
|
||||
for _, o := range s {
|
||||
switch o.Side {
|
||||
case SideTypeBuy:
|
||||
buyOrders = append(buyOrders, o)
|
||||
case SideTypeSell:
|
||||
sellOrders = append(sellOrders, o)
|
||||
}
|
||||
}
|
||||
|
||||
return buyOrders, sellOrders
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ func NewPriceHeartBeat(timeout time.Duration) *PriceHeartBeat {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *PriceHeartBeat) Last() PriceVolume {
|
||||
return b.last
|
||||
}
|
||||
|
||||
// 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,
|
||||
|
|
|
@ -82,6 +82,26 @@ func (slice PriceVolumeSlice) IndexByQuoteVolumeDepth(requiredQuoteVolume fixedp
|
|||
return -1
|
||||
}
|
||||
|
||||
func (slice PriceVolumeSlice) SumDepth() fixedpoint.Value {
|
||||
var total = fixedpoint.Zero
|
||||
for _, pv := range slice {
|
||||
total = total.Add(pv.Volume)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
func (slice PriceVolumeSlice) SumDepthInQuote() fixedpoint.Value {
|
||||
var total = fixedpoint.Zero
|
||||
|
||||
for _, pv := range slice {
|
||||
quoteVolume := fixedpoint.Mul(pv.Price, pv.Volume)
|
||||
total = total.Add(quoteVolume)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
func (slice PriceVolumeSlice) IndexByVolumeDepth(requiredVolume fixedpoint.Value) int {
|
||||
var tv = fixedpoint.Zero
|
||||
for x, el := range slice {
|
||||
|
|
Loading…
Reference in New Issue
Block a user