Define option field structure
Add some extra fields to each quote that QT should already be providing (instead of hiding them in the symbol and request contract info); namely, the expiry and contact type (i.e. put or call). Define the base set of fields to be displayed in an option chain UI and add a quote formatter.kivy_mainline_and_py3.8
parent
9c7ca84fef
commit
fb47ea2e5a
|
@ -326,13 +326,16 @@ class Client:
|
||||||
}
|
}
|
||||||
|
|
||||||
# fill out contract id to strike expiry map
|
# fill out contract id to strike expiry map
|
||||||
for key, bystrikes in by_key.items():
|
for tup, bystrikes in by_key.items():
|
||||||
for strike, ids in bystrikes.items():
|
for strike, ids in bystrikes.items():
|
||||||
for elem in ('callSymbolId', 'putSymbolId'):
|
for key, contract_type in (
|
||||||
|
('callSymbolId', 'call'), ('putSymbolId', 'put')
|
||||||
|
):
|
||||||
self._optids2contractinfo[
|
self._optids2contractinfo[
|
||||||
ids[elem]] = {
|
ids[key]] = {
|
||||||
'strike': strike,
|
'strike': strike,
|
||||||
'expiry': key.expiry,
|
'expiry': tup.expiry,
|
||||||
|
'contract_type': contract_type,
|
||||||
}
|
}
|
||||||
return by_key
|
return by_key
|
||||||
|
|
||||||
|
@ -571,15 +574,15 @@ _qt_stock_keys = {
|
||||||
|
|
||||||
# BidAskLayout columns which will contain three cells the first stacked on top
|
# BidAskLayout columns which will contain three cells the first stacked on top
|
||||||
# of the other 2
|
# of the other 2
|
||||||
_bidasks = {
|
_stock_bidasks = {
|
||||||
'last': ['bid', 'ask'],
|
'last': ['bid', 'ask'],
|
||||||
'size': ['bsize', 'asize'],
|
'size': ['bsize', 'asize'],
|
||||||
'VWAP': ['low', 'high'],
|
'VWAP': ['low', 'high'],
|
||||||
'mktcap': ['vol', '$ vol'],
|
'vol': ['mktcap', '$ vol'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def format_quote(
|
def format_stock_quote(
|
||||||
quote: dict,
|
quote: dict,
|
||||||
symbol_data: dict,
|
symbol_data: dict,
|
||||||
keymap: dict = _qt_stock_keys,
|
keymap: dict = _qt_stock_keys,
|
||||||
|
@ -624,3 +627,97 @@ def format_quote(
|
||||||
displayable[new_key] = display_value
|
displayable[new_key] = display_value
|
||||||
|
|
||||||
return new, displayable
|
return new, displayable
|
||||||
|
|
||||||
|
|
||||||
|
_qt_option_keys = {
|
||||||
|
"lastTradePrice": 'last',
|
||||||
|
"askPrice": 'ask',
|
||||||
|
"bidPrice": 'bid',
|
||||||
|
"lastTradeSize": 'size',
|
||||||
|
"bidSize": 'bsize',
|
||||||
|
"askSize": 'asize',
|
||||||
|
"volume": 'vol',
|
||||||
|
"VWAP": 'VWAP',
|
||||||
|
"lowPrice": 'low',
|
||||||
|
"highPrice": 'high',
|
||||||
|
# "expiry": "expiry",
|
||||||
|
# "delay": 0,
|
||||||
|
"delta": 'delta',
|
||||||
|
"gamma": 'gamma',
|
||||||
|
"rho": 'rho',
|
||||||
|
"theta": 'theta',
|
||||||
|
"vega": 'vega',
|
||||||
|
"$ vol": '$ vol',
|
||||||
|
# "2021-01-15T00:00:00.000000-05:00",
|
||||||
|
# "isHalted": false,
|
||||||
|
# "key": [
|
||||||
|
# "APHA.TO",
|
||||||
|
# "2021-01-15T00:00:00.000000-05:00"
|
||||||
|
# ],
|
||||||
|
# "lastTradePriceTrHrs": null,
|
||||||
|
# "lastTradeTick": 'tick',
|
||||||
|
"lastTradeTime": 'time',
|
||||||
|
"openInterest": 'open_interest',
|
||||||
|
"openPrice": 'open',
|
||||||
|
# "strike": 'strike',
|
||||||
|
# "symbol": "APHA15Jan21P8.00.MX",
|
||||||
|
# "symbolId": 23881868,
|
||||||
|
# "underlying": "APHA.TO",
|
||||||
|
# "underlyingId": 8297492,
|
||||||
|
"symbol": 'symbol',
|
||||||
|
"contract_type": 'contract_type',
|
||||||
|
"volatility": 'volatility',
|
||||||
|
"strike": 'strike',
|
||||||
|
}
|
||||||
|
|
||||||
|
_option_bidasks = {
|
||||||
|
'last': ['bid', 'ask'],
|
||||||
|
'size': ['bsize', 'asize'],
|
||||||
|
'VWAP': ['low', 'high'],
|
||||||
|
'vol': ['open_interest', '$ vol'],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def format_option_quote(
|
||||||
|
quote: dict,
|
||||||
|
symbol_data: dict,
|
||||||
|
keymap: dict = _qt_option_keys,
|
||||||
|
) -> Tuple[dict, dict]:
|
||||||
|
"""Remap a list of quote dicts ``quotes`` using the mapping of old keys
|
||||||
|
-> new keys ``keymap`` returning 2 dicts: one with raw data and the other
|
||||||
|
for display.
|
||||||
|
|
||||||
|
Returns 2 dicts: first is the original values mapped by new keys,
|
||||||
|
and the second is the same but with all values converted to a
|
||||||
|
"display-friendly" string format.
|
||||||
|
"""
|
||||||
|
# TODO: need historical data..
|
||||||
|
# (cause why would QT keep their quote structure consistent across
|
||||||
|
# assets..)
|
||||||
|
# previous = symbol_data[symbol]['prevDayClosePrice']
|
||||||
|
# change = percent_change(previous, last)
|
||||||
|
computed = {
|
||||||
|
# why QT do you have to be an asshole shipping null values!!!
|
||||||
|
'$ vol': round((quote['VWAP'] or 0) * (quote['volume'] or 0), 3),
|
||||||
|
# '%': round(change, 3),
|
||||||
|
# 'close': previous,
|
||||||
|
}
|
||||||
|
new = {}
|
||||||
|
displayable = {}
|
||||||
|
|
||||||
|
# structuring and normalization
|
||||||
|
for key, new_key in keymap.items():
|
||||||
|
display_value = value = computed.get(key) or quote.get(key)
|
||||||
|
|
||||||
|
# API servers can return `None` vals when markets are closed (weekend)
|
||||||
|
value = 0 if value is None else value
|
||||||
|
|
||||||
|
# convert values to a displayble format using available formatting func
|
||||||
|
if isinstance(new_key, tuple):
|
||||||
|
new_key, func = new_key
|
||||||
|
display_value = func(value) if value else value
|
||||||
|
|
||||||
|
new[new_key] = value
|
||||||
|
displayable[new_key] = display_value
|
||||||
|
|
||||||
|
return new, displayable
|
||||||
|
|
Loading…
Reference in New Issue