gloomberb 0.16.3 → 0.16.5

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 (820) hide show
  1. package/README.md +14 -91
  2. package/package.json +7 -1
  3. package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
  4. package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
  5. package/src/account/billing.ts +57 -0
  6. package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
  7. package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
  8. package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
  9. package/src/account/session.ts +16 -0
  10. package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +42 -17
  11. package/src/account/upgrade-personalization.ts +57 -0
  12. package/src/account/upgrade-tickers.ts +124 -0
  13. package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
  14. package/src/api-client/askg.ts +43 -0
  15. package/src/api-client/auth.ts +15 -0
  16. package/src/api-client/beneficial-owners.ts +4 -0
  17. package/src/api-client/chat.ts +19 -0
  18. package/src/api-client/company-kpis.ts +14 -2
  19. package/src/api-client/data.ts +58 -18
  20. package/src/api-client/earnings.ts +6 -0
  21. package/src/api-client/futures-curve.ts +56 -0
  22. package/src/api-client/index.ts +16 -1
  23. package/src/api-client/market-discovery.ts +10 -1
  24. package/src/api-client/normalizers.ts +27 -0
  25. package/src/api-client/paths.ts +95 -23
  26. package/src/api-client/request.ts +2 -1
  27. package/src/api-client/research-activity.ts +46 -10
  28. package/src/api-client/socket.ts +39 -8
  29. package/src/api-client/types.ts +74 -2
  30. package/src/api-client/upgrade-experiment.ts +90 -0
  31. package/src/api-client/yield-curves.ts +8 -0
  32. package/src/app/global-shortcuts.ts +26 -2
  33. package/src/app/keybindings/actions.ts +10 -0
  34. package/src/app/pane-runtime/index.tsx +8 -0
  35. package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
  36. package/src/app/pane-runtime/plugin-bindings.ts +65 -25
  37. package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
  38. package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
  39. package/src/app/runtime/desktop-deeplink.ts +5 -0
  40. package/src/app/star-prompt/model.ts +98 -0
  41. package/src/app/star-prompt/runtime.ts +41 -0
  42. package/src/app/star-prompt/status-line.tsx +190 -0
  43. package/src/app.tsx +13 -7
  44. package/src/architecture/core-builtin-allowlist.json +61 -0
  45. package/src/brokers/signed-in/adapter.ts +33 -2
  46. package/src/brokers/signed-in/client.ts +10 -0
  47. package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
  48. package/src/brokers/signed-in/sign-in.ts +62 -5
  49. package/src/capabilities/chart-series.ts +11 -1
  50. package/src/capabilities/registry.ts +8 -1
  51. package/src/capabilities/types.ts +2 -0
  52. package/src/cli/commands/crypto-hints.ts +19 -4
  53. package/src/cli/commands/fred-series.ts +61 -0
  54. package/src/cli/commands/market.ts +744 -181
  55. package/src/cli/commands/news-hints.ts +62 -0
  56. package/src/cli/commands/news-search.ts +53 -0
  57. package/src/cli/commands/options-chain.ts +172 -0
  58. package/src/cli/commands/options-leaps.ts +425 -0
  59. package/src/cli/commands/overview.ts +251 -40
  60. package/src/cli/commands/remote.ts +2 -1
  61. package/src/cli/commands/search.ts +109 -15
  62. package/src/cli/commands/system.ts +151 -24
  63. package/src/cli/commands/themes.ts +64 -0
  64. package/src/cli/commands/ticker.ts +149 -40
  65. package/src/cli/context.ts +45 -14
  66. package/src/cli/desktop-pane-shot.ts +150 -17
  67. package/src/cli/earnings-calendar.ts +71 -0
  68. package/src/cli/errors.ts +25 -2
  69. package/src/cli/freshness.ts +22 -8
  70. package/src/cli/fx-pair.ts +57 -0
  71. package/src/cli/glossary.ts +429 -0
  72. package/src/cli/help.ts +14 -1
  73. package/src/cli/history-rows.ts +48 -7
  74. package/src/cli/index-roots.ts +58 -0
  75. package/src/cli/index.ts +29 -12
  76. package/src/cli/known-gaps.ts +27 -0
  77. package/src/cli/listing-arg.ts +595 -26
  78. package/src/cli/not-a-ticker.ts +44 -0
  79. package/src/cli/options.ts +50 -6
  80. package/src/cli/pane-functions/access-gate.ts +5 -0
  81. package/src/cli/pane-functions/capabilities.ts +11 -4
  82. package/src/cli/pane-functions/catalog.ts +48 -7
  83. package/src/cli/pane-functions/data.ts +48 -13
  84. package/src/cli/pane-functions/discovery.ts +1 -0
  85. package/src/cli/pane-functions/dom.ts +41 -19
  86. package/src/cli/pane-functions/freshness.ts +531 -32
  87. package/src/cli/pane-functions/function-help.ts +77 -25
  88. package/src/cli/pane-functions/headless.ts +50 -21
  89. package/src/cli/pane-functions/index.ts +66 -10
  90. package/src/cli/pane-functions/market-session.ts +147 -0
  91. package/src/cli/pane-functions/options.ts +77 -25
  92. package/src/cli/pane-functions/report-notices.ts +81 -0
  93. package/src/cli/pane-functions/report.ts +19 -8
  94. package/src/cli/pane-functions/resolver.ts +53 -18
  95. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  96. package/src/cli/pane-functions/screenshot.ts +199 -30
  97. package/src/cli/registry.ts +2 -1
  98. package/src/cli/report-tables.ts +3 -0
  99. package/src/cli/result.ts +53 -13
  100. package/src/cli/row-window.ts +76 -0
  101. package/src/cli/scroll-truncation.ts +34 -0
  102. package/src/cli/staged-tickers.ts +52 -0
  103. package/src/cli/symbol-args.ts +9 -0
  104. package/src/cli/symbol-list.ts +172 -0
  105. package/src/cli/ticker-resolution.ts +223 -30
  106. package/src/cli/types.ts +5 -0
  107. package/src/components/chart/composite/axis-overlays.tsx +6 -2
  108. package/src/components/chart/composite/composite-chart.tsx +83 -10
  109. package/src/components/chart/composite/legend.tsx +88 -8
  110. package/src/components/chart/composite/panel-surface.tsx +44 -17
  111. package/src/components/chart/composite/price-axis-labels.tsx +3 -1
  112. package/src/components/chart/composite/rasterizer.ts +64 -4
  113. package/src/components/chart/composite/series-cues.ts +71 -0
  114. package/src/components/chart/composite/text-renderer.ts +16 -8
  115. package/src/components/chart/composite/types.ts +3 -0
  116. package/src/components/command-bar/commands/direct/index.ts +9 -1
  117. package/src/components/command-bar/commands/plugin/items.ts +3 -1
  118. package/src/components/command-bar/commands/registry.ts +7 -0
  119. package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
  120. package/src/components/command-bar/pane-templates/workflow.ts +5 -0
  121. package/src/components/command-bar/panel/index.tsx +11 -3
  122. package/src/components/command-bar/panel/runtime.ts +3 -0
  123. package/src/components/command-bar/panel/types.ts +2 -0
  124. package/src/components/command-bar/routes/root/command-items.ts +2 -0
  125. package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
  126. package/src/components/command-bar/routes/root/provider-search.ts +4 -3
  127. package/src/components/command-bar/routes/root/results.ts +40 -10
  128. package/src/components/command-bar/routes/root/runtime.ts +8 -0
  129. package/src/components/command-bar/routes/root/search-providers.ts +97 -14
  130. package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
  131. package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
  132. package/src/components/command-bar/surface/index.tsx +18 -4
  133. package/src/components/command-bar/theme-picker.tsx +48 -13
  134. package/src/components/command-bar/workflow/ops.ts +5 -3
  135. package/src/components/command-bar/workflow/tickers.ts +23 -4
  136. package/src/components/data-table/view.tsx +28 -9
  137. package/src/components/layout/detached-pane-shell.tsx +9 -0
  138. package/src/components/layout/floating-pane.tsx +9 -2
  139. package/src/components/layout/header.tsx +20 -5
  140. package/src/components/layout/market-summary.ts +23 -9
  141. package/src/components/layout/pane/content.tsx +40 -29
  142. package/src/components/layout/pane/cycle-order.ts +2 -11
  143. package/src/components/layout/pane/footer/index.tsx +6 -2
  144. package/src/components/layout/pane/footer/model.ts +35 -1
  145. package/src/components/layout/pane/header.tsx +26 -2
  146. package/src/components/layout/pane/index.tsx +12 -2
  147. package/src/components/layout/pane/sidebar.tsx +78 -10
  148. package/src/components/layout/pane/title.ts +1 -1
  149. package/src/components/layout/presentation.ts +22 -0
  150. package/src/components/layout/shell/active-drag.ts +21 -5
  151. package/src/components/layout/shell/drag/index.ts +43 -9
  152. package/src/components/layout/shell/drag/live.ts +87 -6
  153. package/src/components/layout/shell/drag/runtime.ts +62 -20
  154. package/src/components/layout/shell/index.tsx +71 -12
  155. package/src/components/layout/shell/layout-state.ts +5 -11
  156. package/src/components/layout/shell/menu.ts +33 -1
  157. package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
  158. package/src/components/layout/shell/pane/actions.ts +2 -1
  159. package/src/components/layout/shell/pane/layers.tsx +216 -28
  160. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  161. package/src/components/layout/shell/pane/new-layout.ts +116 -0
  162. package/src/components/layout/shell/shortcuts.ts +5 -2
  163. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
  164. package/src/components/layout/shell/visible-layout.ts +44 -1
  165. package/src/components/layout/status-bar.tsx +4 -1
  166. package/src/components/markdown-text.tsx +69 -23
  167. package/src/components/metric-treemap/heat-surface.tsx +37 -9
  168. package/src/components/metric-treemap/heat-tiles.ts +48 -17
  169. package/src/components/onboarding/account-step/form-panel.tsx +1 -1
  170. package/src/components/onboarding/account-step/index.tsx +1 -1
  171. package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
  172. package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
  173. package/src/components/onboarding/onboarding-frame.tsx +33 -10
  174. package/src/components/onboarding/onboarding-keyboard.ts +1 -1
  175. package/src/components/onboarding/onboarding-wizard.tsx +50 -41
  176. package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
  177. package/src/components/onboarding/pro-step-layout.ts +86 -0
  178. package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
  179. package/src/components/onboarding/wizard-account.ts +2 -2
  180. package/src/components/pane-template-wizard.tsx +9 -1
  181. package/src/components/price-selector-dialog.tsx +11 -2
  182. package/src/components/sign-in-gate.tsx +3 -3
  183. package/src/components/ticker/list-table-view.tsx +24 -1
  184. package/src/components/ui/action-row.tsx +2 -1
  185. package/src/components/ui/button.tsx +17 -1
  186. package/src/components/ui/choice-dialog.tsx +6 -4
  187. package/src/components/ui/confirm-dialog.tsx +28 -18
  188. package/src/components/ui/data-table/index.tsx +49 -0
  189. package/src/components/ui/data-table/opentui/index.tsx +37 -6
  190. package/src/components/ui/data-table/types.ts +20 -1
  191. package/src/components/ui/data-table/visible-range.ts +2 -0
  192. package/src/components/ui/dialog-actions.tsx +64 -0
  193. package/src/components/ui/display.tsx +17 -3
  194. package/src/components/ui/frame.tsx +35 -2
  195. package/src/components/ui/icon.tsx +13 -2
  196. package/src/components/ui/index.ts +1 -1
  197. package/src/components/ui/text-prompt-dialog.tsx +11 -9
  198. package/src/core/connection-health.ts +1 -1
  199. package/src/core/state/app/layout-reducer.ts +89 -3
  200. package/src/core/state/app/state.ts +8 -5
  201. package/src/core/state/app/types.ts +13 -2
  202. package/src/data/cached-query.ts +2 -0
  203. package/src/data/config/layout.ts +55 -21
  204. package/src/data/config/store/fold-panes.ts +149 -0
  205. package/src/data/config/store/migrations.ts +7 -0
  206. package/src/data/config/store/node.ts +27 -6
  207. package/src/data/config/store/normalize.ts +44 -5
  208. package/src/data/ticker-repository.ts +5 -0
  209. package/src/data/ticker-store.ts +15 -0
  210. package/src/docs/content.ts +215 -0
  211. package/src/docs/load.ts +139 -0
  212. package/src/docs/requests.ts +39 -0
  213. package/src/docs/snapshot.chunk.ts +8 -0
  214. package/src/docs/snapshot.json +7416 -0
  215. package/src/docs/topics.ts +216 -0
  216. package/src/i18n/es.ts +75 -5
  217. package/src/i18n/ja.ts +75 -5
  218. package/src/i18n/ko.ts +75 -5
  219. package/src/i18n/zh-cn.ts +75 -5
  220. package/src/i18n/zh-tw.ts +75 -5
  221. package/src/layout/desks.ts +2 -3
  222. package/src/layout/pane-layout-move.ts +264 -0
  223. package/src/layout/pane-manager/dock-tree.ts +18 -0
  224. package/src/layout/pane-manager/hidden-panes.ts +160 -0
  225. package/src/layout/pane-manager/index.ts +2 -0
  226. package/src/market-data/coordinator/chart.ts +10 -4
  227. package/src/market-data/coordinator/entries.ts +7 -1
  228. package/src/market-data/coordinator/index.ts +6 -3
  229. package/src/market-data/coordinator/quotes.ts +2 -2
  230. package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
  231. package/src/market-data/futures-contract.ts +151 -0
  232. package/src/market-data/hooks.tsx +10 -2
  233. package/src/market-data/market/format.ts +39 -21
  234. package/src/market-data/market/freshness.ts +193 -30
  235. package/src/market-data/market/status.ts +59 -23
  236. package/src/market-data/options-alternatives.ts +69 -0
  237. package/src/market-data/published-apac-sessions.ts +23 -1
  238. package/src/market-data/quotes/contributions.ts +22 -2
  239. package/src/market-data/quotes/metadata.ts +8 -9
  240. package/src/market-data/quotes/resolution.ts +2 -0
  241. package/src/market-data/quotes/screener-live-quotes.ts +61 -9
  242. package/src/market-data/result-types.ts +2 -0
  243. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  244. package/src/plugins/builtin/account-management/model.ts +2 -56
  245. package/src/plugins/builtin/account-management/navigation.ts +1 -1
  246. package/src/plugins/builtin/account-management/pane.tsx +37 -8
  247. package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
  248. package/src/plugins/builtin/alerts/cli.ts +313 -47
  249. package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
  250. package/src/plugins/builtin/alerts/events.ts +23 -2
  251. package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
  252. package/src/plugins/builtin/alerts/history.ts +2 -0
  253. package/src/plugins/builtin/alerts/index.tsx +41 -9
  254. package/src/plugins/builtin/alerts/pane.tsx +8 -0
  255. package/src/plugins/builtin/alerts/quotes.ts +3 -0
  256. package/src/plugins/builtin/alerts/research-builder.ts +8 -3
  257. package/src/plugins/builtin/alerts/research-rules.ts +18 -2
  258. package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
  259. package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
  260. package/src/plugins/builtin/alerts/scheduled.ts +254 -0
  261. package/src/plugins/builtin/alerts/targets.ts +92 -0
  262. package/src/plugins/builtin/analytics/index.tsx +4 -2
  263. package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
  264. package/src/plugins/builtin/analytics/risk-math.ts +91 -27
  265. package/src/plugins/builtin/analytics/risk-model.ts +71 -12
  266. package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
  267. package/src/plugins/builtin/attention/index.tsx +2 -0
  268. package/src/plugins/builtin/attention/pane.tsx +3 -1
  269. package/src/plugins/builtin/attention/series.ts +26 -0
  270. package/src/plugins/builtin/awards/index.tsx +2 -0
  271. package/src/plugins/builtin/awards/pane.tsx +3 -1
  272. package/src/plugins/builtin/awards/series.ts +29 -0
  273. package/src/plugins/builtin/backtest/pane.tsx +1 -1
  274. package/src/plugins/builtin/bond-calculator/model.ts +2 -1
  275. package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
  276. package/src/plugins/builtin/broker-manager/index.tsx +7 -3
  277. package/src/plugins/builtin/broker-manager/model.ts +8 -0
  278. package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
  279. package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
  280. package/src/plugins/builtin/broker-manager/table.ts +5 -0
  281. package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
  282. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  283. package/src/plugins/builtin/cds/client.ts +70 -13
  284. package/src/plugins/builtin/cds/headless.ts +116 -19
  285. package/src/plugins/builtin/cds/index.tsx +3 -1
  286. package/src/plugins/builtin/cds/model.ts +193 -31
  287. package/src/plugins/builtin/cds/pane.tsx +56 -14
  288. package/src/plugins/builtin/cds/series.ts +19 -0
  289. package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
  290. package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
  291. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
  292. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
  293. package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
  294. package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
  295. package/src/plugins/builtin/chart-composer/headless.ts +8 -3
  296. package/src/plugins/builtin/chart-composer/index.tsx +9 -2
  297. package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
  298. package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
  299. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
  300. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
  301. package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
  302. package/src/plugins/builtin/chat/channels.ts +34 -36
  303. package/src/plugins/builtin/chat/command-bar.ts +138 -0
  304. package/src/plugins/builtin/chat/composer-commands.ts +21 -1
  305. package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
  306. package/src/plugins/builtin/chat/content/footer.tsx +5 -3
  307. package/src/plugins/builtin/chat/content/index.tsx +21 -1
  308. package/src/plugins/builtin/chat/content/mentions.ts +2 -1
  309. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
  310. package/src/plugins/builtin/chat/content/user-map.ts +3 -1
  311. package/src/plugins/builtin/chat/controller/index.ts +50 -0
  312. package/src/plugins/builtin/chat/conversations.ts +256 -0
  313. package/src/plugins/builtin/chat/discord-command.ts +91 -0
  314. package/src/plugins/builtin/chat/edit-window.ts +12 -6
  315. package/src/plugins/builtin/chat/ghost-user.ts +14 -0
  316. package/src/plugins/builtin/chat/index.tsx +40 -2
  317. package/src/plugins/builtin/chat/layout.ts +2 -0
  318. package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
  319. package/src/plugins/builtin/chat/message/header.tsx +24 -15
  320. package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
  321. package/src/plugins/builtin/chat/message/render-state.ts +3 -0
  322. package/src/plugins/builtin/chat/pane-requests.ts +60 -0
  323. package/src/plugins/builtin/chat/pane-state.ts +32 -2
  324. package/src/plugins/builtin/chat/pane.tsx +8 -0
  325. package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
  326. package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
  327. package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
  328. package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
  329. package/src/plugins/builtin/cloud/askg/model.ts +156 -78
  330. package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
  331. package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
  332. package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
  333. package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
  334. package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
  335. package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
  336. package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
  337. package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
  338. package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
  339. package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
  340. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
  341. package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
  342. package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
  343. package/src/plugins/builtin/cloud/plugin.tsx +36 -1
  344. package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
  345. package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
  346. package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
  347. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
  348. package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
  349. package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
  350. package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
  351. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
  352. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
  353. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
  354. package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
  355. package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
  356. package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
  357. package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
  358. package/src/plugins/builtin/comment-letters/client.ts +1 -3
  359. package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
  360. package/src/plugins/builtin/company-attention/headless.ts +19 -5
  361. package/src/plugins/builtin/company-attention/index.tsx +2 -0
  362. package/src/plugins/builtin/company-attention/model.ts +26 -7
  363. package/src/plugins/builtin/company-attention/pane.tsx +12 -9
  364. package/src/plugins/builtin/company-attention/series.ts +52 -0
  365. package/src/plugins/builtin/company-kpis/client.ts +23 -8
  366. package/src/plugins/builtin/company-kpis/headless.ts +3 -1
  367. package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
  368. package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
  369. package/src/plugins/builtin/composite-plugins.ts +116 -67
  370. package/src/plugins/builtin/cot/index.tsx +3 -1
  371. package/src/plugins/builtin/cot/model.ts +40 -11
  372. package/src/plugins/builtin/cot/series.ts +27 -0
  373. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
  374. package/src/plugins/builtin/credit-boards/index.tsx +23 -21
  375. package/src/plugins/builtin/credit-boards/model.ts +0 -1
  376. package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
  377. package/src/plugins/builtin/credit-boards/series.ts +66 -0
  378. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
  379. package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
  380. package/src/plugins/builtin/credit-conditions/series.ts +26 -0
  381. package/src/plugins/builtin/credit-documents/headless.ts +31 -1
  382. package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
  383. package/src/plugins/builtin/crypto-board/headless.ts +2 -3
  384. package/src/plugins/builtin/crypto-board/index.tsx +2 -0
  385. package/src/plugins/builtin/crypto-board/model.ts +12 -0
  386. package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
  387. package/src/plugins/builtin/crypto-board/series.ts +48 -0
  388. package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
  389. package/src/plugins/builtin/debt-maturities/client.ts +37 -9
  390. package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
  391. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  392. package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
  393. package/src/plugins/builtin/debt-maturities/series.ts +45 -0
  394. package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
  395. package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
  396. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  397. package/src/plugins/builtin/dividend-yield/series.ts +20 -0
  398. package/src/plugins/builtin/docs/blocks.tsx +181 -0
  399. package/src/plugins/builtin/docs/index.tsx +68 -0
  400. package/src/plugins/builtin/docs/pane.tsx +426 -0
  401. package/src/plugins/builtin/docs/targets.ts +72 -0
  402. package/src/plugins/builtin/docs/use-docs.ts +60 -0
  403. package/src/plugins/builtin/doe/index.tsx +2 -0
  404. package/src/plugins/builtin/doe/series.ts +62 -0
  405. package/src/plugins/builtin/earnings/client.ts +3 -2
  406. package/src/plugins/builtin/earnings/format.ts +1 -5
  407. package/src/plugins/builtin/earnings/headless.ts +58 -6
  408. package/src/plugins/builtin/earnings/history-model.ts +15 -1
  409. package/src/plugins/builtin/earnings/history-table.ts +13 -2
  410. package/src/plugins/builtin/earnings/history.tsx +7 -3
  411. package/src/plugins/builtin/earnings-calls/data.ts +28 -7
  412. package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
  413. package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
  414. package/src/plugins/builtin/econ/calendar-model.ts +42 -17
  415. package/src/plugins/builtin/econ/detail-view.tsx +2 -2
  416. package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
  417. package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
  418. package/src/plugins/builtin/econ/index.tsx +70 -22
  419. package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
  420. package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
  421. package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
  422. package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
  423. package/src/plugins/builtin/econ-statistics/view.ts +17 -0
  424. package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
  425. package/src/plugins/builtin/executives/data.ts +17 -6
  426. package/src/plugins/builtin/executives/pane.tsx +16 -7
  427. package/src/plugins/builtin/exposure/holdings.ts +1 -1
  428. package/src/plugins/builtin/exposure/pane.tsx +3 -1
  429. package/src/plugins/builtin/fear-greed/index.tsx +4 -0
  430. package/src/plugins/builtin/fear-greed/series.ts +52 -0
  431. package/src/plugins/builtin/filing-events/pane.tsx +22 -5
  432. package/src/plugins/builtin/futures/index.tsx +43 -3
  433. package/src/plugins/builtin/futures/model.ts +1 -1
  434. package/src/plugins/builtin/futures/returns.ts +1 -1
  435. package/src/plugins/builtin/futures/series.ts +13 -0
  436. package/src/plugins/builtin/futures/table.tsx +1 -1
  437. package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
  438. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  439. package/src/plugins/builtin/futures-curve/headless.ts +70 -9
  440. package/src/plugins/builtin/futures-curve/index.tsx +1 -1
  441. package/src/plugins/builtin/futures-curve/model.ts +66 -11
  442. package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
  443. package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
  444. package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
  445. package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
  446. package/src/plugins/builtin/gpu/board.tsx +13 -10
  447. package/src/plugins/builtin/gpu/changes.tsx +4 -4
  448. package/src/plugins/builtin/gpu/client.ts +19 -1
  449. package/src/plugins/builtin/gpu/equities.tsx +14 -10
  450. package/src/plugins/builtin/gpu/headless.ts +64 -27
  451. package/src/plugins/builtin/gpu/history.tsx +3 -3
  452. package/src/plugins/builtin/gpu/index.tsx +2 -0
  453. package/src/plugins/builtin/gpu/model.ts +114 -20
  454. package/src/plugins/builtin/gpu/pane.tsx +28 -12
  455. package/src/plugins/builtin/gpu/series.ts +38 -0
  456. package/src/plugins/builtin/help/function-card.tsx +25 -6
  457. package/src/plugins/builtin/help/index.tsx +18 -8
  458. package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
  459. package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
  460. package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
  461. package/src/plugins/builtin/holders/beneficial-view.tsx +62 -14
  462. package/src/plugins/builtin/holders/client.ts +22 -3
  463. package/src/plugins/builtin/holders/format.ts +18 -3
  464. package/src/plugins/builtin/holders/headless.ts +42 -134
  465. package/src/plugins/builtin/holders/pane.tsx +14 -4
  466. package/src/plugins/builtin/holders/report-header.ts +40 -5
  467. package/src/plugins/builtin/holders/report-rows.ts +240 -0
  468. package/src/plugins/builtin/insider/client.ts +35 -20
  469. package/src/plugins/builtin/insider/headless.ts +41 -11
  470. package/src/plugins/builtin/insider/index.tsx +27 -10
  471. package/src/plugins/builtin/insider/insider-data.ts +10 -0
  472. package/src/plugins/builtin/insider/issuer.ts +49 -0
  473. package/src/plugins/builtin/insider/model.ts +3 -0
  474. package/src/plugins/builtin/iv-history/charts.tsx +21 -7
  475. package/src/plugins/builtin/iv-history/client.ts +26 -6
  476. package/src/plugins/builtin/iv-history/format.ts +33 -2
  477. package/src/plugins/builtin/iv-history/headless.ts +27 -12
  478. package/src/plugins/builtin/iv-history/index.tsx +5 -3
  479. package/src/plugins/builtin/iv-history/model.ts +172 -20
  480. package/src/plugins/builtin/iv-history/pane.tsx +11 -3
  481. package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
  482. package/src/plugins/builtin/iv-history/series.ts +29 -0
  483. package/src/plugins/builtin/jobs/headless.ts +28 -3
  484. package/src/plugins/builtin/jobs/index.tsx +3 -1
  485. package/src/plugins/builtin/jobs/pane.tsx +1 -1
  486. package/src/plugins/builtin/jobs/series.ts +19 -0
  487. package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
  488. package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
  489. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  490. package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
  491. package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
  492. package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
  493. package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
  494. package/src/plugins/builtin/layout-manager/index.tsx +9 -1
  495. package/src/plugins/builtin/macro-day/client.ts +68 -3
  496. package/src/plugins/builtin/macro-day/headless.ts +18 -12
  497. package/src/plugins/builtin/macro-day/index.tsx +3 -0
  498. package/src/plugins/builtin/macro-day/model.ts +66 -15
  499. package/src/plugins/builtin/macro-day/pane.tsx +34 -20
  500. package/src/plugins/builtin/macro-day/release-table.ts +40 -0
  501. package/src/plugins/builtin/macro-day/releases.ts +62 -44
  502. package/src/plugins/builtin/market-heatmap/data.ts +25 -5
  503. package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
  504. package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
  505. package/src/plugins/builtin/market-heatmap/model.ts +102 -3
  506. package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
  507. package/src/plugins/builtin/market-movers/client.ts +7 -5
  508. package/src/plugins/builtin/market-movers/headless.ts +31 -4
  509. package/src/plugins/builtin/market-movers/index.tsx +11 -3
  510. package/src/plugins/builtin/market-movers/model.ts +101 -17
  511. package/src/plugins/builtin/market-movers/screener.ts +31 -0
  512. package/src/plugins/builtin/market-movers/table.ts +50 -23
  513. package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
  514. package/src/plugins/builtin/market-valuation/index.tsx +3 -3
  515. package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
  516. package/src/plugins/builtin/members/headless.ts +7 -2
  517. package/src/plugins/builtin/members/model.ts +31 -3
  518. package/src/plugins/builtin/members/pane.tsx +3 -6
  519. package/src/plugins/builtin/mna/headless.ts +15 -3
  520. package/src/plugins/builtin/money-markets/index.tsx +2 -0
  521. package/src/plugins/builtin/money-markets/series.ts +41 -0
  522. package/src/plugins/builtin/news/headless.ts +9 -2
  523. package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
  524. package/src/plugins/builtin/notes/cli.ts +12 -7
  525. package/src/plugins/builtin/openfda/client.ts +1 -1
  526. package/src/plugins/builtin/options/carry.ts +95 -0
  527. package/src/plugins/builtin/options/index.tsx +58 -5
  528. package/src/plugins/builtin/options/strike-window.ts +183 -0
  529. package/src/plugins/builtin/options/table.ts +55 -3
  530. package/src/plugins/builtin/options/types.ts +8 -1
  531. package/src/plugins/builtin/options/view.tsx +162 -13
  532. package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
  533. package/src/plugins/builtin/options-positioning/client.ts +7 -3
  534. package/src/plugins/builtin/options-positioning/headless.ts +5 -2
  535. package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
  536. package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
  537. package/src/plugins/builtin/options-scenario/client.ts +75 -18
  538. package/src/plugins/builtin/options-scenario/headless.ts +72 -24
  539. package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
  540. package/src/plugins/builtin/options-scenario/index.tsx +9 -2
  541. package/src/plugins/builtin/options-scenario/model.ts +33 -0
  542. package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
  543. package/src/plugins/builtin/pe-band/model.ts +2 -2
  544. package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
  545. package/src/plugins/builtin/perps/client.ts +40 -6
  546. package/src/plugins/builtin/perps/equity-row.tsx +33 -8
  547. package/src/plugins/builtin/perps/freshness.ts +66 -0
  548. package/src/plugins/builtin/perps/headless.ts +45 -30
  549. package/src/plugins/builtin/perps/index.tsx +18 -1
  550. package/src/plugins/builtin/perps/model.ts +32 -6
  551. package/src/plugins/builtin/perps/pane.tsx +76 -20
  552. package/src/plugins/builtin/perps/series.ts +76 -0
  553. package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
  554. package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
  555. package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
  556. package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
  557. package/src/plugins/builtin/plugin-module.ts +90 -4
  558. package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
  559. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
  560. package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
  561. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
  562. package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
  563. package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
  564. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
  565. package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
  566. package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
  567. package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
  568. package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
  569. package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
  570. package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
  571. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
  572. package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
  573. package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
  574. package/src/plugins/builtin/power/client.ts +16 -0
  575. package/src/plugins/builtin/power/evidence.ts +6 -2
  576. package/src/plugins/builtin/power/headless.ts +71 -7
  577. package/src/plugins/builtin/power/index.tsx +4 -1
  578. package/src/plugins/builtin/power/model.ts +72 -1
  579. package/src/plugins/builtin/power/pane.tsx +32 -9
  580. package/src/plugins/builtin/rate-path/headless.ts +11 -3
  581. package/src/plugins/builtin/realized-vol/headless.ts +8 -0
  582. package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
  583. package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
  584. package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
  585. package/src/plugins/builtin/research/event-model.ts +68 -24
  586. package/src/plugins/builtin/research/events-headless.ts +2 -1
  587. package/src/plugins/builtin/research/headless.ts +2 -1
  588. package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
  589. package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
  590. package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
  591. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
  592. package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
  593. package/src/plugins/builtin/risk-factors/data.ts +23 -9
  594. package/src/plugins/builtin/risk-factors/headless.ts +5 -2
  595. package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
  596. package/src/plugins/builtin/seasonality/client.ts +15 -7
  597. package/src/plugins/builtin/seasonality/headless.ts +36 -12
  598. package/src/plugins/builtin/seasonality/index.tsx +2 -2
  599. package/src/plugins/builtin/seasonality/model.ts +119 -0
  600. package/src/plugins/builtin/seasonality/pane.tsx +108 -37
  601. package/src/plugins/builtin/sec/index.tsx +5 -5
  602. package/src/plugins/builtin/sectors/client.ts +10 -2
  603. package/src/plugins/builtin/sectors/headless.ts +35 -6
  604. package/src/plugins/builtin/sectors/index.tsx +18 -1
  605. package/src/plugins/builtin/sectors/sector-model.ts +150 -41
  606. package/src/plugins/builtin/series-inventory.ts +91 -0
  607. package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
  608. package/src/plugins/builtin/shared/command-tab.ts +69 -0
  609. package/src/plugins/builtin/shared/earnings-report.ts +55 -0
  610. package/src/plugins/builtin/shared/fred-points.ts +20 -0
  611. package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
  612. package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
  613. package/src/plugins/builtin/shared/members-menu.tsx +4 -4
  614. package/src/plugins/builtin/shared/open-description.ts +29 -0
  615. package/src/plugins/builtin/shared/report-freshness.ts +59 -2
  616. package/src/plugins/builtin/shared/series-warning.ts +5 -0
  617. package/src/plugins/builtin/shared/ticker-request.ts +25 -1
  618. package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
  619. package/src/plugins/builtin/shared/volatility/options.ts +1 -46
  620. package/src/plugins/builtin/short-interest/headless.ts +1 -0
  621. package/src/plugins/builtin/short-interest/index.tsx +21 -4
  622. package/src/plugins/builtin/short-interest/series.ts +36 -0
  623. package/src/plugins/builtin/short-interest/surface.tsx +4 -4
  624. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  625. package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
  626. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  627. package/src/plugins/builtin/short-volume/index.tsx +3 -10
  628. package/src/plugins/builtin/short-volume/series.ts +23 -0
  629. package/src/plugins/builtin/social-mentions/index.tsx +2 -0
  630. package/src/plugins/builtin/social-mentions/series.ts +23 -0
  631. package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
  632. package/src/plugins/builtin/supply-chain/model.ts +1 -1
  633. package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
  634. package/src/plugins/builtin/thirteenf/api.ts +1 -0
  635. package/src/plugins/builtin/thirteenf/data.ts +6 -4
  636. package/src/plugins/builtin/thirteenf/headless.ts +217 -36
  637. package/src/plugins/builtin/thirteenf/model.ts +39 -1
  638. package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
  639. package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
  640. package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
  641. package/src/plugins/builtin/thirteenf/types.ts +2 -0
  642. package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
  643. package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
  644. package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
  645. package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
  646. package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
  647. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
  648. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
  649. package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
  650. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
  651. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
  652. package/src/plugins/builtin/time-sales/headless.ts +1 -0
  653. package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
  654. package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
  655. package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
  656. package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
  657. package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
  658. package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
  659. package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
  660. package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
  661. package/src/plugins/builtin/vol-surface/client.ts +6 -2
  662. package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
  663. package/src/plugins/builtin/vol-surface/headless.ts +125 -20
  664. package/src/plugins/builtin/vol-surface/model.ts +23 -11
  665. package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
  666. package/src/plugins/builtin/vol-surface/tables.ts +124 -0
  667. package/src/plugins/builtin/volatility/index.tsx +2 -0
  668. package/src/plugins/builtin/volatility/series.ts +84 -0
  669. package/src/plugins/builtin/world-indices/client.ts +22 -4
  670. package/src/plugins/builtin/world-indices/headless.ts +54 -27
  671. package/src/plugins/builtin/world-indices/model.ts +4 -2
  672. package/src/plugins/builtin/world-indices/table.tsx +13 -2
  673. package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
  674. package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
  675. package/src/plugins/builtin/world-venue-map/index.ts +3 -2
  676. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
  677. package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
  678. package/src/plugins/builtin/yield-curve/chart.ts +2 -2
  679. package/src/plugins/builtin/yield-curve/curves.ts +21 -8
  680. package/src/plugins/builtin/yield-curve/headless.ts +71 -18
  681. package/src/plugins/builtin/yield-curve/index.tsx +4 -2
  682. package/src/plugins/builtin/yield-curve/series.ts +86 -0
  683. package/src/plugins/builtin-editorial.ts +126 -0
  684. package/src/plugins/catalog-backend.ts +16 -9
  685. package/src/plugins/catalog-browser.ts +129 -64
  686. package/src/plugins/catalog-manifest.ts +73 -40
  687. package/src/plugins/catalog-ui.ts +26 -6
  688. package/src/plugins/extracted-plugins.ts +7 -1
  689. package/src/plugins/ownership.ts +150 -7
  690. package/src/plugins/plugin-functions.ts +54 -0
  691. package/src/plugins/plugin-off.ts +36 -0
  692. package/src/plugins/registry/host-actions.ts +16 -0
  693. package/src/plugins/registry/index.ts +173 -28
  694. package/src/plugins/registry/plugin-state.ts +25 -1
  695. package/src/plugins/runtime/context.tsx +29 -0
  696. package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
  697. package/src/portfolio/position-value.ts +40 -0
  698. package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
  699. package/src/public/time-series.ts +17 -0
  700. package/src/react/auto-refresh.ts +13 -3
  701. package/src/react/input.ts +48 -1
  702. package/src/remote/app-host.tsx +25 -4
  703. package/src/remote/confirm-change.tsx +85 -0
  704. package/src/remote/controller-utils.ts +8 -1
  705. package/src/remote/controller.ts +126 -59
  706. package/src/remote/matching.ts +69 -0
  707. package/src/remote/pane-screenshot.ts +47 -0
  708. package/src/remote/schema.ts +63 -1
  709. package/src/remote/semantic-tree.tsx +14 -0
  710. package/src/remote/types.ts +32 -0
  711. package/src/remote/watchlist.ts +306 -0
  712. package/src/renderers/browser/main.tsx +3 -2
  713. package/src/renderers/cloudflare/worker.ts +1 -1
  714. package/src/renderers/dom/data-table/frozen-column.ts +3 -1
  715. package/src/renderers/dom/data-table/index.tsx +33 -6
  716. package/src/renderers/dom/data-table/row.tsx +27 -1
  717. package/src/renderers/dom/desktop/control-styles.ts +63 -1
  718. package/src/renderers/dom/desktop/controls.tsx +30 -23
  719. package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
  720. package/src/renderers/dom/desktop/icons.tsx +21 -0
  721. package/src/renderers/dom/desktop/query-bar.tsx +59 -32
  722. package/src/renderers/dom/dom-ui-host.tsx +3 -0
  723. package/src/renderers/dom/host/box.tsx +4 -1
  724. package/src/renderers/dom/host/chart-surface.tsx +6 -2
  725. package/src/renderers/dom/host/drag-shield.ts +17 -6
  726. package/src/renderers/dom/host/live-frame.ts +14 -2
  727. package/src/renderers/dom/host/overflow-fade.ts +14 -1
  728. package/src/renderers/dom/host/size-observer.ts +26 -0
  729. package/src/renderers/dom/host/surface-3d.tsx +7 -2
  730. package/src/renderers/dom/host/text.tsx +1 -1
  731. package/src/renderers/dom/input-host.tsx +6 -1
  732. package/src/renderers/dom/styles.css +74 -0
  733. package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
  734. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
  735. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
  736. package/src/renderers/electrobun/shared/protocol.ts +2 -0
  737. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
  738. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
  739. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
  740. package/src/renderers/electrobun/view/main.tsx +6 -1
  741. package/src/renderers/opentui/input-host.tsx +6 -1
  742. package/src/renderers/opentui/start.tsx +9 -0
  743. package/src/series/capability.ts +75 -0
  744. package/src/series/csv.ts +160 -0
  745. package/src/series/files.ts +107 -0
  746. package/src/series/registry.ts +198 -0
  747. package/src/series/resolve.ts +107 -0
  748. package/src/series/standalone.ts +48 -0
  749. package/src/series/types.ts +145 -0
  750. package/src/series/validate.ts +171 -0
  751. package/src/shares/portable-layout.ts +16 -6
  752. package/src/sources/gloomberb-cloud/index.ts +26 -17
  753. package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
  754. package/src/sources/history-result.ts +1 -0
  755. package/src/sources/listing-symbols.ts +14 -5
  756. package/src/sources/provider-errors.ts +88 -3
  757. package/src/sources/provider-router/batches.ts +4 -1
  758. package/src/sources/provider-router/cache.ts +4 -2
  759. package/src/sources/provider-router/cached-routes.ts +9 -5
  760. package/src/sources/provider-router/financial-routes.ts +12 -5
  761. package/src/sources/provider-router/financials.ts +55 -15
  762. package/src/sources/provider-router/history.ts +68 -34
  763. package/src/sources/provider-router/index.ts +1 -1
  764. package/src/sources/provider-router/primary.ts +23 -5
  765. package/src/sources/provider-router/search.ts +1 -0
  766. package/src/sources/sec-edgar.ts +68 -8
  767. package/src/sync/core-contributors.ts +5 -3
  768. package/src/test-support/cli-context.ts +2 -1
  769. package/src/test-support/data-provider.ts +34 -0
  770. package/src/test-support/shell-pane-keys.tsx +1 -0
  771. package/src/theme/series-colors.ts +46 -0
  772. package/src/theme/themes.ts +149 -0
  773. package/src/tickers/company-name.ts +75 -0
  774. package/src/tickers/instrument-kind.ts +25 -0
  775. package/src/tickers/open-target.ts +3 -2
  776. package/src/tickers/search/index.ts +67 -9
  777. package/src/tickers/search/ranking.ts +78 -18
  778. package/src/tickers/search/types.ts +10 -2
  779. package/src/tickers/starter-symbols.ts +8 -0
  780. package/src/tickers/us-listing.ts +34 -0
  781. package/src/time-series/hooks.ts +9 -0
  782. package/src/time-series/resolve.ts +96 -30
  783. package/src/time-series/types.ts +4 -2
  784. package/src/time-series/use-chart-resolution.ts +32 -0
  785. package/src/types/config.ts +67 -1
  786. package/src/types/data-provider.ts +5 -0
  787. package/src/types/financials.ts +52 -1
  788. package/src/types/headless.ts +72 -0
  789. package/src/types/instrument.ts +8 -0
  790. package/src/types/plugin.ts +68 -3
  791. package/src/types/price-history.ts +7 -0
  792. package/src/types/ticker.ts +14 -0
  793. package/src/ui/host.tsx +26 -4
  794. package/src/ui/index.tsx +2 -0
  795. package/src/ui/live-resize.ts +81 -0
  796. package/src/ui/live-stretch.ts +121 -0
  797. package/src/ui/measured-cells.ts +58 -0
  798. package/src/ui/pane-fill.ts +11 -0
  799. package/src/utils/basis-points.ts +17 -0
  800. package/src/utils/cli-output.ts +21 -2
  801. package/src/utils/concurrency.ts +25 -0
  802. package/src/utils/crypto-pair.ts +20 -0
  803. package/src/utils/currency-pair.ts +19 -0
  804. package/src/utils/decimal-comma.ts +19 -0
  805. package/src/utils/dom-screenshot-css.ts +265 -0
  806. package/src/utils/dom-screenshot-rasters.ts +276 -0
  807. package/src/utils/dom-screenshot.ts +437 -52
  808. package/src/utils/exchange-rate-snapshot.ts +6 -2
  809. package/src/utils/exchanges.ts +120 -1
  810. package/src/utils/format.ts +17 -3
  811. package/src/utils/fundamentals.ts +66 -0
  812. package/src/utils/futures-generic.ts +6 -12
  813. package/src/utils/fx-market-hours.ts +44 -0
  814. package/src/utils/option-expiry.ts +126 -0
  815. package/src/utils/price-history.ts +130 -40
  816. package/src/utils/rpc-timeout-error.ts +6 -2
  817. package/src/utils/sec-eps-basis.ts +178 -36
  818. package/src/utils/sec.ts +98 -40
  819. package/src/utils/throttled-fetch.ts +51 -22
  820. package/src/utils/utc-time.ts +51 -4
