Skip to content

Commit

Permalink
WIP4
Browse files Browse the repository at this point in the history
  • Loading branch information
nagakingg committed Feb 1, 2024
1 parent e10ab86 commit 7dbffb3
Show file tree
Hide file tree
Showing 16 changed files with 151 additions and 112 deletions.
4 changes: 4 additions & 0 deletions curvesim/exceptions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def __repr__(self):
return f"HttpClientError({self.status}, {self.message}, url={self.url})"


class CurvesimTypeError(CurvesimException, TypeError):
"""Raised when an argument is the wrong type."""


class CurvesimValueError(CurvesimException, ValueError):
"""Raised when an argument has an inappropriate value (but the right type)."""

Expand Down
51 changes: 17 additions & 34 deletions curvesim/iterators/price_samplers/price_volume.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Iterator

from curvesim.logging import get_logger
from curvesim.price_data import get_price_data
from curvesim.templates.price_samplers import PriceSample, PriceSampler
from curvesim.utils import dataclass, override

Expand Down Expand Up @@ -29,15 +28,7 @@ class PriceVolume(PriceSampler):
An iterator that retrieves price/volume and iterates over timepoints in the data.
"""

def __init__(
self,
assets,
*,
days=60,
data_dir="data",
src="coingecko",
end=None,
):
def __init__(self, data):
"""
Retrieves price/volume data and prepares it for iteration.
Expand All @@ -57,17 +48,7 @@ def __init__(
Identifies pricing source: coingecko or local.
"""
prices, volumes, _ = get_price_data(
assets.addresses,
chain=assets.chain,
days=days,
data_dir=data_dir,
src=src,
end=end,
)

self.prices = prices.set_axis(assets.symbol_pairs, axis="columns")
self.volumes = volumes.set_axis(assets.symbol_pairs, axis="columns")
self.data = data

@override
def __iter__(self) -> Iterator[PriceVolumeSample]:
Expand All @@ -76,16 +57,18 @@ def __iter__(self) -> Iterator[PriceVolumeSample]:
-------
:class:`PriceVolumeSample`
"""
for price_row, volume_row in zip(
self.prices.iterrows(), self.volumes.iterrows()
):
price_timestamp, prices = price_row
volume_timestamp, volumes = volume_row
assert (
price_timestamp == volume_timestamp
), "Price/volume timestamps don't match"

prices = prices.to_dict()
volumes = volumes.to_dict()

yield PriceVolumeSample(price_timestamp, prices, volumes) # type:ignore
for row in self.data.iterrows():
timestamp, row_data = row

prices = row_data["price"].to_dict()
volumes = row_data["volume"].to_dict()

yield PriceVolumeSample(timestamp, prices, volumes) # type:ignore

@property
def prices(self):
return self.data["price"]

@property
def volumes(self):
return self.data["volume"]
7 changes: 1 addition & 6 deletions curvesim/metrics/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,6 @@ def __init__(self, coin_names, **kwargs):
Symbols for the coins used in a simulation. A numeraire is selected from
the specified coins.
"""

self.coin_names = coin_names
self.numeraire = get_numeraire(coin_names)
super().__init__(**kwargs)

Expand Down Expand Up @@ -348,9 +346,6 @@ def get_market_price(self, base, quote, prices):
return prices[(base, quote)]


pandas_coin_pair_attr = {DataFrame: "columns", Series: "index"}


def get_coin_pairs(prices):
"""
Returns the coin pairs available in the price data.
Expand Down Expand Up @@ -418,4 +413,4 @@ def __init__(self, pool, **kwargs):
:func:`pool_config` and stored as :python:`self._pool` for access during
metric computations. Number and names of coins derived from pool metadata.
"""
super().__init__(pool.assets.symbols, pool=pool)
super().__init__(pool.asset_names, pool=pool)
4 changes: 2 additions & 2 deletions curvesim/metrics/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def config(self):
}

def __init__(self, pool, **kwargs):
super().__init__(pool.assets.symbols)
super().__init__(pool.asset_names)

def compute_arb_metrics(self, **kwargs):
"""Computes all metrics for each timestamp in an individual run."""
Expand Down Expand Up @@ -218,7 +218,7 @@ def get_stableswap_metapool_volume(self, **kwargs):
"""
trade_data = kwargs["trade_data"]

meta_asset = self._pool.assets.symbols[0]
meta_asset = self._pool.asset_names[0]

def per_timestamp_function(trade_data):
volume = 0
Expand Down
4 changes: 4 additions & 0 deletions curvesim/pipelines/common/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"""
Contains variables and functions common to the arbitrage pipelines.
"""
__all__ = ["DEFAULT_METRICS", "get_arb_trades", "get_asset_data", "get_pool_data"]

from scipy.optimize import root_scalar

from curvesim.logging import get_logger
from curvesim.metrics import metrics as Metrics
from curvesim.templates.trader import ArbTrade

from .get_asset_data import get_asset_data
from .get_pool_data import get_pool_data

logger = get_logger(__name__)
DEFAULT_METRICS = [
Metrics.Timestamp,
Expand Down
22 changes: 22 additions & 0 deletions curvesim/pipelines/common/get_asset_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from datetime import datetime, timedelta, timezone

from curvesim.pool_data import get_pool_assets
from curvesim.price_data import get_price_data
from curvesim.templates import DateTimeSequence


def get_asset_data(pool_metadata, time_sequence, data_source):
sim_assets = get_pool_assets(pool_metadata)
time_sequence = time_sequence or _make_default_time_sequence()
asset_data = get_price_data(
sim_assets, time_sequence, data_source=data_source
) # allow DataSource to be passed
return asset_data, time_sequence


def _make_default_time_sequence():
t_end = datetime.now(timezone.utc) - timedelta(days=1)
t_end = t_end.replace(hour=23, minute=0, second=0, microsecond=0)
t_start = t_end - timedelta(days=60) + timedelta(hours=1)
time_sequence = DateTimeSequence.from_range(start=t_start, end=t_end, freq="1h")
return time_sequence
44 changes: 44 additions & 0 deletions curvesim/pipelines/common/get_pool_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from datetime import datetime

from curvesim.exceptions import CurvesimTypeError
from curvesim.pool import get_sim_pool
from curvesim.pool_data import get_metadata
from curvesim.pool_data.metadata import PoolMetaDataInterface


def get_pool_data(metadata_or_address, chain, env, pool_ts):
pool_metadata = _parse_metadata_or_address(metadata_or_address, chain)
end_ts = _parse_timestamp(pool_ts)
pool = get_sim_pool(pool_metadata, env=env, end_ts=end_ts)

return pool, pool_metadata


def _parse_timestamp(timestamp) -> int:
if not timestamp:
return timestamp

if isinstance(timestamp, datetime):
timestamp = int(timestamp.timestamp())

if not isinstance(timestamp, int):
_type = type(timestamp).__name__
raise CurvesimTypeError(f"'Pool_ts' must be 'int' or 'timestamp', not {_type}.")

return timestamp


def _parse_metadata_or_address(metadata_or_address, chain):
if isinstance(metadata_or_address, str):
pool_metadata: PoolMetaDataInterface = get_metadata(metadata_or_address, chain)

elif isinstance(metadata_or_address, PoolMetaDataInterface):
pool_metadata = metadata_or_address

else:
_type = type(metadata_or_address).__name__
raise CurvesimTypeError(
f"'Metadata_or_address' must be 'PoolMetaDataInterface' or 'str', not {_type}."
)

return pool_metadata
21 changes: 8 additions & 13 deletions curvesim/pipelines/simple/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,19 @@
from curvesim.metrics.results import make_results
from curvesim.pipelines import run_pipeline
from curvesim.pipelines.simple.strategy import SimpleStrategy
from curvesim.pool import get_sim_pool

from ..common import DEFAULT_METRICS
from ..common import DEFAULT_METRICS, get_asset_data, get_pool_data


def pipeline( # pylint: disable=too-many-locals
pool_address,
chain,
metadata_or_address,
*,
chain="mainnet",
variable_params=None,
fixed_params=None,
end_ts=None,
days=60,
src="coingecko",
data_dir="data",
time_sequence=None,
pool_ts=None,
ncpu=None,
env="prod",
):
Expand Down Expand Up @@ -84,15 +82,12 @@ def pipeline( # pylint: disable=too-many-locals
"""
ncpu = ncpu or os.cpu_count()

pool = get_sim_pool(pool_address, chain, env=env, end_ts=end_ts)

sim_assets = pool.assets
price_sampler = PriceVolume(
sim_assets, days=days, end=end_ts, data_dir=data_dir, src=src
)
pool, pool_metadata = get_pool_data(metadata_or_address, chain, env, pool_ts)
asset_data, _ = get_asset_data(pool_metadata, time_sequence, src)

# pylint: disable-next=abstract-class-instantiated
param_sampler = ParameterizedPoolIterator(pool, variable_params, fixed_params)
price_sampler = PriceVolume(asset_data)

_metrics = init_metrics(DEFAULT_METRICS, pool=pool)
strategy = SimpleStrategy(_metrics)
Expand Down
2 changes: 1 addition & 1 deletion curvesim/pipelines/simple/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
if __name__ == "__main__":
pool_address = "0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7"
chain = "mainnet"
results = pipeline(pool_address, chain, ncpu=1)
results = pipeline(pool_address, chain=chain, ncpu=1)
23 changes: 12 additions & 11 deletions curvesim/pipelines/vol_limited_arb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@
from curvesim.iterators.price_samplers import PriceVolume
from curvesim.logging import get_logger
from curvesim.metrics import init_metrics, make_results
from curvesim.pool import get_sim_pool
from curvesim.pool_data import get_pool_volume

from .. import run_pipeline
from ..common import DEFAULT_METRICS
from ..common import DEFAULT_METRICS, get_asset_data, get_pool_data
from .strategy import VolumeLimitedStrategy

logger = get_logger(__name__)


# pylint: disable-next=too-many-locals
def pipeline(
pool_metadata,
metadata_or_address,
*,
chain="mainnet",
variable_params=None,
fixed_params=None,
metrics=None,
days=60,
src="coingecko",
data_dir="data",
time_sequence=None,
vol_mult=None,
pool_ts=None,
ncpu=None,
end=None,
env="prod",
):
"""
Implements the volume-limited arbitrage pipeline.
Expand Down Expand Up @@ -91,16 +91,17 @@ def pipeline(
cpu_count = os.cpu_count()
ncpu = cpu_count if cpu_count is not None else 1

pool = get_sim_pool(pool_metadata)
pool, pool_metadata = get_pool_data(metadata_or_address, chain, env, pool_ts)
asset_data, time_sequence = get_asset_data(pool_metadata, time_sequence, src)

# pylint: disable-next=abstract-class-instantiated
param_sampler = ParameterizedPoolIterator(pool, variable_params, fixed_params)
price_sampler = PriceVolume(
pool.assets, days=days, data_dir=data_dir, src=src, end=end
)
price_sampler = PriceVolume(asset_data)

if vol_mult is None:
pool_volume = get_pool_volume(pool_metadata, days=days, end=end)
pool_volume = get_pool_volume(
pool_metadata, time_sequence[0], time_sequence[-1]
)
vol_mult = pool_volume.sum() / price_sampler.volumes.sum()
logger.info("Volume Multipliers:\n%s", vol_mult.to_string())
vol_mult = vol_mult.to_dict()
Expand Down
2 changes: 1 addition & 1 deletion curvesim/pool_data/queries/pool_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from curvesim.constants import Chain
from curvesim.pool_data.metadata import PoolMetaDataInterface
from curvesim.pool_data.queries.metadata import get_metadata
from curvesim.templates.sim_asset import OnChainAsset, OnChainAssetPair
from curvesim.templates import OnChainAsset, OnChainAssetPair
from curvesim.utils import get_pairs


Expand Down
Loading

0 comments on commit 7dbffb3

Please sign in to comment.