mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
delete python
This commit is contained in:
parent
a91685920e
commit
cf42d9d0b0
48
.github/workflows/python.yml
vendored
48
.github/workflows/python.yml
vendored
|
@ -1,48 +0,0 @@
|
||||||
name: Python
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ main ]
|
|
||||||
paths:
|
|
||||||
- python
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
branches: [ main ]
|
|
||||||
paths:
|
|
||||||
- python
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: [ 3.8 ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
|
|
||||||
- name: Install poetry
|
|
||||||
run: pip install poetry==1.1.13
|
|
||||||
|
|
||||||
- name: Install package
|
|
||||||
run: |
|
|
||||||
cd python
|
|
||||||
poetry install
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: |
|
|
||||||
cd python
|
|
||||||
poetry run pytest -v -s tests
|
|
||||||
|
|
||||||
- name: Lint
|
|
||||||
run: |
|
|
||||||
cd python
|
|
||||||
poetry run flake8 .
|
|
129
python/.gitignore
vendored
129
python/.gitignore
vendored
|
@ -1,129 +0,0 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
pip-wheel-metadata/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py,cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
db.sqlite3-journal
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
.python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
|
@ -1,36 +0,0 @@
|
||||||
# pybbgo
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd <path/to/bbgo/python>
|
|
||||||
pip install .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Stream
|
|
||||||
|
|
||||||
```python
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from bbgo import Stream
|
|
||||||
from bbgo.data import Event
|
|
||||||
from bbgo.handlers import UpdateHandler
|
|
||||||
|
|
||||||
|
|
||||||
class LogBook(UpdateHandler):
|
|
||||||
|
|
||||||
def handle(self, event: Event) -> None:
|
|
||||||
logger.info(event)
|
|
||||||
|
|
||||||
|
|
||||||
host = '127.0.0.1'
|
|
||||||
port = 50051
|
|
||||||
|
|
||||||
stream = Stream(host, port)
|
|
||||||
stream.subscribe('max', 'book', 'BTCUSDT', 'full')
|
|
||||||
stream.subscribe('max', 'book', 'ETHUSDT', 'full')
|
|
||||||
stream.add_event_handler(LogBook())
|
|
||||||
stream.start()
|
|
||||||
```
|
|
|
@ -1,7 +0,0 @@
|
||||||
from . import enums
|
|
||||||
from . import handlers
|
|
||||||
from . import utils
|
|
||||||
from .services import MarketService
|
|
||||||
from .services import TradingService
|
|
||||||
from .services import UserDataService
|
|
||||||
from .stream import Stream
|
|
|
@ -1,13 +0,0 @@
|
||||||
from .balance import Balance
|
|
||||||
from .depth import Depth
|
|
||||||
from .depth import PriceVolume
|
|
||||||
from .error import ErrorMessage
|
|
||||||
from .event import Event
|
|
||||||
from .event import MarketDataEvent
|
|
||||||
from .event import UserDataEvent
|
|
||||||
from .kline import KLine
|
|
||||||
from .order import Order
|
|
||||||
from .submit_order import SubmitOrder
|
|
||||||
from .subscription import Subscription
|
|
||||||
from .ticker import Ticker
|
|
||||||
from .trade import Trade
|
|
|
@ -1,30 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..utils import parse_number
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Balance:
|
|
||||||
exchange: str
|
|
||||||
currency: str
|
|
||||||
available: Decimal
|
|
||||||
locked: Decimal
|
|
||||||
borrowed: Decimal
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.Balance) -> Balance:
|
|
||||||
return cls(
|
|
||||||
exchange=obj.exchange,
|
|
||||||
currency=obj.currency,
|
|
||||||
available=parse_number(obj.available),
|
|
||||||
locked=parse_number(obj.locked),
|
|
||||||
borrowed=parse_number(obj.borrowed),
|
|
||||||
)
|
|
||||||
|
|
||||||
def total(self) -> Decimal:
|
|
||||||
return self.available + self.locked
|
|
|
@ -1,39 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from decimal import Decimal
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..utils import parse_number
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Depth:
|
|
||||||
exchange: str
|
|
||||||
symbol: str
|
|
||||||
asks: List[PriceVolume]
|
|
||||||
bids: List[PriceVolume]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.Depth):
|
|
||||||
return cls(
|
|
||||||
exchange=obj.exchange,
|
|
||||||
symbol=obj.symbol,
|
|
||||||
asks=[PriceVolume.from_pb(ask) for ask in obj.asks],
|
|
||||||
bids=[PriceVolume.from_pb(bid) for bid in obj.bids],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class PriceVolume:
|
|
||||||
price: Decimal
|
|
||||||
volume: Decimal
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.PriceVolume):
|
|
||||||
return cls(
|
|
||||||
price=parse_number(obj.price),
|
|
||||||
volume=parse_number(obj.volume),
|
|
||||||
)
|
|
|
@ -1,18 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ErrorMessage:
|
|
||||||
code: int
|
|
||||||
message: str
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.Error) -> ErrorMessage:
|
|
||||||
return cls(
|
|
||||||
code=obj.error_code,
|
|
||||||
message=obj.error_message,
|
|
||||||
)
|
|
|
@ -1,84 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from ..utils import parse_time
|
|
||||||
from .balance import Balance
|
|
||||||
from .depth import Depth
|
|
||||||
from .error import ErrorMessage
|
|
||||||
from .kline import KLine
|
|
||||||
from .order import Order
|
|
||||||
from .ticker import Ticker
|
|
||||||
from .trade import Trade
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Event:
|
|
||||||
session: str
|
|
||||||
exchange: str
|
|
||||||
channel_type: ChannelType
|
|
||||||
event_type: EventType
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class UserDataEvent(Event):
|
|
||||||
balances: List[Balance] = None
|
|
||||||
trades: List[Trade] = None
|
|
||||||
orders: List[Order] = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.UserData) -> UserDataEvent:
|
|
||||||
return cls(
|
|
||||||
session=obj.session,
|
|
||||||
exchange=obj.exchange,
|
|
||||||
channel_type=ChannelType(obj.channel),
|
|
||||||
event_type=EventType(obj.event),
|
|
||||||
balances=[Balance.from_pb(balance) for balance in obj.balances],
|
|
||||||
trades=[Trade.from_pb(trade) for trade in obj.trades],
|
|
||||||
orders=[Order.from_pb(order) for order in obj.orders],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class MarketDataEvent(Event):
|
|
||||||
symbol: str
|
|
||||||
subscribed_at: datetime
|
|
||||||
error: ErrorMessage
|
|
||||||
depth: Depth = None
|
|
||||||
kline: KLine = None
|
|
||||||
ticker: Ticker = None
|
|
||||||
trades: List[Trade] = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.MarketData) -> MarketDataEvent:
|
|
||||||
channel_type = ChannelType(obj.channel)
|
|
||||||
|
|
||||||
event = cls(
|
|
||||||
session=obj.session,
|
|
||||||
exchange=obj.exchange,
|
|
||||||
symbol=obj.symbol,
|
|
||||||
channel_type=channel_type,
|
|
||||||
event_type=EventType(obj.event),
|
|
||||||
subscribed_at=parse_time(obj.subscribed_at),
|
|
||||||
error=ErrorMessage.from_pb(obj.error),
|
|
||||||
)
|
|
||||||
|
|
||||||
if channel_type == ChannelType.BOOK:
|
|
||||||
event.depth = Depth.from_pb(obj.depth)
|
|
||||||
|
|
||||||
if channel_type == ChannelType.KLINE:
|
|
||||||
event.kline = KLine.from_pb(obj.kline)
|
|
||||||
|
|
||||||
if channel_type == ChannelType.TICKER:
|
|
||||||
event.ticker = Ticker.from_pb(obj.ticker)
|
|
||||||
|
|
||||||
if channel_type == ChannelType.TRADE:
|
|
||||||
event.trades = [Trade.from_pb(trade) for trade in obj.trades]
|
|
||||||
|
|
||||||
return event
|
|
|
@ -1,42 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import datetime
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..utils import parse_number
|
|
||||||
from ..utils import parse_time
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class KLine:
|
|
||||||
exchange: str
|
|
||||||
symbol: str
|
|
||||||
open: Decimal
|
|
||||||
high: Decimal
|
|
||||||
low: Decimal
|
|
||||||
close: Decimal
|
|
||||||
volume: Decimal
|
|
||||||
session: str = None
|
|
||||||
start_time: datetime = None
|
|
||||||
end_time: datetime = None
|
|
||||||
quote_volume: Decimal = None
|
|
||||||
closed: bool = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.KLine) -> KLine:
|
|
||||||
return cls(
|
|
||||||
exchange=obj.exchange,
|
|
||||||
symbol=obj.symbol,
|
|
||||||
open=parse_number(obj.open),
|
|
||||||
high=parse_number(obj.high),
|
|
||||||
low=parse_number(obj.low),
|
|
||||||
close=parse_number(obj.close),
|
|
||||||
volume=parse_number(obj.volume),
|
|
||||||
quote_volume=parse_number(obj.quote_volume),
|
|
||||||
start_time=parse_time(obj.start_time),
|
|
||||||
end_time=parse_time(obj.end_time),
|
|
||||||
closed=obj.closed,
|
|
||||||
)
|
|
|
@ -1,47 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import datetime
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..enums import OrderType
|
|
||||||
from ..enums import SideType
|
|
||||||
from ..utils import parse_number
|
|
||||||
from ..utils import parse_time
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Order:
|
|
||||||
exchange: str
|
|
||||||
symbol: str
|
|
||||||
order_id: str
|
|
||||||
side: SideType
|
|
||||||
order_type: OrderType
|
|
||||||
price: Decimal
|
|
||||||
stop_price: Decimal
|
|
||||||
status: str
|
|
||||||
quantity: Decimal
|
|
||||||
executed_quantity: Decimal
|
|
||||||
client_order_id: str
|
|
||||||
group_id: int
|
|
||||||
created_at: datetime
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.Order) -> Order:
|
|
||||||
return cls(
|
|
||||||
exchange=obj.exchange,
|
|
||||||
symbol=obj.symbol,
|
|
||||||
order_id=obj.id,
|
|
||||||
side=SideType(obj.side),
|
|
||||||
order_type=OrderType(obj.order_type),
|
|
||||||
price=parse_number(obj.price),
|
|
||||||
stop_price=parse_number(obj.stop_price),
|
|
||||||
status=obj.status,
|
|
||||||
quantity=parse_number(obj.quantity),
|
|
||||||
executed_quantity=parse_number(obj.executed_quantity),
|
|
||||||
client_order_id=obj.client_order_id,
|
|
||||||
group_id=obj.group_id,
|
|
||||||
created_at=parse_time(obj.created_at),
|
|
||||||
)
|
|
|
@ -1,37 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..enums import OrderType
|
|
||||||
from ..enums import SideType
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SubmitOrder:
|
|
||||||
session: str
|
|
||||||
exchange: str
|
|
||||||
symbol: str
|
|
||||||
side: SideType
|
|
||||||
quantity: Decimal
|
|
||||||
order_type: OrderType
|
|
||||||
price: Decimal = None
|
|
||||||
stop_price: Decimal = None
|
|
||||||
client_order_id: str = None
|
|
||||||
group_id: int = None
|
|
||||||
|
|
||||||
def to_pb(self) -> bbgo_pb2.SubmitOrder:
|
|
||||||
return bbgo_pb2.SubmitOrder(
|
|
||||||
session=self.session,
|
|
||||||
exchange=self.exchange,
|
|
||||||
symbol=self.symbol,
|
|
||||||
side=self.side.value,
|
|
||||||
price=str(self.price or ""),
|
|
||||||
quantity=str(self.quantity or ""),
|
|
||||||
stop_price=str(self.stop_price or ""),
|
|
||||||
order_type=self.order_type.value,
|
|
||||||
client_order_id=self.client_order_id or "",
|
|
||||||
group_id=self.group_id or 0,
|
|
||||||
)
|
|
|
@ -1,32 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import DepthType
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Subscription:
|
|
||||||
exchange: str
|
|
||||||
channel: ChannelType
|
|
||||||
symbol: str
|
|
||||||
depth: DepthType = None
|
|
||||||
interval: str = None
|
|
||||||
|
|
||||||
def to_pb(self) -> bbgo_pb2.Subscription:
|
|
||||||
subscription_pb = bbgo_pb2.Subscription(
|
|
||||||
exchange=self.exchange,
|
|
||||||
channel=self.channel.value,
|
|
||||||
symbol=self.symbol,
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.depth is not None:
|
|
||||||
subscription_pb.depth = self.depth.value
|
|
||||||
|
|
||||||
if self.interval is not None:
|
|
||||||
subscription_pb.interval = self.interval
|
|
||||||
|
|
||||||
return subscription_pb
|
|
|
@ -1,31 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..utils import parse_number
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Ticker:
|
|
||||||
exchange: str
|
|
||||||
symbol: str
|
|
||||||
open: Decimal
|
|
||||||
high: Decimal
|
|
||||||
low: Decimal
|
|
||||||
close: Decimal
|
|
||||||
volume: Decimal
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.KLine) -> Ticker:
|
|
||||||
return cls(
|
|
||||||
exchange=obj.exchange,
|
|
||||||
symbol=obj.symbol,
|
|
||||||
open=parse_number(obj.open),
|
|
||||||
high=parse_number(obj.high),
|
|
||||||
low=parse_number(obj.low),
|
|
||||||
close=parse_number(obj.close),
|
|
||||||
volume=parse_number(obj.volume),
|
|
||||||
)
|
|
|
@ -1,42 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from datetime import datetime
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
|
|
||||||
from ..enums import SideType
|
|
||||||
from ..utils import parse_number
|
|
||||||
from ..utils import parse_time
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Trade:
|
|
||||||
session: str
|
|
||||||
exchange: str
|
|
||||||
symbol: str
|
|
||||||
trade_id: str
|
|
||||||
price: Decimal
|
|
||||||
quantity: Decimal
|
|
||||||
created_at: datetime
|
|
||||||
side: SideType
|
|
||||||
fee_currency: str
|
|
||||||
fee: Decimal
|
|
||||||
maker: bool
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_pb(cls, obj: bbgo_pb2.Trade) -> Trade:
|
|
||||||
return cls(
|
|
||||||
session=obj.session,
|
|
||||||
exchange=obj.exchange,
|
|
||||||
symbol=obj.symbol,
|
|
||||||
trade_id=obj.id,
|
|
||||||
price=parse_number(obj.price),
|
|
||||||
quantity=parse_number(obj.quantity),
|
|
||||||
created_at=parse_time(obj.created_at),
|
|
||||||
side=SideType(obj.side),
|
|
||||||
fee_currency=obj.fee_currency,
|
|
||||||
fee=parse_number(obj.fee),
|
|
||||||
maker=obj.maker,
|
|
||||||
)
|
|
|
@ -1,5 +0,0 @@
|
||||||
from .channel_type import ChannelType
|
|
||||||
from .depth_type import DepthType
|
|
||||||
from .event_type import EventType
|
|
||||||
from .order_type import OrderType
|
|
||||||
from .side_type import SideType
|
|
|
@ -1,16 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class ChannelType(Enum):
|
|
||||||
BOOK = 0
|
|
||||||
TRADE = 1
|
|
||||||
TICKER = 2
|
|
||||||
KLINE = 3
|
|
||||||
BALANCE = 4
|
|
||||||
ORDER = 5
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, s: str) -> ChannelType:
|
|
||||||
return {t.name.lower(): t for t in cls}[s.lower()]
|
|
|
@ -1,16 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
# string depth = 4; // depth is for book, valid values are full, medium, 1, 5 and 20
|
|
||||||
class DepthType(Enum):
|
|
||||||
FULL = 'full'
|
|
||||||
MEDIUM = 'medium'
|
|
||||||
DEPTH_1 = '1'
|
|
||||||
DEPTH_5 = '5'
|
|
||||||
DEPTH_20 = '20'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, s: str) -> DepthType:
|
|
||||||
return {t.name.lower(): t for t in cls}[s.lower()]
|
|
|
@ -1,17 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class EventType(Enum):
|
|
||||||
UNKNOWN = 0
|
|
||||||
SUBSCRIBED = 1
|
|
||||||
UNSUBSCRIBED = 2
|
|
||||||
SNAPSHOT = 3
|
|
||||||
UPDATE = 4
|
|
||||||
AUTHENTICATED = 5
|
|
||||||
ERROR = 99
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, s: str) -> EventType:
|
|
||||||
return {t.name.lower(): t for t in cls}[s.lower()]
|
|
|
@ -1,16 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class OrderType(Enum):
|
|
||||||
MARKET = 0
|
|
||||||
LIMIT = 1
|
|
||||||
STOP_MARKET = 2
|
|
||||||
STOP_LIMIT = 3
|
|
||||||
POST_ONLY = 4
|
|
||||||
IOC_LIMIT = 5
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, s: str) -> OrderType:
|
|
||||||
return {t.name.lower(): t for t in cls}[s.lower()]
|
|
|
@ -1,12 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class SideType(Enum):
|
|
||||||
BUY = 0
|
|
||||||
SELL = 1
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, s: str) -> SideType:
|
|
||||||
return {t.name.lower(): t for t in cls}[s.lower()]
|
|
|
@ -1,21 +0,0 @@
|
||||||
from .balance import BalanceHandler
|
|
||||||
from .balance import BalanceSnapshotHandler
|
|
||||||
from .balance import BalanceUpdateHandler
|
|
||||||
from .book import BookSnapshotHandler
|
|
||||||
from .book import BookUpdateHandler
|
|
||||||
from .error import ErrorHandler
|
|
||||||
from .handler import Handler
|
|
||||||
from .kline import KLineHandler
|
|
||||||
from .kline import KLineSnapshotHandler
|
|
||||||
from .kline import KLineUpdateHandler
|
|
||||||
from .order import OrderHandler
|
|
||||||
from .order import OrderSnapshotHandler
|
|
||||||
from .order import OrderUpdateHandler
|
|
||||||
from .snapshot import SnapshotHandler
|
|
||||||
from .ticker import TickerHandler
|
|
||||||
from .ticker import TickerSnapshotHandler
|
|
||||||
from .ticker import TickerUpdateHandler
|
|
||||||
from .trade import TradeHandler
|
|
||||||
from .trade import TradeSnapshotHandler
|
|
||||||
from .trade import TradeUpdateHandler
|
|
||||||
from .update import UpdateHandler
|
|
|
@ -1,31 +0,0 @@
|
||||||
from ..data import UserDataEvent
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class BalanceHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: UserDataEvent) -> None:
|
|
||||||
if event.channel_type != ChannelType.BALANCE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(BalanceHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class BalanceSnapshotHandler(BalanceHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: UserDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(BalanceSnapshotHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class BalanceUpdateHandler(BalanceHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: UserDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(BalanceUpdateHandler, self).__call__(event)
|
|
|
@ -1,31 +0,0 @@
|
||||||
from ..data import MarketDataEvent
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class BookHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.channel_type != ChannelType.BOOK:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(BookHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class BookSnapshotHandler(BookHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(BookSnapshotHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class BookUpdateHandler(BookHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(BookUpdateHandler, self).__call__(event)
|
|
|
@ -1,12 +0,0 @@
|
||||||
from ..data import Event
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
if event.event_type != EventType.ERROR:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(ErrorHandler, self).__call__(event)
|
|
|
@ -1,10 +0,0 @@
|
||||||
from ..data import Event
|
|
||||||
|
|
||||||
|
|
||||||
class Handler(object):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
self.handle(event)
|
|
||||||
|
|
||||||
def handle(self, event: Event) -> None:
|
|
||||||
raise NotImplementedError
|
|
|
@ -1,31 +0,0 @@
|
||||||
from ..data import MarketDataEvent
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class KLineHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.channel_type != ChannelType.KLINE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(KLineHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class KLineSnapshotHandler(KLineHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(KLineSnapshotHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class KLineUpdateHandler(KLineHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(KLineUpdateHandler, self).__call__(event)
|
|
|
@ -1,31 +0,0 @@
|
||||||
from ..data import UserDataEvent
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class OrderHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: UserDataEvent) -> None:
|
|
||||||
if event.channel_type != ChannelType.ORDER:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(OrderHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class OrderSnapshotHandler(OrderHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: UserDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(OrderSnapshotHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class OrderUpdateHandler(OrderHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: UserDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(OrderUpdateHandler, self).__call__(event)
|
|
|
@ -1,12 +0,0 @@
|
||||||
from ..data import Event
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class SnapshotHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(SnapshotHandler, self).__call__(event)
|
|
|
@ -1,31 +0,0 @@
|
||||||
from ..data import MarketDataEvent
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class TickerHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.channel_type != ChannelType.TICKER:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(TickerHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class TickerSnapshotHandler(TickerHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(TickerSnapshotHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class TickerUpdateHandler(TickerHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: MarketDataEvent) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(TickerUpdateHandler, self).__call__(event)
|
|
|
@ -1,31 +0,0 @@
|
||||||
from ..data import Event
|
|
||||||
from ..enums import ChannelType
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class TradeHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
if event.channel_type != ChannelType.TRADE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(TradeHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class TradeSnapshotHandler(TradeHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
if event.event_type != EventType.SNAPSHOT:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(TradeSnapshotHandler, self).__call__(event)
|
|
||||||
|
|
||||||
|
|
||||||
class TradeUpdateHandler(TradeHandler):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(TradeUpdateHandler, self).__call__(event)
|
|
|
@ -1,12 +0,0 @@
|
||||||
from ..data import Event
|
|
||||||
from ..enums import EventType
|
|
||||||
from .handler import Handler
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateHandler(Handler):
|
|
||||||
|
|
||||||
def __call__(self, event: Event) -> None:
|
|
||||||
if event.event_type != EventType.UPDATE:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(UpdateHandler, self).__call__(event)
|
|
|
@ -1,179 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Iterator
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
import bbgo_pb2_grpc
|
|
||||||
|
|
||||||
from .data import ErrorMessage
|
|
||||||
from .data import KLine
|
|
||||||
from .data import MarketDataEvent
|
|
||||||
from .data import Order
|
|
||||||
from .data import SubmitOrder
|
|
||||||
from .data import Subscription
|
|
||||||
from .data import UserDataEvent
|
|
||||||
from .enums import OrderType
|
|
||||||
from .enums import SideType
|
|
||||||
from .utils import get_insecure_channel
|
|
||||||
|
|
||||||
|
|
||||||
class UserDataService(object):
|
|
||||||
stub: bbgo_pb2_grpc.UserDataServiceStub
|
|
||||||
|
|
||||||
def __init__(self, host: str, port: int) -> None:
|
|
||||||
self.stub = bbgo_pb2_grpc.UserDataServiceStub(get_insecure_channel(host, port))
|
|
||||||
|
|
||||||
def subscribe(self, session: str) -> Iterator[UserDataEvent]:
|
|
||||||
request = bbgo_pb2.UserDataRequest(session)
|
|
||||||
response_iter = self.stub.Subscribe(request)
|
|
||||||
|
|
||||||
for response in response_iter:
|
|
||||||
yield UserDataEvent.from_pb(response)
|
|
||||||
|
|
||||||
|
|
||||||
class MarketService(object):
|
|
||||||
stub: bbgo_pb2_grpc.MarketDataServiceStub
|
|
||||||
|
|
||||||
def __init__(self, host: str, port: int) -> None:
|
|
||||||
self.stub = bbgo_pb2_grpc.MarketDataServiceStub(get_insecure_channel(host, port))
|
|
||||||
|
|
||||||
def subscribe(self, subscriptions: List[Subscription]) -> Iterator[MarketDataEvent]:
|
|
||||||
request = bbgo_pb2.SubscribeRequest(subscriptions=[s.to_pb() for s in subscriptions])
|
|
||||||
response_iter = self.stub.Subscribe(request)
|
|
||||||
|
|
||||||
for response in response_iter:
|
|
||||||
yield MarketDataEvent.from_pb(response)
|
|
||||||
|
|
||||||
def query_klines(self,
|
|
||||||
exchange: str,
|
|
||||||
symbol: str,
|
|
||||||
limit: int = 30,
|
|
||||||
interval: str = '1m',
|
|
||||||
start_time: int = None,
|
|
||||||
end_time: int = None) -> List[KLine]:
|
|
||||||
request = bbgo_pb2.QueryKLinesRequest(exchange=exchange,
|
|
||||||
symbol=symbol,
|
|
||||||
limit=limit,
|
|
||||||
interval=interval,
|
|
||||||
start_time=start_time,
|
|
||||||
end_time=end_time)
|
|
||||||
|
|
||||||
response = self.stub.QueryKLines(request)
|
|
||||||
|
|
||||||
klines = []
|
|
||||||
for kline in response.klines:
|
|
||||||
klines.append(KLine.from_pb(kline))
|
|
||||||
|
|
||||||
error = ErrorMessage.from_pb(response.error)
|
|
||||||
if error.code != 0:
|
|
||||||
logger.error(error.message)
|
|
||||||
|
|
||||||
return klines
|
|
||||||
|
|
||||||
|
|
||||||
class TradingService(object):
|
|
||||||
stub: bbgo_pb2_grpc.TradingServiceStub
|
|
||||||
|
|
||||||
def __init__(self, host: str, port: int) -> None:
|
|
||||||
self.stub = bbgo_pb2_grpc.TradingServiceStub(get_insecure_channel(host, port))
|
|
||||||
|
|
||||||
def submit_order(self,
|
|
||||||
session: str,
|
|
||||||
exchange: str,
|
|
||||||
symbol: str,
|
|
||||||
side: str,
|
|
||||||
quantity: float,
|
|
||||||
order_type: str,
|
|
||||||
price: float = None,
|
|
||||||
stop_price: float = None,
|
|
||||||
client_order_id: str = None,
|
|
||||||
group_id: int = None) -> Order:
|
|
||||||
submit_order = SubmitOrder(session=session,
|
|
||||||
exchange=exchange,
|
|
||||||
symbol=symbol,
|
|
||||||
side=SideType.from_str(side),
|
|
||||||
quantity=quantity,
|
|
||||||
order_type=OrderType.from_str(order_type),
|
|
||||||
price=price,
|
|
||||||
stop_price=stop_price,
|
|
||||||
client_order_id=client_order_id,
|
|
||||||
group_id=group_id)
|
|
||||||
|
|
||||||
request = bbgo_pb2.SubmitOrderRequest(session=session, submit_orders=[submit_order.to_pb()])
|
|
||||||
response = self.stub.SubmitOrder(request)
|
|
||||||
|
|
||||||
order = Order.from_pb(response.orders[0])
|
|
||||||
error = ErrorMessage.from_pb(response.error)
|
|
||||||
if error.code != 0:
|
|
||||||
logger.error(error.message)
|
|
||||||
|
|
||||||
return order
|
|
||||||
|
|
||||||
def cancel_order(self, session: str, order_id: int = None, client_order_id: int = None) -> Order:
|
|
||||||
request = bbgo_pb2.CancelOrderRequest(
|
|
||||||
session=session,
|
|
||||||
id=order_id or "",
|
|
||||||
client_order_id=client_order_id or "",
|
|
||||||
)
|
|
||||||
response = self.stub.CancelOrder(request)
|
|
||||||
|
|
||||||
order = Order.from_pb(response.order)
|
|
||||||
error = ErrorMessage.from_pb(response.error)
|
|
||||||
if error.code != 0:
|
|
||||||
logger.error(error.message)
|
|
||||||
|
|
||||||
return order
|
|
||||||
|
|
||||||
def query_order(self, order_id: int = None, client_order_id: int = None) -> bbgo_pb2.QueryOrderResponse:
|
|
||||||
request = bbgo_pb2.QueryOrderRequest(id=order_id, client_order_id=client_order_id)
|
|
||||||
response = self.stub.QueryOrder(request)
|
|
||||||
return response
|
|
||||||
|
|
||||||
def query_orders(self,
|
|
||||||
exchange: str,
|
|
||||||
symbol: str,
|
|
||||||
states: List[str] = None,
|
|
||||||
order_by: str = 'asc',
|
|
||||||
group_id: int = None,
|
|
||||||
pagination: bool = True,
|
|
||||||
page: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
offset: int = 0) -> bbgo_pb2.QueryOrdersResponse:
|
|
||||||
# set default value to ['wait', 'convert']
|
|
||||||
states = states or ['wait', 'convert']
|
|
||||||
request = bbgo_pb2.QueryOrdersRequest(exchange=exchange,
|
|
||||||
symbol=symbol,
|
|
||||||
states=states,
|
|
||||||
order_by=order_by,
|
|
||||||
group_id=group_id,
|
|
||||||
pagination=pagination,
|
|
||||||
page=page,
|
|
||||||
limit=limit,
|
|
||||||
offset=offset)
|
|
||||||
|
|
||||||
reponse = self.stub.QueryOrders(request)
|
|
||||||
return reponse
|
|
||||||
|
|
||||||
def query_trades(self,
|
|
||||||
exchange: str,
|
|
||||||
symbol: str,
|
|
||||||
timestamp: int,
|
|
||||||
order_by: str = 'asc',
|
|
||||||
pagination: bool = True,
|
|
||||||
page: int = 1,
|
|
||||||
limit: int = 100,
|
|
||||||
offset: int = 0) -> bbgo_pb2.QueryTradesResponse:
|
|
||||||
|
|
||||||
request = bbgo_pb2.QueryTradesRequest(exchange=exchange,
|
|
||||||
symbol=symbol,
|
|
||||||
timestamp=timestamp,
|
|
||||||
order_by=order_by,
|
|
||||||
pagination=pagination,
|
|
||||||
page=page,
|
|
||||||
limit=limit,
|
|
||||||
offset=offset)
|
|
||||||
response = self.stub.QueryTrades(request)
|
|
||||||
return response
|
|
|
@ -1,80 +0,0 @@
|
||||||
import asyncio
|
|
||||||
from typing import Callable
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import grpc
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
import bbgo_pb2_grpc
|
|
||||||
from bbgo.enums import ChannelType
|
|
||||||
from bbgo.enums import DepthType
|
|
||||||
|
|
||||||
from .data import Event
|
|
||||||
from .data import MarketDataEvent
|
|
||||||
from .data import Subscription
|
|
||||||
from .data import UserDataEvent
|
|
||||||
|
|
||||||
|
|
||||||
class Stream(object):
|
|
||||||
subscriptions: List[Subscription]
|
|
||||||
|
|
||||||
def __init__(self, host: str, port: int):
|
|
||||||
self.host = host
|
|
||||||
self.port = port
|
|
||||||
|
|
||||||
self.subscriptions = []
|
|
||||||
self.sessions = []
|
|
||||||
self.event_handlers = []
|
|
||||||
|
|
||||||
def subscribe(self, exchange: str, channel: str, symbol: str, depth: str = None, interval: str = None):
|
|
||||||
subscription = Subscription(exchange=exchange, channel=ChannelType.from_str(channel), symbol=symbol)
|
|
||||||
|
|
||||||
if depth is not None:
|
|
||||||
subscription.depth = DepthType(depth)
|
|
||||||
|
|
||||||
if interval is not None:
|
|
||||||
subscription.interval = interval
|
|
||||||
|
|
||||||
self.subscriptions.append(subscription)
|
|
||||||
|
|
||||||
def subscribe_user_data(self, session: str):
|
|
||||||
self.sessions.append(session)
|
|
||||||
|
|
||||||
def add_event_handler(self, event_handler: Callable) -> None:
|
|
||||||
self.event_handlers.append(event_handler)
|
|
||||||
|
|
||||||
def fire_event_handlers(self, event: Event) -> None:
|
|
||||||
for event_handler in self.event_handlers:
|
|
||||||
event_handler(event)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def address(self):
|
|
||||||
return f'{self.host}:{self.port}'
|
|
||||||
|
|
||||||
async def _subscribe_market_data(self):
|
|
||||||
async with grpc.aio.insecure_channel(self.address) as channel:
|
|
||||||
stub = bbgo_pb2_grpc.MarketDataServiceStub(channel)
|
|
||||||
|
|
||||||
request = bbgo_pb2.SubscribeRequest(subscriptions=[s.to_pb() for s in self.subscriptions])
|
|
||||||
async for response in stub.Subscribe(request):
|
|
||||||
event = MarketDataEvent.from_pb(response)
|
|
||||||
self.fire_event_handlers(event)
|
|
||||||
|
|
||||||
async def _subscribe_user_data(self, session: str):
|
|
||||||
async with grpc.aio.insecure_channel(self.address) as channel:
|
|
||||||
stub = bbgo_pb2_grpc.UserDataServiceStub(channel)
|
|
||||||
|
|
||||||
request = bbgo_pb2.UserDataRequest(session=session)
|
|
||||||
async for response in stub.Subscribe(request):
|
|
||||||
event = UserDataEvent.from_pb(response)
|
|
||||||
self.fire_event_handlers(event)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
coroutines = [self._subscribe_market_data()]
|
|
||||||
for session in self.sessions:
|
|
||||||
coroutines.append(self._subscribe_user_data(session))
|
|
||||||
|
|
||||||
group = asyncio.gather(*coroutines)
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(group)
|
|
||||||
loop.close()
|
|
|
@ -1,7 +0,0 @@
|
||||||
from .convert import parse_number
|
|
||||||
from .convert import parse_time
|
|
||||||
from .grpc_utils import get_credentials_from_env
|
|
||||||
from .grpc_utils import get_grpc_cert_file_from_env
|
|
||||||
from .grpc_utils import get_grpc_key_file_from_env
|
|
||||||
from .grpc_utils import get_insecure_channel
|
|
||||||
from .grpc_utils import get_insecure_channel_from_env
|
|
|
@ -1,20 +0,0 @@
|
||||||
from datetime import datetime
|
|
||||||
from decimal import Decimal
|
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
|
|
||||||
def parse_number(s: Union[str, float]) -> Decimal:
|
|
||||||
if s is None:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if s == "":
|
|
||||||
return 0
|
|
||||||
|
|
||||||
return Decimal(s)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_time(t: Union[str, int]) -> datetime:
|
|
||||||
if isinstance(t, str):
|
|
||||||
t = int(t)
|
|
||||||
|
|
||||||
return datetime.fromtimestamp(t / 1000)
|
|
|
@ -1,43 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
import grpc
|
|
||||||
|
|
||||||
|
|
||||||
def read_binary(f):
|
|
||||||
with open(f, 'rb') as fp:
|
|
||||||
return fp.read()
|
|
||||||
|
|
||||||
|
|
||||||
def get_grpc_cert_file_from_env():
|
|
||||||
cert_file = os.environ.get('BBGO_GRPC_CERT_FILE')
|
|
||||||
return cert_file
|
|
||||||
|
|
||||||
|
|
||||||
def get_grpc_key_file_from_env():
|
|
||||||
key_file = os.environ.get('BBGO_GRPC_KEY_FILE')
|
|
||||||
return key_file
|
|
||||||
|
|
||||||
|
|
||||||
def get_credentials_from_env():
|
|
||||||
key_file = get_grpc_key_file_from_env()
|
|
||||||
private_key = read_binary(key_file)
|
|
||||||
cert_file = get_grpc_cert_file_from_env()
|
|
||||||
certificate_chain = read_binary(cert_file)
|
|
||||||
|
|
||||||
private_key_certificate_chain_pairs = [(private_key, certificate_chain)]
|
|
||||||
server_credentials = grpc.ssl_server_credentials(private_key_certificate_chain_pairs)
|
|
||||||
return server_credentials
|
|
||||||
|
|
||||||
|
|
||||||
def get_insecure_channel(host: str, port: int) -> grpc.Channel:
|
|
||||||
address = f'{host}:{port}'
|
|
||||||
return grpc.insecure_channel(address)
|
|
||||||
|
|
||||||
|
|
||||||
def get_insecure_channel_from_env() -> grpc.Channel:
|
|
||||||
host = os.environ.get('BBGO_GRPC_HOST') or '127.0.0.1'
|
|
||||||
port = os.environ.get('BBGO_GRPC_PORT') or 50051
|
|
||||||
|
|
||||||
address = get_insecure_channel(host, port)
|
|
||||||
|
|
||||||
return grpc.insecure_channel(address)
|
|
File diff suppressed because one or more lines are too long
|
@ -1,354 +0,0 @@
|
||||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
||||||
"""Client and server classes corresponding to protobuf-defined services."""
|
|
||||||
import grpc
|
|
||||||
|
|
||||||
import bbgo_pb2 as bbgo__pb2
|
|
||||||
|
|
||||||
|
|
||||||
class MarketDataServiceStub(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
def __init__(self, channel):
|
|
||||||
"""Constructor.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
channel: A grpc.Channel.
|
|
||||||
"""
|
|
||||||
self.Subscribe = channel.unary_stream(
|
|
||||||
'/bbgo.MarketDataService/Subscribe',
|
|
||||||
request_serializer=bbgo__pb2.SubscribeRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.MarketData.FromString,
|
|
||||||
)
|
|
||||||
self.QueryKLines = channel.unary_unary(
|
|
||||||
'/bbgo.MarketDataService/QueryKLines',
|
|
||||||
request_serializer=bbgo__pb2.QueryKLinesRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.QueryKLinesResponse.FromString,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class MarketDataServiceServicer(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
def Subscribe(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
def QueryKLines(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
|
|
||||||
def add_MarketDataServiceServicer_to_server(servicer, server):
|
|
||||||
rpc_method_handlers = {
|
|
||||||
'Subscribe': grpc.unary_stream_rpc_method_handler(
|
|
||||||
servicer.Subscribe,
|
|
||||||
request_deserializer=bbgo__pb2.SubscribeRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.MarketData.SerializeToString,
|
|
||||||
),
|
|
||||||
'QueryKLines': grpc.unary_unary_rpc_method_handler(
|
|
||||||
servicer.QueryKLines,
|
|
||||||
request_deserializer=bbgo__pb2.QueryKLinesRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.QueryKLinesResponse.SerializeToString,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
generic_handler = grpc.method_handlers_generic_handler(
|
|
||||||
'bbgo.MarketDataService', rpc_method_handlers)
|
|
||||||
server.add_generic_rpc_handlers((generic_handler,))
|
|
||||||
|
|
||||||
|
|
||||||
# This class is part of an EXPERIMENTAL API.
|
|
||||||
class MarketDataService(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def Subscribe(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_stream(request, target, '/bbgo.MarketDataService/Subscribe',
|
|
||||||
bbgo__pb2.SubscribeRequest.SerializeToString,
|
|
||||||
bbgo__pb2.MarketData.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def QueryKLines(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_unary(request, target, '/bbgo.MarketDataService/QueryKLines',
|
|
||||||
bbgo__pb2.QueryKLinesRequest.SerializeToString,
|
|
||||||
bbgo__pb2.QueryKLinesResponse.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
|
|
||||||
class UserDataServiceStub(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
def __init__(self, channel):
|
|
||||||
"""Constructor.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
channel: A grpc.Channel.
|
|
||||||
"""
|
|
||||||
self.Subscribe = channel.unary_stream(
|
|
||||||
'/bbgo.UserDataService/Subscribe',
|
|
||||||
request_serializer=bbgo__pb2.UserDataRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.UserData.FromString,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UserDataServiceServicer(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
def Subscribe(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
|
|
||||||
def add_UserDataServiceServicer_to_server(servicer, server):
|
|
||||||
rpc_method_handlers = {
|
|
||||||
'Subscribe': grpc.unary_stream_rpc_method_handler(
|
|
||||||
servicer.Subscribe,
|
|
||||||
request_deserializer=bbgo__pb2.UserDataRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.UserData.SerializeToString,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
generic_handler = grpc.method_handlers_generic_handler(
|
|
||||||
'bbgo.UserDataService', rpc_method_handlers)
|
|
||||||
server.add_generic_rpc_handlers((generic_handler,))
|
|
||||||
|
|
||||||
|
|
||||||
# This class is part of an EXPERIMENTAL API.
|
|
||||||
class UserDataService(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def Subscribe(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_stream(request, target, '/bbgo.UserDataService/Subscribe',
|
|
||||||
bbgo__pb2.UserDataRequest.SerializeToString,
|
|
||||||
bbgo__pb2.UserData.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
|
|
||||||
class TradingServiceStub(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
def __init__(self, channel):
|
|
||||||
"""Constructor.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
channel: A grpc.Channel.
|
|
||||||
"""
|
|
||||||
self.SubmitOrder = channel.unary_unary(
|
|
||||||
'/bbgo.TradingService/SubmitOrder',
|
|
||||||
request_serializer=bbgo__pb2.SubmitOrderRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.SubmitOrderResponse.FromString,
|
|
||||||
)
|
|
||||||
self.CancelOrder = channel.unary_unary(
|
|
||||||
'/bbgo.TradingService/CancelOrder',
|
|
||||||
request_serializer=bbgo__pb2.CancelOrderRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.CancelOrderResponse.FromString,
|
|
||||||
)
|
|
||||||
self.QueryOrder = channel.unary_unary(
|
|
||||||
'/bbgo.TradingService/QueryOrder',
|
|
||||||
request_serializer=bbgo__pb2.QueryOrderRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.QueryOrderResponse.FromString,
|
|
||||||
)
|
|
||||||
self.QueryOrders = channel.unary_unary(
|
|
||||||
'/bbgo.TradingService/QueryOrders',
|
|
||||||
request_serializer=bbgo__pb2.QueryOrdersRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.QueryOrdersResponse.FromString,
|
|
||||||
)
|
|
||||||
self.QueryTrades = channel.unary_unary(
|
|
||||||
'/bbgo.TradingService/QueryTrades',
|
|
||||||
request_serializer=bbgo__pb2.QueryTradesRequest.SerializeToString,
|
|
||||||
response_deserializer=bbgo__pb2.QueryTradesResponse.FromString,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TradingServiceServicer(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
def SubmitOrder(self, request, context):
|
|
||||||
"""request-response
|
|
||||||
"""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
def CancelOrder(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
def QueryOrder(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
def QueryOrders(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
def QueryTrades(self, request, context):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
||||||
context.set_details('Method not implemented!')
|
|
||||||
raise NotImplementedError('Method not implemented!')
|
|
||||||
|
|
||||||
|
|
||||||
def add_TradingServiceServicer_to_server(servicer, server):
|
|
||||||
rpc_method_handlers = {
|
|
||||||
'SubmitOrder': grpc.unary_unary_rpc_method_handler(
|
|
||||||
servicer.SubmitOrder,
|
|
||||||
request_deserializer=bbgo__pb2.SubmitOrderRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.SubmitOrderResponse.SerializeToString,
|
|
||||||
),
|
|
||||||
'CancelOrder': grpc.unary_unary_rpc_method_handler(
|
|
||||||
servicer.CancelOrder,
|
|
||||||
request_deserializer=bbgo__pb2.CancelOrderRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.CancelOrderResponse.SerializeToString,
|
|
||||||
),
|
|
||||||
'QueryOrder': grpc.unary_unary_rpc_method_handler(
|
|
||||||
servicer.QueryOrder,
|
|
||||||
request_deserializer=bbgo__pb2.QueryOrderRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.QueryOrderResponse.SerializeToString,
|
|
||||||
),
|
|
||||||
'QueryOrders': grpc.unary_unary_rpc_method_handler(
|
|
||||||
servicer.QueryOrders,
|
|
||||||
request_deserializer=bbgo__pb2.QueryOrdersRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.QueryOrdersResponse.SerializeToString,
|
|
||||||
),
|
|
||||||
'QueryTrades': grpc.unary_unary_rpc_method_handler(
|
|
||||||
servicer.QueryTrades,
|
|
||||||
request_deserializer=bbgo__pb2.QueryTradesRequest.FromString,
|
|
||||||
response_serializer=bbgo__pb2.QueryTradesResponse.SerializeToString,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
generic_handler = grpc.method_handlers_generic_handler(
|
|
||||||
'bbgo.TradingService', rpc_method_handlers)
|
|
||||||
server.add_generic_rpc_handlers((generic_handler,))
|
|
||||||
|
|
||||||
|
|
||||||
# This class is part of an EXPERIMENTAL API.
|
|
||||||
class TradingService(object):
|
|
||||||
"""Missing associated documentation comment in .proto file."""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def SubmitOrder(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_unary(request, target, '/bbgo.TradingService/SubmitOrder',
|
|
||||||
bbgo__pb2.SubmitOrderRequest.SerializeToString,
|
|
||||||
bbgo__pb2.SubmitOrderResponse.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def CancelOrder(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_unary(request, target, '/bbgo.TradingService/CancelOrder',
|
|
||||||
bbgo__pb2.CancelOrderRequest.SerializeToString,
|
|
||||||
bbgo__pb2.CancelOrderResponse.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def QueryOrder(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_unary(request, target, '/bbgo.TradingService/QueryOrder',
|
|
||||||
bbgo__pb2.QueryOrderRequest.SerializeToString,
|
|
||||||
bbgo__pb2.QueryOrderResponse.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def QueryOrders(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_unary(request, target, '/bbgo.TradingService/QueryOrders',
|
|
||||||
bbgo__pb2.QueryOrdersRequest.SerializeToString,
|
|
||||||
bbgo__pb2.QueryOrdersResponse.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def QueryTrades(request,
|
|
||||||
target,
|
|
||||||
options=(),
|
|
||||||
channel_credentials=None,
|
|
||||||
call_credentials=None,
|
|
||||||
insecure=False,
|
|
||||||
compression=None,
|
|
||||||
wait_for_ready=None,
|
|
||||||
timeout=None,
|
|
||||||
metadata=None):
|
|
||||||
return grpc.experimental.unary_unary(request, target, '/bbgo.TradingService/QueryTrades',
|
|
||||||
bbgo__pb2.QueryTradesRequest.SerializeToString,
|
|
||||||
bbgo__pb2.QueryTradesResponse.FromString,
|
|
||||||
options, channel_credentials,
|
|
||||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
|
@ -1,24 +0,0 @@
|
||||||
import click
|
|
||||||
|
|
||||||
from bbgo import MarketService
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option('--host', default='127.0.0.1')
|
|
||||||
@click.option('--port', default=50051)
|
|
||||||
def main(host, port):
|
|
||||||
service = MarketService(host, port)
|
|
||||||
|
|
||||||
klines = service.query_klines(
|
|
||||||
exchange='binance',
|
|
||||||
symbol='BTCUSDT',
|
|
||||||
interval='1m',
|
|
||||||
limit=10,
|
|
||||||
)
|
|
||||||
|
|
||||||
for kline in klines:
|
|
||||||
print(kline)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,28 +0,0 @@
|
||||||
import click
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from bbgo import Stream
|
|
||||||
from bbgo.data import Event
|
|
||||||
from bbgo.handlers import UpdateHandler
|
|
||||||
|
|
||||||
|
|
||||||
class LogBook(UpdateHandler):
|
|
||||||
|
|
||||||
def handle(self, event: Event) -> None:
|
|
||||||
logger.info(event)
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option('--host', default='127.0.0.1')
|
|
||||||
@click.option('--port', default=50051)
|
|
||||||
def main(host, port):
|
|
||||||
stream = Stream(host, port)
|
|
||||||
stream.subscribe('max', 'book', 'BTCUSDT', 'full')
|
|
||||||
stream.subscribe('max', 'book', 'ETHUSDT', 'full')
|
|
||||||
stream.subscribe_user_data('max')
|
|
||||||
stream.add_event_handler(LogBook())
|
|
||||||
stream.start()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,25 +0,0 @@
|
||||||
import click
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from bbgo import MarketService
|
|
||||||
from bbgo.data import Subscription
|
|
||||||
from bbgo.enums import ChannelType
|
|
||||||
from bbgo.enums import DepthType
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.option('--host', default='127.0.0.1')
|
|
||||||
@click.option('--port', default=50051)
|
|
||||||
def main(host, port):
|
|
||||||
subscriptions = [
|
|
||||||
Subscription('binance', ChannelType.BOOK, symbol='BTCUSDT', depth=DepthType.FULL),
|
|
||||||
]
|
|
||||||
|
|
||||||
service = MarketService(host, port)
|
|
||||||
response_iter = service.subscribe(subscriptions)
|
|
||||||
for response in response_iter:
|
|
||||||
logger.info(response)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,24 +0,0 @@
|
||||||
import grpc
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
import bbgo_pb2_grpc
|
|
||||||
from bbgo.data import UserDataEvent
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
host = '127.0.0.1'
|
|
||||||
port = 50051
|
|
||||||
address = f'{host}:{port}'
|
|
||||||
channel = grpc.insecure_channel(address)
|
|
||||||
stub = bbgo_pb2_grpc.UserDataServiceStub(channel)
|
|
||||||
|
|
||||||
request = bbgo_pb2.UserDataRequest(session='max')
|
|
||||||
response_iter = stub.Subscribe(request)
|
|
||||||
for response in response_iter:
|
|
||||||
event = UserDataEvent.from_pb(response)
|
|
||||||
logger.info(event)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
406
python/poetry.lock
generated
406
python/poetry.lock
generated
|
@ -1,406 +0,0 @@
|
||||||
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atomicwrites"
|
|
||||||
version = "1.4.0"
|
|
||||||
description = "Atomic file writes."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
files = [
|
|
||||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
|
||||||
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "attrs"
|
|
||||||
version = "21.4.0"
|
|
||||||
description = "Classes Without Boilerplate"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|
||||||
files = [
|
|
||||||
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
|
|
||||||
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"]
|
|
||||||
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
|
|
||||||
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"]
|
|
||||||
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "click"
|
|
||||||
version = "8.0.4"
|
|
||||||
description = "Composable command line interface toolkit"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"},
|
|
||||||
{file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "colorama"
|
|
||||||
version = "0.4.4"
|
|
||||||
description = "Cross-platform colored terminal text."
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|
||||||
files = [
|
|
||||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
|
||||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "flake8"
|
|
||||||
version = "4.0.1"
|
|
||||||
description = "the modular source code checker: pep8 pyflakes and co"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
|
|
||||||
{file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
mccabe = ">=0.6.0,<0.7.0"
|
|
||||||
pycodestyle = ">=2.8.0,<2.9.0"
|
|
||||||
pyflakes = ">=2.4.0,<2.5.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "grpcio"
|
|
||||||
version = "1.53.0"
|
|
||||||
description = "HTTP/2-based RPC framework"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:752d2949b40e12e6ad3ed8cc552a65b54d226504f6b1fb67cab2ccee502cc06f"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8a48fd3a7222be226bb86b7b413ad248f17f3101a524018cdc4562eeae1eb2a3"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f3e837d29f0e1b9d6e7b29d569e2e9b0da61889e41879832ea15569c251c303a"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef7d30242409c3aa5839b501e877e453a2c8d3759ca8230dd5a21cda029f046"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6f90698b5d1c5dd7b3236cd1fa959d7b80e17923f918d5be020b65f1c78b173"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a96c3c7f564b263c5d7c0e49a337166c8611e89c4c919f66dba7b9a84abad137"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ee81349411648d1abc94095c68cd25e3c2812e4e0367f9a9355be1e804a5135c"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-win32.whl", hash = "sha256:fdc6191587de410a184550d4143e2b24a14df495c86ca15e59508710681690ac"},
|
|
||||||
{file = "grpcio-1.53.0-cp310-cp310-win_amd64.whl", hash = "sha256:658ffe1e39171be00490db5bd3b966f79634ac4215a1eb9a85c6cd6783bf7f6e"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:1b172e6d497191940c4b8d75b53de82dc252e15b61de2951d577ec5b43316b29"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:82434ba3a5935e47908bc861ce1ebc43c2edfc1001d235d6e31e5d3ed55815f7"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:1c734a2d4843e4e14ececf5600c3c4750990ec319e1299db7e4f0d02c25c1467"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6a2ead3de3b2d53119d473aa2f224030257ef33af1e4ddabd4afee1dea5f04c"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a34d6e905f071f9b945cabbcc776e2055de1fdb59cd13683d9aa0a8f265b5bf9"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eaf8e3b97caaf9415227a3c6ca5aa8d800fecadd526538d2bf8f11af783f1550"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:da95778d37be8e4e9afca771a83424f892296f5dfb2a100eda2571a1d8bbc0dc"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-win32.whl", hash = "sha256:e4f513d63df6336fd84b74b701f17d1bb3b64e9d78a6ed5b5e8a198bbbe8bbfa"},
|
|
||||||
{file = "grpcio-1.53.0-cp311-cp311-win_amd64.whl", hash = "sha256:ddb2511fbbb440ed9e5c9a4b9b870f2ed649b7715859fd6f2ebc585ee85c0364"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:2a912397eb8d23c177d6d64e3c8bc46b8a1c7680b090d9f13a640b104aaec77c"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:55930c56b8f5b347d6c8c609cc341949a97e176c90f5cbb01d148d778f3bbd23"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:6601d812105583948ab9c6e403a7e2dba6e387cc678c010e74f2d6d589d1d1b3"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c705e0c21acb0e8478a00e7e773ad0ecdb34bd0e4adc282d3d2f51ba3961aac7"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba074af9ca268ad7b05d3fc2b920b5fb3c083da94ab63637aaf67f4f71ecb755"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:14817de09317dd7d3fbc8272864288320739973ef0f4b56bf2c0032349da8cdf"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c7ad9fbedb93f331c2e9054e202e95cf825b885811f1bcbbdfdc301e451442db"},
|
|
||||||
{file = "grpcio-1.53.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dad5b302a4c21c604d88a5d441973f320134e6ff6a84ecef9c1139e5ffd466f6"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:fa8eaac75d3107e3f5465f2c9e3bbd13db21790c6e45b7de1756eba16b050aca"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:104a2210edd3776c38448b4f76c2f16e527adafbde171fc72a8a32976c20abc7"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:dbc1ba968639c1d23476f75c356e549e7bbf2d8d6688717dcab5290e88e8482b"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95952d3fe795b06af29bb8ec7bbf3342cdd867fc17b77cc25e6733d23fa6c519"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f144a790f14c51b8a8e591eb5af40507ffee45ea6b818c2482f0457fec2e1a2e"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0698c094688a2dd4c7c2f2c0e3e142cac439a64d1cef6904c97f6cde38ba422f"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6b6d60b0958be711bab047e9f4df5dbbc40367955f8651232bfdcdd21450b9ab"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-win32.whl", hash = "sha256:1948539ce78805d4e6256ab0e048ec793956d54787dc9d6777df71c1d19c7f81"},
|
|
||||||
{file = "grpcio-1.53.0-cp38-cp38-win_amd64.whl", hash = "sha256:df9ba1183b3f649210788cf80c239041dddcb375d6142d8bccafcfdf549522cd"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:19caa5b7282a89b799e63776ff602bb39604f7ca98db6df27e2de06756ae86c3"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:b5bd026ac928c96cc23149e6ef79183125542062eb6d1ccec34c0a37e02255e7"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:7dc8584ca6c015ad82e186e82f4c0fe977394588f66b8ecfc4ec873285314619"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2eddaae8af625e45b5c8500dcca1043264d751a6872cde2eda5022df8a336959"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5fb6f3d7824696c1c9f2ad36ddb080ba5a86f2d929ef712d511b4d9972d3d27"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8270d1dc2c98ab57e6dbf36fa187db8df4c036f04a398e5d5e25b4e01a766d70"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:976a7f24eb213e8429cab78d5e120500dfcdeb01041f1f5a77b17b9101902615"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-win32.whl", hash = "sha256:9c84a481451e7174f3a764a44150f93b041ab51045aa33d7b5b68b6979114e48"},
|
|
||||||
{file = "grpcio-1.53.0-cp39-cp39-win_amd64.whl", hash = "sha256:6beb84f83360ff29a3654f43f251ec11b809dcb5524b698d711550243debd289"},
|
|
||||||
{file = "grpcio-1.53.0.tar.gz", hash = "sha256:a4952899b4931a6ba12951f9a141ef3e74ff8a6ec9aa2dc602afa40f63595e33"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
protobuf = ["grpcio-tools (>=1.53.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "grpcio-tools"
|
|
||||||
version = "1.44.0"
|
|
||||||
description = "Protobuf code generator for gRPC"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "grpcio-tools-1.44.0.tar.gz", hash = "sha256:be37f458ea510c9a8f1caabbc2b258d12e55d189a567f5edcace90f27dc0efbf"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:9f58529e24f613019a85c258a274d441d89e0cad8cf7fca21ef3807ba5840c5d"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:1d120082236f8d2877f8a19366476b82c3562423b877b7c471a142432e31c2c4"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:65c2fe3cdc5425180f01dd303e28d4f363d38f4c2e3a7e1a87caedd5417e23bb"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5caef118deb8cdee1978fd3d8e388a9b256cd8d34e4a8895731ac0e86fa5e47c"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121c9765cee8636201cf0d4e80bc7b509813194919bccdb66e9671c4ece6dac3"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-win32.whl", hash = "sha256:90d1fac188bac838c4169eb3b67197887fa0572ea8a90519a20cddb080800549"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e16260dfe6e997330473863e01466b0992369ae2337a0249b390b4651cff424"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-linux_armv7l.whl", hash = "sha256:608414cc1093e1e9e5980c97a6ee78e51dffff359e7a3f123d1fb9d95b8763a5"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:395609c06f69fbc79518b30a01931127088a3f9ef2cc2a35269c5f187eefd38c"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f7ce16766b24b88ec0e4355f5dd66c2eee6af210e889fcb7961c9c4634c687de"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3c9abc4a40c62f46d5e43e49c7afc567dedf12eeef95933ac9ea2986baa2420b"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-manylinux_2_17_aarch64.whl", hash = "sha256:b73fd87a44ba1b91866b0254193c37cdb001737759b77b637cebe0c816d38342"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b211f12e4cbc0fde8e0f982b0f581cce38874666a02ebfed93c23dcaeb8a4e0"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b421dc9b27bcaff4c73644cd3801e4893b11ba3eb39729246fd3de98d9f685b"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-win32.whl", hash = "sha256:33d93027840a873c7b59402fe6db8263b88c56e2f84aa0b6281c05cc8bd314a1"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp36-cp36m-win_amd64.whl", hash = "sha256:71fb6e7e66b918803b1bebd0231560981ab86c2546a3318a45822ce94de5e83d"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:614c427ff235d92f103e9189f0230197c8f2f817d0dd9fd078f5d2ea4d920d02"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:c13e0cb486cfa15320ddcd70452a4d736e6ce319c03d6b3c0c2513ec8d2748fb"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:5ade6b13dc4e148f400c8f55a6ef0b14216a3371d7a9e559571d5981b6cec36b"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6138d2c7eec7ed57585bc58e2dbcb65635a2d574ac632abd29949d3e68936bab"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:3d6c8548b199591757dbfe89ed14e23782d6079d6d201c6c314c72f4086883aa"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b41c419829f01734d65958ba9b01b759061d8f7e0698f9612ba6b8837269f7a9"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9f0c5b4567631fec993826e694e83d86a972b3e2e9b05cb0c56839b0316d26c"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-win32.whl", hash = "sha256:3f0e1d1f3f5a6f0c9f8b5441819dbec831ce7e9ffe04768e4b0d965a95fbbe5e"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f87fc86d0b4181b6b4da6ec6a29511dca000e6b5694fdd6bbf87d125128bc41"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:cb8baa1d4cea35ca662c24098377bdd9514c56f227da0e38b43cd9b8223bfcc6"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:ea36a294f7c70fd2f2bfb5dcf08602006304aa65b055ebd4f7c709e2a89deba7"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1972caf8f695b91edc6444134445798692fe71276f0cde7604d55e65179adf93"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:674fb8d9c0e2d75166c4385753962485b757897223fc92a19c9e513ab80b96f7"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:37045ba850d423cdacede77b266b127025818a5a36d80f1fd7a5a1614a6a0de5"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cdf72947c6b0b03aa6dac06117a095947d02d43a5c6343051f4ce161fd0abcb"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69bfa6fc1515c202fe428ba9f99e2b2f947b01bafc15d868798235b2e2d36baa"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-win32.whl", hash = "sha256:2c516124356476d9afa126acce10ce568733120afbd9ae17ee01d44b9da20a67"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6441c24176705c5ab056e65a8b330e107107c5a492ba094d1b862a136d15d"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:398eda759194d355eb09f7beabae6e4fb45b3877cf7efe505b49095fa4889cef"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:a169bfd7a1fe8cc11472eeeeab3088b3c5d56caac12b2192a920b73adcbc974c"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:a58aaaec0d846d142edd8e794ebb80aa429abfd581f4493a60a603aac0c50ac8"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c3253bee8b68fe422754faf0f286aa068861c926a7b11e4daeb44b9af767c7f1"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:3c0be60721ae1ba09c4f29572a145f412e561b9201e19428758893709827f472"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e44b9572c2226b85976e0d6054e22d7c59ebd6c9425ee71e5bc8910434aee3e1"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c04ec47905c4f6d6dad34d29f6ace652cc1ddc986f55aaa5559b72104c3f5cf"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-win32.whl", hash = "sha256:fb8c7b9d24e2c4dc77e7800e83b68081729ac6094b781b2afdabf08af18c3b28"},
|
|
||||||
{file = "grpcio_tools-1.44.0-cp39-cp39-win_amd64.whl", hash = "sha256:4eb93619c8cb3773fb899504e3e30a0dc79d3904fd7a84091d15552178e1e920"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
grpcio = ">=1.44.0"
|
|
||||||
protobuf = ">=3.5.0.post1,<4.0dev"
|
|
||||||
setuptools = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "iniconfig"
|
|
||||||
version = "1.1.1"
|
|
||||||
description = "iniconfig: brain-dead simple config-ini parsing"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
|
||||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "loguru"
|
|
||||||
version = "0.6.0"
|
|
||||||
description = "Python logging made (stupidly) simple"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"},
|
|
||||||
{file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
|
|
||||||
win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mccabe"
|
|
||||||
version = "0.6.1"
|
|
||||||
description = "McCabe checker, plugin for flake8"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
|
||||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "packaging"
|
|
||||||
version = "21.3"
|
|
||||||
description = "Core utilities for Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
|
||||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pluggy"
|
|
||||||
version = "1.0.0"
|
|
||||||
description = "plugin and hook calling mechanisms for python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
|
||||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["pre-commit", "tox"]
|
|
||||||
testing = ["pytest", "pytest-benchmark"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "protobuf"
|
|
||||||
version = "3.19.4"
|
|
||||||
description = "Protocol Buffers"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "protobuf-3.19.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f51d5a9f137f7a2cec2d326a74b6e3fc79d635d69ffe1b036d39fc7d75430d37"},
|
|
||||||
{file = "protobuf-3.19.4-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:09297b7972da685ce269ec52af761743714996b4381c085205914c41fcab59fb"},
|
|
||||||
{file = "protobuf-3.19.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:072fbc78d705d3edc7ccac58a62c4c8e0cec856987da7df8aca86e647be4e35c"},
|
|
||||||
{file = "protobuf-3.19.4-cp310-cp310-win32.whl", hash = "sha256:7bb03bc2873a2842e5ebb4801f5c7ff1bfbdf426f85d0172f7644fcda0671ae0"},
|
|
||||||
{file = "protobuf-3.19.4-cp310-cp310-win_amd64.whl", hash = "sha256:f358aa33e03b7a84e0d91270a4d4d8f5df6921abe99a377828839e8ed0c04e07"},
|
|
||||||
{file = "protobuf-3.19.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1c91ef4110fdd2c590effb5dca8fdbdcb3bf563eece99287019c4204f53d81a4"},
|
|
||||||
{file = "protobuf-3.19.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c438268eebb8cf039552897d78f402d734a404f1360592fef55297285f7f953f"},
|
|
||||||
{file = "protobuf-3.19.4-cp36-cp36m-win32.whl", hash = "sha256:835a9c949dc193953c319603b2961c5c8f4327957fe23d914ca80d982665e8ee"},
|
|
||||||
{file = "protobuf-3.19.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4276cdec4447bd5015453e41bdc0c0c1234eda08420b7c9a18b8d647add51e4b"},
|
|
||||||
{file = "protobuf-3.19.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6cbc312be5e71869d9d5ea25147cdf652a6781cf4d906497ca7690b7b9b5df13"},
|
|
||||||
{file = "protobuf-3.19.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:54a1473077f3b616779ce31f477351a45b4fef8c9fd7892d6d87e287a38df368"},
|
|
||||||
{file = "protobuf-3.19.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:435bb78b37fc386f9275a7035fe4fb1364484e38980d0dd91bc834a02c5ec909"},
|
|
||||||
{file = "protobuf-3.19.4-cp37-cp37m-win32.whl", hash = "sha256:16f519de1313f1b7139ad70772e7db515b1420d208cb16c6d7858ea989fc64a9"},
|
|
||||||
{file = "protobuf-3.19.4-cp37-cp37m-win_amd64.whl", hash = "sha256:cdc076c03381f5c1d9bb1abdcc5503d9ca8b53cf0a9d31a9f6754ec9e6c8af0f"},
|
|
||||||
{file = "protobuf-3.19.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:69da7d39e39942bd52848438462674c463e23963a1fdaa84d88df7fbd7e749b2"},
|
|
||||||
{file = "protobuf-3.19.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:48ed3877fa43e22bcacc852ca76d4775741f9709dd9575881a373bd3e85e54b2"},
|
|
||||||
{file = "protobuf-3.19.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd95d1dfb9c4f4563e6093a9aa19d9c186bf98fa54da5252531cc0d3a07977e7"},
|
|
||||||
{file = "protobuf-3.19.4-cp38-cp38-win32.whl", hash = "sha256:b38057450a0c566cbd04890a40edf916db890f2818e8682221611d78dc32ae26"},
|
|
||||||
{file = "protobuf-3.19.4-cp38-cp38-win_amd64.whl", hash = "sha256:7ca7da9c339ca8890d66958f5462beabd611eca6c958691a8fe6eccbd1eb0c6e"},
|
|
||||||
{file = "protobuf-3.19.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:36cecbabbda242915529b8ff364f2263cd4de7c46bbe361418b5ed859677ba58"},
|
|
||||||
{file = "protobuf-3.19.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:c1068287025f8ea025103e37d62ffd63fec8e9e636246b89c341aeda8a67c934"},
|
|
||||||
{file = "protobuf-3.19.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96bd766831596d6014ca88d86dc8fe0fb2e428c0b02432fd9db3943202bf8c5e"},
|
|
||||||
{file = "protobuf-3.19.4-cp39-cp39-win32.whl", hash = "sha256:84123274d982b9e248a143dadd1b9815049f4477dc783bf84efe6250eb4b836a"},
|
|
||||||
{file = "protobuf-3.19.4-cp39-cp39-win_amd64.whl", hash = "sha256:3112b58aac3bac9c8be2b60a9daf6b558ca3f7681c130dcdd788ade7c9ffbdca"},
|
|
||||||
{file = "protobuf-3.19.4-py2.py3-none-any.whl", hash = "sha256:8961c3a78ebfcd000920c9060a262f082f29838682b1f7201889300c1fbe0616"},
|
|
||||||
{file = "protobuf-3.19.4.tar.gz", hash = "sha256:9df0c10adf3e83015ced42a9a7bd64e13d06c4cf45c340d2c63020ea04499d0a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "py"
|
|
||||||
version = "1.11.0"
|
|
||||||
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|
||||||
files = [
|
|
||||||
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
|
||||||
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pycodestyle"
|
|
||||||
version = "2.8.0"
|
|
||||||
description = "Python style guide checker"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|
||||||
files = [
|
|
||||||
{file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
|
|
||||||
{file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyflakes"
|
|
||||||
version = "2.4.0"
|
|
||||||
description = "passive checker of Python programs"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
files = [
|
|
||||||
{file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
|
|
||||||
{file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyparsing"
|
|
||||||
version = "3.0.7"
|
|
||||||
description = "Python parsing module"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
|
|
||||||
{file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
diagrams = ["jinja2", "railroad-diagrams"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pytest"
|
|
||||||
version = "7.0.1"
|
|
||||||
description = "pytest: simple powerful testing with Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "pytest-7.0.1-py3-none-any.whl", hash = "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db"},
|
|
||||||
{file = "pytest-7.0.1.tar.gz", hash = "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
|
||||||
attrs = ">=19.2.0"
|
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|
||||||
iniconfig = "*"
|
|
||||||
packaging = "*"
|
|
||||||
pluggy = ">=0.12,<2.0"
|
|
||||||
py = ">=1.8.2"
|
|
||||||
tomli = ">=1.0.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "setuptools"
|
|
||||||
version = "68.0.0"
|
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
|
|
||||||
{file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
|
||||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tomli"
|
|
||||||
version = "2.0.1"
|
|
||||||
description = "A lil' TOML parser"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
|
||||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "win32-setctime"
|
|
||||||
version = "1.1.0"
|
|
||||||
description = "A small Python utility to set file creation time on Windows"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
files = [
|
|
||||||
{file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
|
|
||||||
{file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
lock-version = "2.0"
|
|
||||||
python-versions = "^3.8"
|
|
||||||
content-hash = "bfda359d4e023f07cd8df05859450215e9f560f50b4a77a8aa8436ac42a74fe3"
|
|
|
@ -1,25 +0,0 @@
|
||||||
[tool.poetry]
|
|
||||||
name = "bbgo"
|
|
||||||
version = "0.1.9"
|
|
||||||
description = ""
|
|
||||||
authors = ["なるみ <weaper@gmail.com>"]
|
|
||||||
packages = [
|
|
||||||
{ include = "bbgo" },
|
|
||||||
{ include = "bbgo_pb2.py" },
|
|
||||||
{ include = "bbgo_pb2_grpc.py" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
|
||||||
python = "^3.8"
|
|
||||||
click = "^8.0.4"
|
|
||||||
loguru = "^0.6.0"
|
|
||||||
grpcio = "^1.44.0"
|
|
||||||
grpcio-tools = "^1.44.0"
|
|
||||||
flake8 = "^4.0.1"
|
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
|
||||||
pytest = "^7.0.1"
|
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["poetry-core>=1.0.0"]
|
|
||||||
build-backend = "poetry.core.masonry.api"
|
|
|
@ -1,14 +0,0 @@
|
||||||
[flake8]
|
|
||||||
max-line-length = 120
|
|
||||||
per-file-ignores = __init__.py: F401
|
|
||||||
# ignore =
|
|
||||||
exclude = bbgo_pb2.py, bbgo_pb2_grpc.py
|
|
||||||
|
|
||||||
[yapf]
|
|
||||||
based_on_style = google
|
|
||||||
column_limit = 120
|
|
||||||
|
|
||||||
[isort]
|
|
||||||
not_skip = __init__.py
|
|
||||||
line_length = 120
|
|
||||||
force_single_line = True
|
|
|
@ -1,82 +0,0 @@
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import bbgo_pb2
|
|
||||||
from bbgo.data import Balance
|
|
||||||
from bbgo.data import ErrorMessage
|
|
||||||
from bbgo.data import KLine
|
|
||||||
from bbgo.utils import parse_time
|
|
||||||
|
|
||||||
|
|
||||||
def test_balance_from_pb():
|
|
||||||
exchange = 'max'
|
|
||||||
currency = 'BTCUSDT'
|
|
||||||
available = '3.1415926'
|
|
||||||
locked = '2.7182818'
|
|
||||||
borrowed = '0.1234567'
|
|
||||||
|
|
||||||
balance_pb = bbgo_pb2.Balance(
|
|
||||||
exchange=exchange,
|
|
||||||
currency=currency,
|
|
||||||
available=available,
|
|
||||||
locked=locked,
|
|
||||||
borrowed=borrowed,
|
|
||||||
)
|
|
||||||
|
|
||||||
balance = Balance.from_pb(balance_pb)
|
|
||||||
|
|
||||||
assert balance.exchange == exchange
|
|
||||||
assert balance.currency == currency
|
|
||||||
assert balance.available == Decimal(available)
|
|
||||||
assert balance.locked == Decimal(locked)
|
|
||||||
assert balance.borrowed == Decimal(borrowed)
|
|
||||||
|
|
||||||
|
|
||||||
def test_kline_from_pb():
|
|
||||||
exchange = "binance"
|
|
||||||
symbol = "BTCUSDT"
|
|
||||||
open = "39919.31"
|
|
||||||
high = "39919.32"
|
|
||||||
low = "39919.31"
|
|
||||||
close = "39919.31"
|
|
||||||
volume = "0.27697"
|
|
||||||
quote_volume = "11056.4530226"
|
|
||||||
start_time = 1649833260000
|
|
||||||
end_time = 1649833319999
|
|
||||||
closed = True
|
|
||||||
|
|
||||||
kline_pb = bbgo_pb2.KLine(exchange=exchange,
|
|
||||||
symbol=symbol,
|
|
||||||
open=open,
|
|
||||||
high=high,
|
|
||||||
low=low,
|
|
||||||
close=close,
|
|
||||||
volume=volume,
|
|
||||||
quote_volume=quote_volume,
|
|
||||||
start_time=start_time,
|
|
||||||
end_time=end_time,
|
|
||||||
closed=closed)
|
|
||||||
|
|
||||||
kline = KLine.from_pb(kline_pb)
|
|
||||||
|
|
||||||
assert kline.exchange == exchange
|
|
||||||
assert kline.symbol == symbol
|
|
||||||
assert kline.open == Decimal(open)
|
|
||||||
assert kline.high == Decimal(high)
|
|
||||||
assert kline.low == Decimal(low)
|
|
||||||
assert kline.close == Decimal(close)
|
|
||||||
assert kline.volume == Decimal(volume)
|
|
||||||
assert kline.quote_volume == Decimal(quote_volume)
|
|
||||||
assert kline.start_time == parse_time(start_time)
|
|
||||||
assert kline.end_time == parse_time(end_time)
|
|
||||||
assert closed == closed
|
|
||||||
|
|
||||||
|
|
||||||
def test_order_from_pb():
|
|
||||||
error_code = 123
|
|
||||||
error_message = "error message 123"
|
|
||||||
|
|
||||||
error_pb = bbgo_pb2.Error(error_code=error_code, error_message=error_message)
|
|
||||||
error = ErrorMessage.from_pb(error_pb)
|
|
||||||
|
|
||||||
assert error.code == error_code
|
|
||||||
assert error.message == error_message
|
|
|
@ -1,15 +0,0 @@
|
||||||
from bbgo.enums import ChannelType
|
|
||||||
|
|
||||||
|
|
||||||
def test_channel_type_from_str():
|
|
||||||
m = {
|
|
||||||
'book': ChannelType.BOOK,
|
|
||||||
'trade': ChannelType.TRADE,
|
|
||||||
'ticker': ChannelType.TICKER,
|
|
||||||
'kline': ChannelType.KLINE,
|
|
||||||
'balance': ChannelType.BALANCE,
|
|
||||||
'order': ChannelType.ORDER,
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v in m.items():
|
|
||||||
assert ChannelType.from_str(k) == v
|
|
|
@ -1,19 +0,0 @@
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
from bbgo.utils import parse_number
|
|
||||||
from bbgo.utils import parse_time
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_time():
|
|
||||||
t = 1650610080000
|
|
||||||
d = parse_time(t)
|
|
||||||
|
|
||||||
assert d.timestamp() == t / 1000
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_float():
|
|
||||||
assert parse_number(None) == 0
|
|
||||||
assert parse_number("") == 0
|
|
||||||
|
|
||||||
s = "3.14159265358979"
|
|
||||||
assert parse_number(s) == Decimal(s)
|
|
Loading…
Reference in New Issue
Block a user