gloomberb 0.17.5 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (922) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +2 -0
  3. package/package.json +8 -1
  4. package/patches/electrobun@1.18.1.patch +74 -0
  5. package/src/account/auth-model.ts +3 -2
  6. package/src/account/device-signin-dialog.tsx +38 -13
  7. package/src/account/device-signin.ts +2 -1
  8. package/src/account/upgrade-dialog.tsx +6 -2
  9. package/src/api-client/askg.ts +5 -3
  10. package/src/api-client/bank-figures.ts +73 -0
  11. package/src/api-client/chat.ts +9 -0
  12. package/src/api-client/commodity-balances.ts +77 -0
  13. package/src/api-client/credit-boards.ts +21 -1
  14. package/src/api-client/crypto-markets.ts +88 -1
  15. package/src/api-client/data.ts +135 -6
  16. package/src/api-client/debt-maturities.ts +18 -0
  17. package/src/api-client/earnings.ts +10 -0
  18. package/src/api-client/equity-screener.ts +3 -0
  19. package/src/api-client/errors.ts +13 -0
  20. package/src/api-client/fund-facts.ts +72 -0
  21. package/src/api-client/futures-curve.ts +26 -3
  22. package/src/api-client/geo.ts +11 -1
  23. package/src/api-client/index.ts +30 -2
  24. package/src/api-client/insider-signals.ts +159 -0
  25. package/src/api-client/market-discovery.ts +1 -1
  26. package/src/api-client/normalizers.ts +2 -0
  27. package/src/api-client/paths.ts +28 -0
  28. package/src/api-client/request.ts +11 -3
  29. package/src/api-client/research-activity.ts +15 -8
  30. package/src/api-client/socket.ts +16 -3
  31. package/src/api-client/supply-chain-graph.ts +2 -2
  32. package/src/api-client/supply-chain.ts +8 -0
  33. package/src/api-client/tape.ts +12 -0
  34. package/src/api-client/types.ts +91 -3
  35. package/src/api-client/upgrade-experiment.ts +4 -3
  36. package/src/api-client/wall-experiments.ts +5 -3
  37. package/src/api-client/wall-summary.ts +3 -1
  38. package/src/api-client/web-experiments.ts +5 -2
  39. package/src/api-client/yield-curves.ts +17 -0
  40. package/src/app/command-bar-intro.ts +38 -0
  41. package/src/app/keybindings/actions.ts +1 -1
  42. package/src/app/pane-runtime/pane-template-runtime.ts +35 -7
  43. package/src/app/pane-runtime/plugin-bindings.ts +4 -0
  44. package/src/app/pane-runtime/ticker-open-runtime.ts +4 -14
  45. package/src/app/pane-runtime/ticker-open-target.ts +31 -0
  46. package/src/app/runtime/broker-import.ts +23 -21
  47. package/src/app/runtime/desktop-deeplink.ts +3 -4
  48. package/src/app/runtime/plugin-bindings.ts +16 -9
  49. package/src/app/runtime/startup.ts +3 -4
  50. package/src/app/runtime/ticker-refresh.ts +13 -12
  51. package/src/app/runtime/update.ts +17 -3
  52. package/src/architecture/core-builtin-allowlist.json +2 -13
  53. package/src/architecture/silent-catch-allowlist.json +3 -0
  54. package/src/architecture/ui-literals-allowlist.json +186 -0
  55. package/src/architecture/ui-tokens-allowlist.json +40 -0
  56. package/src/ask-gloom/pane-context.ts +3 -1
  57. package/src/brokers/broker-portfolio-sync.ts +66 -0
  58. package/src/brokers/signed-in/catalog.ts +2 -1
  59. package/src/brokers/signed-in/client.ts +7 -2
  60. package/src/brokers/signed-in/sign-in-dialog.tsx +120 -26
  61. package/src/brokers/signed-in/sign-in.ts +22 -20
  62. package/src/brokers/sync-broker-instance.ts +77 -42
  63. package/src/capabilities/chart-series.ts +2 -0
  64. package/src/capabilities/registry.ts +1 -3
  65. package/src/cli/bank-section.ts +147 -0
  66. package/src/cli/base-converter.ts +5 -2
  67. package/src/cli/board-coins.ts +70 -0
  68. package/src/cli/commands/fred-series.ts +90 -0
  69. package/src/cli/commands/market.ts +434 -96
  70. package/src/cli/commands/news-search.ts +35 -2
  71. package/src/cli/commands/options-chain.ts +25 -9
  72. package/src/cli/commands/options-leaps.ts +3 -3
  73. package/src/cli/commands/overview.ts +130 -40
  74. package/src/cli/commands/plugins.ts +1 -0
  75. package/src/cli/commands/search.ts +87 -24
  76. package/src/cli/commands/system.ts +5 -2
  77. package/src/cli/commands/ticker.ts +361 -64
  78. package/src/cli/context.ts +15 -1
  79. package/src/cli/desktop-pane-shot.ts +11 -3
  80. package/src/cli/earnings-calendar.ts +2 -1
  81. package/src/cli/errors.ts +25 -2
  82. package/src/cli/export-source.ts +18 -3
  83. package/src/cli/fx-pair.ts +77 -0
  84. package/src/cli/glossary.ts +196 -14
  85. package/src/cli/history-rows.ts +84 -19
  86. package/src/cli/index-roots.ts +26 -0
  87. package/src/cli/index.ts +57 -20
  88. package/src/cli/known-gaps.ts +156 -22
  89. package/src/cli/listing-arg.ts +217 -150
  90. package/src/cli/listing-suggestion.ts +7 -23
  91. package/src/cli/name-entries.ts +76 -0
  92. package/src/cli/not-a-ticker.ts +15 -6
  93. package/src/cli/pane-functions/access-gate.ts +22 -0
  94. package/src/cli/pane-functions/capabilities.ts +62 -4
  95. package/src/cli/pane-functions/catalog.ts +144 -39
  96. package/src/cli/pane-functions/data.ts +6 -5
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +3 -3
  99. package/src/cli/pane-functions/freshness.ts +93 -17
  100. package/src/cli/pane-functions/function-help.ts +20 -17
  101. package/src/cli/pane-functions/headless.ts +187 -40
  102. package/src/cli/pane-functions/index.ts +126 -12
  103. package/src/cli/pane-functions/options.ts +17 -3
  104. package/src/cli/pane-functions/report-notices.ts +17 -3
  105. package/src/cli/pane-functions/resolver.ts +74 -18
  106. package/src/cli/pane-functions/screenshot.ts +126 -23
  107. package/src/cli/pane-functions/shot-options.ts +68 -0
  108. package/src/cli/perpetual-contract.ts +3 -1
  109. package/src/cli/report-tables.ts +21 -6
  110. package/src/cli/result.ts +2 -0
  111. package/src/cli/series-search.ts +6 -1
  112. package/src/cli/staged-tickers.ts +5 -0
  113. package/src/cli/statement-filings.ts +261 -0
  114. package/src/cli/symbol-args.ts +47 -8
  115. package/src/cli/symbol-list.ts +9 -2
  116. package/src/cli/symbol-rows.ts +269 -29
  117. package/src/cli/ticker-resolution.ts +148 -35
  118. package/src/cli/treasury-yields.ts +86 -0
  119. package/src/cli/types.ts +3 -0
  120. package/src/cli/uncovered-instrument.ts +20 -0
  121. package/src/cli/unknown-command.ts +18 -0
  122. package/src/components/chart/composite/axis-overlays.tsx +16 -9
  123. package/src/components/chart/composite/composite-chart.tsx +163 -23
  124. package/src/components/chart/composite/downsample.ts +19 -3
  125. package/src/components/chart/composite/format.ts +13 -0
  126. package/src/components/chart/composite/legend.tsx +161 -68
  127. package/src/components/chart/composite/panel-bitmap.ts +8 -2
  128. package/src/components/chart/composite/panel-labels.ts +38 -0
  129. package/src/components/chart/composite/panel-series.ts +1 -0
  130. package/src/components/chart/composite/panel-surface.tsx +28 -10
  131. package/src/components/chart/composite/price-axis-labels.tsx +16 -3
  132. package/src/components/chart/composite/scene.ts +60 -2
  133. package/src/components/chart/composite/series-axis-tags.tsx +67 -0
  134. package/src/components/chart/composite/toolbar.tsx +12 -7
  135. package/src/components/chart/composite/tools.ts +2 -2
  136. package/src/components/chart/composite/types.ts +34 -0
  137. package/src/components/chart/composite/use-composite-chart-keyboard.ts +28 -1
  138. package/src/components/chart/core/view-reset.ts +46 -0
  139. package/src/components/chart/curve/curve-surface.tsx +1 -1
  140. package/src/components/chart/static/series.ts +39 -0
  141. package/src/components/chart/static/trail-chart-surface.tsx +2 -1
  142. package/src/components/command-bar/commands/collection-list.ts +45 -15
  143. package/src/components/command-bar/commands/collection.ts +11 -4
  144. package/src/components/command-bar/commands/direct/index.ts +1 -1
  145. package/src/components/command-bar/commands/registry.ts +2 -2
  146. package/src/components/command-bar/list/badge.ts +4 -3
  147. package/src/components/command-bar/list/model.ts +12 -0
  148. package/src/components/command-bar/list/view.tsx +1 -1
  149. package/src/components/command-bar/pane-templates/workflow.ts +5 -0
  150. package/src/components/command-bar/panel/index.tsx +19 -8
  151. package/src/components/command-bar/panel/native-surface.ts +6 -4
  152. package/src/components/command-bar/panel/prompt-example.ts +22 -0
  153. package/src/components/command-bar/routes/root/command-items.ts +1 -1
  154. package/src/components/command-bar/routes/root/pick-prefetch.ts +38 -0
  155. package/src/components/command-bar/routes/root/provider-search.ts +9 -9
  156. package/src/components/command-bar/routes/root/results.ts +13 -0
  157. package/src/components/command-bar/routes/root/runtime.ts +3 -0
  158. package/src/components/command-bar/routes/root/shortcut-feedback.ts +3 -1
  159. package/src/components/command-bar/routes/root/shortcut-items.ts +1 -1
  160. package/src/components/command-bar/routes/root/start-here.ts +90 -0
  161. package/src/components/command-bar/routes/ticker-search/actions.ts +34 -0
  162. package/src/components/command-bar/routes/ticker-search/results.ts +42 -3
  163. package/src/components/command-bar/routes/ticker-search/route.ts +3 -10
  164. package/src/components/command-bar/surface/index.tsx +5 -0
  165. package/src/components/command-bar/theme-picker.tsx +3 -1
  166. package/src/components/command-bar/workflow/builtin.ts +5 -1
  167. package/src/components/command-bar/workflow/collection-actions.ts +23 -13
  168. package/src/components/command-bar/workflow/ops.ts +25 -3
  169. package/src/components/command-bar/workflow/pane-reuse.ts +3 -2
  170. package/src/{plugins/builtin/portfolio-list/command-bar.ts → components/command-bar/workflow/portfolio-position.ts} +42 -9
  171. package/src/components/command-bar/workflow/tickers.ts +7 -5
  172. package/src/components/feedback-dialog.tsx +1 -1
  173. package/src/components/form-modal/broker-step.tsx +7 -63
  174. package/src/components/form-modal/content.tsx +7 -2
  175. package/src/components/form-modal/field-row.tsx +6 -8
  176. package/src/components/form-modal/host.tsx +3 -3
  177. package/src/components/form-modal/model.ts +3 -0
  178. package/src/components/form-modal/routes.ts +17 -2
  179. package/src/components/index.ts +6 -6
  180. package/src/components/input-search-bar.tsx +43 -6
  181. package/src/components/layout/detached-pane-shell.tsx +0 -1
  182. package/src/components/layout/floating-pane.tsx +0 -1
  183. package/src/components/layout/header.tsx +8 -7
  184. package/src/components/layout/pane/content.tsx +11 -8
  185. package/src/components/layout/pane/footer/index.tsx +7 -4
  186. package/src/components/layout/pane/footer/model.ts +28 -2
  187. package/src/components/layout/pane/header.tsx +9 -19
  188. package/src/components/layout/pane/index.tsx +0 -1
  189. package/src/components/layout/pane/instrument-coverage-gate.tsx +57 -0
  190. package/src/components/layout/pane/pane-tabs.tsx +4 -3
  191. package/src/components/layout/pane/sizing.ts +9 -0
  192. package/src/components/layout/pane/ticker-fate-gate.tsx +62 -0
  193. package/src/components/layout/shell/pane/capture.ts +44 -20
  194. package/src/components/layout/status-bar.tsx +3 -6
  195. package/src/components/markdown-text.tsx +17 -2
  196. package/src/components/market-board/index.tsx +19 -8
  197. package/src/components/metric-treemap/heat-surface.tsx +2 -7
  198. package/src/components/onboarding/account-step/qr-panel.tsx +5 -2
  199. package/src/components/onboarding/onboarding-frame.tsx +24 -21
  200. package/src/components/onboarding/portfolio-step/positions-panel.tsx +20 -10
  201. package/src/components/onboarding/wizard-model.ts +1 -1
  202. package/src/components/onboarding/wizard-positions.ts +56 -19
  203. package/src/components/pane-settings-dialog/desktop.tsx +12 -50
  204. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -1
  205. package/src/components/price-performance.tsx +18 -2
  206. package/src/components/reader/article-reader.tsx +11 -10
  207. package/src/components/reader/detail-reader.tsx +9 -5
  208. package/src/components/reader/reader-text.tsx +51 -24
  209. package/src/components/sign-in-code-panel.tsx +129 -75
  210. package/src/components/ticker/badge/format.ts +64 -15
  211. package/src/components/ticker/badge/index.tsx +33 -11
  212. package/src/components/ticker/badge/list.tsx +4 -3
  213. package/src/components/ticker/badge/text.tsx +2 -2
  214. package/src/components/ticker/list-table-view.tsx +8 -1
  215. package/src/components/ui/action-row.tsx +5 -2
  216. package/src/components/ui/audio-player.tsx +70 -0
  217. package/src/components/ui/card.tsx +75 -0
  218. package/src/components/ui/data-table/index.tsx +4 -2
  219. package/src/components/ui/data-table/opentui/index.tsx +61 -20
  220. package/src/components/ui/data-table/opentui/model.ts +104 -0
  221. package/src/components/ui/data-table/types.ts +11 -0
  222. package/src/components/ui/detail-scroll-body.tsx +1 -1
  223. package/src/components/ui/dialog-actions.tsx +1 -21
  224. package/src/components/ui/display.tsx +13 -5
  225. package/src/components/ui/external-link.tsx +4 -2
  226. package/src/components/ui/fields.tsx +12 -0
  227. package/src/components/ui/figure.tsx +5 -3
  228. package/src/components/ui/frame.tsx +40 -6
  229. package/src/components/ui/icon.tsx +4 -0
  230. package/src/components/ui/index.ts +4 -1
  231. package/src/components/ui/inline-quick-add.tsx +4 -1
  232. package/src/components/ui/list-view.tsx +8 -0
  233. package/src/components/ui/prose.tsx +97 -25
  234. package/src/components/ui/query-bar-keys.tsx +32 -6
  235. package/src/components/ui/query-bar.tsx +35 -4
  236. package/src/components/ui/quote.ts +42 -0
  237. package/src/components/ui/range-track.tsx +15 -2
  238. package/src/components/ui/reveal-in-scroll-box.ts +21 -3
  239. package/src/components/ui/select-button.tsx +38 -3
  240. package/src/components/ui/status.tsx +73 -4
  241. package/src/components/ui/table-layout.ts +20 -0
  242. package/src/components/ui/windowed-list.tsx +27 -0
  243. package/src/components/use-pinned-moment.ts +19 -0
  244. package/src/core/app-runtime.ts +2 -2
  245. package/src/core/state/app/instrument.ts +18 -1
  246. package/src/core/state/app/layout.ts +6 -0
  247. package/src/core/state/app/state.ts +14 -2
  248. package/src/data/cached-query.ts +1 -1
  249. package/src/data/config/chart-settings.ts +3 -1
  250. package/src/data/config/home.ts +4 -1
  251. package/src/data/config/store/node.ts +9 -4
  252. package/src/data/config/store/normalize.ts +9 -0
  253. package/src/data/json-storage.ts +6 -3
  254. package/src/data/json-ticker-repository.ts +3 -1
  255. package/src/data/plugin-cache.ts +5 -1
  256. package/src/data/sqlite/json.ts +3 -1
  257. package/src/data/ticker-repository.ts +5 -2
  258. package/src/docs/snapshot.json +248 -5
  259. package/src/feedback/diagnostics.ts +2 -6
  260. package/src/i18n/es.ts +86 -6
  261. package/src/i18n/index.ts +3 -9
  262. package/src/i18n/ja.ts +86 -6
  263. package/src/i18n/ko.ts +86 -6
  264. package/src/i18n/zh-cn.ts +86 -6
  265. package/src/i18n/zh-tw.ts +86 -6
  266. package/src/layout-marketplace/cloud.ts +16 -5
  267. package/src/layout-marketplace/gallery-desktop.tsx +8 -4
  268. package/src/layout-marketplace/gallery.tsx +4 -4
  269. package/src/layout-marketplace/linked-sync.ts +9 -3
  270. package/src/layout-marketplace/linked.ts +24 -3
  271. package/src/layout-marketplace/model.ts +39 -4
  272. package/src/market-data/bars-per-year.ts +43 -0
  273. package/src/market-data/bond-funds.ts +85 -0
  274. package/src/market-data/coordinator/auxiliary.ts +5 -2
  275. package/src/market-data/coordinator/index.ts +39 -5
  276. package/src/market-data/futures-contract.ts +155 -5
  277. package/src/market-data/hooks.tsx +77 -12
  278. package/src/market-data/market/bar-period.ts +107 -0
  279. package/src/market-data/market/format.ts +18 -14
  280. package/src/market-data/market/freshness.ts +29 -4
  281. package/src/market-data/market/index-level.ts +51 -0
  282. package/src/market-data/market/status.ts +152 -13
  283. package/src/market-data/model-dividend-yield.ts +117 -0
  284. package/src/market-data/quotes/freshness.ts +30 -1
  285. package/src/{plugins/builtin/portfolio-list → market-data/quotes}/live-valuation.ts +52 -6
  286. package/src/market-data/quotes/regular-session-valuation.ts +32 -1
  287. package/src/market-data/realized-volatility.ts +16 -7
  288. package/src/market-data/tax-equivalent.ts +344 -0
  289. package/src/news/aggregator.ts +4 -2
  290. package/src/notifications/notification-log.ts +5 -3
  291. package/src/plugins/auto-update-node.ts +1 -0
  292. package/src/plugins/builtin/account-management/footer.ts +1 -1
  293. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  294. package/src/plugins/builtin/account-management/model.ts +1 -0
  295. package/src/plugins/builtin/account-management/pane.tsx +71 -19
  296. package/src/plugins/builtin/account-management/trial-cancel.ts +40 -0
  297. package/src/plugins/builtin/alerts/cli.ts +7 -18
  298. package/src/plugins/builtin/alerts/constants.ts +8 -0
  299. package/src/plugins/builtin/alerts/event-rows.ts +16 -0
  300. package/src/plugins/builtin/alerts/events-pane.tsx +2 -14
  301. package/src/plugins/builtin/alerts/headless.ts +182 -0
  302. package/src/plugins/builtin/alerts/index.tsx +3 -0
  303. package/src/plugins/builtin/alerts/pane.tsx +1 -7
  304. package/src/plugins/builtin/alerts/storage.ts +17 -1
  305. package/src/plugins/builtin/analytics/index.tsx +6 -1
  306. package/src/plugins/builtin/analytics/metrics.ts +55 -13
  307. package/src/plugins/builtin/analytics/risk-headless.ts +26 -7
  308. package/src/plugins/builtin/analytics/risk-math.ts +83 -0
  309. package/src/plugins/builtin/analytics/risk-model.ts +171 -19
  310. package/src/plugins/builtin/analytics/risk-pane.tsx +17 -12
  311. package/src/plugins/builtin/analytics/sector-model.ts +14 -3
  312. package/src/plugins/builtin/awards/headless.ts +6 -5
  313. package/src/plugins/builtin/awards/index.tsx +1 -1
  314. package/src/plugins/builtin/backtest/client.ts +38 -8
  315. package/src/plugins/builtin/backtest/engine.ts +25 -13
  316. package/src/plugins/builtin/backtest/export.ts +27 -0
  317. package/src/plugins/builtin/backtest/format.ts +19 -3
  318. package/src/plugins/builtin/backtest/headless.ts +42 -28
  319. package/src/plugins/builtin/backtest/index.tsx +3 -0
  320. package/src/plugins/builtin/backtest/pane.tsx +39 -10
  321. package/src/plugins/builtin/backtest/report.ts +160 -0
  322. package/src/plugins/builtin/backtest/rules.ts +2 -0
  323. package/src/plugins/builtin/backtest/window.ts +112 -0
  324. package/src/plugins/builtin/bond-calculator/headless.ts +3 -2
  325. package/src/plugins/builtin/broker-manager/add-flow.tsx +4 -4
  326. package/src/plugins/builtin/builtin-plugin-meta.ts +0 -1
  327. package/src/plugins/builtin/catalysts/headless.ts +24 -13
  328. package/src/plugins/builtin/catalysts/index.tsx +4 -2
  329. package/src/plugins/builtin/catalysts/model.ts +18 -1
  330. package/src/plugins/builtin/catalysts/pane.tsx +2 -2
  331. package/src/plugins/builtin/cds/client.ts +28 -5
  332. package/src/plugins/builtin/cds/headless.ts +183 -31
  333. package/src/plugins/builtin/cds/index.tsx +1 -1
  334. package/src/plugins/builtin/cds/model.ts +229 -53
  335. package/src/plugins/builtin/cds/pane.tsx +82 -26
  336. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -1
  337. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +39 -1
  338. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +77 -0
  339. package/src/plugins/builtin/chart-composer/chart-spec.ts +15 -0
  340. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +22 -2
  341. package/src/plugins/builtin/chart-composer/editor/controller.ts +14 -10
  342. package/src/plugins/builtin/chart-composer/editor/desktop-view.tsx +2 -2
  343. package/src/plugins/builtin/chart-composer/formula.ts +233 -0
  344. package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -2
  345. package/src/plugins/builtin/chart-composer/headless.ts +117 -15
  346. package/src/plugins/builtin/chart-composer/index.tsx +73 -15
  347. package/src/plugins/builtin/chart-composer/pane.tsx +86 -23
  348. package/src/plugins/builtin/chart-composer/presets.ts +165 -8
  349. package/src/plugins/builtin/chart-composer/quick-add.tsx +9 -2
  350. package/src/plugins/builtin/chart-composer/series-catalog.ts +85 -16
  351. package/src/plugins/builtin/chart-composer/series-expression.ts +10 -8
  352. package/src/plugins/builtin/chart-composer/series-listings.ts +178 -0
  353. package/src/plugins/builtin/chart-composer/session-range.ts +87 -0
  354. package/src/plugins/builtin/chart-composer/settings.ts +16 -4
  355. package/src/plugins/builtin/chart-composer/studies.ts +1 -1
  356. package/src/plugins/builtin/chat/attachments/desktop.tsx +4 -1
  357. package/src/plugins/builtin/chat/content/channel-navigation.ts +17 -6
  358. package/src/plugins/builtin/chat/content/composer-runtime.ts +49 -14
  359. package/src/plugins/builtin/chat/content/composer.tsx +22 -1
  360. package/src/plugins/builtin/chat/content/index.tsx +47 -10
  361. package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -0
  362. package/src/plugins/builtin/chat/content/mentions.ts +50 -21
  363. package/src/plugins/builtin/chat/content/scroll.ts +12 -5
  364. package/src/plugins/builtin/chat/content/shortcuts.ts +32 -13
  365. package/src/plugins/builtin/chat/content/snapshot.ts +40 -6
  366. package/src/plugins/builtin/chat/content/transcript.tsx +48 -37
  367. package/src/plugins/builtin/chat/content/whole-message-copy.ts +44 -2
  368. package/src/plugins/builtin/chat/controller/index.ts +68 -17
  369. package/src/plugins/builtin/chat/controller/mention-candidates.ts +104 -0
  370. package/src/plugins/builtin/chat/controller/realtime.ts +9 -0
  371. package/src/plugins/builtin/chat/controller/state.ts +10 -0
  372. package/src/plugins/builtin/chat/controller/view.ts +2 -0
  373. package/src/plugins/builtin/chat/conversation-recency.ts +73 -0
  374. package/src/plugins/builtin/chat/conversations.ts +12 -5
  375. package/src/plugins/builtin/chat/ghost-user.ts +11 -3
  376. package/src/plugins/builtin/chat/layout.ts +25 -5
  377. package/src/plugins/builtin/chat/message/desktop.tsx +15 -5
  378. package/src/plugins/builtin/chat/message/header.tsx +26 -4
  379. package/src/plugins/builtin/chat/message/pane-chip.tsx +131 -35
  380. package/src/plugins/builtin/chat/message/render-state.ts +28 -1
  381. package/src/plugins/builtin/chat/message/terminal.tsx +9 -3
  382. package/src/plugins/builtin/chat/pane-links/composer.ts +87 -0
  383. package/src/plugins/builtin/chat/pane-links/model.ts +1 -1
  384. package/src/plugins/builtin/chat/share/flow.tsx +9 -73
  385. package/src/plugins/builtin/chat/sidebar-rows.ts +18 -5
  386. package/src/plugins/builtin/chat/sidebar.tsx +6 -1
  387. package/src/plugins/builtin/cloud/askg/controller.ts +5 -3
  388. package/src/plugins/builtin/cloud/askg/executor.ts +3 -1
  389. package/src/plugins/builtin/cloud/askg/lock-note.ts +16 -0
  390. package/src/plugins/builtin/cloud/askg/manifest.ts +4 -3
  391. package/src/plugins/builtin/cloud/askg/pane.tsx +6 -2
  392. package/src/plugins/builtin/cloud/auth-actions.tsx +4 -2
  393. package/src/plugins/builtin/cloud/company-picker.tsx +21 -26
  394. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +5 -3
  395. package/src/plugins/builtin/cloud/plugin.tsx +2 -0
  396. package/src/plugins/builtin/cloud/team/module.tsx +5 -1
  397. package/src/plugins/builtin/cloud/team/pane.tsx +11 -4
  398. package/src/plugins/builtin/cloud/team/views.ts +11 -4
  399. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +9 -4
  400. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +16 -5
  401. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +3 -2
  402. package/src/plugins/builtin/cloud/thesis/detail.tsx +2 -1
  403. package/src/plugins/builtin/cloud/thesis/exposure.ts +3 -0
  404. package/src/plugins/builtin/cloud/thesis/prompts.tsx +3 -2
  405. package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +2 -1
  406. package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +2 -1
  407. package/src/plugins/builtin/cloud/verification-status-widget.tsx +2 -1
  408. package/src/plugins/builtin/commodities-energy/index.tsx +31 -9
  409. package/src/plugins/builtin/commodities-energy/view-state.ts +11 -0
  410. package/src/plugins/builtin/commodity-balances/client.ts +51 -193
  411. package/src/plugins/builtin/commodity-balances/headless.ts +10 -3
  412. package/src/plugins/builtin/commodity-balances/model.ts +5 -180
  413. package/src/plugins/builtin/commodity-balances/pane.tsx +3 -0
  414. package/src/plugins/builtin/company-attention/headless.ts +15 -7
  415. package/src/plugins/builtin/company-attention/index.tsx +1 -1
  416. package/src/plugins/builtin/company-attention/model.ts +49 -4
  417. package/src/plugins/builtin/company-attention/pane.tsx +11 -9
  418. package/src/plugins/builtin/company-kpis/headless.ts +4 -3
  419. package/src/plugins/builtin/company-kpis/index.tsx +2 -2
  420. package/src/plugins/builtin/company-kpis/pane.tsx +9 -3
  421. package/src/plugins/builtin/congress-trades/headless.ts +23 -2
  422. package/src/plugins/builtin/correlation/relationship/pane.tsx +18 -46
  423. package/src/plugins/builtin/cot/headless.ts +5 -2
  424. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +41 -13
  425. package/src/plugins/builtin/credit-boards/client.ts +9 -2
  426. package/src/plugins/builtin/credit-boards/headless.ts +93 -27
  427. package/src/plugins/builtin/credit-boards/index.tsx +15 -4
  428. package/src/plugins/builtin/credit-boards/model.ts +105 -6
  429. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +14 -3
  430. package/src/plugins/builtin/credit-documents/detail.tsx +2 -1
  431. package/src/plugins/builtin/credit-documents/index.tsx +3 -0
  432. package/src/plugins/builtin/credit-documents/model.ts +3 -10
  433. package/src/plugins/builtin/crypto-board/client.ts +152 -2
  434. package/src/plugins/builtin/crypto-board/headless.ts +138 -19
  435. package/src/plugins/builtin/crypto-board/index.tsx +5 -3
  436. package/src/plugins/builtin/crypto-board/model.ts +210 -12
  437. package/src/plugins/builtin/crypto-board/pane.tsx +148 -9
  438. package/src/plugins/builtin/crypto-board/series.ts +52 -1
  439. package/src/plugins/builtin/crypto-board/supply.ts +123 -0
  440. package/src/plugins/builtin/custom-view/index.tsx +1 -1
  441. package/src/plugins/builtin/custom-view/loader.ts +57 -7
  442. package/src/plugins/builtin/custom-view/sources.ts +146 -0
  443. package/src/plugins/builtin/custom-view/view-spec.ts +37 -1
  444. package/src/plugins/builtin/debt-maturities/client.ts +54 -1
  445. package/src/plugins/builtin/debt-maturities/headless.ts +27 -3
  446. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  447. package/src/plugins/builtin/debt-maturities/model.ts +58 -13
  448. package/src/plugins/builtin/debt-maturities/pane.tsx +47 -7
  449. package/src/plugins/builtin/dividend-yield/client.ts +42 -36
  450. package/src/plugins/builtin/dividend-yield/headless.ts +113 -18
  451. package/src/plugins/builtin/dividend-yield/index.tsx +5 -2
  452. package/src/plugins/builtin/dividend-yield/pane.tsx +37 -13
  453. package/src/plugins/builtin/dividend-yield/provider-client.ts +7 -3
  454. package/src/plugins/builtin/dividend-yield/ranking.ts +187 -0
  455. package/src/plugins/builtin/dividend-yield/reference-price.ts +28 -5
  456. package/src/plugins/builtin/dividend-yield/types.ts +6 -1
  457. package/src/plugins/builtin/dividend-yield/view.ts +1 -1
  458. package/src/plugins/builtin/docs/blocks.tsx +54 -8
  459. package/src/plugins/builtin/docs/pane.tsx +8 -13
  460. package/src/plugins/builtin/earnings/board-model.ts +33 -3
  461. package/src/plugins/builtin/earnings/board-table.ts +59 -14
  462. package/src/plugins/builtin/earnings/board.tsx +36 -3
  463. package/src/plugins/builtin/earnings/headless.ts +27 -7
  464. package/src/plugins/builtin/earnings/history-model.ts +9 -1
  465. package/src/plugins/builtin/earnings/history-table.ts +16 -5
  466. package/src/plugins/builtin/earnings/history.tsx +40 -10
  467. package/src/plugins/builtin/earnings/index.tsx +3 -1
  468. package/src/plugins/builtin/earnings/no-earnings.ts +52 -0
  469. package/src/plugins/builtin/earnings-calls/data.ts +51 -0
  470. package/src/plugins/builtin/earnings-calls/headless.ts +7 -0
  471. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  472. package/src/plugins/builtin/earnings-calls/model.ts +97 -0
  473. package/src/plugins/builtin/earnings-calls/pane.tsx +107 -7
  474. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +140 -22
  475. package/src/plugins/builtin/earnings-calls/use-call-playback.ts +194 -0
  476. package/src/plugins/builtin/econ/calendar-model.ts +22 -0
  477. package/src/plugins/builtin/econ/calendar-source.ts +35 -0
  478. package/src/plugins/builtin/econ/index.tsx +40 -8
  479. package/src/plugins/builtin/econ-statistics/defs.ts +7 -0
  480. package/src/plugins/builtin/econ-statistics/detail.tsx +11 -1
  481. package/src/plugins/builtin/econ-statistics/headless.ts +31 -5
  482. package/src/plugins/builtin/econ-statistics/pane.tsx +5 -3
  483. package/src/plugins/builtin/econ-statistics/stats.ts +10 -0
  484. package/src/plugins/builtin/econ-statistics/view.ts +23 -0
  485. package/src/plugins/builtin/equity-screener/client.ts +1 -1
  486. package/src/plugins/builtin/equity-screener/model.ts +46 -4
  487. package/src/plugins/builtin/equity-screener/pane.tsx +3 -0
  488. package/src/plugins/builtin/estimate-revisions/client.ts +32 -22
  489. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  490. package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
  491. package/src/plugins/builtin/estimate-revisions/pane.tsx +5 -3
  492. package/src/plugins/builtin/executives/index.tsx +1 -0
  493. package/src/plugins/builtin/exposure/editor.tsx +3 -3
  494. package/src/plugins/builtin/fear-greed/index.tsx +9 -0
  495. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  496. package/src/plugins/builtin/futures/index.tsx +2 -2
  497. package/src/plugins/builtin/futures/model.ts +39 -25
  498. package/src/plugins/builtin/futures/series.ts +38 -1
  499. package/src/plugins/builtin/futures/table.tsx +1 -1
  500. package/src/plugins/builtin/futures/use-board-terms.ts +2 -2
  501. package/src/plugins/builtin/futures-curve/client.ts +4 -4
  502. package/src/plugins/builtin/futures-curve/headless.ts +24 -4
  503. package/src/plugins/builtin/futures-curve/index.tsx +2 -2
  504. package/src/plugins/builtin/futures-curve/model.ts +50 -9
  505. package/src/plugins/builtin/futures-curve/pane.tsx +14 -10
  506. package/src/plugins/builtin/help/index.tsx +55 -8
  507. package/src/plugins/builtin/help/shortcut-table.tsx +15 -2
  508. package/src/plugins/builtin/holders/headless.ts +12 -0
  509. package/src/plugins/builtin/insider/headless.ts +345 -5
  510. package/src/plugins/builtin/insider/index.tsx +304 -36
  511. package/src/plugins/builtin/insider/insiders.tsx +224 -0
  512. package/src/plugins/builtin/insider/signals-cells.tsx +52 -0
  513. package/src/plugins/builtin/insider/signals-client.ts +193 -0
  514. package/src/plugins/builtin/insider/signals-model.ts +718 -0
  515. package/src/plugins/builtin/insider/signals.tsx +376 -0
  516. package/src/plugins/builtin/ipo-calendar/headless.ts +17 -7
  517. package/src/plugins/builtin/ipo-calendar/index.tsx +23 -3
  518. package/src/plugins/builtin/ipo-calendar/model.ts +84 -36
  519. package/src/plugins/builtin/ipo-calendar/pane.tsx +20 -8
  520. package/src/plugins/builtin/iv-history/client.ts +41 -2
  521. package/src/plugins/builtin/iv-history/headless.ts +26 -16
  522. package/src/plugins/builtin/iv-history/screen-pane.tsx +25 -7
  523. package/src/plugins/builtin/jobs/headless.ts +1 -0
  524. package/src/plugins/builtin/jobs/index.tsx +1 -0
  525. package/src/plugins/builtin/jodi/client.ts +42 -205
  526. package/src/plugins/builtin/jodi/headless.ts +15 -4
  527. package/src/plugins/builtin/jodi/model.ts +18 -43
  528. package/src/plugins/builtin/jodi/pane.tsx +5 -0
  529. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  530. package/src/plugins/builtin/kelly-sizer/portfolio.ts +1 -1
  531. package/src/plugins/builtin/market-heatmap/headless.ts +1 -0
  532. package/src/plugins/builtin/market-heatmap/portfolio.ts +3 -1
  533. package/src/plugins/builtin/market-movers/client.ts +32 -6
  534. package/src/plugins/builtin/market-movers/headless.ts +7 -2
  535. package/src/plugins/builtin/market-movers/model.ts +64 -3
  536. package/src/plugins/builtin/market-movers/screener.ts +20 -9
  537. package/src/plugins/builtin/market-valuation/detail.tsx +7 -2
  538. package/src/plugins/builtin/market-valuation/headless.ts +17 -4
  539. package/src/plugins/builtin/market-valuation/pane.tsx +8 -4
  540. package/src/plugins/builtin/market-valuation/view.ts +10 -0
  541. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +31 -57
  542. package/src/plugins/builtin/mna/distress/headless.ts +2 -1
  543. package/src/plugins/builtin/mna/headless.ts +14 -2
  544. package/src/plugins/builtin/mna/index.tsx +1 -0
  545. package/src/plugins/builtin/news/headless.ts +4 -0
  546. package/src/plugins/builtin/news/wire/news/footer.ts +5 -3
  547. package/src/plugins/builtin/news/wire/news/table.tsx +57 -11
  548. package/src/plugins/builtin/notes/cli.ts +8 -4
  549. package/src/plugins/builtin/notes/files.ts +66 -20
  550. package/src/plugins/builtin/notes/migration.ts +18 -6
  551. package/src/plugins/builtin/notes/owner.tsx +3 -2
  552. package/src/plugins/builtin/notes/quick-notes-pane.tsx +3 -2
  553. package/src/plugins/builtin/options-positioning/client.ts +10 -0
  554. package/src/plugins/builtin/options-positioning/headless.ts +88 -13
  555. package/src/plugins/builtin/options-positioning/index.tsx +2 -2
  556. package/src/plugins/builtin/options-positioning/model.ts +33 -0
  557. package/src/plugins/builtin/options-positioning/pane.tsx +38 -16
  558. package/src/plugins/builtin/options-scenario/charts.tsx +13 -4
  559. package/src/plugins/builtin/options-scenario/client.ts +114 -17
  560. package/src/plugins/builtin/options-scenario/collar.ts +141 -0
  561. package/src/plugins/builtin/options-scenario/csp.ts +1 -1
  562. package/src/plugins/builtin/options-scenario/freshness.ts +27 -0
  563. package/src/plugins/builtin/options-scenario/headless.ts +30 -12
  564. package/src/plugins/builtin/options-scenario/index.tsx +1 -1
  565. package/src/plugins/builtin/options-scenario/model.ts +55 -5
  566. package/src/plugins/builtin/options-scenario/pane.tsx +24 -5
  567. package/src/plugins/builtin/pe-band/index.tsx +1 -1
  568. package/src/plugins/builtin/pe-band/model.ts +1 -15
  569. package/src/plugins/builtin/perps/headless.ts +30 -13
  570. package/src/plugins/builtin/perps/model.ts +45 -3
  571. package/src/plugins/builtin/perps/pane.tsx +7 -7
  572. package/src/plugins/builtin/portfolio-list/cell-version.ts +10 -4
  573. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +128 -14
  574. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +144 -63
  575. package/src/plugins/builtin/portfolio-list/cli/render.ts +373 -48
  576. package/src/plugins/builtin/portfolio-list/cli/shared.ts +23 -9
  577. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +25 -35
  578. package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
  579. package/src/plugins/builtin/portfolio-list/headless.ts +161 -32
  580. package/src/plugins/builtin/portfolio-list/income.ts +296 -0
  581. package/src/plugins/builtin/portfolio-list/metrics.ts +2 -2
  582. package/src/plugins/builtin/portfolio-list/pane/futures-terms.ts +58 -0
  583. package/src/plugins/builtin/portfolio-list/pane/index.tsx +63 -14
  584. package/src/plugins/builtin/portfolio-list/pane/remove-ticker.ts +1 -1
  585. package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +47 -28
  586. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +38 -8
  587. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +12 -4
  588. package/src/plugins/builtin/portfolio-list/settings.ts +22 -0
  589. package/src/plugins/builtin/portfolio-list/since-last-seen.ts +197 -0
  590. package/src/plugins/builtin/portfolio-list/summary/index.tsx +26 -4
  591. package/src/plugins/builtin/portfolio-list/summary/totals.ts +32 -4
  592. package/src/plugins/builtin/portfolio-list/table.tsx +39 -7
  593. package/src/plugins/builtin/power/prices-headless.ts +2 -1
  594. package/src/plugins/builtin/realized-vol/chart-model.ts +29 -5
  595. package/src/plugins/builtin/realized-vol/charts.tsx +14 -8
  596. package/src/plugins/builtin/realized-vol/evidence.ts +2 -0
  597. package/src/plugins/builtin/realized-vol/headless.ts +6 -4
  598. package/src/plugins/builtin/realized-vol/model.ts +5 -1
  599. package/src/plugins/builtin/realized-vol/pane.tsx +31 -11
  600. package/src/plugins/builtin/realized-vol/settings.ts +1 -1
  601. package/src/plugins/builtin/research/analyst-headless.ts +4 -0
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +16 -5
  603. package/src/plugins/builtin/research/event-model.ts +63 -51
  604. package/src/plugins/builtin/research/headless-schema.ts +1 -0
  605. package/src/plugins/builtin/research/headless.ts +4 -1
  606. package/src/plugins/builtin/research/index.tsx +3 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +27 -5
  608. package/src/plugins/builtin/research/relative-valuation-headless.ts +2 -0
  609. package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
  610. package/src/plugins/builtin/reverse-dcf/headless.ts +28 -9
  611. package/src/plugins/builtin/reverse-dcf/index.tsx +5 -2
  612. package/src/plugins/builtin/reverse-dcf/model.ts +87 -6
  613. package/src/plugins/builtin/reverse-dcf/pane.tsx +30 -7
  614. package/src/plugins/builtin/risk-factors/headless.ts +7 -0
  615. package/src/plugins/builtin/risk-factors/index.tsx +1 -0
  616. package/src/plugins/builtin/scanner/feed.ts +5 -3
  617. package/src/plugins/builtin/scanner/headless.ts +9 -57
  618. package/src/plugins/builtin/scanner/index.ts +1 -2
  619. package/src/plugins/builtin/sec/forms.ts +2 -6
  620. package/src/plugins/builtin/sec/fund-facts-view.tsx +53 -0
  621. package/src/plugins/builtin/sec/fund-facts.ts +328 -0
  622. package/src/plugins/builtin/sec/headless.ts +140 -44
  623. package/src/plugins/builtin/sec/index.tsx +95 -30
  624. package/src/plugins/builtin/sec/model.ts +2 -44
  625. package/src/plugins/builtin/shared/earnings-report.ts +48 -1
  626. package/src/plugins/builtin/shared/headless-options.ts +10 -0
  627. package/src/plugins/builtin/shared/history-span.ts +55 -0
  628. package/src/plugins/builtin/shared/locked-rows.tsx +3 -1
  629. package/src/plugins/builtin/shared/move-rank.ts +108 -0
  630. package/src/plugins/builtin/shared/report-freshness.ts +45 -20
  631. package/src/plugins/builtin/shared/scanner-capture.ts +95 -0
  632. package/src/plugins/builtin/shared/series-detail-chart.tsx +5 -2
  633. package/src/plugins/builtin/shared/series-list-detail.tsx +7 -3
  634. package/src/plugins/builtin/shared/ticker-surface.ts +16 -2
  635. package/src/plugins/builtin/shared/treasury-cutoffs.ts +15 -0
  636. package/src/plugins/builtin/shared/use-quote-board.ts +13 -5
  637. package/src/plugins/builtin/shared/volatility/live-session.ts +34 -0
  638. package/src/plugins/builtin/shared/volatility-indices.ts +32 -0
  639. package/src/plugins/builtin/short-interest/headless.ts +3 -0
  640. package/src/plugins/builtin/short-interest/watch-model.ts +2 -2
  641. package/src/plugins/builtin/social-mentions/client.ts +8 -1
  642. package/src/plugins/builtin/social-mentions/pane.tsx +8 -6
  643. package/src/plugins/builtin/supply-chain/client.ts +12 -3
  644. package/src/plugins/builtin/supply-chain/disclosure-quote.tsx +9 -5
  645. package/src/plugins/builtin/supply-chain/evidence.ts +3 -1
  646. package/src/plugins/builtin/supply-chain/flow-layout.ts +2 -1
  647. package/src/plugins/builtin/supply-chain/flow.tsx +23 -16
  648. package/src/plugins/builtin/supply-chain/graph-client.ts +8 -5
  649. package/src/plugins/builtin/supply-chain/graph-evidence.ts +1 -1
  650. package/src/plugins/builtin/supply-chain/graph-model.ts +10 -2
  651. package/src/plugins/builtin/supply-chain/graph-pane.tsx +9 -7
  652. package/src/plugins/builtin/supply-chain/graph.tsx +8 -6
  653. package/src/plugins/builtin/supply-chain/headless.ts +69 -27
  654. package/src/plugins/builtin/supply-chain/index.tsx +1 -1
  655. package/src/plugins/builtin/supply-chain/model.ts +76 -15
  656. package/src/plugins/builtin/supply-chain/pane.tsx +29 -15
  657. package/src/plugins/builtin/supply-chain/row-evidence.tsx +5 -4
  658. package/src/plugins/builtin/themes/headless.ts +15 -2
  659. package/src/plugins/builtin/themes/model.ts +2 -5
  660. package/src/plugins/builtin/thirteenf/api.ts +50 -2
  661. package/src/plugins/builtin/thirteenf/data.ts +250 -11
  662. package/src/plugins/builtin/thirteenf/headless.ts +311 -28
  663. package/src/plugins/builtin/thirteenf/index.tsx +4 -1
  664. package/src/plugins/builtin/thirteenf/model.ts +244 -19
  665. package/src/plugins/builtin/thirteenf/overlap-pane.tsx +133 -33
  666. package/src/plugins/builtin/thirteenf/overlap.ts +1 -1
  667. package/src/plugins/builtin/thirteenf/pane.tsx +24 -5
  668. package/src/plugins/builtin/thirteenf/report-notes.ts +78 -0
  669. package/src/plugins/builtin/thirteenf/types.ts +49 -0
  670. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +106 -24
  671. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +108 -0
  672. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +26 -8
  673. package/src/plugins/builtin/ticker-detail/financials/model.ts +2 -42
  674. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +1 -1
  675. package/src/plugins/builtin/ticker-detail/headless-schema.ts +4 -2
  676. package/src/plugins/builtin/ticker-detail/headless.ts +109 -23
  677. package/src/plugins/builtin/ticker-detail/overview/components.tsx +27 -3
  678. package/src/plugins/builtin/ticker-detail/overview/dividend.ts +60 -0
  679. package/src/plugins/builtin/ticker-detail/overview/model.ts +46 -9
  680. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +3 -0
  681. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +37 -4
  682. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +18 -19
  683. package/src/plugins/builtin/time-sales/client.ts +7 -4
  684. package/src/plugins/builtin/time-sales/headless.ts +71 -22
  685. package/src/plugins/builtin/time-sales/model.ts +12 -0
  686. package/src/plugins/builtin/time-sales/pane.tsx +31 -7
  687. package/src/plugins/builtin/time-sales/window.ts +128 -0
  688. package/src/plugins/builtin/trace-bonds/client.ts +351 -33
  689. package/src/plugins/builtin/trace-bonds/headless.ts +60 -22
  690. package/src/plugins/builtin/trace-bonds/index.tsx +4 -2
  691. package/src/plugins/builtin/trace-bonds/model.ts +27 -25
  692. package/src/plugins/builtin/trace-bonds/pane.tsx +63 -45
  693. package/src/plugins/builtin/treasury-auctions/cache.ts +61 -15
  694. package/src/plugins/builtin/treasury-auctions/client.ts +45 -10
  695. package/src/plugins/builtin/treasury-auctions/headless.ts +35 -13
  696. package/src/plugins/builtin/treasury-auctions/index.tsx +5 -2
  697. package/src/plugins/builtin/treasury-auctions/model.ts +20 -16
  698. package/src/plugins/builtin/treasury-auctions/pane.tsx +29 -12
  699. package/src/plugins/builtin/vol-surface/charts.tsx +2 -1
  700. package/src/plugins/builtin/vol-surface/headless.ts +3 -2
  701. package/src/plugins/builtin/vol-surface/pane.tsx +2 -1
  702. package/src/plugins/builtin/vol-surface/stored.ts +4 -7
  703. package/src/plugins/builtin/volatility/chart-model.ts +16 -15
  704. package/src/plugins/builtin/volatility/charts.tsx +5 -5
  705. package/src/plugins/builtin/volatility/client.ts +73 -2
  706. package/src/plugins/builtin/volatility/evidence.ts +13 -14
  707. package/src/plugins/builtin/volatility/headless.ts +13 -7
  708. package/src/plugins/builtin/volatility/index.tsx +1 -1
  709. package/src/plugins/builtin/volatility/model.ts +104 -38
  710. package/src/plugins/builtin/volatility/pane.tsx +42 -24
  711. package/src/plugins/builtin/volatility/series.ts +22 -13
  712. package/src/plugins/builtin/world-venue-map/geo-series.ts +9 -0
  713. package/src/plugins/builtin/world-venue-map/headless.ts +25 -8
  714. package/src/plugins/builtin/world-venue-map/index.ts +16 -2
  715. package/src/plugins/builtin/world-venue-map/map.tsx +13 -17
  716. package/src/plugins/builtin/yield-curve/curves.ts +29 -5
  717. package/src/plugins/builtin/yield-curve/headless.ts +41 -8
  718. package/src/plugins/builtin/yield-curve/history.ts +5 -5
  719. package/src/plugins/builtin/yield-curve/index.tsx +30 -13
  720. package/src/plugins/compat.ts +3 -1
  721. package/src/plugins/dependencies.ts +8 -2
  722. package/src/plugins/host-link.ts +12 -5
  723. package/src/plugins/installer.ts +16 -7
  724. package/src/plugins/loader.ts +9 -2
  725. package/src/plugins/marketplace/activation.ts +10 -4
  726. package/src/plugins/registry/host-actions.ts +3 -0
  727. package/src/plugins/registry/index.ts +3 -1
  728. package/src/{plugins/builtin/portfolio-list → portfolio}/allocation.ts +82 -15
  729. package/src/{plugins/builtin/portfolio-list → portfolio}/column-values.ts +143 -55
  730. package/src/portfolio/futures-positions.ts +213 -0
  731. package/src/portfolio/futures-terms.ts +75 -0
  732. package/src/portfolio/manual-lots.ts +78 -0
  733. package/src/{plugins/builtin/portfolio-list → portfolio}/mutations.ts +59 -15
  734. package/src/portfolio/position-metrics.ts +44 -10
  735. package/src/portfolio/valuation-basis.ts +34 -24
  736. package/src/public/__snapshots__/public-api.test.ts.snap +6 -0
  737. package/src/public/time-series.ts +2 -1
  738. package/src/remote/confirm-change.tsx +2 -1
  739. package/src/remote/controller.ts +27 -7
  740. package/src/remote/schema.ts +25 -9
  741. package/src/remote/server.ts +1 -1
  742. package/src/remote/watchlist.ts +9 -1
  743. package/src/renderers/cloudflare/http-proxy.ts +21 -13
  744. package/src/renderers/dom/data-table/row.tsx +1 -1
  745. package/src/renderers/dom/desktop/audio-player.tsx +312 -0
  746. package/src/renderers/dom/desktop/control-styles.ts +17 -82
  747. package/src/renderers/dom/desktop/controls.tsx +39 -63
  748. package/src/renderers/dom/desktop/dialog-actions.tsx +13 -53
  749. package/src/renderers/dom/desktop/icons.tsx +8 -0
  750. package/src/renderers/dom/desktop/list-view.tsx +6 -6
  751. package/src/renderers/dom/desktop/popover.tsx +0 -3
  752. package/src/renderers/dom/desktop/query-bar.tsx +7 -5
  753. package/src/renderers/dom/desktop/select-field.tsx +9 -8
  754. package/src/renderers/dom/desktop/stack-header.ts +3 -0
  755. package/src/renderers/dom/dom-ui-host.tsx +5 -2
  756. package/src/renderers/dom/host/chart-surface.tsx +3 -3
  757. package/src/renderers/dom/host/size-observer.ts +33 -4
  758. package/src/renderers/dom/host/surface-3d.tsx +3 -2
  759. package/src/renderers/dom/host/surface-fit.ts +4 -1
  760. package/src/renderers/dom/host/tabs.tsx +22 -132
  761. package/src/renderers/dom/styles.css +358 -160
  762. package/src/renderers/dom/windowed-list.tsx +201 -0
  763. package/src/renderers/dom/windowed-rows.ts +65 -0
  764. package/src/renderers/electrobun/bun/core-capabilities.ts +1 -1
  765. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +2 -9
  766. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -1
  767. package/src/renderers/electrobun/bun/desktop/http-stream.ts +21 -6
  768. package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
  769. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +43 -1
  770. package/src/renderers/electrobun/bun/desktop/update.ts +21 -6
  771. package/src/renderers/electrobun/bun/desktop/workspace/requests.ts +5 -1
  772. package/src/renderers/electrobun/shared/protocol.ts +4 -2
  773. package/src/renderers/electrobun/shared/rpc-codec.ts +7 -0
  774. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +21 -17
  775. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  776. package/src/renderers/electrobun/view/desktop/window/bridge.ts +6 -8
  777. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +18 -0
  778. package/src/renderers/electrobun/view/http-fetch.ts +12 -1
  779. package/src/series/capability.ts +1 -0
  780. package/src/series/files.ts +9 -3
  781. package/src/series/registry.ts +40 -14
  782. package/src/series/resolve.ts +121 -18
  783. package/src/series/standalone.ts +3 -2
  784. package/src/series/types.ts +55 -1
  785. package/src/series/validate.ts +39 -0
  786. package/src/shares/api.ts +26 -7
  787. package/src/shares/bug-report-dialog.tsx +2 -2
  788. package/src/shares/bug-report-flow.tsx +4 -7
  789. package/src/shares/capture-flow.ts +5 -4
  790. package/src/shares/capture-preview.tsx +2 -2
  791. package/src/shares/chat.ts +7 -27
  792. package/src/shares/flow.tsx +86 -40
  793. package/src/shares/location.ts +1 -3
  794. package/src/shares/pane-image.ts +11 -9
  795. package/src/shares/pane.ts +5 -2
  796. package/src/shares/payload.ts +1 -1
  797. package/src/shares/personal-pane.ts +3 -3
  798. package/src/shares/portable-layout.ts +9 -2
  799. package/src/shares/ready.ts +42 -0
  800. package/src/shares/test-harness.ts +62 -0
  801. package/src/sources/gloomberb-cloud/batched-lookups.ts +73 -0
  802. package/src/sources/gloomberb-cloud/index.ts +64 -12
  803. package/src/sources/gloomberb-cloud/normalizers.ts +31 -2
  804. package/src/sources/gloomberb-cloud/perpetuals.ts +20 -1
  805. package/src/sources/history-omitted.ts +34 -0
  806. package/src/sources/history-result.ts +3 -0
  807. package/src/sources/history-retention.ts +1 -1
  808. package/src/sources/listing-symbols.ts +8 -4
  809. package/src/sources/provider-errors.ts +43 -1
  810. package/src/sources/provider-router/batches.ts +3 -2
  811. package/src/sources/provider-router/cache.ts +2 -1
  812. package/src/sources/provider-router/cached-routes.ts +9 -3
  813. package/src/sources/provider-router/history.ts +9 -8
  814. package/src/sources/provider-router/index.ts +18 -3
  815. package/src/sources/provider-router/primary.ts +5 -4
  816. package/src/sources/provider-router/quote-route.ts +3 -1
  817. package/src/sources/provider-router/routing.ts +2 -1
  818. package/src/sources/provider-router/search.ts +47 -13
  819. package/src/sources/provider-router/streaming.ts +7 -4
  820. package/src/sources/sec-edgar.ts +1 -3
  821. package/src/state/app/context/index.tsx +9 -0
  822. package/src/state/app/tab-cursor.ts +222 -0
  823. package/src/state/hooks/quote-streaming.ts +3 -2
  824. package/src/state/hooks/session-snapshot.ts +3 -2
  825. package/src/state/persist-scheduler.ts +12 -4
  826. package/src/sync/controller.ts +22 -1
  827. package/src/sync/core-contributors.ts +264 -74
  828. package/src/team/collections-sync.ts +14 -4
  829. package/src/team/collections.ts +40 -11
  830. package/src/team/store.ts +5 -4
  831. package/src/telemetry/attention-counts.ts +8 -2
  832. package/src/telemetry/crash-reports-dom.ts +3 -0
  833. package/src/telemetry/crash-reports-node.ts +7 -4
  834. package/src/telemetry/crash-reports.ts +11 -11
  835. package/src/telemetry/usage-counts.ts +16 -12
  836. package/src/test-support/config-store.ts +31 -0
  837. package/src/test-support/moved-symbols.ts +64 -0
  838. package/src/theme/colors.ts +32 -0
  839. package/src/theme/font-scale.ts +2 -0
  840. package/src/theme/ui-tokens.ts +71 -0
  841. package/src/tickers/batched-lookups.ts +186 -0
  842. package/src/tickers/company-name-listing.ts +97 -0
  843. package/src/tickers/company-name.ts +13 -0
  844. package/src/tickers/instrument-coverage.ts +112 -0
  845. package/src/tickers/listing-fate.ts +282 -0
  846. package/src/tickers/listing-venues.ts +24 -5
  847. package/src/tickers/open-target.ts +13 -5
  848. package/src/tickers/search/index.ts +156 -37
  849. package/src/tickers/search/ranking.ts +68 -3
  850. package/src/tickers/search/types.ts +3 -0
  851. package/src/tickers/search/upsert.ts +22 -7
  852. package/src/tickers/terminal-codes.ts +79 -0
  853. package/src/tickers/ticker-changes.ts +100 -12
  854. package/src/tickers/us-listing.ts +2 -1
  855. package/src/time-series/bar-spacing.ts +19 -0
  856. package/src/time-series/chart-data.ts +116 -21
  857. package/src/time-series/field-catalog.ts +5 -2
  858. package/src/time-series/forward-valuation.ts +10 -7
  859. package/src/time-series/fundamentals.ts +103 -17
  860. package/src/time-series/hooks.ts +2 -0
  861. package/src/time-series/ice-credit.ts +17 -2
  862. package/src/time-series/live-bars.ts +24 -9
  863. package/src/time-series/live-quotes.ts +2 -3
  864. package/src/time-series/parsed-history-cache.ts +2 -0
  865. package/src/time-series/price-comparison.ts +6 -1
  866. package/src/time-series/price-units.ts +69 -0
  867. package/src/time-series/resolve.ts +114 -14
  868. package/src/time-series/session-bar.ts +138 -0
  869. package/src/time-series/spec.ts +14 -4
  870. package/src/time-series/studies.ts +214 -15
  871. package/src/time-series/transforms.ts +2 -0
  872. package/src/time-series/types.ts +33 -1
  873. package/src/time-series/use-chart-resolution.ts +2 -1
  874. package/src/time-series/valuation-price.ts +13 -0
  875. package/src/types/config.ts +17 -1
  876. package/src/types/data-provider.ts +20 -0
  877. package/src/types/financials.ts +2 -0
  878. package/src/types/headless.ts +169 -1
  879. package/src/types/instrument.ts +6 -0
  880. package/src/types/plugin.ts +39 -9
  881. package/src/types/price-history.ts +5 -0
  882. package/src/types/ticker-changes.ts +19 -0
  883. package/src/types/ticker.ts +10 -2
  884. package/src/ui/context-menu.tsx +2 -0
  885. package/src/ui/host.tsx +45 -4
  886. package/src/ui/measured-cells.ts +13 -7
  887. package/src/ui/qr.ts +7 -5
  888. package/src/updater/index.ts +8 -6
  889. package/src/utils/asset-category.ts +20 -0
  890. package/src/utils/calendar-date.ts +86 -27
  891. package/src/utils/currency-units.ts +17 -0
  892. package/src/utils/debug-log.ts +1 -1
  893. package/src/utils/decimal-comma.ts +83 -3
  894. package/src/utils/dividend-cash.ts +48 -0
  895. package/src/utils/dom-screenshot-rasters.ts +3 -1
  896. package/src/utils/dom-screenshot.ts +14 -10
  897. package/src/utils/exchange-rate-snapshot.ts +9 -4
  898. package/src/utils/external-url.ts +1 -0
  899. package/src/utils/fiscal-period.ts +47 -0
  900. package/src/utils/format.ts +5 -2
  901. package/src/utils/forward-dividend.ts +160 -11
  902. package/src/utils/fundamentals.ts +7 -2
  903. package/src/utils/futures-generic.ts +34 -8
  904. package/src/utils/http-proxy-response.ts +67 -9
  905. package/src/utils/local-utc-offset.ts +2 -0
  906. package/src/utils/log-failure.ts +31 -0
  907. package/src/utils/option-expiry.ts +12 -12
  908. package/src/utils/plugin-proxy-hosts.json +1 -5
  909. package/src/utils/price-history-integrity.ts +56 -0
  910. package/src/utils/price-history.ts +13 -1
  911. package/src/utils/sec-filings.ts +245 -0
  912. package/src/utils/selection-clipboard.ts +5 -2
  913. package/src/utils/throttled-fetch.ts +1 -0
  914. package/src/{plugins/builtin/dividend-yield/trailing-cash.ts → utils/trailing-dividend.ts} +55 -8
  915. package/src/utils/typo-distance.ts +22 -0
  916. package/src/utils/url.ts +1 -0
  917. package/src/utils/utc-time.ts +11 -0
  918. package/src/plugins/builtin/chat/share/targets.ts +0 -27
  919. package/src/plugins/builtin/shared/zip-text.ts +0 -46
  920. package/src/renderers/dom/host/top-surface.ts +0 -119
  921. package/src/shares/dialog.tsx +0 -221
  922. package/src/shares/live.ts +0 -19
