Skip to content

Commit

Permalink
WIP8
Browse files Browse the repository at this point in the history
  • Loading branch information
nagakingg committed Feb 21, 2024
1 parent cbe3962 commit 5bd18c1
Show file tree
Hide file tree
Showing 16 changed files with 251 additions and 46 deletions.
3 changes: 3 additions & 0 deletions curvesim/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""Contains various exceptions used in curvesim."""


class CurvesimException(Exception):
"""Base exception class"""

Expand Down
31 changes: 26 additions & 5 deletions curvesim/iterators/price_samplers/price_volume.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Contains PriceVolume price sampler and PriceVolumeSample dataclass.
"""

from typing import Iterator

from pandas import DataFrame
Expand Down Expand Up @@ -35,9 +39,12 @@ def __init__(self, data: DataFrame):
Parameters
----------
data: DataFrame
DataFrame with prices and volumes for each asset pair. Row indices must be
datetime.datetime or pd.Timestamp. Column indices must be MultIndex with
"price" and "volume" level 1 for each symbol-pair tuple in level 2.
DataFrame with prices and volumes for each asset pair.
Format should match output of :fun:"curvesim.price_data.get_price_data".
Row indices: datetime.datetime or pandas.Timestamp.
Column indices: MultIndex with "price" and "volume" level 1 for each tuple
of symbols in level 2.
"""
self.data = data

Expand All @@ -57,9 +64,23 @@ def __iter__(self) -> Iterator[PriceVolumeSample]:
yield PriceVolumeSample(timestamp, prices, volumes) # type:ignore

@property
def prices(self):
def prices(self) -> DataFrame:
"""
Returns price data for all asset pairs.
Returns
-------
pandas.DataFrame
"""
return self.data["price"]

@property
def volumes(self):
def volumes(self) -> DataFrame:
"""
Returns volume data for all asset pairs.
Returns
-------
pandas.DataFrame
"""
return self.data["volume"]
6 changes: 6 additions & 0 deletions curvesim/pipelines/common/get_asset_data.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""
Contains convenience functions for fetching asset price/volume data.
"""
from datetime import datetime, timedelta, timezone

from curvesim.pool_data import get_pool_assets
Expand All @@ -6,6 +9,9 @@


