Skip to content

Commit

Permalink
Tobi/multi asset reserve (#160)
Browse files Browse the repository at this point in the history
* adding DAI market price process
* Multi-asset reserve with statistics
* Type refactoring
* Pair refactoring

Co-authored-by: boqdan <[email protected]>
Co-authored-by: Nadiem Sissouno <[email protected]>
  • Loading branch information
3 people authored Jun 22, 2022
1 parent d780fd8 commit d7a5daf
Show file tree
Hide file tree
Showing 24 changed files with 440 additions and 212 deletions.
63 changes: 53 additions & 10 deletions experiments/notebooks/buy-and-sell/1_mento1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"import experiments.default_experiment as default_experiment\n",
"\n",
"# types\n",
"from model.types import *\n",
"from model.types.base import *\n",
"from model.entities.balance import Balance\n",
"\n",
"# options\n",
Expand Down Expand Up @@ -164,8 +164,10 @@
"source": [
"simulation_analysis_1.model.initial_state.update({\n",
" 'reserve_balance': Balance({\n",
" CryptoAsset.CELO: 120.0e6,\n",
" Stable.CUSD: 0.0\n",
" CryptoAsset.CELO: 10000000.0,\n",
" CryptoAsset.BTC: 1000.0,\n",
" CryptoAsset.ETH: 15000.0,\n",
" CryptoAsset.DAI: 80000000.0,\n",
" }),\n",
"})"
]
Expand Down Expand Up @@ -206,6 +208,16 @@
"pprint(simulation_analysis_1.model.params)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "60da36c1",
"metadata": {},
"outputs": [],
"source": [
"simulation_analysis_1.model.params['mento_exchanges_config'][0].keys()"
]
},
{
"cell_type": "markdown",
"id": "7471a5ed",
Expand All @@ -221,9 +233,9 @@
"metadata": {},
"outputs": [],
"source": [
"simulation_analysis_1.model.params.update({\n",
" \"reserve_fraction\": [0.5],\n",
"})"
"#simulation_analysis_1.model.params.update({\n",
"# \"reserve_fraction\": [0.5],\n",
"#})"
]
},
{
Expand Down Expand Up @@ -297,7 +309,8 @@
"metadata": {},
"outputs": [],
"source": [
"df.head()"
"pd.set_option(\"display.max_columns\", None)\n",
"df.tail(20)"
]
},
{
Expand Down Expand Up @@ -463,6 +476,36 @@
"visualizations.plot_helper(data_frame=df, column_label='reserve_balance_celo', y_label='# tokens')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "07afc390",
"metadata": {},
"outputs": [],
"source": [
"visualizations.plot_helper(data_frame=df, column_label='reserve_balance_in_usd')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5511ab57",
"metadata": {},
"outputs": [],
"source": [
"visualizations.plot_helper(data_frame=df, column_label='reserve_ratio')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a9ce188",
"metadata": {},
"outputs": [],
"source": [
"visualizations.plot_helper(data_frame=df, column_label='floating_supply_stables_in_usd')"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -495,9 +538,9 @@
"hash": "e0d943ef511eb062da37f0005de9c5ca6dc4c50b1f75cb4cb85f428d08d55d84"
},
"kernelspec": {
"display_name": "Python 3.8.9 ('mento2-model-ZNlqjaYt')",
"display_name": "mento2-model",
"language": "python",
"name": "python3"
"name": "mento2-model"
},
"language_info": {
"codemirror_mode": {
Expand All @@ -509,7 +552,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.9"
"version": "3.8.12"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion experiments/simulation_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from model.constants import blocks_per_day, blocks_per_year

BLOCKS_PER_TIMESTEP = 1 # number of blocks per timestep (=1 if sim on per-block-basis)
SIMULATION_TIME_DAYS = 1 # number of days
SIMULATION_TIME_DAYS = 2 # number of days
# number of simulation_configuration timesteps
TIMESTEPS = SIMULATION_TIME_DAYS * blocks_per_day // BLOCKS_PER_TIMESTEP
TIMESTEPS_PER_YEAR = blocks_per_year // BLOCKS_PER_TIMESTEP
Expand Down
13 changes: 11 additions & 2 deletions model/entities/balance.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
Balance(celo=2, cusd=10) + Balance(celo=5, cusd=0) = Balance(celo=7, cusd=10)
"""
from typing import Callable, Dict, TYPE_CHECKING

from model.types.base import Fiat
from model.types.pair import Pair
if TYPE_CHECKING:
from model.types import Currency
from model.types.base import Currency


class Balance(dict):
"""
Expand All @@ -26,7 +30,6 @@ def __str__(self) -> str:
])
return f"Balance({values})"


@staticmethod
def zero():
return Balance()
Expand All @@ -43,6 +46,12 @@ def __combine__(self, other: "Balance", combinator: Callable[[int, int], int]):
for currency in set(self.keys()).union(other.keys())
})

def values_in_usd(self, prev_state):
values_in_usd = {
key: inventory * Pair(key, Fiat.USD).get_rate(prev_state).value
for key, inventory in self.items()}
return values_in_usd

@property
def any_negative(self) -> bool:
for (_, value) in self.items():
Expand Down
3 changes: 2 additions & 1 deletion model/entities/oracle_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

from typing import List
from uuid import UUID
from model.types import OracleConfig, Pair
from model.types.configs import OracleConfig
from model.types.pair import Pair
from model.constants import blocktime_seconds
from model.utils.rng_provider import RNGProvider

Expand Down
11 changes: 6 additions & 5 deletions model/entities/strategies/strategy_arbitrage_trader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from enum import Enum
import numpy as np

from model.types import MentoBuckets
from model.types.base import MentoBuckets
from .trader_strategy import TraderStrategy


class TradingRegime(Enum):
SELL_STABLE = "SELL_STABLE"
SELL_RESERVE_ASSET = "SELL_RESERVE_ASSET"
Expand Down Expand Up @@ -135,10 +136,10 @@ def sell_order_stable(self, buckets: MentoBuckets, market_price: float, spread:
}

def sell_order_reserve_asset(
self,
buckets: MentoBuckets,
market_price: float,
spread: float):
self,
buckets: MentoBuckets,
market_price: float,
spread: float):
"""
Calculate order for selling the reserve currency
"""
Expand Down
20 changes: 14 additions & 6 deletions model/entities/strategies/trader_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
from cvxpy import Maximize, Minimize, Problem, Variable
import cvxpy

