Venues
Moved from api to venues all the msgspecs structs, also added critical imports in api, feed and __init__ mods.pull/19/head
parent
3b90f9c5e8
commit
3fb71e9b93
|
@ -34,6 +34,9 @@ from .feed import (
|
||||||
# open_trade_dialog,
|
# open_trade_dialog,
|
||||||
# norm_trade_records,
|
# norm_trade_records,
|
||||||
# )
|
# )
|
||||||
|
from .venues import (
|
||||||
|
OptionPair,
|
||||||
|
)
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
@ -43,6 +46,7 @@ __all__ = [
|
||||||
'open_history_client',
|
'open_history_client',
|
||||||
'open_symbol_search',
|
'open_symbol_search',
|
||||||
'stream_quotes',
|
'stream_quotes',
|
||||||
|
'OptionPair',
|
||||||
# 'norm_trade_records',
|
# 'norm_trade_records',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,14 @@ Deribit backend.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from collections import ChainMap
|
||||||
from contextlib import (
|
from contextlib import (
|
||||||
asynccontextmanager as acm,
|
asynccontextmanager as acm,
|
||||||
)
|
)
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from decimal import (
|
||||||
|
Decimal,
|
||||||
|
)
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import time
|
import time
|
||||||
from typing import (
|
from typing import (
|
||||||
|
@ -31,7 +35,7 @@ from typing import (
|
||||||
Callable,
|
Callable,
|
||||||
)
|
)
|
||||||
|
|
||||||
import pendulum
|
from pendulum import now
|
||||||
import trio
|
import trio
|
||||||
from trio_typing import TaskStatus
|
from trio_typing import TaskStatus
|
||||||
from rapidfuzz import process as fuzzy
|
from rapidfuzz import process as fuzzy
|
||||||
|
@ -51,7 +55,25 @@ from cryptofeed.defines import (
|
||||||
OPTION, CALL, PUT
|
OPTION, CALL, PUT
|
||||||
)
|
)
|
||||||
from cryptofeed.symbols import Symbol
|
from cryptofeed.symbols import Symbol
|
||||||
|
# types for managing the cb callbacks.
|
||||||
|
# from cryptofeed.types import L1Book
|
||||||
|
from .venues import (
|
||||||
|
_ws_url,
|
||||||
|
MarketType,
|
||||||
|
PAIRTYPES,
|
||||||
|
Pair,
|
||||||
|
OptionPair,
|
||||||
|
JSONRPCResult,
|
||||||
|
JSONRPCChannel,
|
||||||
|
KLinesResult,
|
||||||
|
Trade,
|
||||||
|
LastTradesResult,
|
||||||
|
)
|
||||||
|
from piker.accounting import (
|
||||||
|
Asset,
|
||||||
|
digits_to_dec,
|
||||||
|
MktPair,
|
||||||
|
)
|
||||||
from piker.data import (
|
from piker.data import (
|
||||||
def_iohlcv_fields,
|
def_iohlcv_fields,
|
||||||
match_from_pairs,
|
match_from_pairs,
|
||||||
|
@ -74,57 +96,6 @@ _spawn_kwargs = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_url = 'https://www.deribit.com'
|
|
||||||
_ws_url = 'wss://www.deribit.com/ws/api/v2'
|
|
||||||
_testnet_ws_url = 'wss://test.deribit.com/ws/api/v2'
|
|
||||||
|
|
||||||
|
|
||||||
class JSONRPCResult(Struct):
|
|
||||||
jsonrpc: str = '2.0'
|
|
||||||
id: int
|
|
||||||
result: Optional[list[dict]] = None
|
|
||||||
error: Optional[dict] = None
|
|
||||||
usIn: int
|
|
||||||
usOut: int
|
|
||||||
usDiff: int
|
|
||||||
testnet: bool
|
|
||||||
|
|
||||||
class JSONRPCChannel(Struct):
|
|
||||||
jsonrpc: str = '2.0'
|
|
||||||
method: str
|
|
||||||
params: dict
|
|
||||||
|
|
||||||
|
|
||||||
class KLinesResult(Struct):
|
|
||||||
close: list[float]
|
|
||||||
cost: list[float]
|
|
||||||
high: list[float]
|
|
||||||
low: list[float]
|
|
||||||
open: list[float]
|
|
||||||
status: str
|
|
||||||
ticks: list[int]
|
|
||||||
volume: list[float]
|
|
||||||
|
|
||||||
class Trade(Struct):
|
|
||||||
trade_seq: int
|
|
||||||
trade_id: str
|
|
||||||
timestamp: int
|
|
||||||
tick_direction: int
|
|
||||||
price: float
|
|
||||||
mark_price: float
|
|
||||||
iv: float
|
|
||||||
instrument_name: str
|
|
||||||
index_price: float
|
|
||||||
direction: str
|
|
||||||
combo_trade_id: Optional[int] = 0,
|
|
||||||
combo_id: Optional[str] = '',
|
|
||||||
amount: float
|
|
||||||
|
|
||||||
class LastTradesResult(Struct):
|
|
||||||
trades: list[Trade]
|
|
||||||
has_more: bool
|
|
||||||
|
|
||||||
|
|
||||||
# convert datetime obj timestamp to unixtime in milliseconds
|
# convert datetime obj timestamp to unixtime in milliseconds
|
||||||
def deribit_timestamp(when):
|
def deribit_timestamp(when):
|
||||||
return int((when.timestamp() * 1000) + (when.microsecond / 1000))
|
return int((when.timestamp() * 1000) + (when.microsecond / 1000))
|
||||||
|
|
|
@ -21,11 +21,15 @@ Deribit backend.
|
||||||
from contextlib import asynccontextmanager as acm
|
from contextlib import asynccontextmanager as acm
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Optional, Callable
|
from typing import Any, Optional, Callable
|
||||||
|
from pprint import pformat
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import trio
|
import trio
|
||||||
from trio_typing import TaskStatus
|
from trio_typing import TaskStatus
|
||||||
import pendulum
|
from pendulum import (
|
||||||
|
from_timestamp,
|
||||||
|
now,
|
||||||
|
)
|
||||||
from rapidfuzz import process as fuzzy
|
from rapidfuzz import process as fuzzy
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import tractor
|
import tractor
|
||||||
|
@ -50,6 +54,10 @@ from .api import (
|
||||||
str_to_cb_sym, piker_sym_to_cb_sym, cb_sym_to_deribit_inst,
|
str_to_cb_sym, piker_sym_to_cb_sym, cb_sym_to_deribit_inst,
|
||||||
maybe_open_price_feed
|
maybe_open_price_feed
|
||||||
)
|
)
|
||||||
|
from .venues import (
|
||||||
|
Pair,
|
||||||
|
OptionPair,
|
||||||
|
)
|
||||||
|
|
||||||
_spawn_kwargs = {
|
_spawn_kwargs = {
|
||||||
'infect_asyncio': True,
|
'infect_asyncio': True,
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
# piker: trading gear for hackers
|
||||||
|
# Copyright (C) Tyler Goodlet (in stewardship for pikers)
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Per market data-type definitions and schemas types.
|
||||||
|
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
import pendulum
|
||||||
|
from typing import (
|
||||||
|
Literal,
|
||||||
|
)
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from msgspec import field
|
||||||
|
|
||||||
|
from piker.types import Struct
|
||||||
|
|
||||||
|
|
||||||
|
# API endpoint paths by venue / sub-API
|
||||||
|
_domain: str = 'deribit.com'
|
||||||
|
_url = f'https://www.{_domain}'
|
||||||
|
|
||||||
|
# WEBsocketz
|
||||||
|
_ws_url: str = f'wss://www.{_domain}/ws/api/v2'
|
||||||
|
|
||||||
|
# test nets
|
||||||
|
_testnet_ws_url: str = f'wss://test.{_domain}/ws/api/v2'
|
||||||
|
|
||||||
|
MarketType = Literal[
|
||||||
|
'option'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_api_eps(venue: MarketType) -> tuple[str, str]:
|
||||||
|
'''
|
||||||
|
Return API ep root paths per venue.
|
||||||
|
|
||||||
|
'''
|
||||||
|
return {
|
||||||
|
'option': (
|
||||||
|
_ws_url,
|
||||||
|
),
|
||||||
|
}[venue]
|
||||||
|
|
||||||
|
|
||||||
|
class Pair(Struct, frozen=True, kw_only=True):
|
||||||
|
|
||||||
|
symbol: str
|
||||||
|
|
||||||
|
# src
|
||||||
|
quote_currency: str # 'BTC'
|
||||||
|
|
||||||
|
# dst
|
||||||
|
base_currency: str # "BTC",
|
||||||
|
|
||||||
|
tick_size: float # 0.0001 # [{'above_price': 0.005, 'tick_size': 0.0005}]
|
||||||
|
tick_size_steps: list[dict[str, float]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def price_tick(self) -> Decimal:
|
||||||
|
return Decimal(str(self.tick_size_steps[0]['above_price']))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size_tick(self) -> Decimal:
|
||||||
|
return Decimal(str(self.tick_size))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_fqme(self) -> str:
|
||||||
|
return f'{self.symbol}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_mktid(self) -> str:
|
||||||
|
return f'{self.symbol}.{self.venue}'
|
||||||
|
|
||||||
|
|
||||||
|
class OptionPair(Pair, frozen=True):
|
||||||
|
|
||||||
|
taker_commission: float # 0.0003
|
||||||
|
strike: float # 5000.0
|
||||||
|
settlement_period: str # 'day'
|
||||||
|
settlement_currency: str # "BTC",
|
||||||
|
rfq: bool # false
|
||||||
|
price_index: str # 'btc_usd'
|
||||||
|
option_type: str # 'call'
|
||||||
|
min_trade_amount: float # 0.1
|
||||||
|
maker_commission: float # 0.0003
|
||||||
|
kind: str # 'option'
|
||||||
|
is_active: bool # true
|
||||||
|
instrument_type: str # 'reversed'
|
||||||
|
instrument_name: str # 'BTC-1SEP24-55000-C'
|
||||||
|
instrument_id: int # 364671
|
||||||
|
expiration_timestamp: int # 1725177600000
|
||||||
|
creation_timestamp: int # 1724918461000
|
||||||
|
counter_currency: str # 'USD'
|
||||||
|
contract_size: float # '1.0'
|
||||||
|
block_trade_tick_size: float # '0.0001'
|
||||||
|
block_trade_min_trade_amount: int # '25'
|
||||||
|
block_trade_commission: float # '0.003'
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: see `.data._symcache.SymbologyCache.load()` for why
|
||||||
|
ns_path: str = 'piker.brokers.deribit:OptionPair'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def expiry(self) -> str:
|
||||||
|
iso_date = pendulum.from_timestamp(self.expiration_timestamp / 1000).isoformat()
|
||||||
|
return iso_date
|
||||||
|
|
||||||
|
@property
|
||||||
|
def venue(self) -> str:
|
||||||
|
return 'option'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_fqme(self) -> str:
|
||||||
|
return f'{self.symbol}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_src_asset(self) -> str:
|
||||||
|
return f'{self.quote_currency}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bs_dst_asset(self) -> str:
|
||||||
|
return f'{self.symbol}'
|
||||||
|
|
||||||
|
|
||||||
|
PAIRTYPES: dict[MarketType, Pair] = {
|
||||||
|
'option': OptionPair,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class JSONRPCResult(Struct):
|
||||||
|
id: int
|
||||||
|
usIn: int
|
||||||
|
usOut: int
|
||||||
|
usDiff: int
|
||||||
|
testnet: bool
|
||||||
|
jsonrpc: str = '2.0'
|
||||||
|
error: Optional[dict] = None
|
||||||
|
result: Optional[list[dict]] = None
|
||||||
|
|
||||||
|
class JSONRPCChannel(Struct):
|
||||||
|
method: str
|
||||||
|
params: dict
|
||||||
|
jsonrpc: str = '2.0'
|
||||||
|
|
||||||
|
|
||||||
|
class KLinesResult(Struct):
|
||||||
|
low: list[float]
|
||||||
|
cost: list[float]
|
||||||
|
high: list[float]
|
||||||
|
open: list[float]
|
||||||
|
close: list[float]
|
||||||
|
ticks: list[int]
|
||||||
|
status: str
|
||||||
|
volume: list[float]
|
||||||
|
|
||||||
|
class Trade(Struct):
|
||||||
|
iv: float
|
||||||
|
price: float
|
||||||
|
amount: float
|
||||||
|
trade_id: str
|
||||||
|
contracts: float
|
||||||
|
direction: str
|
||||||
|
trade_seq: int
|
||||||
|
timestamp: int
|
||||||
|
mark_price: float
|
||||||
|
index_price: float
|
||||||
|
tick_direction: int
|
||||||
|
instrument_name: str
|
||||||
|
combo_id: Optional[str] = '',
|
||||||
|
combo_trade_id: Optional[int] = 0,
|
||||||
|
block_trade_id: Optional[str] = '',
|
||||||
|
block_trade_leg_count: Optional[int] = 0,
|
||||||
|
|
||||||
|
class LastTradesResult(Struct):
|
||||||
|
trades: list[Trade]
|
||||||
|
has_more: bool
|
Loading…
Reference in New Issue