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 }