code.vegaprotocol.io/vega@v0.79.0/core/execution/future/isolated_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/positions" 23 "code.vegaprotocol.io/vega/core/types" 24 "code.vegaprotocol.io/vega/libs/num" 25 ) 26 27 func (m *Market) updateIsolatedMarginsOnPositionChange(ctx context.Context, mpos *positions.MarketPosition, order *types.Order, trade *types.Trade) error { 28 pos, err := m.collateral.GetPartyMargin(mpos, m.settlementAsset, m.GetID()) 29 if err != nil { 30 return err 31 } 32 price := m.getMarketObservable(order.Price.Clone()) 33 increment := m.tradableInstrument.Instrument.Product.GetMarginIncrease(m.timeService.GetTimeNow().UnixNano()) 34 orders := m.matching.GetOrdersPerParty(order.Party) 35 marginFactor := m.getMarginFactor(order.Party) 36 r, err := m.risk.UpdateIsolatedMarginsOnPositionChange(ctx, pos, price, increment, orders, []*types.Trade{trade}, order.Side, marginFactor) 37 if err != nil { 38 return err 39 } 40 for _, rr := range r { 41 m.transferMargins(ctx, []events.Risk{rr}, nil) 42 } 43 pos, err = m.collateral.GetPartyMargin(mpos, m.settlementAsset, m.GetID()) 44 if err != nil { 45 return err 46 } 47 _, err = m.risk.CheckMarginInvariants(ctx, pos, price, increment, orders, marginFactor) 48 return err 49 } 50 51 func (m *Market) getIsolatedMarginContext(mpos *positions.MarketPosition, order *types.Order) (*num.Uint, events.Margin, num.Decimal, *num.Uint, num.Decimal, []*types.Order, error) { 52 var orderPrice *num.Uint 53 if order != nil { 54 orderPrice = order.Price.Clone() 55 } else { 56 orderPrice = num.UintZero() 57 } 58 marketObservable := m.getMarketObservable(orderPrice) 59 mID := m.GetID() 60 pos, err := m.collateral.GetPartyMargin(mpos, m.settlementAsset, mID) 61 if err != nil { 62 return nil, nil, num.DecimalZero(), nil, num.DecimalZero(), nil, err 63 } 64 increment := m.tradableInstrument.Instrument.Product.GetMarginIncrease(m.timeService.GetTimeNow().UnixNano()) 65 auctionPrice := m.getAuctionPrice() 66 marginFactor := m.getMarginFactor(mpos.Party()) 67 orders := m.matching.GetOrdersPerParty(mpos.Party()) 68 return marketObservable, pos, increment, auctionPrice, marginFactor, orders, nil 69 } 70 71 func (m *Market) getAuctionPrice() *num.Uint { 72 var auctionPrice *num.Uint 73 if m.as.InAuction() { 74 if m.capMax != nil && m.fCap.FullyCollateralised { 75 // if this is a capped market with max price, this is the price we need to use all the time 76 // this function is called to calculate margins, and margin calculations are always going to be based on the max price. 77 return m.capMax.Clone() 78 } 79 auctionPrice = m.matching.GetIndicativePrice() 80 if markPrice := m.getCurrentMarkPrice(); markPrice != nil && !markPrice.IsZero() && (markPrice.GT(auctionPrice) || auctionPrice == nil) { 81 auctionPrice = markPrice 82 } 83 } 84 return auctionPrice 85 }