diff --git a/econ/fi.go b/econ/fi.go index 7e58d43..ba2787a 100644 --- a/econ/fi.go +++ b/econ/fi.go @@ -1,10 +1,10 @@ package econ import ( - "math" "math/big" "github.com/glifio/go-pools/constants" + "github.com/glifio/go-pools/util" ) func NewBaseFi( @@ -200,16 +200,12 @@ func (bfi *BaseFi) LiquidationValue() *big.Int { return new(big.Int).Sub(bfi.Balance, bfi.TerminationFee) } -func (bfi *BaseFi) RecoveryRate() float64 { +func (bfi *BaseFi) RecoveryRate() *big.Float { if bfi.Balance.Cmp(big.NewInt(0)) == 0 { - return 0 + return big.NewFloat(0) } - rr, _ := new(big.Float).Quo( - new(big.Float).SetInt(bfi.LiquidationValue()), - new(big.Float).SetInt(bfi.Balance)).Float64() - - return rr + return computePerc(bfi.LiquidationValue(), bfi.Balance) } // MaxBorrowAndSeal = margin / (1 - max borrow DTL) - margin @@ -294,30 +290,32 @@ func (afi *AgentFi) LeverageRatio() *big.Float { return new(big.Float).SetInf(true) } - return new(big.Float).Quo( - new(big.Float).SetInt(afi.LiquidationValue()), - new(big.Float).SetInt(afi.Margin())) + return computePerc(afi.LiquidationValue(), afi.Margin()) } -func (afi *AgentFi) DTL() float64 { +func (afi *AgentFi) DTL() *big.Float { // if debt is zero then DTL is 0 if afi.Debt().Cmp(big.NewInt(0)) == 0 { - return 0 + return big.NewFloat(0) } lv := afi.LiquidationValue() // if liquidation value is zero and debt is non zero then DTL is infinite if lv.Cmp(big.NewInt(0)) == 0 { // return positive infinite float - return math.Inf(1) + return new(big.Float).SetInf(true) } - dtl, _ := new(big.Float).Quo( - new(big.Float).SetInt(afi.Debt()), - new(big.Float).SetInt(afi.LiquidationValue()), - ).Float64() - return dtl + return computePerc(afi.Debt(), afi.LiquidationValue()) } func (l *Liability) Debt() *big.Int { return new(big.Int).Add(l.Principal, l.Interest) } + +func computePerc(numerator, denominator *big.Int) *big.Float { + if denominator.Cmp(big.NewInt(0)) == 0 { + return new(big.Float).SetInf(true) + } + + return util.ToFIL(util.DivWad(numerator, denominator)) +} diff --git a/econ/terminate_test.go b/econ/terminate_test.go index 23b55a9..356e796 100644 --- a/econ/terminate_test.go +++ b/econ/terminate_test.go @@ -480,6 +480,7 @@ type agentFiTest struct { withdrawLimit *big.Int marginCall *big.Int leverageRatio float64 + dtl float64 } var agentTests = []struct { @@ -513,6 +514,7 @@ var agentTests = []struct { withdrawLimit: bigFromStr("8911457546764252091903"), marginCall: bigFromStr("1272158912732776255650271"), leverageRatio: 0.5743316423053819, + dtl: 0.574289111476492565, }}, // agent 27 {"agent no miners", "0xDBa96B0FDbc87C7eEb641Ee37EAFC55B355079E4", BLOCK_HEIGHT, agentFiTest{ @@ -525,6 +527,7 @@ var agentTests = []struct { withdrawLimit: big.NewInt(0), marginCall: big.NewInt(0), leverageRatio: 0, + dtl: 0, }}, // agent 2 {"agent single miner", "0xf0F1ceCCF78D411EeD9Ca190ca7F157140cCB2d3", BLOCK_HEIGHT, agentFiTest{ @@ -551,6 +554,7 @@ var agentTests = []struct { withdrawLimit: bigFromStr("57665444302030819344"), marginCall: bigFromStr("2359669285522428148"), leverageRatio: 0.016656085317377764, + dtl: 0.016608593934123496, }}, // agent 91 {"agent miner with fee debt", "0xFF65F5f3D309fEA7aA2d4cB2727E918FAb0aE7F7", BLOCK_HEIGHT, agentFiTest{ @@ -577,6 +581,7 @@ var agentTests = []struct { withdrawLimit: bigFromStr("0"), marginCall: bigFromStr("0"), leverageRatio: 0, + dtl: 0, }}, {"agent with balance no miners", "0xf0F1ceCCF78D411EeD9Ca190ca7F157140cCB2d3", big.NewInt(4238800), agentFiTest{ AgentFi: &AgentFi{ @@ -602,6 +607,7 @@ var agentTests = []struct { withdrawLimit: bigFromStr("3454284493328524959"), marginCall: bigFromStr("0"), leverageRatio: 0, + dtl: 0, }}, {"agent with balance no miners with principal", "0xf0F1ceCCF78D411EeD9Ca190ca7F157140cCB2d3", big.NewInt(4238810), agentFiTest{ AgentFi: &AgentFi{ @@ -627,6 +633,7 @@ var agentTests = []struct { withdrawLimit: bigFromStr("3120950589218935919"), marginCall: bigFromStr("1176471091861402094"), leverageRatio: 0.22450304410954403, + dtl: 0.224502948003829978, }}, } @@ -662,6 +669,18 @@ func TestEstimateTermationFeeAgent(t *testing.T) { } } +func TestComputePerc(t *testing.T) { + lv := bigFromStr("871702482492442116952350") + p := bigFromStr("343733044178305628615912") + i := bigFromStr("28202982363374106229") + + perc := computePerc(new(big.Int).Add(p, i), lv) + exp := big.NewFloat(0.394356164017979036) + if perc.Cmp(exp) != 0 { + t.Fatalf("Expected perc: %v, actual: %v", exp, perc) + } +} + func assertAgentFiEqual(t *testing.T, expected *agentFiTest, actual *AgentFi) { if expected.AvailableBalance.Cmp(actual.AvailableBalance) != 0 { t.Fatalf("Expected available balance: %v, actual: %v", expected.AvailableBalance, actual.AvailableBalance) @@ -709,8 +728,9 @@ func assertAgentFiEqual(t *testing.T, expected *agentFiTest, actual *AgentFi) { if expected.marginCall.Cmp(actual.MarginCall()) != 0 { t.Fatalf("Expected margin call: %v, actual: %v", expected.marginCall, actual.MarginCall()) } - if expected.leverageRatio != actual.DTL() { - t.Fatalf("Expected leverage ratio: %v, actual: %v", expected.leverageRatio, actual.DTL()) + dtl, _ := actual.DTL().Float64() + if expected.leverageRatio != dtl { + t.Fatalf("Expected leverage ratio: %v, actual: %v", expected.leverageRatio, dtl) } }