gloomberb 0.18.3 → 0.18.4

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 (886) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/src/account/checkout-handoff.tsx +225 -0
  6. package/src/account/device-signin-dialog.tsx +2 -2
  7. package/src/account/device-signin.ts +2 -2
  8. package/src/account/upgrade-dialog.tsx +1 -1
  9. package/src/api-client/askg.ts +2 -2
  10. package/src/api-client/auth.ts +2 -2
  11. package/src/api-client/central-bank-rates.ts +6 -0
  12. package/src/api-client/collections.ts +5 -1
  13. package/src/api-client/cot.ts +2 -0
  14. package/src/api-client/crypto-etf-flows.ts +37 -0
  15. package/src/api-client/crypto-markets.ts +60 -0
  16. package/src/api-client/data.ts +84 -5
  17. package/src/api-client/doe.ts +15 -0
  18. package/src/api-client/equity-screener.ts +28 -0
  19. package/src/api-client/exchange-announcements.ts +38 -0
  20. package/src/api-client/fund-facts.ts +39 -0
  21. package/src/api-client/futures-curve.ts +9 -1
  22. package/src/api-client/hiring.ts +301 -0
  23. package/src/api-client/index.ts +22 -5
  24. package/src/api-client/market-discovery.ts +14 -0
  25. package/src/api-client/members.ts +6 -0
  26. package/src/api-client/mna.ts +6 -0
  27. package/src/api-client/paths.ts +18 -1
  28. package/src/api-client/request.ts +21 -4
  29. package/src/api-client/short-side-publications.ts +37 -0
  30. package/src/api-client/socket.ts +64 -4
  31. package/src/api-client/swap-curve.ts +35 -0
  32. package/src/api-client/themes.ts +7 -1
  33. package/src/api-client/types.ts +90 -2
  34. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  35. package/src/app/runtime/desktop-deeplink.ts +5 -5
  36. package/src/app/runtime/plugin-bindings.ts +2 -2
  37. package/src/app/runtime/startup.ts +13 -0
  38. package/src/app/star-prompt/status-line.tsx +2 -2
  39. package/src/architecture/core-builtin-allowlist.json +5 -2
  40. package/src/architecture/ui-literals-allowlist.json +3 -3
  41. package/src/architecture/ui-tokens-allowlist.json +1 -1
  42. package/src/brokers/broker-portfolio-sync.ts +37 -0
  43. package/src/brokers/directory.ts +11 -0
  44. package/src/brokers/logos.ts +3 -1
  45. package/src/brokers/signed-in/adapter.ts +304 -26
  46. package/src/brokers/signed-in/client.ts +14 -2
  47. package/src/brokers/signed-in/connect.ts +10 -2
  48. package/src/brokers/sync-broker-instance.ts +9 -1
  49. package/src/capabilities/chart-series.ts +22 -6
  50. package/src/cli/bank-section.ts +1 -1
  51. package/src/cli/base-converter.ts +23 -14
  52. package/src/cli/central-bank-events.ts +1 -1
  53. package/src/cli/command-options.ts +59 -4
  54. package/src/cli/commands/api.ts +9 -6
  55. package/src/cli/commands/broker.ts +2 -2
  56. package/src/cli/commands/command-utils.ts +2 -2
  57. package/src/cli/commands/crypto-hints.ts +7 -20
  58. package/src/cli/commands/fred-series.ts +4 -2
  59. package/src/cli/commands/keybindings.ts +2 -2
  60. package/src/cli/commands/market.ts +1117 -264
  61. package/src/cli/commands/news-hints.ts +2 -2
  62. package/src/cli/commands/news-search.ts +59 -6
  63. package/src/cli/commands/options-leaps.ts +41 -26
  64. package/src/cli/commands/overview.ts +121 -48
  65. package/src/cli/commands/plugins.ts +9 -9
  66. package/src/cli/commands/remote.ts +13 -10
  67. package/src/cli/commands/search.ts +64 -44
  68. package/src/cli/commands/system.ts +27 -19
  69. package/src/cli/commands/themes.ts +1 -1
  70. package/src/cli/commands/ticker.ts +192 -47
  71. package/src/cli/context.ts +3 -2
  72. package/src/cli/desktop-pane-shot-view.ts +2 -2
  73. package/src/cli/desktop-pane-shot.ts +1 -1
  74. package/src/cli/earnings-calendar.ts +4 -4
  75. package/src/cli/entry.ts +18 -1
  76. package/src/cli/errors.ts +20 -2
  77. package/src/cli/exit-codes.ts +1 -1
  78. package/src/cli/export-source.ts +10 -4
  79. package/src/cli/freshness.ts +2 -8
  80. package/src/cli/fx-forward.ts +130 -0
  81. package/src/cli/fx-pair.ts +10 -9
  82. package/src/cli/glossary.ts +64 -20
  83. package/src/cli/help.ts +19 -13
  84. package/src/cli/history-export.ts +126 -0
  85. package/src/cli/history-rows.ts +196 -43
  86. package/src/cli/index-roots.ts +5 -45
  87. package/src/cli/index.ts +24 -18
  88. package/src/cli/known-gaps.ts +118 -25
  89. package/src/cli/listing-arg.ts +300 -41
  90. package/src/cli/name-entries.ts +30 -18
  91. package/src/cli/native-smoke.ts +2 -0
  92. package/src/cli/not-a-ticker.ts +19 -9
  93. package/src/cli/opentui-libc.ts +5 -0
  94. package/src/cli/options.ts +12 -0
  95. package/src/cli/pane-functions/capabilities.ts +75 -20
  96. package/src/cli/pane-functions/catalog.ts +24 -23
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +10 -7
  99. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  100. package/src/cli/pane-functions/freshness.ts +174 -23
  101. package/src/cli/pane-functions/function-help.ts +66 -27
  102. package/src/cli/pane-functions/headless.ts +24 -11
  103. package/src/cli/pane-functions/index.ts +18 -16
  104. package/src/cli/pane-functions/options.ts +22 -2
  105. package/src/cli/pane-functions/report-notices.ts +12 -4
  106. package/src/cli/pane-functions/report.ts +5 -5
  107. package/src/cli/pane-functions/resolver.ts +47 -10
  108. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  109. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  110. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  111. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  112. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  113. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  114. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  115. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  116. package/src/cli/pane-functions/shot-options.ts +8 -3
  117. package/src/cli/peso-dollar-rates.ts +79 -0
  118. package/src/cli/quote-answer.ts +38 -3
  119. package/src/cli/report-tables.ts +61 -16
  120. package/src/cli/restore-plugins.ts +29 -14
  121. package/src/cli/result.ts +111 -22
  122. package/src/cli/series-search.ts +5 -5
  123. package/src/cli/statement-filings.ts +19 -0
  124. package/src/cli/suffixed-listing-rows.ts +49 -0
  125. package/src/cli/symbol-args.ts +50 -15
  126. package/src/cli/symbol-cells.ts +120 -0
  127. package/src/cli/symbol-list.ts +198 -68
  128. package/src/cli/symbol-rows.ts +131 -25
  129. package/src/cli/ticker-resolution.ts +108 -11
  130. package/src/cli/treasury-yields.ts +5 -5
  131. package/src/cli/types.ts +2 -0
  132. package/src/cli/uncovered-instrument.ts +3 -3
  133. package/src/cli/unknown-command.ts +6 -6
  134. package/src/components/chart/composite/chart-layout.ts +131 -0
  135. package/src/components/chart/composite/composite-chart.tsx +373 -16
  136. package/src/components/chart/composite/interactions.ts +7 -2
  137. package/src/components/chart/composite/legend.tsx +75 -3
  138. package/src/components/chart/composite/levels.ts +5 -0
  139. package/src/components/chart/composite/panel-gestures.ts +41 -0
  140. package/src/components/chart/composite/panel-labels.ts +2 -1
  141. package/src/components/chart/composite/panel-surface.tsx +305 -11
  142. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  143. package/src/components/chart/composite/rasterizer.ts +44 -19
  144. package/src/components/chart/composite/scene.ts +16 -4
  145. package/src/components/chart/composite/text-renderer.ts +48 -21
  146. package/src/components/chart/composite/toolbar.tsx +52 -5
  147. package/src/components/chart/composite/types.ts +13 -0
  148. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  149. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  150. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  151. package/src/components/chart/composite/value-scale.ts +149 -0
  152. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  153. package/src/components/chart/core/pointer.ts +2 -0
  154. package/src/components/chart-table/index.ts +2 -0
  155. package/src/components/chart-table/read.tsx +74 -0
  156. package/src/components/command-bar/commands/collection-list.ts +41 -19
  157. package/src/components/command-bar/commands/collection.ts +9 -3
  158. package/src/components/command-bar/commands/direct/index.ts +1 -1
  159. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  160. package/src/components/command-bar/pane-templates/items.ts +59 -6
  161. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  162. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  163. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  164. package/src/components/command-bar/routes/root/results.ts +18 -4
  165. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  166. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  167. package/src/components/command-bar/routes/root/selection.ts +6 -1
  168. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  169. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  170. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  171. package/src/components/command-bar/selection-runtime.ts +50 -10
  172. package/src/components/command-bar/surface/index.tsx +24 -2
  173. package/src/components/command-bar/view-model.ts +7 -0
  174. package/src/components/command-bar/workflow/broker.ts +2 -2
  175. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  176. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  177. package/src/components/command-bar/workflow/fields.ts +8 -2
  178. package/src/components/command-bar/workflow/ops.ts +18 -4
  179. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  180. package/src/components/command-bar/workflow/submit.ts +3 -2
  181. package/src/components/command-bar/workflow/tickers.ts +5 -1
  182. package/src/components/company-logo.tsx +39 -0
  183. package/src/components/data-table/sections.ts +4 -2
  184. package/src/components/form-modal/confirm.tsx +2 -1
  185. package/src/components/form-modal/request.ts +5 -0
  186. package/src/components/form-modal/routes.ts +4 -1
  187. package/src/components/index.ts +12 -6
  188. package/src/components/layout/header.tsx +7 -6
  189. package/src/components/layout/market-summary.ts +9 -6
  190. package/src/components/layout/pane/capture-status.ts +1 -1
  191. package/src/components/layout/pane/footer/model.ts +11 -5
  192. package/src/components/layout/shell/chrome.ts +19 -6
  193. package/src/components/layout/shell/index.tsx +2 -1
  194. package/src/components/layout/shell/pane/layers.tsx +19 -1
  195. package/src/components/layout/status-bar.tsx +2 -2
  196. package/src/components/market-board/index.tsx +11 -3
  197. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  198. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  199. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  200. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  201. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  202. package/src/components/pane-settings-dialog/value.ts +8 -1
  203. package/src/components/pane-settings-dialog.tsx +44 -13
  204. package/src/components/sign-in-code-panel.tsx +27 -19
  205. package/src/components/ui/column-grid.tsx +48 -4
  206. package/src/components/ui/country-flag-art.tsx +180 -0
  207. package/src/components/ui/country-flag.tsx +118 -12
  208. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  209. package/src/components/ui/data-table/opentui/model.ts +109 -2
  210. package/src/components/ui/data-table/types.ts +1 -1
  211. package/src/components/ui/display.tsx +5 -1
  212. package/src/components/ui/index.ts +3 -1
  213. package/src/components/ui/logo-mark.tsx +11 -2
  214. package/src/components/ui/query-bar.tsx +1 -1
  215. package/src/components/ui/row-notes.ts +79 -0
  216. package/src/core/state/app/layout.ts +4 -4
  217. package/src/data/cached-query.ts +8 -1
  218. package/src/data/config/chart-settings.ts +3 -3
  219. package/src/data/config/home.ts +10 -2
  220. package/src/data/config/layout.ts +4 -1
  221. package/src/data/config/store/node.ts +4 -0
  222. package/src/data/config/store/normalize.ts +13 -3
  223. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  224. package/src/data/json-storage.ts +2 -0
  225. package/src/data/saved-copies.ts +84 -0
  226. package/src/docs/snapshot.json +65 -32
  227. package/src/i18n/es.ts +29 -12
  228. package/src/i18n/ja.ts +29 -12
  229. package/src/i18n/ko.ts +29 -12
  230. package/src/i18n/zh-cn.ts +29 -12
  231. package/src/i18n/zh-tw.ts +29 -12
  232. package/src/layout/desks.ts +1 -1
  233. package/src/layout/launch-layout.ts +1 -1
  234. package/src/layout/pane-manager/floating-actions.ts +5 -3
  235. package/src/layout/pane-manager/floating.ts +43 -1
  236. package/src/layout/pane-manager/index.ts +2 -0
  237. package/src/layout/selected-ticker.ts +74 -0
  238. package/src/market-data/depositary-pair.ts +251 -0
  239. package/src/market-data/futures-board.ts +1 -1
  240. package/src/market-data/futures-contract.ts +124 -40
  241. package/src/market-data/fx-closes.ts +17 -2
  242. package/src/market-data/hooks.tsx +19 -11
  243. package/src/market-data/market/change-basis.ts +49 -7
  244. package/src/market-data/market/freshness.ts +34 -5
  245. package/src/market-data/market/period-return.ts +163 -0
  246. package/src/market-data/market/trading-sessions.ts +13 -0
  247. package/src/market-data/market/year-to-date.ts +8 -13
  248. package/src/market-data/performance.ts +20 -14
  249. package/src/market-data/perpetual-premium.ts +32 -0
  250. package/src/market-data/published-apac-sessions.ts +2 -1
  251. package/src/market-data/published-futures-sessions.ts +69 -0
  252. package/src/market-data/quotes/contributions.ts +5 -1
  253. package/src/market-data/quotes/freshness.ts +42 -0
  254. package/src/market-data/quotes/intraday-bar.ts +37 -0
  255. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  256. package/src/market-data/quotes/resolution.ts +4 -2
  257. package/src/market-data/tax-equivalent.ts +1 -1
  258. package/src/market-data/ticker-price-returns.ts +3 -1
  259. package/src/news/aggregator.ts +5 -1
  260. package/src/news/news-model.ts +4 -0
  261. package/src/news/types.ts +11 -0
  262. package/src/notifications/app-notifier.ts +1 -1
  263. package/src/plugins/auto-update.ts +2 -2
  264. package/src/plugins/builtin/account-management/index.tsx +1 -0
  265. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  266. package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
  267. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  268. package/src/plugins/builtin/alerts/cli.ts +485 -76
  269. package/src/plugins/builtin/alerts/command.ts +5 -10
  270. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  271. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  272. package/src/plugins/builtin/alerts/events.ts +107 -5
  273. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  274. package/src/plugins/builtin/alerts/format.ts +2 -1
  275. package/src/plugins/builtin/alerts/headless.ts +100 -39
  276. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  277. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  278. package/src/plugins/builtin/alerts/index.tsx +45 -18
  279. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  280. package/src/plugins/builtin/alerts/levels.ts +3 -3
  281. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  282. package/src/plugins/builtin/alerts/price.ts +35 -0
  283. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  284. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  285. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  286. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  287. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  288. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  289. package/src/plugins/builtin/alerts/storage.ts +13 -10
  290. package/src/plugins/builtin/alerts/targets.ts +12 -3
  291. package/src/plugins/builtin/analytics/index.tsx +8 -2
  292. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  293. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  294. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  295. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  296. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  297. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  298. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  299. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  300. package/src/plugins/builtin/attention/pane.tsx +6 -2
  301. package/src/plugins/builtin/awards/headless.ts +7 -3
  302. package/src/plugins/builtin/awards/model.ts +18 -0
  303. package/src/plugins/builtin/awards/pane.tsx +6 -3
  304. package/src/plugins/builtin/backtest/headless.ts +3 -3
  305. package/src/plugins/builtin/backtest/rules.ts +41 -5
  306. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  307. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  308. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  309. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  310. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  311. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  312. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  313. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  314. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  315. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  316. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  317. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  318. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  319. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  320. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  321. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  322. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  323. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  324. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  325. package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
  326. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  327. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  328. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  329. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  330. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  331. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  332. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  333. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  334. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  335. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  336. package/src/plugins/builtin/catalysts/model.ts +49 -4
  337. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  338. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  339. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  340. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  341. package/src/plugins/builtin/changelog/index.tsx +1 -0
  342. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  343. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  344. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  345. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  346. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  347. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  348. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  349. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  350. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  351. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  352. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  353. package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
  354. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  355. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  356. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  357. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  358. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  359. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  360. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  361. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  362. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  363. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  364. package/src/plugins/builtin/chat/people.ts +1 -1
  365. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  366. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  367. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  368. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  369. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  370. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  371. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  372. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  373. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  374. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  375. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  376. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  377. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  378. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  379. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  380. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  381. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  382. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  383. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  384. package/src/plugins/builtin/company-attention/client.ts +117 -1
  385. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  386. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  387. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  388. package/src/plugins/builtin/company-attention/model.ts +33 -7
  389. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  390. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  391. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  392. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  393. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  394. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  395. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  396. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  397. package/src/plugins/builtin/composite-plugins.ts +2 -1
  398. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  399. package/src/plugins/builtin/connections/index.ts +1 -0
  400. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  401. package/src/plugins/builtin/correlation/headless.ts +5 -3
  402. package/src/plugins/builtin/cot/headless.ts +28 -6
  403. package/src/plugins/builtin/cot/model.ts +12 -0
  404. package/src/plugins/builtin/cot/pane.tsx +3 -2
  405. package/src/plugins/builtin/cpi/headless.ts +5 -1
  406. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  407. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  408. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  409. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  410. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  411. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  412. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  413. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  414. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  415. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  416. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  417. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  418. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  419. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  420. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  421. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  422. package/src/plugins/builtin/debug/index.tsx +1 -0
  423. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  424. package/src/plugins/builtin/docs/index.tsx +1 -1
  425. package/src/plugins/builtin/docs/pane.tsx +2 -2
  426. package/src/plugins/builtin/docs/targets.ts +1 -1
  427. package/src/plugins/builtin/doe/client.ts +5 -1
  428. package/src/plugins/builtin/doe/headless.ts +12 -6
  429. package/src/plugins/builtin/doe/model.ts +43 -6
  430. package/src/plugins/builtin/doe/pane.tsx +18 -11
  431. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  432. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  433. package/src/plugins/builtin/earnings/board.tsx +253 -50
  434. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  435. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  436. package/src/plugins/builtin/earnings/client.ts +4 -3
  437. package/src/plugins/builtin/earnings/headless.ts +53 -15
  438. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  439. package/src/plugins/builtin/earnings/index.tsx +15 -22
  440. package/src/plugins/builtin/earnings/model.ts +17 -12
  441. package/src/plugins/builtin/earnings/scope.ts +89 -0
  442. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  443. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  444. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  445. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  446. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  447. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  448. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  449. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  450. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  451. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  452. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  453. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  454. package/src/plugins/builtin/econ/index.tsx +112 -25
  455. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  456. package/src/plugins/builtin/econ/types.ts +32 -1
  457. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  458. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  459. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  460. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  461. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  462. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  463. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  464. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  465. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  466. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  467. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  468. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  469. package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
  470. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  471. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  472. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  473. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  474. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  475. package/src/plugins/builtin/exposure/headless.ts +51 -6
  476. package/src/plugins/builtin/exposure/index.tsx +28 -2
  477. package/src/plugins/builtin/exposure/model.ts +7 -0
  478. package/src/plugins/builtin/exposure/pane.tsx +6 -1
  479. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  480. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  481. package/src/plugins/builtin/futures/model.ts +10 -9
  482. package/src/plugins/builtin/futures/returns.ts +8 -36
  483. package/src/plugins/builtin/futures/table.tsx +1 -1
  484. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  485. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  486. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  487. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  488. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  489. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  490. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  491. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  492. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  493. package/src/plugins/builtin/gpu/headless.ts +9 -4
  494. package/src/plugins/builtin/help/index.tsx +13 -3
  495. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  496. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  497. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  498. package/src/plugins/builtin/holders/client.ts +13 -1
  499. package/src/plugins/builtin/holders/format.ts +28 -17
  500. package/src/plugins/builtin/holders/headless.ts +46 -7
  501. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  502. package/src/plugins/builtin/holders/pane.tsx +79 -15
  503. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  504. package/src/plugins/builtin/holders/table-model.ts +2 -1
  505. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  506. package/src/plugins/builtin/insider/headless.ts +1 -1
  507. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  508. package/src/plugins/builtin/insider/signals.tsx +1 -1
  509. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  510. package/src/plugins/builtin/iv-history/client.ts +20 -0
  511. package/src/plugins/builtin/iv-history/headless.ts +4 -4
  512. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  513. package/src/plugins/builtin/iv-history/model.ts +13 -4
  514. package/src/plugins/builtin/iv-history/series.ts +3 -1
  515. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  516. package/src/plugins/builtin/jobs/model.ts +4 -15
  517. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  518. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  519. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  520. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  521. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  522. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  523. package/src/plugins/builtin/macro-day/model.ts +29 -8
  524. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  525. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  526. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  527. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  528. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  529. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  530. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  531. package/src/plugins/builtin/market-movers/client.ts +33 -19
  532. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  533. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  534. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  535. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  536. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  537. package/src/plugins/builtin/market-movers/table.ts +4 -1
  538. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  539. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  540. package/src/plugins/builtin/members/headless.ts +6 -5
  541. package/src/plugins/builtin/members/pane.tsx +11 -4
  542. package/src/plugins/builtin/mna/client.ts +1 -0
  543. package/src/plugins/builtin/mna/detail.tsx +20 -32
  544. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  545. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  546. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  547. package/src/plugins/builtin/mna/headless.ts +6 -13
  548. package/src/plugins/builtin/mna/model.ts +93 -15
  549. package/src/plugins/builtin/mna/pane.tsx +5 -4
  550. package/src/plugins/builtin/news/headless.ts +12 -6
  551. package/src/plugins/builtin/news/index.tsx +10 -1
  552. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  553. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  554. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  555. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  556. package/src/plugins/builtin/notes/cli.ts +49 -14
  557. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  558. package/src/plugins/builtin/options/carry.ts +2 -2
  559. package/src/plugins/builtin/options/index.tsx +1 -1
  560. package/src/plugins/builtin/options/view.tsx +10 -10
  561. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  562. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  563. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  564. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  565. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  566. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  567. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  568. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  569. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  570. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  571. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  572. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  573. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  574. package/src/plugins/builtin/perps/freshness.ts +8 -5
  575. package/src/plugins/builtin/perps/headless.ts +3 -1
  576. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  577. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  578. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  579. package/src/plugins/builtin/perps/pane.tsx +36 -17
  580. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  581. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  582. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  583. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  584. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  585. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  586. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  587. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  588. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  589. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  590. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  591. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  592. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  593. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  594. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  595. package/src/plugins/builtin/power/client.ts +4 -1
  596. package/src/plugins/builtin/power/evidence.ts +22 -7
  597. package/src/plugins/builtin/power/gas.tsx +5 -1
  598. package/src/plugins/builtin/power/pane.tsx +8 -1
  599. package/src/plugins/builtin/power/prices.tsx +10 -3
  600. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  601. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  603. package/src/plugins/builtin/research/event-model.ts +3 -1
  604. package/src/plugins/builtin/research/event-sources.ts +12 -4
  605. package/src/plugins/builtin/research/index.tsx +2 -1
  606. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  608. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  609. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  610. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  611. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  612. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  613. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  614. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  615. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  616. package/src/plugins/builtin/sec/forms.ts +13 -0
  617. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  618. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  619. package/src/plugins/builtin/sec/headless.ts +85 -8
  620. package/src/plugins/builtin/sec/index.tsx +58 -12
  621. package/src/plugins/builtin/sectors/client.ts +2 -1
  622. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  623. package/src/plugins/builtin/series-inventory.ts +2 -0
  624. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  625. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  626. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  627. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  628. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  629. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  630. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  631. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  632. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  633. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  634. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  635. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  636. package/src/plugins/builtin/short-interest/client.ts +2 -0
  637. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  638. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  639. package/src/plugins/builtin/short-interest/model.ts +70 -19
  640. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  641. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  642. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  643. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  644. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  645. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  646. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  647. package/src/plugins/builtin/short-interest/types.ts +9 -0
  648. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  649. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  650. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  651. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  652. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  653. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  654. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  655. package/src/plugins/builtin/themes/headless.ts +8 -5
  656. package/src/plugins/builtin/themes/model.ts +14 -4
  657. package/src/plugins/builtin/themes/pane.tsx +24 -5
  658. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  659. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  660. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  661. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  662. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  663. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  664. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  665. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  666. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  667. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  668. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  669. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  670. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  671. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  672. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  673. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  674. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  675. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  676. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  677. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  678. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  679. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  680. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  681. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  682. package/src/plugins/builtin/vol-surface/client.ts +5 -4
  683. package/src/plugins/builtin/vol-surface/headless.ts +12 -3
  684. package/src/plugins/builtin/vol-surface/model.ts +4 -2
  685. package/src/plugins/builtin/volatility/model.ts +5 -10
  686. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  687. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  688. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  689. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  690. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  691. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  692. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  693. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  694. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  695. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  696. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  697. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  698. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  699. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  700. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  701. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  702. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  703. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  704. package/src/plugins/bundle.ts +1 -1
  705. package/src/plugins/catalog-browser.ts +2 -1
  706. package/src/plugins/compat.ts +3 -3
  707. package/src/plugins/dependencies.ts +75 -14
  708. package/src/plugins/extracted-plugins.ts +132 -34
  709. package/src/plugins/host-link.ts +149 -34
  710. package/src/plugins/installer.ts +35 -10
  711. package/src/plugins/loader.ts +206 -38
  712. package/src/plugins/manager-node.ts +2 -2
  713. package/src/plugins/marketplace/deactivation.ts +22 -0
  714. package/src/plugins/marketplace/model.ts +2 -2
  715. package/src/plugins/marketplace/packs.ts +1 -1
  716. package/src/plugins/ownership.ts +1 -1
  717. package/src/plugins/peer-retry.ts +155 -0
  718. package/src/plugins/registry/contributions.ts +3 -1
  719. package/src/plugins/registry/index.ts +4 -3
  720. package/src/plugins/registry/plugin-state.ts +3 -0
  721. package/src/plugins/seed-notice.ts +20 -0
  722. package/src/plugins/shortcut-argument.ts +39 -0
  723. package/src/portfolio/allocation.ts +1 -1
  724. package/src/portfolio/collection-name.ts +31 -0
  725. package/src/portfolio/column-values.ts +10 -8
  726. package/src/portfolio/cost-fx.ts +296 -19
  727. package/src/portfolio/manual-lots.ts +75 -0
  728. package/src/portfolio/mutations.ts +60 -22
  729. package/src/portfolio/suffixed-listings.ts +209 -0
  730. package/src/portfolio/totals-currency.ts +24 -0
  731. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  732. package/src/public/time-series.ts +11 -8
  733. package/src/remote/schema.ts +1 -1
  734. package/src/renderers/browser/config-host.ts +3 -0
  735. package/src/renderers/browser/main.tsx +23 -3
  736. package/src/renderers/dom/boot-frame-page.ts +187 -0
  737. package/src/renderers/dom/boot-frame.ts +237 -0
  738. package/src/renderers/dom/build-assets.ts +46 -8
  739. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  740. package/src/renderers/dom/host/ascii-text.ts +16 -2
  741. package/src/renderers/dom/host/box.tsx +43 -2
  742. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  743. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  744. package/src/renderers/dom/host/image-surface.tsx +49 -0
  745. package/src/renderers/dom/host/media-surface.tsx +24 -18
  746. package/src/renderers/dom/host/mouse.ts +30 -0
  747. package/src/renderers/dom/host/size-observer.ts +1 -1
  748. package/src/renderers/dom/host/style.ts +1 -1
  749. package/src/renderers/dom/styles.css +76 -0
  750. package/src/renderers/dom/test-utils.tsx +2 -1
  751. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  752. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  753. package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
  754. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  755. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  756. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  757. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  758. package/src/renderers/electrobun/bun/index.ts +11 -1
  759. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  760. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  761. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  762. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  763. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  764. package/src/renderers/electrobun/view/config-host.ts +3 -0
  765. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  766. package/src/renderers/electrobun/view/main.tsx +30 -4
  767. package/src/renderers/electrobun/view/news-source.ts +5 -5
  768. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  769. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  770. package/src/renderers/opentui/browser-open.ts +88 -0
  771. package/src/renderers/opentui/host.tsx +5 -14
  772. package/src/renderers/opentui/image/loader.ts +3 -2
  773. package/src/renderers/opentui/native-smoke.ts +10 -1
  774. package/src/renderers/opentui/pane-image/index.ts +2 -1
  775. package/src/renderers/opentui/render-lib.ts +253 -0
  776. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  777. package/src/renderers/opentui/start.tsx +1 -1
  778. package/src/renderers/share/layout-view.tsx +2 -2
  779. package/src/renderers/share/main.tsx +4 -4
  780. package/src/renderers/share/view.tsx +1 -1
  781. package/src/series/resolve.ts +22 -6
  782. package/src/series/standalone.ts +30 -2
  783. package/src/series/types.ts +8 -1
  784. package/src/shares/api.ts +4 -1
  785. package/src/shares/pane.ts +1 -1
  786. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  787. package/src/sources/gloomberb-cloud/index.ts +32 -16
  788. package/src/sources/gloomberb-cloud/news.ts +39 -0
  789. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  790. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  791. package/src/sources/listing-symbols.ts +37 -0
  792. package/src/sources/provider-errors.ts +16 -2
  793. package/src/sources/provider-router/financial-routes.ts +21 -3
  794. package/src/sources/provider-router/financials.ts +15 -2
  795. package/src/sources/provider-router/history.ts +30 -8
  796. package/src/sources/provider-router/primary.ts +1 -1
  797. package/src/state/app/bootstrap.ts +23 -0
  798. package/src/state/hooks/inline-tickers.ts +30 -5
  799. package/src/sync/controller.ts +1 -1
  800. package/src/sync/core-contributors.ts +46 -14
  801. package/src/team/collections-sync.ts +2 -1
  802. package/src/team/collections.ts +178 -17
  803. package/src/telemetry/crash-reports.ts +17 -4
  804. package/src/test-support/builtin-panes.ts +1 -1
  805. package/src/theme/colors.ts +3 -30
  806. package/src/theme/ui-tokens.ts +37 -1
  807. package/src/tickers/company-name-listing.ts +210 -33
  808. package/src/tickers/index-roots.ts +47 -0
  809. package/src/tickers/instrument-label.ts +5 -1
  810. package/src/tickers/metadata.ts +10 -0
  811. package/src/tickers/perpetual-listing.ts +5 -2
  812. package/src/tickers/search/home-listing.ts +75 -0
  813. package/src/tickers/search/index.ts +76 -27
  814. package/src/tickers/search/ranking.ts +54 -4
  815. package/src/tickers/search/upsert.ts +29 -0
  816. package/src/tickers/terminal-codes.ts +416 -40
  817. package/src/time-series/bar-aggregation.ts +243 -0
  818. package/src/time-series/base-series.ts +307 -0
  819. package/src/time-series/chart-bounds.ts +349 -0
  820. package/src/time-series/chart-seed.ts +142 -0
  821. package/src/time-series/economic.ts +5 -0
  822. package/src/time-series/fundamentals.ts +18 -3
  823. package/src/time-series/history-acquisition.ts +499 -0
  824. package/src/time-series/leverage.ts +100 -0
  825. package/src/time-series/market-resolution.ts +4 -2
  826. package/src/time-series/market.ts +2 -1
  827. package/src/time-series/price-comparison.ts +175 -30
  828. package/src/time-series/range.ts +9 -1
  829. package/src/time-series/resolution.ts +174 -16
  830. package/src/time-series/resolve-context.ts +157 -0
  831. package/src/time-series/resolve.ts +126 -1577
  832. package/src/time-series/series-name.ts +38 -0
  833. package/src/time-series/series-presentation.ts +208 -0
  834. package/src/time-series/spec.ts +11 -6
  835. package/src/time-series/studies.ts +109 -12
  836. package/src/time-series/tail-reconcile.ts +121 -0
  837. package/src/time-series/types.ts +29 -2
  838. package/src/time-series/use-chart-resolution.ts +4 -5
  839. package/src/types/broker.ts +10 -0
  840. package/src/types/config.ts +14 -0
  841. package/src/types/data-provider.ts +14 -0
  842. package/src/types/exchange-rate.ts +6 -0
  843. package/src/types/financials.ts +104 -7
  844. package/src/types/headless.ts +76 -6
  845. package/src/types/instrument.ts +3 -0
  846. package/src/types/plugin.ts +65 -8
  847. package/src/types/price-history.ts +2 -0
  848. package/src/types/ticker.ts +13 -0
  849. package/src/types/trading.ts +59 -1
  850. package/src/ui/ascii-font.ts +13 -1
  851. package/src/ui/host.tsx +6 -1
  852. package/src/updater/command-names.ts +175 -0
  853. package/src/updater/index.ts +10 -5
  854. package/src/utils/calendar-date.ts +32 -15
  855. package/src/utils/cash-runway.ts +241 -0
  856. package/src/utils/central-banks.ts +42 -0
  857. package/src/utils/cli-output.ts +259 -80
  858. package/src/utils/contract-month.ts +16 -0
  859. package/src/utils/crypto-pair.ts +61 -3
  860. package/src/utils/currency-units.ts +29 -0
  861. package/src/utils/datetime-format.ts +10 -0
  862. package/src/utils/debug-log.ts +1 -1
  863. package/src/utils/decimal-comma.ts +39 -6
  864. package/src/utils/exchange-announcements.ts +71 -0
  865. package/src/utils/exchange-rate-snapshot.ts +10 -0
  866. package/src/utils/financial-statements.ts +83 -4
  867. package/src/utils/format.ts +34 -16
  868. package/src/utils/fundamentals.ts +150 -34
  869. package/src/utils/fx-market-hours.ts +10 -1
  870. package/src/utils/latest-financial-period.ts +8 -0
  871. package/src/utils/linux-libc.ts +54 -0
  872. package/src/utils/market-capitalization.ts +111 -15
  873. package/src/utils/max-drawdown.ts +64 -0
  874. package/src/utils/network-failure.ts +83 -0
  875. package/src/utils/option-expiry.ts +139 -7
  876. package/src/utils/price-earnings.ts +11 -5
  877. package/src/utils/price-history.ts +18 -8
  878. package/src/utils/price-window.ts +131 -0
  879. package/src/utils/release-date.ts +47 -0
  880. package/src/utils/sec.ts +3 -0
  881. package/src/utils/throttled-fetch.ts +11 -4
  882. package/src/utils/trailing-eps.ts +67 -0
  883. package/src/utils/typed-text.ts +21 -0
  884. package/src/utils/utc-time.ts +24 -1
  885. package/src/version.ts +6 -0
  886. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -1,13 +1,16 @@