@@ -9,6 +9,11 @@ import { quoteFutureToleranceMs } from "../quotes/clock";
9
9
  import { zonedDateKey, zonedDateTimeParts, zonedWallClockToUtcMs } from "../../utils/zoned-date-time";
10
10
 
11
11
  const ALWAYS_OPEN_EXCHANGES = new Set(["CCC"]);
12
+
13
+ /** Spot crypto venues have no equity open or close. */
14
+ export function isAlwaysOpenExchange(exchange: string | undefined): boolean {
15
+ return ALWAYS_OPEN_EXCHANGES.has(canonicalExchange(exchange));
16
+ }
12
17
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
13
18
  const OVERNIGHT_CLOSE_MAX_AGE_MS = 20 * 60 * 60 * 1000;
14
19
  const ALWAYS_OPEN_MAX_AGE_MS = 2 * 60 * 60 * 1000;
@@ -61,6 +66,15 @@ const REGULAR_OPEN_MINUTES: Record<string, number> = {
61
66
  B3: 10 * 60,
62
67
  BYMA: 11 * 60,
63
68
  JSE: 9 * 60,
69
+ // The opening auction ends at 10:00 and the feed stamps its first bar 09:59.
70
+ TASE: 9 * 60 + 59,
71
+ TADAWUL: 10 * 60,
72
+ QE: 9 * 60 + 30,
73
+ BHB: 9 * 60 + 30,
74
+ DFM: 10 * 60,
75
+ MSX: 10 * 60,
76
+ KUWAIT: 9 * 60,
77
+ EGX: 10 * 60,
64
78
  };
