Skip to content

Commit

Permalink
feat: add HVMR feature tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cdummett committed Aug 16, 2024
1 parent 1e2ed42 commit f0edec6
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 12 deletions.
205 changes: 205 additions & 0 deletions core/integration/features/volume-rebate/0095-HVMR.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
Feature: Volume rebate program - contributions from trades

Volume rebate program rewards parties who comprise above a specified
fraction of the maker volume on the network in a window with an
extra rebate factor.

Tests check trades contribute towards a party's maker volume fraction
correctly and that volume across windows and markets is correctly
counted and scaled where necessary.

Background:

# Initialise the network and register the assets
Given the average block duration is "1"
And the following network parameters are set:
| name | value |
| market.fee.factors.makerFee | 0.01 |
| market.fee.factors.infrastructureFee | 0.01 |
| market.fee.factors.treasuryFee | 0.1 |
| market.fee.factors.buybackFee | 0.1 |
| network.markPriceUpdateMaximumFrequency | 0s |
| validators.epoch.length | 20s |
| market.auction.minimumDuration | 1 |

And the following assets are registered:
| id | decimal places | quantum |
| USD-0-1 | 0 | 1 |
| MXN-0-10 | 0 | 10 |

# Initialise the parties and deposit assets
Given the parties deposit on asset's general account the following amount:
| party | asset | amount |
| aux1 | USD-0-1 | 1000000 |
| aux2 | USD-0-1 | 1000000 |
| aux1 | MXN-0-10 | 10000000 |
| aux2 | MXN-0-10 | 10000000 |

# Setup the USD and VMD markets in continuous trading
Given the price monitoring named "price-monitoring":
| horizon | probability | auction extension |
| 3600 | 0.99 | 1 |
And the markets:
| id | quote name | asset | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | decimal places | position decimal places |
| BTC/USD-0-1 | USD | USD-0-1 | default-log-normal-risk-model | default-margin-calculator | 1 | default-none | price-monitoring | default-eth-for-future | 1e-3 | 0 | default-futures | 0 | 0 |
| BTC/MXN-0-10 | VND | MXN-0-10 | default-log-normal-risk-model | default-margin-calculator | 1 | default-none | price-monitoring | default-eth-for-future | 1e-3 | 0 | default-futures | 0 | 0 |
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC |
| aux2 | BTC/USD-0-1 | sell | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC |
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif |
| aux1 | BTC/MXN-0-10 | buy | 1 | 500000 | 0 | TYPE_LIMIT | TIF_GTC |
| aux2 | BTC/MXN-0-10 | sell | 1 | 500000 | 0 | TYPE_LIMIT | TIF_GTC |
When the network moves ahead "2" blocks
And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "BTC/USD-0-1"
And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "BTC/MXN-0-10"


Scenario: Maker / taker volume does / does not contribute towards the maker volume fraction respectively (0095-HVMR-013)(0095-HVMR-015)

Given the volume rebate program tiers named "vrt":
| fraction | rebate |
| 0.0001 | 0.001 |
And the volume rebate program:
| id | tiers | closing timestamp | window length |
| id | vrt | 0 | 1 |
And the network moves ahead "1" epochs

Given the parties deposit on asset's general account the following amount:
| party | asset | amount |
| party1 | USD-0-1 | 1000000 |
| party2 | USD-0-1 | 1000000 |
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| party2 | BTC/USD-0-1 | sell | 1 | 50000 | 1 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer maker fee | seller maker fee |
| party1 | party2 | 1 | 50000 | sell | 0 | 500 |

# In the following epoch, party1 and party2 are both the maker of a
# trade but only party1 recevieves a rebate.
Given the network moves ahead "1" epochs
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| party2 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| aux1 | BTC/USD-0-1 | sell | 2 | 50000 | 2 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer high volume maker fee | seller high volume maker fee |
| party1 | aux1 | 1 | 50000 | sell | 0 | 50 |
| party2 | aux1 | 1 | 50000 | sell | 0 | 0 |
Then the following transfers should happen:
| from | to | from account | to account | market id | amount | asset | type |
| | party1 | ACCOUNT_TYPE_FEES_MAKER | ACCOUNT_TYPE_GENERAL | BTC/USD-0-1 | 50 | USD-0-1 | TRANSFER_TYPE_HIGH_MAKER_FEE_REBATE_RECEIVE |