from model.types import MentoBuckets, MentoExchangeConfig, Pair
from model.types.base import MentoBuckets
from model.types.pair import Pair
from model.types.configs import MentoExchangeConfig
if TYPE_CHECKING:
from model.entities.trader import Trader


class TraderStrategy:
"""
Base trader strategy class to solve a convex optimisation problem.
Expand Down Expand Up @@ -85,7 +88,8 @@ def define_constraints(self, params, prev_state):
max_budget_stable = self.parent.balance.get(self.stable)
max_budget_reserve_asset = self.parent.balance.get(self.reserve_asset)
if self.sell_reserve_asset(params, prev_state):
self.constraints.append(self.variables["sell_amount"] <= max_budget_reserve_asset)
self.constraints.append(
self.variables["sell_amount"] <= max_budget_reserve_asset)
else:
self.constraints.append(self.variables["sell_amount"] <= max_budget_stable)

Expand Down Expand Up @@ -150,12 +154,14 @@ def minimise_price_impact(self, sell_amount, sell_reserve_asset, params):
# Todo logic is probably wrong, fix!
if sell_reserve_asset:
sell_amount_adjusted = min(
params["average_daily_volume"].get(Pair(self.stable, self.reference_fiat)),
params["average_daily_volume"].get(
Pair(self.stable, self.reference_fiat)),
sell_amount
)
elif not sell_reserve_asset:
sell_amount_adjusted = min(
params["average_daily_volume"].get(Pair(self.reserve_asset, self.reference_fiat)),
params["average_daily_volume"].get(
Pair(self.reserve_asset, self.reference_fiat)),
sell_amount
)
return sell_amount_adjusted
Expand All @@ -181,7 +187,8 @@ def return_optimal_trade(self, params, prev_state):
trade = None
else:
sell_reserve_asset = self.sell_reserve_asset(params, prev_state)
sell_amount = self.minimise_price_impact(sell_amount, sell_reserve_asset, params)
sell_amount = self.minimise_price_impact(
sell_amount, sell_reserve_asset, params)
buy_amount = self.mento.get_buy_amount(
exchange=self.parent.config.exchange,
sell_amount=sell_amount,
Expand All @@ -199,7 +206,8 @@ def return_optimal_trade(self, params, prev_state):
def market_price(self, prev_state) -> float:
# TODO: Do we need to quote in equivalent Fiat for Stable?
return (
prev_state["market_price"].get(Pair(self.reserve_asset, self.reference_fiat))
prev_state["market_price"].get(
Pair(self.reserve_asset, self.reference_fiat))
/ prev_state["market_price"].get(Pair(self.stable, self.reference_fiat))
)

Expand Down
4 changes: 3 additions & 1 deletion model/entities/trader.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
from model.generators.mento import MentoExchangeGenerator
from model.entities import strategies
from model.entities.account import Account, Balance
from model.types import MentoExchangeConfig, Pair, TraderConfig
from model.types.pair import Pair
from model.types.configs import MentoExchangeConfig, TraderConfig
from model.utils.rng_provider import RNGProvider

if TYPE_CHECKING:
from model.generators.accounts import AccountGenerator


class Trader(Account):
"""
The Trader extens an account with a trading strategy.
Expand Down
16 changes: 8 additions & 8 deletions model/generators/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from model.entities.account import Account
from model.entities.trader import Trader
from model.entities.balance import Balance
from model.types import TraderConfig
from model.types.configs import TraderConfig
from model.utils import update_from_signal
from model.utils.generator import Generator, state_update_blocks
from model.utils.generator_container import GeneratorContainer
Expand All @@ -32,11 +32,11 @@ class AccountGenerator(Generator):
rngp: RNGProvider

