gloomberb 0.18.2 → 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 (954) 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/patches/electrobun@1.18.1.patch +106 -5
  6. package/src/account/checkout-handoff.tsx +225 -0
  7. package/src/account/device-signin-dialog.tsx +2 -2
  8. package/src/account/device-signin.ts +2 -2
  9. package/src/account/upgrade-dialog.tsx +1 -1
  10. package/src/api-client/askg.ts +2 -2
  11. package/src/api-client/auth.ts +2 -2
  12. package/src/api-client/central-bank-rates.ts +6 -0
  13. package/src/api-client/collections.ts +5 -1
  14. package/src/api-client/cot.ts +2 -0
  15. package/src/api-client/crypto-etf-flows.ts +37 -0
  16. package/src/api-client/crypto-markets.ts +60 -0
  17. package/src/api-client/data.ts +99 -5
  18. package/src/api-client/doe.ts +15 -0
  19. package/src/api-client/equity-screener.ts +28 -0
  20. package/src/api-client/exchange-announcements.ts +38 -0
  21. package/src/api-client/fund-facts.ts +39 -0
  22. package/src/api-client/futures-curve.ts +9 -1
  23. package/src/api-client/hiring.ts +301 -0
  24. package/src/api-client/index.ts +24 -5
  25. package/src/api-client/market-discovery.ts +14 -0
  26. package/src/api-client/members.ts +6 -0
  27. package/src/api-client/mna.ts +6 -0
  28. package/src/api-client/paths.ts +18 -1
  29. package/src/api-client/request.ts +26 -7
  30. package/src/api-client/short-side-publications.ts +37 -0
  31. package/src/api-client/socket.ts +64 -4
  32. package/src/api-client/swap-curve.ts +35 -0
  33. package/src/api-client/telemetry.ts +17 -0
  34. package/src/api-client/themes.ts +7 -1
  35. package/src/api-client/types.ts +90 -2
  36. package/src/app/global-shortcuts.ts +1 -16
  37. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  38. package/src/app/runtime/desktop-deeplink.ts +5 -5
  39. package/src/app/runtime/plugin-bindings.ts +2 -2
  40. package/src/app/runtime/startup.ts +13 -0
  41. package/src/app/runtime/update.ts +28 -8
  42. package/src/app/star-prompt/status-line.tsx +2 -2
  43. package/src/architecture/core-builtin-allowlist.json +5 -2
  44. package/src/architecture/pane-tabs-allowlist.json +65 -0
  45. package/src/architecture/ui-literals-allowlist.json +3 -3
  46. package/src/architecture/ui-tokens-allowlist.json +1 -1
  47. package/src/brokers/broker-portfolio-sync.ts +37 -0
  48. package/src/brokers/directory.ts +11 -0
  49. package/src/brokers/logos.ts +3 -1
  50. package/src/brokers/signed-in/adapter.ts +304 -26
  51. package/src/brokers/signed-in/client.ts +14 -2
  52. package/src/brokers/signed-in/connect.ts +10 -2
  53. package/src/brokers/sync-broker-instance.ts +9 -1
  54. package/src/capabilities/chart-series.ts +22 -6
  55. package/src/cli/bank-section.ts +1 -1
  56. package/src/cli/base-converter.ts +23 -14
  57. package/src/cli/central-bank-events.ts +1 -1
  58. package/src/cli/command-options.ts +59 -4
  59. package/src/cli/commands/api.ts +9 -6
  60. package/src/cli/commands/broker.ts +2 -2
  61. package/src/cli/commands/command-utils.ts +2 -2
  62. package/src/cli/commands/crypto-hints.ts +7 -20
  63. package/src/cli/commands/fred-series.ts +4 -2
  64. package/src/cli/commands/keybindings.ts +2 -2
  65. package/src/cli/commands/market.ts +1189 -296
  66. package/src/cli/commands/news-hints.ts +2 -2
  67. package/src/cli/commands/news-search.ts +59 -6
  68. package/src/cli/commands/options-leaps.ts +41 -26
  69. package/src/cli/commands/overview.ts +121 -48
  70. package/src/cli/commands/plugins.ts +9 -9
  71. package/src/cli/commands/remote.ts +13 -10
  72. package/src/cli/commands/search.ts +64 -44
  73. package/src/cli/commands/system.ts +27 -19
  74. package/src/cli/commands/themes.ts +1 -1
  75. package/src/cli/commands/ticker.ts +272 -70
  76. package/src/cli/context.ts +3 -2
  77. package/src/cli/desktop-pane-shot-view.ts +2 -2
  78. package/src/cli/desktop-pane-shot.ts +1 -1
  79. package/src/cli/earnings-calendar.ts +4 -4
  80. package/src/cli/entry.ts +18 -1
  81. package/src/cli/errors.ts +20 -2
  82. package/src/cli/exit-codes.ts +1 -1
  83. package/src/cli/export-source.ts +10 -4
  84. package/src/cli/freshness.ts +2 -8
  85. package/src/cli/fx-forward.ts +130 -0
  86. package/src/cli/fx-pair.ts +10 -9
  87. package/src/cli/glossary.ts +64 -20
  88. package/src/cli/help.ts +20 -14
  89. package/src/cli/history-export.ts +126 -0
  90. package/src/cli/history-rows.ts +196 -43
  91. package/src/cli/index-roots.ts +5 -45
  92. package/src/cli/index.ts +32 -18
  93. package/src/cli/issuer-membership.ts +103 -0
  94. package/src/cli/known-gaps.ts +118 -25
  95. package/src/cli/listing-arg.ts +315 -43
  96. package/src/cli/name-entries.ts +73 -22
  97. package/src/cli/native-smoke.ts +2 -0
  98. package/src/cli/not-a-ticker.ts +19 -9
  99. package/src/cli/opentui-libc.ts +5 -0
  100. package/src/cli/options.ts +12 -0
  101. package/src/cli/pane-functions/capabilities.ts +77 -20
  102. package/src/cli/pane-functions/catalog.ts +40 -23
  103. package/src/cli/pane-functions/discovery.ts +1 -1
  104. package/src/cli/pane-functions/dom.ts +12 -8
  105. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  106. package/src/cli/pane-functions/freshness.ts +174 -23
  107. package/src/cli/pane-functions/function-help.ts +66 -27
  108. package/src/cli/pane-functions/headless.ts +48 -16
  109. package/src/cli/pane-functions/index.ts +82 -21
  110. package/src/cli/pane-functions/options.ts +22 -2
  111. package/src/cli/pane-functions/report-notices.ts +12 -4
  112. package/src/cli/pane-functions/report.ts +5 -5
  113. package/src/cli/pane-functions/resolver.ts +65 -14
  114. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  115. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  116. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  117. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  118. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  119. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  120. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  121. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  122. package/src/cli/pane-functions/shot-options.ts +8 -3
  123. package/src/cli/peso-dollar-rates.ts +79 -0
  124. package/src/cli/quote-answer.ts +38 -3
  125. package/src/cli/report-tables.ts +190 -27
  126. package/src/cli/restore-plugins.ts +29 -14
  127. package/src/cli/result.ts +122 -25
  128. package/src/cli/series-search.ts +5 -5
  129. package/src/cli/statement-filings.ts +19 -0
  130. package/src/cli/suffixed-listing-rows.ts +49 -0
  131. package/src/cli/symbol-args.ts +50 -15
  132. package/src/cli/symbol-cells.ts +120 -0
  133. package/src/cli/symbol-list.ts +226 -60
  134. package/src/cli/symbol-rows.ts +131 -25
  135. package/src/cli/ticker-resolution.ts +108 -11
  136. package/src/cli/treasury-yields.ts +5 -5
  137. package/src/cli/types.ts +2 -0
  138. package/src/cli/uncovered-instrument.ts +3 -3
  139. package/src/cli/unknown-command.ts +6 -6
  140. package/src/components/chart/composite/chart-layout.ts +131 -0
  141. package/src/components/chart/composite/composite-chart.tsx +387 -21
  142. package/src/components/chart/composite/drawing-store.ts +26 -6
  143. package/src/components/chart/composite/interactions.ts +9 -3
  144. package/src/components/chart/composite/legend.tsx +75 -3
  145. package/src/components/chart/composite/levels.ts +5 -0
  146. package/src/components/chart/composite/panel-gestures.ts +41 -0
  147. package/src/components/chart/composite/panel-labels.ts +2 -1
  148. package/src/components/chart/composite/panel-surface.tsx +316 -11
  149. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  150. package/src/components/chart/composite/rasterizer.ts +44 -19
  151. package/src/components/chart/composite/scene.ts +16 -4
  152. package/src/components/chart/composite/text-renderer.ts +48 -21
  153. package/src/components/chart/composite/toolbar.tsx +52 -5
  154. package/src/components/chart/composite/types.ts +19 -0
  155. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  156. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  157. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  158. package/src/components/chart/composite/value-scale.ts +149 -0
  159. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  160. package/src/components/chart/core/pointer.ts +2 -0
  161. package/src/components/chart-table/index.ts +2 -0
  162. package/src/components/chart-table/read.tsx +74 -0
  163. package/src/components/command-bar/commands/collection-list.ts +41 -19
  164. package/src/components/command-bar/commands/collection.ts +9 -3
  165. package/src/components/command-bar/commands/direct/index.ts +1 -1
  166. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  167. package/src/components/command-bar/pane-templates/items.ts +59 -6
  168. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  169. package/src/components/command-bar/routes/root/command-items.ts +32 -6
  170. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  171. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  172. package/src/components/command-bar/routes/root/results.ts +18 -4
  173. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  174. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  175. package/src/components/command-bar/routes/root/selection.ts +6 -1
  176. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  177. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  178. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  179. package/src/components/command-bar/selection-runtime.ts +50 -10
  180. package/src/components/command-bar/surface/index.tsx +24 -2
  181. package/src/components/command-bar/view-model.ts +7 -0
  182. package/src/components/command-bar/workflow/broker.ts +2 -2
  183. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  184. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  185. package/src/components/command-bar/workflow/fields.ts +8 -2
  186. package/src/components/command-bar/workflow/ops.ts +18 -4
  187. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  188. package/src/components/command-bar/workflow/submit.ts +3 -2
  189. package/src/components/command-bar/workflow/tickers.ts +5 -1
  190. package/src/components/company-logo.tsx +39 -0
  191. package/src/components/data-table/sections.ts +4 -2
  192. package/src/components/data-table/view.tsx +23 -3
  193. package/src/components/form-modal/confirm.tsx +2 -1
  194. package/src/components/form-modal/request.ts +5 -0
  195. package/src/components/form-modal/routes.ts +4 -1
  196. package/src/components/index.ts +13 -6
  197. package/src/components/layout/detached-pane-shell.tsx +1 -0
  198. package/src/components/layout/floating-pane.tsx +1 -0
  199. package/src/components/layout/header.tsx +234 -60
  200. package/src/components/layout/market-summary.ts +9 -6
  201. package/src/components/layout/pane/capture-status.ts +1 -1
  202. package/src/components/layout/pane/footer/model.ts +11 -5
  203. package/src/components/layout/pane/header.tsx +10 -3
  204. package/src/components/layout/pane/index.tsx +1 -0
  205. package/src/components/layout/pane/pane-tabs.tsx +9 -1
  206. package/src/components/layout/shell/chrome.ts +19 -6
  207. package/src/components/layout/shell/index.tsx +2 -1
  208. package/src/components/layout/shell/pane/layers.tsx +19 -1
  209. package/src/components/layout/status-bar.tsx +2 -2
  210. package/src/components/market-board/index.tsx +11 -3
  211. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  212. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  213. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  214. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  215. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  216. package/src/components/pane-settings-dialog/value.ts +8 -1
  217. package/src/components/pane-settings-dialog.tsx +44 -13
  218. package/src/components/sign-in-code-panel.tsx +27 -19
  219. package/src/components/ui/column-grid.tsx +48 -4
  220. package/src/components/ui/country-flag-art.tsx +180 -0
  221. package/src/components/ui/country-flag.tsx +118 -12
  222. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  223. package/src/components/ui/data-table/opentui/model.ts +109 -2
  224. package/src/components/ui/data-table/types.ts +1 -1
  225. package/src/components/ui/display.tsx +5 -1
  226. package/src/components/ui/index.ts +3 -1
  227. package/src/components/ui/logo-mark.tsx +11 -2
  228. package/src/components/ui/query-bar.tsx +1 -1
  229. package/src/components/ui/row-notes.ts +79 -0
  230. package/src/components/ui/stat-grid.tsx +28 -3
  231. package/src/components/ui/status.tsx +3 -1
  232. package/src/core/app-services.ts +4 -0
  233. package/src/core/state/app/layout.ts +4 -4
  234. package/src/data/cached-query.ts +8 -1
  235. package/src/data/config/chart-settings.ts +3 -3
  236. package/src/data/config/home.ts +10 -2
  237. package/src/data/config/layout.ts +4 -1
  238. package/src/data/config/store/node.ts +4 -0
  239. package/src/data/config/store/normalize.ts +13 -3
  240. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  241. package/src/data/json-storage.ts +2 -0
  242. package/src/data/saved-copies.ts +84 -0
  243. package/src/docs/snapshot.json +65 -32
  244. package/src/i18n/es.ts +51 -12
  245. package/src/i18n/ja.ts +51 -12
  246. package/src/i18n/ko.ts +51 -12
  247. package/src/i18n/zh-cn.ts +51 -12
  248. package/src/i18n/zh-tw.ts +51 -12
  249. package/src/layout/desks.ts +1 -1
  250. package/src/layout/launch-layout.ts +1 -1
  251. package/src/layout/pane-manager/floating-actions.ts +5 -3
  252. package/src/layout/pane-manager/floating.ts +43 -1
  253. package/src/layout/pane-manager/index.ts +2 -0
  254. package/src/layout/selected-ticker.ts +74 -0
  255. package/src/market-data/depositary-pair.ts +251 -0
  256. package/src/market-data/futures-board.ts +1 -1
  257. package/src/market-data/futures-contract.ts +124 -40
  258. package/src/market-data/fx-closes.ts +17 -2
  259. package/src/market-data/hooks.tsx +19 -11
  260. package/src/market-data/market/change-basis.ts +49 -7
  261. package/src/market-data/market/freshness.ts +34 -5
  262. package/src/market-data/market/period-return.ts +163 -0
  263. package/src/market-data/market/trading-sessions.ts +13 -0
  264. package/src/market-data/market/year-to-date.ts +8 -13
  265. package/src/market-data/performance.ts +20 -14
  266. package/src/market-data/perpetual-premium.ts +32 -0
  267. package/src/market-data/published-apac-sessions.ts +2 -1
  268. package/src/market-data/published-futures-sessions.ts +69 -0
  269. package/src/market-data/quotes/contributions.ts +5 -1
  270. package/src/market-data/quotes/freshness.ts +42 -0
  271. package/src/market-data/quotes/intraday-bar.ts +37 -0
  272. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  273. package/src/market-data/quotes/resolution.ts +4 -2
  274. package/src/market-data/tax-equivalent.ts +1 -1
  275. package/src/market-data/ticker-price-returns.ts +3 -1
  276. package/src/news/aggregator.ts +5 -1
  277. package/src/news/news-model.ts +4 -0
  278. package/src/news/types.ts +11 -0
  279. package/src/notifications/app-notifier.ts +1 -1
  280. package/src/plugins/auto-update.ts +2 -2
  281. package/src/plugins/builtin/account-management/index.tsx +1 -0
  282. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  283. package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
  284. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  285. package/src/plugins/builtin/alerts/cli.ts +485 -76
  286. package/src/plugins/builtin/alerts/command.ts +5 -10
  287. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  288. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  289. package/src/plugins/builtin/alerts/events.ts +108 -5
  290. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  291. package/src/plugins/builtin/alerts/format.ts +2 -1
  292. package/src/plugins/builtin/alerts/headless.ts +100 -39
  293. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  294. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  295. package/src/plugins/builtin/alerts/index.tsx +45 -18
  296. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  297. package/src/plugins/builtin/alerts/levels.ts +3 -3
  298. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  299. package/src/plugins/builtin/alerts/price.ts +35 -0
  300. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  301. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  302. package/src/plugins/builtin/alerts/research-rules.ts +77 -3
  303. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  304. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  305. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  306. package/src/plugins/builtin/alerts/storage.ts +13 -10
  307. package/src/plugins/builtin/alerts/targets.ts +12 -3
  308. package/src/plugins/builtin/analytics/index.tsx +8 -2
  309. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  310. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  311. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  312. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  313. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  314. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  315. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  316. package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
  317. package/src/plugins/builtin/attention/pane.tsx +22 -16
  318. package/src/plugins/builtin/awards/headless.ts +7 -3
  319. package/src/plugins/builtin/awards/model.ts +18 -0
  320. package/src/plugins/builtin/awards/pane.tsx +12 -9
  321. package/src/plugins/builtin/backtest/export.ts +1 -1
  322. package/src/plugins/builtin/backtest/headless.ts +3 -3
  323. package/src/plugins/builtin/backtest/rules.ts +41 -5
  324. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  325. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  326. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  327. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  328. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  329. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  330. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  331. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  332. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  333. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  334. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  335. package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
  336. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  337. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  338. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  339. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  340. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  341. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  342. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  343. package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
  344. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  345. package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
  346. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  347. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  348. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  349. package/src/plugins/builtin/buildout/pane/index.tsx +34 -18
  350. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  351. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  352. package/src/plugins/builtin/catalysts/client.ts +2 -2
  353. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  354. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  355. package/src/plugins/builtin/catalysts/model.ts +49 -4
  356. package/src/plugins/builtin/catalysts/pane.tsx +9 -11
  357. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  358. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  359. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  360. package/src/plugins/builtin/changelog/index.tsx +1 -0
  361. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  362. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  363. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  364. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  365. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  366. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  367. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  368. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  369. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  370. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  371. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  372. package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
  373. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  374. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  375. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  376. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  377. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  378. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  379. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  380. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  381. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  382. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  383. package/src/plugins/builtin/chat/people.ts +1 -1
  384. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  385. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  386. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  387. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  388. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  389. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  390. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  391. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  392. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  393. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  394. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  395. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  396. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  397. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  398. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  399. package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
  400. package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
  401. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  402. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  403. package/src/plugins/builtin/company-attention/client.ts +117 -1
  404. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  405. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  406. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  407. package/src/plugins/builtin/company-attention/model.ts +33 -7
  408. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  409. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  410. package/src/plugins/builtin/company-attention/pane.tsx +89 -31
  411. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  412. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  413. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  414. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  415. package/src/plugins/builtin/company-kpis/pane.tsx +5 -4
  416. package/src/plugins/builtin/composite-plugins.ts +2 -1
  417. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  418. package/src/plugins/builtin/connections/index.ts +1 -0
  419. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  420. package/src/plugins/builtin/correlation/headless.ts +7 -4
  421. package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
  422. package/src/plugins/builtin/correlation/settings.ts +1 -0
  423. package/src/plugins/builtin/cot/headless.ts +28 -6
  424. package/src/plugins/builtin/cot/model.ts +12 -0
  425. package/src/plugins/builtin/cot/pane.tsx +7 -5
  426. package/src/plugins/builtin/cpi/headless.ts +5 -1
  427. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  428. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  429. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  430. package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
  431. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  432. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  433. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  434. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  435. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  436. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  437. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  438. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  439. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  440. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  441. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  442. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  443. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  444. package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
  445. package/src/plugins/builtin/debug/index.tsx +1 -0
  446. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  447. package/src/plugins/builtin/docs/index.tsx +1 -1
  448. package/src/plugins/builtin/docs/pane.tsx +2 -2
  449. package/src/plugins/builtin/docs/targets.ts +1 -1
  450. package/src/plugins/builtin/doe/client.ts +5 -1
  451. package/src/plugins/builtin/doe/headless.ts +12 -6
  452. package/src/plugins/builtin/doe/model.ts +43 -6
  453. package/src/plugins/builtin/doe/pane.tsx +19 -12
  454. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  455. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  456. package/src/plugins/builtin/earnings/board.tsx +253 -50
  457. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  458. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  459. package/src/plugins/builtin/earnings/client.ts +4 -3
  460. package/src/plugins/builtin/earnings/headless.ts +53 -15
  461. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  462. package/src/plugins/builtin/earnings/index.tsx +15 -22
  463. package/src/plugins/builtin/earnings/model.ts +17 -12
  464. package/src/plugins/builtin/earnings/scope.ts +89 -0
  465. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  466. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  467. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  468. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  469. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  470. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  471. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  472. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  473. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  474. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  475. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  476. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  477. package/src/plugins/builtin/econ/index.tsx +112 -25
  478. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  479. package/src/plugins/builtin/econ/types.ts +32 -1
  480. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  481. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  482. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  483. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  484. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  485. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  486. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  487. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  488. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  489. package/src/plugins/builtin/equity-screener/headless.ts +77 -5
  490. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  491. package/src/plugins/builtin/equity-screener/model.ts +34 -0
  492. package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
  493. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  494. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  495. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  496. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  497. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  498. package/src/plugins/builtin/exposure/headless.ts +51 -6
  499. package/src/plugins/builtin/exposure/index.tsx +28 -2
  500. package/src/plugins/builtin/exposure/model.ts +7 -0
  501. package/src/plugins/builtin/exposure/pane.tsx +16 -10
  502. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  503. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  504. package/src/plugins/builtin/futures/model.ts +10 -9
  505. package/src/plugins/builtin/futures/returns.ts +8 -36
  506. package/src/plugins/builtin/futures/table.tsx +1 -1
  507. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  508. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  509. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  510. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  511. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  512. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  513. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  514. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  515. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  516. package/src/plugins/builtin/gpu/board.tsx +4 -1
  517. package/src/plugins/builtin/gpu/changes.tsx +10 -10
  518. package/src/plugins/builtin/gpu/equities.tsx +4 -1
  519. package/src/plugins/builtin/gpu/headless.ts +9 -4
  520. package/src/plugins/builtin/gpu/history.tsx +4 -2
  521. package/src/plugins/builtin/gpu/pane.tsx +5 -3
  522. package/src/plugins/builtin/help/index.tsx +13 -3
  523. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  524. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  525. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  526. package/src/plugins/builtin/holders/client.ts +15 -2
  527. package/src/plugins/builtin/holders/format.ts +28 -17
  528. package/src/plugins/builtin/holders/headless.ts +48 -8
  529. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  530. package/src/plugins/builtin/holders/pane.tsx +79 -15
  531. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  532. package/src/plugins/builtin/holders/table-model.ts +2 -1
  533. package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
  534. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  535. package/src/plugins/builtin/insider/base-values.ts +11 -7
  536. package/src/plugins/builtin/insider/client.ts +3 -0
  537. package/src/plugins/builtin/insider/headless.ts +20 -7
  538. package/src/plugins/builtin/insider/index.tsx +17 -8
  539. package/src/plugins/builtin/insider/issuer.ts +34 -4
  540. package/src/plugins/builtin/insider/signals-client.ts +3 -3
  541. package/src/plugins/builtin/insider/signals.tsx +1 -1
  542. package/src/plugins/builtin/insider/table-model.ts +35 -13
  543. package/src/plugins/builtin/insider/table.tsx +5 -2
  544. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  545. package/src/plugins/builtin/iv-history/client.ts +20 -0
  546. package/src/plugins/builtin/iv-history/events.ts +145 -0
  547. package/src/plugins/builtin/iv-history/format.ts +3 -0
  548. package/src/plugins/builtin/iv-history/headless.ts +91 -7
  549. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  550. package/src/plugins/builtin/iv-history/model.ts +13 -4
  551. package/src/plugins/builtin/iv-history/series.ts +3 -1
  552. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  553. package/src/plugins/builtin/jobs/model.ts +4 -15
  554. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  555. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  556. package/src/plugins/builtin/jodi/pane.tsx +14 -8
  557. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  558. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  559. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  560. package/src/plugins/builtin/macro-day/model.ts +29 -8
  561. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  562. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  563. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  564. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  565. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  566. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  567. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  568. package/src/plugins/builtin/market-movers/client.ts +36 -21
  569. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  570. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  571. package/src/plugins/builtin/market-movers/screener.ts +33 -11
  572. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  573. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  574. package/src/plugins/builtin/market-movers/table.ts +4 -1
  575. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  576. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  577. package/src/plugins/builtin/members/headless.ts +6 -5
  578. package/src/plugins/builtin/members/pane.tsx +11 -4
  579. package/src/plugins/builtin/mna/client.ts +1 -0
  580. package/src/plugins/builtin/mna/detail.tsx +20 -32
  581. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  582. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  583. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  584. package/src/plugins/builtin/mna/headless.ts +6 -13
  585. package/src/plugins/builtin/mna/model.ts +93 -15
  586. package/src/plugins/builtin/mna/pane.tsx +5 -4
  587. package/src/plugins/builtin/news/headless.ts +12 -6
  588. package/src/plugins/builtin/news/index.tsx +10 -1
  589. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  590. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  591. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  592. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  593. package/src/plugins/builtin/notes/cli.ts +50 -15
  594. package/src/plugins/builtin/notes/export.ts +17 -6
  595. package/src/plugins/builtin/notes/files.ts +16 -5
  596. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  597. package/src/plugins/builtin/options/carry.ts +2 -2
  598. package/src/plugins/builtin/options/enrichment-model.ts +10 -9
  599. package/src/plugins/builtin/options/index.tsx +1 -1
  600. package/src/plugins/builtin/options/model-spot.ts +70 -4
  601. package/src/plugins/builtin/options/view.tsx +51 -23
  602. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  603. package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
  604. package/src/plugins/builtin/options-positioning/headless.ts +11 -3
  605. package/src/plugins/builtin/options-positioning/model.ts +24 -0
  606. package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
  607. package/src/plugins/builtin/options-scenario/client.ts +142 -29
  608. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  609. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  610. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  611. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  612. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  613. package/src/plugins/builtin/options-scenario/headless.ts +49 -21
  614. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  615. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  616. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  617. package/src/plugins/builtin/options-scenario/pane.tsx +22 -10
  618. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  619. package/src/plugins/builtin/perps/freshness.ts +8 -5
  620. package/src/plugins/builtin/perps/headless.ts +3 -1
  621. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  622. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  623. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  624. package/src/plugins/builtin/perps/pane.tsx +36 -17
  625. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  626. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  627. package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
  628. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
  629. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  630. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  631. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  632. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  633. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  634. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  635. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  636. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  637. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  638. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  639. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  640. package/src/plugins/builtin/power/client.ts +6 -3
  641. package/src/plugins/builtin/power/evidence.ts +22 -7
  642. package/src/plugins/builtin/power/gas.tsx +5 -1
  643. package/src/plugins/builtin/power/pane.tsx +44 -32
  644. package/src/plugins/builtin/power/prices.tsx +10 -3
  645. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  646. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  647. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  648. package/src/plugins/builtin/research/event-model.ts +3 -1
  649. package/src/plugins/builtin/research/event-sources.ts +12 -4
  650. package/src/plugins/builtin/research/index.tsx +2 -1
  651. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  652. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  653. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  654. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  655. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  656. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  657. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  658. package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
  659. package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
  660. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  661. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  662. package/src/plugins/builtin/seasonality/client.ts +2 -1
  663. package/src/plugins/builtin/sec/forms.ts +13 -0
  664. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  665. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  666. package/src/plugins/builtin/sec/headless.ts +85 -8
  667. package/src/plugins/builtin/sec/index.tsx +58 -12
  668. package/src/plugins/builtin/sectors/client.ts +6 -4
  669. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  670. package/src/plugins/builtin/series-inventory.ts +2 -0
  671. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  672. package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
  673. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  674. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  675. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  676. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  677. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  678. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  679. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  680. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  681. package/src/plugins/builtin/shared/research-trading.tsx +23 -0
  682. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  683. package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
  684. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  685. package/src/plugins/builtin/shared/volatility/options.ts +2 -1
  686. package/src/plugins/builtin/short-interest/client.ts +2 -0
  687. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  688. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  689. package/src/plugins/builtin/short-interest/model.ts +70 -19
  690. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  691. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  692. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  693. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  694. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  695. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  696. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  697. package/src/plugins/builtin/short-interest/types.ts +9 -0
  698. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  699. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  700. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  701. package/src/plugins/builtin/social-mentions/client.ts +2 -1
  702. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  703. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  704. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  705. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  706. package/src/plugins/builtin/themes/headless.ts +8 -5
  707. package/src/plugins/builtin/themes/model.ts +14 -4
  708. package/src/plugins/builtin/themes/pane.tsx +24 -5
  709. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  710. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  711. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  712. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  713. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  714. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  715. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  716. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  717. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  718. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  719. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  720. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  721. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  722. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  723. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  724. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  725. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  726. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  727. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  728. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  729. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  730. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  731. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  732. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  733. package/src/plugins/builtin/vol-surface/client.ts +28 -7
  734. package/src/plugins/builtin/vol-surface/headless.ts +43 -15
  735. package/src/plugins/builtin/vol-surface/model.ts +34 -12
  736. package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
  737. package/src/plugins/builtin/vol-surface/stored.ts +34 -3
  738. package/src/plugins/builtin/vol-surface/tables.ts +14 -0
  739. package/src/plugins/builtin/volatility/model.ts +5 -10
  740. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  741. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  742. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  743. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  744. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  745. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  746. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  747. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  748. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  749. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  750. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  751. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  752. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  753. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  754. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  755. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  756. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  757. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  758. package/src/plugins/bundle.ts +1 -1
  759. package/src/plugins/catalog-browser.ts +2 -1
  760. package/src/plugins/compat.ts +3 -3
  761. package/src/plugins/dependencies.ts +75 -14
  762. package/src/plugins/extracted-plugins.ts +132 -34
  763. package/src/plugins/host-link.ts +149 -34
  764. package/src/plugins/installer.ts +35 -10
  765. package/src/plugins/loader.ts +206 -38
  766. package/src/plugins/manager-node.ts +2 -2
  767. package/src/plugins/marketplace/deactivation.ts +22 -0
  768. package/src/plugins/marketplace/model.ts +2 -2
  769. package/src/plugins/marketplace/packs.ts +1 -1
  770. package/src/plugins/ownership.ts +1 -1
  771. package/src/plugins/peer-retry.ts +155 -0
  772. package/src/plugins/registry/contributions.ts +3 -1
  773. package/src/plugins/registry/index.ts +4 -3
  774. package/src/plugins/registry/plugin-state.ts +3 -0
  775. package/src/plugins/seed-notice.ts +20 -0
  776. package/src/plugins/shortcut-argument.ts +39 -0
  777. package/src/portfolio/allocation.ts +1 -1
  778. package/src/portfolio/collection-name.ts +31 -0
  779. package/src/portfolio/column-values.ts +10 -8
  780. package/src/portfolio/cost-fx.ts +296 -19
  781. package/src/portfolio/manual-lots.ts +75 -0
  782. package/src/portfolio/mutations.ts +60 -22
  783. package/src/portfolio/suffixed-listings.ts +209 -0
  784. package/src/portfolio/totals-currency.ts +24 -0
  785. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  786. package/src/public/time-series.ts +11 -8
  787. package/src/remote/schema.ts +1 -1
  788. package/src/renderers/browser/config-host.ts +3 -0
  789. package/src/renderers/browser/main.tsx +23 -3
  790. package/src/renderers/dom/boot-frame-page.ts +187 -0
  791. package/src/renderers/dom/boot-frame.ts +237 -0
  792. package/src/renderers/dom/build-assets.ts +46 -8
  793. package/src/renderers/dom/desktop/controls.tsx +1 -1
  794. package/src/renderers/dom/desktop/query-bar.tsx +2 -0
  795. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  796. package/src/renderers/dom/host/ascii-text.ts +16 -2
  797. package/src/renderers/dom/host/box.tsx +43 -2
  798. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  799. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  800. package/src/renderers/dom/host/image-surface.tsx +49 -0
  801. package/src/renderers/dom/host/media-surface.tsx +24 -18
  802. package/src/renderers/dom/host/mouse.ts +30 -0
  803. package/src/renderers/dom/host/size-observer.ts +1 -1
  804. package/src/renderers/dom/host/style.ts +1 -1
  805. package/src/renderers/dom/host/tabs.tsx +16 -5
  806. package/src/renderers/dom/host/top-surface.ts +127 -0
  807. package/src/renderers/dom/styles.css +115 -0
  808. package/src/renderers/dom/test-utils.tsx +2 -1
  809. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  810. package/src/renderers/electrobun/bun/core-capabilities.ts +9 -1
  811. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  812. package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
  813. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  814. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  815. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  816. package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
  817. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  818. package/src/renderers/electrobun/bun/index.ts +11 -1
  819. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  820. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  821. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  822. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  823. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  824. package/src/renderers/electrobun/view/config-host.ts +3 -0
  825. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  826. package/src/renderers/electrobun/view/main.tsx +30 -4
  827. package/src/renderers/electrobun/view/news-source.ts +9 -7
  828. package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
  829. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  830. package/src/renderers/opentui/browser-open.ts +88 -0
  831. package/src/renderers/opentui/host.tsx +5 -14
  832. package/src/renderers/opentui/image/loader.ts +3 -2
  833. package/src/renderers/opentui/native-smoke.ts +10 -1
  834. package/src/renderers/opentui/pane-image/index.ts +2 -1
  835. package/src/renderers/opentui/render-lib.ts +253 -0
  836. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  837. package/src/renderers/opentui/start.tsx +8 -1
  838. package/src/renderers/share/layout-view.tsx +2 -2
  839. package/src/renderers/share/main.tsx +4 -4
  840. package/src/renderers/share/view.tsx +1 -1
  841. package/src/series/resolve.ts +22 -6
  842. package/src/series/standalone.ts +30 -2
  843. package/src/series/types.ts +8 -1
  844. package/src/shares/api.ts +4 -1
  845. package/src/shares/pane.ts +1 -1
  846. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  847. package/src/sources/gloomberb-cloud/index.ts +39 -16
  848. package/src/sources/gloomberb-cloud/news.ts +39 -0
  849. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  850. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  851. package/src/sources/listing-symbols.ts +37 -0
  852. package/src/sources/provider-errors.ts +16 -2
  853. package/src/sources/provider-router/financial-routes.ts +21 -3
  854. package/src/sources/provider-router/financials.ts +15 -2
  855. package/src/sources/provider-router/history.ts +30 -8
  856. package/src/sources/provider-router/index.ts +16 -0
  857. package/src/sources/provider-router/primary.ts +1 -1
  858. package/src/state/app/bootstrap.ts +23 -0
  859. package/src/state/hooks/inline-tickers.ts +30 -5
  860. package/src/sync/controller.ts +1 -1
  861. package/src/sync/core-contributors.ts +46 -14
  862. package/src/team/collections-sync.ts +2 -1
  863. package/src/team/collections.ts +178 -17
  864. package/src/telemetry/crash-reports.ts +21 -4
  865. package/src/telemetry/update-failures-node.ts +59 -0
  866. package/src/telemetry/update-failures.ts +307 -0
  867. package/src/test-support/builtin-panes.ts +1 -1
  868. package/src/theme/colors.ts +3 -30
  869. package/src/theme/ui-tokens.ts +37 -1
  870. package/src/tickers/company-name-listing.ts +215 -36
  871. package/src/tickers/company-name.ts +43 -0
  872. package/src/tickers/index-roots.ts +47 -0
  873. package/src/tickers/instrument-label.ts +5 -1
  874. package/src/tickers/listing-fate.ts +30 -0
  875. package/src/tickers/metadata.ts +10 -0
  876. package/src/tickers/perpetual-listing.ts +5 -2
  877. package/src/tickers/search/home-listing.ts +75 -0
  878. package/src/tickers/search/index.ts +76 -27
  879. package/src/tickers/search/ranking.ts +54 -4
  880. package/src/tickers/search/upsert.ts +29 -0
  881. package/src/tickers/terminal-codes.ts +416 -40
  882. package/src/time-series/bar-aggregation.ts +243 -0
  883. package/src/time-series/base-series.ts +307 -0
  884. package/src/time-series/chart-bounds.ts +349 -0
  885. package/src/time-series/chart-seed.ts +142 -0
  886. package/src/time-series/economic.ts +5 -0
  887. package/src/time-series/fundamentals.ts +18 -3
  888. package/src/time-series/history-acquisition.ts +499 -0
  889. package/src/time-series/leverage.ts +100 -0
  890. package/src/time-series/market-resolution.ts +4 -2
  891. package/src/time-series/market.ts +2 -1
  892. package/src/time-series/price-comparison.ts +175 -30
  893. package/src/time-series/range.ts +9 -1
  894. package/src/time-series/resolution.ts +174 -16
  895. package/src/time-series/resolve-context.ts +157 -0
  896. package/src/time-series/resolve.ts +126 -1577
  897. package/src/time-series/series-name.ts +38 -0
  898. package/src/time-series/series-presentation.ts +208 -0
  899. package/src/time-series/spec.ts +11 -6
  900. package/src/time-series/studies.ts +109 -12
  901. package/src/time-series/tail-reconcile.ts +121 -0
  902. package/src/time-series/types.ts +29 -2
  903. package/src/time-series/use-chart-resolution.ts +4 -5
  904. package/src/types/broker.ts +10 -0
  905. package/src/types/config.ts +14 -0
  906. package/src/types/data-provider.ts +20 -0
  907. package/src/types/exchange-rate.ts +6 -0
  908. package/src/types/financials.ts +104 -7
  909. package/src/types/headless.ts +83 -6
  910. package/src/types/instrument.ts +3 -0
  911. package/src/types/issuer-listings.ts +28 -0
  912. package/src/types/plugin.ts +65 -8
  913. package/src/types/price-history.ts +2 -0
  914. package/src/types/ticker.ts +13 -0
  915. package/src/types/trading.ts +59 -1
  916. package/src/ui/ascii-font.ts +13 -1
  917. package/src/ui/host.tsx +6 -1
  918. package/src/updater/command-names.ts +175 -0
  919. package/src/updater/failure.ts +163 -0
  920. package/src/updater/index.ts +97 -28
  921. package/src/utils/calendar-date.ts +32 -15
  922. package/src/utils/cash-runway.ts +241 -0
  923. package/src/utils/central-banks.ts +42 -0
  924. package/src/utils/cli-output.ts +259 -80
  925. package/src/utils/contract-month.ts +16 -0
  926. package/src/utils/crypto-pair.ts +61 -3
  927. package/src/utils/currency-pair.ts +26 -0
  928. package/src/utils/currency-units.ts +29 -0
  929. package/src/utils/datetime-format.ts +10 -0
  930. package/src/utils/debug-log.ts +1 -1
  931. package/src/utils/decimal-comma.ts +39 -6
  932. package/src/utils/exchange-announcements.ts +71 -0
  933. package/src/utils/exchange-rate-snapshot.ts +10 -0
  934. package/src/utils/financial-statements.ts +83 -4
  935. package/src/utils/format.ts +34 -16
  936. package/src/utils/fundamentals.ts +150 -34
  937. package/src/utils/fx-market-hours.ts +10 -1
  938. package/src/utils/latest-financial-period.ts +8 -0
  939. package/src/utils/linux-libc.ts +54 -0
  940. package/src/utils/market-capitalization.ts +111 -15
  941. package/src/utils/max-drawdown.ts +64 -0
  942. package/src/utils/network-failure.ts +83 -0
  943. package/src/utils/option-expiry.ts +139 -7
  944. package/src/utils/price-earnings.ts +11 -5
  945. package/src/utils/price-history.ts +18 -8
  946. package/src/utils/price-window.ts +131 -0
  947. package/src/utils/release-date.ts +47 -0
  948. package/src/utils/sec.ts +71 -0
  949. package/src/utils/throttled-fetch.ts +11 -4
  950. package/src/utils/trailing-eps.ts +67 -0
  951. package/src/utils/typed-text.ts +21 -0
  952. package/src/utils/utc-time.ts +24 -1
  953. package/src/version.ts +6 -0
  954. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -108,7 +108,7 @@ export function LayoutShareView({
108
108
  return (
109
109
  <main className="layout-share wide">
110
110
  <header>
111
- <p className="eyebrow">Shared via Gloomberb</p>
111
+ <p className="eyebrow">Shared via Gloom</p>
112
112
  <h1>{entry.name}</h1>
113
113
  <p className="layout-meta">{[author, date, `${entry.layout.instances.length} panes`].filter(Boolean).join(" · ")}</p>
114
114
  </header>
@@ -126,7 +126,7 @@ export function LayoutShareView({
126
126
 
127
127
  <div className="handoff">
128
128
  <a className="cta" href={openLiveUrl}>Use this layout</a>
129
- <p className="descriptor">Opens in Gloomberb as an independent, editable copy.</p>
129
+ <p className="descriptor">Opens in Gloom as an independent, editable copy.</p>
130
130
  </div>
131
131
  </main>
132
132
  );
@@ -40,7 +40,7 @@ function LayoutApp({ id }: { id: string }) {
40
40
 
41
41
  return state.entry
42
42
  ? <LayoutShareView entry={state.entry} openLiveUrl={openLiveMarketplaceLayoutUrl(id)} />
43
- : <main><h1>Gloomberb</h1><p>{state.error ?? "Loading shared layout..."}</p></main>;
43
+ : <main><h1>Gloom</h1><p>{state.error ?? "Loading shared layout..."}</p></main>;
44
44
  }
45
45
 
46
46
  function ContentShareApp({ id }: { id: string }) {
@@ -91,18 +91,18 @@ function ContentShareApp({ id }: { id: string }) {
91
91
  />
92
92
  );
93
93
  }
94
- return <main><h1>Gloomberb</h1><p>{state.error ?? "Loading shared view..."}</p></main>;
94
+ return <main><h1>Gloom</h1><p>{state.error ?? "Loading shared view..."}</p></main>;
95
95
  }
96
96
 
97
97
  function SocialShareApp() {
98
98
  const pathname = window.location.pathname;
99
99
  const layoutId = parseMarketplaceLayoutId(pathname);
100
100
  if (layoutId) return <LayoutApp id={layoutId} />;
101
- if (pathname.startsWith("/l/")) return <main><h1>Gloomberb</h1><p>Invalid layout link.</p></main>;
101
+ if (pathname.startsWith("/l/")) return <main><h1>Gloom</h1><p>Invalid layout link.</p></main>;
102
102
  const shareId = parseShareId(pathname);
103
103
  return shareId
104
104
  ? <ContentShareApp id={shareId} />
105
- : <main><h1>Gloomberb</h1><p>Invalid share link.</p></main>;
105
+ : <main><h1>Gloom</h1><p>Invalid share link.</p></main>;
106
106
  }
107
107
 
108
108
  const root = document.getElementById("root");
@@ -89,7 +89,7 @@ export function ShareView({
89
89
  return (
90
90
  <main className="pane">
91
91
  <header>
92
- <p className="eyebrow">Shared via Gloomberb</p>
92
+ <p className="eyebrow">Shared via Gloom</p>
93
93
  <h1>{share.data.title}</h1>
94
94
  {share.data.description ? <p className="pane-description">{share.data.description}</p> : null}
95
95
  </header>
@@ -6,7 +6,8 @@ import type {
6
6
  SeriesPeriod,
7
7
  TimeSeriesPoint,
8
8
  } from "../time-series/types";
9
- import { getPresetResolution, type ManualChartResolution } from "../time-series/resolution";
9
+ import { chartBarSizeSource, getPresetResolution, isCustomChartResolution } from "../time-series/resolution";
10
+ import { futuresSessionOpenMinute } from "../market-data/market/trading-sessions";
10
11
  import { SERIES_COLORS } from "../theme/series-colors";
11
12
  import type {
12
13
  LoadedSeriesDefinition,
@@ -74,9 +75,24 @@ function seriesColor(id: string, lineIndex = 0): string {
74
75
  return SERIES_COLORS[(hash + lineIndex) % SERIES_COLORS.length]!;
75
76
  }
76
77
 
77
- /** The bar size a chart draws prices in: the one it was set to, else its range's default. */
78
- function viewportResolution(viewport: ChartViewportSpec): ManualChartResolution {
79
- return viewport.resolution === "auto" ? getPresetResolution(viewport.range) : viewport.resolution;
78
+ /**
79
+ * The bars a chart draws prices in, as a load request states them: the bar
80
+ * size it was set to, else its range's default. A size the source does not
81
+ * serve (4h) goes as the source bars it is built from (`resolution: 1h`) and
82
+ * the size itself (`barSize: 4h`), so a series that knows only the source
83
+ * sizes still gets one it knows.
84
+ */
85
+ function viewportBars(viewport: ChartViewportSpec, ticker: string | undefined): Pick<SeriesLoadRequest, "resolution" | "barSize"> {
86
+ if (viewport.resolution === "auto") return { resolution: getPresetResolution(viewport.range) };
87
+ if (!isCustomChartResolution(viewport.resolution)) return { resolution: viewport.resolution };
88
+ const openMinute = ticker ? futuresSessionOpenMinute(splitTicker(ticker).symbol, splitTicker(ticker).exchange) : null;
89
+ return { resolution: chartBarSizeSource(viewport.resolution, [], openMinute), barSize: viewport.resolution };
90
+ }
91
+
92
+ /** `NESN:XSWX` as its symbol and listing. */
93
+ function splitTicker(ticker: string): { symbol: string; exchange: string } {
94
+ const colon = ticker.lastIndexOf(":");
95
+ return colon > 0 ? { symbol: ticker.slice(0, colon), exchange: ticker.slice(colon + 1) } : { symbol: ticker, exchange: "" };
80
96
  }
81
97
 
82
98
  /** The dates a chart viewport covers, as a series load request takes them. */
@@ -133,7 +149,7 @@ function loadSeries(definition: LoadedSeriesDefinition, request: SeriesLoadReque
133
149
  if (signal?.aborted) return Promise.reject(signal.reason);
134
150
  // A window measured back from now moves by milliseconds between the lines' requests.
135
151
  const minute = (date: Date | undefined) => date ? Math.floor(date.getTime() / 60_000) : null;
136
- const key = JSON.stringify([shared.ticker ?? null, minute(shared.start), minute(shared.end), shared.resolution ?? null]);
152
+ const key = JSON.stringify([shared.ticker ?? null, minute(shared.start), minute(shared.end), shared.resolution ?? null, shared.barSize ?? null]);
137
153
  let byKey = sharedLoads.get(definition);
138
154
  if (!byKey) sharedLoads.set(definition, byKey = new Map());
139
155
  let load = byKey.get(key);
@@ -182,7 +198,7 @@ export async function resolveLoadedSeries(
182
198
  const { points, edge, warning, attribution } = loadResult(await loadSeries(definition, {
183
199
  ...seriesLoadWindow(request.viewport, now),
184
200
  ...(ticker ? { ticker } : {}),
185
- resolution: viewportResolution(request.viewport),
201
+ ...viewportBars(request.viewport, ticker),
186
202
  ...(request.signal ? { signal: request.signal } : {}),
187
203
  }), line);
188
204
  const seriesId = ticker ? `${definition.id}/${ticker}` : definition.id;
@@ -4,11 +4,12 @@ import type { CapabilityInvoker } from "../capabilities/types";
4
4
  import type { GloomPlugin } from "../types/plugin";
5
5
  import { resolveRegisteredSeries } from "./capability";
6
6
  import { readSeriesFolder } from "./files";
7
- import { SeriesRegistry } from "./registry";
7
+ import { SeriesRegistry, seriesExpression } from "./registry";
8
+ import type { SeriesDefinition } from "./types";
8
9
 
9
10
  /**
10
11
  * Charts the catalog's loaded series where no plugin runtime runs, such as a
11
- * `gloomberb fn G` report: the series plugins declare, and the files in the
12
+ * `gloom fn G` report: the series plugins declare, and the files in the
12
13
  * data directory's series folder. Series a plugin registers from its setup
13
14
  * need the app.
14
15
  */
@@ -47,3 +48,30 @@ export function standaloneSeriesInvoker(
47
48
  },
48
49
  };
49
50
  }
51
+
52
+ /**
53
+ * The plugins' catalog series by what `fn G` charts each as (`FRED:DFII10`),
54
+ * where no plugin runtime runs: a series with an input (a ticker's field) is
55
+ * no one expression. The first plugin to declare an expression keeps it, as
56
+ * the registry's `findByExpression` does.
57
+ */
58
+ export function standaloneSeriesCatalog(
59
+ plugins: readonly GloomPlugin[],
60
+ disabledPlugins: readonly string[] = [],
61
+ ): (expression: string) => SeriesDefinition | undefined {
62
+ let byExpression: Map<string, SeriesDefinition> | null = null;
63
+ return (expression) => {
64
+ if (!byExpression) {
65
+ byExpression = new Map();
66
+ for (const plugin of plugins) {
67
+ if (disabledPlugins.includes(plugin.id)) continue;
68
+ for (const definition of plugin.series ?? []) {
69
+ if (definition.input) continue;
70
+ const key = seriesExpression(definition);
71
+ if (!byExpression.has(key)) byExpression.set(key, definition);
72
+ }
73
+ }
74
+ }
75
+ return byExpression.get(expression);
76
+ };
77
+ }
@@ -6,7 +6,7 @@
6
6
  * either loads its own history (`load`) or points at something the composer
7
7
  * already draws (`expression`), such as a FRED series or a ticker field.
8
8
  */
9
- import type { ManualChartResolution } from "../time-series/resolution";
9
+ import type { ChartBarSize, ManualChartResolution } from "../time-series/resolution";
10
10
 
11
11
  /** How often a series gets a new observation. */
12
12
  export type SeriesFrequency =
@@ -72,6 +72,13 @@ export interface SeriesLoadRequest {
72
72
  * bars uses it to compute on the same bars.
73
73
  */
74
74
  resolution?: ManualChartResolution;
75
+ /**
76
+ * Set when the chart builds its bars from `resolution` bars rather than
77
+ * drawing those (`4h` from `1h`, `2d` from `1d`): the bar size it draws. A
78
+ * series computed from a ticker's bars builds them the same way with
79
+ * `aggregatePriceBars`, so its points fall on the chart's bars.
80
+ */
81
+ barSize?: ChartBarSize;
75
82
  signal?: AbortSignal;
76
83
  }
77
84
 
package/src/shares/api.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ApiRequestError } from "../api-client/errors";
2
+ import { DataServiceUnreachableError } from "../utils/network-failure";
2
3
  import { parseSharePayload, type SharePayload } from "./payload";
3
4
 
4
5
  declare const __GLOOMBERB_API_URL__: string | undefined;
@@ -36,11 +37,13 @@ function validDate(value: unknown): value is string {
36
37
  * A request that never got an answer, in the words of whichever fetch made
37
38
  * it: a browser's ("Failed to fetch", Safari's "Load failed", Firefox's
38
39
  * "NetworkError ..."), Bun's ("Unable to connect ...", which the desktop
39
- * relays from its Bun process as a plain message), or a timeout.
40
+ * relays from its Bun process as a plain message), the Cloud client's
41
+ * `DataServiceUnreachableError` for any of them, or a timeout.
40
42
  */
41
43
  const NETWORK_FAILURE = /failed to fetch|load failed|networkerror|network connection was lost|appears to be offline|fetch failed|unable to connect|socket connection was closed|typo in the url or port|timed out/i;
42
44
 
43
45
  function isNetworkFailure(error: unknown): boolean {
46
+ if (error instanceof DataServiceUnreachableError) return true;
44
47
  if (!error || typeof error !== "object") return false;
45
48
  const { name, message } = error as { name?: unknown; message?: unknown };
46
49
  return name === "AbortError" || name === "TimeoutError" || (typeof message === "string" && NETWORK_FAILURE.test(message));
@@ -53,7 +53,7 @@ export async function openPaneShare(
53
53
  return;
54
54
  }
55
55
  const template = pluginRegistry.paneTemplates.get(share.templateId);
56
- if (!template?.publicShare) throw new Error("This shared pane is unavailable in this version of Gloomberb.");
56
+ if (!template?.publicShare) throw new Error("This shared pane is unavailable in this version of Gloom.");
57
57
  const options = template.publicShare.restore(share.data);
58
58
  if (!options) throw new Error("This shared pane contains invalid settings.");
59
59
  await pluginRegistry.createPaneFromTemplateAsync(template.id, options);
@@ -68,21 +68,66 @@ const TURKISH_CPI: SeriesNotOnFred = {
68
68
  url: "https://www.tcmb.gov.tr/wps/wcm/connect/EN/TCMB+EN/Main+Menu/Statistics/Inflation+Data/Consumer+Prices",
69
69
  };
70
70
 
71
+ /** IBGE's IPCA (433) and IPCA-15 (7478), as the central bank's SGS republishes them. */
72
+ const brazilianCpi = (code: number): SeriesNotOnFred => ({
73
+ publisher: "IBGE",
74
+ via: "the Banco Central do Brasil's SGS",
75
+ url: `https://www3.bcb.gov.br/sgspub/consultarvalores/telaCvsSelecionarSeries.paint?codigoSerie=${code}`,
76
+ });
77
+
71
78
  const NOT_ON_FRED: Readonly<Record<string, SeriesNotOnFred>> = {
72
79
  TURCPIYOY: TURKISH_CPI,
73
80
  TURCPIMOM: TURKISH_CPI,
81
+ BRAIPCAMOM: brazilianCpi(433),
82
+ BRAIPCA15MOM: brazilianCpi(7478),
83
+ // NAHB's builder sentiment index as first released, from the economic calendar's actuals.
84
+ NAHBHMI: {
85
+ publisher: "NAHB",
86
+ via: "the economic calendar",
87
+ url: "https://www.nahb.org/news-and-economics/housing-economics/indices/housing-market-index",
88
+ },
89
+ };
90
+
91
+ /** A series Gloom Cloud computes from two of FRED's, the first less the second, and how. */
92
+ interface ComputedFromFred {
93
+ legs: readonly [string, string];
94
+ note: string;
95
+ }
96
+
97
+ const COMPUTED_FROM_FRED: Readonly<Record<string, ComputedFromFred>> = {
98
+ MORTGAGE30US10Y: {
99
+ legs: ["MORTGAGE30US", "DGS10"],
100
+ note: "MORTGAGE30US minus DGS10 on each Freddie Mac PMMS date; when the Treasury market is closed that day, the 10-year yield of the session before.",
101
+ },
74
102
  };
75
103
 
104
+ /** How a series Gloom Cloud computes from FRED's is computed, for the note under its table; null for any other. */
105
+ export function computedFredSeriesNote(seriesId: string): string | null {
106
+ return COMPUTED_FROM_FRED[seriesId.trim().toUpperCase()]?.note ?? null;
107
+ }
108
+
76
109
  /** The publisher of a served series FRED does not carry; null for FRED's own. */
77
110
  export function seriesNotOnFred(seriesId: string): SeriesNotOnFred | null {
78
111
  return NOT_ON_FRED[seriesId.trim().toUpperCase()] ?? null;
79
112
  }
80
113
 
81
- /** The series' page on the FRED site, where its notes and release schedule live, or its publisher's page when FRED does not carry it. */
114
+ /**
115
+ * The series' page on the FRED site, where its notes and release schedule
116
+ * live; FRED's graph of both legs for a series computed from two; its
117
+ * publisher's page when FRED does not carry it.
118
+ */
82
119
  export function fredSeriesUrl(seriesId: string): string {
120
+ const legs = COMPUTED_FROM_FRED[seriesId.trim().toUpperCase()]?.legs;
121
+ if (legs) return `https://fred.stlouisfed.org/graph/?id=${legs.join(",")}`;
83
122
  return seriesNotOnFred(seriesId)?.url ?? `https://fred.stlouisfed.org/series/${seriesId}`;
84
123
  }
85
124
 
125
+ /** What a source line names a series by: `FRED DGS10`, or the FRED series a computed one comes from (`FRED MORTGAGE30US minus DGS10`). */
126
+ export function fredSourceLabel(seriesId: string): string {
127
+ const legs = COMPUTED_FROM_FRED[seriesId.trim().toUpperCase()]?.legs;
128
+ return `FRED ${legs ? legs.join(" minus ") : seriesId}`;
129
+ }
130
+
86
131
  function cacheKey(request: FredSeriesRequest): string {
87
132
  const range = [
88
133
  request.startDate ? `start=${request.startDate}` : "",
@@ -30,6 +30,7 @@ import { parseHistorySession } from "../../market-data/history-session";
30
30
  import { quoteMetadataFromQuote, quoteMetadataMatchesTarget } from "../../market-data/quotes/metadata";
31
31
  import type { InstrumentSearchResult } from "../../types/instrument";
32
32
  import type { TickerChanges } from "../../types/ticker-changes";
33
+ import type { IssuerListings } from "../../types/issuer-listings";
33
34
  import {
34
35
  apiClient,
35
36
  type CloudAnalystResearchPayload,
@@ -44,7 +45,7 @@ import { resolveCurrencyUnit } from "../../utils/currency-units";
44
45
  import { isRoundTheClockCoin } from "../../utils/crypto-pair";
45
46
  import { canonicalExchange, canonicalTickerKey, parsePublicTickerKey } from "../../utils/exchanges";
46
47
  import { normalizePriceHistory, priceHistoryIntervalMs, reachesLatestSettledSession } from "../../utils/price-history";
47
- import { createProviderMiss, ProviderBusyError, providerMissReason } from "../provider-errors";
48
+ import { createProviderMiss, ProviderBusyError, providerMissReason, StaleHistoryError } from "../provider-errors";
48
49
  import { parseListingDelisting } from "../../market-data/quotes/delisting";
49
50
  import { isRetryableApiError } from "../../api-client/errors";
50
51
  import { assertSecRegistrantMatches } from "../sec-registrant";
@@ -56,8 +57,9 @@ import { hongKongListingCode, tickerHasListingSuffix } from "../listing-symbols"
56
57
  import { parseSecAcceptanceTime } from "../sec-edgar/acceptance-time";
57
58
  import { hasMalformedIntradayHistory } from "../../time-series/history-quality";
58
59
  import {
59
- cloudNewsParams,
60
+ cloudNewsReadArticles,
60
61
  mapCloudNewsArticle,
62
+ readCloudNews,
61
63
  } from "./news";
62
64
  import {
63
65
  GLOOMBERB_CLOUD_PROVIDER_ID,
@@ -76,6 +78,7 @@ import {
76
78
  import {
77
79
  getPerpetualHistory,
78
80
  getPerpetualQuote,
81
+ streamedPerpetualQuote,
79
82
  namesPerpetualMarket,
80
83
  perpetualTarget,
81
84
  searchPerpetualMarkets,
@@ -122,6 +125,7 @@ function mapCloudSecFiling(item: {
122
125
  filingUrl: string;
123
126
  primaryDocumentUrl?: string;
124
127
  fileNumber?: string;
128
+ fundSeries?: boolean;
125
129
  }): SecFilingItem {
126
130
  return {
127
131
  accessionNumber: item.accessionNumber,
@@ -138,6 +142,7 @@ function mapCloudSecFiling(item: {
138
142
  primaryDocumentUrl: item.primaryDocumentUrl,
139
143
  // Absent from an older server: no file number is not the same as an empty one.
140
144
  ...(typeof item.fileNumber === "string" ? { fileNumber: item.fileNumber } : {}),
145
+ ...(typeof item.fundSeries === "boolean" ? { fundSeries: item.fundSeries } : {}),
141
146
  };
142
147
  }
143
148
 
@@ -202,7 +207,7 @@ function mapCloudPriceHistory(
202
207
  // or a stale answer without bars, are a miss.
203
208
  const stale = isStaleCloudResponse(response);
204
209
  if (stale && response.status !== "success" && response.status !== "partial") {
205
- throw createProviderMiss(`Cloud chart data is stale for ${ticker}`);
210
+ throw new StaleHistoryError(`Cloud chart data is stale for ${ticker}`);
206
211
  }
207
212
  if (response.status === "unsupported" && response.reasonCode === "HISTORY_RETENTION" && requestedEnd) {
208
213
  const retention = parseHistoryRetention(response.historyRetention);
@@ -227,7 +232,7 @@ function mapCloudPriceHistory(
227
232
  ).map((point) => mapPricePoint(point, divisor, exchange, coin)),
228
233
  );
229
234
  if (stale && !reachesLatestSettledSession(points, Date.now(), { symbol: ticker, exchange, intervalMs: priceHistoryIntervalMs(interval) })) {
230
- throw createProviderMiss(`Cloud chart data is stale for ${ticker}`);
235
+ throw new StaleHistoryError(`Cloud chart data is stale for ${ticker}`);
231
236
  }
232
237
  const intraday = /^\d+(min|h)$/i.test(interval);
233
238
  // Daily bars answering an intraday range: the listing has no intraday bars.
@@ -718,6 +723,12 @@ export class GloomberbCloudProvider implements AssetDataProvider {
718
723
  return cloudTickerChangesBatch(symbols, options);
719
724
  }
720
725
 
726
+ async getIssuerListings(symbol: string, exchange = "", options: { signal?: AbortSignal } = {}): Promise<IssuerListings | null> {
727
+ const response = await apiClient.getCloudIssuerListings(symbol, exchange, options);
728
+ // "empty" is an answer: the service holds no company for the listing.
729
+ return response.status === "success" || response.status === "partial" ? response.data : null;
730
+ }
731
+
721
732
  async searchBatch(queries: string[], options: { limit?: number; signal?: AbortSignal } = {}): Promise<Map<string, InstrumentSearchResult[]> | null> {
722
733
  const answers = await cloudSearchBatch(queries, options);
723
734
  if (!answers) return null;
@@ -878,14 +889,23 @@ export class GloomberbCloudProvider implements AssetDataProvider {
878
889
  targets: QuoteSubscriptionTarget[],
879
890
  onQuote: (target: QuoteSubscriptionTarget, quote: Quote) => void,
880
891
  ): () => void {
881
- // Perpetual markets are polled, a minute apart at the venue; the quote stream carries none.
882
- const { valid } = cloudBatchTargets(splitPerpetualTargets(targets).others);
892
+ // A perpetual market streams as its listing on its venue (BTC:HYPERLIQUID): Gloom Cloud follows the venue's own
893
+ // socket for it, once the server says it can (the socket holds it back until then).
894
+ const { perpetuals, others } = splitPerpetualTargets(targets);
895
+ const valid: Array<{ target: QuoteSubscriptionTarget; request: { symbol: string; exchange?: string } }> = [
896
+ ...cloudBatchTargets(others).valid,
897
+ ...perpetuals.flatMap((target) => {
898
+ const listing = perpetualTarget(target.symbol, target.exchange);
899
+ return listing ? [{ target, request: { symbol: listing.symbol, exchange: listing.exchange } }] : [];
900
+ }),
901
+ ];
883
902
  if (!valid.length) return () => {};
884
903
  // No-op without a session credential; covers browser cookie sessions too.
885
904
  void apiClient.ensureVerifiedSession().catch(logFailure("sources.gloomberb-cloud.index", "Verifying the quote streaming session failed"));
886
905
  const targetMap = new Map<string, QuoteSubscriptionTarget[]>();
887
- for (const { target } of valid) {
888
- const key = quoteTargetKey(target.symbol, target.exchange);
906
+ for (const { target, request } of valid) {
907
+ // A perpetual comes back as its listing, whatever form it was asked for in.
908
+ const key = perpetuals.includes(target) ? quoteTargetKey(request.symbol, request.exchange) : quoteTargetKey(target.symbol, target.exchange);
889
909
  const matches = targetMap.get(key) ?? [];
890
910
  matches.push(target);
891
911
  targetMap.set(key, matches);
@@ -909,7 +929,10 @@ export class GloomberbCloudProvider implements AssetDataProvider {
909
929
  }
910
930
  const matchedKey = cloudResponseTargetKey(key, requested);
911
931
  const matches = matchedKey ? targetMap.get(matchedKey) ?? [] : [];
912
- const mappedQuote = mapQuote(quote);
932
+ if (!matches.length) return;
933
+ const listing = perpetualTarget(target.symbol, target.exchange);
934
+ const mappedQuote = listing ? streamedPerpetualQuote(quote, listing) : mapQuote(quote);
935
+ if (!mappedQuote) return;
913
936
  for (const match of matches) {
914
937
  onQuote(match, retainRequestedQuoteSymbol(mappedQuote, match.symbol));
915
938
  }
@@ -934,21 +957,21 @@ export function createGloomberbCloudCapabilities(provider = createGloomberbCloud
934
957
  return normalizeNewsFeed(query) === "ticker" ? !!query.ticker && !predictionMarketListing(query.ticker, query.exchange) : true;
935
958
  },
936
959
  async fetchNewsPage(query: NewsQuery) {
937
- const response = await withCloudFallback(
938
- () => apiClient.getCloudNews(cloudNewsParams(query)),
960
+ const read = await withCloudFallback(
961
+ () => readCloudNews(apiClient, query),
939
962
  "Cloud news is unavailable",
940
963
  );
941
964
  return {
942
- articles: response.items.map((item) => mapCloudNewsArticle(item, query.ticker)),
943
- nextCursor: response.nextCursor ?? null,
965
+ articles: cloudNewsReadArticles(read, query.ticker),
966
+ nextCursor: read.nextCursor ?? null,
944
967
  };
945
968
  },
946
969
  async fetchNews(query: NewsQuery): Promise<NewsArticle[]> {
947
- const response = await withCloudFallback(
948
- () => apiClient.getCloudNews(cloudNewsParams(query)),
970
+ const read = await withCloudFallback(
971
+ () => readCloudNews(apiClient, query),
949
972
  "Cloud news is unavailable",
950
973
  );
951
- return response.items.map((item) => mapCloudNewsArticle(item, query.ticker));
974
+ return cloudNewsReadArticles(read, query.ticker);
952
975
  },
953
976
  async fetchNewsStory(storyId: string): Promise<NewsArticle | null> {
954
977
  const story = await withCloudFallback(
@@ -3,11 +3,15 @@ import { readableNewsSource } from "../../news/source-label";
3
3
  import { collectNewsDisplayTickers } from "../../news/ticker-symbols";
4
4
  import type { NewsArticle, NewsQuery, NewsStoryItem } from "../../types/news-source";
5
5
  import type {
6
+ apiClient,
7
+ CloudNewsListResponse,
6
8
  CloudNewsPayload,
7
9
  CloudNewsStoryItemPayload,
8
10
  } from "../../api-client";
9
11
  import type { CloudNewsParams } from "../../api-client/paths";
10
12
  import { parsePublicTickerKey, publicExchange } from "../../utils/exchanges";
13
+ import { coinSearchName } from "../../utils/crypto-pair";
14
+ import { logFailure } from "../../utils/log-failure";
11
15
  import { getListingSymbol, tickerHasListingSuffix } from "../listing-symbols";
12
16
 
13
17
  function normalizeStringArray(value: unknown): string[] {
@@ -129,3 +133,38 @@ export function cloudNewsParams(query: NewsQuery): CloudNewsParams {
129
133
  cursor: query.cursor,
130
134
  };
131
135
  }
136
+
137
+ /** A page of Gloom Cloud stories, with the text searched for when a coin pair's feed had none filed under it. */
138
+ export type CloudNewsRead = CloudNewsListResponse & { searchedFor?: string };
139
+
140
+ type CloudNewsClient = Pick<typeof apiClient, "getCloudNews" | "searchCloudNews">;
141
+
142
+ /**
143
+ * A news query's first page from Gloom Cloud. Stories are filed under company
144
+ * tickers, and a coin pair (BTC-USD) rarely has any filed under it, so its
145
+ * empty feed falls back to the stories that mention the coin ("bitcoin"),
146
+ * marked with what was searched. A later page, a failed search or a coin with
147
+ * no name to search keeps the empty answer.
148
+ */
149
+ export async function readCloudNews(client: CloudNewsClient, query: NewsQuery): Promise<CloudNewsRead> {
150
+ const response = await client.getCloudNews(cloudNewsParams(query));
151
+ if (response.items.length > 0 || query.cursor || normalizeNewsFeed(query) !== "ticker") return response;
152
+ const text = coinSearchName(query.ticker, query.exchange, query.listingName);
153
+ if (!text) return response;
154
+ const found = await client.searchCloudNews(text, query.limit)
155
+ .catch(logFailure("sources.gloomberb-cloud.news", "Search a coin's stories failed", null));
156
+ return found && found.items.length > 0 ? { items: found.items, nextCursor: null, searchedFor: text } : response;
157
+ }
158
+
159
+ /** A read's stories as articles, each marked with the text a coin's fallback searched for. */
160
+ export function cloudNewsReadArticles(read: CloudNewsRead, ticker?: string): NewsArticle[] {
161
+ return read.items.map((item) => {
162
+ const article = mapCloudNewsArticle(item, read.searchedFor ? undefined : ticker);
163
+ return read.searchedFor ? { ...article, searchedFor: read.searchedFor } : article;
164
+ });
165
+ }
166
+
167
+ /** What a pane or report says above the stories a coin's fallback found: "No stories are filed under BTC-USD; these mention bitcoin." */
168
+ export function coinNewsFallbackNotice(ticker: string, searchedFor: string): string {
169
+ return `No stories are filed under ${ticker}; these mention ${searchedFor}.`;
170
+ }
@@ -28,6 +28,7 @@ import { reconcileQuoteDayRange } from "../../market-data/quotes/day-range";
28
28
  import { redactUnavailableFundamentals } from "../../utils/fundamentals";
29
29
  import { readWithdrawnObservations } from "../../utils/statement-gaps";
30
30
  import { parseListingDelisting } from "../../market-data/quotes/delisting";
31
+ import { readIntradayBar, readStaleReason } from "../../market-data/quotes/intraday-bar";
31
32
 
32
33
  export const GLOOMBERB_CLOUD_PROVIDER_ID = "gloomberb-cloud" as const;
33
34
 
@@ -96,6 +97,8 @@ export function mapQuote(
96
97
  return withoutUndefinedFields(reconcileQuoteDayRange({
97
98
  ...quote,
98
99
  delisting: parseListingDelisting(quote.delisting),
100
+ intradayBar: readIntradayBar(quote.intradayBar),
101
+ staleReason: readStaleReason(quote.staleReason),
99
102
  priceBasis,
100
103
  priceObservation,
101
104
  currency: currency || quote.currency,
@@ -222,6 +225,15 @@ function parseCloudPricePointDate(
222
225
  : new Date(value);
223
226
  }
224
227
 
228
+ /** A served venue count, when it is one: a venue name and a count of zero or more. */
229
+ function venueVolume(value: unknown): { venueVolume: { venue: string; volume: number } } | null {
230
+ if (!value || typeof value !== "object") return null;
231
+ const { venue, volume } = value as { venue?: unknown; volume?: unknown };
232
+ return typeof venue === "string" && venue.trim() && typeof volume === "number" && Number.isFinite(volume) && volume >= 0
233
+ ? { venueVolume: { venue: venue.trim(), volume } }
234
+ : null;
235
+ }
236
+
225
237
  /**
226
238
  * One served bar. `coin`: the bars are a coin's, which trades every hour of every day. Its intraday volume is the
227
239
  * value traded in the bar on major spot venues, and a bar no venue reported has none rather than 0, so a 0 (from an
@@ -241,6 +253,7 @@ export function mapPricePoint(
241
253
  low: normalizePriceValueByDivisor(point.low, divisor),
242
254
  close: normalizePriceValueByDivisor(point.close, divisor) ?? point.close,
243
255
  volume: coin && point.volume === 0 ? undefined : point.volume,
256
+ ...(venueVolume(point.venueVolume) ?? {}),
244
257
  ...(point.partial === true ? { partial: true } : {}),
245
258
  ...(point.filled === true ? { filled: true } : {}),
246
259
  ...(point.unsettled === true ? { unsettled: true } : {}),
@@ -437,7 +450,7 @@ const HISTORY_OUTPUT_SIZE: Record<TimeRange, number> = {
437
450
  "ALL": 600,
438
451
  };
439
452
 
440
- /** The bar size comes from the shared range table, which `gloomberb help history` also lists. */
453
+ /** The bar size comes from the shared range table, which `gloom help history` also lists. */
441
454
  export function toHistoryRequest(range: TimeRange): {
442
455
  interval: string;
443
456
  outputsize: number;
@@ -115,7 +115,55 @@ export function perpetualQuote(row: PerpBoardRow, listing: PerpetualListing): Qu
115
115
  dataSource: "delayed",
116
116
  ...(row.markPrice != null ? { mark: row.markPrice } : {}),
117
117
  ...(row.lastPrice != null ? { lastTradePrice: row.lastPrice } : {}),
118
- ...(row.stale || row.delisted ? { stale: true } : {}),
118
+ // Said either way: a fresh reading merged over a stale one must clear it, not inherit it.
119
+ stale: row.stale === true || row.delisted === true,
120
+ perpetual: row,
121
+ };
122
+ }
123
+
124
+ /** The figures a streamed row is read by: each a finite number, or none. */
125
+ const STREAMED_FIGURES = ["markPrice", "lastPrice", "fundingRate8h", "openInterestUsd", "premium"] as const;
126
+
127
+ /**
128
+ * A row the market socket carried for this listing's market, readable as a fetched one; null for anything else. A
129
+ * figure the frame leaves out (a server writes no key for a value it does not have) is none, as null says.
130
+ */
131
+ function streamedRow(value: unknown, listing: PerpetualListing): PerpBoardRow | null {
132
+ if (!value || typeof value !== "object") return null;
133
+ const row = value as PerpBoardRow;
134
+ if (typeof row.marketId !== "string" || row.marketId.toLowerCase() !== listing.marketId.toLowerCase()
135
+ || typeof row.quoteCurrency !== "string" || typeof row.observedAt !== "string" || !Number.isFinite(Date.parse(row.observedAt))) return null;
136
+ const figures: Partial<Record<(typeof STREAMED_FIGURES)[number], number | null>> = {};
137
+ for (const field of STREAMED_FIGURES) {
138
+ const figure: unknown = row[field];
139
+ if (figure != null && !(typeof figure === "number" && Number.isFinite(figure))) return null;
140
+ figures[field] = figure ?? null;
141
+ }
142
+ return { ...row, ...figures };
143
+ }
144
+
145
+ /**
146
+ * A perpetual's quote from the market socket: the same quote its fetched row
147
+ * makes, from the row the socket carried, marked live while the venue's own
148
+ * socket feeds it. Null when the frame holds no row for this market.
149
+ */
150
+ export function streamedPerpetualQuote(
151
+ frame: { perpetual?: unknown; dataSource?: unknown; delivery?: unknown; stale?: unknown; bid?: unknown; ask?: unknown },
152
+ listing: PerpetualListing,
153
+ ): Quote | null {
154
+ const row = streamedRow(frame.perpetual, listing);
155
+ const quote = row ? perpetualQuote(row, listing) : null;
156
+ if (!quote) return null;
157
+ const number = (value: unknown) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
158
+ const bid = number(frame.bid);
159
+ const ask = number(frame.ask);
160
+ return {
161
+ ...quote,
162
+ ...(frame.dataSource === "live" ? { dataSource: "live" as const } : {}),
163
+ ...(frame.delivery === "stream" || frame.delivery === "poll" ? { delivery: frame.delivery } : {}),
164
+ stale: quote.stale === true || frame.stale === true,
165
+ ...(bid !== undefined ? { bid } : {}),
166
+ ...(ask !== undefined ? { ask } : {}),
119
167
  };
120
168
  }
121
169
 
@@ -139,6 +139,43 @@ export function listingSuffixConflictsWithExchange(ticker: string, exchange: str
139
139
  return suffixes.length > 0 && !suffixes.includes(ticker.slice(ticker.indexOf(".")));
140
140
  }
141
141
 
142
+ /**
143
+ * The venue a vendor's suffix names, whatever else it could be: GARAN.IS is
144
+ * GARAN on BIST, 7203.T 7203 on JPX, and MKC.V reads as MKC on TSXV, though it
145
+ * is McCormick's voting class on NYSE. For a caller that confirms it, by a row
146
+ * saved on that venue or the listing's own quote (`listingSuffixVenue`). Null
147
+ * for a symbol without a venue suffix (BRK.B) and a suffix several venues share.
148
+ */
149
+ export function listingSuffixCandidate(ticker: string): { symbol: string; exchange: string } | null {
150
+ if (!tickerHasListingSuffix(ticker)) return null;
151
+ const dot = ticker.indexOf(".");
152
+ const suffix = ticker.slice(dot);
153
+ // The one host venue the suffix names, else the one venue the table names for it (BIST, which the host table lacks).
154
+ const venues = new Set(HOST_SUFFIX_ENTRIES.filter(([, entry]) => entry === suffix).map(([venue]) => venue));
155
+ const venue = listingSuffixExchange(ticker) ?? (venues.size === 1 ? [...venues][0] : undefined);
156
+ return venue ? { symbol: ticker.slice(0, dot), exchange: venue } : null;
157
+ }
158
+
159
+ /**
160
+ * The listing a vendor's suffixed symbol stands for, when that is settled:
161
+ * GARAN.IS is GARAN on BIST, VOD.L on LSE is VOD there. A venue the table
162
+ * knows settles it, either way: its own suffix maps, another's (MKC.V on NYSE,
163
+ * McCormick's voting class) does not. With no venue, or one the table does not
164
+ * know (IST, JNB), the suffix's own venue is read for a suffix of two letters
165
+ * or more; a one-letter suffix is also a US class letter (MKC.V, BRK.B), so it
166
+ * maps only when a venue agrees. Null when it does not map.
167
+ */
168
+ export function listingSuffixVenue(ticker: string, exchange?: string): { symbol: string; exchange: string } | null {
169
+ const candidate = listingSuffixCandidate(ticker);
170
+ if (!candidate) return null;
171
+ const suffix = ticker.slice(ticker.indexOf("."));
172
+ const given = canonicalExchange(exchange);
173
+ // SMART routes for a broker; it names no venue.
174
+ const suffixes = given && given !== "SMART" ? HOST_SUFFIX_ENTRIES.filter(([venue]) => venue === given).map(([, entry]) => entry) : [];
175
+ if (suffixes.length > 0) return suffixes.includes(suffix) ? { symbol: candidate.symbol, exchange: given } : null;
176
+ return suffix.length > 2 ? candidate : null;
177
+ }
178
+
142
179
  /** Infer a venue only when the suffix names one recognized host exchange. */
143
180
  export function listingSuffixExchange(ticker: string): string | undefined {
144
181
  if (!tickerHasListingSuffix(ticker)) return undefined;