Compare commits

..

No commits in common. "bf86772d4b3e1b9825d65ddd191cee493dd3f43e" and "f2f7855e5444be6b87e7c1fe8f7fec4e15466e67" have entirely different histories.

2 changed files with 33 additions and 137 deletions

View File

@ -2,6 +2,8 @@
import trio
import tractor
from piker.brokers.deribit.api import (
Client,
get_client,
maybe_open_oi_feed,
)

View File

@ -112,10 +112,6 @@ def deribit_timestamp(when: datetime) -> int:
)
def get_timestamp_int(expiry_date: str) -> int:
return int(time.mktime(time.strptime(expiry_date, '%d%b%y')))
def str_to_cb_sym(name: str) -> Symbol:
base, strike_price, expiry_date, option_type = name.split('-')
@ -123,14 +119,13 @@ def str_to_cb_sym(name: str) -> Symbol:
if option_type == 'put':
option_type = PUT
elif option_type == 'call':
elif option_type == 'call':
option_type = CALL
else:
raise Exception("Couldn\'t parse option type")
new_expiry_date: int = get_timestamp_int(
get_values_from_cb_normalized_date(expiry_date)
)
new_expiry_date = get_values_from_cb_normalized_date(expiry_date)
return Symbol(
base=base,
quote=quote,
@ -150,12 +145,11 @@ def piker_sym_to_cb_sym(name: str) -> Symbol:
)= tuple(
name.upper().split('-'))
new_expiry_date = get_timestamp_int(expiry_date)
quote: str = base
if option_type == 'P' or option_type == 'PUT':
if option_type == 'P':
option_type = PUT
elif option_type == 'C' or option_type == 'CALL':
elif option_type == 'C':
option_type = CALL
else:
raise Exception("Couldn\'t parse option type")
@ -166,7 +160,7 @@ def piker_sym_to_cb_sym(name: str) -> Symbol:
type=OPTION,
strike_price=strike_price,
option_type=option_type,
expiry_date=new_expiry_date
expiry_date=expiry_date
)
@ -242,24 +236,9 @@ def get_config() -> dict[str, Any]:
section['log'] = {}
section['log']['filename'] = 'feedhandler.log'
section['log']['level'] = 'DEBUG'
section['log']['disabled'] = True
return section
def check_if_complete(
oi: dict[str, dict[str, Decimal | None]],
) -> bool:
for strike in oi:
if (
oi[strike]['C'] == None
or
oi[strike]['P'] == None
):
return False
return True
class Client:
'''
@ -334,20 +313,6 @@ class Client:
return balances
async def get_currencies(
self,
) -> list[dict]:
'''
Return the set of currencies for deribit.
'''
assets = {}
resp = await self._json_rpc_auth_wrapper(
'public/get_currencies',
params={}
)
return resp.result
async def get_assets(
self,
venue: str | None = None,
@ -360,7 +325,11 @@ class Client:
'''
assets = {}
currencies = await self.get_currencies()
resp = await self._json_rpc_auth_wrapper(
'public/get_currencies',
params={}
)
currencies: list[dict] = resp.result
for currency in currencies:
name: str = currency['currency']
tx_tick: Decimal = digits_to_dec(currency['fee_precision'])
@ -397,7 +366,6 @@ class Client:
currency: str = 'btc',
kind: str = 'option',
expired: bool = False,
expiry_date: str = None,
) -> list[Symbol]:
"""
@ -416,35 +384,12 @@ class Client:
resp = r.result
response_list = []
for i in range(len(resp)):
for i in range(len(resp) // 10):
element = resp[i]
name = f'{element["instrument_name"].split("-")[1]}'
if not expiry_date or name == expiry_date.upper():
response_list.append(piker_sym_to_cb_sym(element['instrument_name']))
response_list.append(piker_sym_to_cb_sym(element['instrument_name']))
return response_list
def get_strikes_dict(
self,
instruments: list[Symbol],
) -> dict[str, dict[str, Decimal | None]]:
"""
Get a dict with strike prices as keys.
"""
response: dict[str, dict[str, Decimal | None]] = {}
for i in range(len(instruments)):
element = instruments[i]
strike = f'{str(element).split('-')[1]}'
response[f'{strike}'] = {
'C': None,
'P': None,
}
return response
async def submit_limit(
self,
symbol: str,
@ -827,15 +772,9 @@ async def maybe_open_price_feed(
async def aio_open_interest_feed_relay(
fh: FeedHandler,
instruments: list,
intrinsic_values: dict[str, Decimal],
oi_by_strikes: dict[str, dict[str, Decimal]],
from_trio: asyncio.Queue,
to_trio: trio.abc.SendChannel,
) -> None:
max_losses: Decimal = Decimal('Infinity')
max_pain: Decimal = Decimal(0)
async def _trade(
trade: Trade, # cryptofeed, NOT ours from `.venues`!
receipt_timestamp: int,
@ -844,6 +783,12 @@ async def aio_open_interest_feed_relay(
Proxy-thru `cryptofeed.FeedHandler` "trades" to `piker`-side.
'''
# Get timestamp and convert it to isoformat
date = (datetime.utcfromtimestamp(trade.timestamp)).isoformat()
print('Trade...')
print(date)
print(trade)
print('=======================')
to_trio.send_nowait(('trade', trade))
# trade and oi are user defined functions that
@ -857,60 +802,18 @@ async def aio_open_interest_feed_relay(
Proxy-thru `cryptofeed.FeedHandler` "oi" to `piker`-side.
'''
nonlocal intrinsic_values
nonlocal oi_by_strikes
nonlocal max_losses
nonlocal max_pain
symbol: Symbol = str_to_cb_sym(oi.symbol)
piker_sym: str = cb_sym_to_deribit_inst(symbol)
(
base,
expiry_date,
strike_price,
option_type
) = tuple(
piker_sym.split('-')
)
open_interest: Decimal = oi.open_interest
oi_by_strikes[f'{strike_price}'][f'{option_type}'] = open_interest
is_ready = check_if_complete(oi_by_strikes)
if is_ready:
for strike in oi_by_strikes:
s: Decimal = Decimal(f'{strike}')
close_losses = Decimal(0)
closes: list[str] = sorted(oi_by_strikes.keys())
call_cash: Decimal = Decimal(0)
put_cash: Decimal = Decimal(0)
for close in closes:
c: Decimal = Decimal(f'{close}')
call_cash += max(0, (s - c) * oi_by_strikes[f'{close}']['C'])
put_cash += max(0, (c - s) * oi_by_strikes[f'{close}']['P'])
intrinsic_values[f'{strike}'] = {}
intrinsic_values[f'{strike}']['C'] = call_cash
intrinsic_values[f'{strike}']['P'] = put_cash
intrinsic_values[f'{strike}']['total'] = (call_cash + put_cash)
for strike in intrinsic_values:
if intrinsic_values[f'{strike}']['total'] < max_losses:
max_losses = intrinsic_values[f'{strike}']['total']
max_pain = strike
print('-----------------------------------------------')
print(f'time: {oi.timestamp}')
print(f'max_pain: {max_pain}')
print(f'max_losses: {max_losses}')
print('-----------------------------------------------')
channels = [TRADES, OPEN_INTEREST]
callbacks={TRADES: _trade, OPEN_INTEREST: _oi}
# Get timestamp and convert it to isoformat
date = (datetime.utcfromtimestamp(oi.timestamp)).isoformat()
print('>>>> Open Interest...')
print(date)
print(oi)
print('==========================')
to_trio.send_nowait(('oi', oi))
callbacks = {TRADES: _trade, OPEN_INTEREST: _oi}
fh.add_feed(
DERIBIT,
channels=channels,
channels=[TRADES, OPEN_INTEREST],
symbols=instruments,
callbacks=callbacks
)
@ -932,17 +835,10 @@ async def aio_open_interest_feed_relay(
async def open_oi_feed(
) -> to_asyncio.LinkedTaskChannel:
expiry_date: str = '20DEC24'
instruments: list[Symbol] = []
intrinsic_values: dict[str, dict[str, Decimal]] = {}
oi_by_strikes: dict[str, dict[str, Decimal]]
instruments: list[Symbol]
async with get_client(
) as client:
instruments = await client.get_instruments(
expiry_date=expiry_date,
)
oi_by_strikes = client.get_strikes_dict(instruments)
instruments = await client.get_instruments()
fh: FeedHandler
first: None
@ -953,9 +849,7 @@ async def open_oi_feed(
partial(
aio_open_interest_feed_relay,
fh,
instruments,
intrinsic_values,
oi_by_strikes,
instruments
)
) as (first, chan)
):