code.vegaprotocol.io/vega@v0.79.0/core/monitor/price/statevar.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 price 17 18 import ( 19 "context" 20 "errors" 21 22 "code.vegaprotocol.io/vega/core/types/statevar" 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/logging" 25 ) 26 27 type boundFactorsConverter struct{} 28 29 func (boundFactorsConverter) BundleToInterface(kvb *statevar.KeyValueBundle) statevar.StateVariableResult { 30 return &boundFactors{ 31 up: kvb.KVT[0].Val.(*statevar.DecimalVector).Val, 32 down: kvb.KVT[1].Val.(*statevar.DecimalVector).Val, 33 } 34 } 35 36 func (boundFactorsConverter) InterfaceToBundle(res statevar.StateVariableResult) *statevar.KeyValueBundle { 37 value := res.(*boundFactors) 38 return &statevar.KeyValueBundle{ 39 KVT: []statevar.KeyValueTol{ 40 {Key: "up", Val: &statevar.DecimalVector{Val: value.up}, Tolerance: tolerance}, 41 {Key: "down", Val: &statevar.DecimalVector{Val: value.down}, Tolerance: tolerance}, 42 }, 43 } 44 } 45 46 func (e *Engine) IsBoundFactorsInitialised() bool { 47 return e.boundFactorsInitialised 48 } 49 50 // startCalcPriceRanges kicks off the bounds factors calculation, done asynchronously for illustration. 51 func (e *Engine) startCalcPriceRanges(eventID string, endOfCalcCallback statevar.FinaliseCalculation) { 52 if e.log.GetLevel() <= logging.DebugLevel { 53 e.log.Debug("price range factors calculation started", logging.String("event-id", eventID)) 54 } 55 56 down := make([]num.Decimal, 0, len(e.bounds)) 57 up := make([]num.Decimal, 0, len(e.bounds)) 58 59 // if we have no reference price, just abort and wait for the next round 60 if len(e.pricesPast) < 1 && len(e.pricesNow) < 1 { 61 e.log.Info("no reference price available for market - cannot calculate price ranges", logging.String("event-id", eventID)) 62 endOfCalcCallback.CalculationFinished(eventID, nil, errors.New("no reference price available for market - cannot calculate price ranges")) 63 return 64 } 65 66 for _, b := range e.bounds { 67 ref := e.getRefPriceNoUpdate(b.Trigger.Horizon) 68 minPrice, maxPrice := e.riskModel.PriceRange(ref, e.fpHorizons[b.Trigger.Horizon], b.Trigger.Probability) 69 down = append(down, minPrice.Div(ref)) 70 up = append(up, maxPrice.Div(ref)) 71 } 72 res := &boundFactors{ 73 down: down, 74 up: up, 75 } 76 77 if e.log.GetLevel() <= logging.DebugLevel { 78 e.log.Debug("price range factors calculation completed", logging.String("event-id", eventID), logging.String("asset", e.asset), logging.String("market", e.market)) 79 } 80 endOfCalcCallback.CalculationFinished(eventID, res, nil) 81 } 82 83 // updatePriceBounds is called back from the state variable consensus engine when consensus is reached for the down/up factors and updates the price bounds. 84 func (e *Engine) updatePriceBounds(ctx context.Context, res statevar.StateVariableResult) error { 85 bRes := res.(*boundFactors) 86 e.updateFactors(bRes.down, bRes.up) 87 if e.log.GetLevel() <= logging.DebugLevel { 88 e.log.Debug("consensus reached for price ranges", logging.String("asset", e.asset), logging.String("market", e.market)) 89 } 90 return nil 91 } 92 93 func (e *Engine) updateFactors(down, up []num.Decimal) { 94 for i, b := range e.bounds { 95 b.DownFactor = down[i] 96 b.UpFactor = up[i] 97 } 98 e.boundFactorsInitialised = true 99 // force invalidation of the price range cache 100 if len(e.pricesNow) > 0 { 101 e.getCurrentPriceRanges(true) 102 } 103 104 e.clearStalePrices() 105 e.stateChanged = true 106 }