Skip to content

Commit

Permalink
Merge pull request #170 from bancorprotocol/simulator-tutorials
Browse files Browse the repository at this point in the history
Last Simulator Session Updates
  • Loading branch information
mikewcasale authored Sep 30, 2022
2 parents 31c279f + 4718e66 commit a782a82
Show file tree
Hide file tree
Showing 18 changed files with 62,328 additions and 1,794 deletions.
2 changes: 1 addition & 1 deletion bancor_research/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,4 @@ def read_price_feeds(price_feeds_path: str):
return price_feeds


__version__ = "3.1.0"
__version__ = "3.1.1"
2 changes: 1 addition & 1 deletion bancor_research/bancor_simulator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning)

__version__ = "3.1.0"
__version__ = "3.1.1"
183 changes: 175 additions & 8 deletions bancor_research/bancor_simulator/v3/spec/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@
# Licensed under the MIT LICENSE. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------------------------------
"""Agent-based actions. (e.g. trade, deposit, withdraw, etc...)"""
from pydantic.dataclasses import dataclass

from bancor_research.bancor_simulator.v3.spec.state import (
get_trade_inputs,
get_withdrawal_id,
Cooldown,
Token,
)
from bancor_research.bancor_simulator.v3.spec.utils import *


Expand Down Expand Up @@ -905,3 +897,178 @@ def vortex_burner(state: State, user_name: str):
state.set_tkn_trading_liquidity(tkn_name, updated_tkn_liquidity)
state.increase_staked_balance(tkn_name, trade_fee)
state.update_spot_rate(tkn_name)


def process_arbitrage_trade(
tkn_name: str,
tkn_token_virtual_balance: Decimal,
bnt_virtual_balance: Decimal,
bnt_trading_liquidity: Decimal,
tkn_trading_liquidity: Decimal,
trading_fee: Decimal,
user_tkn: Decimal,
user_bnt: Decimal,
) -> Tuple[Decimal, str, str, bool]:
"""
Computes the appropriate arbitrage trade on the tkn_name pool.
"""
a = bnt_trading_liquidity
b = tkn_trading_liquidity
m = trading_fee
p = bnt_virtual_balance
q = tkn_token_virtual_balance

bnt_trade_amt = (
-Decimal("2") * a * q
+ b * m * p
+ (
(Decimal("2") * a * q - b * m * p) ** Decimal("2")
- Decimal("4") * a * q * (a * q - b * p)
)
** (Decimal("1") / Decimal("2"))
) / (Decimal("2") * q)

tkn_trade_amt = (
-Decimal("2") * b * p
+ a * m * q
+ (
(Decimal("2") * b * p - a * m * q) ** Decimal("2")
- Decimal("4") * b * p * (b * p - a * q)
)
** (Decimal("1") / Decimal("2"))
) / (Decimal("2") * p)

if bnt_trade_amt > 0:
source_token = "bnt"
target_token = tkn_name
trade_amt = bnt_trade_amt
user_capability = user_bnt > bnt_trade_amt
return trade_amt, source_token, target_token, user_capability

elif tkn_trade_amt > 0:
source_token = tkn_name
target_token = "bnt"
trade_amt = tkn_trade_amt
user_capability = user_tkn > tkn_trade_amt
return trade_amt, source_token, target_token, user_capability


def trade_tkn_to_ema(
bnt_trading_liquidity: Decimal,
tkn_trading_liquidity: Decimal,
trading_fee: Decimal,
network_fee: Decimal,
future_ema: Decimal,
) -> Decimal:
"""
Outputs the tkn_amt that should be traded to force the ema and the spot price together on a given pool.
"""
a = bnt_trading_liquidity
b = tkn_trading_liquidity
d = trading_fee
e = network_fee
f = future_ema
tkn_amt = (
(a * d * (Decimal("1") - e) - Decimal("2") * f * b)
+ (
a
* (
Decimal("4") * f * b * (Decimal("1") - d * (Decimal("1") - e))
+ a * d ** Decimal("2") * (Decimal("1") - e) ** Decimal("2")
)
)
** (Decimal("1") / Decimal("2"))
) / (Decimal("2") * f)
return tkn_amt


def trade_bnt_to_ema(
bnt_trading_liquidity,
tkn_trading_liquidity,
trading_fee,
network_fee,
future_ema,
):
"""
Analyze the state of any pool and create a swap that drives the ema and the spot price together.
"""

a = bnt_trading_liquidity
b = tkn_trading_liquidity
d = trading_fee
e = network_fee
f = future_ema
x = (
-Decimal("2") * a
+ b * d * f
+ (
(Decimal("2") * a - b * d * f) ** Decimal("2")
- Decimal("4") * a * (a - b * f)
)
** (Decimal("1") / Decimal("2"))
) / Decimal("2")
a_recursion = (
a * (a + x) + d * (Decimal("1") - e) * (a * x + x ** Decimal("2"))
) / (a + d * x)
b_recursion = b * (a + d * x) / (a + x)
n = 0
p = Decimal("0.001")
while a_recursion / b_recursion < f:
n += 1
p += Decimal("0.0001")
x += x * (f**p - (a_recursion / b_recursion) ** p) / f
a_recursion = (
a * (a + x) + d * (Decimal("1") - e) * (a * x + x ** Decimal("2"))
) / (a + d * x)
b_recursion = b * (a + d * x) / (a + x)
if n > 20000:
break
bnt_amt = x
return bnt_amt