1
1
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { Box, Text, TextAttributes, useUiCapabilities } from "../../../ui";
2
+ import { Box, Text, TextAttributes, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
3
3
  import {
4
4
  Badge,
5
5
  DataTableView,
6
+ usePagedRows,
6
7
  usePaneFooter,
7
8
  usePaneTabs,
8
9
  usePaneTicker,
10
+ useTableLoadMore,
9
11
  type DataTableCell,
10
12
  type DataTableKeyEvent,
13
+ type PageRequest,
11
14
  } from "../../../components";
12
15
  import { handleRefreshKey, loadingErrorFooterInfo } from "../../../components/data-table/table-pane";
13
16
  import { useAsyncResource } from "../../../react/async-resource";
@@ -22,8 +25,8 @@ import { THIRTEENF_TEMPLATE_ID } from "../thirteenf/model";
22
25
  import { useInResearchTab } from "../ticker-detail/research-tab-keys";
23
26
  import {
24
27
  displayDate,
28
+ formatHolderChangePercent,
25
29
  formatHolderOwnershipPercent,
26
- formatMaybePercent,
27
30
  formatMoneyCompact,
28
31
  formatSignedCompact,
29
32
  holderStakeMarketCap,
@@ -40,15 +43,23 @@ import {
40
43
  sortRows,
41
44
  VIEW_TABS,
42
45
  } from "./table-model";
43
- import { classSharesToday, loadHolderData } from "./client";
46
+ import { classSharesAsOf, classSharesToday, loadHolderData } from "./client";
44
47
  import { HoldersTreemap } from "./treemap";
45
48
  import { BeneficialOwnersView } from "./beneficial-view";
46
49
  import { useIssuerListing } from "../shared/ticker-request";
47
50
  import type { HolderColumn, HolderColumnId, HolderRow, SortPreference, ViewMode } from "./types";
48
51
  import { loadHolder13FMatches, type Holder13FMatch } from "./thirteenf-match";
52
+ import { indexedHolderUnits, indexHolderTicker, loadIndexedHolderPage, withIndexedHolders } from "./index-holders";
49
53
  import { useSampledValue, useTickerQuoteStream } from "../../../state/hooks/live-ticker-financials";
50
54
 
51
55
  const HOLDER_MARKET_CAP_SAMPLE_MS = 5_000;
56
+ /** Rows past the end of the table that a scroll loads the next page within, as `useTableLoadMore` does. */
57
+ const LOAD_MORE_ROWS = 8;
58
+
59
+ /** Index rows have their CIK, so their 13F filing needs no name search. */
60
+ function cikMatches(rows: readonly HolderRow[]): Map<string, Holder13FMatch> {
61
+ return new Map(rows.flatMap((row) => row.cik ? [[row.id, { cik: row.cik, fundName: row.name, periodOfReport: row.reportDate }]] : []));
62
+ }
52
63
 
53
64
  /** The width of a three-letter badge ("13F", "ADR"): the label and its padding. */
54
65
  const BADGE_WIDTH = 5;
@@ -64,6 +75,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
64
75
  const [fundMatching, setFundMatching] = useState(false);
65
76
  const [selectedId, setSelectedId] = useState<string | null>(null);
66
77
  const fundMatchAbortRef = useRef<AbortController | null>(null);
78
+ const tableScrollRef = useRef<ScrollBoxRenderable | null>(null);
67
79
 
68
80
  const exchange = ticker?.metadata.exchange ?? "";
69
81
  const issuerListing = useIssuerListing(ticker);
@@ -80,8 +92,33 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
80
92
  keepPreviousData: true,
81
93
  });
