From d7cf82990a6f7ff438b765525d5e9e2814ed438a Mon Sep 17 00:00:00 2001 From: mkXultra Date: Fri, 17 Mar 2023 18:28:44 +0900 Subject: [PATCH] modify: rename variable name and define type --- x/derivatives/abci.go | 5 +- x/derivatives/keeper/grpc_query.go | 28 +++++--- x/derivatives/keeper/perpetual_futures.go | 10 ++- x/derivatives/types/positions.go | 83 +++++++++++++---------- 4 files changed, 79 insertions(+), 47 deletions(-) diff --git a/x/derivatives/abci.go b/x/derivatives/abci.go index 1b24d4a6b..7e886f55c 100644 --- a/x/derivatives/abci.go +++ b/x/derivatives/abci.go @@ -29,12 +29,15 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { func CheckPosition(ctx sdk.Context, k keeper.Keeper) { positions := k.GetAllPositions(ctx) params := k.GetParams(ctx) + quoteTicker := k.GetPoolQuoteTicker(ctx) for _, position := range positions { currentBaseUsdRate, currentQuoteUsdRate, err := k.GetPairUsdPriceFromMarket(ctx, position.Market) + baseMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.BaseDenom, currentBaseUsdRate) + quoteMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.QuoteDenom, currentQuoteUsdRate) if err != nil { panic(err) } - if position.NeedLiquidation(params.PerpetualFutures.MarginMaintenanceRate, currentBaseUsdRate, currentQuoteUsdRate) { + if position.NeedLiquidation(params.PerpetualFutures.MarginMaintenanceRate, baseMetricsRate, quoteMetricsRate) { msg := types.MsgReportLiquidation{ Sender: position.Address, PositionId: position.Id, diff --git a/x/derivatives/keeper/grpc_query.go b/x/derivatives/keeper/grpc_query.go index fea18e0e4..4254a3c80 100644 --- a/x/derivatives/keeper/grpc_query.go +++ b/x/derivatives/keeper/grpc_query.go @@ -49,8 +49,9 @@ func (k Keeper) PerpetualFutures(c context.Context, req *types.QueryPerpetualFut } } - longUsd := positions.EvaluateLongPositions(getPriceFunc(ctx)) - shortUsd := positions.EvaluateShortPositions(getPriceFunc(ctx)) + quoteTicker := k.GetPoolQuoteTicker(ctx) + longUsd := positions.EvaluateLongPositions(quoteTicker, getPriceFunc(ctx)) + shortUsd := positions.EvaluateShortPositions(quoteTicker, getPriceFunc(ctx)) // TODO: implement the handler logic ctx.BlockHeight() metricsQuoteTicker := "USD" @@ -209,12 +210,15 @@ func (k Keeper) MakeQueriedPositions(ctx sdk.Context, positions types.Positions) return nil, status.Error(codes.Internal, err.Error()) } - profit := perpetualFuturesPosition.ProfitAndLossInMetrics(currentBaseUsdRate, currentQuoteUsdRate) + quoteTicker := k.GetPoolQuoteTicker(ctx) + baseMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.BaseDenom, currentBaseUsdRate) + quoteMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.QuoteDenom, currentQuoteUsdRate) + profit := perpetualFuturesPosition.ProfitAndLossInMetrics(baseMetricsRate, quoteMetricsRate) queriedPosition := types.QueriedPosition{ Position: position, ValuationProfit: sdk.NewCoin("uusd", types.MicroToNormalDenom(profit)), - MarginMaintenanceRate: perpetualFuturesPosition.MarginMaintenanceRate(currentBaseUsdRate, currentQuoteUsdRate), - EffectiveMargin: sdk.NewCoin("uusd", types.MicroToNormalDenom(perpetualFuturesPosition.EffectiveMarginInMetrics(currentBaseUsdRate, currentQuoteUsdRate))), + MarginMaintenanceRate: perpetualFuturesPosition.MarginMaintenanceRate(baseMetricsRate, quoteMetricsRate), + EffectiveMargin: sdk.NewCoin("uusd", types.MicroToNormalDenom(perpetualFuturesPosition.EffectiveMarginInMetrics(baseMetricsRate, quoteMetricsRate))), } queriedPositions = append(queriedPositions, queriedPosition) } @@ -244,13 +248,16 @@ func (k Keeper) Position(c context.Context, req *types.QueryPositionRequest) (*t if err != nil { panic(err) } + quoteTicker := k.GetPoolQuoteTicker(ctx) + baseMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.BaseDenom, currentBaseUsdRate) + quoteMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.QuoteDenom, currentQuoteUsdRate) - profit := perpetualFuturesPosition.ProfitAndLossInMetrics(currentBaseUsdRate, currentQuoteUsdRate) + profit := perpetualFuturesPosition.ProfitAndLossInMetrics(baseMetricsRate, quoteMetricsRate) return &types.QueryPositionResponse{ Position: position, ValuationProfit: sdk.NewCoin("uusd", types.MicroToNormalDenom(profit)), - MarginMaintenanceRate: perpetualFuturesPosition.MarginMaintenanceRate(currentBaseUsdRate, currentQuoteUsdRate), - EffectiveMargin: sdk.NewCoin("uusd", types.MicroToNormalDenom(perpetualFuturesPosition.EffectiveMarginInMetrics(currentBaseUsdRate, currentQuoteUsdRate))), + MarginMaintenanceRate: perpetualFuturesPosition.MarginMaintenanceRate(baseMetricsRate, quoteMetricsRate), + EffectiveMargin: sdk.NewCoin("uusd", types.MicroToNormalDenom(perpetualFuturesPosition.EffectiveMarginInMetrics(baseMetricsRate, quoteMetricsRate))), }, nil } @@ -271,10 +278,11 @@ func (k Keeper) PerpetualFuturesPositionSize(c context.Context, req *types.Query } } var result sdk.Dec + quoteTicker := k.GetPoolQuoteTicker(ctx) if req.PositionType == types.PositionType_LONG { - result = positions.EvaluateLongPositions(getPriceFunc(ctx)) + result = positions.EvaluateLongPositions(quoteTicker, getPriceFunc(ctx)) } else if req.PositionType == types.PositionType_SHORT { - result = positions.EvaluateShortPositions(getPriceFunc(ctx)) + result = positions.EvaluateShortPositions(quoteTicker, getPriceFunc(ctx)) } else { return nil, status.Error(codes.InvalidArgument, "invalid position type") } diff --git a/x/derivatives/keeper/perpetual_futures.go b/x/derivatives/keeper/perpetual_futures.go index 2c41222bf..f8a2a19b1 100644 --- a/x/derivatives/keeper/perpetual_futures.go +++ b/x/derivatives/keeper/perpetual_futures.go @@ -112,7 +112,10 @@ func (k Keeper) ClosePerpetualFuturesPosition(ctx sdk.Context, position types.Pe } } - returningAmount, lossToLP := position.CalcReturningAmountAtClose(baseUsdPrice, quoteUsdPrice) + quoteTicker := k.GetPoolQuoteTicker(ctx) + baseMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.BaseDenom, baseUsdPrice) + quoteMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.QuoteDenom, quoteUsdPrice) + returningAmount, lossToLP := position.CalcReturningAmountAtClose(baseMetricsRate, quoteMetricsRate) if !(lossToLP.IsNil()) { // TODO: emit event to tell how much loss is taken by liquidity provider. @@ -141,7 +144,10 @@ func (k Keeper) ReportLiquidationNeededPerpetualFuturesPosition(ctx sdk.Context, panic(err) } - if position.NeedLiquidation(params.PerpetualFutures.MarginMaintenanceRate, currentBaseUsdRate, currentQuoteUsdRate) { + quoteTicker := k.GetPoolQuoteTicker(ctx) + baseMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.BaseDenom, currentBaseUsdRate) + quoteMetricsRate := types.NewMetricsRateType(quoteTicker, position.Market.QuoteDenom, currentQuoteUsdRate) + if position.NeedLiquidation(params.PerpetualFutures.MarginMaintenanceRate, baseMetricsRate, quoteMetricsRate) { k.ClosePerpetualFuturesPosition(ctx, position) rewardAmount := sdk.NewDecFromInt(position.RemainingMargin.Amount).Mul(params.PoolParams.ReportLiquidationRewardRate).RoundInt() diff --git a/x/derivatives/types/positions.go b/x/derivatives/types/positions.go index 5794d68dd..3138b7938 100644 --- a/x/derivatives/types/positions.go +++ b/x/derivatives/types/positions.go @@ -37,7 +37,7 @@ func MustUnpackPositionInstance(positionAny types.Any) PositionInstance { return position } -func (m Position) NeedLiquidation(MarginMaintenanceRate, currentBaseUsdRate, currentQuoteUsdRate sdk.Dec) bool { +func (m Position) NeedLiquidation(MarginMaintenanceRate sdk.Dec, currentBaseMetricsRate, currentQuoteMetricsRate MetricsRateType) bool { ins, err := UnpackPositionInstance(m.PositionInstance) if err != nil { return false @@ -46,7 +46,7 @@ func (m Position) NeedLiquidation(MarginMaintenanceRate, currentBaseUsdRate, cur switch positionInstance := ins.(type) { case *PerpetualFuturesPositionInstance: perpetualFuturesPosition := NewPerpetualFuturesPosition(m, *positionInstance) - return perpetualFuturesPosition.NeedLiquidation(MarginMaintenanceRate, currentBaseUsdRate, currentQuoteUsdRate) + return perpetualFuturesPosition.NeedLiquidation(MarginMaintenanceRate, currentBaseMetricsRate, currentQuoteMetricsRate) break case *PerpetualOptionsPositionInstance: panic("not implemented") @@ -98,8 +98,8 @@ func NewPerpetualFuturesPositionFromPosition(position Position) (PerpetualFuture return PerpetualFuturesPosition{}, fmt.Errorf("this Any doesn't have PerpetualFuturesPositionInstance value") } -func (m PerpetualFuturesPosition) NeedLiquidation(minMarginMaintenanceRate, currentBaseUsdRate, currentQuoteUsdRate sdk.Dec) bool { - marginMaintenanceRate := m.MarginMaintenanceRate(currentBaseUsdRate, currentQuoteUsdRate) +func (m PerpetualFuturesPosition) NeedLiquidation(minMarginMaintenanceRate sdk.Dec, currentBaseMetricsRate, currentQuoteMetricsRate MetricsRateType) bool { + marginMaintenanceRate := m.MarginMaintenanceRate(currentBaseMetricsRate, currentQuoteMetricsRate) if marginMaintenanceRate.LT(minMarginMaintenanceRate) { return true } else { @@ -112,17 +112,17 @@ func (m PerpetualFuturesPosition) OpenedPairRate() sdk.Dec { } // todo make test -func (m PerpetualFuturesPosition) EvaluatePosition(currentBaseUsdRate sdk.Dec) sdk.Dec { - return currentBaseUsdRate.Mul(m.PositionInstance.Size_) +func (m PerpetualFuturesPosition) EvaluatePosition(currentBaseMetricsRate MetricsRateType) sdk.Dec { + return currentBaseMetricsRate.Amount.Amount.Mul(m.PositionInstance.Size_) } func MicroToNormalDenom(amount sdk.Dec) math.Int { return amount.Mul(sdk.MustNewDecFromStr("1000000")).TruncateInt() } -func (m PerpetualFuturesPosition) CalcReturningAmountAtClose(baseUSDRate, quoteUSDRate sdk.Dec) (returningAmount math.Int, lossToLP math.Int) { +func (m PerpetualFuturesPosition) CalcReturningAmountAtClose(baseMetricsRate, quoteMetricsRate MetricsRateType) (returningAmount math.Int, lossToLP math.Int) { principal := m.RemainingMargin.Amount - pnlAmount := m.ProfitAndLossInMetrics(baseUSDRate, quoteUSDRate) + pnlAmount := m.ProfitAndLossInMetrics(baseMetricsRate, quoteMetricsRate) returningAmount = principal.Add(pnlAmount.TruncateInt()) @@ -136,7 +136,7 @@ func (m PerpetualFuturesPosition) CalcReturningAmountAtClose(baseUSDRate, quoteU } // todo make test -func (m Positions) EvaluatePositions(posType PositionType, getCurrentPriceF func(denom string) (sdk.Dec, error)) sdk.Dec { +func (m Positions) EvaluatePositions(posType PositionType, quoteTicker string, getCurrentPriceF func(denom string) (sdk.Dec, error)) sdk.Dec { usdMap := map[string]sdk.Dec{} result := sdk.ZeroDec() for _, position := range m { @@ -159,7 +159,10 @@ func (m Positions) EvaluatePositions(posType PositionType, getCurrentPriceF func if perpetualFuturesPosition.PositionInstance.PositionType != posType { continue } - result = result.Add(perpetualFuturesPosition.EvaluatePosition(usdMap[position.Market.BaseDenom])) + + metricsRate := NewMetricsRateType(quoteTicker, position.Market.BaseDenom, usdMap[position.Market.BaseDenom]) + + result = result.Add(perpetualFuturesPosition.EvaluatePosition(metricsRate)) break case *PerpetualOptionsPositionInstance: panic("not implemented") @@ -170,12 +173,12 @@ func (m Positions) EvaluatePositions(posType PositionType, getCurrentPriceF func return result } -func (m Positions) EvaluateLongPositions(getCurrentPriceF func(denom string) (sdk.Dec, error)) sdk.Dec { - return m.EvaluatePositions(PositionType_LONG, getCurrentPriceF) +func (m Positions) EvaluateLongPositions(quoteTicker string, getCurrentPriceF func(denom string) (sdk.Dec, error)) sdk.Dec { + return m.EvaluatePositions(PositionType_LONG, quoteTicker, getCurrentPriceF) } -func (m Positions) EvaluateShortPositions(getCurrentPriceF func(denom string) (sdk.Dec, error)) sdk.Dec { - return m.EvaluatePositions(PositionType_SHORT, getCurrentPriceF) +func (m Positions) EvaluateShortPositions(quoteTicker string, getCurrentPriceF func(denom string) (sdk.Dec, error)) sdk.Dec { + return m.EvaluatePositions(PositionType_SHORT, quoteTicker, getCurrentPriceF) } func (m PerpetualFuturesPosition) RequiredMarginInQuote(baseQuoteRate sdk.Dec) sdk.Dec { @@ -187,22 +190,22 @@ func (m PerpetualFuturesPosition) RequiredMarginInBase() sdk.Dec { return m.PositionInstance.MarginRequirement(sdk.MustNewDecFromStr("1")) } -// func (m PerpetualFuturesPosition) RequiredMarginInMetrics(requiredMarginInQuote, quoteUSDRate sdk.Dec) sdk.Dec { -func (m PerpetualFuturesPosition) RequiredMarginInMetrics(baseUSDRate, quoteUSDRate sdk.Dec) sdk.Dec { +// func (m PerpetualFuturesPosition) RequiredMarginInMetrics(requiredMarginInQuote, quoteMetricsRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) RequiredMarginInMetrics(baseMetricsRate, quoteMetricsRate MetricsRateType) sdk.Dec { // 必要証拠金(USD単位) = 必要証拠金(quote単位) * 現在のquote/USDレート // = 必要証拠金(base単位) * 現在のbase/USDレート if m.RemainingMargin.Denom == m.Market.QuoteDenom { - baseQuoteRate := baseUSDRate.Quo(quoteUSDRate) - return m.RequiredMarginInQuote(baseQuoteRate).Mul(quoteUSDRate) + baseQuoteRate := baseMetricsRate.Amount.Amount.Quo(quoteMetricsRate.Amount.Amount) + return m.RequiredMarginInQuote(baseQuoteRate).Mul(quoteMetricsRate.Amount.Amount) } else if m.RemainingMargin.Denom == m.Market.BaseDenom { - return m.RequiredMarginInBase().Mul(baseUSDRate) + return m.RequiredMarginInBase().Mul(baseMetricsRate.Amount.Amount) } else { panic("not supported denom") } } -func (m PerpetualFuturesPosition) ProfitAndLossInQuote(baseUSDRate, quoteUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) ProfitAndLossInQuote(baseMetricsRate, quoteMetricsRate MetricsRateType) sdk.Dec { // 損益(quote単位) = (longなら1,shortなら-1) * (現在のbase/quoteレート - ポジション開設時base/quoteレート) * ポジションサイズ(base単位) - baseQuoteRate := baseUSDRate.Quo(quoteUSDRate) + baseQuoteRate := baseMetricsRate.Amount.Amount.Quo(quoteMetricsRate.Amount.Amount) profitOrLoss := baseQuoteRate.Sub(m.OpenedPairRate()).Mul(m.PositionInstance.Size_) if m.PositionInstance.PositionType == PositionType_LONG { return profitOrLoss @@ -211,35 +214,47 @@ func (m PerpetualFuturesPosition) ProfitAndLossInQuote(baseUSDRate, quoteUSDRate } } -func (m PerpetualFuturesPosition) ProfitAndLossInMetrics(baseUSDRate, quoteUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) ProfitAndLossInMetrics(baseMetricsRate, quoteMetricsRate MetricsRateType) sdk.Dec { // 損益(USD単位) = 損益(quote単位) * 現在のquote/USDレート - return m.ProfitAndLossInQuote(baseUSDRate, quoteUSDRate).Mul(quoteUSDRate) + return m.ProfitAndLossInQuote(baseMetricsRate, quoteMetricsRate).Mul(quoteMetricsRate.Amount.Amount) } -func (m PerpetualFuturesPosition) MarginMaintenanceRate(baseUSDRate, quoteUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) MarginMaintenanceRate(baseMetricsRate, quoteMetricsRate MetricsRateType) sdk.Dec { // 証拠金維持率 = 有効証拠金(USD単位) ÷ 必要証拠金(USD単位) - return m.EffectiveMarginInMetrics(baseUSDRate, quoteUSDRate).Quo(m.RequiredMarginInMetrics(baseUSDRate, quoteUSDRate)) + return m.EffectiveMarginInMetrics(baseMetricsRate, quoteMetricsRate).Quo(m.RequiredMarginInMetrics(baseMetricsRate, quoteMetricsRate)) } -func (m PerpetualFuturesPosition) RemainingMarginInBase(baseUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) RemainingMarginInBase(baseMetricsRate MetricsRateType) sdk.Dec { // 残存証拠金(USD単位) = 残存証拠金(base単位) * 現在のbase/USDレート - return sdk.NewDecFromInt(m.RemainingMargin.Amount).Mul(baseUSDRate) + return sdk.NewDecFromInt(m.RemainingMargin.Amount).Mul(baseMetricsRate.Amount.Amount) } -func (m PerpetualFuturesPosition) RemainingMarginInQuote(quoteUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) RemainingMarginInQuote(quoteMetricsRate MetricsRateType) sdk.Dec { // 残存証拠金(USD単位) = 残存証拠金(quote単位) * 現在のquote/USDレート - return sdk.NewDecFromInt(m.RemainingMargin.Amount).Mul(quoteUSDRate) + return sdk.NewDecFromInt(m.RemainingMargin.Amount).Mul(quoteMetricsRate.Amount.Amount) } -func (m PerpetualFuturesPosition) RemainingMarginInMetrics(baseUSDRate, quoteUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) RemainingMarginInMetrics(baseMetricsRate, quoteMetricsRate MetricsRateType) sdk.Dec { // 残存証拠金(USD単位) = 残存証拠金(base単位) * 現在のbase/USDレート // = 残存証拠金(quote単位) * 現在のquote/USDレート if m.RemainingMargin.Denom == m.Market.BaseDenom { - return m.RemainingMarginInBase(baseUSDRate) + return m.RemainingMarginInBase(baseMetricsRate) } else if m.RemainingMargin.Denom == m.Market.QuoteDenom { - return m.RemainingMarginInQuote(quoteUSDRate) + return m.RemainingMarginInQuote(quoteMetricsRate) } else { panic("not supported denom") } } -func (m PerpetualFuturesPosition) EffectiveMarginInMetrics(baseUSDRate, quoteUSDRate sdk.Dec) sdk.Dec { +func (m PerpetualFuturesPosition) EffectiveMarginInMetrics(baseMetricsRate, quoteMetricsRate MetricsRateType) sdk.Dec { // 有効証拠金(USD単位) = 残存証拠金(USD単位) + 損益(USD単位) - return m.RemainingMarginInMetrics(baseUSDRate, quoteUSDRate).Add(m.ProfitAndLossInMetrics(baseUSDRate, quoteUSDRate)) + return m.RemainingMarginInMetrics(baseMetricsRate, quoteMetricsRate).Add(m.ProfitAndLossInMetrics(baseMetricsRate, quoteMetricsRate)) +} + +func NewMetricsRateType(unit string, denom string, amount sdk.Dec) MetricsRateType { + return MetricsRateType{ + MetricsUnit: unit, + Amount: sdk.NewDecCoinFromDec(denom, amount), + } +} + +type MetricsRateType struct { + MetricsUnit string + Amount sdk.DecCoin }