def __init__(self,
reserve_inventory: Balance,
initial_floating_supply: Balance,
traders: List[TraderConfig],
container: GeneratorContainer,
rngp: RNGProvider):
reserve_inventory: Balance,
initial_floating_supply: Balance,
traders: List[TraderConfig],
container: GeneratorContainer,
rngp: RNGProvider):
self.container = container
self.rngp = rngp
self.reserve = self.create_reserve_account(
Expand Down Expand Up @@ -116,7 +116,7 @@ def traders(self) -> List[Trader]:
account
for account in self.accounts_by_id.values()
if isinstance(account, Trader)
]
]

def get(self, account_id) -> Account:
account = self.accounts_by_id.get(account_id)
Expand All @@ -131,7 +131,7 @@ def tracked_floating_supply(self) -> Balance:
return sum(
[account.balance for account in self.accounts_by_id.values()],
Balance.zero()
)
)

@property
def floating_supply(self) -> Balance:
Expand Down
2 changes: 1 addition & 1 deletion model/generators/markets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from experiments.simulation_configuration import TOTAL_BLOCKS
from model.system_parameters import Parameters

from model.types import MarketPriceModel
from model.types.base import MarketPriceModel
from model.utils.data_feed import DATA_FOLDER, DataFeed
from model.utils.generator import Generator
from model.utils.price_impact_valuator import PriceImpactValuator
Expand Down
4 changes: 3 additions & 1 deletion model/generators/mento.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from model.constants import blocktime_seconds
from model.entities.balance import Balance
from model.types import MentoBuckets, MentoExchange, MentoExchangeConfig, Pair, Stable
from model.types.base import MentoBuckets, MentoExchange, Stable
from model.types.pair import Pair
from model.types.configs import MentoExchangeConfig
from model.utils.generator import Generator, state_update_blocks
from model.utils import update_from_signal

Expand Down
3 changes: 2 additions & 1 deletion model/generators/oracles.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@


from model.entities.oracle_provider import OracleProvider
from model.types import OracleConfig, Pair
from model.types.pair import Pair
from model.types.configs import OracleConfig
from model.utils import update_from_signal
from model.utils.generator import Generator, state_update_blocks
from model.utils.rng_provider import RNGProvider
Expand Down
5 changes: 2 additions & 3 deletions model/parts/celo_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from model.entities.balance import Balance
from model.generators.accounts import AccountGenerator
from model.constants import target_epoch_rewards_downscaled, seconds_per_epoch, blocktime_seconds
from model.types import CryptoAsset, Fiat, Pair, Stable
from model.types.base import CryptoAsset, Fiat, Stable
from model.types.pair import Pair
from model.utils.generator_container import inject


Expand All @@ -33,8 +34,6 @@ def p_epoch_rewards(_params, _substep, _state_history, prev_state,
validator_rewards
/ prev_state["oracle_rate"].get(Pair(CryptoAsset.CELO, Fiat.USD))
)


account_generator.reserve.balance += Balance({
CryptoAsset.CELO: validator_rewards,
})
Expand Down
Loading

0 comments on commit d7a5daf

Please sign in to comment.