65
79
  // Local regular close with the closing auction, rounded up. A close taken too
66
80
  // early would let a copy fetched during the auction pass as final.
@@ -74,7 +88,79 @@ const REGULAR_CLOSE_MINUTES: Record<string, number> = {
74
88
  JPX: 15 * 60 + 30, HKEX: 16 * 60 + 10, TWSE: 14 * 60 + 30, TPEX: 14 * 60 + 30,
75
89
  NSE: 16 * 60, BSE: 16 * 60, ASX: 16 * 60 + 15, SGX: 17 * 60 + 20, KRX: 16 * 60, KOSDAQ: 16 * 60,
76
90
  NZX: 17 * 60, SSE: 15 * 60 + 30, SZSE: 15 * 60 + 30,
77
- BMV: 15 * 60 + 10, B3: 18 * 60 + 30, BYMA: 17 * 60 + 10, JSE: 17 * 60 + 15, TASE: 17 * 60 + 40,
91
+ BMV: 15 * 60 + 10, B3: 18 * 60 + 30, BYMA: 17 * 60 + 10, JSE: 17 * 60 + 15,
92
+ // Monday to Thursday: trading at last ends 17:30, after the closing auction.
93
+ // Not later: a complete 5-minute copy ends with its 17:09 bar, which must
94
+ // reach the close less the half hour a history copy may lag.
95
+ TASE: 17 * 60 + 30,
96
+ // Continuous trading to 15:00, the closing auction to 15:10 and trading at
97
+ // last to 15:20. A complete 5-minute copy ends with its 14:55 bar.
98
+ TADAWUL: 15 * 60 + 20,
99
+ // Continuous trading to 13:00, the closing auction to 13:10 and trading at
100
+ // last to 13:15. A complete 5-minute copy ends with its 13:05 or 13:10 bar.
101
+ QE: 13 * 60 + 15,
102
+ // Bahrain Bourse trades continuously to 13:00, with no closing auction.
103
+ BHB: 13 * 60,
104
+ // Continuous trading to 14:45, the closing auction to 14:55 and trading at
105
+ // the close to 15:00. A complete 5-minute copy ends with its 14:55 bar.
106
+ DFM: 15 * 60,
107
+ // The Muscat Stock Exchange since 1 Jun 2026: continuous trading to 14:45,
108
+ // the closing auction to 14:55 and trade at last to 15:00. A complete
109
+ // 5-minute copy ends with its 14:55 bar.
110
+ MSX: 15 * 60,
111
+ // Boursa Kuwait: continuous trading to 13:00, the closing auction to 13:10
112
+ // and trade at last to 13:15. Not later than the auction's end: a complete
113
+ // 5-minute copy ends with its 12:40 bar (the source still closes its
114
+ // period at 12:45), which must reach the close less the half hour a
115
+ // history copy may lag.
116
+ KUWAIT: 13 * 60 + 10,
117
+ // The Egyptian Exchange: continuous trading to 14:15, the closing auction
118
+ // to 14:25 and trading at the close to 14:30.
119
+ EGX: 14 * 60 + 25,
120
+ };
121
+ // Venues whose week is not Monday to Friday, as their days off (0 is Sunday).
122
+ // Tadawul, Qatar, Boursa Kuwait and the Egyptian Exchange trade Sunday to
123
+ // Thursday. Dubai's DFM has traded Monday to Friday since 2022, like the
124
+ // venues not listed here.
125
+ const WEEKEND_DAYS: Record<string, readonly number[]> = {
126
+ TADAWUL: [5, 6],
127
+ // Bahrain Bourse trades Sunday to Thursday.
128
+ BHB: [5, 6],
129
+ QE: [5, 6],
130
+ // The Muscat Stock Exchange trades Sunday to Thursday.
131
+ MSX: [5, 6],
132
+ KUWAIT: [5, 6],
133
+ EGX: [5, 6],
134
+ };
135
+ const DEFAULT_WEEKEND_DAYS: readonly number[] = [0, 6];
136
+ // History only: venues whose chart source files their bars on another week,
137
+ // as its days off. The chart source still files DFM Sunday to Thursday, the
138
+ // week Dubai traded until 2022, and has no Friday bars, so DFM history ends
139
+ // with Thursday's session from Friday until Monday's opens.
140
+ const HISTORY_SOURCE_WEEKEND_DAYS: Record<string, readonly number[]> = {
141
+ DFM: [5, 6],
142
+ };
143
+
144
+ /**
145
+ * For history only, the days off of the sessions a venue's chart source has
146
+ * bars for, where its week differs from the venue's: the days both weeks
147
+ * trade (DFM Monday to Thursday, since Dubai does not trade the source's
148
+ * Sundays). Undefined for every other venue. Quotes and the calendar keep the
149
+ * venue's own week.
150
+ */
151
+ export function historySourceWeekendDays(exchange: string | undefined): readonly number[] | undefined {
152
+ const canonical = canonicalExchange(exchange);
153
+ const source = HISTORY_SOURCE_WEEKEND_DAYS[canonical];
154
+ return source && [...new Set([...(WEEKEND_DAYS[canonical] ?? DEFAULT_WEEKEND_DAYS), ...source])];
155
+ }
156
+ // Venues whose regular session ends earlier on one weekday every week, as
157
+ // local minutes by weekday (0 is Sunday); the other days close as above. TASE
158
+ // has traded Monday to Friday since January 2026, and on Fridays trading at
159
+ // last ends 13:50 (closing auction 13:44 to 13:45). A complete 5-minute copy
160
+ // ends with its 13:29 bar. Holidays and the shortened days around Sukkot and
161
+ // Pesach are not weekly and are not listed.
162
+ const WEEKDAY_CLOSE_MINUTES: Record<string, Partial<Record<number, number>>> = {
163
+ TASE: { 5: 13 * 60 + 50 },
78
164
  };