Scenario: Trades on auction uncrossing do not contribute towards the maker volume fraction (0095-HVMR-017)

Given the volume rebate program tiers named "vrt":
| fraction | rebate |
| 0.0001 | 0.001 |
And the volume rebate program:
| id | tiers | closing timestamp | window length |
| id | vrt | 0 | 1 |
And the network moves ahead "1" epochs

# Trigger a PM auction
Given the market data for the market "BTC/USD-0-1" should be:
| mark price | trading mode | horizon | min bound | max bound |
| 50000 | TRADING_MODE_CONTINUOUS | 3600 | 47313 | 52816 |
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | reference |
| aux1 | BTC/USD-0-1 | buy | 1 | 60 | 0 | TYPE_LIMIT | TIF_GTC | auction-order-aux1 |
| aux2 | BTC/USD-0-1 | sell | 1 | 60 | 0 | TYPE_LIMIT | TIF_GTC | auction-order-aux2 |
When the network moves ahead "1" blocks
And the parties cancel the following orders:
| party | reference |
| aux1 | auction-order-aux1 |
| aux2 | auction-order-aux2 |
Then the trading mode should be "TRADING_MODE_MONITORING_AUCTION" for the market "BTC/USD-0-1"

# Exit the PM auction - volume should not contribute towards maker
# volume fraction of either party1 or party2
Given the parties deposit on asset's general account the following amount:
| party | asset | amount |
| party1 | USD-0-1 | 1000000 |
| party2 | USD-0-1 | 1000000 |
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| party2 | BTC/USD-0-1 | sell | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "BTC/USD-0-1"
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer maker fee | seller maker fee |
| party1 | party2 | 1 | 50000 | | 0 | 0 |

# In the following epoch, party1 and party2 are both the maker of a
# trade but neither receive a rebate.
Given the network moves ahead "1" epochs
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| party2 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| aux1 | BTC/USD-0-1 | sell | 2 | 50000 | 2 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer high volume maker fee | seller high volume maker fee |
| party1 | aux1 | 1 | 50000 | sell | 0 | 0 |
| party2 | aux1 | 1 | 50000 | sell | 0 | 0 |


Scenario Outline: Volume made in previous window correctly contributes towards maker volume fraction (0095-HVMR-019)(0095-HVMR-021)

Given the volume rebate program tiers named "vrt":
| fraction | rebate |
| 0.0001 | 0.001 |
And the volume rebate program:
| id | tiers | closing timestamp | window length |
| id | vrt | 0 | <window length> |
And the network moves ahead "1" epochs

Given the parties deposit on asset's general account the following amount:
| party | asset | amount |
| party1 | USD-0-1 | 1000000 |
| party2 | USD-0-1 | 1000000 |
And the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| aux1 | BTC/USD-0-1 | sell | 1 | 50000 | 1 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer maker fee | seller maker fee |
| party1 | aux1 | 1 | 50000 | sell | 0 | 500 |

Given the network moves ahead <epochs between trades> epochs
When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party2 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| aux1 | BTC/USD-0-1 | sell | 1 | 50000 | 1 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer maker fee | seller maker fee |
| party2 | aux1 | 1 | 50000 | sell | 0 | 500 |

When the network moves ahead "1" epochs
When the parties place the following orders:
| party | market id | side | volume | price | resulting trades | type | tif | error |
| party1 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| party2 | BTC/USD-0-1 | buy | 1 | 50000 | 0 | TYPE_LIMIT | TIF_GTC | |
| aux1 | BTC/USD-0-1 | sell | 2 | 50000 | 2 | TYPE_LIMIT | TIF_GTC | |
When the network moves ahead "1" blocks
Then the following trades should be executed:
| buyer | seller | size | price | aggressor side | buyer high volume maker fee | seller high volume maker fee |
| party1 | aux1 | 1 | 50000 | sell | 0 | <party1 rebate> |
| party2 | aux1 | 1 | 50000 | sell | 0 | <party2 rebate> |

Examples:
| window length | epochs between trades | party1 rebate | party2 rebate |
| 10 | "1" | 50 | 50 |


