Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 27 additions & 26 deletions bancor_research/bancor_simulator/v3/spec/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@
from bancor_research import DEFAULT, PandasDataFrame, read_price_feeds, pd


def toDecimal(percent: str):
def to_decimal(percent: str):
return Decimal(percent[:-1]) / 100


def userAmount(state: State, tkn_name: str, user_name: str, amount: str):
if amount.endswith("%"):
return get_user_balance(state, user_name, tkn_name) * toDecimal(amount)
def get_user_amount(state: State, tkn_name: str, user_name: str, amount: Any):
if str(amount).endswith("%"):
return (
get_user_balance(state, user_name, tkn_name)
* Decimal(str(amount)[:-1])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with regards to str(amount)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same response as previous

/ 100
)
return Decimal(amount)


Expand Down Expand Up @@ -74,7 +78,7 @@ def __init__(

whitelisted_tokens = {
k: {
"trading_fee": toDecimal(v["trading_fee"]),
"trading_fee": to_decimal(v["trading_fee"]),
"bnt_funding_limit": Decimal(v["bnt_funding_limit"]),
}
for k, v in whitelisted_tokens.items()
Expand All @@ -92,9 +96,9 @@ def __init__(
whitelisted_tokens=whitelisted_tokens,
usernames=[],
cooldown_time=cooldown_time,
network_fee=toDecimal(network_fee),
network_fee=to_decimal(network_fee),
bnt_min_liquidity=Decimal(bnt_min_liquidity),
withdrawal_fee=toDecimal(withdrawal_fee),
withdrawal_fee=to_decimal(withdrawal_fee),
)

# initialize bnt
Expand Down Expand Up @@ -187,10 +191,10 @@ def deposit(
Top level logic for deposit actions.
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, tkn_name, user_name = validate_input(
state, tkn_name, user_name, timestamp
tkn_amt = get_user_amount(state, tkn_name, user_name, tkn_amt)
state, tkn_name, tkn_amt, user_name = validate_input(
state, tkn_name, tkn_amt, user_name, timestamp
)
tkn_amt = userAmount(state, tkn_name, user_name, tkn_amt)
if tkn_name == "bnt":
state = deposit_bnt(
state=state, tkn_name=tkn_name, tkn_amt=tkn_amt, user_name=user_name
Expand Down Expand Up @@ -223,13 +227,10 @@ def trade(
Main logic for trade actions.
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, source_token, user_name = validate_input(
state, source_token, user_name, timestamp
tkn_amt = get_user_amount(state, source_token, user_name, tkn_amt)
state, source_token, tkn_amt, user_name = validate_input(
state, source_token, tkn_amt, user_name, timestamp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same (you can/should revert this change).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

)
state, target_token, user_name = validate_input(
state, target_token, user_name, timestamp
)
tkn_amt = userAmount(state, source_token, user_name, tkn_amt)
state = process_trade(
state, tkn_amt, source_token, target_token, user_name, timestamp
)
Expand All @@ -255,10 +256,10 @@ def begin_cooldown(
Begin the withdrawal cooldown operation.
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, tkn_name, user_name = validate_input(
state, tkn_name, user_name, timestamp
tkn_amt = get_user_amount(state, tkn_name, user_name, tkn_amt)
state, tkn_name, tkn_amt, user_name = validate_input(
state, tkn_name, tkn_amt, user_name, timestamp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same (you can/should revert this change).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

)
tkn_amt = userAmount(state, tkn_name, user_name, tkn_amt)
state, id_number = begin_withdrawal_cooldown(
state, tkn_amt, tkn_name, user_name
)
Expand Down Expand Up @@ -518,7 +519,7 @@ def burn_pool_tokens(
state, tkn_name, user_name = validate_input(
state, tkn_name, user_name, timestamp
)
tkn_amt = userAmount(state, tkn_name, user_name, tkn_amt)
tkn_amt = get_user_amount(state, tkn_name, user_name, tkn_amt)
if tkn_name != "bnt":
state.decrease_pooltoken_balance(tkn_name, tkn_amt)
state.decrease_user_balance(
Expand Down Expand Up @@ -582,7 +583,7 @@ def join_standard_rewards_program(
state, tkn_name, user_name = validate_input(
state, tkn_name, user_name, timestamp
)
tkn_amt = userAmount(state, tkn_name, user_name, tkn_amt)
tkn_amt = get_user_amount(state, tkn_name, user_name, tkn_amt)
state = join_standard_reward_program(
state=state,
user_name=user_name,
Expand Down Expand Up @@ -611,7 +612,7 @@ def leave_standard_rewards_program(
state, tkn_name, user_name = validate_input(
state, tkn_name, user_name, timestamp
)
tkn_amt = userAmount(state, tkn_name, user_name, tkn_amt)
tkn_amt = get_user_amount(state, tkn_name, user_name, tkn_amt)
state = leave_standard_reward_program(
state=state,
user_name=user_name,
Expand Down Expand Up @@ -695,7 +696,7 @@ def set_trading_fee(
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, tkn_name, user_name = validate_input(state, tkn_name, "", timestamp)
value = toDecimal(percent)
value = to_decimal(percent)
state.set_trading_fee(tkn_name, value)
self.next_transaction(state)
handle_logging(
Expand All @@ -715,7 +716,7 @@ def set_network_fee(
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, tkn_name, user_name = validate_input(state, tkn_name, "", timestamp)
value = toDecimal(percent)
value = to_decimal(percent)
state.set_network_fee(tkn_name, value)
self.next_transaction(state)
handle_logging(
Expand All @@ -735,7 +736,7 @@ def set_withdrawal_fee(
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, tkn_name, user_name = validate_input(state, tkn_name, "", timestamp)
value = toDecimal(percent)
value = to_decimal(percent)
state.set_withdrawal_fee(tkn_name, value)
self.next_transaction(state)
handle_logging(
Expand All @@ -755,7 +756,7 @@ def set_bnt_funding_limit(
"""
state = self.get_state(copy_type="initial", timestamp=timestamp)
state, tkn_name, user_name = validate_input(state, tkn_name, "", timestamp)
value = toDecimal(amount)
value = to_decimal(amount)
state.set_bnt_funding_limit(tkn_name, value)
self.next_transaction(state)
handle_logging(
Expand Down
45 changes: 24 additions & 21 deletions bancor_research/scenario_generator/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@
# Licensed under the MIT LICENSE. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------------------------------
"""Mesa Agent-based implementations of the Bancor protocol."""
from decimal import Decimal
from typing import Tuple

import mesa

from bancor_research.bancor_simulator.v3.spec import get_prices, State, get_bnt_trading_liquidity, \
get_tkn_trading_liquidity, get_trading_fee, get_user_balance, get_is_trading_enabled, get_network_fee, get_ema_rate, \
get_spot_rate, get_vault_balance, get_pooltoken_balance, get_staked_balance, get_external_protection_vault, \
get_protocol_wallet_balance, get_vortex_balance, get_bnt_funding_limit, get_bnbnt_rate, get_max_bnt_deposit, \
get_user_pending_withdrawals
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: I'd split that into several statements (would make it more readable IMO) - one for each getter function, and one for all the rest. Or perhaps just do it with parenthesis, similarly to how you are doing it below).

from bancor_research.bancor_simulator.v3.spec.actions import (
unpack_withdrawal_cooldown,
vortex_burner,
)
from bancor_research.bancor_simulator.v3.spec.network import BancorDapp
from bancor_research.bancor_simulator.v3.simulation.random_walk import RandomWalker
from bancor_research.bancor_simulator.v3.simulation.utils import (
from bancor_research.scenario_generator.monte_carlo import MonteCarlo
from bancor_research.scenario_generator.utils import (
trade_tkn_to_ema,
trade_bnt_to_ema,
process_arbitrage_trade,
Expand All @@ -26,7 +33,7 @@
)


class Trader(RandomWalker):
class Trader(MonteCarlo):
"""
Represents a Bancor dapp user (trader and/or arbitrageur). Subclass to Mesa Agent
"""
Expand Down Expand Up @@ -267,9 +274,8 @@ def perform_random_ema_force_trade(self):
return self

def get_random_tkn_names(self, state: State) -> Tuple[str, str]:
tokens = state.whitelisted_tokens
source_tkn = self.random.choice(tokens)
target_tkn = self.random.choice([tkn for tkn in tokens if tkn != source_tkn])
tokens = [tkn for tkn in state.whitelisted_tokens]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: I think that you can also use tokens = list(whitelisted_tokens.keys()), if you happen to prefer it.
Same in a bunch of places below...

source_tkn, target_tkn = self.random.sample(tokens, 2)
return source_tkn, target_tkn

def get_average_trading_fee(self):
Expand Down Expand Up @@ -328,7 +334,7 @@ def step(self):
self.transact()


class LP(RandomWalker):
class LP(MonteCarlo):
"""
Represents a Bancor dapp liquidity provider. Subclass to Mesa Agent
"""
Expand Down Expand Up @@ -432,7 +438,7 @@ def get_random_bnt_funding_limit(self, bnt_funding_amt: Decimal) -> Decimal:
def set_random_trading_fee(self):
state = self.protocol.v3.global_state
for i in range(self.random.randint(1, 3)):
tkn_name = self.random.choice(state.whitelisted_tokens)
tkn_name = self.random.choice([tkn for tkn in state.whitelisted_tokens])
trading_fee = get_trading_fee(state, tkn_name)
trading_fee = self.get_random_trading_fee(trading_fee)
state.set_trading_fee(tkn_name, trading_fee)
Expand All @@ -441,7 +447,7 @@ def set_random_trading_fee(self):

def set_random_network_fee(self):
state = self.protocol.v3.global_state
tkn_name = self.random.choice(state.whitelisted_tokens)
tkn_name = self.random.choice([tkn for tkn in state.whitelisted_tokens])
network_fee = get_network_fee(state, tkn_name)
network_fee = self.get_random_network_fee(network_fee)
state.set_network_fee(tkn_name, network_fee)
Expand All @@ -451,25 +457,25 @@ def set_random_network_fee(self):
def set_random_withdrawal_fee(self):
state = self.protocol.v3.global_state
withdrawal_fee = state.withdrawal_fee
tkn_name = self.random.choice(state.whitelisted_tokens)
tkn_name = self.random.choice([tkn for tkn in state.whitelisted_tokens])
withdrawal_fee = self.get_random_withdrawal_fee(withdrawal_fee)
state.set_withdrawal_fee(tkn_name, withdrawal_fee)
self.protocol.v3.set_state(state)
return self

def set_random_bnt_funding_limit(self):
state = self.protocol.v3.global_state
tkn_name = self.random.choice(state.whitelisted_tokens)
tkn_name = self.random.choice([tkn for tkn in state.whitelisted_tokens])
bnt_funding_limit = get_bnt_funding_limit(state, tkn_name)
updated_bnt_funding_limit = self.get_random_bnt_funding_limit(bnt_funding_limit)
state.set_bnt_funding_limit(tkn_name, updated_bnt_funding_limit)
self.protocol.v3.set_state(state)
return self

def perform_random_enable_trading(self):
self.protocol.v3.dao_msig_init_pools(
self.protocol.v3.global_state.whitelisted_tokens, "bnt"
)
state = self.protocol.v3.global_state
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to initialize state here?

for tkn in [tkn for tkn in state.whitelisted_tokens]:
self.protocol.v3.enable_trading(tkn)
return self

def get_random_withdrawal_amt(self, tkn_name: str) -> Decimal:
Expand Down Expand Up @@ -497,9 +503,8 @@ def get_random_amt(self, amt: Decimal) -> Decimal:
return Decimal(self.random.uniform(float(min_amt), float(max_amt)))

def get_random_tkn_names(self, state: State) -> Tuple[str, str]:
tokens = state.whitelisted_tokens
source_tkn = self.random.choice(tokens)
target_tkn = self.random.choice([tkn for tkn in tokens if tkn != source_tkn])
tokens = [tkn for tkn in state.whitelisted_tokens]
source_tkn, target_tkn = self.random.sample(tokens, 2)
return source_tkn, target_tkn

def is_protocol_bnbnt_healthy(
Expand Down Expand Up @@ -554,7 +559,7 @@ def create_random_autocompounding_rewards(self):
timestamp = state.timestamp
start_time = 1 + timestamp

tkn_name = self.random.choice(state.whitelisted_tokens)
tkn_name = self.random.choice([tkn for tkn in state.whitelisted_tokens])
distribution_type = self.random.choice(["flat", "exp"])

if distribution_type == "flat":
Expand Down Expand Up @@ -769,7 +774,7 @@ def perform_random_withdrawal(self):
state = self.protocol.v3.global_state
timestamp = state.timestamp
user_name = self.random.choice(state.usernames)
tkn_name = self.random.choice(state.whitelisted_tokens)
tkn_name = self.random.choice([tkn for tkn in state.whitelisted_tokens])
pending_withdrawals = get_user_pending_withdrawals(state, user_name, tkn_name)
if len(pending_withdrawals) > 0:
id_number = self.random.choice(pending_withdrawals)
Expand Down Expand Up @@ -965,10 +970,8 @@ def __init__(
self.v3 = BancorDapp(
price_feeds=price_feeds,
whitelisted_tokens=whitelisted_tokens,
trading_fee=trading_fee,
network_fee=network_fee,
withdrawal_fee=withdrawal_fee,
bnt_funding_limit=bnt_funding_limit,
bnt_min_liquidity=bnt_min_liquidity,
)

Expand Down
7 changes: 7 additions & 0 deletions bancor_research/scenario_generator/batch_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
"""
import os

import mesa
from bancor_research.scenario_generator.constants import SIMULATION_MAX_STEPS, SIMULATION_OUTPUT_PATH

from bancor_research.scenario_generator.model import BancorSimulation

from bancor_research.bancor_simulator.v3.spec import *

# Add any desired parameters to sweep below.
br_params = {
"trading_fee": [
Expand Down
28 changes: 26 additions & 2 deletions bancor_research/scenario_generator/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
# --------------------------------------------------------------------------------------------------------------------
"""Simulation constants and default state variables."""
from decimal import Decimal
from bancor_research import DEFAULT
DEFAULT_TRADING_FEE = DEFAULT.TRADING_FEE
DEFAULT_BNT_FUNDING_LIMIT = DEFAULT.BNT_FUNDING_LIMIT
DEFAULT_NETWORK_FEE = DEFAULT.NETWORK_FEE
DEFAULT_WITHDRAWAL_FEE = DEFAULT.WITHDRAWAL_FEE

SIMULATION_TARGET_TVL: Decimal = Decimal("160000000")
SIMULATION_TARGET_TRADE_VOLUME: Decimal = Decimal("20000000")
Expand All @@ -13,6 +18,25 @@
SIMULATION_TARGET_NUM_WITHDRAWALS_PER_DAY: int = 200
SIMULATION_NUM_TRADERS = 2
SIMULATION_NUM_LPs = 2
SIMULATION_WHITELISTED_TOKENS = ["tkn", "bnt"]


SIMULATION_WHITELISTED_TOKENS = {
"eth": {
"trading_fee": DEFAULT_TRADING_FEE,
"bnt_funding_limit": DEFAULT_BNT_FUNDING_LIMIT,
},
"link": {
"trading_fee": DEFAULT_TRADING_FEE,
"bnt_funding_limit": DEFAULT_BNT_FUNDING_LIMIT,
},
"tkn": {
"trading_fee": DEFAULT_TRADING_FEE,
"bnt_funding_limit": DEFAULT_BNT_FUNDING_LIMIT,
},
"wbtc": {
"trading_fee": DEFAULT_TRADING_FEE,
"bnt_funding_limit": DEFAULT_BNT_FUNDING_LIMIT,
},
}
SIMULATION_MAX_STEPS = 100
SIMULATION_OUTPUT_PATH: str = "data/simulation_output.csv"
SIMULATION_OUTPUT_PATH: str = "examples/studies/limit_max_on_curve_liquidity/data/simulation_output.csv"
Loading