mango-explorer/tests/test_walletbalancer.py

155 lines
5.7 KiB
Python

from .context import mango
from .fakes import fake_token
from decimal import Decimal
from solana.publickey import PublicKey
ETH_TOKEN = mango.Token("ETH", "Wrapped Ethereum (Sollet)", PublicKey(
"2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk"), Decimal(6))
BTC_TOKEN = mango.Token("BTC", "Wrapped Bitcoin (Sollet)", PublicKey(
"9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E"), Decimal(6))
USDT_TOKEN = mango.Token("USDT", "USDT", PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"), Decimal(6))
def test_target_balance_constructor():
succeeded = False
try:
mango.TargetBalance(fake_token())
except TypeError:
# Can't instantiate the abstract base class.
succeeded = True
assert succeeded
def test_fixed_target_balance_constructor():
token = fake_token()
value = Decimal(23)
actual = mango.FixedTargetBalance(token, value)
assert actual is not None
assert actual.token == token
assert actual.value == value
def test_percentage_target_balance_constructor():
token = fake_token()
value = Decimal(5)
actual = mango.PercentageTargetBalance(token, value)
assert actual is not None
assert actual.token == token
assert actual.target_fraction == Decimal("0.05") # Calculated as a fraction instead of a percentage.
def test_target_balance_parser_constructor():
token1 = fake_token()
token2 = fake_token()
tokens = [token1, token2]
actual = mango.TargetBalanceParser(tokens)
assert actual is not None
assert actual.tokens == tokens
def test_calculate_required_balance_changes():
current_balances = [
mango.TokenValue(ETH_TOKEN, Decimal("0.5")),
mango.TokenValue(BTC_TOKEN, Decimal("0.2")),
mango.TokenValue(USDT_TOKEN, Decimal("10000")),
]
desired_balances = [
mango.TokenValue(ETH_TOKEN, Decimal("1")),
mango.TokenValue(BTC_TOKEN, Decimal("0.1"))
]
changes = mango.calculate_required_balance_changes(current_balances, desired_balances)
assert(changes[0].token.symbol == "ETH")
assert(changes[0].value == Decimal("0.5"))
assert(changes[1].token.symbol == "BTC")
assert(changes[1].value == Decimal("-0.1"))
def test_percentage_target_balance():
token = fake_token()
percentage_parsed_balance_change = mango.PercentageTargetBalance(token, Decimal(33))
assert(percentage_parsed_balance_change.token == token)
current_token_price = Decimal(2000) # It's $2,000 per TOKEN
current_account_value = Decimal(10000) # We hold $10,000 in total across all assets in our account.
resolved_parsed_balance_change = percentage_parsed_balance_change.resolve(
current_token_price, current_account_value)
assert(resolved_parsed_balance_change.token == token)
# 33% of $10,000 is $3,300
# $3,300 spent on TOKEN gives us 1.65 TOKEN
assert(resolved_parsed_balance_change.value == Decimal("1.65"))
def test_target_balance_parser():
parser = mango.TargetBalanceParser([ETH_TOKEN, BTC_TOKEN, USDT_TOKEN])
parsed_percent = parser.parse("eth:10%")
assert(parsed_percent.token == ETH_TOKEN)
assert(parsed_percent.target_fraction == Decimal("0.1"))
parsed_fixed = parser.parse("eth:70")
assert(parsed_fixed.token == ETH_TOKEN)
assert(parsed_fixed.value == Decimal(70))
def test_filter_small_changes_constructor():
current_prices = [
mango.TokenValue(ETH_TOKEN, Decimal("4000")),
mango.TokenValue(BTC_TOKEN, Decimal("60000")),
mango.TokenValue(USDT_TOKEN, Decimal("1")),
]
current_balances = [
mango.TokenValue(ETH_TOKEN, Decimal("0.5")),
mango.TokenValue(BTC_TOKEN, Decimal("0.2")),
mango.TokenValue(USDT_TOKEN, Decimal("10000")),
]
action_threshold = Decimal("0.01") # Don't bother if it's less than 1% of the total value (24,000)
expected_prices = {
f"{current_prices[0].token.mint}": current_prices[0],
f"{current_prices[1].token.mint}": current_prices[1],
f"{current_prices[2].token.mint}": current_prices[2]
}
expected_total_balance = Decimal(24000)
expected_action_threshold_value = expected_total_balance / 100 # Action threshold is 0.01
actual = mango.FilterSmallChanges(action_threshold, current_balances, current_prices)
assert actual is not None
assert actual.logger is not None
assert actual.prices == expected_prices
assert actual.total_balance == expected_total_balance
assert actual.action_threshold_value == expected_action_threshold_value
def test_filtering_small_changes():
current_prices = [
mango.TokenValue(ETH_TOKEN, Decimal("4000")),
mango.TokenValue(BTC_TOKEN, Decimal("60000")),
mango.TokenValue(USDT_TOKEN, Decimal("1")),
]
current_balances = [
mango.TokenValue(ETH_TOKEN, Decimal("0.5")),
mango.TokenValue(BTC_TOKEN, Decimal("0.2")),
mango.TokenValue(USDT_TOKEN, Decimal("10000")),
]
action_threshold = Decimal("0.01") # Don't bother if it's less than 1% of the total value (24,000)
actual = mango.FilterSmallChanges(action_threshold, current_balances, current_prices)
# 0.05 ETH is worth $200 at our test prices, which is less than our $240 threshold
assert(not actual.allow(mango.TokenValue(ETH_TOKEN, Decimal("0.05"))))
# 0.05 BTC is worth $3,000 at our test prices, which is much more than our $240 threshold
assert(actual.allow(mango.TokenValue(BTC_TOKEN, Decimal("0.05"))))
def test_sort_changes_for_trades():
eth_buy = mango.TokenValue(ETH_TOKEN, Decimal("5"))
btc_sell = mango.TokenValue(BTC_TOKEN, Decimal("-1"))
sorted_changes = mango.sort_changes_for_trades([
eth_buy,
btc_sell
])
assert(sorted_changes[0] == btc_sell)
assert(sorted_changes[1] == eth_buy)