Combine last,bid,ask in a StackLayout-cell

kivy_mainline_and_py3.8
Tyler Goodlet 2018-02-14 02:07:42 -05:00
parent 29be7f58c9
commit e464898210
1 changed files with 115 additions and 42 deletions

View File

@ -5,11 +5,14 @@ Launch with ``piker watch <watchlist name>``.
(Currently there's a bunch of QT specific stuff in here) (Currently there's a bunch of QT specific stuff in here)
""" """
from itertools import chain
from functools import partial
import trio import trio
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout from kivy.uix.gridlayout import GridLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView from kivy.uix.scrollview import ScrollView
from kivy.lang import Builder from kivy.lang import Builder
from kivy import utils from kivy import utils
@ -40,34 +43,26 @@ def colorcode(name):
# border size # border size
_bs = 3 _bs = 3
_color = [0.14]*4 # 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
text_size: self.size text_size: self.size
size: self.texture_size size: self.texture_size
font_size: '20'
color: {colorcode('gray')} color: {colorcode('gray')}
# size_hint_y: None
font_color: {colorcode('gray')} font_color: {colorcode('gray')}
font_name: 'Roboto-Regular' font_name: 'Roboto-Regular'
# height: 50 background_color: [0.13]*3 + [1]
# width: 50 background_normal: ''
background_color: [0]*4
valign: 'middle' valign: 'middle'
halign: 'center' halign: 'center'
outline_color: [0.1]*4 outline_color: [0.1]*4
canvas.before:
Color:
rgb: {_color}
BorderImage:
pos: self.pos
size: self.size
<HeaderCell> <HeaderCell>
font_size: '20' font_size: 21
background_color: [0]*4 background_color: [0]*4
canvas.before: canvas.before:
Color: Color:
@ -84,11 +79,14 @@ _kv = (f'''
row_default_height: 75 row_default_height: 75
cols: 1 cols: 1
<BidAskLayout>
spacing: [{_bs}, 0]
<Row> <Row>
minimum_height: 200 # should be pulled from Cell text size # minimum_height: 200 # should be pulled from Cell text size
minimum_width: 200 # minimum_width: 200
row_force_default: True # row_force_default: True
row_default_height: 75 # row_default_height: 75
outline_color: [.7]*4 outline_color: [.7]*4
''') ''')
@ -99,19 +97,19 @@ _qt_keys = {
'lastTradePrice': 'last', 'lastTradePrice': 'last',
'askPrice': 'ask', 'askPrice': 'ask',
'bidPrice': 'bid', 'bidPrice': 'bid',
'lastTradeSize': 'last size', 'lastTradeSize': 'size',
'bidSize': 'bid size', 'bidSize': 'bsize',
'askSize': 'ask size', 'askSize': 'asize',
'volume': ('vol', humanize), 'volume': ('vol', humanize),
'VWAP': ('VWAP', "{:.3f}".format), 'VWAP': ('VWAP', partial(round, ndigits=3)),
'high52w': 'high52w', 'openPrice': 'open',
'lowPrice': 'low',
'highPrice': 'high', 'highPrice': 'high',
'low52w': 'low52w',
'high52w': 'high52w',
# "lastTradePriceTrHrs": 7.99, # "lastTradePriceTrHrs": 7.99,
# "lastTradeTick": "Equal", # "lastTradeTick": "Equal",
# "lastTradeTime": "2018-01-30T18:28:23.434000-05:00", # "lastTradeTime": "2018-01-30T18:28:23.434000-05:00",
# 'low52w': 'low52w',
'lowPrice': 'low day',
'openPrice': 'open',
# "symbolId": 3575753, # "symbolId": 3575753,
# "tier": "", # "tier": "",
# 'isHalted': 'halted', # 'isHalted': 'halted',
@ -188,11 +186,62 @@ class HeaderCell(Button):
self.background_color = self.color self.background_color = self.color
class Cell(Label): class Cell(Button):
"""Data cell label. """Data cell.
""" """
class BidAskLayout(StackLayout):
"""Cell which houses three buttons containing a last, bid, and ask in a
single unit oriented with the last 2 under the first.
"""
def __init__(self, values, header=False, **kwargs):
super(BidAskLayout, self).__init__(orientation='lr-tb', **kwargs)
assert len(values) == 3, "You can only provide 3 values: last,bid,ask"
self._keys2cells = {}
cell_type = HeaderCell if header else Cell
top_size = cell_type().font_size
small_size = top_size - 5
top_prop = 0.7
bottom_prop = 1 - top_prop
for (key, size_hint, font_size), value in zip(
[('last', (1, top_prop), top_size),
('bid', (0.5, bottom_prop), small_size),
('ask', (0.5, bottom_prop), small_size)],
values
):
cell = cell_type(
text=str(value),
size_hint=size_hint,
width=self.width/2 - 3,
font_size=font_size
)
self._keys2cells[key] = cell
cell.key = value
cell.is_header = header
setattr(self, key, cell)
self.add_widget(cell)
# should be assigned by referrer
self.row = None
def get_cell(self, key):
return self._keys2cells[key]
@property
def row(self):
return self.row
@row.setter
def row(self, row):
for cell in self.cells:
cell.row = row
@property
def cells(self):
return [self.last, self.bid, self.ask]
class Row(GridLayout): class Row(GridLayout):
"""A grid for displaying a row of ticker quote data. """A grid for displaying a row of ticker quote data.
@ -209,12 +258,41 @@ class Row(GridLayout):
self.table = table self.table = table
self.is_header = is_header_row self.is_header = is_header_row
# create `BidAskCells` first
bidasks = {
'last': ['bid', 'ask'],
'size': ['bsize', 'asize']
}
# import pdb; pdb.set_trace()
ba_cells = {}
layouts = {}
for key, children in bidasks.items():
layout = BidAskLayout(
[record[key]] + [record[child] for child in children],
header=is_header_row
)
layout.row = self
layouts[key] = layout
for i, child in enumerate([key] + children):
ba_cells[child] = layout.cells[i]
children_flat = list(chain.from_iterable(bidasks.values()))
self._cell_widgets.update(ba_cells)
# build out row using Cell labels # build out row using Cell labels
for (key, val) in record.items(): for (key, val) in record.items():
header = key in headers header = key in headers
# handle bidask cells
if key in layouts:
self.add_widget(layouts[key])
elif key in children_flat:
# these cells have already been added to the `BidAskLayout`
continue
else:
cell = self._append_cell(val, header=header) cell = self._append_cell(val, header=header)
self._cell_widgets[key] = cell
cell.key = key cell.key = key
self._cell_widgets[key] = cell
def get_cell(self, key): def get_cell(self, key):
return self._cell_widgets[key] return self._cell_widgets[key]
@ -228,11 +306,6 @@ class Row(GridLayout):
cell = celltype(text=str(text)) cell = celltype(text=str(text))
cell.is_header = header cell.is_header = header
cell.row = self cell.row = self
# don't bold the header row
if header and self.is_header:
cell.bold = False
self.add_widget(cell) self.add_widget(cell)
return cell return cell
@ -296,8 +369,8 @@ async def update_quotes(
grid = widgets['grid'] grid = widgets['grid']
def color_row(row, data): def color_row(row, data):
hdrcell = row._cell_widgets['symbol'] hdrcell = row.get_cell('symbol')
chngcell = row._cell_widgets['%'] chngcell = row.get_cell('%')
daychange = float(data['%']) daychange = float(data['%'])
if daychange < 0.: if daychange < 0.:
color = colorcode('red2') color = colorcode('red2')
@ -319,7 +392,7 @@ 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, _ = qtconvert(quote, symbol_data=symbol_data) data, displayable = qtconvert(quote, symbol_data=symbol_data)
color_row(row, data) color_row(row, data)
cache[sym] = (data, row) cache[sym] = (data, row)
@ -344,7 +417,7 @@ async def update_quotes(
else: else:
color = colorcode('gray') color = colorcode('gray')
cell = row._cell_widgets[key] cell = row.get_cell(key)
cell.text = str(displayable[key]) cell.text = str(displayable[key])
cell.color = color cell.color = color
@ -385,11 +458,11 @@ async def _async_main(name, watchlists, brokermod):
return return
first_quotes = [ first_quotes = [
qtconvert(quote, symbol_data=sd)[0] for quote in pkts] qtconvert(quote, symbol_data=sd)[1] for quote in pkts]
# build out UI # build out UI
Builder.load_string(_kv) Builder.load_string(_kv)
root = BoxLayout(orientation='vertical', padding=5, spacing=-20) root = BoxLayout(orientation='vertical', padding=5, spacing=5)
header = header_row( header = header_row(
first_quotes[0].keys(), first_quotes[0].keys(),
size_hint=(1, None), size_hint=(1, None),