hist_backfill_fixes: solving conc issues in the tsdb backfiller #62
Open
goodboy
wants to merge 12 commits from
hist_backfill_fixes into main
pull from: hist_backfill_fixes
merge into: pikers:main
pikers:main
pikers:binance_nq_hotfix
pikers:pdbp_bump
pikers:dpi-font-auto-calc
pikers:macos_fixed_with_readme
pikers:macos_fixes_2025
pikers:add_visidata
pikers:service_mng_to_tractor
pikers:how_to_show_ur_pp
pikers:ib_2025_updates
pikers:providers_sync
pikers:port_to_latest_tractor
pikers:decimal_prices_thru_ems
pikers:rando_data_subsys_styling
pikers:subsys_refinery
pikers:bump_polars
pikers:brokers_refinery
pikers:simpler_gitea_merge_template
pikers:gitea_merge_template
pikers:nixround2_n_sway_testing
pikers:alt_tpts_for_perf
pikers:binance_api_3.1
pikers:accounting_refinery
pikers:no_symcache_no_problem
pikers:wayland_nix_py313
pikers:dpi_font_autocalc_fomo_bits
pikers:qt_w_graceful_SIGINT
pikers:stop_is_eoc
pikers:mp_fomo_polish
pikers:dpi_scaling_round2
pikers:max_pain_storage
pikers:testing_utils
pikers:max_pain_chart
pikers:max_pain_deribit
pikers:deribit_fix
pikers:gitea_feats
pikers:jsonrpc_err_in_rent
pikers:tsp_gaps
pikers:max_pain_chart_backup
pikers:subsys_refinery_BACKUP
pikers:max_pain_deribit_backup
pikers:add_ruff_linter
pikers:deribit_fix_backup
pikers:kucoin_and_binance_fix
pikers:uv_migration
pikers:kucoin_and_binance_BACKUP
pikers:go_httpx_no_unrelated_binance_stuff
pikers:go_httpx
pikers:go_httpx_orig_BACKUP
pikers:ib_refinements
pikers:fix_deribit_hist_queries_NEW
pikers:fix_deribit_hist_queries
pikers:prev_deribit_fix
pikers:nix_shell_env_fix
pikers:cherry_to_storage_pr
pikers:fix_deribit_hist_queries_BACKUP
pikers:kucoin_and_binance_fix_goodboyBACKUP
pikers:nix-headless-fix
pikers:go_httpx_binance
pikers:fix-binance-venues
pikers:pyqt6
pikers:distribute_dis
pikers:runtime_to_msgspec
pikers:nix-monkeys-fix
pikers:ib_py311_fixes
pikers:poetry2nix
pikers:account_tests
pikers:py311_ib_fix
pikers:master
pikers:basic_buy_bot
pikers:marketstore_disable_snappy
pikers:rekt_pps
pikers:py311
pikers:kucoin_backend
pikers:small_kucoin_fixes
pikers:pre_overruns_ctxcancelled
pikers:emit_clear_ticks_only_on_ts_change
pikers:binance_ws_ep_update
pikers:log_linearized_curve_overlays
pikers:xdotool_fixes
pikers:deribit_updates
pikers:storage_middleware_layer
pikers:service_subpkg
pikers:pps_precision_hotfixes
pikers:service_subpkg_backup
pikers:storage_cli
pikers:xdo_and_you
pikers:decimalization_take_2
pikers:backward_compat_trans_with_symbolinfo
pikers:explicit_write_pps_on_exit
pikers:backend_spec
pikers:paper_trade_improvements_rebase
pikers:loglevel_to_testpikerd
pikers:overlays_interaction_latency_tuning
pikers:kraken_deposits_fixes
pikers:l1_compaction
pikers:epoch_indexing_and_dataviz_layer
pikers:multichartz
pikers:axis_sticky_api
pikers:multi_symbol_input
pikers:update_qt_screen_info_script
pikers:fsps_and_flumes
pikers:epoch_index
pikers:pregraphics_formatters
pikers:multichartz_backup
pikers:samplerd_service
pikers:misc_brokerd_backend_repairs
pikers:pre_viz_calls
pikers:dark_clearing_improvements
pikers:dark_clearing_repairs
pikers:epoch_index_backup
pikers:agg_feedz
pikers:kraken_limits_fields
pikers:cz_post_ftx
pikers:kraken_pair_status
pikers:ib_contract_updates
pikers:pre_multifeed_hotfix
pikers:kraken_pair_updates
pikers:daemon_sockaddr_config
pikers:no_signal_pi_overlays
pikers:pre_multi_feedz
pikers:pg_exts_fork
pikers:ib_1m_hist
pikers:even_moar_kraken_order_fixes
pikers:ci_fix_tractor_testing
pikers:clears_table_events
pikers:offline_dark_clearing
pikers:multi_client_order_mgt
pikers:pin_tractor_main
pikers:history_view
pikers:tractor_core_port
pikers:kraken_fill_bugs
pikers:paper_clear_logics_fix
pikers:kraken_nameerr_fix
pikers:livenpaper
pikers:size_in_shm_token
pikers:deribit
pikers:asycvnc_pin_bump
pikers:live_n_paper
pikers:open_order_loading
pikers:doin_the_splits
pikers:dict_differ
pikers:msgpack_zombie
pikers:the_ems_flattening
pikers:kraken_ws_orders
pikers:kraken_userref_hackzin
pikers:pydantic_zombie
pikers:ib_pps_upgrade
pikers:multisympaper
pikers:ppu_history
pikers:basic_pp_audit
pikers:historical_breakeven_pp_price
pikers:ib_native_data_hack
pikers:pptables
pikers:ahab_you_bad_boi
pikers:fix_forex
pikers:fsp_shm_caching
pikers:paper_eng_msg_fixes
pikers:drop_pydantic
pikers:krakenwsbackup
pikers:dpbackup
pikers:null_last_quote_fix
pikers:ahab_hardkill
pikers:tractor_typed_msg_hackin
pikers:kraken_ledger_pps
pikers:ib_rt_pp_update_hotfix
pikers:notokeninwswrapper
pikers:pps_postmortem
pikers:lifo_pps_ib
pikers:310_plus
pikers:mxmn_from_m4
pikers:contain_mkts
pikers:slic_fix_v2
pikers:uppx_slice_fix
pikers:update_last_datums_in_view
pikers:ib_subpkg
pikers:flexxin
pikers:ib_checker_hackz
pikers:incremental_update_paths
pikers:ib_dedicated_data_client
pikers:dockerize_ib_gw
pikers:pre_flow
pikers:drop_pandas
pikers:no_ib_pps
pikers:trimeter_dep
pikers:l1_precision_fix
pikers:marketstore
pikers:no_orderid_in_error
pikers:incr_update_backup
pikers:big_data_lines
pikers:m4_corrections
pikers:offline_history_loading
pikers:drop_arrow_add_predulum
pikers:marketstore_backup
pikers:broker_bumpz
pikers:no_git_prot_w_pip
pikers:kraken_editorder
pikers:fqsns
pikers:kraken_cleaning
pikers:kraken_orders
pikers:only_draw_iv_for_ohlc
pikers:mkts_backup
pikers:pp_bar_fixes
pikers:async_hist_loading
pikers:kraken_gb
pikers:windows_fixes_yo
pikers:ib_mkt_closed
pikers:py3.10_support
pikers:gb_kraken_orders
pikers:dark_vlm
pikers:overlayed_dvlm
pikers:fsp_ui_mod
pikers:vlm_plotz
pikers:plotitem_overlays
pikers:misc_backend_fixes
pikers:dolla_vlm
pikers:fspd_cluster
pikers:misc_ib_updates
pikers:single_display_update_loop
pikers:basic_vlm_display
pikers:pane_sizing_fixes
pikers:tractor_clustering
pikers:msgpack_no_sets_allowed
pikers:tinas_unite
pikers:simpler_quote_throttle_logic
pikers:fast_step_curve
pikers:win_fixes
pikers:fsp_hotfixes
pikers:teardown_guesmost_via_cs
pikers:windows_testing_volume
pikers:fsp_drunken_alignment
pikers:vlm_plotz_backup
pikers:fsp_feeds
pikers:chart_mod_breakup
pikers:pause_feeds_on_sym_switch
pikers:brokers_config
pikers:ordermodepps_backup
pikers:readme_bump_zone
pikers:ci_on_forks
pikers:asyncify_input_modes
pikers:minimal_brokerd_trade_dialogues
pikers:wait_on_daemon_portals
pikers:backup_asyncify_input_modes
pikers:naive_feed_throttling
pikers:window_cuckery
pikers:msgspec_fixes
pikers:status_bar
pikers:ems_hotfixes
pikers:ems_to_bidir_streaming
pikers:web_utils
pikers:symbol_search
pikers:binance_syminfo_and_mintick
pikers:update_throttling
pikers:syseng_tweaks
pikers:ems_tweaks
pikers:py3.9
pikers:binance_aggtrades_and_ohlc_parsing
pikers:binance_backend
pikers:tractor_open_stream_from
pikers:feed_fixes
pikers:order_mode_finesse
pikers:cached_feeds
pikers:readme_bumpz
pikers:supervise
pikers:basic_orders
pikers:kraken_trades_data
pikers:basic_alerts
pikers:kraken_history
pikers:y_zoom
pikers:chart_trader
pikers:graphics_pixel_buffer
pikers:vwap_fsp
pikers:to_qpainterpath_and_beyond
pikers:tina_free_vwap
pikers:vwap_backup
pikers:bar_select
pikers:ib_backend
pikers:unleash_the_kraken
pikers:facepalm
pikers:marketstore_integration
pikers:its_happening
pikers:relicense_as_agplv3
pikers:questrade_candles
pikers:use_tractor_logging
pikers:questrade_conns
pikers:kivy_mainline_and_py3.8
12 Commits (main)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
ad299789db | Mv `markup_gaps()` to new `.tsp._annotate` mod | |
|
|
cd6bc105de |
Enable tracing back insert backfills
Namely insertion writes which over-fill the shm buffer past the latest tsdb sample via `.tsp._history.shm_push_in_between()`. Deats, - check earliest `to_push` timestamp and enter pause point if it's earlier then the tsdb's `backfill_until_dt` stamp. - requires actually passing the `backfill_until_dt: datetime` thru, * `get_null_segs()` * `maybe_fill_null_segments()` * `shm_push_in_between()` (obvi XD) |
|
|
|
a8e4e1b2c5 |
Tolerate various "bad data" cases in `markup_gaps()`
Namely such that when the previous-df-row by our shm-abs-'index' doesn't
exist we ignore certain cases which are likely due to borked-but-benign
samples written to the tsdb or rt shm buffers prior.
Particularly we now ignore,
- any `dt`/`prev_dt` values which are UNIX-epoch timestamped (val of 0).
- any row-is-first-row in the df; there is no previous.
- any missing previous datum by 'index', in which case we lookup the
`wdts` prior row and use that instead.
* this would indicate a missing sample for the time-step but we can
still detect a "gap" by looking at the prior row, by df-abs-index
`i`, and use its timestamp to determine the period/size of missing
samples (which need to likely still be retrieved).
* in this case i'm leaving in a pause-point for introspecting these
rarer cases when `--pdb` is passed via CLI.
Relatedly in the `piker store` CLI ep,
- add `--pdb` flag to `piker store`, pass it verbatim as `debug_mode`.
- when `times` has only a single row, don't calc a `period_s` median.
- only trace `null_segs` when in debug mode.
- always markup/dedupe gaps for `period_s==60`
|
|
|
|
caf2cc5a5b | ib: up API timeout default for remote host conns | |
|
|
d4b46e0eda | Fix `Qt6` types for new sub-namespaces | |
|
|
a1048c847b |
Add vlm-based "smart" OHLCV de-duping & bar validation
Using `claude`, add a `.tsp._dedupe_smart` module that attemps "smarter" duplicate bars by attempting to distinguish between erroneous bars partially written during concurrent backfill race conditions vs. **actual** data quality issues from historical providers. Problem: -------- Concurrent writes (live updates vs. backfilling) can result in create duplicate timestamped ohlcv vars with different values. Some potential scenarios include, - a market live feed is cancelled during live update resulting in the "last" datum being partially updated with all the ticks for the time step. - when the feed is rebooted during charting, the backfiller will not finalize this bar since rn it presumes it should only fill data for time steps not already in the tsdb storage. Our current naive `.unique()` approach obvi keeps the incomplete bar and a "smarter" approach is to compare the provider's final vlm amount vs. the maybe-cancelled tsdb's bar; a higher vlm value from the provider likely indicates the cancelled-during-live-write and **not** a datum discrepancy from said data provider. Analysis (with `claude`) of `zecusdt` data revealed: - 1000 duplicate timestamps - 999 identical bars (pure duplicates from 2022 backfill overlap) - 1 volume-monotonic conflict (live partial vs backfill complete) A soln from `claude` -> `tsp._dedupe_smart.dedupe_ohlcv_smart()` which: - sorts by vlm **before** deduplication and keep the most complete bar based on vlm monotonicity as well as the following OHLCV validation assumptions: * volume should always increase * high should be non-decreasing, * low should be non-increasing * open should be identical - Separates valid race conditions from provider data quality issues and reports and returns both dfs. Change summary by `claude`: - `.tsp._dedupe_smart`: new module with validation logic - `.tsp.__init__`: expose `dedupe_ohlcv_smart()` - `.storage.cli`: integrate smart dedupe, add logging for: * duplicate counts (identical vs monotonic races) * data quality violations (non-monotonic, invalid OHLC ranges) * warnings for provider data issues - Remove `assert not diff` (duplicates are valid now) Verified on `zecusdt`: correctly keeps index 3143645 (volume=287.777) over 3143644 (volume=140.299) for conflicting 2026-01-16 18:54 UTC bar. `claude`'s Summary of reasoning ------------------------------- - volume monotonicity is critical: a bar's volume only increases during its time window. - a backfilled bar should always have volume >= live updated. - violations indicate any of: * Provider data corruption * Non-OHLCV aggregation semantics * Timestamp misalignment (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code |
|
|
|
192fe0dc73 |
Add `pexpect`-based `pdbp`-REPL offline helper
Add a new `snippets/claude_debug_helper.py` to
provide a programmatic interface to `tractor.pause()` debugger
sessions for incremental data inspection matching the interactive UX
but able to be run by `claude` "offline" since it can't seem to feed
stdin (so it claims) to the `pdb` instance due to lack of ability to
allocate a tty internally.
The script-wrapper is based on `tractor`'s `tests/devx/` suite's use of
`pexpect` patterns for driving `pdbp` prompts and thus enables
automated-offline execution of REPL-inspection commands **without**
using incremental-realtime output capture (like a human would use it).
Features:
- `run_pdb_commands()`: batch command execution
- `InteractivePdbSession`: context manager for step-by-step REPL interaction
- `expect()` wrapper: timeout handling with buffer display
- Proper stdin/stdout handling via `pexpect.spawn()`
Example usage:
```python
from debug_helper import InteractivePdbSession
with InteractivePdbSession(
cmd='piker store ldshm zecusdt.usdtm.perp.binance'
) as session:
session.run('deduped.shape')
session.run('step_gaps.shape')
```
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
|
|
|
|
4bfdd388bb |
Fix polars 1.36.0 duration API
Polars tightened type safety for `.dt` accessor methods requiring `total_*` methods for duration types vs datetime component accessors like `day()` which now only work on datetime dtypes. `detect_time_gaps()` in `.tsp._anal` was calling `.dt.day()` on `dt_diff` column (a duration from `.diff()`) which throws `InvalidOperationError` on modern polars. Changes: - use f-string to add pluralization to map time unit strings to `total_<unit>s` form for the new duration API. - Handle singular/plural forms: 'day' -> 'days' -> 'total_days' - Ensure trailing 's' before applying 'total_' prefix Also updates inline comments explaining the polars type distinction between datetime components vs duration totals. Fixes `piker store ldshm` crashes on datasets with time gaps. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code |
|
|
|
534b13f755 | `.storage.__init__`: code styling updates | |
|
|
108646fdfb |
`.tsp._history`: drop `feed_is_live` syncing, another seg flag
The `await feed_is_live.wait()` is more or less pointless and would only cause slower startup afaig (as-far-as-i-grok) so i'm masking it here. This also removes the final `strict_exception_groups=False` use from the non-tests code base, flipping to the `tractor.trionics` collapser once and for all! |
|
|
|
d6d4fec666 | Woops, keep `np2pl` exposed from `.tsp` | |
|
|
14ac351a65 |
Factor to a new `.tsp._history` sub-mod
Cleaning out the `piker.tsp` pkg-mod to be only the (re)exports needed for `._anal`/`._history` refs-use elsewhere! |