@@ -19,10 +19,10 @@ import { isDetailBackNavigationKey } from "../../../utils/back-navigation";
19
19
  import { isPlainKey } from "../../../utils/keyboard";
20
20
  import { isPlainArrowUp, stopSearchFocusNavigation } from "../../../utils/search-focus-navigation";
21
21
  import { nextHeaderSort } from "../../../utils/sort-values";
22
- import { usePluginPaneState, usePluginTickerActions } from "../../runtime";
22
+ import { useAssetData, usePluginPaneState, usePluginTickerActions } from "../../runtime";
23
23
  import { useMineTickers } from "../shared/mine-tickers";
24
24
  import { usePaneStatusFooter, usePaneStatusLinkFooter } from "../../../components/layout/pane/status-footer";
25
- import { loadBrowserRows, loadFilingPositions, loadFundDetail } from "./data";
25
+ import { corporateSplitFactor, loadBrowserRows, loadFilingPositions, loadFundDetail, loadSplitFactors } from "./data";
26
26
  import { FundOverlapView } from "./overlap-pane";
27
27
  import { ThirteenFCrowdingPane, ThirteenFTickerHoldingsView } from "./signals-pane";
28
28
  import { PaneFooterScope } from "../../../components/layout/pane/footer";
@@ -53,7 +53,7 @@ import {
53
53
  sortHoldingRows,
54
54
  sortTimelineRows,
55
55
  } from "./model";