79
165
  // Venues that pause at midday, as local minutes [start, end), with a zone for
80
166
  // those the session tables above do not cover. Jakarta pauses longer on Fridays.
@@ -189,20 +275,31 @@ function isPublishedClosure(exchange: string, date: string): boolean {
189
275
  return getPublishedUsEquityCalendarDay(exchange, date) === "closed";
190
276
  }
191
277
 
192
- function isLocalTradingDay(exchange: string, date: string): boolean {
278
+ /** Whether `weekday` (0 is Sunday) is in the venue's trading week. */
279
+ export function isTradingWeekday(exchange: string, weekday: number, weekendDays?: readonly number[]): boolean {
280
+ return !(weekendDays ?? WEEKEND_DAYS[exchange] ?? DEFAULT_WEEKEND_DAYS).includes(weekday);
281
+ }
282
+
283
+ /** `weekendDays` replaces the venue's days off (historySourceWeekendDays). */
284
+ function isLocalTradingDay(exchange: string, date: string, weekendDays?: readonly number[]): boolean {
193
285
  const weekday = localWeekday(date);
194
- return weekday != null && weekday !== 0 && weekday !== 6 && !isPublishedClosure(exchange, date);
286
+ return weekday != null && isTradingWeekday(exchange, weekday, weekendDays) && !isPublishedClosure(exchange, date);
195
287
  }
196
288
 
197
- /** Weekdays in (earlier, later], less published closures for venues with a calendar. */
198
- function localTradingDaysBetween(exchange: string, earlierDate: string, laterDate: string): number {
289
+ /** Days of the venue's trading week in (earlier, later], less published closures for venues with a calendar. */
290
+ function localTradingDaysBetween(
291
+ exchange: string,
292
+ earlierDate: string,
293
+ laterDate: string,
294
+ weekendDays?: readonly number[],
295
+ ): number {
199
296
  const earlierDay = isoLocalDateToUtcDay(earlierDate);
200
297
  const laterDay = isoLocalDateToUtcDay(laterDate);
201
298
  if (earlierDay == null || laterDay == null || laterDay <= earlierDay) return 0;
202
299
 
203
300
  let sessions = 0;
204
301
  for (let day = earlierDay + 1; day <= laterDay; day += 1) {
205
- if (isLocalTradingDay(exchange, new Date(day * MS_PER_DAY).toISOString().slice(0, 10))) sessions += 1;
302
+ if (isLocalTradingDay(exchange, new Date(day * MS_PER_DAY).toISOString().slice(0, 10), weekendDays)) sessions += 1;
206
303
  }
207
304
  return sessions;
208
305
  }
@@ -212,6 +309,12 @@ function localWeekday(date: string): number | null {
212
309
  return day == null ? null : new Date(day * MS_PER_DAY).getUTCDay();
213
310
  }
214
311
 
312
+ /** The local close of the venue's regular session on `date`, in minutes of the day. */
313
+ function regularCloseMinutes(exchange: string, date: string): number | undefined {
314
+ const weekday = localWeekday(date);
315
+ return (weekday == null ? undefined : WEEKDAY_CLOSE_MINUTES[exchange]?.[weekday]) ?? REGULAR_CLOSE_MINUTES[exchange];
316
+ }
317
+
215
318
  /** The zone a venue's session dates are read in, or null when unknown. */
216
319
  export function sessionCalendarTimeZone(exchange: string | undefined): string | null {
217
320
  const canonical = canonicalExchange(exchange);
@@ -221,13 +324,14 @@ export function sessionCalendarTimeZone(exchange: string | undefined): string |
221
324
 
222
325
  /**
223
326
  * The latest regular session that closed at or before `time`: the published
224
- * calendar for US venues, otherwise local weekdays less published closures. A
225
- * venue without a known close hour is taken to close at local midnight. Null
226
- * for round-the-clock and unknown venues.
327
+ * calendar for US venues, otherwise the days of the venue's trading week less
328
+ * published closures. A venue without a known close hour is taken to close at
329
+ * local midnight. Null for round-the-clock and unknown venues.
227
330
  */
228
331
  export function latestRegularSessionClose(
229
332
  exchange: string | undefined,
230
333
  time: number,
334
+ weekendDays?: readonly number[],
231
335
  ): { date: string; close: number; timeZone: string } | null {
232
336
  const canonical = canonicalExchange(exchange);
233
337
  const timeZone = sessionCalendarTimeZone(canonical);
@@ -240,8 +344,8 @@ export function latestRegularSessionClose(
240
344
  let close: number | null = null;
241
345
  if (published) {
242
346
  if (published.kind === "session") close = published.close;
243
- } else if (isLocalTradingDay(canonical, date)) {
244
- const minutes = REGULAR_CLOSE_MINUTES[canonical] ?? 24 * 60;
347
+ } else if (isLocalTradingDay(canonical, date, weekendDays)) {
348
+ const minutes = regularCloseMinutes(canonical, date) ?? 24 * 60;
245
349
  close = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)),
246
350
  Number(date.slice(8, 10)), Math.floor(minutes / 60), minutes % 60, 0);
247
351
  }
@@ -267,10 +371,14 @@ export function regularSessionCloseUtcMinute(exchange: string | undefined, time:
267
371
  /**
268
372
  * The open of the regular session `time` falls in, or of the latest one
269
373
  * before it: the published calendar for US venues, otherwise the venue's
270
- * local open on a weekday that is not a published closure. Null for
271
- * round-the-clock venues and venues without a known open hour.
374
+ * local open on a day of its trading week that is not a published closure.
375
+ * Null for round-the-clock venues and venues without a known open hour.
272
376
  */
273
- export function latestRegularSessionOpen(exchange: string | undefined, time: number): number | null {
377
+ export function latestRegularSessionOpen(
378
+ exchange: string | undefined,
379
+ time: number,
380
+ weekendDays?: readonly number[],
381
+ ): number | null {
274
382
  const canonical = canonicalExchange(exchange);
275
383
  const timeZone = sessionCalendarTimeZone(canonical);
276
384
  if (!timeZone || ALWAYS_OPEN_EXCHANGES.has(canonical) || !Number.isFinite(time)) return null;
@@ -285,7 +393,7 @@ export function latestRegularSessionOpen(exchange: string | undefined, time: num
285
393
  if (published.kind === "session") open = published.open;
286
394
  } else if (minutes === undefined) {
287
395
  return null;
288
- } else if (isLocalTradingDay(canonical, date)) {
396
+ } else if (isLocalTradingDay(canonical, date, weekendDays)) {
289
397
  open = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)),
290
398
  Number(date.slice(8, 10)), Math.floor(minutes / 60), minutes % 60, 0);
291
399
  }
@@ -294,22 +402,60 @@ export function latestRegularSessionOpen(exchange: string | undefined, time: num
294
402
  return null;
295
403
  }
296
404
 
405
+ /**
406
+ * The open of the first regular session after `time`, with its local date and
407
+ * the venue's zone: the published calendar for US venues, otherwise the
408
+ * venue's local open on the next day of its trading week that is not a
409
+ * published closure. Null for round-the-clock venues and venues without a
410
+ * known open hour.
411
+ */
412
+ export function nextRegularSessionOpen(
413
+ exchange: string | undefined,
414
+ time: number,
415
+ ): { date: string; open: number; timeZone: string } | null {
416
+ const canonical = canonicalExchange(exchange);
417
+ const timeZone = sessionCalendarTimeZone(canonical);
418
+ if (!timeZone || ALWAYS_OPEN_EXCHANGES.has(canonical) || !Number.isFinite(time)) return null;
419
+ const minutes = REGULAR_OPEN_MINUTES[canonical];
420
+ const { year, month, day } = zonedDateTimeParts(time, timeZone);
421
+ const today = Date.UTC(year, month - 1, day) / MS_PER_DAY;
422
+ for (let offset = 0; offset <= SESSION_LOOKBACK_DAYS; offset++) {
423
+ const date = new Date((today + offset) * MS_PER_DAY).toISOString().slice(0, 10);
424
+ const published = getPublishedUsEquitySession(canonical, date);
425
+ let open: number | null = null;
426
+ if (published) {
427
+ if (published.kind === "session") open = published.open;
428
+ } else if (minutes === undefined) {
429
+ return null;
430
+ } else if (isLocalTradingDay(canonical, date)) {
431
+ open = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)),
432
+ Number(date.slice(8, 10)), Math.floor(minutes / 60), minutes % 60, 0);
433
+ }
434
+ if (open != null && open > time) return { date, open, timeZone };
435
+ }
436
+ return null;
437
+ }
438
+
297
439
  /**
298
440
  * Whether `time` is inside a regular session: at or after its open and
299
441
  * before its close. Null for venues without known hours.
300
442
  */