82
94
 
95
+ // A US line's 13F holders are every filer in the SEC holder index, paged
96
+ // as fn 13F pages them and asked beside the source's short list, which
97
+ // stands until the first page answers and whenever the index cannot be read.
98
+ const indexTicker = indexHolderTicker(symbol, exchange);
99
+ const loadIndexPage = useMemo(() => indexTicker
100
+ ? ({ offset, signal }: PageRequest) => loadIndexedHolderPage(indexTicker, offset, signal)
101
+ : null, [indexTicker]);
102
+ const index = usePagedRows(loadIndexPage, { getId: (row) => row.cik });
103
+ // The source's list kept from the previous ticker must not price this one's filers: they wait for its own.
104
+ const base = data && indexHolderTicker(data.symbol) === indexTicker ? data : null;
105
+ const indexed = index.rows.length > 0 && (!!base || !loading) && indexHolderTicker(symbol, exchange, base) != null;
106
+ const indexPending = !!indexTicker && index.loading && index.rows.length === 0;
107
+ // Index rows take the source's price; the quote's only when the source gave none, sampled so ticks do not re-sort.
108
+ // The rows follow the units in use, so a quote that is not the price used leaves them as they are.
109
+ const quotePrice = useSampledValue(financials?.quote?.price, HOLDER_MARKET_CAP_SAMPLE_MS, symbol ?? "");
110
+ const { price: unitPrice, classShares: unitClassShares } = indexedHolderUnits(base, quotePrice);
111
+ const listData = useMemo(() => {
112
+ const first = index.pages[0];
113
+ if (!indexed || !first || !indexTicker) return data;
114
+ return withIndexedHolders(base, indexTicker, { ...first, rows: index.rows }, {
115
+ ...(unitPrice != null ? { price: unitPrice } : {}),
116
+ ...(unitClassShares != null ? { classShares: unitClassShares } : {}),
117
+ });
118
+ }, [base, data, index.pages, index.rows, indexTicker, indexed, unitClassShares, unitPrice]);
119
+
83
120
  // The values' own currency: dollars from the 13F filings on a London line, not its pence.