56
- import { isOptionType, isStaleFiling, quartersOldText } from "./report-notes";
56
+ import { filingGapText, holdingUnreadNotes, isOptionType, isStaleFiling, quartersOldText } from "./report-notes";
57
57
  import {
58
58
  renderBrowserCell,
59
59
  renderFilingPositionCell,
@@ -345,9 +345,14 @@ export function FundDetailView({
345
345
  const [openFilingId, setOpenFilingId] = usePluginPaneState<string | null>("openFilingId", null);
346
346
  const [filingReturnTab, setFilingReturnTab] = useState<ThirteenFDetailTab | null>(null);
347
347
  const [data, setData] = useState<FundDetailData | null>(null);
348
+ // The split factors of the lines that moved as across a split; null until their corporate actions answer.
349
+ const [splitFactors, setSplitFactors] = useState<ReadonlyMap<string, number | null> | null>(null);
348
350
  const [status, setStatus] = useState<LoadStatus>("loading");
349
351
  const [error, setError] = useState<string | null>(null);
350
352
  const abortRef = useRef<AbortController | null>(null);
353
+ const marketData = useAssetData();
354
+ const marketDataRef = useRef(marketData);
355
+ marketDataRef.current = marketData;
351
356
  // In the Research pane's 13F tab, h/l move between these sections while the
352
357
  // fund is open, as they do in the 13F pane.
353
358
  useClaimResearchTabKeys(focused);
@@ -362,7 +367,16 @@ export function FundDetailView({
362
367
  .then((nextData) => {
363
368
  if (abortRef.current !== controller) return;
364
369
  setData(nextData);
370
+ setSplitFactors(null);
365
371
  setStatus("loaded");
372
+ // The table is up already: a line that moved as across a split has no Est P&L until its corporate actions say whether one happened.
373
+ const provider = marketDataRef.current;
374
+ void (provider
375
+ ? loadSplitFactors(nextData, (ticker, after, through) => corporateSplitFactor(provider, ticker, after, through), controller.signal)
376
+ : Promise.resolve(new Map<string, number | null>())
377
+ ).then((factors) => {
378
+ if (abortRef.current === controller) setSplitFactors(factors);
379
+ }, () => {});
366
380
  })
367
381
  .catch((loadError) => {
368
382
  if (abortRef.current !== controller) return;
@@ -380,7 +394,7 @@ export function FundDetailView({
380
394
  };
381
395
  }, [load]);
382
396
 
383
- const holdingRows = useMemo(() => buildFundHoldingRows(data), [data]);
397
+ const holdingRows = useMemo(() => buildFundHoldingRows(data, splitFactors ?? undefined), [data, splitFactors]);
384
398
  const visibleHoldingRows = useMemo(() => (
385
399
  sortHoldingRows(holdingRows.filter(row => !mineOnly || mine.has(row.ticker)).map(row => ({ ...row, mine: mine.has(row.ticker) })), holdingSort)
386
400
  ), [holdingRows, holdingSort, mineOnly, mine]);
@@ -507,9 +521,14 @@ export function FundDetailView({
507
521
  : []),
508
522
  ];
509
523
 
524
+ // A 13F-NT, or no 13F, for the newest quarter past its deadline; a stale filing's age is in the stats already.
525
+ const filingGap = data?.filingGap && (data.filingGap.filing || !staleFiling) ? filingGapText(data.filingGap, { command: false }) : null;
526
+ // Lines left without an Est P&L because their split could not be confirmed, said once their corporate actions have answered; a confirmed split is method, not a warning.
527
+ const splitNotices = useMemo(() => (activeTab === "holdings" && splitFactors ? holdingUnreadNotes(visibleHoldingRows) : []), [activeTab, splitFactors, visibleHoldingRows]);
528
+ const holdingNotices = useMemo(() => [...(filingGap ? [filingGap] : []), ...splitNotices, ...(data?.warnings ?? [])], [filingGap, splitNotices, data?.warnings]);
510
529
  usePaneNoticeFooter({
511
530
  registrationId: "thirteenf-holdings-notices",
512
- notices: data?.warnings ?? [],
531
+ notices: holdingNotices,
513
532
  focused,
514
533
  enabled: !openFiling && activeTab !== "overlap",
515
534
  });
@@ -1,5 +1,7 @@
1
1
  import type { CrowdingRow, TickerHolderRow } from "./signals";
2
2
  import { formatMoneyCompact } from "./format";
3
+ import { formatSplitRatio } from "./model";
4
+ import type { ThirteenFFilingGap, ThirteenFOtherManager } from "./types";
3
5
 
4
6
  /**
5
7
  * Summary lines for the 13F text reports. Each says which quarters the rows
@@ -121,6 +123,82 @@ export function staleFundsText(funds: readonly { name: string; quarters: number
121
123
  return `Latest filing 2+ quarters old: ${named}${funds.length > shown ? ` and ${count(funds.length - shown)} more` : ""}`;
122
124
  }
123
125
 
126
+ interface SplitLine {
127
+ ticker: string;
128
+ issuer: string;
129
+ }
130
+
131
+ const lineName = (line: SplitLine) => line.ticker || line.issuer;
132
+
133
+ /** The first few lines as `text` gives them, then a count of the rest. */
134
+ function listedLines<T>(lines: readonly T[], text: (line: T) => string, shown = 5): string {
135
+ return `${lines.slice(0, shown).map(text).join(", ")}${lines.length > shown ? ` and ${count(lines.length - shown)} more` : ""}`;
136
+ }
137
+
138
+ /** "Split-adjusted: NVDA 10:1, Odd Co 1:10 (split between the filings, as the corporate actions show)": lines priced on split-adjusted shares. */
139
+ export function splitAdjustedText(lines: readonly (SplitLine & { ratio: number })[], prefix = "Split-adjusted"): string {
140
+ return `${prefix}: ${listedLines(lines, (line) => `${lineName(line)} ${formatSplitRatio(line.ratio)}`)} (split between the filings, as the corporate actions show)`;
141
+ }
142
+
143
+ /** "No Est P&L: XYZ (shares and value per share moved as across a split, and the corporate actions could not be read to tell)": lines left without a figure, `leftOut` opening it. */
144
+ export function splitUnreadText(lines: readonly SplitLine[], leftOut: string): string {
145
+ return `${leftOut}: ${listedLines(lines, lineName)} (shares and value per share moved as across a split, and the corporate actions could not be read to tell)`;
146
+ }
147
+
148
+ /** The note for the lines of a Holdings table left without an Est P&L because their split could not be confirmed: a data limitation, the pane's notice as well as the report's. */
149
+ export function holdingUnreadNotes(rows: readonly (SplitLine & { splitUnread?: boolean })[]): string[] {
150
+ const unread = rows.filter((row) => row.splitUnread);
151
+ return unread.length ? [splitUnreadText(unread, "No Est P&L")] : [];
152
+ }
153
+
154
+ /** What a Holdings report says of its lines that moved as across a split: the ones priced split-adjusted (method, so a report's note only), and the ones left without a figure. */
155
+ export function holdingSplitNotes(rows: readonly (SplitLine & { splitRatio?: number; splitUnread?: boolean })[]): string[] {
156
+ const adjusted = rows.flatMap((row) => row.splitRatio ? [{ ...row, ratio: row.splitRatio }] : []);
157
+ return [...(adjusted.length ? [splitAdjustedText(adjusted, "Est P&L split-adjusted")] : []), ...holdingUnreadNotes(rows)];
158
+ }
159
+
160
+ /** "Q2 2026" for the quarter ending 30 Jun 2026. */
161
+ function quarterText(period: string): string {
162
+ const day = calendarDay(period);
163
+ return day ? `Q${Math.floor(day.getUTCMonth() / 3) + 1} ${day.getUTCFullYear()}` : period;
164
+ }
165
+
166
+ /** The fund to open for a manager: its CIK, else its quoted name. */
167
+ function openCommand(manager: ThirteenFOtherManager): string {
168
+ return manager.cik ? `fn 13F ${manager.cik}` : `fn 13F "${manager.name}"`;
169
+ }
170
+
171
+ /**
172
+ * What a fund filed for the newest quarter past its deadline instead of a
173
+ * holdings report: "13F-NT for Q2 2026, filed 14 Aug; holdings reported by
174
+ * PERSHING SQUARE INC. | open: fn 13F 0002026053", or "No 13F for Q2 2026,
175
+ * due 14 Aug" once EDGAR shows nothing. `command: false` names the CIK instead
176
+ * of the command, for the pane.
177
+ */
178
+ export function filingGapText(gap: ThirteenFFilingGap, { command = true }: { command?: boolean } = {}): string {
179
+ const quarter = quarterText(gap.period);
180
+ const year = Number(gap.due.slice(0, 4));
181
+ const filing = gap.filing;
182
+ if (filing?.form.startsWith("13F-NT")) {
183
+ const [first, ...others] = filing.otherManagers ?? [];
184
+ const filed = `13F-NT for ${quarter}, filed ${filingDayText(filing.filed, year)}`;
185
+ if (!first) return `${filed}; another manager reported its holdings`;
186
+ const more = others.length ? ` and ${count(others.length)} more` : "";
187
+ return command
188
+ ? `${filed}; holdings reported by ${first.name}${more} | open: ${openCommand(first)}`
189
+ : `${filed}; holdings reported by ${first.name}${first.cik ? ` (CIK ${first.cik})` : ""}${more}`;
190
+ }
191
+ if (filing) return `${filing.form} for ${quarter} filed ${filingDayText(filing.filed, year)}; its holdings are not loaded yet`;
192
+ // Unasked, EDGAR may well hold a 13F-NT or a report the source has not loaded: say only what the loaded filings show.
193
+ if (!gap.checked) return `${quarter} 13F (due ${filingDayText(gap.due, year)}) not in the loaded filings; EDGAR not checked`;
194
+ return `No 13F for ${quarter}, due ${filingDayText(gap.due, year)}`;
195
+ }
196
+
197
+ /** A search asks EDGAR about a few lagging funds only: "EDGAR checked for the first 10 of 14 funds with no Q2 2026 13F loaded; ...". */
198
+ export function uncheckedFundsText(asked: number, behind: number, period: string): string {
199
+ return `EDGAR checked for the first ${count(asked)} of ${count(behind)} funds with no ${quarterText(period)} 13F loaded; fn 13F <CIK> checks any other`;
200
+ }
201
+
124
202
  /** "showing 50 of 374" from the start of the list, "showing 51-100 of 374" past it. */
125
203
  function shownRangeText(offset: number, end: number, total: number): string {
126
204
  return offset > 0
@@ -97,6 +97,51 @@ export interface FundDetailData {
97
97
  latestReport?: ThirteenFPeriodReport;
98
98
  previousReport?: ThirteenFPeriodReport;
99
99
  warnings?: string[];
100
+ /** Set when the latest report predates the newest quarter past its deadline. */
101
+ filingGap?: ThirteenFFilingGap | null;
102
+ }
103
+
104
+ /** A manager a 13F-NT names as reporting its holdings. */
105
+ export interface ThirteenFOtherManager {
106
+ /** Null on a cover page that gives only the 028- file number. */
107
+ cik: string | null;
108
+ name: string;
109
+ fileNumber: string | null;
110
+ }
111
+
112
+ /** One 13F filing as EDGAR lists it, notices included. */
113
+ export interface ThirteenFEdgarFiling {
114
+ /** 13F-HR, 13F-HR/A, 13F-NT or 13F-NT/A. */
115
+ form: string;
116
+ period: string;
117
+ filed: string;
118
+ accession: string;
119
+ url: string;
120
+ otherManagers?: ThirteenFOtherManager[];
121
+ }
122
+
123
+ /** A filer's 13F filings from EDGAR, newest first. */
124
+ export interface ThirteenFFilerStatus {
125
+ cik: string;
126
+ name: string;
127
+ source: string;
128
+ filings: ThirteenFEdgarFiling[];
129
+ }
130
+
131
+ /**
132
+ * What a fund filed for the newest quarter past its deadline when no holdings
133
+ * report for it is loaded: a 13F-NT (another manager reported the holdings), a
134
+ * report EDGAR has that is not loaded yet, or nothing EDGAR shows.
135
+ */
136
+ export interface ThirteenFFilingGap {
137
+ /** The quarter end, YYYY-MM-DD. */
138
+ period: string;
139
+ /** The day the 13F was due, YYYY-MM-DD. */
140
+ due: string;
141
+ /** The fund's own filing for that quarter, when EDGAR lists one. */
142
+ filing: ThirteenFEdgarFiling | null;
143
+ /** False when EDGAR could not be asked; a missing filing is then as far as the loaded reports know. */
144
+ checked: boolean;
100
145
  }
101
146
 
102
147
  /** The public report for one period, after applying known amendment types. */
@@ -126,6 +171,10 @@ export interface FundHoldingRow {
126
171
  previousShares: number | null;
127
172
  valueChange: number | null;
128
173
  estimatedPnl: number | null;
174
+ /** New shares per old (10 for 10:1) when the filings straddle a split its corporate actions show: Est P&L is priced, and sharesChange, sharesChangePercent and action measured, on the previous shares carried across it. */
175
+ splitRatio?: number;
176
+ /** The line moved as across a split and its corporate actions could not be read to tell: Est P&L is left empty, not priced as a crash or a surge, and its share change stays as filed. */
177
+ splitUnread?: boolean;
129
178
  sharesChange: number | null;
130
179
  sharesChangePercent: number | null;
131
180
  action: HoldingAction;
@@ -10,6 +10,7 @@ import {
10
10
  type DataTableCell,
11
11
  type DataTableColumn,
12
12
  type DataTableKeyEvent,
13
+ type PaneFooterSegment,
13
14
  } from "../../../../components";
14
15
  import { TIME_RANGES, type TimeRange } from "../../../../time-series/range";
15
16
  import type { PaneProps } from "../../../../types/plugin";
@@ -20,7 +21,9 @@ import { isPlainKeyboardEvent } from "../../../../utils/keyboard";
20
21
  import { publicTickerKey } from "../../../../utils/exchanges";
21
22
  import { formatPriceObservation, quoteFormatOptions } from "../../../../market-data/market/format";
22
23
  import { cleanFloat32Price, historyPriceDecimals } from "../../../../cli/history-rows";
23
- import { pricePointValues, priceHistoryIntegrityNotice } from "../../../../utils/price-history-integrity";
24
+ import {
25
+ MISSING_VOLUME_TEXT, missingVolumeCount, missingVolumeNotice, pricePointValues, priceHistoryIntegrityNotice,
26
+ } from "../../../../utils/price-history-integrity";
24
27
  import {
25
28
  useAssetData,
26
29
  useDebouncedPluginPaneState,
@@ -29,6 +32,18 @@ import {
29
32
  import { usePaneTicker } from "../../../../state/app/context";
30
33
  import { handleRefreshKey, useClampSelectedIndex } from "../../../../components/data-table/table-pane";
31
34
  import { useBoundTicker, useTickerRequest } from "../../shared/ticker-request";
35
+ import { DAY_SO_FAR_TEXT, withSessionBar } from "../../../../time-series/session-bar";
36
+ import {
37
+ formingHistoryBar,
38
+ formingHistoryBarText,
39
+ HISTORY_DEFAULT_RANGE,
40
+ historyBarDate,
41
+ historyBarSize,
42
+ historyBarSizeText,
43
+ historyBarSizeWord,
44
+ historyDateHeader,
45
+ type HistoryBarSize,
46
+ } from "./history-bars";
32
47
 
33
48
  type HistoryColumnId = "date" | "open" | "high" | "low" | "close" | "change" | "changePercent" | "volume";
34
49
  type HistoryColumn = DataTableColumn & { id: HistoryColumnId };
@@ -36,7 +51,18 @@ type HistoryColumn = DataTableColumn & { id: HistoryColumnId };
36
51
  export type HistoricalPriceRow = {
37
52
  key: string;
38
53
  point: ReturnType<typeof pricePointValues>;
54
+ /** The bar's date as the table reads it: `2026-10 MTD` for a month still running, `2026-10-16 DTD` for today's session. */
39
55
  date: string;
56
+ /** What a CSV export writes for the date: the bar's own date, whatever the table says of its period. */
57
+ exportDate: string;
58
+ /** The bar carries a time of day, so the table dates it with one. */
59
+ timed: boolean;
60
+ /** When the bar opens, or the time of the latest trade an intraday history can end with (latestTradeIndex). */
61
+ time: number;
62
+ /** The bar's period had not ended: a week or month still running, or the day's session still trading. */
63
+ partial: boolean;
64
+ /** A coin's day Gloom Cloud rebuilt from hourly bars, which has no volume of its own. */
65
+ filled: boolean;
40
66
  change: number | null;
41
67
  changePercent: number | null;
42
68
  };
@@ -86,29 +112,56 @@ function formatMaybePercent(value: number | null): string {
86
112
  return value == null ? "-" : formatPercent(value);
87
113
  }
88
114
 
89
- function formatMaybeCompact(value: number | null | undefined): string {
90
- return value == null ? "-" : formatCompact(value);
115
+ /** Volume as the table shows it; missing reads as missing (`volumeMissing`) in a history that reports volume, never 0. */
116
+ function formatVolume(value: number | null | undefined, volumeMissing: boolean): string {
117
+ return value == null ? volumeMissing ? MISSING_VOLUME_TEXT : "-" : formatCompact(value);
91
118
  }
92
119
 
93
- function buildHistoricalPriceRows(points: PricePoint[]): HistoricalPriceRow[] {
120
+ interface HistoricalPriceTable {
121
+ /** Newest first. */
122
+ rows: HistoricalPriceRow[];
123
+ size: HistoryBarSize;
124
+ /** The newest bar's week or month had not ended, and how far into it the bar runs. */
125
+ forming: ReturnType<typeof formingHistoryBar>;
126
+ /** The newest bar is a day whose session is still trading. */
127
+ dayToDate: boolean;
128
+ /** The newest bar's day, `YYYY-MM-DD`. */
129
+ newestDate: string | undefined;
130
+ }
131
+
132
+ function buildHistoricalPriceRows(points: PricePoint[], venue: string | undefined, now: number): HistoricalPriceTable {
94
133
  const sorted = points
95
134
  .flatMap((point, sourceIndex) => {
96
135
  const date = pricePointDate(point);
97
- return date ? [{ point: pricePointValues(point), date, sourceIndex }] : [];
136
+ return date ? [{ point: pricePointValues(point), date, sourceIndex, partial: point.partial === true, filled: point.filled === true }] : [];
98
137
  })
99
138
  .sort((left, right) => left.date.getTime() - right.date.getTime());
100
- return sorted.map((entry, index) => {
139
+ const size = historyBarSize(sorted.map((entry) => entry.date.getTime()));
140
+ const newestDate = sorted.at(-1)?.date.toISOString().slice(0, 10);
141
+ const forming = formingHistoryBar(size, newestDate, venue, now);
142
+ const dayToDate = size === "1d" && sorted.at(-1)?.partial === true;
143
+ const rows = sorted.map((entry, index) => {
101
144
  const previous = sorted[index - 1]?.point;
102
- const { point, date, sourceIndex } = entry;
145
+ const { point, date, sourceIndex, filled } = entry;
146
+ const newest = index === sorted.length - 1;
147
+ const partial = newest && (!!forming || dayToDate);
103
148
  const change = previous?.close != null && point.close != null ? point.close - previous.close : null;
149
+ const shown = formatDateTime(date);
150
+ const timed = shown.length > 10;
104
151
  return {
105
152
  key: `${date.toISOString()}:${sourceIndex}`,
106
153
  point,
107
- date: formatDateTime(date),
154
+ date: timed ? shown : historyBarDate(shown, size, partial),
155
+ exportDate: shown,
156
+ timed,
157
+ time: date.getTime(),
158
+ partial,
159
+ filled,
108
160
  change,
109
161
  changePercent: previous?.close && change !== null ? change / previous.close : null,
110
162
  };
111
163
  }).reverse();
164
+ return { rows, size, forming, dayToDate, newestDate };
112
165
  }
113
166
 
114
167
  const HISTORY_PRICE_WIDTH = 10;
@@ -123,8 +176,9 @@ const HISTORY_NUMERIC_IDS = ["open", "high", "low", "close", "change", "changePe
123
176
  * evenly, and give up cells down to a floor when it is narrow, so the volume
124
177
  * stays on screen.
125
178
  */
126
- function buildHistoryColumns(width: number, intraday: boolean): HistoryColumn[] {
127
- const dateWidth = intraday ? 16 : 10;
179
+ function buildHistoryColumns(width: number, intraday: boolean, size: HistoryBarSize, newestDate: string): HistoryColumn[] {
180
+ // A month reads as `2026-10`; the newest bar, when its week or month runs on, adds `MTD` or `WTD`.
181
+ const dateWidth = Math.max(intraday ? 16 : size === "1mo" ? 7 : 10, newestDate.length);
128
182
  const numeric: number[] = HISTORY_NUMERIC_IDS.map((id) => id === "changePercent" ? HISTORY_PERCENT_WIDTH : HISTORY_PRICE_WIDTH);
129
183
  // One gap per column plus the table's inset on both sides.
130
184
  const available = width - dateWidth - HISTORY_VOLUME_WIDTH - 8 - 2;
@@ -141,7 +195,7 @@ function buildHistoryColumns(width: number, intraday: boolean): HistoryColumn[]
141
195
  }
142
196
  const [open, high, low, close, change, changePercent] = numeric as [number, number, number, number, number, number];
143
197
  return [
144
- { id: "date", label: intraday ? "DATE/TIME" : "DATE", width: dateWidth, align: "left" },
198
+ { id: "date", label: intraday ? "DATE/TIME" : historyDateHeader(size)?.toUpperCase() ?? "DATE", width: dateWidth, align: "left" },
145
199
  { id: "open", label: "OPEN", width: open, align: "right", flexGrow: 1 },
146
200
  { id: "high", label: "HIGH", width: high, align: "right", flexGrow: 1 },
147
201
  { id: "low", label: "LOW", width: low, align: "right", flexGrow: 1 },
@@ -162,7 +216,7 @@ function nextHistoryRange(current: TimeRange): TimeRange {
162
216
  export function HistoricalPricesPane({ focused, width, height }: PaneProps) {
163
217
  const dataProvider = useAssetData();
164
218
  const { symbol, exchange, ticker } = useBoundTicker();
165
- const [range, setRange] = usePluginPaneState<TimeRange>("range", "ALL");
219
+ const [range, setRange] = usePluginPaneState<TimeRange>("range", HISTORY_DEFAULT_RANGE);
166
220
  const [selectedIdx, setSelectedIdx] = useDebouncedPluginPaneState<number>("selectedIdx", 0);
167
221
  const loader = useCallback((nextSymbol: string, nextExchange: string, forceRefresh: boolean) => {
168
222
  if (!dataProvider) throw new Error("Market data unavailable");
@@ -174,14 +228,31 @@ export function HistoricalPricesPane({ focused, width, height }: PaneProps) {
174
228
  );
175
229
  }, [dataProvider, range]);
176
230
  const { data, loading, error, reload } = useTickerRequest<PricePoint[]>(loader, symbol, exchange);
177
- const rows = useMemo(() => buildHistoricalPriceRows(data ?? []), [data]);
178
- const integrityNotice = priceHistoryIntegrityNotice(rows.filter((row) => row.point.integrity).length);
179
- // Daily and longer bars are dates; only intraday bars carry a time.
180
- const intraday = rows.length > 0 ? rows.some((row) => row.date.length > 10) : range === "1D" || range === "1W";
181
- const columns = useMemo(() => buildHistoryColumns(width, intraday), [intraday, width]);
182
231
  // The quote knows the instrument type even when the saved ticker does not;
183
- // resolve it the way every quote display does.
232
+ // resolve it the way every quote display does. It also names the venue
233
+ // whose sessions say whether a week or month is still running.
184
234
  const { financials } = usePaneTicker();
235
+ const venue = exchange || financials?.quote?.listingExchangeName || financials?.quote?.exchangeName || undefined;
236
+ // While the session trades the day's bar is the quote's: the history keeps a
237
+ // snapshot of it from whenever it was last fetched (withSessionBar).
238
+ const quote = financials?.quote;
239
+ const points = useMemo(
240
+ () => withSessionBar(data ?? [], quote, { now: Date.now(), venue }),
241
+ [data, quote, venue],
242
+ );
243
+ const { rows, size, forming, dayToDate, newestDate } = useMemo(
244
+ () => buildHistoricalPriceRows(points, venue, Date.now()),
245
+ [points, venue],
246
+ );
247
+ const integrityNotice = priceHistoryIntegrityNotice(rows.filter((row) => row.point.integrity).length);
248
+ const volumeMissing = useMemo(() => missingVolumeCount(rows.map((row) => ({
249
+ ...row.point, date: row.time, partial: row.partial, filled: row.filled,
250
+ }))), [rows]);
251
+ const volumeNotice = missingVolumeNotice(volumeMissing, rows.length);
252
+ // Daily and longer bars are dates; only intraday bars carry a time.
253
+ const intraday = rows.length > 0 ? rows.some((row) => row.timed) : range === "1D" || range === "1W";
254
+ const newestRowDate = rows[0]?.date ?? "";
255
+ const columns = useMemo(() => buildHistoryColumns(width, intraday, size, newestRowDate), [intraday, newestRowDate, size, width]);
185
256
  const assetCategory = quoteFormatOptions(
186
257
  financials?.quote,
187
258
  ticker?.metadata.assetCategory,
@@ -217,7 +288,7 @@ export function HistoricalPricesPane({ focused, width, height }: PaneProps) {
217
288
  ): DataTableCell => {
218
289
  switch (column.id) {
219
290
  case "date":
220
- return { text: row.date, color: colors.textDim };
291
+ return { text: row.date, value: row.exportDate, color: colors.textDim };
221
292
  case "open":
222
293
  case "high":
223
294
  case "low":
@@ -232,16 +303,23 @@ export function HistoricalPricesPane({ focused, width, height }: PaneProps) {
232
303
  case "changePercent":
233
304
  return { text: formatMaybePercent(row.changePercent), value: row.changePercent == null ? null : row.changePercent * 100, color: priceColor(row.changePercent ?? 0) };
234
305
  case "volume":
235
- return { text: formatMaybeCompact(row.point.volume), value: row.point.volume ?? null, color: colors.textDim };
306
+ return { text: formatVolume(row.point.volume, volumeMissing > 0), value: row.point.volume ?? null, color: colors.textDim };
236
307
  }
237
- }, [priceDecimals]);
308
+ }, [priceDecimals, volumeMissing]);
238
309
 
239
- // The range is picked in the query bar; t still steps through it.
240
- usePaneStatusFooter({ registrationId: "historical-prices", loading, error });
310
+ // The range is picked in the query bar; t still steps through it. The range
311
+ // sets the bar size, which the footer says, and a week or month still
312
+ // running says how far the newest bar goes.
313
+ const barInfo = useMemo<PaneFooterSegment[]>(() => [
314
+ ...rows.length > 0 ? [{ id: "bars", parts: [{ text: historyBarSizeText(size), tone: "muted" as const }] }] : [],
315
+ ...forming && newestDate ? [{ id: "forming", parts: [{ text: formingHistoryBarText(forming, newestDate), tone: "muted" as const }] }] : [],
316
+ ...dayToDate ? [{ id: "forming", parts: [{ text: DAY_SO_FAR_TEXT, tone: "muted" as const }] }] : [],
317
+ ], [dayToDate, forming, newestDate, rows.length, size]);
318
+ usePaneStatusFooter({ registrationId: "historical-prices", loading, error, info: barInfo });
241
319
 
242
320
  usePaneNoticeFooter({
243
321
  registrationId: "historical-prices:integrity",
244
- notices: integrityNotice ? [integrityNotice] : [],
322
+ notices: [integrityNotice, volumeNotice].filter((notice): notice is string => !!notice),
245
323
  focused,
246
324
  title: "Price history data",
247
325
  });
@@ -280,11 +358,15 @@ export function HistoricalPricesPane({ focused, width, height }: PaneProps) {
280
358
  getExportMetadata={() => [
281
359
  ["Ticker", symbol ? publicTickerKey(symbol, exchange) : ""],
282
360
  ["Requested range", range],
361
+ ...(rows.length > 0 ? [["Bar size", historyBarSizeWord(size)]] : []),
283
362
  ["Time zone", "UTC"],
363
+ ...(forming && newestDate ? [["Partial bar", `${newestDate}, ${formingHistoryBarText(forming, newestDate)}`]] : []),
364
+ ...(dayToDate && newestDate ? [["Partial bar", `${newestDate}, ${DAY_SO_FAR_TEXT}`]] : []),
284
365
  ["Price units", "As served in the history; currency and price-basis metadata are unavailable"],
285
366
  ["Status", error ? (rows.length ? "Retained after refresh failure" : "Unavailable")
286
367
  : loading ? (rows.length ? "Refreshing" : "Loading") : rows.length ? "Available" : "Empty"],
287
368
  ...(integrityNotice ? [["Warning", integrityNotice]] : []),
369
+ ...(volumeNotice ? [["Volume note", volumeNotice]] : []),
288
370
  ...(error ? [["Error", error]] : []),
289
371
  ]}
290
372
  emptyStateTitle={error
@@ -0,0 +1,108 @@
1
+ import { BAR_INTERVAL_LABELS } from "../../../../cli/history-rows";
2
+ import { periodToDateText } from "../../../../cli/pane-functions/freshness";
3
+ import { barLastSession, barPeriodToDate, type BarPeriod, type BarPeriodToDate } from "../../../../market-data/market/bar-period";
4
+ import { barSizeFromGap, medianBarGap } from "../../../../time-series/bar-spacing";
5
+ import type { TimeRange } from "../../../../time-series/range";
6
+ import { CHART_RESOLUTION_STEP_MS, type ManualChartResolution } from "../../../../time-series/resolution";
7
+
8
+ /**
9
+ * The range a price history opens on, in Historical Prices, `fn HP` and
10
+ * `shot HP`: a recent window in daily bars (RANGE_HISTORY_RESOLUTION serves
11
+ * 1M to 1Y daily). 5Y is weekly and ALL monthly, so neither is a place to start.
12
+ */
13
+ export const HISTORY_DEFAULT_RANGE: TimeRange = "3M";
14
+
15
+ /** The size of one bar of a price history; `intraday` when its minutes are not a size the source serves. */
16
+ export type HistoryBarSize = ManualChartResolution | "intraday";
17
+
18
+ const INTRADAY_SIZES: readonly ManualChartResolution[] = ["1m", "5m", "15m", "30m", "45m", "1h"];
19
+ /** A day's bars can sit a little under a day apart where the clocks change. */
20
+ const INTRADAY_BELOW_MS = 0.8 * CHART_RESOLUTION_STEP_MS["1d"];
21
+
22
+ /**
23
+ * The bar size of a history, read from the usual spacing of its bars
24
+ * (medianBarGap), as `history` reads it, so the gap a holiday leaves does not
25
+ * make daily bars weekly. Daily when there is no gap to read.
26
+ */
27
+ export function historyBarSize(times: readonly number[]): HistoryBarSize {
28
+ const gap = medianBarGap(times);
29
+ if (gap == null) return "1d";
30
+ if (gap < INTRADAY_BELOW_MS) return INTRADAY_SIZES.find((size) => CHART_RESOLUTION_STEP_MS[size] === gap) ?? "intraday";
31
+ return barSizeFromGap(gap);
32
+ }
33
+
34
+ /** Whether a bar of this size covers a day or more, so its date is a day and not a time. */
35
+ export function isDailyOrLongerBar(size: HistoryBarSize): size is "1d" | "1wk" | "1mo" {
36
+ return size === "1d" || size === "1wk" || size === "1mo";
37
+ }
38
+
39
+ /** `daily`, `5-minute`, `hourly`, `weekly`, `monthly`; `intraday` when the minutes are not a known size. */
40
+ export function historyBarSizeWord(size: HistoryBarSize): string {
41
+ return size === "intraday" ? size : BAR_INTERVAL_LABELS[size];
42
+ }
43
+
44
+ /** `daily bars`, `monthly bars`: what a history says its bars are, which the range it was asked for sets. */
45
+ export function historyBarSizeText(size: HistoryBarSize): string {
46
+ return `${historyBarSizeWord(size)} bars`;
47
+ }
48
+
49
+ /**
50
+ * What a date column heads when its bars cover more than a day: `Week of`
51
+ * (each is dated by the day its week starts) or `Month`. Null for a day's bar,
52
+ * whose column is `Date`, or an intraday one, which is dated with a time.
53
+ */
54
+ export function historyDateHeader(size: HistoryBarSize): string | null {
55
+ return size === "1wk" ? "Week of" : size === "1mo" ? "Month" : null;
56
+ }
57
+
58
+ /** The calendar period a weekly or monthly bar covers; null for any other. */
59
+ function historyBarPeriod(size: HistoryBarSize): BarPeriod | null {
60
+ return size === "1mo" ? "month" : size === "1wk" ? "week" : null;
61
+ }
62
+
63
+ /**
64
+ * Whether the newest bar, dated `date`, is a week or month that had not ended
65
+ * at `now` on its `venue` (barPeriodToDate), and how far into it the bar runs.
66
+ * Null for a complete bar, and for any bar that is not weekly or monthly.
67
+ */
68
+ export function formingHistoryBar(
69
+ size: HistoryBarSize,
70
+ date: string | undefined,
71
+ venue: string | undefined,
72
+ now: number,
73
+ ): BarPeriodToDate | null {
74
+ const period = historyBarPeriod(size);
75
+ return period && date ? barPeriodToDate(date, period, venue, now) : null;
76
+ }
77
+
78
+ /**
79
+ * The day the newest weekly or monthly bar, dated `date` by the start of its
80
+ * period, closed on once that period has ended (barLastSession): the week of
81
+ * Mon 12 Oct 2026 is Fri 16 Oct, the day its close is from. Null while it
82
+ * forms (formingHistoryBar dates it then), and for any other bar.
83
+ */
84
+ export function closedHistoryBarDay(
85
+ size: HistoryBarSize,
86
+ date: string | undefined,
87
+ venue: string | undefined,
88
+ now: number,
89
+ ): string | null {
90
+ const period = historyBarPeriod(size);
91
+ return period && date && !barPeriodToDate(date, period, venue, now) ? barLastSession(date, period, venue, now) : null;
92
+ }
93
+
94
+ /**
95
+ * A bar's day as its table dates it: a month's bar as the month (`2026-10`),
96
+ * a week's by the day it starts, and `MTD`, `WTD` or `DTD` after one whose
97
+ * period had not ended, so it never reads as a complete bar dated on its
98
+ * first day. `day` is `YYYY-MM-DD`.
99
+ */
100
+ export function historyBarDate(day: string, size: HistoryBarSize, partial = false): string {
101
+ const text = size === "1mo" ? day.slice(0, 7) : day;
102
+ return partial ? `${text} ${size === "1mo" ? "MTD" : size === "1wk" ? "WTD" : "DTD"}` : text;
103
+ }
104
+
105
+ /** What the newest bar covers so far: `month to date, through Fri 16 Oct 2026`. */
106
+ export function formingHistoryBarText(forming: BarPeriodToDate, date: string): string {
107
+ return periodToDateText({ period: forming.period, ...(forming.through ? { through: forming.through } : {}) }, date);
108
+ }
@@ -42,6 +42,7 @@ import {
42
42
  type ReturnRow,
43
43
  } from "./returns-model";
44
44
  import { loadReturnSeries, type ReturnSeries } from "./returns-history";
45
+ import { formingHistoryBar, formingHistoryBarText, historyBarDate } from "./history-bars";
45
46
 
46
47
  type ReturnColumnId = "time" | "price" | "intervalChange" | "intervalPercent" | "cumulativeChange" | "cumulativePercent";
47
48
  type ReturnColumn = DataTableColumn & { id: ReturnColumnId };
@@ -185,12 +186,21 @@ export function ReturnsPane({ focused, width, height }: PaneProps) {
185
186
  const hints = useMemo<PaneHint[]>(() => (
186
187
  table.searchable ? [{ id: "search", key: "/", label: "search", onPress: focusSearch }] : []
187
188
  ), [focusSearch, table.searchable]);
189
+ // A weekly or monthly interval's newest bar is its week or month so far when that has not ended.
190
+ const newestDate = returnRows[0] ? new Date(returnRows[0].timestamp).toISOString().slice(0, 10) : undefined;
191
+ const forming = useMemo(
192
+ () => data ? formingHistoryBar(data.resolution, newestDate, data.venue || undefined, Date.now()) : null,
193
+ [data, newestDate],
194
+ );
195
+ const formingKey = forming ? returnRows[0]?.key : undefined;
196
+ const barSize = data?.resolution ?? shownResolution;
188
197
  // A shut market's window ends at its last session, which the footer names.
189
- const marketInfo = useMemo<PaneFooterSegment[]>(() => (
190
- data?.lastSession
191
- ? [{ id: "market", parts: [{ text: closedMarketNote(data.lastSession, data.visibleTo), tone: "muted" }] }]
192
- : []
193
- ), [data]);
198
+ const marketInfo = useMemo<PaneFooterSegment[]>(() => [
199
+ ...data?.lastSession
200
+ ? [{ id: "market", parts: [{ text: closedMarketNote(data.lastSession, data.visibleTo), tone: "muted" as const }] }]
201
+ : [],
202
+ ...forming && newestDate ? [{ id: "forming", parts: [{ text: formingHistoryBarText(forming, newestDate), tone: "muted" as const }] }] : [],
203
+ ], [data, forming, newestDate]);
194
204
  usePaneStatusFooter({ registrationId: "returns", loading, error, hints, info: marketInfo });
195
205
 
196
206
  const integrityNotice = priceHistoryIntegrityNotice(returnRows.filter((row) => row.inconsistent).length);
@@ -208,8 +218,15 @@ export function ReturnsPane({ focused, width, height }: PaneProps) {
208
218
 
209
219
  const renderCell = useCallback((row: ReturnRow, column: ReturnColumn): DataTableCell => {
210
220
  switch (column.id) {
211
- case "time":
212
- return { text: formatDateTime(new Date(row.timestamp)), value: new Date(row.timestamp).toISOString(), color: colors.textDim };
221
+ case "time": {
222
+ const shown = formatDateTime(new Date(row.timestamp));
223
+ // A daily or longer bar is a date; a month's reads as the month, and one still running says so.
224
+ return {
225
+ text: shown.length > 10 ? shown : historyBarDate(shown, barSize, row.key === formingKey),
226
+ value: new Date(row.timestamp).toISOString(),
227
+ color: colors.textDim,
228
+ };
229
+ }
213
230
  case "price":
214
231
  return { text: formatMaybePrice(row.price, priceDecimals, column.width), value: exportPrice(row.price, priceDecimals), color: colors.textBright, attributes: TextAttributes.BOLD };
215
232
  case "intervalChange":
@@ -221,7 +238,7 @@ export function ReturnsPane({ focused, width, height }: PaneProps) {
221
238
  case "cumulativePercent":
222
239
  return { text: formatMaybePercent(row.cumulativePercent), value: row.cumulativePercent === null ? null : row.cumulativePercent * 100, color: priceColor(row.cumulativePercent ?? 0) };
223
240
  }
224
- }, [priceDecimals]);
241
+ }, [barSize, formingKey, priceDecimals]);
225
242
 
226
243
  return (
227
244
  <DataTableView<ReturnRow, ReturnColumn>
@@ -270,6 +287,7 @@ export function ReturnsPane({ focused, width, height }: PaneProps) {
270
287
  ["Ticker", symbol ? publicTickerKey(symbol, exchange) : ""],
271
288
  ["Range", data?.range ?? range],
272
289
  ["Interval", getChartResolutionLabel(data?.resolution ?? shownResolution)],
290
+ ...(forming && newestDate ? [["Partial bar", `${newestDate}, ${formingHistoryBarText(forming, newestDate)}`]] : []),
273
291
  ["Window", data ? `after ${new Date(data.visibleFrom).toISOString()} through ${new Date(data.visibleTo).toISOString()}` : ""],
274
292
  ...(data?.lastSession ? [["Market", closedMarketNote(data.lastSession, data.visibleTo)]] : []),
275
293
  ["Time zone", "UTC, bar open"],