Add real-time market caps

kivy_mainline_and_py3.8
Tyler Goodlet 2018-02-14 12:06:54 -05:00
parent 722d294915
commit d50aa17a83
1 changed files with 47 additions and 39 deletions

View File

@ -41,15 +41,13 @@ def colorcode(name):
return _colors[name if name else 'gray'] return _colors[name if name else 'gray']
# border size _bs = 3 # border size
_bs = 3
_color = [0.13]*3 # nice shade of gray _color = [0.13]*3 # nice shade of gray
_kv = (f''' _kv = (f'''
#:kivy 1.10.0 #:kivy 1.10.0
<Cell> <Cell>
font_size: 20 font_size: 18
text_size: self.size text_size: self.size
size: self.texture_size size: self.texture_size
color: {colorcode('gray')} color: {colorcode('gray')}
@ -62,7 +60,7 @@ _kv = (f'''
outline_color: [0.1]*4 outline_color: [0.1]*4
<HeaderCell> <HeaderCell>
font_size: 21 font_size: 20
background_color: [0]*4 background_color: [0]*4
canvas.before: canvas.before:
Color: Color:
@ -91,17 +89,19 @@ _kv = (f'''
''') ''')
# Questrade key conversion # Questrade key conversion / column order
_qt_keys = { _qt_keys = {
# 'symbol': 'symbol', # done manually in qtconvert 'symbol': 'symbol', # done manually in qtconvert
'%': '%',
'lastTradePrice': 'last', 'lastTradePrice': 'last',
'askPrice': 'ask', 'askPrice': 'ask',
'bidPrice': 'bid', 'bidPrice': 'bid',
'lastTradeSize': 'size', 'lastTradeSize': 'size',
'bidSize': 'bsize', 'bidSize': 'bsize',
'askSize': 'asize', 'askSize': 'asize',
'volume': ('vol', humanize),
'VWAP': ('VWAP', partial(round, ndigits=3)), 'VWAP': ('VWAP', partial(round, ndigits=3)),
'volume': ('vol', humanize),
'mktcap': ('mktcap', humanize),
'openPrice': 'open', 'openPrice': 'open',
'lowPrice': 'low', 'lowPrice': 'low',
'highPrice': 'high', 'highPrice': 'high',
@ -127,19 +127,25 @@ def qtconvert(
and the second is the same but with all values converted to a and the second is the same but with all values converted to a
"display-friendly" string format. "display-friendly" string format.
""" """
last = quote['lastTradePrice']
symbol = quote['symbol']
if symbol_data: # we can only compute % change from symbols data if symbol_data: # we can only compute % change from symbols data
previous = symbol_data[quote['symbol']]['prevDayClosePrice'] previous = symbol_data[symbol]['prevDayClosePrice']
change = percent_change(previous, quote['lastTradePrice']) change = percent_change(previous, last)
share_count = symbol_data[symbol].get('outstandingShares', None)
mktcap = share_count * last if share_count else 'NA'
else: else:
change = 0 change = 0
new = { computed = {
'symbol': quote['symbol'], 'symbol': quote['symbol'],
'%': round(change, 3) '%': round(change, 3),
'mktcap': mktcap,
} }
displayable = new.copy() new = {}
displayable = {}
for key, new_key in keymap.items(): for key, new_key in keymap.items():
display_value = value = quote[key] display_value = value = quote.get(key) or computed.get(key)
# API servers can return `None` vals when markets are closed (weekend) # API servers can return `None` vals when markets are closed (weekend)
value = 0 if value is None else value value = 0 if value is None else value
@ -263,7 +269,6 @@ class Row(GridLayout):
'last': ['bid', 'ask'], 'last': ['bid', 'ask'],
'size': ['bsize', 'asize'] 'size': ['bsize', 'asize']
} }
# import pdb; pdb.set_trace()
ba_cells = {} ba_cells = {}
layouts = {} layouts = {}
for key, children in bidasks.items(): for key, children in bidasks.items():
@ -309,6 +314,23 @@ class Row(GridLayout):
self.add_widget(cell) self.add_widget(cell)
return cell return cell
def update(self, record, displayable):
# color changed field values
for key, val in record.items():
# logic for cell text coloring: up-green, down-red
if self._last_record[key] < val:
color = colorcode('forestgreen')
elif self._last_record[key] > val:
color = colorcode('red2')
else:
color = colorcode('gray')
cell = self.get_cell(key)
cell.text = str(displayable[key])
cell.color = color
self._last_record = record
class TickerTable(GridLayout): class TickerTable(GridLayout):
"""A grid for displaying ticker quote records as a table. """A grid for displaying ticker quote records as a table.
@ -392,9 +414,10 @@ async def update_quotes(
for quote in first_quotes: for quote in first_quotes:
sym = quote['symbol'] sym = quote['symbol']
row = grid.symbols2rows[sym] row = grid.symbols2rows[sym]
data, displayable = qtconvert(quote, symbol_data=symbol_data) record, displayable = qtconvert(quote, symbol_data=symbol_data)
color_row(row, data) row.update(record, displayable)
cache[sym] = (data, row) color_row(row, record)
cache[sym] = (record, row)
grid.render_rows(cache) grid.render_rows(cache)
@ -403,26 +426,11 @@ async def update_quotes(
log.debug("Waiting on quotes") log.debug("Waiting on quotes")
quotes = await queue.get() # new quotes data only quotes = await queue.get() # new quotes data only
for quote in quotes: for quote in quotes:
data, displayable = qtconvert(quote, symbol_data=symbol_data) record, displayable = qtconvert(quote, symbol_data=symbol_data)
row = grid.symbols2rows[data['symbol']] row = grid.symbols2rows[record['symbol']]
cache[data['symbol']] = (data, row) cache[record['symbol']] = (record, row)
row.update(record, displayable)
# color changed field values color_row(row, record)
for key, val in data.items():
# logic for cell text coloring: up-green, down-red
if row._last_record[key] < val:
color = colorcode('forestgreen')
elif row._last_record[key] > val:
color = colorcode('red2')
else:
color = colorcode('gray')
cell = row.get_cell(key)
cell.text = str(displayable[key])
cell.color = color
color_row(row, data)
row._last_record = data
grid.render_rows(cache) grid.render_rows(cache)
@ -458,7 +466,7 @@ async def _async_main(name, watchlists, brokermod):
return return
first_quotes = [ first_quotes = [
qtconvert(quote, symbol_data=sd)[1] for quote in pkts] qtconvert(quote, symbol_data=sd)[0] for quote in pkts]
# build out UI # build out UI
Builder.load_string(_kv) Builder.load_string(_kv)