code.vegaprotocol.io/vega@v0.79.0/core/execution/amm/estimator_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 amm 17 18 import ( 19 "testing" 20 21 "code.vegaprotocol.io/vega/libs/num" 22 23 "github.com/stretchr/testify/assert" 24 ) 25 26 func TestEstimateSeparateFunctions(t *testing.T) { 27 balance := num.NewUint(100) 28 lowerPrice := num.NewUint(900) 29 basePrice := num.NewUint(1000) 30 upperPrice := num.NewUint(1300) 31 leverageAtUpper := num.NewDecimalFromFloat(1.00) 32 leverageAtLower := num.NewDecimalFromFloat(5.00) 33 sqrter := NewSqrter() 34 35 shortRiskFactor := num.NewDecimalFromFloat(0.01) 36 longRiskFactor := num.NewDecimalFromFloat(0.01) 37 linearSlippage := num.NewDecimalFromFloat(0.05) 38 initialMargin := num.DecimalOne() 39 40 // test liquidity unit 41 unitLower := LiquidityUnit(sqrter, basePrice, lowerPrice) 42 unitUpper := LiquidityUnit(sqrter, upperPrice, basePrice) 43 44 assert.Equal(t, num.DecimalFromFloat(584.6049894).String(), unitLower.Round(7).String()) 45 assert.Equal(t, num.DecimalFromFloat(257.2170745).String(), unitUpper.Round(7).String()) 46 47 // test average entry price 48 avgEntryLower := AverageEntryPrice(sqrter, unitLower, basePrice) 49 avgEntryUpper := AverageEntryPrice(sqrter, unitUpper, upperPrice) 50 assert.Equal(t, num.DecimalFromFloat(948.683).String(), avgEntryLower.Round(3).String()) 51 assert.Equal(t, num.DecimalFromFloat(1140.175).String(), avgEntryUpper.Round(3).String()) 52 53 // test risk factor 54 riskFactorLower := RiskFactor(leverageAtLower, longRiskFactor, linearSlippage, initialMargin) 55 riskFactorUpper := RiskFactor(leverageAtUpper, shortRiskFactor, linearSlippage, initialMargin) 56 assert.Equal(t, leverageAtLower.String(), riskFactorLower.String()) 57 assert.Equal(t, leverageAtUpper.String(), riskFactorUpper.String()) 58 59 lowerPriceD := lowerPrice.ToDecimal() 60 upperPriceD := upperPrice.ToDecimal() 61 62 // test position at bounds 63 lowerBoundPos := PositionAtLowerBound(riskFactorLower, balance.ToDecimal(), lowerPriceD, avgEntryLower, num.DecimalOne()) 64 upperBoundPos := PositionAtUpperBound(riskFactorUpper, balance.ToDecimal(), upperPriceD, avgEntryUpper, num.DecimalOne()) 65 assert.Equal(t, num.DecimalFromFloat(0.437).String(), lowerBoundPos.Round(3).String()) 66 assert.Equal(t, num.DecimalFromFloat(-0.069).String(), upperBoundPos.Round(3).String()) 67 68 // test loss on commitment 69 lossAtLower := LossOnCommitment(avgEntryLower, lowerPriceD, lowerBoundPos) 70 lossAtUpper := LossOnCommitment(avgEntryUpper, upperPriceD, upperBoundPos) 71 assert.Equal(t, num.DecimalFromFloat(21.28852368).String(), lossAtLower.Round(8).String()) 72 assert.Equal(t, num.DecimalFromFloat(10.94820416).String(), lossAtUpper.Round(8).String()) 73 74 linearSlippageFactor := num.DecimalZero() 75 76 // test liquidation price 77 liquidationPriceAtLower := LiquidationPrice(balance.ToDecimal(), lossAtLower, lowerBoundPos, lowerPriceD, linearSlippageFactor, longRiskFactor) 78 liquidationPriceAtUpper := LiquidationPrice(balance.ToDecimal(), lossAtUpper, upperBoundPos, upperPriceD, linearSlippageFactor, shortRiskFactor) 79 assert.Equal(t, num.DecimalFromFloat(727.2727273).String(), liquidationPriceAtLower.Round(7).String()) 80 assert.Equal(t, num.DecimalFromFloat(2574.257426).String(), liquidationPriceAtUpper.Round(6).String()) 81 } 82 83 func TestEstimate(t *testing.T) { 84 initialMargin := num.DecimalFromFloat(1) 85 riskFactorShort := num.DecimalFromFloat(0.01) 86 riskFactorLong := num.DecimalFromFloat(0.01) 87 linearSlippageFactor := num.DecimalFromFloat(0) 88 sqrter := NewSqrter() 89 90 t.Run("test 0014-NP-VAMM-001", func(t *testing.T) { 91 lowerPrice := num.NewUint(900) 92 basePrice := num.NewUint(1000) 93 upperPrice := num.NewUint(1100) 94 leverageUpper := num.DecimalFromFloat(2.00) 95 leverageLower := num.DecimalFromFloat(2.00) 96 balance := num.NewUint(100) 97 98 expectedMetrics := EstimatedBounds{ 99 PositionSizeAtUpper: num.DecimalFromFloat(-0.166), 100 PositionSizeAtLower: num.DecimalFromFloat(0.201), 101 LossOnCommitmentAtUpper: num.DecimalFromFloat(8.515), 102 LossOnCommitmentAtLower: num.DecimalFromFloat(9.762), 103 LiquidationPriceAtUpper: num.DecimalFromFloat(1633.663), 104 LiquidationPriceAtLower: num.DecimalFromFloat(454.545), 105 } 106 107 metrics := EstimateBounds( 108 sqrter, 109 lowerPrice, 110 basePrice, 111 upperPrice, 112 leverageLower, 113 leverageUpper, 114 balance, 115 linearSlippageFactor, 116 initialMargin, 117 riskFactorShort, 118 riskFactorLong, 119 num.DecimalOne(), 120 num.DecimalOne(), 121 0, 122 ) 123 124 assert.Equal(t, expectedMetrics.PositionSizeAtUpper.String(), metrics.PositionSizeAtUpper.Round(3).String()) 125 assert.Equal(t, expectedMetrics.PositionSizeAtLower.String(), metrics.PositionSizeAtLower.Round(3).String()) 126 assert.Equal(t, expectedMetrics.LossOnCommitmentAtUpper.String(), metrics.LossOnCommitmentAtUpper.Round(3).String()) 127 assert.Equal(t, expectedMetrics.LossOnCommitmentAtLower.String(), metrics.LossOnCommitmentAtLower.Round(3).String()) 128 assert.Equal(t, expectedMetrics.LiquidationPriceAtUpper.String(), metrics.LiquidationPriceAtUpper.Round(3).String()) 129 assert.Equal(t, expectedMetrics.LiquidationPriceAtLower.String(), metrics.LiquidationPriceAtLower.Round(3).String()) 130 assert.True(t, metrics.TooWideLower) 131 assert.True(t, metrics.TooWideUpper) 132 }) 133 134 t.Run("test 0014-NP-VAMM-004", func(t *testing.T) { 135 lowerPrice := num.NewUint(900) 136 basePrice := num.NewUint(1000) 137 upperPrice := num.NewUint(1300) 138 leverageUpper := num.DecimalFromFloat(1) 139 leverageLower := num.DecimalFromFloat(5) 140 balance := num.NewUint(100) 141 142 expectedMetrics := EstimatedBounds{ 143 PositionSizeAtUpper: num.DecimalFromFloat(-0.069), 144 PositionSizeAtLower: num.DecimalFromFloat(0.437), 145 LossOnCommitmentAtUpper: num.DecimalFromFloat(10.948), 146 LossOnCommitmentAtLower: num.DecimalFromFloat(21.289), 147 LiquidationPriceAtUpper: num.DecimalFromFloat(2574.257), 148 LiquidationPriceAtLower: num.DecimalFromFloat(727.273), 149 } 150 151 metrics := EstimateBounds( 152 sqrter, 153 lowerPrice, 154 basePrice, 155 upperPrice, 156 leverageLower, 157 leverageUpper, 158 balance, 159 linearSlippageFactor, 160 initialMargin, 161 riskFactorShort, 162 riskFactorLong, 163 num.DecimalOne(), 164 num.DecimalOne(), 165 0, 166 ) 167 168 assert.Equal(t, expectedMetrics.PositionSizeAtUpper.String(), metrics.PositionSizeAtUpper.Round(3).String()) 169 assert.Equal(t, expectedMetrics.PositionSizeAtLower.String(), metrics.PositionSizeAtLower.Round(3).String()) 170 assert.Equal(t, expectedMetrics.LossOnCommitmentAtUpper.String(), metrics.LossOnCommitmentAtUpper.Round(3).String()) 171 assert.Equal(t, expectedMetrics.LossOnCommitmentAtLower.String(), metrics.LossOnCommitmentAtLower.Round(3).String()) 172 assert.Equal(t, expectedMetrics.LiquidationPriceAtUpper.String(), metrics.LiquidationPriceAtUpper.Round(3).String()) 173 assert.Equal(t, expectedMetrics.LiquidationPriceAtLower.String(), metrics.LiquidationPriceAtLower.Round(3).String()) 174 }) 175 } 176 177 func TestEstimatePositionFactor(t *testing.T) { 178 initialMargin := num.DecimalFromFloat(1.2) 179 riskFactorShort := num.DecimalFromFloat(0.05529953589167391) 180 riskFactorLong := num.DecimalFromFloat(0.05529953589167391) 181 linearSlippageFactor := num.DecimalFromFloat(0.01) 182 sqrter := NewSqrter() 183 184 lowerPrice := num.MustUintFromString("80000000000000000000", 10) 185 basePrice := num.MustUintFromString("100000000000000000000", 10) 186 upperPrice := num.MustUintFromString("120000000000000000000", 10) 187 leverageUpper := num.DecimalFromFloat(0.5) 188 leverageLower := num.DecimalFromFloat(0.5) 189 balance := num.MustUintFromString("390500000000000000000000000", 10) 190 191 expectedMetrics := EstimatedBounds{ 192 PositionSizeAtUpper: num.DecimalFromFloat(-1559159.284), 193 PositionSizeAtLower: num.DecimalFromFloat(2304613.63), 194 } 195 196 metrics := EstimateBounds( 197 sqrter, 198 lowerPrice, 199 basePrice, 200 upperPrice, 201 leverageLower, 202 leverageUpper, 203 balance, 204 linearSlippageFactor, 205 initialMargin, 206 riskFactorShort, 207 riskFactorLong, 208 num.DecimalFromInt64(1000000000000000000), 209 num.DecimalOne(), 210 0, 211 ) 212 213 assert.Equal(t, expectedMetrics.PositionSizeAtUpper.String(), metrics.PositionSizeAtUpper.Round(3).String()) 214 assert.Equal(t, expectedMetrics.PositionSizeAtLower.String(), metrics.PositionSizeAtLower.Round(3).String()) 215 assert.False(t, metrics.TooWideLower) 216 assert.False(t, metrics.TooWideUpper) 217 218 // if commitment is super low then we could panic, so test that we don't 219 metrics = EstimateBounds( 220 sqrter, 221 lowerPrice, 222 basePrice, 223 upperPrice, 224 leverageLower, 225 leverageUpper, 226 num.MustUintFromString("390500000000000000000", 10), 227 linearSlippageFactor, 228 initialMargin, 229 riskFactorShort, 230 riskFactorLong, 231 num.DecimalFromInt64(1000000000000000000), 232 num.DecimalOne(), 233 10, 234 ) 235 236 assert.Equal(t, "-1.559", metrics.PositionSizeAtUpper.Round(3).String()) 237 assert.Equal(t, "2.305", metrics.PositionSizeAtLower.Round(3).String()) 238 assert.False(t, metrics.TooWideLower) // is valid as there are less than 10 empty price levels 239 assert.True(t, metrics.TooWideUpper) // isn't valid as there are more than 10 empty price levels 240 } 241 242 func TestEstimateBoundsOneSided(t *testing.T) { 243 initialMargin := num.DecimalFromFloat(1) 244 riskFactorShort := num.DecimalFromFloat(0.01) 245 riskFactorLong := num.DecimalFromFloat(0.01) 246 linearSlippageFactor := num.DecimalFromFloat(0) 247 sqrter := NewSqrter() 248 249 lowerPrice := num.NewUint(900) 250 basePrice := num.NewUint(1000) 251 upperPrice := num.NewUint(1100) 252 leverageUpper := num.DecimalFromFloat(2.00) 253 leverageLower := num.DecimalFromFloat(2.00) 254 balance := num.NewUint(100) 255 256 // no upper bound supplied 257 metrics := EstimateBounds( 258 sqrter, 259 lowerPrice, 260 basePrice, 261 nil, 262 leverageLower, 263 leverageUpper, 264 balance, 265 linearSlippageFactor, 266 initialMargin, 267 riskFactorShort, 268 riskFactorLong, 269 num.DecimalOne(), 270 num.DecimalOne(), 271 0, 272 ) 273 assert.True(t, metrics.LiquidationPriceAtUpper.IsZero()) 274 assert.True(t, metrics.PositionSizeAtUpper.IsZero()) 275 assert.True(t, metrics.LossOnCommitmentAtUpper.IsZero()) 276 277 // no lower bound supplied 278 metrics = EstimateBounds( 279 sqrter, 280 nil, 281 basePrice, 282 upperPrice, 283 leverageLower, 284 leverageUpper, 285 balance, 286 linearSlippageFactor, 287 initialMargin, 288 riskFactorShort, 289 riskFactorLong, 290 num.DecimalOne(), 291 num.DecimalOne(), 292 0, 293 ) 294 assert.True(t, metrics.LiquidationPriceAtLower.IsZero()) 295 assert.True(t, metrics.PositionSizeAtLower.IsZero()) 296 assert.True(t, metrics.LossOnCommitmentAtLower.IsZero()) 297 }