code.vegaprotocol.io/vega@v0.79.0/core/execution/future/margin.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 future
    17  
    18  import (
    19  	"context"
    20  
    21  	"code.vegaprotocol.io/vega/core/events"
    22  	"code.vegaprotocol.io/vega/core/execution/common"
    23  	"code.vegaprotocol.io/vega/core/positions"
    24  	"code.vegaprotocol.io/vega/core/types"
    25  	"code.vegaprotocol.io/vega/logging"
    26  )
    27  
    28  func (m *Market) calcMargins(ctx context.Context, pos *positions.MarketPosition, order *types.Order) ([]events.Risk, []events.MarketPosition, error) {
    29  	if m.as.InAuction() {
    30  		return m.marginsAuction(ctx, order)
    31  	}
    32  	return m.margins(ctx, pos, order)
    33  }
    34  
    35  func (m *Market) updateMargin(ctx context.Context, pos []events.MarketPosition) []events.Risk {
    36  	price := m.getCurrentMarkPriceForMargin()
    37  	mID := m.GetID()
    38  	margins := make([]events.Margin, 0, len(pos))
    39  	for _, p := range pos {
    40  		e, err := m.collateral.GetPartyMargin(p, m.settlementAsset, mID)
    41  		if err != nil {
    42  			m.log.Error("Failed to get margin event for party position",
    43  				logging.String("party", p.Party()),
    44  				logging.Error(err),
    45  			)
    46  			continue
    47  		}
    48  		// add the required margin event
    49  		margins = append(margins, e)
    50  	}
    51  	// we should get any and all risk events we need here
    52  	increment := m.tradableInstrument.Instrument.Product.GetMarginIncrease(m.timeService.GetTimeNow().UnixNano())
    53  	return m.risk.UpdateMarginsOnSettlement(ctx, margins, price, increment, m.getAuctionPrice())
    54  }
    55  
    56  func (m *Market) marginsAuction(ctx context.Context, order *types.Order) ([]events.Risk, []events.MarketPosition, error) {
    57  	cPos, ok := m.position.GetPositionByPartyID(order.Party)
    58  	if !ok {
    59  		return nil, nil, nil
    60  	}
    61  	mID := m.GetID()
    62  	e, err := m.collateral.GetPartyMargin(cPos, m.settlementAsset, mID)
    63  	if err != nil {
    64  		return nil, nil, err
    65  	}
    66  	increment := m.tradableInstrument.Instrument.Product.GetMarginIncrease(m.timeService.GetTimeNow().UnixNano())
    67  	risk, closed := m.risk.UpdateMarginAuction(ctx, []events.Margin{e}, m.getMarketObservable(order.Price.Clone()), increment, m.getAuctionPrice())
    68  	if len(closed) > 0 {
    69  		// this order would take party below maintenance -> stop here
    70  		return nil, nil, common.ErrMarginCheckInsufficient
    71  	}
    72  	return risk, nil, nil
    73  }
    74  
    75  func (m *Market) margins(ctx context.Context, mpos *positions.MarketPosition, order *types.Order) ([]events.Risk, []events.MarketPosition, error) {
    76  	price := m.getMarketObservable(order.Price.Clone())
    77  	mID := m.GetID()
    78  	pos, err := m.collateral.GetPartyMargin(mpos, m.settlementAsset, mID)
    79  	if err != nil {
    80  		return nil, nil, err
    81  	}
    82  	increment := m.tradableInstrument.Instrument.Product.GetMarginIncrease(m.timeService.GetTimeNow().UnixNano())
    83  	risk, evt, err := m.risk.UpdateMarginOnNewOrder(ctx, pos, price.Clone(), increment, m.getAuctionPrice())
    84  	if err != nil {
    85  		return nil, nil, err
    86  	}
    87  	if risk == nil {
    88  		return nil, nil, nil
    89  	}
    90  	if evt != nil {
    91  		return []events.Risk{risk}, []events.MarketPosition{evt}, nil
    92  	}
    93  	return []events.Risk{risk}, nil, nil
    94  }