84
- const currency = holderValueCurrency(data, ticker?.metadata.currency || "USD")!;
121
+ const currency = holderValueCurrency(listData, ticker?.metadata.currency || "USD")!;
85
122
  // A stake without a reported percentage is the holding's value over the
86
123
  // market cap, when both are in one currency. The stream keeps the cap
87
124
  // current, about once a second; the stakes follow it at most every few
@@ -91,10 +128,11 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
91
128
  const marketCap = useSampledValue(liveMarketCap, HOLDER_MARKET_CAP_SAMPLE_MS, `${symbol ?? ""}:${currency}`);
92
129
  // Today's share count, which a 13D/13G report's own base is checked against.
93
130
  const sharesOutstanding = classSharesToday(financials);
94
- const rows = useMemo(() => buildRows(data), [data]);
131
+ const sharesOutstandingAsOf = classSharesAsOf(financials);
132
+ const rows = useMemo(() => buildRows(listData), [listData]);
95
133
  const periodsDiffer = useMemo(() => holderPeriodsDiffer(rows), [rows]);
96
134
  const sortedRows = useMemo(() => sortRows(rows, sortPreference, marketCap), [marketCap, rows, sortPreference]);
97
- // Change columns only when the source reports a change; otherwise they read "-" on every row.
135
+ // Change columns only when the source reports a change; otherwise every row would read as missing.
98
136
  const showChange = useMemo(() => hasHolderChanges(rows), [rows]);
