Compare commits

..

13 Commits

Author SHA1 Message Date
Gud Boi b58a714965 Enable console log (from passed down `loglevel`) in `.tsp._history.manage_history()` 2026-02-26 18:01:24 -05:00
Gud Boi 90964487ec Drop `Flume.feed`, it's unused yet causes import cycles.. 2026-02-26 18:01:24 -05:00
Gud Boi 621707582c Just warn on single-bar nulls instead of bping
Replace the debug breakpoint with a warning-log when a single-bar
null-segment is detected in `get_null_segs()`. This lets the gap
analysis continue while still alerting about the anomaly.

Deats,
- extract the 3-bar window (before, null, after) and calculate
  a `gap: pendulum.Interval` for the warning msg.
- comment-out the old breakpoint block for optional debugging as needed.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-02-26 18:01:24 -05:00
Gud Boi abad8f751b Lul, drop long unused poetry lock file 2026-02-26 18:01:24 -05:00
Gud Boi ba7d45dbd2 Pin `pg` at latest official `0.14.0` release
Keep in masked GH sources lines for easy hackin against upstream
`master` branch when needed as well!
2026-02-26 18:01:24 -05:00
Gud Boi 491bb66912 .ui._editors: log multiline styling and re-leveling 2026-02-26 18:01:24 -05:00
Gud Boi 329d212e00 .ui._lines: drop unused graphics-item import 2026-02-26 18:01:24 -05:00
Gud Boi 17fdae4654 Add batch-submit API for gap annotations
Introduce `AnnotCtl.add_batch()` and `serve_rc_annots()` batch
handler to submit 1000s of gaps in single IPC msg instead of
per-annot round-trips. Server builds `GapAnnotations` from specs
and handles vectorized timestamp-to-index lookups.

Deats,
- add `'cmd': 'batch'` handler in `serve_rc_annots()`
- vectorized timestamp lookup via `np.searchsorted()` + masking
- build `gap_specs: list[dict]` from rect+arrow specs client-side
- create single `GapAnnotations` item for all gaps server-side
- handle `GapAnnotations.reposition()` in redraw handler
- add profiling to batch path for perf measurement
- support optional individual arrows for A/B comparison

Also,
- refactor `markup_gaps()` to collect specs + single batch call
- add `no_qt_updates()` context mgr for batch render ops
- add profiling to annotation teardown path
- add `GapAnnotations` case to `rm_annot()` match block

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-02-26 18:01:24 -05:00
Gud Boi 446558f3ad Add a `GapAnnotations` path-renderer
For a ~1000x perf gain says ol' claudy, our boi who wrote this entire
patch! Bo

Introduce `GapAnnotations` in `.ui._annotate` for batch-rendering gap
rects/arrows instead of individual `QGraphicsItem` instances. Uses
upstream's `pyqtgraph.Qt.internals.PrimitiveArray` for rects and
a `QPainterPath` for arrows. This API-replicates our prior annotator's
in view shape-graphics but now using (what we're dubbing)
"single-array-multiple-graphics" tech much like our `.ui._curve`
extensions to `pg` B)

Impl deats,
- batch draw ~1000 gaps in single paint call vs 1000 items
- arrows render in scene coords to maintain pixel size on zoom
- add vectorized timestamp-to-index lookup for repositioning
- cache bounding rect, rebuild on `reposition()` calls
- match `SelectRect` + `ArrowItem` visual style/colors
- skip reposition when timeframe doesn't match gap's period

Other,
- fix typo in `LevelMarker` docstring: "graphich" -> "graphic"
- reflow docstring in `qgo_draw_markers()` to 67 char limit

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-02-26 18:01:24 -05:00
Gud Boi e55637ae44 Add info log for shm processing in `ldshm` CLI cmd
Log shm file name and detected period before null segment
processing to aid debugging.

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-02-26 18:01:24 -05:00
Gud Boi 6ad9d6e149 Bump to latest official `pyqtgraph` release 2026-02-26 18:01:24 -05:00
Gud Boi 32786c5894 Remap non-std IB exhcange values
Add exchange name translation in `.ib.venues.has_holiday()` to handle
non-standard exchange codes when looking up holiday gaps..

