Files
mev-beta/examples/profitability_demo.go
2025-10-04 09:31:02 -05:00

168 lines
5.2 KiB
Go

// Package main demonstrates MEV bot profitability calculations
package main
import (
"fmt"
"math/big"
"github.com/fraktal/mev-beta/pkg/math"
)
func runProfitabilityDemo() {
fmt.Println("=== MEV Bot Profitability Demonstration ===")
fmt.Println()
// Create a decimal converter for handling different denominations
dc := math.NewDecimalConverter()
// Example 1: Basic arbitrage calculation
fmt.Println("1. Basic Arbitrage Profitability:")
// Simulate a trade: 1 ETH -> USDC -> DAI -> ETH
inputETH, _ := dc.FromString("1.0", 18, "ETH")
// Exchange rates (simplified for demonstration)
// 1 ETH = 3000 USDC
usdcPerETH, _ := dc.FromString("3000.0", 6, "USDC")
usdcAmount, _ := dc.Multiply(inputETH, usdcPerETH, 6, "USDC")
// 1 USDC = 0.999 DAI (0.1% slippage)
daiPerUSDC, _ := dc.FromString("0.999", 18, "DAI")
daiAmount, _ := dc.Multiply(usdcAmount, daiPerUSDC, 18, "DAI")
// 1 DAI = 0.000333 ETH (slightly less than 1/3000 due to slippage)
ethPerDAI, _ := dc.FromString("0.000333", 18, "ETH")
outputETH, _ := dc.Multiply(daiAmount, ethPerDAI, 18, "ETH")
fmt.Printf(" Input: %s ETH\n", formatDecimal(inputETH))
fmt.Printf(" Route: ETH -> USDC -> DAI -> ETH\n")
fmt.Printf(" Output: %s ETH\n", formatDecimal(outputETH))
// Calculate gross profit
grossProfit, _ := dc.Subtract(outputETH, inputETH)
fmt.Printf(" Gross Profit: %s ETH\n", formatDecimal(grossProfit))
// Estimate gas costs (0.001 ETH for a 3-hop arbitrage)
gasCost, _ := dc.FromString("0.001", 18, "ETH")
netProfit, _ := dc.Subtract(grossProfit, gasCost)
fmt.Printf(" Gas Cost: %s ETH\n", formatDecimal(gasCost))
fmt.Printf(" Net Profit: %s ETH\n", formatDecimal(netProfit))
profitPercentage, _ := dc.CalculatePercentage(netProfit, inputETH)
fmt.Printf(" Profit Percentage: %s%%\n", formatDecimal(profitabilityToPercentage(profitPercentage)))
// Check if profitable (minimum 0.01 ETH profit)
minProfit, _ := dc.FromString("0.01", 18, "ETH")
isProfitable := netProfit.Value.Cmp(minProfit.Value) > 0
fmt.Printf(" Is Profitable (>0.01 ETH)? %t\n", isProfitable)
fmt.Println()
// Example 2: Price impact analysis
fmt.Println("2. Price Impact Analysis:")
// Simulate large trade affecting pool price
poolLiquidity, _ := dc.FromString("1000.0", 18, "ETH")
tradeSize, _ := dc.FromString("50.0", 18, "ETH")
// Price impact = (tradeSize / (tradeSize + liquidity))^2
// Simplified calculation for demonstration
priceImpact := calculateSimplePriceImpact(tradeSize, poolLiquidity)
fmt.Printf(" Pool Liquidity: %s ETH\n", formatDecimal(poolLiquidity))
fmt.Printf(" Trade Size: %s ETH\n", formatDecimal(tradeSize))
fmt.Printf(" Price Impact: %.2f%%\n", priceImpact*100)
// High price impact increases slippage and reduces profitability
fmt.Println(" Note: High price impact leads to increased slippage and reduced profitability")
fmt.Println()
// Example 3: Risk assessment
fmt.Println("3. Key Profitability Factors:")
fmt.Println(" • Accurate price calculations and slippage modeling")
fmt.Println(" • Realistic gas cost estimation")
fmt.Println(" • Competition analysis for optimal bidding")
fmt.Println(" • Risk assessment to avoid unprofitable opportunities")
fmt.Println(" • Proper sizing to balance profits and price impact")
fmt.Println()
}
// Helper function to format decimals for display
func formatDecimal(d *math.UniversalDecimal) string {
if d == nil {
return "0"
}
// Convert to float for easier formatting
f := new(big.Float).SetInt(d.Value)
f.Quo(f, big.NewFloat(float64(power(10, int(d.Decimals)))))
// Format based on symbol
switch d.Symbol {
case "PERCENT":
return fmt.Sprintf("%.2f", mustFloat64(f))
case "ETH":
return fmt.Sprintf("%.6f", mustFloat64(f))
case "USDC", "DAI":
return fmt.Sprintf("%.2f", mustFloat64(f))
default:
return fmt.Sprintf("%.4f", mustFloat64(f))
}
}
// Helper function to convert profitability percentage to readable format
func profitabilityToPercentage(d *math.UniversalDecimal) *math.UniversalDecimal {
if d == nil {
return &math.UniversalDecimal{Value: big.NewInt(0), Decimals: 2, Symbol: "PERCENT"}
}
// Convert from decimal to percentage (multiply by 100)
f := new(big.Float).SetInt(d.Value)
f.Quo(f, big.NewFloat(float64(power(10, int(d.Decimals)))))
f.Mul(f, big.NewFloat(100))
// Convert back to big.Int with 2 decimal places
result := big.NewInt(0)
f.Mul(f, big.NewFloat(100)).Int(result)
return &math.UniversalDecimal{Value: result, Decimals: 2, Symbol: "PERCENT"}
}
// Simple price impact calculation
func calculateSimplePriceImpact(tradeSize, liquidity *math.UniversalDecimal) float64 {
// Price impact = tradeSize / (tradeSize + liquidity)
// This is a simplified model
if liquidity.Value.Sign() == 0 {
return 0
}
ratio := new(big.Float).Quo(
new(big.Float).SetInt(tradeSize.Value),
new(big.Float).SetInt(liquidity.Value),
)
// Square the ratio for concentrated liquidity impact
result := new(big.Float).Mul(ratio, ratio)
f, _ := result.Float64()
return f
}
// Helper function for integer powers
func power(base, exp int) int {
result := 1
for i := 0; i < exp; i++ {
result *= base
}
return result
}
// Helper function to convert big.Float to float64
func mustFloat64(f *big.Float) float64 {
if f == nil {
return 0
}
result, _ := f.Float64()
return result
}