99
137
  const columns = useMemo(() => buildColumns(width, showChange), [showChange, width]);
100
138
  const selectedIdx = selectedId
@@ -114,8 +152,14 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
114
152
  // restart 25 two-request 13F lookups.
115
153
  useEffect(() => {
116
154
  fundMatchAbortRef.current?.abort();
155
+ if (rows.length > 0 && rows.every((row) => row.cik)) {
156
+ setFundMatches(cikMatches(rows));
157
+ setFundMatching(false);
158
+ return;
159
+ }
117
160
  setFundMatches(new Map());
118
- if (rows.length === 0) {
161
+ // The source's rows are not matched while the index's may replace them.
162
+ if (rows.length === 0 || indexPending) {
119
163
  setFundMatching(false);
120
164
  return;
121
165
  }
@@ -138,7 +182,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
138
182
  fundMatchAbortRef.current = null;
139
183
  }
140
184
  };
141
- }, [rows]);
185
+ }, [indexPending, rows]);
142
186
 
143
187
  const selectedRow = activeIdx >= 0 ? sortedRows[activeIdx] ?? null : null;
144
188
  const selectedFundMatch = selectedRow ? fundMatches.get(selectedRow.id) ?? null : null;
@@ -167,9 +211,12 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
167
211
  setViewMode(nextViewMode);
168
212
  }, [setViewMode]);
169
213
 
214
+ const reloadIndex = index.reload;
170
215
  const refresh = useCallback(() => {
171
216
  void reload();
172
- }, [reload]);
217
+ reloadIndex();
218
+ }, [reload, reloadIndex]);
219
+ const loadMoreFromScroll = useTableLoadMore(tableScrollRef, indexed && index.hasMore, index.loadMore);
173
220
 
174
221
  // Plain keys only: Cmd/Ctrl+Shift+R, S and O resize, share and pop out the pane.
175
222
  const handleKeyDown = useCallback((event: DataTableKeyEvent) => {
@@ -261,7 +308,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
261
308
  };
262
309
  case "changePercent":
263
310
  return {
264
- text: formatMaybePercent(row.changePercent),
311
+ text: formatHolderChangePercent(row.changePercent),
265
312
  color: row.changePercent != null ? priceColor(row.changePercent) : colors.textDim,
266
313
  };
267
314
  case "percentHeld":
@@ -282,8 +329,14 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
282
329
  // One date only when every holder's row is of it; the PERIOD column dates each row.
283
330
  ...(periodsDiffer
284
331
  ? [{ id: "as-of", parts: [{ text: "latest period per holder", tone: "muted" as const }] }]
285
- : data?.asOf ? [{ id: "as-of", parts: [{ text: data.asOf, tone: "value" as const }] }] : []),
286
- ...loadingErrorFooterInfo(loading, data ? error : null),
332
+ : listData?.asOf ? [{ id: "as-of", parts: [{ text: listData.asOf, tone: "value" as const }] }] : []),
333
+ // The index's first page replaces the source's list, so it is loading too; a failed one leaves that list.
334
+ ...loadingErrorFooterInfo(loading || (indexPending && !!data), listData ? error : null),
335
+ ...(index.loadingMore ? [{ id: "loading-more", parts: [{ text: "loading more", tone: "muted" as const }] }] : []),
336
+ // A later page that failed keeps the rows loaded; scrolling asks for it again.
337
+ ...(indexed && index.moreError && !index.loadingMore
338
+ ? [{ id: "more-error", parts: [{ text: "more holders could not be read", tone: "warning" as const }] }]
339
+ : []),
287
340
  ...(fundMatching ? [{ id: "fund-matching", parts: [{ text: "13F matching", tone: "muted" as const }] }] : []),
288
341
  ],
289
342
  // The title-bar tabs (or the query bar inside Ticker Research) switch
@@ -293,7 +346,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
293
346
  ...(selectedFundMatch ? [{ id: "fund", key: "o", label: "pen 13F", onPress: () => openFundDetail(selectedRow) }] : []),
294
347
  ],
295
348
  };
296
- }, [data, error, fundMatching, loading, openFundDetail, periodsDiffer, selectedFundMatch, selectedRow, viewMode]);
349
+ }, [data, error, fundMatching, index.loadingMore, index.moreError, indexed, indexPending, listData, loading, openFundDetail, periodsDiffer, selectedFundMatch, selectedRow, viewMode]);
297
350
 
298
351
  const selectView = useCallback((value: string) => setViewMode(value as ViewMode), [setViewMode]);
299
352
  // As a research tab, h/l move between research tabs; `s` switches the view.
@@ -313,11 +366,19 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
313
366
  // values" while the request is still in flight or the pane has no ticker.
314
367
  const statusTitle = !symbol
315
368
  ? "No ticker selected."
