code.vegaprotocol.io/vega@v0.79.0/core/liquidity/supplied/statevar_test.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 supplied 17 18 import ( 19 "testing" 20 21 "code.vegaprotocol.io/vega/core/risk/models" 22 "code.vegaprotocol.io/vega/core/types" 23 "code.vegaprotocol.io/vega/libs/num" 24 25 "github.com/stretchr/testify/require" 26 ) 27 28 var ( 29 min = num.DecimalZero() 30 max = num.MaxUint().ToDecimal() 31 ) 32 33 func TestBidRange(t *testing.T) { 34 prob := calculateBidRange(num.DecimalFromFloat(100), num.DecimalFromFloat(0.01), num.DecimalFromInt64(1), pOfT) 35 require.Equal(t, 100, len(prob)) 36 for i := range prob { 37 require.Equal(t, num.DecimalFromFloat(1.0).Sub(num.DecimalFromInt64(int64(i)).Div(num.DecimalFromFloat(100))).String(), prob[i].String()) 38 } 39 40 prob2 := calculateBidRange(num.DecimalFromFloat(200), num.DecimalFromFloat(0.01), num.DecimalFromInt64(1), pOfT) 41 require.Equal(t, 100, len(prob2)) 42 for i := range prob2 { 43 require.Equal(t, num.DecimalFromFloat(1.0).Sub(num.DecimalFromInt64(int64(i)).Div(num.DecimalFromFloat(100))).String(), prob2[i].String()) 44 } 45 } 46 47 func TestAskRange(t *testing.T) { 48 prob := calculateAskRange(num.DecimalFromFloat(100), num.DecimalFromFloat(0.01), num.DecimalFromInt64(1), pOfT) 49 require.Equal(t, 100, len(prob)) 50 for i := range prob { 51 require.Equal(t, num.DecimalFromFloat(1.0).Sub(num.DecimalFromInt64(int64(i)).Div(num.DecimalFromFloat(100))).String(), prob[i].String()) 52 } 53 54 prob2 := calculateAskRange(num.DecimalFromFloat(200), num.DecimalFromFloat(0.01), num.DecimalFromInt64(1), pOfT) 55 require.Equal(t, 100, len(prob2)) 56 for i := range prob2 { 57 require.Equal(t, num.DecimalFromFloat(1.0).Sub(num.DecimalFromInt64(int64(i)).Div(num.DecimalFromFloat(100))).String(), prob[i].String()) 58 } 59 } 60 61 func TestBidRangeAtTheEdge(t *testing.T) { 62 params := &types.LogNormalRiskModel{ 63 RiskAversionParameter: num.DecimalFromFloat(0.001), 64 Tau: num.DecimalFromFloat(0o0011407711613050422), 65 Params: &types.LogNormalModelParams{ 66 R: num.DecimalFromFloat(0.016), 67 Sigma: num.DecimalFromFloat(1.5), 68 }, 69 } 70 risk, _ := models.NewBuiltinFutures(params, "asset") 71 72 p := calculateBidRange(num.DecimalFromFloat(900), num.DecimalFromFloat(0.001), num.DecimalFromFloat(0.00012345), risk.ProbabilityOfTrading) 73 74 require.Equal(t, 92, len(p)) 75 76 pot := &probabilityOfTrading{ 77 bidProbability: p, 78 bidOffset: []uint32{0, 40}, 79 } 80 minProb := num.DecimalFromFloat(0.021) 81 82 // order price 899, best bid 900 83 // offset is therefore int(1600*(900-899)/900) = 1 84 // so we're interpolating between the probability 1 at offset 0 and probability of 0.9524363412970467 at offset 40 85 // so expecting scaled probability to be (0.975*1 + 0.025*0.9524363412970467)/2 = 0.4999762182 86 require.Equal(t, "0.4994054543", getProbabilityOfTrading(num.DecimalFromFloat(900), num.DecimalFromFloat(900), num.DecimalZero(), num.MaxDecimal(), pot, num.DecimalFromFloat(899), true, minProb, num.DecimalFromInt64(1600)).StringFixed(10)) 87 } 88 89 func pOfT(best, p, min, max, tauScaled num.Decimal, isBid bool, applyMinMax bool) num.Decimal { 90 if p.LessThanOrEqual(num.DecimalZero()) { 91 return defaultMinimumProbabilityOfTrading 92 } 93 if p.GreaterThanOrEqual(num.DecimalFromInt64(2).Mul(best)) { 94 return defaultMinimumProbabilityOfTrading 95 } 96 return num.DecimalFromFloat(1).Sub(best.Sub(p).Abs().Div(best)) 97 } 98 99 func TestGetProbability(t *testing.T) { 100 offsetFactor := num.DecimalFromInt64(1000000) 101 minProb := num.DecimalFromFloat(0.21) 102 103 // no consensus yet within 20% ticks (bid) 104 require.Equal(t, defaultInRangeProbabilityOfTrading.String(), getProbabilityOfTrading(num.DecimalFromFloat(200000), num.DecimalFromFloat(600), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(160000), true, minProb, offsetFactor).String()) 105 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(200000), num.DecimalFromFloat(600), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(159999), true, minProb, offsetFactor).String()) 106 107 // no consensus yet within 20% ticks (ask) 108 require.Equal(t, defaultInRangeProbabilityOfTrading.String(), getProbabilityOfTrading(num.DecimalFromFloat(100000), num.DecimalFromFloat(200000), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(240000), false, minProb, offsetFactor).String()) 109 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(100000), num.DecimalFromFloat(200000), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(240001), false, minProb, offsetFactor).String()) 110 111 // price is GTE best bid and LTE best ask - use defaultInRangeProbabilityOfTrading 112 require.Equal(t, defaultInRangeProbabilityOfTrading, getProbabilityOfTrading(num.DecimalFromFloat(120), num.DecimalFromFloat(220), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(120), true, minProb, offsetFactor)) 113 require.Equal(t, defaultInRangeProbabilityOfTrading, getProbabilityOfTrading(num.DecimalFromFloat(120), num.DecimalFromFloat(220), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(121), true, minProb, offsetFactor)) 114 require.Equal(t, defaultInRangeProbabilityOfTrading, getProbabilityOfTrading(num.DecimalFromFloat(120), num.DecimalFromFloat(220), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(220), false, minProb, offsetFactor)) 115 require.Equal(t, defaultInRangeProbabilityOfTrading, getProbabilityOfTrading(num.DecimalFromFloat(120), num.DecimalFromFloat(220), min, max, &probabilityOfTrading{}, num.DecimalFromInt64(219), false, minProb, offsetFactor)) 116 117 bProb := calculateBidRange(num.DecimalFromFloat(400), num.DecimalFromFloat(0.001), num.DecimalFromFloat(1), pOfT) 118 aProb := calculateAskRange(num.DecimalFromFloat(600), num.DecimalFromFloat(0.001), num.DecimalFromInt64(1), pOfT) 119 120 bOffsets := make([]uint32, 0, len(bProb)) 121 aOffsets := make([]uint32, 0, len(aProb)) 122 123 for i := range bProb { 124 bOffsets = append(bOffsets, uint32(i*1000)) 125 } 126 for i := range aProb { 127 aOffsets = append(aOffsets, uint32(i*1000)) 128 } 129 130 pot := &probabilityOfTrading{ 131 bidOffset: bOffsets, 132 bidProbability: bProb, 133 askOffset: aOffsets, 134 askProbability: aProb, 135 } 136 137 // find exact match bid side - offset of 200 is the middle point of the probabilities so should have probability of 0.5 scaled by 0.5 138 require.Equal(t, "0.25", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(200), true, minProb, offsetFactor).String()) 139 // linterp bid => (0.75*0.5+0.25*0.51)/2 140 require.Equal(t, "0.25125", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(201), true, minProb, offsetFactor).String()) 141 // linterp bid => (0.5*0.5+0.5*0.51)/2 142 require.Equal(t, "0.2525", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(202), true, minProb, offsetFactor).String()) 143 // linterp bid => (0.25*0.5+0.75*0.51)/2 144 require.Equal(t, "0.25375", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(203), true, minProb, offsetFactor).String()) 145 // linterp bid => (0*0.5+1*0.51)/2 146 require.Equal(t, "0.255", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(204), true, minProb, offsetFactor).String()) 147 148 // linterp bid => max(0.2, 0.21) = 0.21 149 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(100), true, minProb, offsetFactor).String()) 150 // linterp bid => max(0.75*0 + 0.5*0.2, minProb) = 0.21 151 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(101), true, minProb, offsetFactor).String()) 152 // linterp bid => max(0.5*0 + 0.5*0.2, minProb) = 0.21 153 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(102), true, minProb, offsetFactor).String()) 154 // linterp bid => max(0.25*0 + 0.5*0.2, minProb) = 0.21 155 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(103), true, minProb, offsetFactor).String()) 156 157 // find exact match ask side - offset of 200 is the middle point of the probabilities so should have probability of 0.5 scaled by 0.5 158 require.Equal(t, "0.25", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(900), false, minProb, offsetFactor).String()) 159 // linterp ask => (0.75*0.5+0.25*0.51)/2 160 require.Equal(t, "0.25125", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromFloat(898.5), false, minProb, offsetFactor).String()) 161 // linterp ask => (0.5*0.5+0.5*0.51)/2 162 require.Equal(t, "0.2525", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(897), false, minProb, offsetFactor).String()) 163 // linterp ask => (0.25*0.5+0.75*0.51)/2 164 require.Equal(t, "0.25375", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromFloat(895.5), false, minProb, offsetFactor).String()) 165 // linterp ask => (0*0.5+1*0.51)/2 166 require.Equal(t, "0.255", getProbabilityOfTrading(num.DecimalFromFloat(400), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(894), false, minProb, offsetFactor).String()) 167 168 // linterp ask => max(0, minProb) = 0.21 169 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(1000), false, minProb, offsetFactor).String()) 170 // linterp ask => max(0.75*0 + 0.5*0.01, minProb) = 0.21 171 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(999), false, minProb, offsetFactor).String()) 172 // linterp ask => max(0.5*0 + 0.5*0.01, minProb) = 0.21 173 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(998), false, minProb, offsetFactor).String()) 174 // linterp ask => max(0.25*0 + 0.5*0.01, minProb) = 0.21 175 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, pot, num.DecimalFromInt64(997), false, minProb, offsetFactor).String()) 176 177 // // extrapolating 178 potForExtrapolation := &probabilityOfTrading{ 179 bidOffset: []uint32{0, 1000 * 100}, 180 askOffset: []uint32{0, 1000 * 100}, 181 bidProbability: []num.Decimal{num.DecimalFromFloat(0.9), num.DecimalFromFloat(0.5)}, 182 askProbability: []num.Decimal{num.DecimalFromFloat(0.9), num.DecimalFromFloat(0.5)}, 183 } 184 185 // ask 186 require.Equal(t, "0.05", getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, potForExtrapolation, num.DecimalFromInt64(720), false, num.DecimalZero(), offsetFactor).String()) 187 // too far, floored at min prob 188 require.Equal(t, minProb.String(), getProbabilityOfTrading(num.DecimalFromFloat(500), num.DecimalFromFloat(600), min, max, potForExtrapolation, num.DecimalFromInt64(10000), false, minProb, offsetFactor).String()) 189 }