Compare commits
No commits in common. "de5b1737b4d66397bbcec40867d3666be978d6f9" and "8701b517e7c5e8074010549e800647554cb26149" have entirely different histories.
de5b1737b4
...
8701b517e7
|
|
@ -250,9 +250,7 @@ async def vnc_click_hack(
|
||||||
'connection': 'r'
|
'connection': 'r'
|
||||||
}[reset_type]
|
}[reset_type]
|
||||||
|
|
||||||
with tractor.devx.open_crash_handler(
|
with tractor.devx.open_crash_handler():
|
||||||
ignore={TimeoutError,},
|
|
||||||
):
|
|
||||||
client = await AsyncVNCClient.connect(
|
client = await AsyncVNCClient.connect(
|
||||||
VNCConfig(
|
VNCConfig(
|
||||||
host=host,
|
host=host,
|
||||||
|
|
|
||||||
|
|
@ -267,28 +267,19 @@ async def open_history_client(
|
||||||
if (
|
if (
|
||||||
start_dt
|
start_dt
|
||||||
and
|
and
|
||||||
first_dt < start_dt
|
last_dt < start_dt
|
||||||
):
|
):
|
||||||
trimmed_bars = bars_array[
|
bars_array = bars_array[
|
||||||
bars_array['time'] >= start_dt.timestamp()
|
bars_array['time'] >= start_dt.timestamp()
|
||||||
]
|
]
|
||||||
if (
|
|
||||||
trimmed_first_dt := from_timestamp(trimmed_bars['time'][0])
|
|
||||||
!=
|
|
||||||
start_dt
|
|
||||||
):
|
|
||||||
# TODO! rm this once we're more confident it never hits!
|
# TODO! rm this once we're more confident it never hits!
|
||||||
breakpoint()
|
breakpoint()
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f'OHLC-bars array start is gt `start_dt` limit !!\n'
|
f'OHLC-bars array start is gt `start_dt` limit !!\n'
|
||||||
f'start_dt: {start_dt}\n'
|
f'start_dt: {start_dt}\n'
|
||||||
f'first_dt: {first_dt}\n'
|
f'last_dt: {last_dt}\n'
|
||||||
f'trimmed_first_dt: {trimmed_first_dt}\n'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# XXX, overwrite with start_dt-limited frame
|
|
||||||
bars_array = trimmed_bars
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
bars_array,
|
bars_array,
|
||||||
first_dt,
|
first_dt,
|
||||||
|
|
|
||||||
|
|
@ -35,51 +35,6 @@ if TYPE_CHECKING:
|
||||||
from piker.ui._remote_ctl import AnnotCtl
|
from piker.ui._remote_ctl import AnnotCtl
|
||||||
|
|
||||||
|
|
||||||
def humanize_duration(
|
|
||||||
seconds: float,
|
|
||||||
) -> str:
|
|
||||||
'''
|
|
||||||
Convert duration in seconds to short human-readable form.
|
|
||||||
|
|
||||||
Uses smallest appropriate time unit:
|
|
||||||
- d: days
|
|
||||||
- h: hours
|
|
||||||
- m: minutes
|
|
||||||
- s: seconds
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
- 86400 -> "1d"
|
|
||||||
- 28800 -> "8h"
|
|
||||||
- 180 -> "3m"
|
|
||||||
- 45 -> "45s"
|
|
||||||
|
|
||||||
'''
|
|
||||||
abs_secs: float = abs(seconds)
|
|
||||||
|
|
||||||
if abs_secs >= 86400:
|
|
||||||
days: float = abs_secs / 86400
|
|
||||||
if days >= 10:
|
|
||||||
return f'{int(days)}d'
|
|
||||||
return f'{days:.1f}d'
|
|
||||||
|
|
||||||
elif abs_secs >= 3600:
|
|
||||||
hours: float = abs_secs / 3600
|
|
||||||
if hours >= 10:
|
|
||||||
return f'{int(hours)}h'
|
|
||||||
return f'{hours:.1f}h'
|
|
||||||
|
|
||||||
elif abs_secs >= 60:
|
|
||||||
mins: float = abs_secs / 60
|
|
||||||
if mins >= 10:
|
|
||||||
return f'{int(mins)}m'
|
|
||||||
return f'{mins:.1f}m'
|
|
||||||
|
|
||||||
else:
|
|
||||||
if abs_secs >= 10:
|
|
||||||
return f'{int(abs_secs)}s'
|
|
||||||
return f'{abs_secs:.1f}s'
|
|
||||||
|
|
||||||
|
|
||||||
async def markup_gaps(
|
async def markup_gaps(
|
||||||
fqme: str,
|
fqme: str,
|
||||||
timeframe: float,
|
timeframe: float,
|
||||||
|
|
@ -169,13 +124,10 @@ async def markup_gaps(
|
||||||
opn: float = row['open'][0]
|
opn: float = row['open'][0]
|
||||||
cls: float = prev_r['close'][0]
|
cls: float = prev_r['close'][0]
|
||||||
|
|
||||||
# get gap duration for humanized label
|
|
||||||
gap_dur_s: float = row['s_diff'][0]
|
|
||||||
gap_label: str = humanize_duration(gap_dur_s)
|
|
||||||
|
|
||||||
# BGM=0.16 is the normal diff from overlap between bars, SO
|
# BGM=0.16 is the normal diff from overlap between bars, SO
|
||||||
# just go slightly "in" from that "between them".
|
# just go slightly "in" from that "between them".
|
||||||
from_idx: int = BGM - .06 # = .10
|
from_idx: int = BGM - .06 # = .10
|
||||||
|
|
||||||
lc: tuple[float, float] = (
|
lc: tuple[float, float] = (
|
||||||
istart + 1 - from_idx,
|
istart + 1 - from_idx,
|
||||||
cls,
|
cls,
|
||||||
|
|
@ -210,43 +162,20 @@ async def markup_gaps(
|
||||||
'down' if sgn == 1
|
'down' if sgn == 1
|
||||||
else 'up'
|
else 'up'
|
||||||
)
|
)
|
||||||
# TODO! mk this a `msgspec.Struct` which we deserialize
|
|
||||||
# on the server side!
|
|
||||||
arrow_kwargs: dict[str, Any] = dict(
|
arrow_kwargs: dict[str, Any] = dict(
|
||||||
fqme=fqme,
|
fqme=fqme,
|
||||||
timeframe=timeframe,
|
timeframe=timeframe,
|
||||||
x=iend,
|
x=iend,
|
||||||
y=cls,
|
y=cls,
|
||||||
color=color,
|
color=color,
|
||||||
alpha=169,
|
alpha=160,
|
||||||
pointing=direction,
|
pointing=direction,
|
||||||
# TODO: expose these as params to markup_gaps()?
|
|
||||||
headLen=10,
|
|
||||||
headWidth=2.222,
|
|
||||||
pxMode=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
aid: int = await actl.add_arrow(
|
aid: int = await actl.add_arrow(
|
||||||
**arrow_kwargs
|
**arrow_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
# add duration label to RHS of arrow
|
|
||||||
if sgn == -1: # up-gap
|
|
||||||
anchor = (0, 0) # XXX, i dun get dese dims.. XD
|
|
||||||
else: # down-gap
|
|
||||||
anchor = (0, 1) # XXX y, x?
|
|
||||||
|
|
||||||
text_aid: int = await actl.add_text(
|
|
||||||
fqme=fqme,
|
|
||||||
timeframe=timeframe,
|
|
||||||
text=gap_label,
|
|
||||||
x=iend + 1,
|
|
||||||
y=cls,
|
|
||||||
color=color,
|
|
||||||
anchor=anchor,
|
|
||||||
)
|
|
||||||
aids[text_aid] = {'text': gap_label}
|
|
||||||
|
|
||||||
# tell chart to redraw all its
|
# tell chart to redraw all its
|
||||||
# graphics view layers Bo
|
# graphics view layers Bo
|
||||||
await actl.redraw(
|
await actl.redraw(
|
||||||
|
|
|
||||||
|
|
@ -243,8 +243,8 @@ async def maybe_fill_null_segments(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
frame_start_dt := (
|
from_timestamp(
|
||||||
from_timestamp(array['time'][0])
|
array['time'][0]
|
||||||
) < backfill_until_dt
|
) < backfill_until_dt
|
||||||
):
|
):
|
||||||
await tractor.pause()
|
await tractor.pause()
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,6 @@ class ArrowEditor(Struct):
|
||||||
] = None,
|
] = None,
|
||||||
alpha: int = 255,
|
alpha: int = 255,
|
||||||
zval: float = 1e9,
|
zval: float = 1e9,
|
||||||
headLen: float|None = None,
|
|
||||||
headWidth: float|None = None,
|
|
||||||
tailLen: float|None = None,
|
|
||||||
tailWidth: float|None = None,
|
|
||||||
pxMode: bool = True,
|
|
||||||
|
|
||||||
) -> pg.ArrowItem:
|
) -> pg.ArrowItem:
|
||||||
'''
|
'''
|
||||||
|
|
@ -114,15 +109,6 @@ class ArrowEditor(Struct):
|
||||||
# scale arrow sizing to dpi-aware font
|
# scale arrow sizing to dpi-aware font
|
||||||
size = _font.font.pixelSize() * 0.8
|
size = _font.font.pixelSize() * 0.8
|
||||||
|
|
||||||
# allow caller override of head dimensions
|
|
||||||
if headLen is None:
|
|
||||||
headLen = size
|
|
||||||
if headWidth is None:
|
|
||||||
headWidth = size/2
|
|
||||||
# tail params default to None (no tail)
|
|
||||||
if tailWidth is None:
|
|
||||||
tailWidth = 3
|
|
||||||
|
|
||||||
color = color or 'default'
|
color = color or 'default'
|
||||||
color = QColor(hcolor(color))
|
color = QColor(hcolor(color))
|
||||||
color.setAlpha(alpha)
|
color.setAlpha(alpha)
|
||||||
|
|
@ -131,11 +117,10 @@ class ArrowEditor(Struct):
|
||||||
arrow = pg.ArrowItem(
|
arrow = pg.ArrowItem(
|
||||||
angle=angle,
|
angle=angle,
|
||||||
baseAngle=0,
|
baseAngle=0,
|
||||||
headLen=headLen,
|
headLen=size,
|
||||||
headWidth=headWidth,
|
headWidth=size/2,
|
||||||
tailLen=tailLen,
|
tailLen=None,
|
||||||
tailWidth=tailWidth,
|
pxMode=True,
|
||||||
pxMode=pxMode,
|
|
||||||
# coloring
|
# coloring
|
||||||
pen=pen,
|
pen=pen,
|
||||||
brush=brush,
|
brush=brush,
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ from piker.service import find_service
|
||||||
from piker.brokers import SymbolNotFound
|
from piker.brokers import SymbolNotFound
|
||||||
from piker.ui.qt import (
|
from piker.ui.qt import (
|
||||||
QGraphicsItem,
|
QGraphicsItem,
|
||||||
QColor,
|
|
||||||
)
|
)
|
||||||
from ._display import DisplayState
|
from ._display import DisplayState
|
||||||
from ._interaction import ChartView
|
from ._interaction import ChartView
|
||||||
|
|
@ -58,7 +57,6 @@ from ._editors import (
|
||||||
)
|
)
|
||||||
from ._chart import ChartPlotWidget
|
from ._chart import ChartPlotWidget
|
||||||
from ._dataviz import Viz
|
from ._dataviz import Viz
|
||||||
from ._style import hcolor
|
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
@ -95,7 +93,7 @@ _annots: AnnotsTable = {}
|
||||||
_editors: EditorsTable = {}
|
_editors: EditorsTable = {}
|
||||||
|
|
||||||
def rm_annot(
|
def rm_annot(
|
||||||
annot: ArrowEditor|SelectRect|pg.TextItem
|
annot: ArrowEditor|SelectRect
|
||||||
) -> bool:
|
) -> bool:
|
||||||
global _editors
|
global _editors
|
||||||
match annot:
|
match annot:
|
||||||
|
|
@ -116,12 +114,6 @@ def rm_annot(
|
||||||
annot.delete()
|
annot.delete()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
case pg.TextItem():
|
|
||||||
scene = annot.scene()
|
|
||||||
if scene:
|
|
||||||
scene.removeItem(annot)
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -191,11 +183,6 @@ async def serve_rc_annots(
|
||||||
'color': color,
|
'color': color,
|
||||||
'aid': str()|None as aid,
|
'aid': str()|None as aid,
|
||||||
'alpha': int(alpha),
|
'alpha': int(alpha),
|
||||||
'headLen': int()|float()|None as headLen,
|
|
||||||
'headWidth': int()|float()|None as headWidth,
|
|
||||||
'tailLen': int()|float()|None as tailLen,
|
|
||||||
'tailWidth': int()|float()|None as tailWidth,
|
|
||||||
'pxMode': bool(pxMode),
|
|
||||||
},
|
},
|
||||||
# ?TODO? split based on method fn-sigs?
|
# ?TODO? split based on method fn-sigs?
|
||||||
# 'pointing',
|
# 'pointing',
|
||||||
|
|
@ -226,11 +213,6 @@ async def serve_rc_annots(
|
||||||
pointing=pointing,
|
pointing=pointing,
|
||||||
color=color,
|
color=color,
|
||||||
alpha=alpha,
|
alpha=alpha,
|
||||||
headLen=headLen,
|
|
||||||
headWidth=headWidth,
|
|
||||||
tailLen=tailLen,
|
|
||||||
tailWidth=tailWidth,
|
|
||||||
pxMode=pxMode,
|
|
||||||
)
|
)
|
||||||
annots[aid] = arrow
|
annots[aid] = arrow
|
||||||
_editors[aid] = arrows
|
_editors[aid] = arrows
|
||||||
|
|
@ -238,41 +220,8 @@ async def serve_rc_annots(
|
||||||
aids.add(aid)
|
aids.add(aid)
|
||||||
await annot_req_stream.send(aid)
|
await annot_req_stream.send(aid)
|
||||||
|
|
||||||
case {
|
# TODO, use `pg.TextItem` to put a humaized
|
||||||
'cmd': 'TextItem',
|
# time label beside the arrows
|
||||||
'fqme': fqme,
|
|
||||||
'timeframe': timeframe,
|
|
||||||
'kwargs': {
|
|
||||||
'text': str(text),
|
|
||||||
'x': int()|float() as x,
|
|
||||||
'y': int()|float() as y,
|
|
||||||
'color': color,
|
|
||||||
'anchor': list(anchor),
|
|
||||||
},
|
|
||||||
}:
|
|
||||||
ds: DisplayState = _dss[fqme]
|
|
||||||
chart: ChartPlotWidget = {
|
|
||||||
60: ds.hist_chart,
|
|
||||||
1: ds.chart,
|
|
||||||
}[timeframe]
|
|
||||||
|
|
||||||
# convert named color to hex
|
|
||||||
color_hex: str = hcolor(color)
|
|
||||||
|
|
||||||
# create text item
|
|
||||||
text_item: pg.TextItem = pg.TextItem(
|
|
||||||
text=text,
|
|
||||||
color=color_hex,
|
|
||||||
anchor=anchor,
|
|
||||||
)
|
|
||||||
text_item.setPos(x, y)
|
|
||||||
chart.plotItem.addItem(text_item)
|
|
||||||
|
|
||||||
aid: str = str(uuid4())
|
|
||||||
annots[aid] = text_item
|
|
||||||
aids: set[int] = ctxs[ipc_key][1]
|
|
||||||
aids.add(aid)
|
|
||||||
await annot_req_stream.send(aid)
|
|
||||||
|
|
||||||
case {
|
case {
|
||||||
'cmd': 'remove',
|
'cmd': 'remove',
|
||||||
|
|
@ -492,11 +441,6 @@ class AnnotCtl(Struct):
|
||||||
# domain: str = 'view', # or 'scene'
|
# domain: str = 'view', # or 'scene'
|
||||||
color: str = 'dad_blue',
|
color: str = 'dad_blue',
|
||||||
alpha: int = 116,
|
alpha: int = 116,
|
||||||
headLen: float|None = None,
|
|
||||||
headWidth: float|None = None,
|
|
||||||
tailLen: float|None = None,
|
|
||||||
tailWidth: float|None = None,
|
|
||||||
pxMode: bool = True,
|
|
||||||
|
|
||||||
from_acm: bool = False,
|
from_acm: bool = False,
|
||||||
|
|
||||||
|
|
@ -520,54 +464,6 @@ class AnnotCtl(Struct):
|
||||||
'pointing': pointing, # up|down
|
'pointing': pointing, # up|down
|
||||||
'alpha': alpha,
|
'alpha': alpha,
|
||||||
'aid': None,
|
'aid': None,
|
||||||
'headLen': headLen,
|
|
||||||
'headWidth': headWidth,
|
|
||||||
'tailLen': tailLen,
|
|
||||||
'tailWidth': tailWidth,
|
|
||||||
'pxMode': pxMode,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
aid: int = await ipc.receive()
|
|
||||||
self._ipcs[aid] = ipc
|
|
||||||
if not from_acm:
|
|
||||||
self._annot_stack.push_async_callback(
|
|
||||||
partial(
|
|
||||||
self.remove,
|
|
||||||
aid,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return aid
|
|
||||||
|
|
||||||
async def add_text(
|
|
||||||
self,
|
|
||||||
fqme: str,
|
|
||||||
timeframe: float,
|
|
||||||
text: str,
|
|
||||||
x: float,
|
|
||||||
y: float,
|
|
||||||
color: str|tuple = 'dad_blue',
|
|
||||||
anchor: tuple[float, float] = (0, 1),
|
|
||||||
|
|
||||||
from_acm: bool = False,
|
|
||||||
|
|
||||||
) -> int:
|
|
||||||
'''
|
|
||||||
Add a `pg.TextItem` annotation to the target view.
|
|
||||||
|
|
||||||
anchor: (x, y) where (0,0) is upper-left, (1,1) is lower-right
|
|
||||||
|
|
||||||
'''
|
|
||||||
ipc: MsgStream = self._get_ipc(fqme)
|
|
||||||
await ipc.send({
|
|
||||||
'fqme': fqme,
|
|
||||||
'cmd': 'TextItem',
|
|
||||||
'timeframe': timeframe,
|
|
||||||
'kwargs': {
|
|
||||||
'text': text,
|
|
||||||
'x': float(x),
|
|
||||||
'y': float(y),
|
|
||||||
'color': color,
|
|
||||||
'anchor': tuple(anchor),
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
aid: int = await ipc.receive()
|
aid: int = await ipc.receive()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue