gloomberb 0.17.6 → 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 (768) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +2 -0
  3. package/package.json +6 -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/credit-boards.ts +21 -1
  12. package/src/api-client/crypto-markets.ts +88 -1
  13. package/src/api-client/data.ts +104 -4
  14. package/src/api-client/debt-maturities.ts +18 -0
  15. package/src/api-client/equity-screener.ts +3 -0
  16. package/src/api-client/errors.ts +13 -0
  17. package/src/api-client/fund-facts.ts +72 -0
  18. package/src/api-client/futures-curve.ts +26 -3
  19. package/src/api-client/geo.ts +11 -1
  20. package/src/api-client/index.ts +25 -2
  21. package/src/api-client/insider-signals.ts +95 -11
  22. package/src/api-client/normalizers.ts +1 -0
  23. package/src/api-client/paths.ts +20 -1
  24. package/src/api-client/request.ts +11 -3
  25. package/src/api-client/research-activity.ts +15 -8
  26. package/src/api-client/socket.ts +6 -3
  27. package/src/api-client/supply-chain-graph.ts +2 -2
  28. package/src/api-client/supply-chain.ts +8 -0
  29. package/src/api-client/tape.ts +12 -0
  30. package/src/api-client/types.ts +66 -2
  31. package/src/api-client/upgrade-experiment.ts +4 -3
  32. package/src/api-client/wall-experiments.ts +5 -3
  33. package/src/api-client/wall-summary.ts +3 -1
  34. package/src/api-client/web-experiments.ts +5 -2
  35. package/src/api-client/yield-curves.ts +17 -0
  36. package/src/app/command-bar-intro.ts +38 -0
  37. package/src/app/keybindings/actions.ts +1 -1
  38. package/src/app/pane-runtime/pane-template-runtime.ts +35 -7
  39. package/src/app/pane-runtime/plugin-bindings.ts +4 -0
  40. package/src/app/pane-runtime/ticker-open-runtime.ts +4 -14
  41. package/src/app/pane-runtime/ticker-open-target.ts +31 -0
  42. package/src/app/runtime/desktop-deeplink.ts +3 -4
  43. package/src/app/runtime/plugin-bindings.ts +3 -2
  44. package/src/app/runtime/startup.ts +3 -4
  45. package/src/app/runtime/ticker-refresh.ts +13 -12
  46. package/src/app/runtime/update.ts +3 -2
  47. package/src/architecture/core-builtin-allowlist.json +0 -3
  48. package/src/architecture/silent-catch-allowlist.json +3 -0
  49. package/src/architecture/ui-literals-allowlist.json +186 -0
  50. package/src/architecture/ui-tokens-allowlist.json +40 -0
  51. package/src/ask-gloom/pane-context.ts +3 -1
  52. package/src/brokers/signed-in/catalog.ts +2 -1
  53. package/src/brokers/signed-in/client.ts +7 -2
  54. package/src/brokers/signed-in/sign-in-dialog.tsx +120 -26
  55. package/src/brokers/signed-in/sign-in.ts +22 -20
  56. package/src/brokers/sync-broker-instance.ts +2 -1
  57. package/src/capabilities/chart-series.ts +2 -0
  58. package/src/capabilities/registry.ts +1 -3
  59. package/src/cli/bank-section.ts +147 -0
  60. package/src/cli/base-converter.ts +5 -2
  61. package/src/cli/board-coins.ts +70 -0
  62. package/src/cli/commands/fred-series.ts +90 -0
  63. package/src/cli/commands/market.ts +340 -69
  64. package/src/cli/commands/news-search.ts +35 -2
  65. package/src/cli/commands/options-chain.ts +7 -5
  66. package/src/cli/commands/options-leaps.ts +3 -3
  67. package/src/cli/commands/overview.ts +78 -29
  68. package/src/cli/commands/plugins.ts +1 -0
  69. package/src/cli/commands/search.ts +87 -24
  70. package/src/cli/commands/system.ts +5 -2
  71. package/src/cli/commands/ticker.ts +337 -60
  72. package/src/cli/context.ts +2 -1
  73. package/src/cli/desktop-pane-shot.ts +11 -3
  74. package/src/cli/earnings-calendar.ts +2 -1
  75. package/src/cli/errors.ts +10 -0
  76. package/src/cli/export-source.ts +18 -3
  77. package/src/cli/glossary.ts +196 -14
  78. package/src/cli/history-rows.ts +60 -9
  79. package/src/cli/index-roots.ts +26 -0
  80. package/src/cli/index.ts +34 -9
  81. package/src/cli/known-gaps.ts +156 -22
  82. package/src/cli/listing-arg.ts +156 -12
  83. package/src/cli/listing-suggestion.ts +4 -2
  84. package/src/cli/name-entries.ts +76 -0
  85. package/src/cli/not-a-ticker.ts +15 -6
  86. package/src/cli/pane-functions/access-gate.ts +22 -0
  87. package/src/cli/pane-functions/capabilities.ts +62 -4
  88. package/src/cli/pane-functions/catalog.ts +94 -39
  89. package/src/cli/pane-functions/data.ts +6 -5
  90. package/src/cli/pane-functions/discovery.ts +1 -1
  91. package/src/cli/pane-functions/dom.ts +3 -3
  92. package/src/cli/pane-functions/freshness.ts +49 -8
  93. package/src/cli/pane-functions/function-help.ts +13 -10
  94. package/src/cli/pane-functions/headless.ts +177 -42
  95. package/src/cli/pane-functions/index.ts +64 -8
  96. package/src/cli/pane-functions/options.ts +17 -3
  97. package/src/cli/pane-functions/report-notices.ts +17 -3
  98. package/src/cli/pane-functions/resolver.ts +48 -13
  99. package/src/cli/pane-functions/screenshot.ts +124 -23
  100. package/src/cli/pane-functions/shot-options.ts +68 -0
  101. package/src/cli/perpetual-contract.ts +3 -1
  102. package/src/cli/report-tables.ts +10 -2
  103. package/src/cli/staged-tickers.ts +5 -0
  104. package/src/cli/statement-filings.ts +261 -0
  105. package/src/cli/symbol-args.ts +47 -8
  106. package/src/cli/symbol-list.ts +9 -2
  107. package/src/cli/symbol-rows.ts +269 -29
  108. package/src/cli/ticker-resolution.ts +148 -34
  109. package/src/cli/treasury-yields.ts +86 -0
  110. package/src/cli/types.ts +3 -0
  111. package/src/cli/uncovered-instrument.ts +20 -0
  112. package/src/components/chart/composite/axis-overlays.tsx +16 -9
  113. package/src/components/chart/composite/composite-chart.tsx +85 -6
  114. package/src/components/chart/composite/downsample.ts +19 -3
  115. package/src/components/chart/composite/format.ts +3 -0
  116. package/src/components/chart/composite/legend.tsx +155 -76
  117. package/src/components/chart/composite/panel-bitmap.ts +8 -2
  118. package/src/components/chart/composite/panel-surface.tsx +3 -3
  119. package/src/components/chart/composite/toolbar.tsx +12 -7
  120. package/src/components/chart/composite/types.ts +6 -0
  121. package/src/components/chart/composite/use-composite-chart-keyboard.ts +28 -1
  122. package/src/components/chart/curve/curve-surface.tsx +1 -1
  123. package/src/components/chart/static/series.ts +39 -0
  124. package/src/components/chart/static/trail-chart-surface.tsx +2 -1
  125. package/src/components/command-bar/commands/collection-list.ts +45 -15
  126. package/src/components/command-bar/commands/collection.ts +10 -3
  127. package/src/components/command-bar/commands/registry.ts +2 -2
  128. package/src/components/command-bar/list/badge.ts +4 -3
  129. package/src/components/command-bar/list/model.ts +5 -0
  130. package/src/components/command-bar/list/view.tsx +1 -1
  131. package/src/components/command-bar/panel/index.tsx +19 -8
  132. package/src/components/command-bar/panel/native-surface.ts +6 -4
  133. package/src/components/command-bar/panel/prompt-example.ts +22 -0
  134. package/src/components/command-bar/routes/root/provider-search.ts +3 -9
  135. package/src/components/command-bar/routes/root/results.ts +13 -0
  136. package/src/components/command-bar/routes/root/start-here.ts +90 -0
  137. package/src/components/command-bar/routes/ticker-search/results.ts +42 -3
  138. package/src/components/command-bar/routes/ticker-search/route.ts +3 -10
  139. package/src/components/command-bar/theme-picker.tsx +3 -1
  140. package/src/components/command-bar/workflow/builtin.ts +5 -1
  141. package/src/components/command-bar/workflow/collection-actions.ts +21 -12
  142. package/src/components/command-bar/workflow/ops.ts +21 -1
  143. package/src/{plugins/builtin/portfolio-list/command-bar.ts → components/command-bar/workflow/portfolio-position.ts} +42 -9
  144. package/src/components/command-bar/workflow/tickers.ts +6 -4
  145. package/src/components/feedback-dialog.tsx +1 -1
  146. package/src/components/form-modal/broker-step.tsx +7 -63
  147. package/src/components/form-modal/content.tsx +7 -2
  148. package/src/components/form-modal/field-row.tsx +6 -8
  149. package/src/components/form-modal/host.tsx +3 -3
  150. package/src/components/form-modal/model.ts +3 -0
  151. package/src/components/form-modal/routes.ts +17 -2
  152. package/src/components/index.ts +6 -6
  153. package/src/components/input-search-bar.tsx +43 -6
  154. package/src/components/layout/detached-pane-shell.tsx +0 -1
  155. package/src/components/layout/floating-pane.tsx +0 -1
  156. package/src/components/layout/header.tsx +8 -7
  157. package/src/components/layout/pane/footer/index.tsx +7 -4
  158. package/src/components/layout/pane/footer/model.ts +28 -2
  159. package/src/components/layout/pane/header.tsx +9 -19
  160. package/src/components/layout/pane/index.tsx +0 -1
  161. package/src/components/layout/pane/instrument-coverage-gate.tsx +57 -0
  162. package/src/components/layout/pane/pane-tabs.tsx +4 -3
  163. package/src/components/layout/pane/sizing.ts +9 -0
  164. package/src/components/layout/pane/ticker-fate-gate.tsx +8 -2
  165. package/src/components/layout/shell/pane/capture.ts +44 -20
  166. package/src/components/layout/status-bar.tsx +3 -6
  167. package/src/components/markdown-text.tsx +17 -2
  168. package/src/components/market-board/index.tsx +19 -8
  169. package/src/components/metric-treemap/heat-surface.tsx +2 -7
  170. package/src/components/onboarding/account-step/qr-panel.tsx +5 -2
  171. package/src/components/onboarding/onboarding-frame.tsx +24 -21
  172. package/src/components/onboarding/portfolio-step/positions-panel.tsx +20 -10
  173. package/src/components/onboarding/wizard-positions.ts +40 -11
  174. package/src/components/pane-settings-dialog/desktop.tsx +12 -50
  175. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -1
  176. package/src/components/price-performance.tsx +18 -2
  177. package/src/components/reader/article-reader.tsx +11 -10
  178. package/src/components/reader/detail-reader.tsx +9 -5
  179. package/src/components/reader/reader-text.tsx +51 -24
  180. package/src/components/sign-in-code-panel.tsx +129 -75
  181. package/src/components/ticker/badge/index.tsx +2 -1
  182. package/src/components/ui/action-row.tsx +5 -2
  183. package/src/components/ui/audio-player.tsx +70 -0
  184. package/src/components/ui/card.tsx +75 -0
  185. package/src/components/ui/data-table/index.tsx +4 -2
  186. package/src/components/ui/data-table/types.ts +11 -0
  187. package/src/components/ui/detail-scroll-body.tsx +1 -1
  188. package/src/components/ui/dialog-actions.tsx +1 -21
  189. package/src/components/ui/display.tsx +13 -5
  190. package/src/components/ui/external-link.tsx +4 -2
  191. package/src/components/ui/fields.tsx +12 -0
  192. package/src/components/ui/figure.tsx +5 -3
  193. package/src/components/ui/frame.tsx +40 -6
  194. package/src/components/ui/icon.tsx +4 -0
  195. package/src/components/ui/index.ts +4 -1
  196. package/src/components/ui/list-view.tsx +8 -0
  197. package/src/components/ui/prose.tsx +97 -25
  198. package/src/components/ui/query-bar-keys.tsx +3 -1
  199. package/src/components/ui/query-bar.tsx +6 -0
  200. package/src/components/ui/quote.ts +42 -0
  201. package/src/components/ui/range-track.tsx +15 -2
  202. package/src/components/ui/reveal-in-scroll-box.ts +21 -3
  203. package/src/components/ui/select-button.tsx +38 -3
  204. package/src/components/ui/status.tsx +73 -4
  205. package/src/components/ui/table-layout.ts +20 -0
  206. package/src/components/use-pinned-moment.ts +19 -0
  207. package/src/core/app-runtime.ts +2 -2
  208. package/src/core/state/app/instrument.ts +18 -1
  209. package/src/core/state/app/layout.ts +6 -0
  210. package/src/core/state/app/state.ts +14 -2
  211. package/src/data/cached-query.ts +1 -1
  212. package/src/data/config/chart-settings.ts +3 -1
  213. package/src/data/config/home.ts +4 -1
  214. package/src/data/config/store/node.ts +9 -4
  215. package/src/data/config/store/normalize.ts +9 -0
  216. package/src/data/json-storage.ts +6 -3
  217. package/src/data/json-ticker-repository.ts +3 -1
  218. package/src/data/plugin-cache.ts +5 -1
  219. package/src/data/sqlite/json.ts +3 -1
  220. package/src/data/ticker-repository.ts +5 -2
  221. package/src/feedback/diagnostics.ts +2 -6
  222. package/src/i18n/es.ts +86 -6
  223. package/src/i18n/index.ts +3 -9
  224. package/src/i18n/ja.ts +86 -6
  225. package/src/i18n/ko.ts +86 -6
  226. package/src/i18n/zh-cn.ts +86 -6
  227. package/src/i18n/zh-tw.ts +86 -6
  228. package/src/layout-marketplace/gallery-desktop.tsx +8 -4
  229. package/src/market-data/bars-per-year.ts +43 -0
  230. package/src/market-data/bond-funds.ts +85 -0
  231. package/src/market-data/coordinator/auxiliary.ts +5 -2
  232. package/src/market-data/coordinator/index.ts +6 -5
  233. package/src/market-data/futures-contract.ts +102 -5
  234. package/src/market-data/hooks.tsx +20 -11
  235. package/src/market-data/market/bar-period.ts +36 -0
  236. package/src/market-data/market/format.ts +5 -13
  237. package/src/market-data/market/freshness.ts +1 -3
  238. package/src/market-data/market/index-level.ts +51 -0
  239. package/src/market-data/model-dividend-yield.ts +57 -16
  240. package/src/market-data/quotes/live-valuation.ts +48 -2
  241. package/src/market-data/realized-volatility.ts +16 -7
  242. package/src/market-data/tax-equivalent.ts +344 -0
  243. package/src/news/aggregator.ts +4 -2
  244. package/src/notifications/notification-log.ts +5 -3
  245. package/src/plugins/auto-update-node.ts +1 -0
  246. package/src/plugins/builtin/account-management/footer.ts +1 -1
  247. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  248. package/src/plugins/builtin/account-management/model.ts +1 -0
  249. package/src/plugins/builtin/account-management/pane.tsx +71 -19
  250. package/src/plugins/builtin/account-management/trial-cancel.ts +40 -0
  251. package/src/plugins/builtin/alerts/cli.ts +7 -18
  252. package/src/plugins/builtin/alerts/constants.ts +8 -0
  253. package/src/plugins/builtin/alerts/event-rows.ts +16 -0
  254. package/src/plugins/builtin/alerts/events-pane.tsx +2 -14
  255. package/src/plugins/builtin/alerts/headless.ts +182 -0
  256. package/src/plugins/builtin/alerts/index.tsx +3 -0
  257. package/src/plugins/builtin/alerts/pane.tsx +1 -7
  258. package/src/plugins/builtin/alerts/storage.ts +17 -1
  259. package/src/plugins/builtin/analytics/index.tsx +6 -1
  260. package/src/plugins/builtin/analytics/metrics.ts +47 -9
  261. package/src/plugins/builtin/analytics/risk-headless.ts +14 -2
  262. package/src/plugins/builtin/analytics/risk-math.ts +83 -0
  263. package/src/plugins/builtin/analytics/risk-model.ts +97 -4
  264. package/src/plugins/builtin/analytics/risk-pane.tsx +11 -6
  265. package/src/plugins/builtin/analytics/sector-model.ts +14 -3
  266. package/src/plugins/builtin/awards/headless.ts +6 -5
  267. package/src/plugins/builtin/awards/index.tsx +1 -1
  268. package/src/plugins/builtin/backtest/client.ts +38 -8
  269. package/src/plugins/builtin/backtest/engine.ts +25 -13
  270. package/src/plugins/builtin/backtest/export.ts +27 -0
  271. package/src/plugins/builtin/backtest/format.ts +19 -3
  272. package/src/plugins/builtin/backtest/headless.ts +42 -28
  273. package/src/plugins/builtin/backtest/index.tsx +3 -0
  274. package/src/plugins/builtin/backtest/pane.tsx +39 -10
  275. package/src/plugins/builtin/backtest/report.ts +160 -0
  276. package/src/plugins/builtin/backtest/rules.ts +2 -0
  277. package/src/plugins/builtin/backtest/window.ts +112 -0
  278. package/src/plugins/builtin/bond-calculator/headless.ts +3 -2
  279. package/src/plugins/builtin/broker-manager/add-flow.tsx +4 -4
  280. package/src/plugins/builtin/catalysts/headless.ts +24 -13
  281. package/src/plugins/builtin/catalysts/index.tsx +4 -2
  282. package/src/plugins/builtin/catalysts/model.ts +18 -1
  283. package/src/plugins/builtin/catalysts/pane.tsx +2 -2
  284. package/src/plugins/builtin/cds/client.ts +28 -5
  285. package/src/plugins/builtin/cds/headless.ts +183 -31
  286. package/src/plugins/builtin/cds/index.tsx +1 -1
  287. package/src/plugins/builtin/cds/model.ts +229 -53
  288. package/src/plugins/builtin/cds/pane.tsx +82 -26
  289. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -1
  290. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +39 -1
  291. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +77 -0
  292. package/src/plugins/builtin/chart-composer/chart-spec.ts +15 -0
  293. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +22 -2
  294. package/src/plugins/builtin/chart-composer/editor/desktop-view.tsx +2 -2
  295. package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -2
  296. package/src/plugins/builtin/chart-composer/headless.ts +99 -21
  297. package/src/plugins/builtin/chart-composer/index.tsx +70 -13
  298. package/src/plugins/builtin/chart-composer/pane.tsx +65 -15
  299. package/src/plugins/builtin/chart-composer/presets.ts +79 -11
  300. package/src/plugins/builtin/chart-composer/series-catalog.ts +50 -14
  301. package/src/plugins/builtin/chart-composer/series-expression.ts +9 -7
  302. package/src/plugins/builtin/chart-composer/series-listings.ts +178 -0
  303. package/src/plugins/builtin/chart-composer/session-range.ts +87 -0
  304. package/src/plugins/builtin/chat/attachments/desktop.tsx +4 -1
  305. package/src/plugins/builtin/chat/content/composer-runtime.ts +49 -14
  306. package/src/plugins/builtin/chat/content/composer.tsx +22 -1
  307. package/src/plugins/builtin/chat/content/index.tsx +35 -5
  308. package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -0
  309. package/src/plugins/builtin/chat/content/shortcuts.ts +32 -13
  310. package/src/plugins/builtin/chat/content/snapshot.ts +29 -6
  311. package/src/plugins/builtin/chat/ghost-user.ts +11 -3
  312. package/src/plugins/builtin/chat/layout.ts +2 -0
  313. package/src/plugins/builtin/chat/message/desktop.tsx +13 -5
  314. package/src/plugins/builtin/chat/message/header.tsx +26 -4
  315. package/src/plugins/builtin/chat/message/pane-chip.tsx +131 -35
  316. package/src/plugins/builtin/chat/message/render-state.ts +28 -1
  317. package/src/plugins/builtin/chat/message/terminal.tsx +9 -3
  318. package/src/plugins/builtin/chat/pane-links/composer.ts +87 -0
  319. package/src/plugins/builtin/chat/pane-links/model.ts +1 -1
  320. package/src/plugins/builtin/chat/share/flow.tsx +9 -73
  321. package/src/plugins/builtin/cloud/askg/controller.ts +5 -3
  322. package/src/plugins/builtin/cloud/askg/executor.ts +3 -1
  323. package/src/plugins/builtin/cloud/askg/lock-note.ts +16 -0
  324. package/src/plugins/builtin/cloud/askg/pane.tsx +6 -2
  325. package/src/plugins/builtin/cloud/auth-actions.tsx +4 -2
  326. package/src/plugins/builtin/cloud/company-picker.tsx +21 -26
  327. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +5 -3
  328. package/src/plugins/builtin/cloud/plugin.tsx +2 -0
  329. package/src/plugins/builtin/cloud/team/module.tsx +5 -1
  330. package/src/plugins/builtin/cloud/team/pane.tsx +11 -4
  331. package/src/plugins/builtin/cloud/team/views.ts +11 -4
  332. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +9 -4
  333. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +3 -2
  334. package/src/plugins/builtin/cloud/thesis/detail.tsx +2 -1
  335. package/src/plugins/builtin/cloud/thesis/exposure.ts +3 -0
  336. package/src/plugins/builtin/cloud/thesis/prompts.tsx +3 -2
  337. package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +2 -1
  338. package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +2 -1
  339. package/src/plugins/builtin/cloud/verification-status-widget.tsx +2 -1
  340. package/src/plugins/builtin/commodities-energy/index.tsx +8 -5
  341. package/src/plugins/builtin/commodities-energy/view-state.ts +11 -0
  342. package/src/plugins/builtin/company-attention/headless.ts +15 -7
  343. package/src/plugins/builtin/company-attention/index.tsx +1 -1
  344. package/src/plugins/builtin/company-attention/model.ts +49 -4
  345. package/src/plugins/builtin/company-attention/pane.tsx +11 -9
  346. package/src/plugins/builtin/company-kpis/headless.ts +4 -3
  347. package/src/plugins/builtin/company-kpis/index.tsx +2 -2
  348. package/src/plugins/builtin/company-kpis/pane.tsx +9 -3
  349. package/src/plugins/builtin/congress-trades/headless.ts +23 -2
  350. package/src/plugins/builtin/correlation/relationship/pane.tsx +18 -46
  351. package/src/plugins/builtin/cot/headless.ts +5 -2
  352. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +41 -13
  353. package/src/plugins/builtin/credit-boards/client.ts +9 -2
  354. package/src/plugins/builtin/credit-boards/headless.ts +93 -27
  355. package/src/plugins/builtin/credit-boards/index.tsx +15 -4
  356. package/src/plugins/builtin/credit-boards/model.ts +105 -6
  357. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +14 -3
  358. package/src/plugins/builtin/credit-documents/detail.tsx +2 -1
  359. package/src/plugins/builtin/credit-documents/index.tsx +3 -0
  360. package/src/plugins/builtin/credit-documents/model.ts +3 -10
  361. package/src/plugins/builtin/crypto-board/client.ts +152 -2
  362. package/src/plugins/builtin/crypto-board/headless.ts +138 -19
  363. package/src/plugins/builtin/crypto-board/index.tsx +5 -3
  364. package/src/plugins/builtin/crypto-board/model.ts +210 -12
  365. package/src/plugins/builtin/crypto-board/pane.tsx +148 -9
  366. package/src/plugins/builtin/crypto-board/series.ts +52 -1
  367. package/src/plugins/builtin/crypto-board/supply.ts +123 -0
  368. package/src/plugins/builtin/debt-maturities/client.ts +54 -1
  369. package/src/plugins/builtin/debt-maturities/headless.ts +27 -3
  370. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  371. package/src/plugins/builtin/debt-maturities/model.ts +58 -13
  372. package/src/plugins/builtin/debt-maturities/pane.tsx +47 -7
  373. package/src/plugins/builtin/dividend-yield/client.ts +42 -36
  374. package/src/plugins/builtin/dividend-yield/headless.ts +113 -18
  375. package/src/plugins/builtin/dividend-yield/index.tsx +5 -2
  376. package/src/plugins/builtin/dividend-yield/pane.tsx +37 -13
  377. package/src/plugins/builtin/dividend-yield/provider-client.ts +7 -3
  378. package/src/plugins/builtin/dividend-yield/ranking.ts +187 -0
  379. package/src/plugins/builtin/dividend-yield/reference-price.ts +28 -5
  380. package/src/plugins/builtin/dividend-yield/types.ts +6 -1
  381. package/src/plugins/builtin/dividend-yield/view.ts +1 -1
  382. package/src/plugins/builtin/docs/blocks.tsx +54 -8
  383. package/src/plugins/builtin/docs/pane.tsx +8 -13
  384. package/src/plugins/builtin/earnings/headless.ts +3 -2
  385. package/src/plugins/builtin/earnings-calls/data.ts +51 -0
  386. package/src/plugins/builtin/earnings-calls/headless.ts +7 -0
  387. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  388. package/src/plugins/builtin/earnings-calls/model.ts +97 -0
  389. package/src/plugins/builtin/earnings-calls/pane.tsx +107 -7
  390. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +140 -22
  391. package/src/plugins/builtin/earnings-calls/use-call-playback.ts +194 -0
  392. package/src/plugins/builtin/econ/calendar-model.ts +22 -0
  393. package/src/plugins/builtin/econ/calendar-source.ts +35 -0
  394. package/src/plugins/builtin/econ/index.tsx +40 -8
  395. package/src/plugins/builtin/econ-statistics/defs.ts +7 -0
  396. package/src/plugins/builtin/econ-statistics/detail.tsx +8 -1
  397. package/src/plugins/builtin/econ-statistics/headless.ts +26 -5
  398. package/src/plugins/builtin/econ-statistics/pane.tsx +4 -2
  399. package/src/plugins/builtin/econ-statistics/stats.ts +10 -0
  400. package/src/plugins/builtin/econ-statistics/view.ts +19 -0
  401. package/src/plugins/builtin/equity-screener/client.ts +1 -1
  402. package/src/plugins/builtin/equity-screener/model.ts +46 -4
  403. package/src/plugins/builtin/equity-screener/pane.tsx +3 -0
  404. package/src/plugins/builtin/estimate-revisions/client.ts +32 -22
  405. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  406. package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
  407. package/src/plugins/builtin/estimate-revisions/pane.tsx +5 -3
  408. package/src/plugins/builtin/executives/index.tsx +1 -0
  409. package/src/plugins/builtin/exposure/editor.tsx +3 -3
  410. package/src/plugins/builtin/fear-greed/index.tsx +9 -0
  411. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  412. package/src/plugins/builtin/futures/index.tsx +2 -2
  413. package/src/plugins/builtin/futures/model.ts +34 -21
  414. package/src/plugins/builtin/futures/table.tsx +1 -1
  415. package/src/plugins/builtin/futures/use-board-terms.ts +2 -2
  416. package/src/plugins/builtin/futures-curve/headless.ts +4 -2
  417. package/src/plugins/builtin/futures-curve/model.ts +5 -7
  418. package/src/plugins/builtin/help/index.tsx +55 -8
  419. package/src/plugins/builtin/help/shortcut-table.tsx +15 -2
  420. package/src/plugins/builtin/holders/headless.ts +12 -0
  421. package/src/plugins/builtin/insider/headless.ts +311 -41
  422. package/src/plugins/builtin/insider/index.tsx +280 -106
  423. package/src/plugins/builtin/insider/insiders.tsx +224 -0
  424. package/src/plugins/builtin/insider/signals-cells.tsx +52 -0
  425. package/src/plugins/builtin/insider/signals-client.ts +135 -11
  426. package/src/plugins/builtin/insider/signals-model.ts +628 -56
  427. package/src/plugins/builtin/insider/signals.tsx +283 -83
  428. package/src/plugins/builtin/ipo-calendar/headless.ts +17 -7
  429. package/src/plugins/builtin/ipo-calendar/index.tsx +23 -3
  430. package/src/plugins/builtin/ipo-calendar/model.ts +84 -36
  431. package/src/plugins/builtin/ipo-calendar/pane.tsx +20 -8
  432. package/src/plugins/builtin/iv-history/headless.ts +2 -0
  433. package/src/plugins/builtin/jobs/headless.ts +1 -0
  434. package/src/plugins/builtin/jobs/index.tsx +1 -0
  435. package/src/plugins/builtin/jodi/headless.ts +2 -0
  436. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  437. package/src/plugins/builtin/kelly-sizer/portfolio.ts +1 -1
  438. package/src/plugins/builtin/market-heatmap/headless.ts +1 -0
  439. package/src/plugins/builtin/market-heatmap/portfolio.ts +3 -1
  440. package/src/plugins/builtin/market-valuation/pane.tsx +1 -1
  441. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +31 -57
  442. package/src/plugins/builtin/mna/distress/headless.ts +2 -1
  443. package/src/plugins/builtin/mna/headless.ts +14 -2
  444. package/src/plugins/builtin/mna/index.tsx +1 -0
  445. package/src/plugins/builtin/news/headless.ts +4 -0
  446. package/src/plugins/builtin/news/wire/news/footer.ts +5 -3
  447. package/src/plugins/builtin/news/wire/news/table.tsx +57 -11
  448. package/src/plugins/builtin/notes/cli.ts +8 -4
  449. package/src/plugins/builtin/notes/files.ts +66 -20
  450. package/src/plugins/builtin/notes/migration.ts +18 -6
  451. package/src/plugins/builtin/notes/owner.tsx +3 -2
  452. package/src/plugins/builtin/notes/quick-notes-pane.tsx +3 -2
  453. package/src/plugins/builtin/options-scenario/client.ts +7 -4
  454. package/src/plugins/builtin/options-scenario/headless.ts +5 -3
  455. package/src/plugins/builtin/pe-band/index.tsx +1 -1
  456. package/src/plugins/builtin/pe-band/model.ts +1 -15
  457. package/src/plugins/builtin/perps/headless.ts +30 -13
  458. package/src/plugins/builtin/perps/model.ts +45 -3
  459. package/src/plugins/builtin/perps/pane.tsx +7 -7
  460. package/src/plugins/builtin/portfolio-list/cell-version.ts +10 -4
  461. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +128 -14
  462. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +108 -46
  463. package/src/plugins/builtin/portfolio-list/cli/render.ts +368 -45
  464. package/src/plugins/builtin/portfolio-list/cli/shared.ts +8 -2
  465. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +24 -34
  466. package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
  467. package/src/plugins/builtin/portfolio-list/headless.ts +151 -29
  468. package/src/plugins/builtin/portfolio-list/income.ts +296 -0
  469. package/src/plugins/builtin/portfolio-list/metrics.ts +2 -2
  470. package/src/plugins/builtin/portfolio-list/pane/futures-terms.ts +58 -0
  471. package/src/plugins/builtin/portfolio-list/pane/index.tsx +27 -10
  472. package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +47 -28
  473. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +3 -2
  474. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +10 -3
  475. package/src/plugins/builtin/portfolio-list/summary/index.tsx +26 -4
  476. package/src/plugins/builtin/portfolio-list/summary/totals.ts +31 -3
  477. package/src/plugins/builtin/portfolio-list/table.tsx +25 -5
  478. package/src/plugins/builtin/power/prices-headless.ts +2 -1
  479. package/src/plugins/builtin/realized-vol/chart-model.ts +29 -5
  480. package/src/plugins/builtin/realized-vol/charts.tsx +14 -8
  481. package/src/plugins/builtin/realized-vol/evidence.ts +2 -0
  482. package/src/plugins/builtin/realized-vol/headless.ts +6 -4
  483. package/src/plugins/builtin/realized-vol/model.ts +5 -1
  484. package/src/plugins/builtin/realized-vol/pane.tsx +31 -11
  485. package/src/plugins/builtin/realized-vol/settings.ts +1 -1
  486. package/src/plugins/builtin/research/analyst-headless.ts +4 -0
  487. package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -0
  488. package/src/plugins/builtin/research/event-model.ts +22 -2
  489. package/src/plugins/builtin/research/headless-schema.ts +1 -0
  490. package/src/plugins/builtin/research/headless.ts +3 -0
  491. package/src/plugins/builtin/research/index.tsx +3 -0
  492. package/src/plugins/builtin/research/relative-valuation-columns.ts +27 -5
  493. package/src/plugins/builtin/research/relative-valuation-headless.ts +2 -0
  494. package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
  495. package/src/plugins/builtin/reverse-dcf/headless.ts +9 -6
  496. package/src/plugins/builtin/reverse-dcf/index.tsx +2 -2
  497. package/src/plugins/builtin/reverse-dcf/model.ts +51 -4
  498. package/src/plugins/builtin/reverse-dcf/pane.tsx +23 -10
  499. package/src/plugins/builtin/risk-factors/headless.ts +7 -0
  500. package/src/plugins/builtin/risk-factors/index.tsx +1 -0
  501. package/src/plugins/builtin/scanner/feed.ts +5 -3
  502. package/src/plugins/builtin/scanner/headless.ts +9 -57
  503. package/src/plugins/builtin/scanner/index.ts +1 -2
  504. package/src/plugins/builtin/sec/forms.ts +2 -6
  505. package/src/plugins/builtin/sec/fund-facts-view.tsx +53 -0
  506. package/src/plugins/builtin/sec/fund-facts.ts +328 -0
  507. package/src/plugins/builtin/sec/headless.ts +140 -44
  508. package/src/plugins/builtin/sec/index.tsx +95 -30
  509. package/src/plugins/builtin/sec/model.ts +2 -44
  510. package/src/plugins/builtin/shared/headless-options.ts +10 -0
  511. package/src/plugins/builtin/shared/locked-rows.tsx +3 -1
  512. package/src/plugins/builtin/shared/move-rank.ts +108 -0
  513. package/src/plugins/builtin/shared/report-freshness.ts +25 -9
  514. package/src/plugins/builtin/shared/scanner-capture.ts +95 -0
  515. package/src/plugins/builtin/shared/treasury-cutoffs.ts +15 -0
  516. package/src/plugins/builtin/shared/use-quote-board.ts +1 -0
  517. package/src/plugins/builtin/shared/volatility/live-session.ts +34 -0
  518. package/src/plugins/builtin/shared/volatility-indices.ts +32 -0
  519. package/src/plugins/builtin/short-interest/headless.ts +3 -0
  520. package/src/plugins/builtin/short-interest/watch-model.ts +2 -2
  521. package/src/plugins/builtin/social-mentions/client.ts +8 -1
  522. package/src/plugins/builtin/social-mentions/pane.tsx +8 -6
  523. package/src/plugins/builtin/supply-chain/client.ts +12 -3
  524. package/src/plugins/builtin/supply-chain/disclosure-quote.tsx +9 -5
  525. package/src/plugins/builtin/supply-chain/evidence.ts +3 -1
  526. package/src/plugins/builtin/supply-chain/flow-layout.ts +2 -1
  527. package/src/plugins/builtin/supply-chain/flow.tsx +23 -16
  528. package/src/plugins/builtin/supply-chain/graph-client.ts +8 -5
  529. package/src/plugins/builtin/supply-chain/graph-evidence.ts +1 -1
  530. package/src/plugins/builtin/supply-chain/graph-model.ts +10 -2
  531. package/src/plugins/builtin/supply-chain/graph-pane.tsx +9 -7
  532. package/src/plugins/builtin/supply-chain/graph.tsx +8 -6
  533. package/src/plugins/builtin/supply-chain/headless.ts +69 -27
  534. package/src/plugins/builtin/supply-chain/index.tsx +1 -1
  535. package/src/plugins/builtin/supply-chain/model.ts +76 -15
  536. package/src/plugins/builtin/supply-chain/pane.tsx +29 -15
  537. package/src/plugins/builtin/supply-chain/row-evidence.tsx +5 -4
  538. package/src/plugins/builtin/themes/model.ts +2 -5
  539. package/src/plugins/builtin/thirteenf/api.ts +50 -2
  540. package/src/plugins/builtin/thirteenf/data.ts +250 -11
  541. package/src/plugins/builtin/thirteenf/headless.ts +311 -28
  542. package/src/plugins/builtin/thirteenf/index.tsx +4 -1
  543. package/src/plugins/builtin/thirteenf/model.ts +244 -19
  544. package/src/plugins/builtin/thirteenf/overlap-pane.tsx +133 -33
  545. package/src/plugins/builtin/thirteenf/overlap.ts +1 -1
  546. package/src/plugins/builtin/thirteenf/pane.tsx +24 -5
  547. package/src/plugins/builtin/thirteenf/report-notes.ts +78 -0
  548. package/src/plugins/builtin/thirteenf/types.ts +49 -0
  549. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +22 -8
  550. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +17 -1
  551. package/src/plugins/builtin/ticker-detail/financials/model.ts +2 -42
  552. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +1 -1
  553. package/src/plugins/builtin/ticker-detail/headless.ts +23 -10
  554. package/src/plugins/builtin/ticker-detail/overview/components.tsx +27 -3
  555. package/src/plugins/builtin/ticker-detail/overview/dividend.ts +60 -0
  556. package/src/plugins/builtin/ticker-detail/overview/model.ts +46 -9
  557. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +3 -0
  558. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +36 -3
  559. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +18 -19
  560. package/src/plugins/builtin/time-sales/client.ts +7 -4
  561. package/src/plugins/builtin/time-sales/headless.ts +71 -22
  562. package/src/plugins/builtin/time-sales/model.ts +12 -0
  563. package/src/plugins/builtin/time-sales/pane.tsx +31 -7
  564. package/src/plugins/builtin/time-sales/window.ts +128 -0
  565. package/src/plugins/builtin/trace-bonds/client.ts +351 -33
  566. package/src/plugins/builtin/trace-bonds/headless.ts +60 -22
  567. package/src/plugins/builtin/trace-bonds/index.tsx +4 -2
  568. package/src/plugins/builtin/trace-bonds/model.ts +27 -25
  569. package/src/plugins/builtin/trace-bonds/pane.tsx +63 -45
  570. package/src/plugins/builtin/treasury-auctions/cache.ts +61 -15
  571. package/src/plugins/builtin/treasury-auctions/client.ts +45 -10
  572. package/src/plugins/builtin/treasury-auctions/headless.ts +35 -13
  573. package/src/plugins/builtin/treasury-auctions/index.tsx +5 -2
  574. package/src/plugins/builtin/treasury-auctions/model.ts +20 -16
  575. package/src/plugins/builtin/treasury-auctions/pane.tsx +29 -12
  576. package/src/plugins/builtin/vol-surface/charts.tsx +2 -1
  577. package/src/plugins/builtin/vol-surface/headless.ts +3 -2
  578. package/src/plugins/builtin/vol-surface/pane.tsx +2 -1
  579. package/src/plugins/builtin/vol-surface/stored.ts +4 -7
  580. package/src/plugins/builtin/volatility/chart-model.ts +16 -15
  581. package/src/plugins/builtin/volatility/charts.tsx +5 -5
  582. package/src/plugins/builtin/volatility/client.ts +73 -2
  583. package/src/plugins/builtin/volatility/evidence.ts +13 -14
  584. package/src/plugins/builtin/volatility/headless.ts +13 -7
  585. package/src/plugins/builtin/volatility/index.tsx +1 -1
  586. package/src/plugins/builtin/volatility/model.ts +104 -38
  587. package/src/plugins/builtin/volatility/pane.tsx +42 -24
  588. package/src/plugins/builtin/volatility/series.ts +22 -13
  589. package/src/plugins/builtin/world-venue-map/geo-series.ts +9 -0
  590. package/src/plugins/builtin/world-venue-map/headless.ts +8 -5
  591. package/src/plugins/builtin/world-venue-map/index.ts +16 -2
  592. package/src/plugins/builtin/world-venue-map/map.tsx +13 -17
  593. package/src/plugins/builtin/yield-curve/curves.ts +29 -5
  594. package/src/plugins/builtin/yield-curve/headless.ts +41 -8
  595. package/src/plugins/builtin/yield-curve/history.ts +5 -5
  596. package/src/plugins/builtin/yield-curve/index.tsx +30 -13
  597. package/src/plugins/compat.ts +3 -1
  598. package/src/plugins/dependencies.ts +8 -2
  599. package/src/plugins/host-link.ts +12 -5
  600. package/src/plugins/installer.ts +16 -7
  601. package/src/plugins/loader.ts +9 -2
  602. package/src/plugins/marketplace/activation.ts +10 -4
  603. package/src/plugins/registry/host-actions.ts +3 -0
  604. package/src/plugins/registry/index.ts +3 -1
  605. package/src/{plugins/builtin/portfolio-list → portfolio}/allocation.ts +74 -12
  606. package/src/{plugins/builtin/portfolio-list → portfolio}/column-values.ts +140 -53
  607. package/src/portfolio/futures-positions.ts +213 -0
  608. package/src/portfolio/futures-terms.ts +75 -0
  609. package/src/portfolio/manual-lots.ts +78 -0
  610. package/src/portfolio/mutations.ts +54 -10
  611. package/src/portfolio/position-metrics.ts +44 -10
  612. package/src/portfolio/valuation-basis.ts +31 -4
  613. package/src/public/__snapshots__/public-api.test.ts.snap +4 -0
  614. package/src/public/time-series.ts +2 -1
  615. package/src/remote/confirm-change.tsx +2 -1
  616. package/src/remote/server.ts +1 -1
  617. package/src/remote/watchlist.ts +9 -1
  618. package/src/renderers/dom/data-table/row.tsx +1 -1
  619. package/src/renderers/dom/desktop/audio-player.tsx +312 -0
  620. package/src/renderers/dom/desktop/control-styles.ts +17 -82
  621. package/src/renderers/dom/desktop/controls.tsx +39 -63
  622. package/src/renderers/dom/desktop/dialog-actions.tsx +13 -53
  623. package/src/renderers/dom/desktop/icons.tsx +8 -0
  624. package/src/renderers/dom/desktop/list-view.tsx +6 -6
  625. package/src/renderers/dom/desktop/popover.tsx +0 -3
  626. package/src/renderers/dom/desktop/query-bar.tsx +6 -4
  627. package/src/renderers/dom/desktop/select-field.tsx +9 -8
  628. package/src/renderers/dom/desktop/stack-header.ts +3 -0
  629. package/src/renderers/dom/dom-ui-host.tsx +3 -2
  630. package/src/renderers/dom/host/chart-surface.tsx +3 -3
  631. package/src/renderers/dom/host/size-observer.ts +33 -4
  632. package/src/renderers/dom/host/surface-3d.tsx +3 -2
  633. package/src/renderers/dom/host/surface-fit.ts +4 -1
  634. package/src/renderers/dom/host/tabs.tsx +22 -132
  635. package/src/renderers/dom/styles.css +358 -160
  636. package/src/renderers/electrobun/bun/core-capabilities.ts +1 -1
  637. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -1
  638. package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
  639. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +43 -1
  640. package/src/renderers/electrobun/bun/desktop/workspace/requests.ts +5 -1
  641. package/src/renderers/electrobun/shared/rpc-codec.ts +7 -0
  642. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +21 -17
  643. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  644. package/src/renderers/electrobun/view/desktop/window/bridge.ts +6 -8
  645. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +18 -0
  646. package/src/series/capability.ts +1 -0
  647. package/src/series/files.ts +9 -3
  648. package/src/series/registry.ts +40 -14
  649. package/src/series/resolve.ts +121 -18
  650. package/src/series/standalone.ts +3 -2
  651. package/src/series/types.ts +55 -1
  652. package/src/series/validate.ts +39 -0
  653. package/src/shares/api.ts +26 -7
  654. package/src/shares/bug-report-dialog.tsx +2 -2
  655. package/src/shares/bug-report-flow.tsx +4 -7
  656. package/src/shares/capture-flow.ts +5 -4
  657. package/src/shares/capture-preview.tsx +2 -2
  658. package/src/shares/chat.ts +7 -27
  659. package/src/shares/flow.tsx +86 -40
  660. package/src/shares/location.ts +1 -3
  661. package/src/shares/pane-image.ts +11 -9
  662. package/src/shares/pane.ts +5 -2
  663. package/src/shares/payload.ts +1 -1
  664. package/src/shares/personal-pane.ts +3 -3
  665. package/src/shares/portable-layout.ts +9 -2
  666. package/src/shares/ready.ts +42 -0
  667. package/src/shares/test-harness.ts +62 -0
  668. package/src/sources/gloomberb-cloud/batched-lookups.ts +73 -0
  669. package/src/sources/gloomberb-cloud/index.ts +64 -12
  670. package/src/sources/gloomberb-cloud/normalizers.ts +31 -2
  671. package/src/sources/gloomberb-cloud/perpetuals.ts +20 -1
  672. package/src/sources/history-omitted.ts +34 -0
  673. package/src/sources/history-result.ts +3 -0
  674. package/src/sources/history-retention.ts +1 -1
  675. package/src/sources/provider-errors.ts +43 -1
  676. package/src/sources/provider-router/batches.ts +3 -2
  677. package/src/sources/provider-router/cache.ts +2 -1
  678. package/src/sources/provider-router/cached-routes.ts +9 -3
  679. package/src/sources/provider-router/history.ts +9 -8
  680. package/src/sources/provider-router/index.ts +18 -3
  681. package/src/sources/provider-router/primary.ts +5 -4
  682. package/src/sources/provider-router/quote-route.ts +3 -1
  683. package/src/sources/provider-router/routing.ts +2 -1
  684. package/src/sources/provider-router/search.ts +47 -13
  685. package/src/sources/provider-router/streaming.ts +7 -4
  686. package/src/sources/sec-edgar.ts +1 -3
  687. package/src/state/app/context/index.tsx +9 -13
  688. package/src/state/app/tab-cursor.ts +149 -12
  689. package/src/state/hooks/quote-streaming.ts +3 -2
  690. package/src/state/hooks/session-snapshot.ts +3 -2
  691. package/src/state/persist-scheduler.ts +12 -4
  692. package/src/sync/controller.ts +22 -1
  693. package/src/sync/core-contributors.ts +58 -15
  694. package/src/team/collections-sync.ts +14 -4
  695. package/src/team/collections.ts +40 -11
  696. package/src/team/store.ts +5 -4
  697. package/src/telemetry/attention-counts.ts +8 -2
  698. package/src/telemetry/crash-reports-dom.ts +3 -0
  699. package/src/telemetry/crash-reports-node.ts +7 -4
  700. package/src/telemetry/crash-reports.ts +11 -11
  701. package/src/telemetry/usage-counts.ts +16 -12
  702. package/src/theme/colors.ts +2 -0
  703. package/src/theme/font-scale.ts +2 -0
  704. package/src/theme/ui-tokens.ts +71 -0
  705. package/src/tickers/batched-lookups.ts +186 -0
  706. package/src/tickers/company-name-listing.ts +97 -0
  707. package/src/tickers/company-name.ts +13 -0
  708. package/src/tickers/instrument-coverage.ts +112 -0
  709. package/src/tickers/listing-fate.ts +49 -9
  710. package/src/tickers/listing-venues.ts +24 -5
  711. package/src/tickers/open-target.ts +13 -5
  712. package/src/tickers/search/index.ts +112 -35
  713. package/src/tickers/search/ranking.ts +49 -1
  714. package/src/tickers/terminal-codes.ts +79 -0
  715. package/src/tickers/ticker-changes.ts +74 -3
  716. package/src/tickers/us-listing.ts +2 -1
  717. package/src/time-series/chart-data.ts +79 -8
  718. package/src/time-series/fundamentals.ts +55 -7
  719. package/src/time-series/ice-credit.ts +17 -2
  720. package/src/time-series/live-bars.ts +21 -8
  721. package/src/time-series/live-quotes.ts +2 -3
  722. package/src/time-series/price-comparison.ts +6 -1
  723. package/src/time-series/resolve.ts +65 -10
  724. package/src/time-series/spec.ts +2 -1
  725. package/src/time-series/studies.ts +3 -3
  726. package/src/time-series/types.ts +22 -0
  727. package/src/time-series/use-chart-resolution.ts +2 -1
  728. package/src/types/config.ts +7 -0
  729. package/src/types/data-provider.ts +20 -0
  730. package/src/types/headless.ts +142 -1
  731. package/src/types/instrument.ts +6 -0
  732. package/src/types/plugin.ts +32 -9
  733. package/src/types/price-history.ts +5 -0
  734. package/src/types/ticker-changes.ts +19 -0
  735. package/src/types/ticker.ts +10 -2
  736. package/src/ui/context-menu.tsx +2 -0
  737. package/src/ui/host.tsx +40 -4
  738. package/src/ui/measured-cells.ts +13 -7
  739. package/src/ui/qr.ts +7 -5
  740. package/src/updater/index.ts +5 -5
  741. package/src/utils/calendar-date.ts +86 -27
  742. package/src/utils/currency-units.ts +17 -0
  743. package/src/utils/debug-log.ts +1 -1
  744. package/src/utils/dividend-cash.ts +48 -0
  745. package/src/utils/dom-screenshot-rasters.ts +3 -1
  746. package/src/utils/dom-screenshot.ts +14 -10
  747. package/src/utils/exchange-rate-snapshot.ts +9 -4
  748. package/src/utils/external-url.ts +1 -0
  749. package/src/utils/fiscal-period.ts +47 -0
  750. package/src/utils/format.ts +5 -2
  751. package/src/utils/forward-dividend.ts +160 -11
  752. package/src/utils/futures-generic.ts +34 -8
  753. package/src/utils/http-proxy-response.ts +2 -1
  754. package/src/utils/local-utc-offset.ts +2 -0
  755. package/src/utils/log-failure.ts +31 -0
  756. package/src/utils/option-expiry.ts +12 -12
  757. package/src/utils/price-history-integrity.ts +56 -0
  758. package/src/utils/price-history.ts +13 -1
  759. package/src/utils/sec-filings.ts +245 -0
  760. package/src/utils/selection-clipboard.ts +5 -2
  761. package/src/utils/throttled-fetch.ts +1 -0
  762. package/src/{plugins/builtin/dividend-yield/trailing-cash.ts → utils/trailing-dividend.ts} +55 -8
  763. package/src/utils/url.ts +1 -0
  764. package/src/utils/utc-time.ts +11 -0
  765. package/src/plugins/builtin/chat/share/targets.ts +0 -27
  766. package/src/renderers/dom/host/top-surface.ts +0 -119
  767. package/src/shares/dialog.tsx +0 -221
  768. package/src/shares/live.ts +0 -19
