code.vegaprotocol.io/vega@v0.79.0/datanode/service/market_depth.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package service
    17  
    18  import (
    19  	"context"
    20  	"sync"
    21  	"time"
    22  
    23  	"code.vegaprotocol.io/vega/core/types"
    24  	"code.vegaprotocol.io/vega/datanode/entities"
    25  	"code.vegaprotocol.io/vega/datanode/utils"
    26  	"code.vegaprotocol.io/vega/libs/num"
    27  	"code.vegaprotocol.io/vega/logging"
    28  	"code.vegaprotocol.io/vega/protos/vega"
    29  )
    30  
    31  type OrderStore interface {
    32  	GetLiveOrders(ctx context.Context) ([]entities.Order, error)
    33  }
    34  
    35  type AMMStore interface {
    36  	ListActive(ctx context.Context) ([]entities.AMMPool, error)
    37  }
    38  
    39  type Positions interface {
    40  	GetByMarketAndParty(ctx context.Context, marketID string, partyID string) (entities.Position, error)
    41  }
    42  
    43  type AssetStore interface {
    44  	GetByID(ctx context.Context, id string) (entities.Asset, error)
    45  }
    46  
    47  type ammCache struct {
    48  	priceFactor    num.Decimal                 // the price factor for this market
    49  	ammOrders      map[string][]*types.Order   // map amm id -> expanded orders, so we can remove them if amended
    50  	activeAMMs     map[string]entities.AMMPool // map amm id -> amm definition, so we can refresh its expansion
    51  	estimatedOrder map[string]struct{}         // order-id -> whether it was an estimated order
    52  
    53  	// the lowest/highest bounds of all AMMs
    54  	lowestBound  num.Decimal
    55  	highestBound num.Decimal
    56  
    57  	// reference -> calculation levels, if the reference point hasn't changed we can avoid the busy task
    58  	// of recalculating them
    59  	levels map[string][]*level
    60  }
    61  
    62  func (c *ammCache) addAMM(a entities.AMMPool) {
    63  	c.activeAMMs[a.AmmPartyID.String()] = a
    64  
    65  	low := a.ParametersBase
    66  	if a.ParametersLowerBound != nil {
    67  		low = *a.ParametersLowerBound
    68  	}
    69  
    70  	if c.lowestBound.IsZero() {
    71  		c.lowestBound = low
    72  	} else {
    73  		c.lowestBound = num.MinD(c.lowestBound, low)
    74  	}
    75  
    76  	high := a.ParametersBase
    77  	if a.ParametersUpperBound != nil {
    78  		high = *a.ParametersUpperBound
    79  	}
    80  	c.highestBound = num.MaxD(c.highestBound, high)
    81  }
    82  
    83  func (c *ammCache) removeAMM(ammParty string) {
    84  	delete(c.activeAMMs, ammParty)
    85  	delete(c.ammOrders, ammParty)
    86  
    87  	// now we need to recalculate the lowest/highest
    88  
    89  	c.lowestBound = num.DecimalZero()
    90  	c.highestBound = num.DecimalZero()
    91  	for _, a := range c.activeAMMs {
    92  		low := a.ParametersBase
    93  		if a.ParametersLowerBound != nil {
    94  			low = *a.ParametersLowerBound
    95  		}
    96  		if c.lowestBound.IsZero() {
    97  			c.lowestBound = low
    98  		} else {
    99  			c.lowestBound = num.MinD(c.lowestBound, low)
   100  		}
   101  
   102  		high := a.ParametersBase
   103  		if a.ParametersUpperBound != nil {
   104  			high = *a.ParametersUpperBound
   105  		}
   106  		c.lowestBound = num.MaxD(c.highestBound, high)
   107  	}
   108  }
   109  
   110  type MarketDepth struct {
   111  	log            *logging.Logger
   112  	cfg            MarketDepthConfig
   113  	marketDepths   map[string]*entities.MarketDepth
   114  	orderStore     OrderStore
   115  	ammStore       AMMStore
   116  	assetStore     AssetStore
   117  	markets        MarketStore
   118  	marketData     MarketDataStore
   119  	positions      Positions
   120  	depthObserver  utils.Observer[*types.MarketDepth]
   121  	updateObserver utils.Observer[*types.MarketDepthUpdate]
   122  	mu             sync.RWMutex
   123  	sequenceNumber uint64
   124  
   125  	ammCache map[string]*ammCache
   126  }
   127  
   128  func NewMarketDepth(
   129  	cfg MarketDepthConfig,
   130  	orderStore OrderStore,
   131  	ammStore AMMStore,
   132  	marketData MarketDataStore,
   133  	positions Positions,
   134  	assets AssetStore,
   135  	markets MarketStore,
   136  	logger *logging.Logger,
   137  ) *MarketDepth {
   138  	return &MarketDepth{
   139  		log:            logger,
   140  		cfg:            cfg,
   141  		marketDepths:   map[string]*entities.MarketDepth{},
   142  		orderStore:     orderStore,
   143  		ammStore:       ammStore,
   144  		marketData:     marketData,
   145  		positions:      positions,
   146  		assetStore:     assets,
   147  		markets:        markets,
   148  		depthObserver:  utils.NewObserver[*types.MarketDepth]("market_depth", logger, 100, 100),
   149  		updateObserver: utils.NewObserver[*types.MarketDepthUpdate]("market_depth_update", logger, 100, 100),
   150  		ammCache:       map[string]*ammCache{},
   151  	}
   152  }
   153  
   154  func (m *MarketDepth) Initialise(ctx context.Context) error {
   155  	liveOrders, err := m.orderStore.GetLiveOrders(ctx)
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	// process the live orders and initialize market depths from database data
   161  	for _, liveOrder := range liveOrders {
   162  		order, err := types.OrderFromProto(liveOrder.ToProto())
   163  		if err != nil {
   164  			panic(err)
   165  		}
   166  		m.AddOrder(order, liveOrder.VegaTime, liveOrder.SeqNum)
   167  	}
   168  
   169  	m.InitialiseAMMs(ctx)
   170  
   171  	return nil
   172  }
   173  
   174  func (m *MarketDepth) PublishAtEndOfBlock() {
   175  	m.publishChanges()
   176  }
   177  
   178  func (m *MarketDepth) publishChanges() {
   179  	m.mu.Lock()
   180  	defer m.mu.Unlock()
   181  	for marketID, md := range m.marketDepths {
   182  		buyPtr := []*types.PriceLevel{}
   183  		sellPtr := []*types.PriceLevel{}
   184  
   185  		// No need to notify anyone if nothing has changed
   186  		if len(md.Changes) == 0 {
   187  			continue
   188  		}
   189  
   190  		// Send out market depth updates to any listeners
   191  		for _, pl := range md.Changes {
   192  			if pl.Side == types.SideBuy {
   193  				buyPtr = append(buyPtr, &types.PriceLevel{
   194  					Price:          pl.Price.Clone(),
   195  					NumberOfOrders: pl.TotalOrders,
   196  					Volume:         pl.TotalVolume,
   197  				})
   198  			} else {
   199  				sellPtr = append(sellPtr, &types.PriceLevel{
   200  					Price:          pl.Price.Clone(),
   201  					NumberOfOrders: pl.TotalOrders,
   202  					Volume:         pl.TotalVolume,
   203  				})
   204  			}
   205  		}
   206  
   207  		marketDepthUpdate := &types.MarketDepthUpdate{
   208  			MarketId:               marketID,
   209  			Buy:                    types.PriceLevels(buyPtr).IntoProto(),
   210  			Sell:                   types.PriceLevels(sellPtr).IntoProto(),
   211  			SequenceNumber:         md.SequenceNumber,
   212  			PreviousSequenceNumber: md.PreviousSequenceNumber,
   213  		}
   214  
   215  		m.updateObserver.Notify([]*types.MarketDepthUpdate{marketDepthUpdate})
   216  		m.depthObserver.Notify([]*types.MarketDepth{md.ToProto(0)})
   217  
   218  		// Clear the list of changes
   219  		md.Changes = make([]*entities.PriceLevel, 0, len(md.Changes))
   220  		md.PreviousSequenceNumber = md.SequenceNumber
   221  	}
   222  }
   223  
   224  func (m *MarketDepth) sequential(t time.Time, sequenceNumber uint64) bool {
   225  	// we truncate the vegaTime by microsecond because Postgres only supports microsecond
   226  	// granularity for time. In order to be able to reproduce the same sequence numbers regardless
   227  	// the source, we have to truncate the time to microsecond granularity
   228  	n := uint64(t.Truncate(time.Microsecond).UnixNano()) + sequenceNumber
   229  
   230  	if m.sequenceNumber > n {
   231  		// This update is older than the current MarketDepth
   232  		return false
   233  	}
   234  
   235  	m.sequenceNumber = n
   236  	return true
   237  }
   238  
   239  func (m *MarketDepth) AddOrder(order *types.Order, vegaTime time.Time, sequenceNumber uint64) {
   240  	m.mu.Lock()
   241  	defer m.mu.Unlock()
   242  
   243  	// Non persistent and network orders do not matter
   244  	if order.Type == types.OrderTypeMarket ||
   245  		order.TimeInForce == types.OrderTimeInForceFOK ||
   246  		order.TimeInForce == types.OrderTimeInForceIOC {
   247  		return
   248  	}
   249  
   250  	// Orders that where not valid are ignored
   251  	if order.Status == types.OrderStatusUnspecified {
   252  		return
   253  	}
   254  
   255  	if !m.sequential(vegaTime, sequenceNumber) {
   256  		return
   257  	}
   258  
   259  	if m.isAMMOrder(order) {
   260  		// this AMM order has come through the orders stream, it can only mean that it has traded so we need to refresh its depth
   261  		m.onAMMTraded(order.Party, order.MarketID)
   262  		return
   263  	}
   264  
   265  	md := m.getDepth(order.MarketID)
   266  	md.AddOrderUpdate(order, false)
   267  	md.SequenceNumber = m.sequenceNumber
   268  }
   269  
   270  func (m *MarketDepth) getDepth(marketID string) *entities.MarketDepth {
   271  	// See if we already have a MarketDepth item for this market
   272  	if md := m.marketDepths[marketID]; md != nil {
   273  		return md
   274  	}
   275  
   276  	// First time we have an update for this market
   277  	// so we need to create a new MarketDepth
   278  	md := &entities.MarketDepth{
   279  		MarketID:   marketID,
   280  		LiveOrders: map[string]*types.Order{},
   281  	}
   282  	md.SequenceNumber = m.sequenceNumber
   283  	m.marketDepths[marketID] = md
   284  	return md
   285  }
   286  
   287  // GetMarketDepth builds up the structure to be sent out to any market depth listeners.
   288  func (m *MarketDepth) GetMarketDepth(market string, limit uint64) *types.MarketDepth {
   289  	m.mu.RLock()
   290  	defer m.mu.RUnlock()
   291  	md, ok := m.marketDepths[market]
   292  	if !ok || md == nil {
   293  		// When a market is new with no orders there will not be any market depth/order book
   294  		// so we do not need to try and calculate the depth cumulative volumes etc
   295  		return &types.MarketDepth{
   296  			MarketId: market,
   297  			Buy:      []*vega.PriceLevel{},
   298  			Sell:     []*vega.PriceLevel{},
   299  		}
   300  	}
   301  
   302  	return md.ToProto(limit)
   303  }
   304  
   305  func (m *MarketDepth) ObserveDepth(ctx context.Context, retries int, marketIds []string) (<-chan []*types.MarketDepth, uint64) {
   306  	markets := map[string]bool{}
   307  	for _, id := range marketIds {
   308  		markets[id] = true
   309  	}
   310  
   311  	ch, ref := m.depthObserver.Observe(ctx,
   312  		retries,
   313  		func(md *types.MarketDepth) bool { return markets[md.MarketId] })
   314  	return ch, ref
   315  }
   316  
   317  func (m *MarketDepth) ObserveDepthUpdates(ctx context.Context, retries int, marketIds []string) (<-chan []*types.MarketDepthUpdate, uint64) {
   318  	markets := map[string]bool{}
   319  	for _, id := range marketIds {
   320  		markets[id] = true
   321  	}
   322  
   323  	ch, ref := m.updateObserver.Observe(ctx,
   324  		retries,
   325  		func(md *types.MarketDepthUpdate) bool { return markets[md.MarketId] })
   326  	return ch, ref
   327  }
   328  
   329  /*****************************************************************************/
   330  /*                 FUNCTIONS TO HELP WITH UNIT TESTING                       */
   331  /*****************************************************************************/
   332  
   333  func (m *MarketDepth) GetAllOrders(market string) map[string]*types.Order {
   334  	md := m.marketDepths[market]
   335  	if md != nil {
   336  		return md.LiveOrders
   337  	}
   338  	return nil
   339  }
   340  
   341  // GetOrderCount returns the number of live orders for the given market.
   342  func (m *MarketDepth) GetOrderCount(market string) int64 {
   343  	var liveOrders int64
   344  	var bookOrders uint64
   345  	md := m.marketDepths[market]
   346  	if md != nil {
   347  		liveOrders = int64(len(md.LiveOrders))
   348  
   349  		for _, pl := range md.BuySide {
   350  			bookOrders += pl.TotalOrders
   351  		}
   352  
   353  		for _, pl := range md.SellSide {
   354  			bookOrders += pl.TotalOrders
   355  		}
   356  
   357  		if liveOrders != int64(bookOrders) {
   358  			return -1
   359  		}
   360  		return liveOrders
   361  	}
   362  	return 0
   363  }
   364  
   365  // GetVolumeAtPrice returns the order volume at the given price level.
   366  func (m *MarketDepth) GetVolumeAtPrice(market string, side types.Side, price uint64) uint64 {
   367  	md := m.marketDepths[market]
   368  	if md != nil {
   369  		pl := md.GetPriceLevel(side, num.NewUint(price))
   370  		if pl == nil {
   371  			return 0
   372  		}
   373  		return pl.TotalVolume + pl.TotalAMMVolume
   374  	}
   375  	return 0
   376  }
   377  
   378  // GetVolumeAtPrice returns the order volume at the given price level.
   379  func (m *MarketDepth) GetEstimatedVolumeAtPrice(market string, side types.Side, price uint64) uint64 {
   380  	md := m.marketDepths[market]
   381  	if md != nil {
   382  		pl := md.GetPriceLevel(side, num.NewUint(price))
   383  		if pl == nil {
   384  			return 0
   385  		}
   386  		return pl.TotalEstimatedAMMVolume
   387  	}
   388  	return 0
   389  }
   390  
   391  // GetTotalVolume returns the total volume in the order book.
   392  func (m *MarketDepth) GetTotalVolume(market string) int64 {
   393  	var volume int64
   394  	md := m.marketDepths[market]
   395  	if md != nil {
   396  		for _, pl := range md.BuySide {
   397  			volume += int64(pl.TotalVolume) + int64(pl.TotalAMMVolume) + int64(pl.TotalEstimatedAMMVolume)
   398  		}
   399  
   400  		for _, pl := range md.SellSide {
   401  			volume += int64(pl.TotalVolume) + int64(pl.TotalAMMVolume) + int64(pl.TotalEstimatedAMMVolume)
   402  		}
   403  		return volume
   404  	}
   405  	return 0
   406  }
   407  
   408  // GetAMMVolume returns the total volume in the order book.
   409  func (m *MarketDepth) GetAMMVolume(market string, estimated bool) int64 {
   410  	var volume int64
   411  	md := m.marketDepths[market]
   412  	if md != nil {
   413  		for _, pl := range md.BuySide {
   414  			if estimated {
   415  				volume += int64(pl.TotalEstimatedAMMVolume)
   416  				continue
   417  			}
   418  			volume += int64(pl.TotalAMMVolume)
   419  		}
   420  
   421  		for _, pl := range md.SellSide {
   422  			if estimated {
   423  				volume += int64(pl.TotalEstimatedAMMVolume)
   424  				continue
   425  			}
   426  			volume += int64(pl.TotalAMMVolume)
   427  		}
   428  		return volume
   429  	}
   430  	return 0
   431  }
   432  
   433  // GetAMMVolume returns the total volume in the order book.
   434  func (m *MarketDepth) GetTotalAMMVolume(market string) int64 {
   435  	return m.GetAMMVolume(market, true) + m.GetAMMVolume(market, false)
   436  }
   437  
   438  // GetOrderCountAtPrice returns the number of orders at the given price level.
   439  func (m *MarketDepth) GetOrderCountAtPrice(market string, side types.Side, price uint64) uint64 {
   440  	md := m.marketDepths[market]
   441  	if md != nil {
   442  		pl := md.GetPriceLevel(side, num.NewUint(price))
   443  		if pl == nil {
   444  			return 0
   445  		}
   446  		return pl.TotalOrders
   447  	}
   448  	return 0
   449  }
   450  
   451  // GetPriceLevels returns the number of non empty price levels.
   452  func (m *MarketDepth) GetPriceLevels(market string) int {
   453  	return m.GetBuyPriceLevels(market) + m.GetSellPriceLevels(market)
   454  }
   455  
   456  // GetBestBidPrice returns the highest bid price in the book.
   457  func (m *MarketDepth) GetBestBidPrice(market string) *num.Uint {
   458  	md := m.marketDepths[market]
   459  	if md != nil {
   460  		if len(md.BuySide) > 0 {
   461  			return md.BuySide[0].Price.Clone()
   462  		}
   463  	}
   464  	return num.UintZero()
   465  }
   466  
   467  // GetBestAskPrice returns the highest bid price in the book.
   468  func (m *MarketDepth) GetBestAskPrice(market string) *num.Uint {
   469  	md := m.marketDepths[market]
   470  	if md != nil {
   471  		if len(md.SellSide) > 0 {
   472  			return md.SellSide[0].Price.Clone()
   473  		}
   474  	}
   475  	return num.UintZero()
   476  }
   477  
   478  // GetBuyPriceLevels returns the number of non empty buy price levels.
   479  func (m *MarketDepth) GetBuyPriceLevels(market string) int {
   480  	md := m.marketDepths[market]
   481  	if md != nil {
   482  		return len(md.BuySide)
   483  	}
   484  	return 0
   485  }
   486  
   487  // GetSellPriceLevels returns the number of non empty sell price levels.
   488  func (m *MarketDepth) GetSellPriceLevels(market string) int {
   489  	md := m.marketDepths[market]
   490  	if md != nil {
   491  		return len(md.SellSide)
   492  	}
   493  	return 0
   494  }