Start of work on downloading trades to CSV.
This commit is contained in:
parent
3dceb8e544
commit
57a1d2e0e6
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import typing
|
||||
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
|
||||
sys.path.insert(0, os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), "..")))
|
||||
import mango # nopep8
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Downloads perp and spot trades for the current wallet. Will perform incremental updates to the given filename instead of re-downloading all trades.")
|
||||
mango.ContextBuilder.add_command_line_parameters(parser)
|
||||
mango.Wallet.add_command_line_parameters(parser)
|
||||
parser.add_argument("--address", type=PublicKey, required=False,
|
||||
help="Address of the Mango account to load (defaults to current wallet's Mango account)")
|
||||
parser.add_argument("--filename", type=str, required=False,
|
||||
help="filename for loading and storing the trade history data in CSV format")
|
||||
args: argparse.Namespace = mango.parse_args(parser)
|
||||
|
||||
context = mango.ContextBuilder.from_command_line_parameters(args)
|
||||
|
||||
|
||||
accounts: typing.Sequence[mango.Account]
|
||||
group = mango.Group.load(context)
|
||||
if args.address is not None:
|
||||
account = mango.Account.load(context, args.address, group)
|
||||
accounts = [account]
|
||||
else:
|
||||
wallet = mango.Wallet.from_command_line_parameters_or_raise(args)
|
||||
accounts = mango.Account.load_all_for_owner(context, wallet.address, group)
|
||||
|
||||
for account in accounts:
|
||||
filename: str = args.filename
|
||||
if filename is None:
|
||||
filename = f"trade-history-{account.address}.csv"
|
||||
history: mango.TradeHistory = mango.TradeHistory(context, account, filename)
|
||||
history.update()
|
||||
history.save()
|
|
@ -200,6 +200,7 @@ from .tokenbank import TokenBank as TokenBank
|
|||
from .tradeexecutor import ImmediateTradeExecutor as ImmediateTradeExecutor
|
||||
from .tradeexecutor import NullTradeExecutor as NullTradeExecutor
|
||||
from .tradeexecutor import TradeExecutor as TradeExecutor
|
||||
from .tradehistory import TradeHistory as TradeHistory
|
||||
from .transactionscout import TransactionScout as TransactionScout
|
||||
from .transactionscout import fetch_all_recent_transaction_signatures as fetch_all_recent_transaction_signatures
|
||||
from .transactionscout import mango_instruction_from_response as mango_instruction_from_response
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
# # ⚠ Warning
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# [🥭 Mango Markets](https://mango.markets/) support is available at:
|
||||
# [Docs](https://docs.mango.markets/)
|
||||
# [Discord](https://discord.gg/67jySBhxrg)
|
||||
# [Twitter](https://twitter.com/mangomarkets)
|
||||
# [Github](https://github.com/blockworks-foundation)
|
||||
# [Email](mailto:hello@blockworks.foundation)
|
||||
|
||||
import logging
|
||||
import numpy
|
||||
import pandas
|
||||
import os
|
||||
import os.path
|
||||
import requests
|
||||
import time
|
||||
import typing
|
||||
|
||||
from datetime import datetime
|
||||
from solana.publickey import PublicKey
|
||||
|
||||
from .account import Account
|
||||
from .context import Context
|
||||
|
||||
|
||||
# # 🥭 TradeHistory class
|
||||
#
|
||||
# Downloads and unifies trade history data.
|
||||
#
|
||||
class TradeHistory:
|
||||
COLUMNS = ["Timestamp", "Market", "Side", "MakerOrTaker", "Value", "Price", "Quantity", "Fee",
|
||||
"SequenceNumber", "FeeTier", "MarketType", "OrderId"]
|
||||
|
||||
__perp_column_mapper = {
|
||||
"loadTimestamp": "Timestamp",
|
||||
"seqNum": "SequenceNumber",
|
||||
"price": "Price",
|
||||
"quantity": "Quantity"
|
||||
}
|
||||
|
||||
__spot_column_mapper = {
|
||||
"loadTimestamp": "Timestamp",
|
||||
"seqNum": "SequenceNumber",
|
||||
"price": "Price",
|
||||
"size": "Quantity",
|
||||
"side": "Side",
|
||||
"feeCost": "Fee",
|
||||
"feeTier": "FeeTier",
|
||||
"orderId": "OrderId"
|
||||
}
|
||||
|
||||
__dtype_mapper = {
|
||||
"SequenceNumber": "Int64",
|
||||
"Fee": "float64",
|
||||
"Price": "float64",
|
||||
"Quantity": "float64",
|
||||
"Value": "float64"
|
||||
}
|
||||
|
||||
def __init__(self, context: Context, account: Account, filename: str, seconds_pause_between_rest_calls: int = 10) -> None:
|
||||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
||||
self.__context: Context = context
|
||||
self.__account: Account = account
|
||||
self.__filename: str = filename
|
||||
self.__seconds_pause_between_rest_calls: int = seconds_pause_between_rest_calls
|
||||
self.__trades: pandas.DataFrame = pandas.DataFrame(columns=TradeHistory.COLUMNS)
|
||||
if os.path.isfile(filename):
|
||||
existing = pandas.read_csv(self.__filename,
|
||||
parse_dates=["Timestamp"],
|
||||
dtype=TradeHistory.__dtype_mapper,
|
||||
float_precision="round_trip")
|
||||
|
||||
self.__trades = self.__trades.append(existing)
|
||||
|
||||
@staticmethod
|
||||
def __market_lookup(context: Context) -> typing.Callable[[pandas.Series], str]:
|
||||
def __safe_lookup(row: pandas.Series) -> str:
|
||||
address: PublicKey = PublicKey(row["address"])
|
||||
market = context.market_lookup.find_by_address(address)
|
||||
if market is None:
|
||||
raise Exception(f"No market found with address {address}")
|
||||
return market.symbol
|
||||
return __safe_lookup
|
||||
|
||||
@staticmethod
|
||||
def __set_dtypes(data: pandas.DataFrame) -> None:
|
||||
data["Timestamp"] = pandas.to_datetime(data["Timestamp"])
|
||||
data["Value"] = pandas.to_numeric(data["Value"])
|
||||
data["Price"] = pandas.to_numeric(data["Price"])
|
||||
data["Quantity"] = pandas.to_numeric(data["Quantity"])
|
||||
data["Fee"] = pandas.to_numeric(data["Fee"])
|
||||
data["SequenceNumber"] = pandas.to_numeric(data["SequenceNumber"])
|
||||
data["FeeTier"] = pandas.to_numeric(data["FeeTier"])
|
||||
|
||||
@staticmethod
|
||||
def __download_json(url: str) -> typing.Any:
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
@staticmethod
|
||||
def __download_all_perps(context: Context, account: Account, newer_than: typing.Optional[datetime], seconds_pause_between_rest_calls: int) -> pandas.DataFrame:
|
||||
# Perp data is an array of JSON packages like:
|
||||
# {
|
||||
# "loadTimestamp": "2021-09-02T10:54:56.000Z",
|
||||
# "address": <PUBLIC-KEY-STRING>,
|
||||
# "seqNum": "2831",
|
||||
# "makerFee": "0",
|
||||
# "takerFee": "0.0004999999999988347",
|
||||
# "takerSide": "sell",
|
||||
# "maker": <PUBLIC-KEY-STRING>,
|
||||
# "makerOrderId": <BIG-INT>,
|
||||
# "taker": <PUBLIC-KEY-STRING>,
|
||||
# "takerOrderId": <BIG-INT>,
|
||||
# "price": "50131.9",
|
||||
# "quantity": "0.019"
|
||||
# },
|
||||
this_address = f"{account.address}"
|
||||
|
||||
def __side_lookup(row: pandas.Series) -> str:
|
||||
if row["MakerOrTaker"] == "taker":
|
||||
return str(row["takerSide"])
|
||||
elif row["takerSide"] == "buy":
|
||||
return "sell"
|
||||
else:
|
||||
return "buy"
|
||||
|
||||
trades: pandas.DataFrame = pandas.DataFrame(columns=TradeHistory.COLUMNS)
|
||||
page: int = 0
|
||||
complete: bool = False
|
||||
while not complete:
|
||||
page += 1
|
||||
url = f"https://event-history-api.herokuapp.com/perp_trades/{account.address}?page={page}"
|
||||
data = TradeHistory.__download_json(url)
|
||||
|
||||
if len(data["data"]) <= 1:
|
||||
complete = True
|
||||
else:
|
||||
raw_data = pandas.DataFrame(data["data"][:-1])
|
||||
raw_data["Market"] = raw_data.apply(TradeHistory.__market_lookup(context), axis=1)
|
||||
|
||||
data = raw_data.rename(mapper=TradeHistory.__perp_column_mapper, axis=1, copy=True)
|
||||
data["MarketType"] = "perp"
|
||||
data["MakerOrTaker"] = data["maker"].apply(lambda addy: "maker" if addy == this_address else "taker")
|
||||
|
||||
data["Fee"] = pandas.to_numeric(numpy.where(data["MakerOrTaker"] == "maker",
|
||||
data["makerFee"], data["takerFee"]))
|
||||
data["FeeTier"] = -1
|
||||
data["Price"] = data["Price"].astype("float64")
|
||||
data["Quantity"] = data["Quantity"].astype("float64")
|
||||
data["Value"] = (data["Price"] * data["Quantity"]) - data["Fee"]
|
||||
data["Side"] = data.apply(__side_lookup, axis=1)
|
||||
data["OrderId"] = numpy.where(data["MakerOrTaker"] == "maker",
|
||||
data["makerOrderId"], data["takerOrderId"])
|
||||
TradeHistory.__set_dtypes(data)
|
||||
trades = trades.append(data[TradeHistory.COLUMNS])
|
||||
|
||||
if (newer_than is not None) and (data.loc[data.index[-1], "Timestamp"] < newer_than):
|
||||
complete = True
|
||||
else:
|
||||
time.sleep(seconds_pause_between_rest_calls)
|
||||
|
||||
return trades
|
||||
|
||||
@staticmethod
|
||||
def __download_all_spots(context: Context, account: Account, newer_than: typing.Optional[datetime], seconds_pause_between_rest_calls: int) -> pandas.DataFrame:
|
||||
# Spot data is an array of JSON packages like:
|
||||
# {
|
||||
# "loadTimestamp": "2021-10-05T16:04:50.717Z",
|
||||
# "address": <PUBLIC-KEY-STRING>,
|
||||
# "programId": <PUBLIC-KEY-STRING>,
|
||||
# "baseCurrency": "SOL",
|
||||
# "quoteCurrency": "USDC",
|
||||
# "fill": true,
|
||||
# "out": false,
|
||||
# "bid": true,
|
||||
# "maker": true,
|
||||
# "openOrderSlot": "0",
|
||||
# "feeTier": "4",
|
||||
# "nativeQuantityReleased": "3000000000",
|
||||
# "nativeQuantityPaid": "487482712",
|
||||
# "nativeFeeOrRebate": "146288",
|
||||
# "orderId": <BIG-INT>,
|
||||
# "openOrders": <PUBLIC-KEY-STRING>,
|
||||
# "clientOrderId": <BIG-INT>,
|
||||
# "uuid": <LONG-OPAQUE-UUID-STRING>,
|
||||
# "source": "2",
|
||||
# "seqNum": "24827175",
|
||||
# "baseTokenDecimals": 9,
|
||||
# "quoteTokenDecimals": 6,
|
||||
# "side": "buy",
|
||||
# "price": 162.543,
|
||||
# "feeCost": -0.146288,
|
||||
# "size": 3
|
||||
# }
|
||||
trades: pandas.DataFrame = pandas.DataFrame(columns=TradeHistory.COLUMNS)
|
||||
for spot_open_orders_address in account.spot_open_orders:
|
||||
page: int = 0
|
||||
complete: bool = False
|
||||
while not complete:
|
||||
page += 1
|
||||
url = f"https://event-history-api.herokuapp.com/trades/open_orders/{spot_open_orders_address}?page={page}"
|
||||
data = TradeHistory.__download_json(url)
|
||||
|
||||
if len(data["data"]) <= 1:
|
||||
complete = True
|
||||
else:
|
||||
raw_data = pandas.DataFrame(data["data"])
|
||||
raw_data["Market"] = raw_data.apply(TradeHistory.__market_lookup(context), axis=1)
|
||||
|
||||
data = raw_data.rename(mapper=TradeHistory.__spot_column_mapper, axis=1, copy=True)
|
||||
data["MakerOrTaker"] = numpy.where(data["maker"], "maker", "taker")
|
||||
data["Price"] = data["Price"].astype("float64")
|
||||
data["Quantity"] = data["Quantity"].astype("float64")
|
||||
data["Value"] = (data["Price"] * data["Quantity"]) - data["Fee"]
|
||||
data["MarketType"] = "spot"
|
||||
TradeHistory.__set_dtypes(data)
|
||||
|
||||
trades = trades.append(data[TradeHistory.COLUMNS])
|
||||
|
||||
if (newer_than is not None) and (data.loc[data.index[-1], "Timestamp"] < newer_than):
|
||||
complete = True
|
||||
else:
|
||||
time.sleep(seconds_pause_between_rest_calls)
|
||||
|
||||
return trades
|
||||
|
||||
@property
|
||||
def trades(self) -> pandas.DataFrame:
|
||||
return self.__trades.copy(deep=True)
|
||||
|
||||
def update(self) -> None:
|
||||
latest_trade: typing.Optional[datetime] = self.__trades.loc[self.__trades.index[-1],
|
||||
"Timestamp"] if len(self.__trades) > 0 else None
|
||||
self.logger.info(f"Downloading spot trades up to cutoff: {latest_trade}")
|
||||
spot = TradeHistory.__download_all_spots(self.__context, self.__account,
|
||||
latest_trade, self.__seconds_pause_between_rest_calls)
|
||||
self.logger.info(f"Downloading perp trades up to cutoff: {latest_trade}")
|
||||
perp = TradeHistory.__download_all_perps(self.__context, self.__account,
|
||||
latest_trade, self.__seconds_pause_between_rest_calls)
|
||||
all_trades = pandas.concat([self.__trades, spot, perp])
|
||||
distinct_trades = all_trades.drop_duplicates()
|
||||
sorted_trades = distinct_trades.sort_values(["Timestamp", "Market", "SequenceNumber"], axis=0, ascending=True)
|
||||
self.logger.info(f"Download complete. Data contains {len(sorted_trades)} trades.")
|
||||
self.__trades = sorted_trades
|
||||
|
||||
def save(self) -> None:
|
||||
self.__trades.to_csv(self.__filename, index=False, mode="w")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"« 𝚃𝚛𝚊𝚍𝚎𝙷𝚒𝚜𝚝𝚘𝚛𝚢 for {self.__account.address} »"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self}"
|
|
@ -1,6 +1,6 @@
|
|||
[[package]]
|
||||
name = "anyio"
|
||||
version = "3.3.4"
|
||||
version = "3.4.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -12,7 +12,7 @@ sniffio = ">=1.1"
|
|||
|
||||
[package.extras]
|
||||
doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
|
||||
test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
|
||||
test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
|
||||
trio = ["trio (>=0.16)"]
|
||||
|
||||
[[package]]
|
||||
|
@ -246,16 +246,53 @@ category = "dev"
|
|||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "1.21.4"
|
||||
description = "NumPy is the fundamental package for array computing with Python."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<3.11"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "21.2"
|
||||
version = "21.3"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2,<3"
|
||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
||||
|
||||
[[package]]
|
||||
name = "pandas"
|
||||
version = "1.3.4"
|
||||
description = "Powerful data structures for data analysis, time series, and statistics"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7.1"
|
||||
|
||||
[package.dependencies]
|
||||
numpy = [
|
||||
{version = ">=1.17.3", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""},
|
||||
{version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""},
|
||||
{version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""},
|
||||
{version = ">=1.21.0", markers = "python_version >= \"3.10\""},
|
||||
]
|
||||
python-dateutil = ">=2.7.3"
|
||||
pytz = ">=2017.3"
|
||||
|
||||
[package.extras]
|
||||
test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"]
|
||||
|
||||
[[package]]
|
||||
name = "pandas-stubs"
|
||||
version = "1.2.0.39"
|
||||
description = "Type annotations for Pandas"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
|
@ -319,11 +356,14 @@ tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"]
|
|||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "2.4.7"
|
||||
version = "3.0.6"
|
||||
description = "Python parsing module"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
diagrams = ["jinja2", "railroad-diagrams"]
|
||||
|
||||
[[package]]
|
||||
name = "pyserum"
|
||||
|
@ -370,6 +410,14 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
|||
[package.dependencies]
|
||||
six = ">=1.5"
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2021.3"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.26.0"
|
||||
|
@ -436,7 +484,7 @@ python-versions = ">=3.5"
|
|||
|
||||
[[package]]
|
||||
name = "solana"
|
||||
version = "0.18.2"
|
||||
version = "0.18.3"
|
||||
description = "Solana Python API"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -462,7 +510,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
|||
|
||||
[[package]]
|
||||
name = "types-cachetools"
|
||||
version = "4.2.4"
|
||||
version = "4.2.6"
|
||||
description = "Typing stubs for cachetools"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -478,7 +526,7 @@ python-versions = "*"
|
|||
|
||||
[[package]]
|
||||
name = "types-python-dateutil"
|
||||
version = "2.8.2"
|
||||
version = "2.8.3"
|
||||
description = "Typing stubs for python-dateutil"
|
||||
category = "dev"
|
||||
optional = false
|
||||
|
@ -494,7 +542,7 @@ python-versions = "*"
|
|||
|
||||
[[package]]
|
||||
name = "types-setuptools"
|
||||
version = "57.4.2"
|
||||
version = "57.4.3"
|
||||
description = "Typing stubs for setuptools"
|
||||
category = "dev"
|
||||
optional = false
|
||||
|
@ -568,13 +616,13 @@ cffi = ["cffi (>=1.11)"]
|
|||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "d4f21f06e7f1dcc4923f8943aa5c7e10a3ee56b11490685a92c0bca07fc0eb6c"
|
||||
python-versions = ">=3.9,<3.11"
|
||||
content-hash = "a0ed504ba5754895491bc77ab78ffe6a9f16edd3c025478b5dc02f8950cf46ea"
|
||||
|
||||
[metadata.files]
|
||||
anyio = [
|
||||
{file = "anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"},
|
||||
{file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"},
|
||||
{file = "anyio-3.4.0-py3-none-any.whl", hash = "sha256:2855a9423524abcdd652d942f8932fda1735210f77a6b392eafd9ff34d3fe020"},
|
||||
{file = "anyio-3.4.0.tar.gz", hash = "sha256:24adc69309fb5779bc1e06158e143e0b6d2c56b302a3ac3de3083c705a6ed39d"},
|
||||
]
|
||||
atomicwrites = [
|
||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
||||
|
@ -727,9 +775,68 @@ mypy-extensions = [
|
|||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
numpy = [
|
||||
{file = "numpy-1.21.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8890b3360f345e8360133bc078d2dacc2843b6ee6059b568781b15b97acbe39f"},
|
||||
{file = "numpy-1.21.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:69077388c5a4b997442b843dbdc3a85b420fb693ec8e33020bb24d647c164fa5"},
|
||||
{file = "numpy-1.21.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e89717274b41ebd568cd7943fc9418eeb49b1785b66031bc8a7f6300463c5898"},
|
||||
{file = "numpy-1.21.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b78ecfa070460104934e2caf51694ccd00f37d5e5dbe76f021b1b0b0d221823"},
|
||||
{file = "numpy-1.21.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:615d4e328af7204c13ae3d4df7615a13ff60a49cb0d9106fde07f541207883ca"},
|
||||
{file = "numpy-1.21.4-cp310-cp310-win_amd64.whl", hash = "sha256:1403b4e2181fc72664737d848b60e65150f272fe5a1c1cbc16145ed43884065a"},
|
||||
{file = "numpy-1.21.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74b85a17528ca60cf98381a5e779fc0264b4a88b46025e6bcbe9621f46bb3e63"},
|
||||
{file = "numpy-1.21.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92aafa03da8658609f59f18722b88f0a73a249101169e28415b4fa148caf7e41"},
|
||||
{file = "numpy-1.21.4-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5d95668e727c75b3f5088ec7700e260f90ec83f488e4c0aaccb941148b2cd377"},
|
||||
{file = "numpy-1.21.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5162ec777ba7138906c9c274353ece5603646c6965570d82905546579573f73"},
|
||||
{file = "numpy-1.21.4-cp37-cp37m-win32.whl", hash = "sha256:81225e58ef5fce7f1d80399575576fc5febec79a8a2742e8ef86d7b03beef49f"},
|
||||
{file = "numpy-1.21.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32fe5b12061f6446adcbb32cf4060a14741f9c21e15aaee59a207b6ce6423469"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c449eb870616a7b62e097982c622d2577b3dbc800aaf8689254ec6e0197cbf1e"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2e4ed57f45f0aa38beca2a03b6532e70e548faf2debbeb3291cfc9b315d9be8f"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1247ef28387b7bb7f21caf2dbe4767f4f4175df44d30604d42ad9bd701ebb31f"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:34f3456f530ae8b44231c63082c8899fe9c983fd9b108c997c4b1c8c2d435333"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c9c23158b87ed0e70d9a50c67e5c0b3f75bcf2581a8e34668d4e9d7474d76c6"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4799be6a2d7d3c33699a6f77201836ac975b2e1b98c2a07f66a38f499cb50ce"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-win32.whl", hash = "sha256:bc988afcea53e6156546e5b2885b7efab089570783d9d82caf1cfd323b0bb3dd"},
|
||||
{file = "numpy-1.21.4-cp38-cp38-win_amd64.whl", hash = "sha256:170b2a0805c6891ca78c1d96ee72e4c3ed1ae0a992c75444b6ab20ff038ba2cd"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fde96af889262e85aa033f8ee1d3241e32bf36228318a61f1ace579df4e8170d"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c885bfc07f77e8fee3dc879152ba993732601f1f11de248d4f357f0ffea6a6d4"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e6f5f50d1eff2f2f752b3089a118aee1ea0da63d56c44f3865681009b0af162"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad010846cdffe7ec27e3f933397f8a8d6c801a48634f419e3d075db27acf5880"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c74c699b122918a6c4611285cc2cad4a3aafdb135c22a16ec483340ef97d573c"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9864424631775b0c052f3bd98bc2712d131b3e2cd95d1c0c68b91709170890b0"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-win32.whl", hash = "sha256:b1e2312f5b8843a3e4e8224b2b48fe16119617b8fc0a54df8f50098721b5bed2"},
|
||||
{file = "numpy-1.21.4-cp39-cp39-win_amd64.whl", hash = "sha256:e3c3e990274444031482a31280bf48674441e0a5b55ddb168f3a6db3e0c38ec8"},
|
||||
{file = "numpy-1.21.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a3deb31bc84f2b42584b8c4001c85d1934dbfb4030827110bc36bfd11509b7bf"},
|
||||
{file = "numpy-1.21.4.zip", hash = "sha256:e6c76a87633aa3fa16614b61ccedfae45b91df2767cf097aa9c933932a7ed1e0"},
|
||||
]
|
||||
packaging = [
|
||||
{file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"},
|
||||
{file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"},
|
||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||
]
|
||||
pandas = [
|
||||
{file = "pandas-1.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:372d72a3d8a5f2dbaf566a5fa5fa7f230842ac80f29a931fb4b071502cf86b9a"},
|
||||
{file = "pandas-1.3.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99d2350adb7b6c3f7f8f0e5dfb7d34ff8dd4bc0a53e62c445b7e43e163fce63"},
|
||||
{file = "pandas-1.3.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c2646458e1dce44df9f71a01dc65f7e8fa4307f29e5c0f2f92c97f47a5bf22f5"},
|
||||
{file = "pandas-1.3.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5298a733e5bfbb761181fd4672c36d0c627320eb999c59c65156c6a90c7e1b4f"},
|
||||
{file = "pandas-1.3.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22808afb8f96e2269dcc5b846decacb2f526dd0b47baebc63d913bf847317c8f"},
|
||||
{file = "pandas-1.3.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b528e126c13816a4374e56b7b18bfe91f7a7f6576d1aadba5dee6a87a7f479ae"},
|
||||
{file = "pandas-1.3.4-cp37-cp37m-win32.whl", hash = "sha256:fe48e4925455c964db914b958f6e7032d285848b7538a5e1b19aeb26ffaea3ec"},
|
||||
{file = "pandas-1.3.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eaca36a80acaacb8183930e2e5ad7f71539a66805d6204ea88736570b2876a7b"},
|
||||
{file = "pandas-1.3.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:42493f8ae67918bf129869abea8204df899902287a7f5eaf596c8e54e0ac7ff4"},
|
||||
{file = "pandas-1.3.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a388960f979665b447f0847626e40f99af8cf191bce9dc571d716433130cb3a7"},
|
||||
{file = "pandas-1.3.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba0aac1397e1d7b654fccf263a4798a9e84ef749866060d19e577e927d66e1b"},
|
||||
{file = "pandas-1.3.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f567e972dce3bbc3a8076e0b675273b4a9e8576ac629149cf8286ee13c259ae5"},
|
||||
{file = "pandas-1.3.4-cp38-cp38-win32.whl", hash = "sha256:c1aa4de4919358c5ef119f6377bc5964b3a7023c23e845d9db7d9016fa0c5b1c"},
|
||||
{file = "pandas-1.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:dd324f8ee05925ee85de0ea3f0d66e1362e8c80799eb4eb04927d32335a3e44a"},
|
||||
{file = "pandas-1.3.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d47750cf07dee6b55d8423471be70d627314277976ff2edd1381f02d52dbadf9"},
|
||||
{file = "pandas-1.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d1dc09c0013d8faa7474574d61b575f9af6257ab95c93dcf33a14fd8d2c1bab"},
|
||||
{file = "pandas-1.3.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10e10a2527db79af6e830c3d5842a4d60383b162885270f8cffc15abca4ba4a9"},
|
||||
{file = "pandas-1.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35c77609acd2e4d517da41bae0c11c70d31c87aae8dd1aabd2670906c6d2c143"},
|
||||
{file = "pandas-1.3.4-cp39-cp39-win32.whl", hash = "sha256:003ba92db58b71a5f8add604a17a059f3068ef4e8c0c365b088468d0d64935fd"},
|
||||
{file = "pandas-1.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:a51528192755f7429c5bcc9e80832c517340317c861318fea9cea081b57c9afd"},
|
||||
{file = "pandas-1.3.4.tar.gz", hash = "sha256:a2aa18d3f0b7d538e21932f637fbfe8518d085238b429e4790a35e1e44a96ffc"},
|
||||
]
|
||||
pandas-stubs = [
|
||||
{file = "pandas-stubs-1.2.0.39.tar.gz", hash = "sha256:a9b8d95e41a58657918e9b0b665808925e86fbc508bc59e50e99e384b28f6498"},
|
||||
{file = "pandas_stubs-1.2.0.39-py3-none-any.whl", hash = "sha256:d6cb03bc2c4681c678450c35b66d735937763e5c74cdeb8388fc706eb8d52d7d"},
|
||||
]
|
||||
pluggy = [
|
||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
||||
|
@ -772,8 +879,8 @@ pynacl = [
|
|||
{file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
|
||||
]
|
||||
pyparsing = [
|
||||
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
||||
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
|
||||
{file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
|
||||
{file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
|
||||
]
|
||||
pyserum = [
|
||||
{file = "pyserum-0.5.0a0-py2-none-any.whl", hash = "sha256:f0282afbbb4b4de04eb783502b05f0dc405392c95ab844b28828160db0779a3a"},
|
||||
|
@ -787,6 +894,10 @@ python-dateutil = [
|
|||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
|
||||
{file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
|
||||
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
|
||||
|
@ -811,32 +922,32 @@ sniffio = [
|
|||
{file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"},
|
||||
]
|
||||
solana = [
|
||||
{file = "solana-0.18.2-py3-none-any.whl", hash = "sha256:c0550915db89261ed78335ee5728341e7094444a6442529d9c9407e364185456"},
|
||||
{file = "solana-0.18.2.tar.gz", hash = "sha256:0431bd10cbe92d82a0c102e9f736483afc06ffbb6af18b81b06aec0c5e029813"},
|
||||
{file = "solana-0.18.3-py3-none-any.whl", hash = "sha256:a7778f477e4c2d880f6ce181830fcc2bc78a93e69abb645d49c77ba2a8105afe"},
|
||||
{file = "solana-0.18.3.tar.gz", hash = "sha256:59a664e7008f9a385447e6e870b241df4954dc2b889cc278de96047d6b09d181"},
|
||||
]
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
]
|
||||
types-cachetools = [
|
||||
{file = "types-cachetools-4.2.4.tar.gz", hash = "sha256:f6331ef60e788920200b92a4648728e4de0a71cd67322abe38296125c2b75f7b"},
|
||||
{file = "types_cachetools-4.2.4-py3-none-any.whl", hash = "sha256:a675d2ee0d7a3f20ba0fa5bb975e7e7774307b434bcb2ffe504c2f9c2aa83e97"},
|
||||
{file = "types-cachetools-4.2.6.tar.gz", hash = "sha256:4492f47ab2d95243449bb5474be8956afc33e87a3ae70e43b170f168410c199c"},
|
||||
{file = "types_cachetools-4.2.6-py3-none-any.whl", hash = "sha256:1b562fe589d78fc4ec702996d5c42eecf3fd4e3b5aa9ae1be95a0fc28c390ec7"},
|
||||
]
|
||||
types-certifi = [
|
||||
{file = "types-certifi-2021.10.8.0.tar.gz", hash = "sha256:33308fb722d28cad8ae19834dcc4d2593509ac80bcbabe77c6d8e9a25001c2de"},
|
||||
{file = "types_certifi-2021.10.8.0-py3-none-any.whl", hash = "sha256:ca164939fe86b5f70988eed480b788162ee81f62e72f486a7b96cb53f4112355"},
|
||||
]
|
||||
types-python-dateutil = [
|
||||
{file = "types-python-dateutil-2.8.2.tar.gz", hash = "sha256:84a1b09fae40d61c01f450ea87cd594201bbe8511a64fecbe433051b87fb582c"},
|
||||
{file = "types_python_dateutil-2.8.2-py3-none-any.whl", hash = "sha256:74d7d3a79ff07e7921472cf252b7fe4ffda5dc35570b9d3c7c4908761e9f9b87"},
|
||||
{file = "types-python-dateutil-2.8.3.tar.gz", hash = "sha256:d94e7c7ecd9f0e23b3a78087eae12c0d7aa4af9e067a8ea963ad03ed0abd1cb7"},
|
||||
{file = "types_python_dateutil-2.8.3-py3-none-any.whl", hash = "sha256:42262d0b8f8ecb06cdc5c458956685eb3b27c74f170adf541d1cc5ee4ff68bdc"},
|
||||
]
|
||||
types-requests = [
|
||||
{file = "types-requests-2.26.0.tar.gz", hash = "sha256:df5ec8c34b413a42ebb38e4f96bdeb68090b875bdfcc5138dc82989c95445883"},
|
||||
{file = "types_requests-2.26.0-py3-none-any.whl", hash = "sha256:809b5dcd3c408ac39d11d593835b6aff32420b3e7ddb79c7f3e823330f040466"},
|
||||
]
|
||||
types-setuptools = [
|
||||
{file = "types-setuptools-57.4.2.tar.gz", hash = "sha256:5499a0f429281d1a3aa9494c79b6599ab356dfe6d393825426bc749e48ea1bf8"},
|
||||
{file = "types_setuptools-57.4.2-py3-none-any.whl", hash = "sha256:9c96aab47fdcf066fef83160b2b9ddbfab3d2c8fdc89053579d0b306837bf22a"},
|
||||
{file = "types-setuptools-57.4.3.tar.gz", hash = "sha256:1bc9a00bae901ef939c1720ae040c9f1127e79e60e04588ed1506c62685385ed"},
|
||||
{file = "types_setuptools-57.4.3-py3-none-any.whl", hash = "sha256:2b969e6545859be2c26cd0eb8bf6ccf17995ba9dee98825fd7b6ab8c46224875"},
|
||||
]
|
||||
types-toml = [
|
||||
{file = "types-toml-0.10.1.tar.gz", hash = "sha256:5c1f8f8d57692397c8f902bf6b4d913a0952235db7db17d2908cc110e70610cb"},
|
||||
|
|
|
@ -15,8 +15,10 @@ packages = [
|
|||
|
||||
[tool.poetry.dependencies]
|
||||
jsons = "^1.6.0"
|
||||
numpy = "^1.21.4"
|
||||
pandas = "^1.3.4"
|
||||
python = ">=3.9,<3.11"
|
||||
pyserum = "^0.5.0a0"
|
||||
python = "^3.9"
|
||||
python-dateutil = "^2.8.2"
|
||||
requests = "^2.22.0"
|
||||
Rx = "^3.2.0"
|
||||
|
@ -36,6 +38,7 @@ types-requests = "^2.25.11"
|
|||
types-setuptools = "^57.4.2"
|
||||
types-toml = "^0.10.1"
|
||||
types-python-dateutil = "^2.8.2"
|
||||
pandas-stubs = "^1.2.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
|
Loading…
Reference in New Issue