Start of work on downloading trades to CSV.

This commit is contained in:
Geoff Taylor 2021-11-26 13:29:21 +00:00
parent 3dceb8e544
commit 57a1d2e0e6
5 changed files with 446 additions and 27 deletions

44
bin/download-trades Executable file
View File

@ -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()

View File

@ -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

260
mango/tradehistory.py Normal file
View File

@ -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}"

163
poetry.lock generated
View File

@ -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"},

View File

@ -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"]