301
- export function isRegularSessionTime(exchange: string | undefined, time: number): boolean | null {
302
- const open = latestRegularSessionOpen(exchange, time);
443
+ export function isRegularSessionTime(
444
+ exchange: string | undefined,
445
+ time: number,
446
+ weekendDays?: readonly number[],
447
+ ): boolean | null {
448
+ const open = latestRegularSessionOpen(exchange, time, weekendDays);
303
449
  if (open === null) return null;
304
450
  // Before this session's close, the latest close is still the one before it opened.
305
- const close = latestRegularSessionClose(exchange, time);
451
+ const close = latestRegularSessionClose(exchange, time, weekendDays);
306
452
  return !close || close.close < open;
307
453
  }
308
454
 
309
455
  /**
310
456
  * True when the venue's full-day closures for the year of `date` are
311
457
  * published: US venues, JPX, NSE, BSE, SSE, SZSE, KRX, KOSDAQ, TWSE, TPEX,
312
- * HKEX, SGX and ASX. Elsewhere a local holiday reads as a weekday.
458
+ * HKEX, SGX, ASX and EGX. Elsewhere a local holiday reads as a trading day.
313
459
  */
314
460
  export function hasPublishedSessionCalendar(exchange: string | undefined, date: string): boolean {
315
461
  const canonical = canonicalExchange(exchange);
@@ -345,7 +491,7 @@ export function isMiddayBreakPrint(
345
491
  if (!pause || !timeZone || !Number.isFinite(timestampMs) || !Number.isFinite(now) || timestampMs > now) return false;
346
492
  const { year, month, day } = zonedDateTimeParts(now, timeZone);
347
493
  const weekday = new Date(Date.UTC(year, month - 1, day)).getUTCDay();
348
- if (weekday === 0 || weekday === 6) return false;
494
+ if (!isTradingWeekday(canonical, weekday)) return false;
349
495
  const [start, end] = weekday === 5 && pause.friday ? pause.friday : pause.weekdays;
350
496
  const at = (minutes: number) => zonedWallClockToUtcMs(timeZone, year, month, day, Math.floor(minutes / 60), minutes % 60, 0);
351
497
  const breakStart = at(start);
@@ -443,20 +589,35 @@ export function isUsRegularCloseQuoteInPostSession(
443
589
  }
444
590
 
445
591
  /**
446
- * Whether a US print belongs to the after-hours session in progress: today's,
447
- * from the regular close. An earlier day's after-hours print is not.
592
+ * Whether a US print belongs to the extended-hours session the source labels,
593
+ * or to the regular session it extends. POST, after today's regular close (a
594
+ * published early close included) and before 20:00: a print from today's
595
+ * regular session or its after-hours. PRE, before today's open: a print from
596
+ * the previous regular session or since, so its after-hours or this morning's
597
+ * pre-market. An earlier print is not, and neither is any print on a day
598
+ * without a session.
448
599
  */
449
- export function isUsPostSessionPrint(
600
+ export function isUsExtendedHoursSessionPrint(
450
601
  timestampMs: number,
451
602
  exchange: string | undefined,
603
+ marketState: MarketState | undefined,
452
604
  now = Date.now(),
453
605
  ): boolean {
454
606
  const canonical = canonicalExchange(exchange);
455
- if (!isUsListingExchange(canonical)) return false;
607
+ if ((marketState !== "PRE" && marketState !== "POST") || !isUsListingExchange(canonical)) return false;
456
608
  if (!Number.isFinite(timestampMs) || !Number.isFinite(now) || timestampMs > now + quoteFutureToleranceMs()) return false;
457
- if (!Number.isFinite(new Date(now).getTime()) || usSessionState(now) !== "POST") return false;
458
- const currentDate = exchangeLocalDate(canonical, now);
459
- return !!currentDate && exchangeLocalDate(canonical, timestampMs) === currentDate && usSessionState(timestampMs) === "POST";
609
+ if (!Number.isFinite(new Date(now).getTime())) return false;
610
+ const today = exchangeLocalDate(canonical, now);
611
+ const close = latestRegularSessionClose(canonical, now);
612
+ if (!today || !close || !isLocalTradingDay(canonical, today)) return false;
613
+ const session = usSessionState(now);
614
+ const closedToday = close.date === today;
615
+ if (marketState === "POST" ? !closedToday || (session !== "REGULAR" && session !== "POST") : closedToday || session !== "PRE") {
616
+ return false;
617
+ }
618
+ // The open of the session that closed last: today's after the close, the previous one before the open.
619
+ const open = latestRegularSessionOpen(canonical, close.close);
620
+ return open != null && timestampMs >= open;
460
621
  }
461
622
 
462
623
  export function isTimestampStaleForExchangeSession(
@@ -464,9 +625,10 @@ export function isTimestampStaleForExchangeSession(
464
625
  exchange?: string,
465
626
  now = Date.now(),
466
627
  marketState?: MarketState,
628
+ weekendDays?: readonly number[],
467
629
  ): boolean {
468
630
  try {
469
- return isTimestampStaleForExchangeSessionUnsafe(timestampMs, exchange, now, marketState);
631
+ return isTimestampStaleForExchangeSessionUnsafe(timestampMs, exchange, now, marketState, weekendDays);
470
632
  } catch {
471
633
  return true;
472
634
  }
@@ -477,6 +639,7 @@ function isTimestampStaleForExchangeSessionUnsafe(
477
639
  exchange?: string,
478
640
  now = Date.now(),
479
641
  marketState?: MarketState,
642
+ weekendDays?: readonly number[],
480
643
  ): boolean {
481
644
  const canonical = canonicalExchange(exchange);
482
645
  if (!canonical || !Number.isFinite(timestampMs) || !Number.isFinite(now)) return false;
@@ -498,13 +661,13 @@ function isTimestampStaleForExchangeSessionUnsafe(
498
661
  }
499
662
  }
500
663
 
501
- const sessionsBehind = localTradingDaysBetween(canonical, timestampDate, currentDate);
664
+ const sessionsBehind = localTradingDaysBetween(canonical, timestampDate, currentDate, weekendDays);
502
665
  if (sessionsBehind > 1) return true;
503
666
  if (sessionsBehind === 1 && now - timestampMs > OVERNIGHT_CLOSE_MAX_AGE_MS) {
504
667
  // When today is the first session after a weekend or exchange holiday,
505
668
  // the last close stays current until the provider reports the new session.
506
669
  const calendarDaysBehind = isoLocalDateToUtcDay(currentDate)! - isoLocalDateToUtcDay(timestampDate)!;
507
- return !(isLocalTradingDay(canonical, currentDate) && (calendarDaysBehind > 1 || localWeekday(currentDate) === 1));
670
+ return !(isLocalTradingDay(canonical, currentDate, weekendDays) && (calendarDaysBehind > 1 || localWeekday(currentDate) === 1));
508
671
  }
509
672
  return false;
510
673
  }
@@ -1,6 +1,7 @@
1
1
  import type { MarketState, Quote } from "../../types/financials";
2
2
  import { blendHex, colors, priceColor, type ThemeColors } from "../../theme/colors";
3
3
  import { isFiniteNumber } from "../../utils/guards";
4
+ import { canonicalExchange, isKnownExchangeCode } from "../../utils/exchanges";
4
5
  import { quoteTradingDay } from "../quotes/day-range";
5
6
 
6
7
  const CLOSED_CHANGE_MUTING_RATIO = 0.55;
@@ -24,6 +25,9 @@ export interface ActiveQuoteDisplay {
24
25
 
25
26
  export type ExtendedSession = "PRE" | "POST";
26
27
 
28
+ /** What reports call each extended session's line or column. */
29
+ export const EXTENDED_SESSION_LABELS: Record<ExtendedSession, string> = { PRE: "Pre-Market", POST: "After Hours" };
30
+
27
31
  export interface ExtendedSessionDisplay extends ActiveQuoteDisplay {
28
32
  session: ExtendedSession;
29
33
  }
@@ -105,31 +109,14 @@ export function marketChangeColor(change: number | undefined, state?: MarketStat
105
109
  return blendHex(directionalColor, colors.textDim, CLOSED_CHANGE_MUTING_RATIO);
106
110
  }
107
111
 
108
- /** Short exchange display name */
112
+ /**
113
+ * The venue's code as a listing key names it (EPA, JPX), from the app's one
114
+ * venue list, so the code a pane shows is the one to type after the symbol.
115
+ * A venue the list does not know keeps the name it came with.
116
+ */
109
117
  export function exchangeShortName(exchangeName?: string, fullExchangeName?: string): string {
110
- if (!exchangeName && !fullExchangeName) return "";
111
118
  const name = exchangeName || fullExchangeName || "";
112
- // Common market data exchange abbreviations
113
- const map: Record<string, string> = {
114
- NMS: "NASDAQ", NGM: "NASDAQ", NCM: "NASDAQ", NAS: "NASDAQ",
115
- NYQ: "NYSE", NYS: "NYSE",
116
- PCX: "ARCA", NYSEArca: "ARCA", "NYSE Arca": "ARCA", ASE: "AMEX",
117
- HKG: "HKEX",
118
- TYO: "TYO",
119
- LSE: "LSE",
120
- ASX: "ASX",
121
- SGX: "SGX",
122
- KSC: "KRX", KOE: "KOSDAQ",
123
- TAI: "TWSE",
124
- SHH: "SSE", SHZ: "SZSE",
125
- PAR: "EURONEXT", AMS: "EURONEXT", BRU: "EURONEXT",
126
- GER: "XETRA",
127
- OSL: "OSE",
128
- BOM: "BSE", NSI: "NSE",
129
- SAO: "B3",
130
- JPX: "TYO",
131
- };
132
- return map[name] || name;
119
+ return isKnownExchangeCode(name) ? canonicalExchange(name) : name;
133
120
  }
134
121
 
135
122
  /**
@@ -278,11 +265,48 @@ export function getExtendedSessionDisplay(quote: Quote | null | undefined): Exte
278
265
  return { session: "POST", price, change, changePercent: (change / close) * 100 };
279
266
  }
280
267
 
268
+ /**
269
+ * A quote's headline and extended print as flat figures, for a report row or
270
+ * an export: price, change and changePercent are the regular session's
271
+ * (getRegularSessionDisplay), the extended fields the pre-market or
272
+ * after-hours print measured from its close (getExtendedSessionDisplay), all
273
+ * null when there is none.
274
+ */
275
+ export function getQuoteSessionFields(quote: Quote | null | undefined) {
276
+ const headline = getRegularSessionDisplay(quote);
277
+ const extended = getExtendedSessionDisplay(quote);
278
+ return {
279
+ price: headline?.price ?? null,
280
+ change: headline?.change ?? null,
281
+ changePercent: headline?.changePercent ?? null,
282
+ extendedSession: extended?.session ?? null,
283
+ extendedPrice: extended?.price ?? null,
284
+ extendedChange: extended?.change ?? null,
285
+ extendedChangePercent: extended?.changePercent ?? null,
286
+ };
287
+ }
288
+
281
289
  /** The extended display only while its session is open: the pre-market or the after-hours session. */
282
290
  function getOpenExtendedSessionDisplay(quote: Quote | null | undefined): ExtendedSessionDisplay | null {
283
291
  return quote?.marketState === "PRE" || quote?.marketState === "POST" ? getExtendedSessionDisplay(quote) : null;
284
292
  }
285
293
 
294
+ /**
295
+ * The regular session alone, for a board that never shows extended trading:
296
+ * the live quote while the session trades, then the completed session's close
297
+ * and its move (getCompletedRegularSessionDisplay). Null outside the session
298
+ * when the quote cannot say which close that is, rather than an extended
299
+ * print or a flat move standing in for one. A quote that does not say its
300
+ * session is read as the regular one, as getRegularSessionDisplay does.
301
+ */
302
+ export function getRegularSessionMoveDisplay(quote: Quote | null | undefined): ActiveQuoteDisplay | null {
303
+ if (!quote) return null;
304
+ if (quote.marketState == null || quote.marketState === "REGULAR") {
305
+ return { price: quote.price, change: quote.change, changePercent: quote.changePercent };
306
+ }
307
+ return getCompletedRegularSessionDisplay(quote);
308
+ }
309
+
286
310
  /**
287
311
  * The move a board of tiles colors by: the open pre-market or after-hours
288
312
  * session's, from the regular close, otherwise the day's regular session.
@@ -292,3 +316,15 @@ export function getSessionMoveDisplay(
292
316
  ): (ActiveQuoteDisplay & { session?: ExtendedSession }) | null {
293
317
  return getOpenExtendedSessionDisplay(quote) ?? getRegularSessionDisplay(quote);
294
318
  }
319
+
320
+ /**
321
+ * getSessionMoveDisplay for a board that marks an extended move on each tile
322
+ * (the heat map): while a quote says nothing has traded in the open session
323
+ * yet (extendedSessionPrint false), its extended figures are the close
324
+ * carried forward, not a flat print, so the regular session stands.
325
+ */
326
+ export function getTradedSessionMoveDisplay(
327
+ quote: Quote | null | undefined,
328
+ ): (ActiveQuoteDisplay & { session?: ExtendedSession }) | null {
329
+ return quote?.extendedSessionPrint === false ? getRegularSessionDisplay(quote) : getSessionMoveDisplay(quote);
330
+ }
@@ -0,0 +1,69 @@
1
+ import { parseFuturesGeneric } from "../utils/futures-generic";
2
+
3
+ /** A US-listed fund whose options track an instrument that has none of its own. */
4
+ export interface ListedOptionsAlternative {
5
+ symbol: string;
6
+ name: string;
7
+ }
8
+
9
+ /**
10
+ * Futures roots with no option chain here, and the listed fund whose options
11
+ * are the nearest stand-in. One table for every surface that says so.
12
+ */
13
+ const FUTURES_ALTERNATIVES: Readonly<Record<string, ListedOptionsAlternative>> = {
14
+ GC: { symbol: "GLD", name: "SPDR Gold Shares" },
15
+ SI: { symbol: "SLV", name: "iShares Silver Trust" },
16
+ HG: { symbol: "CPER", name: "United States Copper Index Fund" },
17
+ PL: { symbol: "PPLT", name: "abrdn Physical Platinum Shares" },
18
+ PA: { symbol: "PALL", name: "abrdn Physical Palladium Shares" },
19
+ CL: { symbol: "USO", name: "United States Oil Fund" },
20
+ BZ: { symbol: "BNO", name: "United States Brent Oil Fund" },
21
+ NG: { symbol: "UNG", name: "United States Natural Gas Fund" },
22
+ LTH: { symbol: "LIT", name: "Global X Lithium & Battery Tech ETF" },
23
+ UX: { symbol: "URA", name: "Global X Uranium ETF" },
24
+ ZC: { symbol: "CORN", name: "Teucrium Corn Fund" },
25
+ ZW: { symbol: "WEAT", name: "Teucrium Wheat Fund" },
26
+ ZS: { symbol: "SOYB", name: "Teucrium Soybean Fund" },
27
+ ES: { symbol: "SPY", name: "SPDR S&P 500 ETF" },
28
+ NQ: { symbol: "QQQ", name: "Invesco QQQ Trust" },
29
+ YM: { symbol: "DIA", name: "SPDR Dow Jones Industrial Average ETF" },
30
+ RTY: { symbol: "IWM", name: "iShares Russell 2000 ETF" },
31
+ ZB: { symbol: "TLT", name: "iShares 20+ Year Treasury Bond ETF" },
32
+ ZN: { symbol: "IEF", name: "iShares 7-10 Year Treasury Bond ETF" },
33
+ "6E": { symbol: "FXE", name: "Invesco CurrencyShares Euro Trust" },
34
+ "6J": { symbol: "FXY", name: "Invesco CurrencyShares Japanese Yen Trust" },
35
+ BTC: { symbol: "IBIT", name: "iShares Bitcoin Trust" },
36
+ ETH: { symbol: "ETHA", name: "iShares Ethereum Trust" },
37
+ };
38
+
39
+ const MONTH_CODE_CONTRACT = /^([A-Z0-9]{1,3}?)[FGHJKMNQUVXZ]\d{1,4}$/;
40
+
41
+ /** The futures root a symbol names: GC=F, GCZ26 and the generic GC1 all give GC. */
42
+ function futuresRoot(symbol: string): string | null {
43
+ const ticker = symbol.trim().toUpperCase().replace(/[.:][A-Z]+$/, "");
44
+ if (ticker.endsWith("=F")) {
45
+ const body = ticker.slice(0, -2);
46
+ return FUTURES_ALTERNATIVES[body] ? body : MONTH_CODE_CONTRACT.exec(body)?.[1] ?? body;
47
+ }
48
+ const generic = parseFuturesGeneric(ticker);
49
+ if (generic) return generic.root;
50
+ const contract = MONTH_CODE_CONTRACT.exec(ticker)?.[1];
51
+ return contract && FUTURES_ALTERNATIVES[contract] ? contract : null;
52
+ }
53
+
54
+ /** The listed fund whose options stand in for an instrument with no chain, if there is one. */
55
+ export function listedOptionsAlternative(symbol: string): ListedOptionsAlternative | null {
56
+ const root = futuresRoot(symbol);
57
+ return root ? FUTURES_ALTERNATIVES[root] ?? null : null;
58
+ }
59
+
60
+ /** Whether an options request failed because nothing lists options on the instrument. */
61
+ export function isOptionsUnavailableError(error: unknown): boolean {
62
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
63
+ return /\boptions provider available for\b/i.test(message);
64
+ }
65
+
66
+ /** "Options are not available for GC=F.": the dead end itself, before any follow-up. */
67
+ export function optionsUnavailableTitle(symbol: string): string {
68
+ return `Options are not available for ${symbol.trim().toUpperCase()}.`;
69
+ }
@@ -1,15 +1,22 @@
1
- // Published full-day closures (weekend dates omitted) for Asia-Pacific venues,
1
+ // Published full-day closures (weekend dates omitted) for Asia-Pacific venues and EGX,
2
2
  // not a holiday-rule engine. A year a venue has not published is unknown, not
3
3
  // open: every weekday of it reads as a session. Half-day sessions (HKEX and
4
4
  // SGX eves, ASX's 14:10 closes) are not modelled. Checked 2026-10-09:
5
5
  // KRX, also KOSDAQ: http://open.krx.co.kr/contents/MKD/01/0110/01100305/MKD01100305.jsp
6
6
  // TWSE, whose closures TPEx shares: https://www.twse.com.tw/en/trading/holiday.html
7
7
  // (2027 not yet published; 12 and 13 Feb 2026 are clearing-only days without trading)
8
+ // BHB closes on the dates its own daily closes skip in 2026, which match the holidays it lists
9
+ // (some moved, as its list warns), and on National Day, 16 and 17 Dec. Its week is Sunday to Thursday.
8
10
  // HKEX: https://www.hkex.com.hk/-/media/HKEX-Market/Services/Circulars-and-Notices/Participant-and-Members-Circulars/SEHK/2025/ce_SEHK_CT_075_2025.pdf
9
11
  // and https://www.hkex.com.hk/-/media/HKEX-Market/Services/Circulars-and-Notices/Participant-and-Members-Circulars/SEHK/2026/ce_SEHK_CT_077_2026.pdf
10
12
  // SGX closes on Singapore's gazetted public holidays, one on a Sunday moving to the Monday:
11
13
  // https://www.sgx.com/stock-exchange/trading and https://www.mom.gov.sg/employment-practices/public-holidays
14
+ // MSX closes on the holidays its site lists (msx.om exchange holidays, read 10 Oct 2026).
15
+ // Its week is Sunday to Thursday.
12
16
  // ASX: https://www.asx.com.au/markets/market-resources/trading-hours-calendar/cash-market-trading-hours/trading-calendar
17
+ // EGX closes on Egypt's public holidays, often moved to the Thursday of their
18
+ // week (Armed Forces Day, Tuesday 6 Oct 2026, to Thursday 8 Oct, by the
19
+ // exchange's statement of 5 Oct). Its week is Sunday to Thursday.
13
20
  const KRX_CLOSURES: Record<number, readonly string[]> = {
14
21
  2026: [
15
22
  "01-01", "02-16", "02-17", "02-18", "03-02", "05-01", "05-05", "05-25", "06-03",
@@ -34,6 +41,12 @@ export const PUBLISHED_APAC_CLOSURES: Readonly<Record<string, Record<number, rea
34
41
  KOSDAQ: KRX_CLOSURES,
35
42
  TWSE: TWSE_CLOSURES,
36
43
  TPEX: TWSE_CLOSURES,
44
+ BHB: {
45
+ 2026: [
46
+ "01-01", "03-22", "03-23", "03-24", "05-03", "05-26", "05-27", "05-28", "05-31", "06-16", "06-25", "06-28",
47
+ "08-25", "12-16", "12-17",
48
+ ],
49
+ },
37
50
  HKEX: {
38
51
  2026: [
39
52
  "01-01", "02-17", "02-18", "02-19", "04-03", "04-06", "04-07", "05-01", "05-25",
@@ -48,10 +61,19 @@ export const PUBLISHED_APAC_CLOSURES: Readonly<Record<string, Record<number, rea
48
61
  2026: ["01-01", "02-17", "02-18", "04-03", "05-01", "05-27", "06-01", "08-10", "11-09", "12-25"],
49
62
  2027: ["01-01", "02-08", "03-10", "03-26", "05-17", "05-20", "08-09", "10-28"],
50
63
  },
64
+ MSX: {
65
+ 2026: ["01-15", "01-18", "03-19", "03-22", "03-23", "05-26", "05-27", "05-28", "06-18", "08-27", "11-25", "11-26"],
66
+ },
51
67
  ASX: {
52
68
  2026: ["01-01", "01-26", "04-03", "04-06", "06-08", "12-25", "12-28"],
53
69
  2027: ["01-01", "01-26", "03-26", "03-29", "06-14", "12-27", "12-28"],
54
70
  },
71
+ EGX: {
72
+ 2026: [
73
+ "01-01", "01-07", "01-29", "03-19", "03-22", "03-23", "04-12", "04-13", "05-07",
74
+ "05-26", "05-27", "05-28", "05-31", "06-18", "07-02", "07-23", "08-27", "10-08",
75
+ ],
76
+ },
55
77
  };
56
78
 
57
79
  /** True only for a published full-day closure; unpublished years are unknown, not open. */