316
- : loading && !data
369
+ : (loading || indexPending) && !listData
317
370
  ? "Loading holders..."
318
- : !data && error ? error : sortedRows.length === 0 ? "No holders available" : null;
371
+ : !listData && error ? error : sortedRows.length === 0 ? "No holders available" : null;
319
372
  const chartHeight = Math.max(1, height - tabRows - (nativePaneChrome ? 1 : 0));
320
373
 
374
+ // A list shorter than the table cannot scroll to load more, so it pages on
375
+ // until it fills the table, as a scroll would; a failed page waits for one.
376
+ const { hasMore: indexHasMore, loading: indexLoading, loadingMore: indexLoadingMore, moreError: indexMoreError, loadMore: loadMoreIndex } = index;
377
+ useEffect(() => {
378
+ if (viewMode !== "table" || !indexed || !indexHasMore || indexLoading || indexLoadingMore || indexMoreError) return;
379
+ if (sortedRows.length < chartHeight + LOAD_MORE_ROWS) loadMoreIndex();
380
+ }, [chartHeight, indexHasMore, indexLoading, indexLoadingMore, indexMoreError, indexed, loadMoreIndex, sortedRows.length, viewMode]);
381
+
321
382
  return (
322
383
  <Box flexDirection="column" width={width} height={height}>
323
384
  {nativePaneChrome ? tabStrip : tabStrip && <Box height={1} paddingX={1}>{tabStrip}</Box>}
@@ -333,6 +394,8 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
333
394
  }}
334
395
  onActivate={openFundDetail}
335
396
  onRootKeyDown={handleKeyDown}
397
+ scrollRef={tableScrollRef}
398
+ onBodyScrollActivity={loadMoreFromScroll}
336
399
  resetScrollKey={data?.symbol}
337
400
  rootWidth={width}
338
401
  columns={columns}
@@ -354,6 +417,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
354
417
  holderRows={rows}
355
418
  fundMatches={fundMatches}
356
419
  sharesOutstanding={sharesOutstanding}
420
+ sharesOutstandingAsOf={sharesOutstandingAsOf}
357
421
  onCycleView={toggleView}
358
422
  onRefreshHolders={refresh}
359
423
  />
@@ -1,8 +1,9 @@
1
1
  import type { HeadlessPaneColumn } from "../../../types/plugin";
2
2
  import type { HolderData, ShareBasis } from "../../../types/financials";
3
- import { formatCompact, formatPercentRaw } from "../../../utils/format";
3
+ import { formatCompact, MISSING_VALUE } from "../../../utils/format";
4
4
  import {
5
5
  displayDate,
6
+ formatChangePercent,
6
7
  formatMoneyCompact,
7
8
  formatPercentHeld,
8
9
  formatSignedCompact,
@@ -21,6 +22,7 @@ import {
21
22
  nonUsHolderCaveat,
22
23
  sharedReportDate,
23
24
  } from "./report-header";
25
+ import { HOLDER_ROWS_MAX } from "./index-holders";
24
26
  import { buildRows, DEFAULT_SORT, sortRows } from "./table-model";
25
27
  import type { HolderColumnId, SortPreference } from "./types";
26
28
 
@@ -28,7 +30,8 @@ import type { HolderColumnId, SortPreference } from "./types";
28
30
  * A holder as `holders` and `fn HDS` report it; the keys are the JSON
29
31
  * contract. `value` is in `currency`, the values' own currency; the percents
30
32
  * are in percent (0.59 is 0.59% of the shares outstanding, 13.15 a 13.15%
31
- * change on the quarter). A figure the source did not give is null.
33
+ * change on the quarter, 108.6 a position that more than doubled), from the
34
+ * record's fractions. A figure the source did not give is null.
32
35
  */
