code.vegaprotocol.io/vega@v0.79.0/core/execution/spot/spot_monitoring_auction_execution_test.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 spot_test
    17  
    18  import (
    19  	"context"
    20  	"testing"
    21  	"time"
    22  
    23  	"code.vegaprotocol.io/vega/core/types"
    24  	vegacontext "code.vegaprotocol.io/vega/libs/context"
    25  	"code.vegaprotocol.io/vega/libs/crypto"
    26  	"code.vegaprotocol.io/vega/libs/num"
    27  
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestMonitoringAuction(t *testing.T) {
    32  	now := time.Now()
    33  	ctx := context.Background()
    34  	ctx = vegacontext.WithTraceID(ctx, crypto.RandomHash())
    35  	tm := newTestMarket(t, defaultPriceMonitorSettings, &types.AuctionDuration{Duration: 1}, now)
    36  
    37  	addAccountWithAmount(tm, "party1", 100000, "ETH")
    38  	addAccountWithAmount(tm, "party2", 5, "BTC")
    39  
    40  	tm.market.StartOpeningAuction(ctx)
    41  
    42  	order1 := getGTCLimitOrder(tm, now, crypto.RandomHash(), types.SideBuy, "party1", 2, 30000)
    43  	conf1, err := tm.market.SubmitOrder(ctx, order1.IntoSubmission(), order1.Party, crypto.RandomHash())
    44  	require.NoError(t, err)
    45  
    46  	order2 := getGTCLimitOrder(tm, now, crypto.RandomHash(), types.SideSell, "party2", 1, 30000)
    47  	_, err = tm.market.SubmitOrder(ctx, order2.IntoSubmission(), order2.Party, crypto.RandomHash())
    48  	require.NoError(t, err)
    49  
    50  	tm.market.OnTick(ctx, now.Add(2*time.Second))
    51  	md := tm.market.GetMarketData()
    52  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
    53  
    54  	// at this point party 1 bought 1 BTC and has one outstanding order at price 30k as we've left opening auction
    55  	gaBalance1, err := tm.collateralEngine.GetPartyGeneralAccount("party1", tm.quoteAsset)
    56  	require.NoError(t, err)
    57  	require.Equal(t, "40000", gaBalance1.Balance.String())
    58  	haBalance1, err := tm.collateralEngine.GetPartyHoldingAccount("party1", tm.quoteAsset)
    59  	require.NoError(t, err)
    60  	require.Equal(t, "30000", haBalance1.Balance.String())
    61  	gaBaseBalance1, err := tm.collateralEngine.GetPartyGeneralAccount("party1", tm.baseAsset)
    62  	require.NoError(t, err)
    63  	require.Equal(t, "1", gaBaseBalance1.Balance.String())
    64  
    65  	// move the price of the remaining order of party1 significantly
    66  	_, err = tm.market.AmendOrder(ctx, &types.OrderAmendment{OrderID: conf1.Order.ID, Price: num.NewUint(10000)}, "party1", crypto.RandomHash())
    67  	require.NoError(t, err)
    68  
    69  	gaBalance1, err = tm.collateralEngine.GetPartyGeneralAccount("party1", tm.quoteAsset)
    70  	require.NoError(t, err)
    71  	require.Equal(t, "60000", gaBalance1.Balance.String())
    72  	haBalance1, err = tm.collateralEngine.GetPartyHoldingAccount("party1", tm.quoteAsset)
    73  	require.NoError(t, err)
    74  	require.Equal(t, "10000", haBalance1.Balance.String())
    75  
    76  	order3 := getGTCLimitOrder(tm, now, crypto.RandomHash(), types.SideSell, "party2", 1, 10000)
    77  	_, err = tm.market.SubmitOrder(ctx, order3.IntoSubmission(), order3.Party, crypto.RandomHash())
    78  	require.NoError(t, err)
    79  
    80  	tm.market.OnTick(ctx, now.Add(2*time.Second))
    81  	md = tm.market.GetMarketData()
    82  	// we're in price monitoring!!!
    83  	require.Equal(t, types.MarketTradingModeMonitoringAuction, md.MarketTradingMode)
    84  
    85  	// check that the buyer transfers into holding the expected fees amounts
    86  	gaBalance1, err = tm.collateralEngine.GetPartyGeneralAccount("party1", tm.quoteAsset)
    87  	require.NoError(t, err)
    88  	require.Equal(t, "59995", gaBalance1.Balance.String())
    89  	haBalance1, err = tm.collateralEngine.GetPartyHoldingAccount("party1", tm.quoteAsset)
    90  	require.NoError(t, err)
    91  	require.Equal(t, "10005", haBalance1.Balance.String())
    92  
    93  	gaBalance2, err := tm.collateralEngine.GetPartyGeneralAccount("party2", tm.quoteAsset)
    94  	require.NoError(t, err)
    95  	require.Equal(t, "30000", gaBalance2.Balance.String())
    96  
    97  	tm.market.OnTick(ctx, now.Add(60*time.Minute))
    98  	md = tm.market.GetMarketData()
    99  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   100  
   101  	// we're out of the monitoring auction. expect the trade to have happened and both parties paying fees
   102  	// both pay infra fee, none gets maker fee as we're in auction
   103  	gaBalance1, err = tm.collateralEngine.GetPartyGeneralAccount("party1", tm.quoteAsset)
   104  	require.NoError(t, err)
   105  	require.Equal(t, "59995", gaBalance1.Balance.String())
   106  	haBalance1, err = tm.collateralEngine.GetPartyHoldingAccount("party1", tm.quoteAsset)
   107  	require.NoError(t, err)
   108  	require.Equal(t, "0", haBalance1.Balance.String())
   109  	gaBaseBalance1, err = tm.collateralEngine.GetPartyGeneralAccount("party1", tm.baseAsset)
   110  	require.NoError(t, err)
   111  	require.Equal(t, "2", gaBaseBalance1.Balance.String())
   112  
   113  	gaBaseBalance2, err := tm.collateralEngine.GetPartyGeneralAccount("party2", tm.baseAsset)
   114  	require.NoError(t, err)
   115  	require.Equal(t, "3", gaBaseBalance2.Balance.String())
   116  	gaalance2, err := tm.collateralEngine.GetPartyGeneralAccount("party2", tm.quoteAsset)
   117  	require.NoError(t, err)
   118  	require.Equal(t, "39995", gaalance2.Balance.String())
   119  }
   120  
   121  func TestMonitoringAuctionInsufficientFundsToCoverFeesOnAmend(t *testing.T) {
   122  	now := time.Now()
   123  	ctx := context.Background()
   124  	ctx = vegacontext.WithTraceID(ctx, crypto.RandomHash())
   125  	tm := newTestMarket(t, defaultPriceMonitorSettings, &types.AuctionDuration{Duration: 1}, now)
   126  
   127  	addAccountWithAmount(tm, "party1", 100000, "ETH")
   128  	addAccountWithAmount(tm, "party2", 5, "BTC")
   129  
   130  	tm.market.StartOpeningAuction(ctx)
   131  
   132  	order1 := getGTCLimitOrder(tm, now, crypto.RandomHash(), types.SideBuy, "party1", 2, 30000)
   133  	conf1, err := tm.market.SubmitOrder(ctx, order1.IntoSubmission(), order1.Party, crypto.RandomHash())
   134  	require.NoError(t, err)
   135  
   136  	order2 := getGTCLimitOrder(tm, now, crypto.RandomHash(), types.SideSell, "party2", 1, 30000)
   137  	_, err = tm.market.SubmitOrder(ctx, order2.IntoSubmission(), order2.Party, crypto.RandomHash())
   138  	require.NoError(t, err)
   139  
   140  	tm.market.OnTick(ctx, now.Add(2*time.Second))
   141  	md := tm.market.GetMarketData()
   142  	require.Equal(t, types.MarketTradingModeContinuous, md.MarketTradingMode)
   143  
   144  	// move the price of the remaining order of party1 significantly
   145  	_, err = tm.market.AmendOrder(ctx, &types.OrderAmendment{OrderID: conf1.Order.ID, Price: num.NewUint(10000)}, "party1", crypto.RandomHash())
   146  	require.NoError(t, err)
   147  
   148  	// submit an order to get us into price monitoring auction
   149  	order3 := getGTCLimitOrder(tm, now, crypto.RandomHash(), types.SideSell, "party2", 1, 10000)
   150  	_, err = tm.market.SubmitOrder(ctx, order3.IntoSubmission(), order3.Party, crypto.RandomHash())
   151  	require.NoError(t, err)
   152  
   153  	tm.market.OnTick(ctx, now.Add(2*time.Second))
   154  	md = tm.market.GetMarketData()
   155  	// we're in price monitoring!!!
   156  	require.Equal(t, types.MarketTradingModeMonitoringAuction, md.MarketTradingMode)
   157  
   158  	// try to increase the size by 6 for party 1, this would require them to have in their general account 60k + infra fee which they don't have so expect a failure
   159  	_, err = tm.market.AmendOrder(ctx, &types.OrderAmendment{OrderID: conf1.Order.ID, Price: num.NewUint(10000), SizeDelta: 6}, "party1", crypto.RandomHash())
   160  	require.Equal(t, "party does not have sufficient balance to cover the trade and fees", err.Error())
   161  }