@@ -11,9 +11,9 @@ export const companyKpisModule: PluginModule = {
11
11
  dispose() { companyKpisCache.reset(); },
12
12
  panes: [
13
13
  { id: "company-kpis", name: "Company KPIs", icon: "K", component: CompanyKpisPane, defaultPosition: "right", defaultMode: "floating",
14
- defaultFloatingSize: { width: 130, height: 30 }, tickerFollower: true, tableExport: true, headless: kpisHeadless },
14
+ defaultFloatingSize: { width: 130, height: 30 }, tickerFollower: true, instruments: ["equity"], tableExport: true, headless: kpisHeadless },
15
15
  { id: "company-guidance", name: "Company Guidance", icon: "G", component: CompanyGuidancePane, defaultPosition: "right", defaultMode: "floating",
16
- defaultFloatingSize: { width: 130, height: 30 }, tickerFollower: true, tableExport: true, headless: guidanceHeadless },
16
+ defaultFloatingSize: { width: 130, height: 30 }, tickerFollower: true, instruments: ["equity"], tableExport: true, headless: guidanceHeadless },
17
17
  ],
18
18
  paneTemplates: [
19
19
  { ...createTickerSurfacePaneTemplate({ id: "company-kpis-pane", paneId: "company-kpis", label: "Company KPIs", shortcut: "KPIS",
@@ -9,6 +9,7 @@ import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
9
9
  import { useAsyncResource, useAutoRefresh, usePaneSettingValue, usePluginAppActions, usePluginPaneState } from "../../../public/react";
10
10
  import { usePaneTickerIdentity } from "../../../state/hooks/pane-ticker";
11
11
  import { useThemeColors } from "../../../theme/theme-context";
12
+ import { quoteBlockStyle } from "../../../components/ui/quote";
12
13
  import type { PaneProps } from "../../../types/plugin";
13
14
  import { Box, Text, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
14
15
  import { SignInWall } from "../cloud/auth-actions";
@@ -31,8 +32,10 @@ const getId = (item: Item) => item.id;
31
32
  const isNote = (item: Item) => "note" in item && !!item.note;
32
33
  function DisclosureEvidence({ row, sourceId, onSource, width }: { row: CompanyRow; sourceId: string | null; onSource: (id: string) => void; width: number }) {
33
34
  const colors = useThemeColors();
35
+ const desktop = useUiCapabilities().nativePaneChrome === true;
34
36
  const evidence = row.evidence.find((entry) => entry.id === sourceId) ?? row.evidence[0]!;
35
- return <Box flexDirection="column" paddingX={1}>
37
+ // The desktop's detail body already holds the pane's inset.
38
+ return <Box flexDirection="column" paddingX={desktop ? 0 : 1}>
36
39
  {row.evidence.length > 1 ? <QueryBar width={Math.max(1, width - 4)} filters={[{ id: "source", label: "Document", value: evidence.id,
37
40
  options: row.evidence.map((entry) => ({ value: entry.id, label: `${entry.publishedAt.slice(0, 10)} · ${entry.title}` })), onChange: onSource }]} /> : null}
38
41
  <KeyValueRow label="Value" value={isGuidance(row) ? rangeText(row) : observationValue(row)} detail={row.currency || row.unit === "volume" || row.unit === "count" ? unitLabel(row) : undefined} labelWidth={18} />
@@ -53,7 +56,10 @@ function DisclosureEvidence({ row, sourceId, onSource, width }: { row: CompanyRo
53
56
  <KeyValueRow label="Document" value={evidence.title} labelWidth={18} />
54
57
  <KeyValueRow label="Published" value={evidence.publishedAt.slice(0, 10)} detail={`${evidence.country} · ${evidence.language}`} labelWidth={18} />
55
58
  <KeyValueRow label="Confidence" value={`${Math.round(evidence.confidence * 100)}%`} detail={evidence.quoteMatchMode === "exact" ? "Exact text match" : "Normalized text match"} labelWidth={18} />
56
- <Box paddingY={1}><Text fg={colors.textBright}>{evidence.quote}</Text></Box>
59
+ {/* The filing's own words: on the desktop, the quote block. */}
60
+ {desktop
61
+ ? <Box marginY={1} style={quoteBlockStyle()}><Text fg={colors.textBright} wrapText>{evidence.quote}</Text></Box>
62
+ : <Box paddingY={1}><Text fg={colors.textBright}>{evidence.quote}</Text></Box>}
57
63
  <Text fg={colors.textDim}>{evidence.url}</Text>
58
64
  </Box>
59
65
  </Box>;
@@ -179,7 +185,7 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
179
185
  data?.truncated && data.access === "full" ? "The response reached its stored-record limit. Narrow the metric or date range in a CLI or REST query." : null,
180
186
  data?.coverage.conflicts ? "Conflicting disclosures are retained in Evidence and excluded from comparable trends." : null].filter((value): value is string => !!value) });
181
187
  if (!symbol) return <EmptyState title="Select a ticker." />;
182
- if (!data && isCloudSessionRequired(resource.error)) return <SignInWall placement="company-kpis-signin" action="view company KPIs and guidance" needsVerification={session.needsVerification} />;
188
+ if (!data && isCloudSessionRequired(resource.error)) return <SignInWall placement="company-kpis-signin" action={mode === "guidance" ? "view company guidance" : "view company KPIs"} needsVerification={session.needsVerification} />;
183
189
  const bodyHeight = Math.max(3, height - tabRows);
184
190
  const query = <QueryBar width={width} filters={[{ id: "metric", label: "Metric", value: metric, defaultValue: "all", options: metricOptions,
185
191
  onChange: (value: string) => { setMetric(value); setSelected(null); setOpen(null); } }, ...(tab === "chart" && plotOptions.length ? [{ id: "series", label: "Series", value: activePlot,
@@ -20,6 +20,7 @@ import {
20
20
  tradeAssetLabel,
21
21
  } from "./model";
22
22
  import type { CloudCongressHouseParams } from "../../../api-client/paths";
23
+ import { REPORT_PAGE, REPORT_ROWS } from "../shared/headless-options";
23
24
 
24
25
  const TRADE_COLUMNS: HeadlessPaneColumn[] = [
25
26
  { key: "filingDate", header: "Filed", format: (value) => formatShortDate(typeof value === "string" ? value : null, FILING_DAY_FORMAT) },
@@ -99,6 +100,16 @@ const defaultDependencies: CongressHeadlessDependencies = {
99
100
  }, ctx.apiClient, ctx.signal),
100
101
  };
101
102
 
103
+ /** The filter bar's state for the filters asked for, as the pane stores it: "all" and a zero minimum are no filter. Null when none was. */
104
+ function shotFilters(options: HeadlessPaneLoadArgs["options"], given: ReadonlySet<string>): Record<string, string | number> | null {
105
+ const keys = ["chamber", "side", "owner", "assetType", "minAmount"].filter((key) => given.has(key));
106
+ if (!keys.length) return null;
107
+ return Object.fromEntries(keys.flatMap((key) => {
108
+ const value = options[key];
109
+ return value === "all" || (key === "minAmount" && !Number(value)) ? [] : [[key, key === "minAmount" ? Number(value) : String(value)]];
110
+ }));
111
+ }
112
+
102
113
  export function createCongressHeadless(
103
114
  dependencies: CongressHeadlessDependencies = defaultDependencies,
104
115
  ): HeadlessPaneDefinition<"rows"> {
@@ -112,8 +123,8 @@ export function createCongressHeadless(
112
123
  },
113
124
  options: [
114
125
  { key: "chamber", description: "House, Senate, or both merged by filing date.", type: "enum", defaultValue: "all", values: ["all", "house", "senate"].map((value) => ({ value })) },
115
- { key: "offset", description: "Trade offset within the filing window.", type: "integer", defaultValue: 0, minimum: 0 },
116
- { key: "filingOffset", description: "Offset into the year's filing index.", type: "integer", defaultValue: 0, minimum: 0 },
126
+ { key: "offset", shot: REPORT_PAGE, description: "Trade offset within the filing window.", type: "integer", defaultValue: 0, minimum: 0 },
127
+ { key: "filingOffset", shot: REPORT_PAGE, description: "Offset into the year's filing index.", type: "integer", defaultValue: 0, minimum: 0 },
117
128
  {
118
129
  key: "tab",
119
130
  description: "Congress pane tab.",
@@ -124,6 +135,7 @@ export function createCongressHeadless(
124
135
  },
125
136
  {
126
137
  key: "year",
138
+ shot: { reportOnly: "reads one disclosure year, and the pane opens on the latest" },
127
139
  description: "Disclosure year.",
128
140
  type: "integer",
129
141
  defaultValue: new Date().getUTCFullYear(),
@@ -132,6 +144,7 @@ export function createCongressHeadless(
132
144
  },
133
145
  {
134
146
  key: "limit",
147
+ shot: REPORT_ROWS,
135
148
  aliases: ["count", "rows"],
136
149
  description: "Maximum rows.",
137
150
  type: "integer",
@@ -145,6 +158,14 @@ export function createCongressHeadless(
145
158
  { key: "minAmount", description: "Minimum disclosed lower dollar bound.", type: "integer", defaultValue: 0, minimum: 0 },
146
159
  ],
147
160
  describe: (args) => `Congress Trades | ${args.options.tab === "members" ? "Members" : args.options.tab === "tickers" ? "Tickers" : "Trades"}`,
161
+ // A ticker's pane lists its trades only. The filters are the pane's filter bar, kept apart for a ticker's pane.
162
+ shotState: (args, _load, given) => {
163
+ if (args.symbols.length && args.options.tab !== "trades") {
164
+ throw new Error(`The Congress pane for one ticker lists its trades only. Drop --tab ${args.options.tab} or ${args.symbols[0]} from shot, or run the report: gloomberb fn CG ${args.symbols[0]} --tab ${args.options.tab}`);
165
+ }
166
+ const filters = shotFilters(args.options, given);
167
+ return filters ? { pluginState: { "gloomberb-cloud": { [`${args.symbols.length ? "congressTicker." : ""}filters`]: filters } } } : {};
168
+ },
148
169
  async load(args, ctx) {
149
170
  const payload = await dependencies.loadHouse(args, ctx);
150
171
  const limit = Number(args.options.limit);
@@ -5,6 +5,7 @@ import {
5
5
  QueryBar,
6
6
  StatGrid,
7
7
  statGridRows,
8
+ usePaneFooter,
8
9
  usePaneNoticeFooter,
9
10
  usePaneStatusFooter,
10
11
  type CompositeAxisDomain,
@@ -54,36 +55,18 @@ export {
54
55
  buildRelationshipGraphSettingsDef
55
56
  } from "./model";
56
57
 
57
- type RelationshipGraphShortcut =
58
- | "range"
59
- | "window"
60
- | "correlation"
61
- | "regression"
62
- | { range: RelationshipRange };
63
-
64
58
  /**
65
- * [t]ime range cycles and 1-6 pick a range, [p]eriod cycles the correlation
66
- * window, [c]orr and [f]it toggle their panels. The query bar shows all four,
67
- * so none needs a footer hint. Plain `r` is the pane refresh key.
59
+ * 1-6 pick a range. [t]ime range cycles, [p]eriod cycles the correlation
60
+ * window, [c]orr and [f]it toggle their panels: footer keys, bound but not
61
+ * drawn, since the query bar shows all four, and a chart's own `p` gives way
62
+ * to them. Plain `r` is the pane refresh key.
68
63
  */
69
- function resolveRelationshipGraphShortcut(
64
+ function resolveRelationshipRangeKey(
70
65
  event: Pick<KeyEventLike, "name" | "key" | "ctrl" | "shift" | "alt" | "meta" | "super">,
71
- ): RelationshipGraphShortcut | null {
66
+ ): RelationshipRange | null {
72
67
  if (event.ctrl || event.shift || event.alt || event.meta || event.super) return null;
73
-
74
- const key = (event.name ?? event.key ?? "").toLowerCase();
75
- switch (key) {
76
- case "t":
77
- return "range";
78
- case "p":
79
- return "window";
80
- case "c":
81
- return "correlation";
82
- case "f":
83
- return "regression";
84
- }
85
- const range = /^[1-9]$/.test(key) ? RELATIONSHIP_RANGES[Number(key) - 1] : undefined;
86
- return range ? { range } : null;
68
+ const key = event.name ?? event.key ?? "";
69
+ return (/^[1-9]$/.test(key) ? RELATIONSHIP_RANGES[Number(key) - 1] : undefined) ?? null;
87
70
  }
88
71
 
89
72
  const RANGE_OPTIONS = RELATIONSHIP_RANGES.map((range, index) => ({ label: range, value: range, hint: String(index + 1) }));
@@ -238,29 +221,18 @@ export function RelationshipGraphPane({ focused, width, height }: PaneProps) {
238
221
  event.stopPropagation();
239
222
  return;
240
223
  }
241
- const shortcut = resolveRelationshipGraphShortcut(event);
242
- if (!shortcut) return;
224
+ const range = resolveRelationshipRangeKey(event);
225
+ if (!range) return;
243
226
  event.preventDefault();
244
227
  event.stopPropagation();
245
- if (typeof shortcut === "object") {
246
- setRange(shortcut.range);
247
- return;
248
- }
249
- switch (shortcut) {
250
- case "range":
251
- cycleRange();
252
- return;
253
- case "window":
254
- cycleWindow();
255
- return;
256
- case "correlation":
257
- toggleCorrelation();
258
- return;
259
- case "regression":
260
- toggleRegression();
261
- return;
262
- }
228
+ setRange(range);
263
229
  });
230
+ usePaneFooter("relationship-keys", () => ({ keys: [
231
+ { id: "range", key: "t", label: "ime range", onPress: cycleRange },
232
+ { id: "window", key: "p", label: "eriod", title: "Correlation Window", onPress: cycleWindow },
233
+ { id: "correlation", key: "c", label: "orr", onPress: toggleCorrelation },
234
+ { id: "regression", key: "f", label: "it", onPress: toggleRegression },
235
+ ] }), [cycleRange, cycleWindow, toggleCorrelation, toggleRegression]);
264
236
 
265
237
  usePaneNoticeFooter({
266
238
  registrationId: "relationship-warnings", focused,
@@ -2,6 +2,7 @@ import type { CotClass, CotClassSummary } from "../../../api-client/cot";
2
2
  import type { HeadlessPaneColumn, HeadlessPaneDefinition } from "../../../types/plugin";
3
3
  import { fetchCotBoard, fetchCotContract } from "./client";
4
4
  import { COT_MAJOR_CODES, COT_SCOPES, cotClass, cotContractCode, cotInteger, cotMarketName, cotScope, cotUnknownMarketMessage } from "./model";
5
+ import { COMMODITIES_VIEW_STATE } from "../commodities-energy/view-state";
5
6
 
6
7
  const camelClass = (id: CotClass) => id.replace(/-(\w)/g, (_match, letter: string) => letter.toUpperCase());
7
8
  const rounded = (value: number | null, digits: number) => value == null ? null : Number(value.toFixed(digits));
@@ -30,8 +31,10 @@ export const cotHeadless: HeadlessPaneDefinition<"bundle"> = {
30
31
  freshness: { source: "CFTC", status: "not-a-feed", basis: "weekly report", maxAgeMinutes: 14 * 24 * 60 },
31
32
  argument: { kind: "free-text", optional: true, placeholder: "code or root", description: "CFTC market code or verified futures root; omit for the extremes board." },
32
33
  options: [{ key: "report", type: "enum", values: [{ value: "legacy" }, { value: "disaggregated" }], defaultValue: "legacy", description: "CFTC report family." },
33
- { key: "traderClass", type: "enum", values: ["noncommercial", "commercial", "producer", "swap", "managed-money", "other-reportable", "nonreportable"].map((value) => ({ value })), description: "Trader class for the extremes board; defaults by report family." },
34
- { key: "scope", type: "enum", values: COT_SCOPES.map(({ value }) => ({ value })), defaultValue: "major", description: "Markets on the extremes board, as in the pane." }],
34
+ { key: "traderClass", type: "enum", values: ["noncommercial", "commercial", "producer", "swap", "managed-money", "other-reportable", "nonreportable"].map((value) => ({ value })), description: "Trader class for the extremes board; defaults by report family.",
35
+ pluginState: { pluginId: COMMODITIES_VIEW_STATE.cot, key: "class" } },
36
+ { key: "scope", type: "enum", values: COT_SCOPES.map(({ value }) => ({ value })), defaultValue: "major", description: "Markets on the extremes board, as in the pane.",
37
+ pluginState: { pluginId: COMMODITIES_VIEW_STATE.cot, key: "scope" } }],
35
38
  discovery: { aliases: ["COT", "CFTC"], dataRequirements: ["Gloom Cloud CFTC history"], limitations: ["Futures-only positions aggregate all maturities.", "Legacy and disaggregated classes differ.", "Observation date is not publication date.", "Some markets have short or suppressed histories."] },
36
39
  describe: "CFTC positioning",
37
40
  async load(args, ctx) {
@@ -20,13 +20,17 @@ import type { PaneProps } from "../../../types/plugin";
20
20
  import { formatPercentileRank } from "../../../utils/format";
21
21
  import { usePluginPaneState } from "../../runtime";
22
22
  import { formatAsOf } from "../cds/model";
23
+ import { FIXED_INCOME_PANE_ID } from "../fixed-income/model";
24
+ import { useCommandValue } from "../shared/command-tab";
23
25
  import { getCachedCdxBoard, loadCdxBoard } from "./client";
24
26
  import {
25
27
  axisFormatter,
26
28
  cdxRows,
29
+ findIndex,
27
30
  formatContract,
28
31
  formatLevel,
29
32
  formatMove,
33
+ partialDayText,
30
34
  type CdxRow,
31
35
  } from "./model";
32
36
 
@@ -59,16 +63,22 @@ function HistoryChart({ row, width, height, focused }: { row: CdxRow; width: num
59
63
  }
60
64
 
61
65
  function IndexDetail({ row, width, height, focused }: { row: CdxRow; width: number; height: number; focused: boolean }) {
62
- const { index, year } = row;
66
+ const { index, year, day } = row;
67
+ // While today trades the moves run to the last complete day, which the 1D says.
68
+ const through = day.partial && day.changeDate ? `to ${day.changeDate}` : undefined;
63
69
  const items: StatItem[] = [
64
70
  { id: "level", label: index.quote === "spread" ? "5Y spread" : "5Y price", value: formatLevel(index.quote, index.level),
65
71
  detail: `${formatPercentileRank(year.percentile, "1Y")} · ${index.date ?? "--"}` },
66
- { id: "1d", label: "1D", value: formatMove(index.quote, index.change1D) },
67
- { id: "1w", label: "1W", value: formatMove(index.quote, index.change1W) },
68
- { id: "1m", label: "1M", value: formatMove(index.quote, index.change1M ?? null) },
72
+ ...(index.quote === "price" && index.spreadBp !== undefined ? [{ id: "spread", label: "Spread eq", value: formatLevel("spread", index.spreadBp ?? null),
73
+ ...(index.recovery != null ? { detail: `${Math.round(index.recovery * 100)}% recovery` } : {}) }] : []),
74
+ { id: "1d", label: "1D", value: formatMove(index.quote, day.change1D), ...(through ? { detail: through } : {}) },
75
+ { id: "1w", label: "1W", value: formatMove(index.quote, day.change1W) },
76
+ { id: "1m", label: "1M", value: formatMove(index.quote, day.change1M) },
69
77
  { id: "range", label: "1Y range", value: `${formatLevel(index.quote, year.low)} to ${formatLevel(index.quote, year.high)}` },
70
78
  { id: "contract", label: "Contract", value: formatContract(index.maturity), detail: `${index.couponBp}bp coupon` },
71
- { id: "prints", label: "Prints", value: index.prints == null ? "--" : String(index.prints) },
79
+ { id: "prints", label: "Prints", value: index.prints == null ? "--" : String(index.prints),
80
+ // The value is the count already: the detail says only that the day is still trading, and its last print.
81
+ ...(day.partial ? { detail: partialDayText(null, day.lastPrintAt) } : {}) },
72
82
  ];
73
83
  return (
74
84
  <StatChartDetail items={items} width={width} height={height} empty={index.points.length < 3}
@@ -83,7 +93,13 @@ export function CdxPane({ focused, width, height }: PaneProps) {
83
93
  const { loading, load: refresh, reload } = resource;
84
94
  const payload = resource.data?.payload ?? null;
85
95
  const rows = useMemo(() => payload ? cdxRows(payload.indexes, payload.asOf) : EMPTY_ROWS, [payload]);
86
- const [selectedId, setSelectedId] = usePluginPaneState<string | null>("cdx:selected", null);
96
+ // `CDX HY` opens on that index, named as `fn CDX HY` names it; a later `CDX IG` replaces it.
97
+ const [selectedId, setSelectedId] = useCommandValue<string | null>(
98
+ FIXED_INCOME_PANE_ID,
99
+ "cdx:selected",
100
+ (params) => params.view === "index" && params.index ? params.index : null,
101
+ null,
102
+ );
87
103
  const [openId, setOpenId] = usePluginPaneState<string | null>("cdx:open", null);
88
104
  useAutoRefresh(resource.updatedAt, refresh);
89
105
  usePaneRefreshKey(reload, { focused, enabled: !loading });
@@ -101,13 +117,14 @@ export function CdxPane({ focused, width, height }: PaneProps) {
101
117
  info,
102
118
  });
103
119
 
104
- // The 1W and 1M moves and the print count ride beside the board's own 1D column.
120
+ // The 1W and 1M moves, HY and EM's price as a spread and the print count ride beside the board's own 1D column.
121
+ const spreads = rows.some((row) => row.index.spreadBp !== undefined);
105
122
  const extraColumns = useMemo(() => [
106
123
  {
107
124
  column: { id: "week", label: "1W", width: 10, align: "right" as const },
108
125
  sortValue: (row: CdxRow) => row.week,
109
126
  renderCell: (row: CdxRow) => ({
110
- text: formatMove(row.index.quote, row.index.change1W),
127
+ text: formatMove(row.index.quote, row.day.change1W),
111
128
  color: signedMoveColor(row.week, row.adverseMove, theme),
112
129
  }),
113
130
  },
@@ -115,10 +132,19 @@ export function CdxPane({ focused, width, height }: PaneProps) {
115
132
  column: { id: "month", label: "1M", width: 10, align: "right" as const },
116
133
  sortValue: (row: CdxRow) => row.month,
117
134
  renderCell: (row: CdxRow) => ({
118
- text: formatMove(row.index.quote, row.index.change1M ?? null),
135
+ text: formatMove(row.index.quote, row.day.change1M),
119
136
  color: signedMoveColor(row.month, row.adverseMove, theme),
120
137
  }),
121
138
  },
139
+ // A server that predates the spread equivalent sends none: no column of blanks.
140
+ ...(spreads ? [{
141
+ column: { id: "spread", label: "SPREAD EQ", width: 9, align: "right" as const },
142
+ sortValue: (row: CdxRow) => row.index.quote === "price" ? row.index.spreadBp ?? null : null,
143
+ renderCell: (row: CdxRow) => ({
144
+ text: row.index.quote === "price" ? formatLevel("spread", row.index.spreadBp ?? null) : "--",
145
+ color: theme.textMuted,
146
+ }),
147
+ }] : []),
122
148
  {
123
149
  column: { id: "prints", label: "PRINTS", width: 7, align: "right" as const },
124
150
  sortValue: (row: CdxRow) => row.index.prints,
@@ -127,7 +153,7 @@ export function CdxPane({ focused, width, height }: PaneProps) {
127
153
  color: theme.textMuted,
128
154
  }),
129
155
  },
130
- ], [theme]);
156
+ ], [theme, spreads]);
131
157
 
132
158
  if (rows.length === 0) {
133
159
  return (
@@ -136,13 +162,15 @@ export function CdxPane({ focused, width, height }: PaneProps) {
136
162
  );
137
163
  }
138
164
 
139
- // The selected index's history sits above the board; the legend names it.
140
- const selected = rows.find((row) => row.id === selectedId) ?? rows[0];
165
+ // The selected index's history sits above the board; the legend names it. What a command named (`HY`, `itraxx
166
+ // main`) is read like `fn` reads it, and one the board does not have leaves the board on its first.
167
+ const named = selectedId ? findIndex(payload?.indexes ?? [], selectedId) : null;
168
+ const selected = rows.find((row) => row.id === selectedId) ?? rows.find((row) => row.id === named?.id) ?? rows[0];
141
169
  return (
142
170
  <MarketBoardStack rows={rows} width={width} height={height} focused={focused}
143
171
  rootBefore={({ columns }) => <ChartTableHeader width={width} height={height} tableRows={rows.length}
144
172
  tableColumns={columns} chart={selected ? historyChart(selected) : null} />}
145
- selectedId={selectedId} onSelectedIdChange={setSelectedId} openId={openId} onOpenIdChange={setOpenId}
173
+ selectedId={selected?.id ?? null} onSelectedIdChange={setSelectedId} openId={openId} onOpenIdChange={setOpenId}
146
174
  labelHeader="INDEX" labelWidth={16} valueLabel="5Y" valueWidth={9} signedChange extraColumns={extraColumns}
147
175
  renderDetail={(row) => <IndexDetail row={row} width={width} height={Math.max(5, height - 2)} focused={focused} />} />
148
176
  );
@@ -24,8 +24,11 @@ const BOARD_DAYS = 365;
24
24
  const finiteOrNull = (value: unknown) => value === null || typeof value === "number" && Number.isFinite(value);
25
25
  const isDate = (value: unknown): value is string => typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)
26
26
  && Number.isFinite(Date.parse(value));
27
+ const optionalFinite = (value: unknown) => value === undefined || finiteOrNull(value);
28
+ const isInstant = (value: unknown) => typeof value === "string" && Number.isFinite(Date.parse(value));
27
29
  const validPoints = (points: unknown) => Array.isArray(points) && points.every((point: CreditBoardPoint) =>
28
- point && isDate(point.date) && isDate(point.maturity) && Number.isFinite(point.level) && Number.isInteger(point.prints));
30
+ point && isDate(point.date) && isDate(point.maturity) && Number.isFinite(point.level) && Number.isInteger(point.prints)
31
+ && optionalFinite(point.spreadBp));
29
32
 
30
33
  function validateCdxBoard(payload: CdxBoardPayload): CdxBoardPayload {
31
34
  if (!payload || !Array.isArray(payload.indexes) || payload.indexes.some((index) =>
@@ -33,7 +36,11 @@ function validateCdxBoard(payload: CdxBoardPayload): CdxBoardPayload {
33
36
  || (index.quote !== "spread" && index.quote !== "price")
34
37
  || !finiteOrNull(index.level) || !finiteOrNull(index.change1D) || !finiteOrNull(index.change1W)
35
38
  || (index.change1M !== undefined && !finiteOrNull(index.change1M))
36
- || !finiteOrNull(index.prints) || (index.date !== null && !isDate(index.date)) || !validPoints(index.points))) {
39
+ || !finiteOrNull(index.prints) || (index.date !== null && !isDate(index.date)) || !validPoints(index.points)
40
+ || !optionalFinite(index.spreadBp) || (index.recovery !== undefined && !Number.isFinite(index.recovery))
41
+ || (index.partial !== undefined && typeof index.partial !== "boolean")
42
+ || (index.lastPrintAt != null && !isInstant(index.lastPrintAt))
43
+ || (index.changeDate != null && !isDate(index.changeDate)))) {
37
44
  throw new Error("The server returned an invalid index CDS board");
38
45
  }
39
46
  return payload;
@@ -1,9 +1,26 @@
1
1
  import type { HeadlessPaneColumn, HeadlessPaneDefinition, HeadlessPaneRow } from "../../../types/plugin";
2
2
  import type { CdxBoardIndex, CreditIndexQuote } from "../../../api-client/credit-boards";
3
3
  import { CDX_MAX_DAYS, fetchCdxBoard, fetchSovrBoard, loadCurrencyMoves } from "./client";
4
- import { cdxRows, formatContract, formatCurrencyMove, formatLevel, formatMove, quoteUnits, sovrRows } from "./model";
4
+ import {
5
+ cdxDay,
6
+ cdxRows,
7
+ findIndex,
8
+ findSovereign,
9
+ formatContract,
10
+ formatCurrencyMove,
11
+ formatLevel,
12
+ formatMove,
13
+ partialDayText,
14
+ quoteUnits,
15
+ sovrRows,
16
+ } from "./model";
5
17
 
6
18
  const percentile = (value: unknown) => value == null ? "--" : Number(value).toFixed(0);
19
+ /** A 1Y rank as the board draws it, a whole number, so exports do not carry 8.23293172691. */
20
+ const rank = (value: number | null) => value == null ? null : Math.round(value);
21
+ /** The series a row is of, as `history` and the data catalog name it: `cdx:hy`, `sovereign-cds:br`. */
22
+ const cdxSeries = (id: string) => `cdx:${id.toLowerCase()}`;
23
+ const sovereignSeries = (id: string) => `sovereign-cds:${id.toLowerCase()}`;
7
24
  const numberOrNull = (value: unknown) => typeof value === "number" ? value : null;
8
25
  /** A row's quote, from the unit its level is in. */
9
26
  const rowQuote = (row: HeadlessPaneRow): CreditIndexQuote => row.unit === "bp" ? "spread" : "price";
@@ -21,39 +38,62 @@ const moveColumn = (key: string, header: string, unitKey: string): HeadlessPaneC
21
38
  key, header, align: "right", unitKey,
22
39
  textFormat: (value, row) => formatMove(rowQuote(row), numberOrNull(value)),
23
40
  });
41
+ /** HY and EM's price as a spread in bp; spread-quoted rows leave it blank, their level already is one. */
42
+ const spreadColumn: HeadlessPaneColumn = {
43
+ key: "spreadBp", header: "Spread eq", align: "right", unitKey: "spreadUnit",
44
+ description: "HY and EM: the price as a conventional spread in bp, under the ISDA standard model: a flat hazard rate, the index's "
45
+ + "coupon (HY 500bp, EM 100bp) and standard recovery (HY 30%, EM 25%), the contract's maturity and that day's flat USD rate. "
46
+ + "Price 100 is the coupon; above 100 the spread is under it.",
47
+ textFormat: (value) => formatLevel("spread", numberOrNull(value)),
48
+ };
49
+ /** A day still trading says what it rests on; a complete day says nothing. */
50
+ const dayColumn: HeadlessPaneColumn = {
51
+ key: "session", header: "Day",
52
+ description: "Blank for a complete day. For today's New York trade date, still trading: so far, the prints behind its level and the last one's time (UTC).",
53
+ format: (value) => typeof value === "string" ? value : "",
54
+ };
24
55
 
25
56
  /** The publisher a board's payload names, spelled out: `DTCC PPD` is DTCC's public price dissemination. */
26
57
  function boardPublisher(source: string | null | undefined): string | undefined {
27
58
  return source?.trim().replace(/\bPPD\b/, "Public Price Dissemination") || undefined;
28
59
  }
29
60
 
30
- /** `IG`, `cdx hy`, `itraxx main`, `crossover`: an index by its code, its name or the name's last word. */
31
- function findIndex(indexes: readonly CdxBoardIndex[], query: string): CdxBoardIndex | null {
32
- const key = (text: string) => text.toLowerCase().replace(/[^a-z0-9]/g, "");
33
- const wanted = key(query) === "crossover" ? "xover" : key(query);
34
- return indexes.find((index) => [index.id, index.name, index.name.split(" ").at(-1) ?? ""]
35
- .some((name) => key(name) === wanted)) ?? null;
36
- }
37
-
38
61
  /**
39
62
  * Each day's level on the contract on the run that day, newest first, over
40
63
  * the last `days`: the chart as a table. Its key is `day`, not `date`, so the
41
- * history is not read as the board's own observation dates.
64
+ * history is not read as the board's own observation dates; every exported
65
+ * row is dated by its day and names the series and unit. HY and EM carry each
66
+ * day's spread equivalent, and today's day, still trading, says so.
42
67
  */
43
- function historySection(index: CdxBoardIndex, days: number) {
68
+ function historySection(index: CdxBoardIndex, days: number, now: number) {
44
69
  const unit = quoteUnits(index.quote).level;
45
70
  const latest = index.points.at(-1)?.date;
46
71
  const from = latest ? new Date(Date.parse(`${latest}T00:00:00Z`) - days * 86_400_000).toISOString().slice(0, 10) : "";
72
+ const today = cdxDay(index, now);
73
+ // A server that predates the spread equivalent sends none: no column of blanks.
74
+ const priced = index.quote === "price" && index.points.some((point) => point.spreadBp !== undefined);
75
+ const partial = today.partial && latest === index.date;
76
+ const symbol = cdxSeries(index.id);
47
77
  return {
48
78
  title: `${index.name} 5Y daily ${index.quote === "spread" ? "spread" : "price"}`,
49
79
  columns: [
50
80
  { key: "day", header: "Date" },
51
81
  { ...levelColumn, header: index.quote === "spread" ? "Spread" : "Price" },
82
+ ...(priced ? [spreadColumn] : []),
52
83
  { key: "prints", header: "Prints", align: "right" as const },
53
84
  { key: "maturity", header: "Contract", textFormat: (value: unknown) => formatContract(typeof value === "string" ? value : null) },
85
+ ...(partial ? [dayColumn] : []),
54
86
  ],
55
- rows: index.points.filter((point) => point.date > from).reverse()
56
- .map((point) => ({ day: point.date, level: point.level, unit, prints: point.prints, maturity: point.maturity })),
87
+ rows: index.points.filter((point) => point.date > from).reverse().map((point) => ({
88
+ day: point.date, level: point.level, unit,
89
+ ...(priced ? { spreadBp: point.spreadBp ?? null, spreadUnit: "bp" } : {}),
90
+ prints: point.prints, maturity: point.maturity, series: symbol,
91
+ ...(partial && point.date === latest ? { session: partialDayText(point.prints, today.lastPrintAt), partial: true, lastPrintAt: today.lastPrintAt } : {}),
92
+ })),
93
+ rowUnitKey: "unit",
94
+ rowSymbolKey: "series",
95
+ rowAsOfKey: "day",
96
+ interval: "daily",
57
97
  };
58
98
  }
59
99
 
@@ -63,6 +103,7 @@ const CDX_COLUMNS: HeadlessPaneColumn[] = [
63
103
  moveColumn("change1D", "1D", "changeUnit"),
64
104
  moveColumn("change1W", "1W", "changeUnit"),
65
105
  moveColumn("change1M", "1M", "changeUnit"),
106
+ spreadColumn,
66
107
  { key: "percentile", header: "Pctl 1Y", align: "right", format: percentile },
67
108
  { key: "prints", header: "Prints", align: "right" },
68
109
  { key: "contract", header: "Contract" },
@@ -71,12 +112,13 @@ const CDX_COLUMNS: HeadlessPaneColumn[] = [
71
112
 
72
113
  export const cdxHeadless: HeadlessPaneDefinition<"bundle"> = {
73
114
  discovery: { aliases: ["CDX"], dataRequirements: ["Gloom Cloud index CDS endpoint"],
74
- limitations: ["Daily medians of public DTCC prints on the on-the-run 5Y contract.", "HY and EM quote in price, and move in points."] },
115
+ limitations: ["Daily medians of public DTCC prints on the on-the-run 5Y contract.", "HY and EM quote in price, and move in points; Spread eq converts their price at a standard coupon and recovery, a model figure, not a traded spread.",
116
+ "Today's New York trade date is so far until it ends; the moves compare complete days."] },
75
117
  shape: "bundle",
76
118
  freshness: { source: "DTCC", status: "not-a-feed", basis: "daily medians of public trades", cadence: "daily", observedKey: "date" },
77
119
  argument: { kind: "free-text", optional: true, placeholder: "index",
78
120
  description: "An index (IG, HY, EM, MAIN, XOVER) for its daily history; omit for the board." },
79
- options: [{ key: "days", type: "integer", minimum: 30, maximum: CDX_MAX_DAYS, defaultValue: 365,
121
+ options: [{ key: "days", shot: { reportOnly: "sets how many days of an index's history the text report prints" }, type: "integer", minimum: 30, maximum: CDX_MAX_DAYS, defaultValue: 365,
80
122
  description: "Days of a named index's daily levels." }],
81
123
  describe: "Index CDS",
82
124
  async load(args, ctx) {
@@ -87,27 +129,41 @@ export const cdxHeadless: HeadlessPaneDefinition<"bundle"> = {
87
129
  const index = query ? findIndex(payload.indexes, query) : null;
88
130
  if (query && !index) throw new Error(`No index ${query}. Use one of: ${payload.indexes.map((entry) => entry.id).join(", ")}.`);
89
131
  const publisher = boardPublisher(payload.source);
90
- const rows = cdxRows(index ? [index] : payload.indexes, payload.asOf).map((row) => {
132
+ const now = Date.now();
133
+ const shown = index ? [index] : payload.indexes;
134
+ // A server that predates the spread equivalent sends none: no column of blanks.
135
+ const spreads = shown.some((entry) => entry.spreadBp !== undefined);
136
+ const rows = cdxRows(shown, payload.asOf, now).map((row) => {
91
137
  const units = quoteUnits(row.index.quote);
138
+ const priced = spreads && row.index.quote === "price";
92
139
  return {
93
140
  name: row.label,
141
+ series: cdxSeries(row.index.id),
94
142
  level: row.index.level,
95
143
  unit: units.level,
96
- change1D: row.index.change1D,
97
- change1W: row.index.change1W,
98
- change1M: row.index.change1M ?? null,
144
+ change1D: row.day.change1D,
145
+ change1W: row.day.change1W,
146
+ change1M: row.day.change1M,
99
147
  changeUnit: units.move,
100
- percentile: row.percentile,
148
+ ...(priced ? { spreadBp: row.index.spreadBp ?? null, spreadUnit: "bp" } : {}),
149
+ percentile: rank(row.percentile),
101
150
  prints: row.index.prints,
102
151
  contract: formatContract(row.index.maturity),
103
152
  date: row.index.date,
153
+ changeDate: row.day.changeDate,
154
+ ...(row.day.partial ? { session: partialDayText(row.index.prints, row.day.lastPrintAt), partial: true, lastPrintAt: row.day.lastPrintAt } : {}),
104
155
  };
105
156
  });
157
+ const anyPartial = rows.some((row) => row.partial === true);
106
158
  return {
107
159
  sections: [
108
- { title: "On the run, 5Y", columns: CDX_COLUMNS, rows },
109
- ...(index ? [historySection(index, days)] : []),
160
+ {
161
+ title: "On the run, 5Y", columns: [...CDX_COLUMNS.filter((column) => spreads || column !== spreadColumn), ...(anyPartial ? [dayColumn] : [])], rows,
162
+ rowUnitKey: "unit", rowSymbolKey: "series", rowAsOfKey: "date", interval: "daily",
163
+ },
164
+ ...(index ? [historySection(index, days, now)] : []),
110
165
  ],
166
+ ...(anyPartial ? { notes: ["Today's New York trade date is still trading: its level and prints are so far, and 1D, 1W and 1M run to the last complete day."] } : {}),
111
167
  metadata: { asOf: payload.asOf },
112
168
  ...(publisher ? { freshness: { publisher } } : {}),
113
169
  };
@@ -119,7 +175,8 @@ export const sovrHeadless: HeadlessPaneDefinition<"rows"> = {
119
175
  limitations: ["Daily 5Y levels from public DTCC prints; thinly traded names can miss days."] },
120
176
  shape: "rows",
121
177
  freshness: { source: "DTCC", status: "not-a-feed", basis: "daily levels of public trades", cadence: "daily", observedKey: "date" },
122
- argument: { kind: "none" },
178
+ argument: { kind: "free-text", optional: true, placeholder: "country",
179
+ description: "A country (Brazil, BR) to list its row alone; omit for every sovereign." },
123
180
  options: [],
124
181
  columns: [
125
182
  { key: "name", header: "Sovereign" },
@@ -130,21 +187,30 @@ export const sovrHeadless: HeadlessPaneDefinition<"rows"> = {
130
187
  { key: "date", header: "As of" },
131
188
  ],
132
189
  describe: "Sovereign CDS",
133
- async load(_args, ctx) {
190
+ async load(args, ctx) {
134
191
  const payload = await fetchSovrBoard(ctx.apiClient);
135
- const moves = await loadCurrencyMoves(payload.sovereigns.map((row) => row.currency),
192
+ const query = typeof args.argument === "string" ? args.argument.trim() : "";
193
+ const country = query ? findSovereign(payload.sovereigns, query) : null;
194
+ if (query && !country) throw new Error(`No sovereign ${query}. Use one of: ${payload.sovereigns.map((entry) => entry.name).join(", ")}.`);
195
+ const sovereigns = country ? [country] : payload.sovereigns;
196
+ const moves = await loadCurrencyMoves(sovereigns.map((row) => row.currency),
136
197
  (symbol) => ctx.marketData.getPriceHistory(symbol, "", "3M"));
137
198
  const publisher = boardPublisher(payload.source);
138
199
  return {
139
- rows: sovrRows(payload.sovereigns, payload.asOf, moves).map((row) => ({
200
+ rows: sovrRows(sovereigns, payload.asOf, moves).map((row) => ({
140
201
  name: row.label,
202
+ series: sovereignSeries(row.sovereign.id),
141
203
  level: row.sovereign.level,
142
204
  unit: quoteUnits("spread").level,
143
205
  change1M: row.sovereign.change1M,
144
206
  currency: formatCurrencyMove(row.sovereign.currency, row.currencyMove),
145
- percentile: row.percentile,
207
+ percentile: rank(row.percentile),
146
208
  date: row.sovereign.date,
147
209
  })),
210
+ rowUnitKey: "unit",
211
+ rowSymbolKey: "series",
212
+ rowAsOfKey: "date",
213
+ interval: "daily",
148
214
  metadata: { asOf: payload.asOf },
149
215
  ...(publisher ? { freshness: { publisher } } : {}),
150
216
  };