diff --git a/core/execution/amm/estimator.go b/core/execution/amm/estimator.go index 18cf4db75c..db062ac936 100644 --- a/core/execution/amm/estimator.go +++ b/core/execution/amm/estimator.go @@ -75,7 +75,7 @@ func EstimateBounds( l: l, high: basePrice, low: lowerPrice, - sqrtHigh: sqrter.sqrt(upperPrice), + sqrtHigh: sqrter.sqrt(basePrice), isLower: true, pv: r.PositionSizeAtLower, } diff --git a/core/execution/amm/estimator_test.go b/core/execution/amm/estimator_test.go index 0355b8c022..f17e136cb7 100644 --- a/core/execution/amm/estimator_test.go +++ b/core/execution/amm/estimator_test.go @@ -238,3 +238,60 @@ func TestEstimatePositionFactor(t *testing.T) { assert.False(t, metrics.TooWideLower) // is valid as there are less than 10 empty price levels assert.True(t, metrics.TooWideUpper) // isn't valid as there are more than 10 empty price levels } + +func TestEstimateBoundsOneSided(t *testing.T) { + initialMargin := num.DecimalFromFloat(1) + riskFactorShort := num.DecimalFromFloat(0.01) + riskFactorLong := num.DecimalFromFloat(0.01) + linearSlippageFactor := num.DecimalFromFloat(0) + sqrter := NewSqrter() + + lowerPrice := num.NewUint(900) + basePrice := num.NewUint(1000) + upperPrice := num.NewUint(1100) + leverageUpper := num.DecimalFromFloat(2.00) + leverageLower := num.DecimalFromFloat(2.00) + balance := num.NewUint(100) + + // no upper bound supplied + metrics := EstimateBounds( + sqrter, + lowerPrice, + basePrice, + nil, + leverageLower, + leverageUpper, + balance, + linearSlippageFactor, + initialMargin, + riskFactorShort, + riskFactorLong, + num.DecimalOne(), + num.DecimalOne(), + 0, + ) + assert.True(t, metrics.LiquidationPriceAtUpper.IsZero()) + assert.True(t, metrics.PositionSizeAtUpper.IsZero()) + assert.True(t, metrics.LossOnCommitmentAtUpper.IsZero()) + + // no lower bound supplied + metrics = EstimateBounds( + sqrter, + nil, + basePrice, + upperPrice, + leverageLower, + leverageUpper, + balance, + linearSlippageFactor, + initialMargin, + riskFactorShort, + riskFactorLong, + num.DecimalOne(), + num.DecimalOne(), + 0, + ) + assert.True(t, metrics.LiquidationPriceAtLower.IsZero()) + assert.True(t, metrics.PositionSizeAtLower.IsZero()) + assert.True(t, metrics.LossOnCommitmentAtLower.IsZero()) +} diff --git a/datanode/service/market_depth_amm.go b/datanode/service/market_depth_amm.go index 412bb8fa78..c5c5d06ec3 100644 --- a/datanode/service/market_depth_amm.go +++ b/datanode/service/market_depth_amm.go @@ -233,8 +233,11 @@ func (m *MarketDepth) getReference(ctx context.Context, marketID string) (num.De } func (m *MarketDepth) expandByLevels(pool entities.AMMPool, levels []*level, priceFactor num.Decimal) ([]*types.Order, []bool, error) { - // get positions + if len(levels) == 0 { + return nil, nil, nil + } + // get position pos, err := m.getAMMPosition(pool.MarketID.String(), pool.AmmPartyID.String()) if err != nil { return nil, nil, err diff --git a/datanode/service/market_depth_amm_test.go b/datanode/service/market_depth_amm_test.go index 09fe4610e1..c267d7fa7f 100644 --- a/datanode/service/market_depth_amm_test.go +++ b/datanode/service/market_depth_amm_test.go @@ -472,6 +472,34 @@ func TestFairgroundAMM(t *testing.T) { assert.Equal(t, "12956", mds.service.GetBestAskPrice(marketID).String()) } +func TestAMMDepthOutOfRange(t *testing.T) { + ctx := context.Background() + + cfg := service.MarketDepthConfig{ + AmmFullExpansionPercentage: 200, + AmmEstimatedStepPercentage: 0, + AmmMaxEstimatedSteps: 0, + } + mds := getServiceWithConfig(t, cfg) + defer mds.ctrl.Finish() + + marketID := vgcrypto.RandomHash() + + ensureLiveOrders(t, mds, marketID) + ensureDecimalPlaces(t, mds, 1, 1) + + // set the mid-price to a value no where near the AMM's prices + mds.marketData.EXPECT().GetMarketDataByID(gomock.Any(), gomock.Any()).Times(1).Return(entities.MarketData{MidPrice: num.DecimalFromInt64(10)}, nil) + + // data node is starting from network history, initialise market-depth based on whats aleady there + ensureAMMs(t, mds, marketID) + mds.service.Initialise(ctx) + + assert.Equal(t, 0, int(mds.service.GetTotalAMMVolume(marketID))) + assert.Equal(t, 0, int(mds.service.GetAMMVolume(marketID, true))) + assert.Equal(t, 0, int(mds.service.GetAMMVolume(marketID, false))) +} + func ensureLiveOrders(t *testing.T, mds *MDS, marketID string) { t.Helper() mds.orders.EXPECT().GetLiveOrders(gomock.Any()).Return([]entities.Order{