code.vegaprotocol.io/vega@v0.79.0/core/liquidity/target/snapshot.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 target 17 18 import ( 19 "context" 20 "time" 21 22 "code.vegaprotocol.io/vega/core/types" 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/libs/proto" 25 snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1" 26 ) 27 28 func newTimestampedOISnapshotFromProto(s *snapshot.TimestampedOpenInterest) timestampedOI { 29 return timestampedOI{ 30 Time: time.Unix(0, s.Time), 31 OI: s.OpenInterest, 32 } 33 } 34 35 func (toi timestampedOI) toSnapshotProto() *snapshot.TimestampedOpenInterest { 36 return &snapshot.TimestampedOpenInterest{ 37 OpenInterest: toi.OI, 38 Time: toi.Time.UnixNano(), 39 } 40 } 41 42 type SnapshotEngine struct { 43 *Engine 44 data []byte 45 stopped bool 46 key string 47 keys []string 48 } 49 50 func NewSnapshotEngine( 51 parameters types.TargetStakeParameters, 52 oiCalc OpenInterestCalculator, 53 marketID string, 54 positionFactor num.Decimal, 55 ) *SnapshotEngine { 56 key := (&types.PayloadLiquidityTarget{ 57 Target: &snapshot.LiquidityTarget{MarketId: marketID}, 58 }).Key() 59 60 return &SnapshotEngine{ 61 Engine: NewEngine(parameters, oiCalc, marketID, positionFactor), 62 key: key, 63 keys: []string{key}, 64 } 65 } 66 67 func (e *SnapshotEngine) UpdateParameters(parameters types.TargetStakeParameters) { 68 e.Engine.UpdateParameters(parameters) 69 } 70 71 func (e *SnapshotEngine) StopSnapshots() { 72 e.stopped = true 73 } 74 75 func (e *SnapshotEngine) RecordOpenInterest(oi uint64, now time.Time) error { 76 if err := e.Engine.RecordOpenInterest(oi, now); err != nil { 77 return err 78 } 79 80 return nil 81 } 82 83 func (e *SnapshotEngine) GetTargetStake(rf types.RiskFactor, now time.Time, markPrice *num.Uint) *num.Uint { 84 ts, _ := e.Engine.GetTargetStake(rf, now, markPrice) 85 86 return ts 87 } 88 89 func (e *SnapshotEngine) GetTheoreticalTargetStake(rf types.RiskFactor, now time.Time, markPrice *num.Uint, trades []*types.Trade) *num.Uint { 90 tts, _ := e.Engine.GetTheoreticalTargetStake(rf, now, markPrice, trades) 91 return tts 92 } 93 94 func (e *SnapshotEngine) Namespace() types.SnapshotNamespace { 95 return types.LiquidityTargetSnapshot 96 } 97 98 func (e *SnapshotEngine) Keys() []string { 99 return e.keys 100 } 101 102 func (e *SnapshotEngine) Stopped() bool { 103 return e.stopped 104 } 105 106 func (e *SnapshotEngine) GetState(k string) ([]byte, []types.StateProvider, error) { 107 if k != e.key { 108 return nil, nil, types.ErrSnapshotKeyDoesNotExist 109 } 110 111 state, err := e.serialise() 112 return state, nil, err 113 } 114 115 func (e *SnapshotEngine) LoadState(_ context.Context, payload *types.Payload) ([]types.StateProvider, error) { 116 if e.Namespace() != payload.Data.Namespace() { 117 return nil, types.ErrInvalidSnapshotNamespace 118 } 119 120 switch pl := payload.Data.(type) { 121 case *types.PayloadLiquidityTarget: 122 123 // Check the payload is for this market 124 if e.marketID != pl.Target.MarketId { 125 return nil, types.ErrUnknownSnapshotType 126 } 127 128 e.now = time.Unix(0, pl.Target.CurrentTime) 129 e.scheduledTruncate = time.Unix(0, pl.Target.ScheduledTruncate) 130 e.current = pl.Target.CurrentOpenInterests 131 e.previous = make([]timestampedOI, 0, len(pl.Target.PreviousOpenInterests)) 132 e.max = newTimestampedOISnapshotFromProto(pl.Target.MaxOpenInterests) 133 134 for _, poi := range pl.Target.PreviousOpenInterests { 135 e.previous = append(e.previous, newTimestampedOISnapshotFromProto(poi)) 136 } 137 138 var err error 139 e.data, err = proto.Marshal(payload.IntoProto()) 140 return nil, err 141 142 default: 143 return nil, types.ErrUnknownSnapshotType 144 } 145 } 146 147 func (e *SnapshotEngine) serialisePrevious() []*snapshot.TimestampedOpenInterest { 148 poi := make([]*snapshot.TimestampedOpenInterest, 0, len(e.previous)) 149 for _, p := range e.previous { 150 poi = append(poi, p.toSnapshotProto()) 151 } 152 return poi 153 } 154 155 // serialise marshal the snapshot state, populating the data fields 156 // with updated values. 157 func (e *SnapshotEngine) serialise() ([]byte, error) { 158 if e.stopped { 159 return nil, nil 160 } 161 162 p := &snapshot.Payload{ 163 Data: &snapshot.Payload_LiquidityTarget{ 164 LiquidityTarget: &snapshot.LiquidityTarget{ 165 MarketId: e.marketID, 166 CurrentTime: e.now.UnixNano(), 167 ScheduledTruncate: e.scheduledTruncate.UnixNano(), 168 CurrentOpenInterests: e.current, 169 PreviousOpenInterests: e.serialisePrevious(), 170 MaxOpenInterests: e.max.toSnapshotProto(), 171 }, 172 }, 173 } 174 175 var err error 176 e.data, err = proto.Marshal(p) 177 if err != nil { 178 return nil, err 179 } 180 return e.data, nil 181 }