30 changes: 18 additions & 12 deletions core/integration/steps/the_following_trades_happened.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func TheFollowingTradesShouldBeExecuted(
buyerInfraFeeReferrerDiscount, hasBuyerInfraFeeReferrerDiscount := row.DecimalB("buyer infrastructure fee referrer discount")
buyerMakerFeeReferrerDiscount, hasBuyerMakerFeeReferrerDiscount := row.DecimalB("buyer maker fee referrer discount")
buyerLiqFeeReferrerDiscount, hasBuyerLiqFeeReferrerDiscount := row.DecimalB("buyer liquidity fee referrer discount")
buyerHighVolumeMakerFee, hasBuyerHighVolumeMakerFee := row.DecimalB("buyer high volume maker fee")

sellerFee, hasSellerFee := row.U64B("seller fee")
sellerInfraFee, hasSellerInfraFee := row.U64B("seller infrastructure fee")
Expand All @@ -76,6 +77,7 @@ func TheFollowingTradesShouldBeExecuted(
sellerInfraFeeReferrerDiscount, hasSellerInfraFeeReferrerDiscount := row.DecimalB("seller infrastructure fee referrer discount")
sellerMakerFeeReferrerDiscount, hasSellerMakerFeeReferrerDiscount := row.DecimalB("seller maker fee referrer discount")
sellerLiqFeeReferrerDiscount, hasSellerLiqFeeReferrerDiscount := row.DecimalB("seller liquidity fee referrer discount")
sellerHighVolumeMakerFee, hasSellerHighVolumeMakerFee := row.DecimalB("seller high volume maker fee")

data := broker.GetTrades()
var found bool
Expand All @@ -89,22 +91,24 @@ func TheFollowingTradesShouldBeExecuted(
(!hasBuyerInfraFee || buyerInfraFee == stringToU64(v.BuyerFee.InfrastructureFee)) &&
(!hasBuyerMakerFee || buyerMakerFee == stringToU64(v.BuyerFee.MakerFee)) &&
(!hasBuyerLiqFee || buyerLiqFee == stringToU64(v.BuyerFee.LiquidityFee)) &&
(!hasBuyerInfraFeeVolumeDiscount || buyerInfraFeeVolumeDiscount == num.MustDecimalFromString(v.BuyerFee.InfrastructureFeeVolumeDiscount)) &&
(!hasBuyerMakerFeeVolumeDiscount || buyerMakerFeeVolumeDiscount == num.MustDecimalFromString(v.BuyerFee.MakerFeeVolumeDiscount)) &&
(!hasBuyerLiqFeeVolumeDiscount || buyerLiqFeeVolumeDiscount == num.MustDecimalFromString(v.BuyerFee.LiquidityFeeVolumeDiscount)) &&
(!hasBuyerInfraFeeReferrerDiscount || buyerInfraFeeReferrerDiscount == num.MustDecimalFromString(v.BuyerFee.InfrastructureFeeReferrerDiscount)) &&
(!hasBuyerMakerFeeReferrerDiscount || buyerMakerFeeReferrerDiscount == num.MustDecimalFromString(v.BuyerFee.MakerFeeReferrerDiscount)) &&
(!hasBuyerLiqFeeReferrerDiscount || buyerLiqFeeReferrerDiscount == num.MustDecimalFromString(v.BuyerFee.LiquidityFeeReferrerDiscount)) &&
(!hasBuyerInfraFeeVolumeDiscount || buyerInfraFeeVolumeDiscount.Equal(num.MustDecimalFromString(v.BuyerFee.InfrastructureFeeVolumeDiscount))) &&
(!hasBuyerMakerFeeVolumeDiscount || buyerMakerFeeVolumeDiscount.Equal(num.MustDecimalFromString(v.BuyerFee.MakerFeeVolumeDiscount))) &&
(!hasBuyerLiqFeeVolumeDiscount || buyerLiqFeeVolumeDiscount.Equal(num.MustDecimalFromString(v.BuyerFee.LiquidityFeeVolumeDiscount))) &&
(!hasBuyerInfraFeeReferrerDiscount || buyerInfraFeeReferrerDiscount.Equal(num.MustDecimalFromString(v.BuyerFee.InfrastructureFeeReferrerDiscount))) &&
(!hasBuyerMakerFeeReferrerDiscount || buyerMakerFeeReferrerDiscount.Equal(num.MustDecimalFromString(v.BuyerFee.MakerFeeReferrerDiscount))) &&
(!hasBuyerLiqFeeReferrerDiscount || buyerLiqFeeReferrerDiscount.Equal(num.MustDecimalFromString(v.BuyerFee.LiquidityFeeReferrerDiscount))) &&
(!hasBuyerHighVolumeMakerFee || buyerHighVolumeMakerFee.Equal(num.MustDecimalFromString(v.BuyerFee.HighVolumeMakerFee))) &&
(!hasSellerFee || sellerFee == feeToU64(v.SellerFee)) &&
(!hasSellerInfraFee || sellerInfraFee == stringToU64(v.SellerFee.InfrastructureFee)) &&
(!hasSellerMakerFee || sellerMakerFee == stringToU64(v.SellerFee.MakerFee)) &&
(!hasSellerLiqFee || sellerLiqFee == stringToU64(v.SellerFee.LiquidityFee)) &&
(!hasSellerInfraFeeVolumeDiscount || sellerInfraFeeVolumeDiscount == num.MustDecimalFromString(v.SellerFee.InfrastructureFeeVolumeDiscount)) &&
(!hasSellerMakerFeeVolumeDiscount || sellerMakerFeeVolumeDiscount == num.MustDecimalFromString(v.SellerFee.MakerFeeVolumeDiscount)) &&
(!hasSellerLiqFeeVolumeDiscount || sellerLiqFeeVolumeDiscount == num.MustDecimalFromString(v.SellerFee.LiquidityFeeVolumeDiscount)) &&
(!hasSellerInfraFeeReferrerDiscount || sellerInfraFeeReferrerDiscount == num.MustDecimalFromString(v.SellerFee.InfrastructureFeeReferrerDiscount)) &&
(!hasSellerMakerFeeReferrerDiscount || sellerMakerFeeReferrerDiscount == num.MustDecimalFromString(v.SellerFee.MakerFeeReferrerDiscount)) &&
(!hasSellerLiqFeeReferrerDiscount || sellerLiqFeeReferrerDiscount == num.MustDecimalFromString(v.SellerFee.LiquidityFeeReferrerDiscount)) {
(!hasSellerInfraFeeVolumeDiscount || sellerInfraFeeVolumeDiscount.Equal(num.MustDecimalFromString(v.SellerFee.InfrastructureFeeVolumeDiscount))) &&
(!hasSellerMakerFeeVolumeDiscount || sellerMakerFeeVolumeDiscount.Equal(num.MustDecimalFromString(v.SellerFee.MakerFeeVolumeDiscount))) &&
(!hasSellerLiqFeeVolumeDiscount || sellerLiqFeeVolumeDiscount.Equal(num.MustDecimalFromString(v.SellerFee.LiquidityFeeVolumeDiscount))) &&
(!hasSellerInfraFeeReferrerDiscount || sellerInfraFeeReferrerDiscount.Equal(num.MustDecimalFromString(v.SellerFee.InfrastructureFeeReferrerDiscount))) &&
(!hasSellerMakerFeeReferrerDiscount || sellerMakerFeeReferrerDiscount.Equal(num.MustDecimalFromString(v.SellerFee.MakerFeeReferrerDiscount))) &&
(!hasSellerLiqFeeReferrerDiscount || sellerLiqFeeReferrerDiscount.Equal(num.MustDecimalFromString(v.SellerFee.LiquidityFeeReferrerDiscount))) &&
(!hasSellerHighVolumeMakerFee || sellerHighVolumeMakerFee.Equal(num.MustDecimalFromString(v.SellerFee.HighVolumeMakerFee))) {
found = true
}
}
Expand Down Expand Up @@ -141,6 +145,7 @@ func parseExecutedTradesTable(table *godog.Table) []RowWrapper {
"buyer infrastructure fee referrer discount",
"buyer liquidity fee referrer discount",
"buyer maker fee referrer discount",
"buyer high volume maker fee",

"seller fee",
"seller infrastructure fee",
Expand All @@ -152,6 +157,7 @@ func parseExecutedTradesTable(table *godog.Table) []RowWrapper {
"seller infrastructure fee referrer discount",
"seller liquidity fee referrer discount",
"seller maker fee referrer discount",
"seller high volume maker fee",
"is amm",
})
}
Expand Down

0 comments on commit f0edec6

Please sign in to comment.