Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up open-interest liquidity tier calculations #1592

Merged
merged 3 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/protocol-benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ name: Protocol Benchmark
on: # yamllint disable-line rule:truthy
pull_request:
paths:
- 'protocol/lib/**'
- 'protocol/**'
push:
branches:
- main
- 'release/protocol/v[0-9]+.[0-9]+.x' # e.g. release/protocol/v0.1.x
- 'release/protocol/v[0-9]+.x' # e.g. release/protocol/v1.x
paths:
- 'protocol/lib/**'
- 'protocol/**'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
Expand Down
257 changes: 112 additions & 145 deletions protocol/x/perpetuals/keeper/perpetual_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,107 +681,107 @@ func TestModifyOpenInterest_Mixed(t *testing.T) {
func TestGetMarginRequirements_Success(t *testing.T) {
oneBip := math.Pow10(2)
tests := map[string]struct {
price uint64
exponent int32
baseCurrencyAtomicResolution int32
bigBaseQuantums *big.Int
initialMarginPpm uint32
maintenanceFractionPpm uint32
openInterest *big.Int
openInterestLowerCap uint64
openInterestUpperCap uint64
bigExpectedInitialMarginPpm *big.Int
bigExpectedMaintenanceMarginPpm *big.Int
price uint64
exponent int32
baseCurrencyAtomicResolution int32
bigBaseQuantums *big.Int
initialMarginPpm uint32
maintenanceFractionPpm uint32
openInterest *big.Int
openInterestLowerCap uint64
openInterestUpperCap uint64
bigExpectedInitialMargin *big.Int
bigExpectedMaintenanceMargin *big.Int
Comment on lines +693 to +694
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are not ppm values, they are in quantums, so I renamed them

}{
"InitialMargin 2 BIPs, MaintenanceMargin 1 BIP, positive exponent, atomic resolution 8": {
price: 5_555,
exponent: 2,
baseCurrencyAtomicResolution: -8,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 2),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMarginPpm: big.NewInt(7_777),
bigExpectedMaintenanceMarginPpm: big.NewInt(3_889),
price: 5_555,
exponent: 2,
baseCurrencyAtomicResolution: -8,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 2),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMargin: big.NewInt(7_777),
bigExpectedMaintenanceMargin: big.NewInt(3_889),
},
"InitialMargin 100 BIPs, MaintenanceMargin 50 BIPs, atomic resolution 4": {
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -4,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMarginPpm: big.NewInt(38_885_000),
bigExpectedMaintenanceMarginPpm: big.NewInt(19_442_500),
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -4,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMargin: big.NewInt(38_885_000),
bigExpectedMaintenanceMargin: big.NewInt(19_442_500),
},
"InitialMargin 100 BIPs, MaintenanceMargin 50 BIPs, positive exponent, atomic resolution 0": {
price: 42,
exponent: 5,
baseCurrencyAtomicResolution: -0,
bigBaseQuantums: big.NewInt(88),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMarginPpm: big.NewInt(3_696_000_000_000),
bigExpectedMaintenanceMarginPpm: big.NewInt(1_848_000_000_000),
price: 42,
exponent: 5,
baseCurrencyAtomicResolution: -0,
bigBaseQuantums: big.NewInt(88),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMargin: big.NewInt(3_696_000_000_000),
bigExpectedMaintenanceMargin: big.NewInt(1_848_000_000_000),
},
"InitialMargin 100 BIPs, MaintenanceMargin 50 BIPs, negative exponent, atomic resolution 6": {
price: 42_000_000,
exponent: -2,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(-5_000),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMarginPpm: big.NewInt(21_000_000),
bigExpectedMaintenanceMarginPpm: big.NewInt(10_500_000),
price: 42_000_000,
exponent: -2,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(-5_000),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMargin: big.NewInt(21_000_000),
bigExpectedMaintenanceMargin: big.NewInt(10_500_000),
},
"InitialMargin 10_000 BIPs (max), MaintenanceMargin 10_000 BIPs (max), atomic resolution 6": {
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 10_000),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM
bigExpectedInitialMarginPpm: big.NewInt(38_885_000),
bigExpectedMaintenanceMarginPpm: big.NewInt(38_885_000),
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 10_000),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM
bigExpectedInitialMargin: big.NewInt(38_885_000),
bigExpectedMaintenanceMargin: big.NewInt(38_885_000),
},
"InitialMargin 100 BIPs, MaintenanceMargin 100 BIPs, atomic resolution 6": {
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM
bigExpectedInitialMarginPpm: big.NewInt(388_850),
bigExpectedMaintenanceMarginPpm: big.NewInt(388_850),
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 100),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM
bigExpectedInitialMargin: big.NewInt(388_850),
bigExpectedMaintenanceMargin: big.NewInt(388_850),
},
"InitialMargin 0.02 BIPs, MaintenanceMargin 0.01 BIPs, positive exponent, atomic resolution 6": {
price: 5_555,
exponent: 3,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(-7_000),
initialMarginPpm: uint32(oneBip * 0.02),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMarginPpm: big.NewInt(77_770),
bigExpectedMaintenanceMarginPpm: big.NewInt(38_885),
price: 5_555,
exponent: 3,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(-7_000),
initialMarginPpm: uint32(oneBip * 0.02),
maintenanceFractionPpm: uint32(500_000), // 50% of IM
bigExpectedInitialMargin: big.NewInt(77_770),
bigExpectedMaintenanceMargin: big.NewInt(38_885),
},
"InitialMargin 0 BIPs (min), MaintenanceMargin 0 BIPs (min), atomic resolution 6": {
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 0),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM,
bigExpectedInitialMarginPpm: big.NewInt(0),
bigExpectedMaintenanceMarginPpm: big.NewInt(0),
price: 5_555,
exponent: 0,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(7_000),
initialMarginPpm: uint32(oneBip * 0),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM,
bigExpectedInitialMargin: big.NewInt(0),
bigExpectedMaintenanceMargin: big.NewInt(0),
},
"Price is zero, atomic resolution 6": {
price: 0,
exponent: 1,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(-7_000),
initialMarginPpm: uint32(oneBip * 1),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM,
bigExpectedInitialMarginPpm: big.NewInt(0),
bigExpectedMaintenanceMarginPpm: big.NewInt(0),
price: 0,
exponent: 1,
baseCurrencyAtomicResolution: -6,
bigBaseQuantums: big.NewInt(-7_000),
initialMarginPpm: uint32(oneBip * 1),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM,
bigExpectedInitialMargin: big.NewInt(0),
bigExpectedMaintenanceMargin: big.NewInt(0),
},
"Price and quantums are max uints": {
price: math.MaxUint64,
Expand All @@ -790,10 +790,10 @@ func TestGetMarginRequirements_Success(t *testing.T) {
bigBaseQuantums: new(big.Int).SetUint64(math.MaxUint64),
initialMarginPpm: uint32(oneBip * 1),
maintenanceFractionPpm: uint32(1_000_000), // 100% of IM,
bigExpectedInitialMarginPpm: big_testutil.MustFirst(
bigExpectedInitialMargin: big_testutil.MustFirst(
new(big.Int).SetString("340282366920938463426481119284349109", 10),
),
bigExpectedMaintenanceMarginPpm: big_testutil.MustFirst(
bigExpectedMaintenanceMargin: big_testutil.MustFirst(
new(big.Int).SetString("340282366920938463426481119284349109", 10),
),
},
Expand All @@ -806,8 +806,8 @@ func TestGetMarginRequirements_Success(t *testing.T) {
maintenanceFractionPpm: uint32(500_000), // 50% of IM
// initialMarginPpmQuoteQuantums = initialMarginPpm * quoteQuantums / 1_000_000
// = 10_000 * 38_885_000 / 1_000_000 ~= 388_850.
bigExpectedInitialMarginPpm: big.NewInt(388_850),
bigExpectedMaintenanceMarginPpm: big.NewInt(388_850 / 2),
bigExpectedInitialMargin: big.NewInt(388_850),
bigExpectedMaintenanceMargin: big.NewInt(388_850 / 2),
},
"InitialMargin 20%, MaintenanceMargin 10%, atomic resolution 6": {
price: 36_750,
Expand All @@ -819,8 +819,8 @@ func TestGetMarginRequirements_Success(t *testing.T) {
// quoteQuantums = 36_750 * 12_000 = 441_000_000
// initialMarginPpmQuoteQuantums = initialMarginPpm * quoteQuantums / 1_000_000
// = 200_000 * 441_000_000 / 1_000_000 ~= 88_200_000
bigExpectedInitialMarginPpm: big.NewInt(88_200_000),
bigExpectedMaintenanceMarginPpm: big.NewInt(88_200_000 / 2),
bigExpectedInitialMargin: big.NewInt(88_200_000),
bigExpectedMaintenanceMargin: big.NewInt(88_200_000 / 2),
},
"InitialMargin 5%, MaintenanceMargin 3%, atomic resolution 6": {
price: 123_456,
Expand All @@ -832,8 +832,8 @@ func TestGetMarginRequirements_Success(t *testing.T) {
// quoteQuantums = 123_456 * 74_523 = 9_200_311_488
// initialMarginPpmQuoteQuantums = initialMarginPpm * quoteQuantums / 1_000_000
// = 50_000 * 9_200_311_488 / 1_000_000 ~= 460_015_575
bigExpectedInitialMarginPpm: big.NewInt(460_015_575),
bigExpectedMaintenanceMarginPpm: big.NewInt(276_009_345),
bigExpectedInitialMargin: big.NewInt(460_015_575),
bigExpectedMaintenanceMargin: big.NewInt(276_009_345),
},
"InitialMargin 25%, MaintenanceMargin 15%, atomic resolution 6": {
price: 123_456,
Expand All @@ -843,8 +843,8 @@ func TestGetMarginRequirements_Success(t *testing.T) {
initialMarginPpm: uint32(250_000),
maintenanceFractionPpm: uint32(600_000), // 60% of IM
// quoteQuantums = 123_456 * 74_523 = 9_200_311_488
bigExpectedInitialMarginPpm: big.NewInt(2_300_077_872),
bigExpectedMaintenanceMarginPpm: big.NewInt(1_380_046_724), // Rounded up
bigExpectedInitialMargin: big.NewInt(2_300_077_872),
bigExpectedMaintenanceMargin: big.NewInt(1_380_046_724), // Rounded up
},
"OIMF: IM 20%, scaled to 60%, MaintenanceMargin 10%, atomic resolution 6": {
price: 36_750,
Expand All @@ -856,11 +856,12 @@ func TestGetMarginRequirements_Success(t *testing.T) {
openInterest: big.NewInt(408_163_265), // 408.163265
openInterestLowerCap: 10_000_000_000_000,
openInterestUpperCap: 20_000_000_000_000,
// quoteQuantums = 36_750 * 12_000 = 441_000_000
// initialMarginPpmQuoteQuantums = initialMarginPpm * quoteQuantums / 1_000_000
// = 200_000 * 441_000_000 / 1_000_000 ~= 88_200_000
bigExpectedInitialMarginPpm: big.NewInt(88_200_000 * 3),
bigExpectedMaintenanceMarginPpm: big.NewInt(88_200_000 / 2),
// openInterestNotional = 408_163_265 * 36_750 = 14_999_999_988_750
// percentageOfCap = (openInterestNotional - lowerCap) / (upperCap - lowerCap) = 0.499999998875
// adjustedIMF = (0.499999998875) * 0.8 + 0.2 = 0.5999999991 (rounded is 599_999 ppm)
// bigExpectedInitialMargin = bigBaseQuantums * price * adjustedIMF = 264_599_559
bigExpectedInitialMargin: big.NewInt(264_599_559),
bigExpectedMaintenanceMargin: big.NewInt(88_200_000 / 2),
},
"OIMF: IM 20%, scaled to 100%, MaintenanceMargin 10%, atomic resolution 6": {
price: 36_750,
Expand All @@ -875,8 +876,8 @@ func TestGetMarginRequirements_Success(t *testing.T) {
// quoteQuantums = 36_750 * 12_000 = 441_000_000
// initialMarginPpmQuoteQuantums = initialMarginPpm * quoteQuantums / 1_000_000
// = 200_000 * 441_000_000 / 1_000_000 ~= 88_200_000
bigExpectedInitialMarginPpm: big.NewInt(441_000_000),
bigExpectedMaintenanceMarginPpm: big.NewInt(88_200_000 / 2),
bigExpectedInitialMargin: big.NewInt(441_000_000),
bigExpectedMaintenanceMargin: big.NewInt(88_200_000 / 2),
},
"OIMF: IM 20%, lower_cap < realistic open interest < upper_cap, MaintenanceMargin 10%, atomic resolution 6": {
price: 36_750,
Expand All @@ -888,12 +889,12 @@ func TestGetMarginRequirements_Success(t *testing.T) {
openInterest: big.NewInt(1_123_456_789), // 1123.456 or ~$41mm notional
openInterestLowerCap: 25_000_000_000_000,
openInterestUpperCap: 50_000_000_000_000,
// quoteQuantums = 36_750 * 12_000 = 441_000_000
// initialMarginPpmQuoteQuantums = initialMarginPpm * quoteQuantums / 1_000_000
// = ((1123.456789 * 36750 - 25000000) / 25000000 * 0.8 + 0.2) * 441_000_000
// ~= 318042667
bigExpectedInitialMarginPpm: big.NewInt(318_042_667),
bigExpectedMaintenanceMarginPpm: big.NewInt(88_200_000 / 2),
// openInterestNotional = 1_123_456_789 * 36_750 = 41_287_036_995_750
// percentageOfCap = (openInterestNotional - lowerCap) / (upperCap - lowerCap) = 0.65148147983
// adjustedIMF = (0.65148147983) * 0.8 + 0.2 = 0.721185183864 (rounded is 721_185 ppm)
// bigExpectedInitialMargin = bigBaseQuantums * price * adjustedIMF = 318_042_585
bigExpectedInitialMargin: big.NewInt(318_042_585),
bigExpectedMaintenanceMargin: big.NewInt(88_200_000 / 2),
},
}

Expand Down Expand Up @@ -976,21 +977,8 @@ func TestGetMarginRequirements_Success(t *testing.T) {
)
require.NoError(t, err)

if tc.bigExpectedInitialMarginPpm.Cmp(bigInitialMargin) != 0 {
t.Fatalf(
"%s: expectedInitialMargin: %s, initialMargin: %s",
name,
tc.bigExpectedInitialMarginPpm.String(),
bigInitialMargin.String())
}

if tc.bigExpectedMaintenanceMarginPpm.Cmp(bigMaintenanceMargin) != 0 {
t.Fatalf(
"%s: expectedMaintenanceMargin: %s, maintenanceMargin: %s",
name,
tc.bigExpectedMaintenanceMarginPpm.String(),
bigMaintenanceMargin.String())
}
require.Equal(t, tc.bigExpectedInitialMargin, bigInitialMargin, "Initial margin mismatch")
require.Equal(t, tc.bigExpectedMaintenanceMargin, bigMaintenanceMargin, "Maintenance margin mismatch")
})
}
}
Expand Down Expand Up @@ -1177,14 +1165,7 @@ func TestGetNetNotional_Success(t *testing.T) {
)
require.NoError(t, err)

if tc.bigExpectedNetNotionalQuoteQuantums.Cmp(bigNotionalQuoteQuantums) != 0 {
t.Fatalf(
"%s: expectedNetNotionalQuoteQuantums: %s, collateralQuoteQuantums: %s",
name,
tc.bigExpectedNetNotionalQuoteQuantums.String(),
bigNotionalQuoteQuantums.String(),
)
}
require.Equal(t, tc.bigExpectedNetNotionalQuoteQuantums, bigNotionalQuoteQuantums, "Net notional mismatch")
})
}
}
Expand Down Expand Up @@ -1339,14 +1320,7 @@ func TestGetNotionalInBaseQuantums_Success(t *testing.T) {
)
require.NoError(t, err)

if tc.bigExpectedNetNotionalBaseQuantums.Cmp(bigNotionalBaseQuantums) != 0 {
t.Fatalf(
"%s: expectedNetNotionalBaseQuantums: %s, collateralBaseQuantums: %s",
name,
tc.bigExpectedNetNotionalBaseQuantums.String(),
bigNotionalBaseQuantums.String(),
)
}
require.Equal(t, tc.bigExpectedNetNotionalBaseQuantums, bigNotionalBaseQuantums, "Net notional mismatch")
})
}
}
Expand Down Expand Up @@ -1502,14 +1476,7 @@ func TestGetNetCollateral_Success(t *testing.T) {
)
require.NoError(t, err)

if tc.bigExpectedNetCollateralQuoteQuantums.Cmp(bigCollateralQuoteQuantums) != 0 {
t.Fatalf(
"%s: expectedNetCollateralQuoteQuantums: %s, collateralQuoteQuantums: %s",
name,
tc.bigExpectedNetCollateralQuoteQuantums.String(),
bigCollateralQuoteQuantums.String(),
)
}
require.Equal(t, tc.bigExpectedNetCollateralQuoteQuantums, bigCollateralQuoteQuantums, "Net collateral mismatch")
})
}
}
Expand Down
Loading
Loading