def get_asset_data(pool_metadata, time_sequence, data_source):
"""
Fetches price/volume data for a pool's assets.
"""
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)
Expand Down
12 changes: 10 additions & 2 deletions curvesim/pipelines/common/get_pool_data.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Contains convenience functions to get Curve sim pools and/or metadata.
"""

from datetime import datetime

from curvesim.exceptions import CurvesimTypeError
Expand All @@ -7,14 +11,17 @@


def get_pool_data(metadata_or_address, chain, env, pool_ts):
"""
Gets sim pool and (if needed) pool metadata.
"""
pool_ts = _parse_timestamp(pool_ts)
pool_metadata = _parse_metadata_or_address(metadata_or_address, chain, pool_ts)
pool = get_sim_pool(pool_metadata, env=env)

return pool, pool_metadata


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

Expand All @@ -40,7 +47,8 @@ def _parse_metadata_or_address(metadata_or_address, chain, pool_ts):
else:
_type = type(metadata_or_address).__name__
raise CurvesimTypeError(
f"'Metadata_or_address' must be 'PoolMetaDataInterface' or 'str', not {_type}."
"'Metadata_or_address' must be 'PoolMetaDataInterface' or 'str',"
f"not {_type}."
)

return pool_metadata
27 changes: 11 additions & 16 deletions curvesim/pipelines/simple/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,13 @@ def pipeline( # pylint: disable=too-many-locals
Parameters
----------
pool_address : str
'0x'-prefixed string representing the pool address.
metadata_or_address: :class:`~curvesim.pool_data.metadata.PoolMetaDataInterface` or str
Pool metadata obect or address to fetch metadata for.
chain: str
Identifier for blockchain or layer2. Supported values are:
"mainnet", "arbitrum", "optimism", "fantom", "avalanche", "matic", "xdai"
chain : str or :class:`curvesim.constants.Chain`, default="mainnet"
Chain to use if fetching metadata by address.
variable_params : dict, defaults to broad range of A/fee values
variable_params : dict
Pool parameters to vary across simulations.
keys: pool parameters, values: iterables of ints
Expand All @@ -59,18 +58,14 @@ def pipeline( # pylint: disable=too-many-locals
--------
>>> fixed_params = {"D": 1000000*10**18}
end_ts : int, optional
End timestamp in Unix time. Defaults to 30 minutes before midnight of the
current day in UTC.
days : int, default=60
Number of days to pull price/volume data for.
src : str, default="coingecko"
src : str or :class:`~curvesim.templates.DateSource`, default="coingecko"
Source for price/volume data: "coingecko" or "local".
data_dir : str, default="data"
relative path to saved price data folder
time_sequence : :class:`~curvesim.templates.DateTimeSequence`, optional
Timepoints for price/volume data and simulated trades.
pool_ts : datetime.datetime or int, optional
Optional timestamp to use when fetching metadata by address.
ncpu : int, default=os.cpu_count()
Number of cores to use.
Expand Down
23 changes: 15 additions & 8 deletions curvesim/pipelines/vol_limited_arb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,13 @@ def pipeline(
Parameters
----------
pool_metadata : :class:`~curvesim.pool_data.metadata.PoolMetaDataInterface`
Pool metadata object for the pool of interest.
metadata_or_address: :class:`~curvesim.pool_data.metadata.PoolMetaDataInterface` or str
Pool metadata obect or address to fetch metadata for.
variable_params : dict, defaults to broad range of A/fee values
chain : str or :class:`curvesim.constants.Chain`, default="mainnet"
Chain to use if fetching metadata by address.
variable_params : dict
Pool parameters to vary across simulations.
keys: pool parameters, values: iterables of ints
Expand All @@ -61,14 +64,15 @@ def pipeline(
--------
>>> fixed_params = {"D": 1000000*10**18}
days : int, default=60
Number of days to pull pool and price data for.
metrics : list of :class:`~curvesim.metrics.base.Metric` classes, optional
Metrics to compute for each simulation run.
Defaults to `curvesim.pipelines.common.DEFAULT_METRICS`
src : str, default="coingecko"
src : str or :class:`~curvesim.templates.DateSource`, default="coingecko"
Source for price/volume data: "coingecko" or "local".
data_dir : str, default="data"
relative path to saved price data folder
time_sequence : :class:`~curvesim.templates.DateTimeSequence`, optional
Timepoints for price/volume data and simulated trades.
vol_mult : dict, default computed from data
Value(s) multiplied by market volume to specify volume limits
Expand All @@ -80,6 +84,9 @@ def pipeline(
{('DAI', 'USDC'): 0.1, ('DAI', 'USDT'): 0.1, ('USDC', 'USDT'): 0.1}
pool_ts : datetime.datetime or int, optional
Optional timestamp to use when fetching metadata by address.
ncpu : int, default=os.cpu_count()
Number of cores to use.
Expand Down
2 changes: 0 additions & 2 deletions curvesim/pool_data/queries/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

def from_address(address, chain, env="prod", end_ts=None):
"""
Returns
Parameters
----------
address: str
Expand Down
20 changes: 20 additions & 0 deletions curvesim/pool_data/queries/pool_assets.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Functions to get assets for Curve pools.
"""

from typing import List, Union

from curvesim.constants import Chain
Expand All @@ -10,6 +14,22 @@
def get_pool_assets(
metadata_or_address, chain: Union[str, Chain] = Chain.MAINNET
) -> List[OnChainAssetPair]:
"""
Gets asset pairs tradeable for the specified pool.
Parameters
----------
metadata_or_address: PoolMetaDataInterface or str
Pool metadata or pool address to fetch metadata.
chain: str or Chain, default=Chain.MAINNET
Chain to use if pool address is provided to fetch metadata.
Returns
-------
List[OnChainAssetPair]
"""
if isinstance(metadata_or_address, str):
pool_metadata: PoolMetaDataInterface = get_metadata(metadata_or_address, chain)
else:
Expand Down
13 changes: 7 additions & 6 deletions curvesim/pool_data/queries/pool_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

from pandas import DataFrame, Series

from curvesim.constants import Chain
from curvesim.logging import get_logger
from curvesim.network.curve_prices import get_pool_pair_volume_sync
from curvesim.pool_data.metadata import PoolMetaDataInterface
from curvesim.utils import get_event_loop, get_pairs

from .metadata import Chain, get_metadata
from .metadata import get_metadata

logger = get_logger(__name__)

Expand All @@ -22,7 +23,7 @@ def get_pool_volume(
metadata_or_address: Union[PoolMetaDataInterface, str],
start: Union[int, datetime],
end: Union[int, datetime],
chain: Union[str, Chain] = "mainnet",
chain: Union[str, Chain] = Chain.MAINNET,
) -> DataFrame:
"""
Gets historical daily volume for each pair of coins traded in a Curve pool.
Expand All @@ -32,11 +33,11 @@ def get_pool_volume(
metadata_or_address: PoolMetaDataInterface or str
Pool metadata or pool address to fetch metadata.
days: int, defaults to 60
Number of days to pull volume data for.
start: datetime.datetime or int (POSIX timestamp)
Timestamp of the last time to pull data for.
end: int, defaults to start of current date
Posix timestamp of the last time to pull data for.
end: datetime.datetime or int (POSIX timestamp)
Timestamp of the last time to pull data for.
chain: str, default "mainnet"
Chain to use if pool address is provided to fetch metadata.
Expand Down
11 changes: 6 additions & 5 deletions curvesim/price_data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,18 @@ def get_price_data(
Parameters
----------
sim_assets: List[SimAsset]
The assets to pull data for.
time_sequence: TimeSequence
Timestamps to pull data for. If the specified source can't provide data for
the specified times, the data will be resampled.
data_source: str, DataSource, or DataSourceEnum
DataSource object to query.
Returns
-------
prices : pandas.DataFrame
Timestamped prices for each pair of coins.
volumes : pandas.DataFrame
Timestamped volumes for each pair of coins.
pandas.DataFrame
"""

Expand Down
6 changes: 6 additions & 0 deletions curvesim/price_data/data_sources/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
"""Contains data sources used by curvesim.price_data.get_price_data()"""

from enum import Enum

from .coingecko import CoinGeckoPriceVolumeSource
from .local import CsvDataSource


class DataSourceEnum(Enum):
"""
Enum of data sources used by curvesim.price_data.get_price_data()
"""

COINGECKO = CoinGeckoPriceVolumeSource
LOCAL = CsvDataSource
23 changes: 22 additions & 1 deletion curvesim/price_data/data_sources/coingecko.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Helper functions for the different data sources we pull from.
Coingecko price/volume Data Source and helper functions.
"""


Expand All @@ -22,9 +22,30 @@


class CoinGeckoPriceVolumeSource(ApiDataSource):
"""
DataSource for Coingecko price/volume data.
"""

def query(
self, sim_asset: OnChainAssetPair, time_sequence: TimeSequence[datetime]
) -> DataFrame:
"""
Fetches asset data for a particular range of times. Timestamps are matched with
a tolerance of 10 minutes, then missing prices are frontfilled and missing
volume is filled with zeros.
Parameters
----------
sim_asset: OnChainAssetPair
The asset-pair to pull data for.
time_sequence: TimeSequence
Timestamps to pull data for.
Returns
-------
pandas.DataFrame
"""

symbol_pair = (sim_asset.base.symbol, sim_asset.quote.symbol)
logger.info("Fetching CoinGecko price data for %s...", "-".join(symbol_pair))
Expand Down
8 changes: 8 additions & 0 deletions curvesim/price_data/data_sources/local.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
DataSources for local files and helper functions.
"""

from pandas import MultiIndex, read_csv

from curvesim.logging import get_logger
Expand All @@ -7,6 +11,10 @@


class CsvDataSource(FileDataSource):
"""
DataSource for local price/volume data stored in CSV files.
"""

@property
def file_extension(self):
return "csv"
Expand Down
Loading

0 comments on commit 5bd18c1

Please sign in to comment.