diff --git a/plugin/evm/orderbook/hubbleutils/margin_math.go b/plugin/evm/orderbook/hubbleutils/margin_math.go index 6a7ae9457f..b7d346388a 100644 --- a/plugin/evm/orderbook/hubbleutils/margin_math.go +++ b/plugin/evm/orderbook/hubbleutils/margin_math.go @@ -8,7 +8,7 @@ import ( type HubbleState struct { Assets []Collateral OraclePrices map[Market]*big.Int - LastPrices map[Market]*big.Int + MidPrices map[Market]*big.Int ActiveMarkets []Market MinAllowableMargin *big.Int MaintenanceMargin *big.Int @@ -63,7 +63,7 @@ func GetOptimalPnl(hState *HubbleState, position *Position, margin *big.Int, mar // based on last price notionalPosition, unrealizedPnl, lastPriceBasedMF := GetPositionMetadata( - hState.LastPrices[market], + hState.MidPrices[market], position.OpenNotional, position.Size, margin, diff --git a/plugin/evm/orderbook/liquidations.go b/plugin/evm/orderbook/liquidations.go index 67cb9b0494..548a705628 100644 --- a/plugin/evm/orderbook/liquidations.go +++ b/plugin/evm/orderbook/liquidations.go @@ -67,7 +67,7 @@ func getTotalNotionalPositionAndUnrealizedPnl(trader *Trader, margin *big.Int, m return hu.GetTotalNotionalPositionAndUnrealizedPnl( &hu.HubbleState{ OraclePrices: oraclePrices, - LastPrices: lastPrices, + MidPrices: lastPrices, ActiveMarkets: markets, }, &hu.UserState{ diff --git a/plugin/evm/orderbook/liquidations_test.go b/plugin/evm/orderbook/liquidations_test.go index a272cc429b..22ca3f2c36 100644 --- a/plugin/evm/orderbook/liquidations_test.go +++ b/plugin/evm/orderbook/liquidations_test.go @@ -40,7 +40,7 @@ func TestGetLiquidableTraders(t *testing.T) { hState := &hu.HubbleState{ Assets: assets, OraclePrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(110))}, - LastPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(100))}, + MidPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(100))}, ActiveMarkets: []hu.Market{market}, MaintenanceMargin: db.configService.getMaintenanceMargin(), } @@ -74,7 +74,7 @@ func TestGetLiquidableTraders(t *testing.T) { hState := &hu.HubbleState{ Assets: assets, OraclePrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(49))}, - LastPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(50))}, + MidPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(50))}, ActiveMarkets: []hu.Market{market}, MinAllowableMargin: db.configService.getMinAllowableMargin(), MaintenanceMargin: db.configService.getMaintenanceMargin(), @@ -91,7 +91,7 @@ func TestGetLiquidableTraders(t *testing.T) { // oracle price: notional = 49 * 10 = 490, pnl = 490-900 = -410, mf = (500-42-410)/490 = 0.097 // for hu.Min_Allowable_Margin we select the min of 2 hence orale_mf - notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Min_Allowable_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Min_Allowable_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(490)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-410)), unrealizePnL) @@ -101,11 +101,11 @@ func TestGetLiquidableTraders(t *testing.T) { assert.Equal(t, hu.Mul1e6(big.NewInt(-50)), availableMargin) // for hu.Maintenance_Margin we select the max of 2 hence, last_mf - notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Maintenance_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Maintenance_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(500)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-400)), unrealizePnL) - // marginFraction := calcMarginFraction(_trader, pendingFundingLong, assets, oraclePrices, hState.LastPrices, []Market{market}) + // marginFraction := calcMarginFraction(_trader, pendingFundingLong, assets, oraclePrices, hState.MidPrices, []Market{market}) marginFraction := calcMarginFraction(_trader, hState) assert.Equal(t, new(big.Int).Div(hu.Mul1e6(new(big.Int).Add(new(big.Int).Sub(marginLong, pendingFundingLong), unrealizePnL)), notionalPosition), marginFraction) @@ -131,7 +131,7 @@ func TestGetLiquidableTraders(t *testing.T) { hState := &hu.HubbleState{ Assets: assets, OraclePrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(50))}, - LastPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(49))}, + MidPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(49))}, ActiveMarkets: []hu.Market{market}, MinAllowableMargin: db.configService.getMinAllowableMargin(), MaintenanceMargin: db.configService.getMaintenanceMargin(), @@ -149,7 +149,7 @@ func TestGetLiquidableTraders(t *testing.T) { // oracle price: notional = 50 * 10 = 500, pnl = 500-900 = -400, mf = (500-42-400)/500 = 0.116 // for hu.Min_Allowable_Margin we select the min of 2 hence last_mf - notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Min_Allowable_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Min_Allowable_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(490)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-410)), unrealizePnL) @@ -158,7 +158,7 @@ func TestGetLiquidableTraders(t *testing.T) { assert.Equal(t, hu.Mul1e6(big.NewInt(-50)), availableMargin) // for hu.Maintenance_Margin we select the max of 2 hence, oracle_mf - notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Maintenance_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginLong, pendingFundingLong), hu.Maintenance_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(500)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-400)), unrealizePnL) @@ -195,7 +195,7 @@ func TestGetLiquidableTraders(t *testing.T) { hState := &hu.HubbleState{ Assets: assets, OraclePrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(143))}, - LastPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(142))}, + MidPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(142))}, ActiveMarkets: []hu.Market{market}, MinAllowableMargin: db.configService.getMinAllowableMargin(), MaintenanceMargin: db.configService.getMaintenanceMargin(), @@ -212,7 +212,7 @@ func TestGetLiquidableTraders(t *testing.T) { // oracle price based notional = 143 * 20 = 2860, pnl = 2100-2860 = -760, mf = (1000+37-760)/2860 = 0.096 // for hu.Min_Allowable_Margin we select the min of 2 hence, oracle_mf - notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Min_Allowable_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Min_Allowable_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(2860)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-760)), unrealizePnL) @@ -221,7 +221,7 @@ func TestGetLiquidableTraders(t *testing.T) { assert.Equal(t, hu.Mul1e6(big.NewInt(-295)), availableMargin) // for hu.Maintenance_Margin we select the max of 2 hence, last_mf - notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Maintenance_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Maintenance_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(2840)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-740)), unrealizePnL) @@ -250,7 +250,7 @@ func TestGetLiquidableTraders(t *testing.T) { hState := &hu.HubbleState{ Assets: assets, OraclePrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(142))}, - LastPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(143))}, + MidPrices: map[Market]*big.Int{market: hu.Mul1e6(big.NewInt(143))}, ActiveMarkets: []hu.Market{market}, MinAllowableMargin: db.configService.getMinAllowableMargin(), MaintenanceMargin: db.configService.getMaintenanceMargin(), @@ -267,7 +267,7 @@ func TestGetLiquidableTraders(t *testing.T) { // oracle price: notional = 142 * 20 = 2840, pnl = 2100-2840 = -740, mf = (1000+37-740)/2840 = 0.104 // for hu.Min_Allowable_Margin we select the min of 2 hence, last_mf - notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Min_Allowable_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Min_Allowable_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(2860)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-760)), unrealizePnL) @@ -276,7 +276,7 @@ func TestGetLiquidableTraders(t *testing.T) { assert.Equal(t, hu.Mul1e6(big.NewInt(-295)), availableMargin) // for hu.Maintenance_Margin we select the max of 2 hence, oracle_mf - notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Maintenance_Margin, oraclePrices, hState.LastPrices, []Market{market}) + notionalPosition, unrealizePnL = getTotalNotionalPositionAndUnrealizedPnl(_trader, new(big.Int).Add(marginShort, pendingFundingShort), hu.Maintenance_Margin, oraclePrices, hState.MidPrices, []Market{market}) assert.Equal(t, hu.Mul1e6(big.NewInt(2840)), notionalPosition) assert.Equal(t, hu.Mul1e6(big.NewInt(-740)), unrealizePnL) diff --git a/plugin/evm/orderbook/matching_pipeline.go b/plugin/evm/orderbook/matching_pipeline.go index de7a58ccd8..8e30991322 100644 --- a/plugin/evm/orderbook/matching_pipeline.go +++ b/plugin/evm/orderbook/matching_pipeline.go @@ -74,7 +74,7 @@ func (pipeline *MatchingPipeline) Run(blockNumber *big.Int) bool { hState := &hu.HubbleState{ Assets: pipeline.GetCollaterals(), OraclePrices: pipeline.GetUnderlyingPrices(), - LastPrices: pipeline.GetMidPrices(), + MidPrices: pipeline.GetMidPrices(), ActiveMarkets: markets, MinAllowableMargin: pipeline.configService.getMinAllowableMargin(), MaintenanceMargin: pipeline.configService.getMaintenanceMargin(), diff --git a/plugin/evm/orderbook/memory_database.go b/plugin/evm/orderbook/memory_database.go index a865f89643..a4cc6fba6a 100644 --- a/plugin/evm/orderbook/memory_database.go +++ b/plugin/evm/orderbook/memory_database.go @@ -231,7 +231,6 @@ type LimitOrderDatabase interface { UpdateNextSamplePITime(nextSamplePITime uint64) GetNextSamplePITime() uint64 UpdateLastPrice(market Market, lastPrice *big.Int) - GetLastPrice(market Market) *big.Int GetLastPrices() map[Market]*big.Int GetAllTraders() map[common.Address]Trader GetOrderBookData() InMemoryDatabase @@ -817,13 +816,6 @@ func (db *InMemoryDatabase) UpdateLastPremiumFraction(market Market, trader comm db.TraderMap[trader].Positions[market].UnrealisedFunding = hu.Div1e18(big.NewInt(0).Mul(big.NewInt(0).Sub(cumulativePremiumFraction, lastPremiumFraction), db.TraderMap[trader].Positions[market].Size)) } -func (db *InMemoryDatabase) GetLastPrice(market Market) *big.Int { - db.mu.RLock() - defer db.mu.RUnlock() - - return big.NewInt(0).Set(db.LastPrice[market]) -} - func (db *InMemoryDatabase) GetLastPrices() map[Market]*big.Int { db.mu.RLock() defer db.mu.RUnlock() diff --git a/plugin/evm/orderbook/memory_database_test.go b/plugin/evm/orderbook/memory_database_test.go index d47ebf5c95..a6d3f9b9f7 100644 --- a/plugin/evm/orderbook/memory_database_test.go +++ b/plugin/evm/orderbook/memory_database_test.go @@ -422,7 +422,7 @@ func TestGetCancellableOrders(t *testing.T) { hState := &hu.HubbleState{ Assets: assets, OraclePrices: priceMap, - LastPrices: inMemoryDatabase.GetLastPrices(), + MidPrices: inMemoryDatabase.GetLastPrices(), ActiveMarkets: []Market{market}, MinAllowableMargin: inMemoryDatabase.configService.getMinAllowableMargin(), MaintenanceMargin: inMemoryDatabase.configService.getMaintenanceMargin(), @@ -799,7 +799,7 @@ func TestGetLastPrice(t *testing.T) { var market Market = 1 lastPrice := big.NewInt(20) inMemoryDatabase.UpdateLastPrice(market, lastPrice) - assert.Equal(t, lastPrice, inMemoryDatabase.GetLastPrice(market)) + assert.Equal(t, lastPrice, inMemoryDatabase.GetLastPrices()[market]) } func TestUpdateReservedMargin(t *testing.T) { diff --git a/plugin/evm/orderbook/service.go b/plugin/evm/orderbook/service.go index c8b733b54a..9becba9d4b 100644 --- a/plugin/evm/orderbook/service.go +++ b/plugin/evm/orderbook/service.go @@ -73,6 +73,7 @@ type GetDebugDataResponse struct { UnrealizePnL map[common.Address]*big.Int LastPrice map[Market]*big.Int OraclePrice map[Market]*big.Int + MidPrice map[Market]*big.Int } func (api *OrderBookAPI) GetDebugData(ctx context.Context, trader string) GetDebugDataResponse { @@ -97,32 +98,34 @@ func (api *OrderBookAPI) GetDebugData(ctx context.Context, trader string) GetDeb } } - minAllowableMargin := api.configService.getMinAllowableMargin() prices := api.configService.GetUnderlyingPrices() - lastPrices := api.db.GetLastPrices() + mPrices := api.configService.GetMidPrices() + oraclePrices := map[Market]*big.Int{} + midPrices := map[Market]*big.Int{} count := api.configService.GetActiveMarketsCount() markets := make([]Market, count) for i := int64(0); i < count; i++ { markets[i] = Market(i) oraclePrices[Market(i)] = prices[Market(i)] + midPrices[Market(i)] = mPrices[Market(i)] } assets := api.configService.GetCollaterals() for addr, trader := range traderMap { pendingFunding := getTotalFunding(&trader, markets) margin := new(big.Int).Sub(getNormalisedMargin(&trader, assets), pendingFunding) - notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(&trader, margin, hu.Min_Allowable_Margin, oraclePrices, lastPrices, markets) + notionalPosition, unrealizePnL := getTotalNotionalPositionAndUnrealizedPnl(&trader, margin, hu.Min_Allowable_Margin, oraclePrices, midPrices, markets) hState := &hu.HubbleState{ Assets: assets, OraclePrices: oraclePrices, - LastPrices: lastPrices, + MidPrices: midPrices, ActiveMarkets: markets, MinAllowableMargin: api.configService.getMinAllowableMargin(), MaintenanceMargin: api.configService.getMaintenanceMargin(), } marginFraction := calcMarginFraction(&trader, hState) availableMargin := getAvailableMargin(&trader, hState) - utilisedMargin := hu.Div1e6(new(big.Int).Mul(notionalPosition, minAllowableMargin)) + utilisedMargin := hu.Div1e6(new(big.Int).Mul(notionalPosition, hState.MinAllowableMargin)) response.MarginFraction[addr] = marginFraction response.AvailableMargin[addr] = availableMargin @@ -134,8 +137,9 @@ func (api *OrderBookAPI) GetDebugData(ctx context.Context, trader string) GetDeb response.ReservedMargin[addr] = trader.Margin.Reserved } - response.LastPrice = lastPrices + response.LastPrice = api.db.GetLastPrices() response.OraclePrice = oraclePrices + response.MidPrice = midPrices return response } diff --git a/plugin/evm/orderbook/trading_apis.go b/plugin/evm/orderbook/trading_apis.go index af6edd89b2..68ac0449f0 100644 --- a/plugin/evm/orderbook/trading_apis.go +++ b/plugin/evm/orderbook/trading_apis.go @@ -184,8 +184,8 @@ func (api *TradingAPI) GetMarginAndPositions(ctx context.Context, trader string) response.ReservedMargin = utils.BigIntToDecimal(traderInfo.Margin.Reserved, 6, 8) for market, position := range traderInfo.Positions { - lastPrice := api.db.GetLastPrice(market) - notionalPosition, uPnL, mf := getPositionMetadata(lastPrice, position.OpenNotional, position.Size, margin) + midPrice := api.configService.GetMidPrices()[market] + notionalPosition, uPnL, mf := getPositionMetadata(midPrice, position.OpenNotional, position.Size, margin) response.Positions = append(response.Positions, TraderPosition{ Market: market, @@ -197,7 +197,7 @@ func (api *TradingAPI) GetMarginAndPositions(ctx context.Context, trader string) MarginFraction: utils.BigIntToDecimal(mf, 6, 8), NotionalPosition: utils.BigIntToDecimal(notionalPosition, 6, 8), LiquidationPrice: "0", // todo: calculate - MarkPrice: utils.BigIntToDecimal(lastPrice, 6, 8), + MarkPrice: utils.BigIntToDecimal(midPrice, 6, 8), }) } diff --git a/precompile/contracts/bibliophile/clearing_house.go b/precompile/contracts/bibliophile/clearing_house.go index e0715c328b..8484d92a87 100644 --- a/precompile/contracts/bibliophile/clearing_house.go +++ b/precompile/contracts/bibliophile/clearing_house.go @@ -87,7 +87,7 @@ func getNotionalPositionAndMargin(stateDB contract.StateDB, input *GetNotionalPo &hu.HubbleState{ Assets: GetCollaterals(stateDB), OraclePrices: underlyingPrices, - LastPrices: midPrices, + MidPrices: midPrices, ActiveMarkets: activeMarketIds, }, &hu.UserState{