33
36
  export interface HolderReportRow {
34
37
  name: string;
@@ -63,14 +66,14 @@ export const HOLDER_REPORT_COLUMNS: HeadlessPaneColumn[] = [
63
66
  key: "value",
64
67
  header: "Mkt value",
65
68
  align: "right",
66
- format: (value) => num(value) == null ? "-" : formatCompact(num(value)!),
69
+ format: (value) => num(value) == null ? MISSING_VALUE : formatCompact(num(value)!),
67
70
  textFormat: (value, row) => formatMoneyCompact(num(value) ?? undefined, String(row.currency ?? "USD")),
68
71
  },
69
72
  {
70
73
  key: "shares",
71
74
  header: "Amount",
72
75
  align: "right",
73
- format: (value) => num(value) == null ? "-" : formatCompact(num(value)!),
76
+ format: (value) => num(value) == null ? MISSING_VALUE : formatCompact(num(value)!),
74
77
  },
75
78
  {
76
79
  key: BASIS_COLUMN_KEY,
@@ -87,13 +90,13 @@ export const HOLDER_REPORT_COLUMNS: HeadlessPaneColumn[] = [
87
90
  key: "changePercent",
88
91
  header: "Chg%",
89
92
  align: "right",
90
- format: (value) => num(value) == null ? "-" : formatPercentRaw(num(value)!),
93
+ format: (value) => formatChangePercent(num(value)),
91
94
  },
92
95
  {
93
96
  key: "percentHeld",
94
97
  header: "Held",
95
98
  align: "right",
96
- format: (value) => num(value) == null ? "-" : `${num(value)!.toFixed(2)}%`,
99
+ format: (value) => num(value) == null ? MISSING_VALUE : `${num(value)!.toFixed(2)}%`,
97
100
  textFormat: (value) => formatPercentHeld(num(value)),
98
101
  },
99
102
  {
@@ -186,10 +189,13 @@ export function holderReportNotices({
186
189
  reported,
187
190
  total,
188
191
  sort = DEFAULT_SORT,
192
+ indexed = false,
189
193
  }: {
190
194
  data: HolderData;
191
195
  /** The symbol as asked for, which `fn 13F` takes. */
192
196
  requested: string;
197
+ /** The rows are the SEC 13F holder index's, largest first, not the source's short list. */
198
+ indexed?: boolean;
193
199
  shown: readonly HolderReportRow[];
194
200
  /** Holders on the list before a limit. */
195
201
  reported: number;
@@ -218,8 +224,14 @@ export function holderReportNotices({
218
224
  `Mkt value = ${valueBasis}.`,
219
225
  changeReported ? "" : `Change vs prior quarter: not reported by this source; see fn 13F ${requested}`,
220
226
  ].filter(Boolean).join(" ");
227
+ const cut = indexed
228
+ ? indexedListCut(requested, shown.length, total, sort)
229
+ // The source names only its largest holders, so a higher limit shows no more of them.
230
+ : shown.length > 0 && shown.length === reported && total != null && total > reported
231
+ ? `The source lists its ${reported} largest holders; fn 13F ${requested} lists all ${total.toLocaleString("en-US")}.`
232
+ : null;
221
233
  return {
222
- notices: [header, basis, positionsBasis, holderShareBasisNote(data, shown), unvaluedHoldersNote(shown, sort)]
234
+ notices: [header, basis, cut, positionsBasis, holderShareBasisNote(data, shown), unvaluedHoldersNote(shown, sort)]
223
235
  .filter((line): line is string => !!line),
224
236
  valueBasis,
225
237
  positionsBasis,
@@ -227,6 +239,22 @@ export function holderReportNotices({
227
239
  };
228
240
  }
229
241
 
242
+ /**
243
+ * What a cut index list leaves out: the rows are its largest holders, so
244
+ * another order ranks only those, and `--limit` or `fn 13F` shows the rest.
245
+ */
246
+ function indexedListCut(requested: string, shown: number, total: number | null, sort: SortPreference): string | null {
247
+ if (shown === 0 || total == null || shown >= total) return null;
248
+ const within = sort.columnId === "value" || sort.columnId === "shares" ? "" : `Sorted among the ${shown} largest. `;
249
+ const all = total.toLocaleString("en-US");
250
+ const more = total <= HOLDER_ROWS_MAX
251
+ ? `--limit ${total} lists them all.`
252
+ : shown < HOLDER_ROWS_MAX
253
+ ? `--limit lists up to ${HOLDER_ROWS_MAX}; fn 13F ${requested} lists all ${all}.`
254
+ : `fn 13F ${requested} lists all ${all}.`;
255
+ return within + more;
256
+ }
257
+
230
258
  /**
231
259
  * Holders the list gives no value for (a home line's position its filing
232
260
  * could not tie to a priced security) sort after every valued one, and a
@@ -23,7 +23,8 @@ export function nextViewMode(current: ViewMode): ViewMode {
23
23
  export function buildRows(data: HolderData | null): HolderRow[] {
24
24
  return (data?.holders ?? []).map((holder, index) => ({
25
25
  ...holder,
26
- id: `${holder.ownerType}:${holder.name}:${holder.reportDate ?? ""}:${index}`,
26
+ // A filer's CIK names its row across pages; the source's rows have none.
27
+ id: holder.cik ? `cik:${holder.cik}` : `${holder.ownerType}:${holder.name}:${holder.reportDate ?? ""}:${index}`,
27
28
  }));
28
29
  }
29
30
 
@@ -2,8 +2,8 @@ import { useMemo } from "react";
2
2
  import { MetricTreemapSurface, type MetricTreemapItem } from "../../../components/metric-treemap";
3
3
  import { formatCompact } from "../../../utils/format";
4
4
  import {
5
+ formatHolderChangePercent,
5
6
  formatHolderOwnershipLine,
6
- formatMaybePercent,
7
7
  formatMoneyCompact,
8
8
  } from "./format";
9
9
  import type { HolderRow } from "./types";
@@ -22,7 +22,7 @@ export function HoldersTreemap({ rows, width, height, selectedId, onSelect, onAc
22
22
  }) {
23
23
  const items = useMemo<Array<MetricTreemapItem<HolderRow>>>(() => rows.map((row) => {
24
24
  const ownership = formatHolderOwnershipLine(row, marketCap);
25
- const change = row.changePercent != null ? formatMaybePercent(row.changePercent) : "No change";
25
+ const change = row.changePercent != null ? formatHolderChangePercent(row.changePercent) : "No change";
26
26
  return {
27
27
  id: row.id,
28
28
  label: row.name,
@@ -459,7 +459,7 @@ export function createInsiderHeadless(
459
459
  if (!symbol || args.options.view === "insiders") {
460
460
  throw new Error(symbol
461
461
  ? `--name filters ${symbol}'s trades, not its insiders. Drop --view insiders or --name from shot.`
462
- : `--name filters one company's trades: gloomberb shot INS <ticker> --name ${JSON.stringify(name)}`);
462
+ : `--name filters one company's trades: gloom shot INS <ticker> --name ${JSON.stringify(name)}`);
463
463
  }
464
464
  return { pluginState: { "ticker-research": { [`insider:nameFilter:${parsePublicTickerKey(symbol).symbol}`]: name } } };
465
465
  },
@@ -60,7 +60,7 @@ function insiderSignalsParams(query: InsiderSignalsQuery, limit: number): CloudI
60
60
  export const insiderSignalsCache = createPluginCache<InsiderSignalsPayload>({
61
61
  kind: "insider-signals",
62
62
  source: "gloom-cloud",
63
- // 2: sides, filters and structured signals (Linear: GLO-921).
63
+ // 2: sides, filters and structured signals.
64
64
  schemaVersion: 2,
65
65
  // Filings arrive through the day; the ranking moves with them, not with the market.
66
66
  policy: { staleMs: 5 * 60_000, expireMs: 2 * 86_400_000 },
@@ -95,7 +95,7 @@ export function InsiderSignalsView({ width, height, focused, renderCompany }: In
95
95
  const colors = useThemeColors();
96
96
  const { nativePaneChrome } = useUiCapabilities();
97
97
  const session = useResearchCloudSession();
98
- // Each part of the query is its own pane state, so `gloomberb shot INS --side sell` and the CLI's options set them one by one.
98
+ // Each part of the query is its own pane state, so `gloom shot INS --side sell` and the CLI's options set them one by one.
99
99
  const [storedSide, setSide] = usePluginPaneState<InsiderSignalSide>("insider:signals:side", "buy");
100
100
  const [storedWindow, setWindow] = usePluginPaneState<number>("insider:signals:window", DEFAULT_INSIDER_SIGNAL_WINDOW);
101
101
  const [storedRole, setRole] = usePluginPaneState<InsiderSignalRoleGroup>("insider:signals:role", "all");
@@ -19,7 +19,8 @@ import { priceColor, type ThemeColors } from "../../../theme/colors";
19
19
  import { useThemeColors } from "../../../theme/theme-context";
20
20
  import { TICKER_RESEARCH_PANE_ID } from "../../../types/config";
21
21
  import type { PaneProps } from "../../../types/plugin";
22
- import { Box, TextAttributes } from "../../../ui";
22
+ import { Box, TextAttributes, useUiCapabilities } from "../../../ui";
23
+ import { COUNTRY_FLAG_CELLS, withCountryFlag } from "../../../components/ui/country-flag";
23
24
  import { isPlainArrowUp, stopSearchFocusNavigation } from "../../../utils/search-focus-navigation";
24
25
  import { nextHeaderSort } from "../../../utils/sort-values";
25
26
  import { usePluginTickerActions } from "../../runtime";
@@ -95,7 +96,9 @@ export function IpoCalendarPane({ focused, width, height }: PaneProps) {
95
96
  // The cursor starts on the first deal, and moves there when its deal leaves the list.
96
97
  const selected = rows.find((deal) => deal.id === selectedId) ?? rows[0] ?? null;
97
98
  // Sized on the whole board, so switching tabs does not move the columns.
98
- const marketWidth = useMemo(() => marketColumnWidth(deals), [deals]);
99
+ // The desktop and the web lead each venue with its country's flag.
100
+ const flagged = useUiCapabilities().nativePaneChrome === true;
101
+ const marketWidth = useMemo(() => marketColumnWidth(deals) + (flagged ? COUNTRY_FLAG_CELLS : 0), [deals, flagged]);
99
102
  const columns = useMemo(() => buildIpoColumns(width, marketWidth), [marketWidth, width]);
100
103
 
101
104
  const openDeal = useCallback((deal: IpoDeal) => {
@@ -155,7 +158,7 @@ export function IpoCalendarPane({ focused, width, height }: PaneProps) {
155
158
  case "company":
156
159
  return { text: deal.company, color: colors.text };
157
160
  case "market":
158
- return { text: deal.venue || deal.mic, color: colors.textDim };
161
+ return withCountryFlag({ text: deal.venue || deal.mic, color: colors.textDim }, deal.country, flagged);
159
162
  case "date": {
160
163
  // A target date the venue has not set yet reads quieter than a set
161
164
  // one, and so does a book's closing day standing in for a listing
@@ -186,7 +189,7 @@ export function IpoCalendarPane({ focused, width, height }: PaneProps) {
186
189
  };
187
190
  }
188
191
  }
189
- }, [colors, now]);
192
+ }, [colors, flagged, now]);
190
193
 
191
194
  if (!payload) {
192
195
  return (
@@ -87,6 +87,26 @@ export interface IvScreenRow {
87
87
  latest: IvReading | null;
88
88
  skew: { date: string; put25: number; call25: number; skew: number } | null;
89
89
  }
90
+ /** Why a name IV history covers has no rank yet, by where its history stands. */
91
+ const IV_COVERAGE_REASONS: Partial<Record<IvCoverageStatus, string>> = {
92
+ queued: "IV history queued, try again in a few minutes",
93
+ backfilling: "IV history still loading",
94
+ unavailable: "no options history",
95
+ };
96
+
97
+ /**
98
+ * Why a screened name has no IV rank, in words for the reader: the server's
99
+ * note for a history too short to rank, or where its history stands. Null when
100
+ * there is nothing true to add, as for a name demand coverage could not take
101
+ * (the row carries the server's queue wording as a warning): none of its
102
+ * history is being collected, so no reason and no promise of one later.
103
+ */
104
+ export function ivRankReason(row: IvScreenRow | undefined): string | null {
105
+ if (!row) return "no IV history";
106
+ if (row.iv30?.rankNote) return row.iv30.rankNote;
107
+ if (row.warnings?.length) return null;
108
+ return IV_COVERAGE_REASONS[row.coverageStatus ?? row.status] ?? null;
109
+ }
90
110
  export interface IvScreenPayload { version: 1; asOf: string; rows: IvScreenRow[] }
91
111
  export interface StoredSurfacePayload {
92
112
  version: 1;
@@ -7,7 +7,7 @@ import { HV_WINDOWS, type HvWindow, type IvLookback, type IvStatRow, projectIvHi
7
7
  import { vcaUniverse } from "./universe";
8
8
  import { offsetText, releaseOffsetRows } from "./events";
9
9
  import { loadMacroReleases } from "../macro-day/client";
10
- import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, MACRO_RELEASE_SOURCES, staleMacroReleasesNotice, type MacroEventKind, type MacroRelease,
10
+ import { MACRO_EVENT_LABELS, MACRO_RELEASE_SOURCES, staleMacroReleasesNotice, US_MACRO_EVENT_KINDS, type MacroRelease, type UsMacroEventKind,
11
11
  type MacroReleaseList } from "../macro-day/releases";
12
12
  import { lookupScheduledDates } from "../alerts/scheduled";
13
13
  import { fetchCpiBoard } from "../cpi/client";
@@ -33,7 +33,7 @@ export const ivHistoryHeadless: HeadlessPaneDefinition<"bundle"> = {
33
33
  options: [
34
34
  { key: "lookback", type: "enum", values: [{ value: "1Y" }, { value: "2Y" }, { value: "ALL" }], defaultValue: "1Y", description: "Visible history" },
35
35
  { key: "hvWindow", type: "enum", values: HV_WINDOWS.map((window) => ({ value: String(window) })), defaultValue: "20", description: "Realized volatility window in sessions" },
36
- { key: "event", type: "enum", aliases: ["release"], values: MACRO_EVENT_KINDS.map((value) => ({ value, ...value === "jobs" ? { aliases: ["nfp", "payrolls"] } : {} })),
36
+ { key: "event", type: "enum", aliases: ["release"], values: US_MACRO_EVENT_KINDS.map((value) => ({ value, ...value === "jobs" ? { aliases: ["nfp", "payrolls"] } : {} })),
37
37
  description: "One row per release of this kind whose session at --offset has closed (the next scheduled FOMC or CPI included), in place of the daily history",
38
38
  example: "--event fomc --offset -6", shot: { reportOnly: "lists the readings around past release days" } },
39
39
  { key: "offset", type: "integer", minimum: -60, maximum: 60, defaultValue: 0,
@@ -41,7 +41,7 @@ export const ivHistoryHeadless: HeadlessPaneDefinition<"bundle"> = {
41
41
  example: "--event cpi --offset -1", shot: { reportOnly: "picks the session read around each release" } },
42
42
  ],
43
43
  async load(args, ctx) {
44
- const event = typeof args.options.event === "string" && args.options.event ? args.options.event as MacroEventKind : null;
44
+ const event = typeof args.options.event === "string" && args.options.event ? args.options.event as UsMacroEventKind : null;
45
45
  const offset = Number(args.options.offset) || 0;
46
46
  if (!event && offset !== 0) throw new Error("--offset counts sessions from a release day: add --event fomc, cpi or jobs.");
47
47
  const instrument = await resolveHeadlessInstrument(ctx, args.symbols[0]!);
@@ -215,7 +215,7 @@ export const ivScreenHeadless: HeadlessPaneDefinition<"bundle"> = {
215
215
  * from the CPI board's release calendar or the FOMC meetings WIRP prices, as
216
216
  * scheduled alerts read them. Payrolls have no schedule to read.
217
217
  */
218
- async function eventReleases(event: MacroEventKind, ctx: HeadlessPaneContext): Promise<{
218
+ async function eventReleases(event: UsMacroEventKind, ctx: HeadlessPaneContext): Promise<{
219
219
  list: MacroReleaseList; upcoming: string | null; upcomingNote: string | null;
220
220
  }> {
221
221
  const label = MACRO_EVENT_LABELS[event];
@@ -37,7 +37,7 @@ export const ivHistoryModule: PluginModule = {
37
37
  {
38
38
  id: "iv-screen-pane", paneId: "iv-screen", label: "Volatility Rich/Cheap",
39
39
  description: "IV rank, percentile, one-year IV, term slope, skew and IV/HV across a list, ranked rich to cheap.",
40
- // Where a put seller finds rich premium; OSA owns the exact put-selling phrases and ranks first on them.
40
+ // Where a put seller finds rich premium; CSP and OSA own the exact put-selling phrases and rank first on them.
41
41
  keywords: ["vca", "rich", "cheap", "iv rank", "implied volatility", "screen", "cash-secured puts", "selling puts", "short-put candidates",
42
42
  "csp candidates", "wheel candidates"],
43
43
  shortcut: { prefix: "VCA", argKind: "ticker-list" as const, argOptional: true }, headless: ivScreenHeadless,
@@ -2,6 +2,16 @@ import type { PricePoint } from "../../../types/financials";
2
2
  import { rollingRealizedVolatility } from "../shared/volatility";
3
3
  import type { IvCoverageStatus, IvHistoryPayload, IvMethod, IvPoint, IvScreenRow, IvStats } from "./client";
4
4
 
5
+ /**
6
+ * A history's warnings in words for the reader. A symbol demand coverage could
7
+ * not take (unavailable, with the server's queue wording as its warning) is
8
+ * said plainly instead: none of its history is being collected, so nothing is
9
+ * promised.
10
+ */
11
+ export function ivHistoryWarnings(payload: Pick<IvHistoryPayload, "status" | "symbol" | "warnings">): string[] {
12
+ return payload.status === "unavailable" && payload.warnings.length ? [`No IV history for ${payload.symbol} yet.`] : [...payload.warnings];
13
+ }
14
+
5
15
  export const HV_WINDOWS = [20, 30] as const;
6
16
  export type HvWindow = (typeof HV_WINDOWS)[number];
7
17
  export type IvLookback = "1Y" | "2Y" | "ALL";
@@ -159,7 +169,7 @@ export function projectIvHistory(
159
169
  ): IvHistoryModel {
160
170
  const lookback = options.lookback ?? "1Y";
161
171
  const window = options.hvWindow ?? 20;
162
- const warnings = [...payload.warnings];
172
+ const warnings = ivHistoryWarnings(payload);
163
173
  const tradeIv30 = byMethod(payload.series, "trade-close", "iv30");
164
174
  const latestDate = [payload.latest?.date, tradeIv30.at(-1) && day(tradeIv30.at(-1)!.date)].filter((value): value is string => !!value).sort().at(-1) ?? null;
165
175
  const start = latestDate ? lookbackStart(latestDate, lookback) : null;
@@ -358,9 +368,8 @@ export function screenCoverage(
358
368
  notes.push(`Backfilling: ${backfilling.map((row) => row.backfilledThrough ? `${row.symbol} through ${row.backfilledThrough}` : row.symbol).join(", ")}.`);
359
369
  }
360
370
  if (final.length) notes.push(`No options history: ${final.map((row) => row.symbol).join(", ")}.`);
361
- const reasons = new Map<string, string[]>();
362
- for (const row of uncovered) reasons.set(row.warning!, [...(reasons.get(row.warning!) ?? []), row.symbol]);
363
- for (const [reason, symbols] of reasons) notes.push(`Not queued: ${symbols.join(", ")}. ${reason}`);
371
+ // The server's queue wording (why demand coverage could not take them) is not repeated: none of their history is being collected, so nothing is promised.
372
+ if (uncovered.length) notes.push(`No IV history yet: ${uncovered.map((row) => row.symbol).join(", ")}.`);
364
373
  const pending = [...queued, ...backfilling, ...uncovered];
365
374
  return { notes, pending: pending.map((row) => row.symbol),
366
375
  missing: pending.filter((row) => row.iv30 == null && row.date == null).map((row) => row.symbol) };
@@ -1,5 +1,6 @@
1
1
  import type { SeriesDefinition } from "../../../series/types";
2
2
  import { loadIvHistory, type IvPoint } from "./client";
3
+ import { ivHistoryWarnings } from "./model";
3
4
 
4
5
  const TENORS: ReadonlyArray<readonly [key: "iv30" | "iv90" | "iv365", label: string]> = [
5
6
  ["iv30", "30-day"],
@@ -18,12 +19,13 @@ export const IV_SERIES: readonly SeriesDefinition[] = TENORS.map(([key, label]):
18
19
  input: "ticker",
19
20
  load: async ({ ticker, signal }) => {
20
21
  const payload = await loadIvHistory(ticker!, { ...(signal ? { signal } : {}) });
22
+ const warnings = ivHistoryWarnings(payload);
21
23
  return {
22
24
  points: payload.series.map((point: IvPoint) => ({
23
25
  date: point.sessionDate,
24
26
  value: point[key] == null ? null : point[key]! * 100,
25
27
  })),
26
- ...(payload.warnings.length ? { warning: payload.warnings.join("; ") } : {}),
28
+ ...(warnings.length ? { warning: warnings.join("; ") } : {}),
27
29
  };
28
30
  },
29
31
  }));
@@ -5,7 +5,7 @@ import { proLockNote, type FreeRoute } from "../shared/pro-lock-note";
5
5
 
6
6
  /** HIRE's preview, for a company whose careers system it reads: Coffee Holding (JVA) is mapped but uncovered. */
7
7
  const HIRE_ROUTE: FreeRoute = {
8
- text: (ticker, company) => `gloomberb fn HIRE ${ticker} previews ${company}'s hiring with its latest roles, without the full history.`,
8
+ text: (ticker, company) => `gloom fn HIRE ${ticker} previews ${company}'s hiring with its latest roles, without the full history.`,
9
9
  answers: async (symbol, context) => {
10
10
  const data = await fetchAttention("hiring", symbol, { limit: 1 }, context.apiClient, context.signal) as HiringPayload;
11
11
  return data.evidence.length + data.series.length + data.functions.length > 0;
@@ -9,6 +9,9 @@ import type {
9
9
  } from "../../../api-client/types";
10
10
  import { formatCompact, formatNumber } from "../../../utils/format";
11
11
  import { compareSortValues } from "../../../utils/sort-values";
12
+ import { formatSalaryRange, postingTitle } from "../shared/job-posting";
13
+
14
+ export { formatSalaryRange };
12
15
 
13
16
  /**
14
17
  * Pure projections from the cloud payload to what the pane, the research tab
@@ -110,20 +113,6 @@ export function formatShare(share: number): string {
110
113
  return `${formatNumber(share * 100, share >= 0.1 ? 0 : 1)}%`;
111
114
  }
112
115
 
113
- export function formatSalaryRange(
114
- min: number | null,
115
- max: number | null,
116
- currency: string | null,
117
- period: string | null,
118
- ): string {
119
- if (min == null && max == null) return "";
120
- const symbol = currency === "USD" ? "$" : currency === "EUR" ? "€" : currency === "GBP" ? "£" : currency ? `${currency} ` : "";
121
- const fmt = (value: number) => (period === "hour" ? formatNumber(value, 0) : formatCompact(value));
122
- const range = min != null && max != null && min !== max
123
- ? `${symbol}${fmt(min)}–${fmt(max)}`
124
- : `${symbol}${fmt((min ?? max)!)}`;
125
- return period === "hour" ? `${range}/h` : period === "month" ? `${range}/mo` : range;
126
- }
127
116
 
128
117
  /** "3d", "6w", "4mo" from an ISO date, with a `+` when the date is a floor. */
129
118
  export function formatAge(posted: string | null, precision: string | null, now = new Date()): string {
@@ -162,7 +151,7 @@ export function buildPostingRows(postings: readonly CloudJobsPosting[], now = ne
162
151
  return postings.map((posting) => ({
163
152
  key: String(posting.id),
164
153
  posting,
165
- title: posting.title,
154
+ title: postingTitle(posting.title),
166
155
  function: functionLabel(posting.function),
167
156
  seniority: seniorityLabel(posting.seniority),
168
157
  location: posting.remote && !/remote/i.test(posting.location ?? "")