def process_force_moving_average(
self, tkn_name: str, user_tkn: Decimal, user_bnt: Decimal
) -> Tuple[Decimal, str, str, bool]:
"""
Process the trade amount to force the ema and the spot price together.
"""
state = self.protocol.v3.global_state
tkn_trading_liquidity = get_tkn_trading_liquidity(state, tkn_name)
bnt_trading_liquidity = get_bnt_trading_liquidity(state, tkn_name)
trading_fee = get_trading_fee(state, tkn_name)
network_fee = get_network_fee(state, tkn_name)
ema_rate = get_ema_rate(state, tkn_name)
spot_rate = get_spot_rate(state, tkn_name)
future_ema = compute_ema(spot_rate, ema_rate)
if ema_rate < spot_rate:
source_tkn = tkn_name
target_tkn = "bnt"
trade_amt = trade_tkn_to_ema(
bnt_trading_liquidity,
tkn_trading_liquidity,
trading_fee,
network_fee,
future_ema,
)
user_capability = user_tkn > trade_amt
elif ema_rate > spot_rate:
source_tkn = "bnt"
target_tkn = tkn_name
trade_amt = trade_bnt_to_ema(
bnt_trading_liquidity,
tkn_trading_liquidity,
trading_fee,
network_fee,
future_ema,
)
user_capability = user_bnt > trade_amt
else:
source_tkn = tkn_name
target_tkn = tkn_name
trade_amt = Decimal("0")
user_capability = False

self.latest_tkn_name = source_tkn + "_" + target_tkn
self.latest_amt = trade_amt
return trade_amt, source_tkn, target_tkn, user_capability
6 changes: 6 additions & 0 deletions bancor_research/bancor_simulator/v3/spec/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,12 @@ def get_user_reward_per_token_paid(state: State, id: int, user_name: str) -> Dec
)


def get_bnt_per_tkn(state: State, tkn_name: str):
tkn_price = get_tkn_price(state, tkn_name)
bnt_price = get_tkn_price(state, "bnt")
return tkn_price / bnt_price


def get_tkn_trading_liquidity(state: State, tkn_name: str) -> Decimal:
"""
The current tkn trading liquidity for a given tkn_name.
Expand Down
20 changes: 14 additions & 6 deletions bancor_research/bancor_simulator/v3/spec/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@
# Licensed under the MIT LICENSE. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------------------------------
"""Utility functions."""
from bancor_research.bancor_simulator.v3.spec.state import *
from bancor_research import Decimal, DataFrame
import json, pickle, cloudpickle
import cloudpickle
import json
import pickle

from bancor_research import Decimal, DataFrame
from bancor_research.bancor_simulator.v3.spec.state import *

protocol_user = "protocol"


def compute_ema(
spot_rate: Decimal, ema_rate: Decimal, alpha: Decimal = Decimal("0.2")
) -> Decimal:
"""
Computes the ema as a lagging average only once per block, per pool.
"""
return alpha * spot_rate + (1 - alpha) * ema_rate


def check_if_program_enabled(start_time: int, end_time: int, timestamp: int):
"""
Checks if the given rewards program is enabled.
Expand Down Expand Up @@ -353,7 +364,6 @@ def handle_whitelisting_tokens(state):

# Get tokens not yet initialized.
if tkn_name not in state.tokens:

decimals = whitelisted_tokens[tkn_name]["decimals"]
trading_fee = whitelisted_tokens[tkn_name]["trading_fee"]
bnt_funding_limit = whitelisted_tokens[tkn_name]["bnt_funding_limit"]
Expand Down Expand Up @@ -406,7 +416,6 @@ def init_protocol(

# Get tokens not yet initialized.
if tkn_name not in state.tokens:

decimals = whitelisted_tokens[tkn_name]["decimals"]
trading_fee = whitelisted_tokens[tkn_name]["trading_fee"]
bnt_funding_limit = whitelisted_tokens[tkn_name]["bnt_funding_limit"]
Expand Down Expand Up @@ -438,7 +447,6 @@ def init_protocol(
)

for tkn_name in ["bnt", "bnbnt", "vbnt"]:

state.tokens[tkn_name] = Tokens(
tkn_name=tkn_name,
network_fee=network_fee,
Expand Down
1 change: 1 addition & 0 deletions bancor_research/scenario_generator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
# --------------------------------------------------------------------------------------------------------------------
# Licensed under the MIT LICENSE. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------------------------------
from .monte_carlo_generator import MonteCarloGenerator
Loading

0 comments on commit a782a82

Please sign in to comment.