Deats,
- add an ad-hoc lookup dict to remap an IB `Contract.primaryExchange` val
  which doesn't exist in the `exchange_calendars`'s alias set.
- use `.get()` with fallback to map `exch` to new `std_exch` and pass
  that to `xcals.get_calendar()`.
- add the case i just caught, `'ARCA'` -> `'ARCX'` to the table when i loaded
  the `gld.arca.ib` market..

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-02-26 18:01:03 -05:00
Gud Boi 9247746a79 Handle unknown order statuses in `.ib.broker`
Add fallback handling for unknown IB order status strings to
avoid crashes when IB returns unexpected status values.

Deats,
- add `'ValidationError': 'error'` mapping to `_statuses` dict.
- use `.get()` with `'error'` default instead of direct dict
  lookup for `status.status`.
- add `elif status_str == 'error'` block to log unknown status
  values.
- add type annots to `event_name` and `item` in
  `deliver_trade_events()` loop.

Also,
- reformat log msg in `deliver_trade_events()` to multiline.
- drop extra conditional in `if status_str == 'filled'` check.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-02-26 18:01:03 -05:00
3 changed files with 42 additions and 7 deletions

View File

@ -991,6 +991,9 @@ _statuses: dict[str, str] = {
# TODO: see a current ``ib_insync`` issue around this:
# https://github.com/erdewit/ib_insync/issues/363
'Inactive': 'pending',
# XXX, uhh wut the heck is this?
'ValidationError': 'error',
}
_action_map = {
@ -1063,8 +1066,19 @@ async def deliver_trade_events(
# TODO: for some reason we can receive a ``None`` here when the
# ib-gw goes down? Not sure exactly how that's happening looking
# at the eventkit code above but we should probably handle it...
event_name: str
item: (
Trade
|tuple[Trade, Fill]
|CommissionReport
|IbPosition
|dict
)
async for event_name, item in trade_event_stream:
log.info(f'Relaying `{event_name}`:\n{pformat(item)}')
log.info(
f'Relaying {event_name!r}:\n'
f'{pformat(item)}\n'
)
match event_name:
case 'orderStatusEvent':
@ -1075,11 +1089,12 @@ async def deliver_trade_events(
trade: Trade = item
reqid: str = str(trade.order.orderId)
status: OrderStatus = trade.orderStatus
status_str: str = _statuses[status.status]
status_str: str = _statuses.get(
status.status,
'error',
)
remaining: float = status.remaining
if (
status_str == 'filled'
):
if status_str == 'filled':
fill: Fill = trade.fills[-1]
execu: Execution = fill.execution
@ -1110,6 +1125,12 @@ async def deliver_trade_events(
# all units were cleared.
status_str = 'closed'
elif status_str == 'error':
log.error(
f'IB reported error status for order ??\n'
f'{status.status!r}\n'
)
# skip duplicate filled updates - we get the deats
# from the execution details event
msg = BrokerdStatus(

View File

@ -83,7 +83,14 @@ def has_holiday(
'''
tz: str = con_deats.timeZoneId
exch: str = con_deats.contract.primaryExchange
cal: ExchangeCalendar = xcals.get_calendar(exch)
# XXX, ad-hoc handle any IB exchange which are non-std
# via lookup table..
std_exch: dict = {
'ARCA': 'ARCX',
}.get(exch, exch)
cal: ExchangeCalendar = xcals.get_calendar(std_exch)
end: datetime = period.end
# _start: datetime = period.start
# ?TODO, can rm ya?

View File

@ -58,7 +58,10 @@ from piker.brokers import NoData
from piker.accounting import (
MktPair,
)
from piker.log import get_logger
from piker.log import (
get_logger,
get_console_log,
)
from ..data._sharedmem import (
maybe_open_shm_array,
ShmArray,
@ -1368,6 +1371,10 @@ async def manage_history(
engages.
'''
get_console_log(
name=__name__,
level=loglevel,
)
# TODO: is there a way to make each shm file key
# actor-tree-discovery-addr unique so we avoid collisions
# when doing tests which also allocate shms for certain instruments