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
@@ -2,25 +2,45 @@ import { saveConfig } from "../../../../data/config/store";
2
2
  import { withConfigData, withMarketData } from "../../../../cli/scoped-context";
3
3
  import { countCollectionTickers, findWatchlist } from "../../../../cli/helpers";
4
4
  import { slugifyName } from "../../../../utils/slugify";
5
- import { resolveTickerForCli } from "../../../../cli/ticker-resolution";
5
+ import { resolveCliTicker } from "../../../../cli/ticker-resolution";
6
6
  import { takeOption } from "../../../../cli/commands/command-utils";
7
- import { EXCHANGE_OPTION, loadSavedListing, requireListingArg, savedListingName } from "../../../../cli/listing-arg";
7
+ import { EXCHANGE_OPTION, ListingArgError, loadSavedListing, requireListingArg, savedListingName } from "../../../../cli/listing-arg";
8
8
  import {
9
9
  cliStyles,
10
10
  renderSection,
11
11
  renderStats,
12
12
  renderTable,
13
13
  } from "../../../../utils/cli-output";
14
+ import type { AppConfig } from "../../../../types/config";
14
15
  import type { CliCommandContext, CliCommandDef } from "../../../../types/plugin";
16
+ import type { Watchlist } from "../../../../types/ticker";
17
+ import type { ConfigContext, MarketContext } from "../../../../cli/types";
15
18
  import {
16
19
  addTickerToWatchlist,
17
20
  deleteWatchlist as deleteWatchlistConfig,
18
21
  removeTickerFromWatchlist as removeWatchlistMembership,
19
22
  } from "../mutations";
20
23
  import { showCollection } from "./render";
21
- import { listingFields } from "./shared";
24
+ import { listingFields, takeCollectionName } from "./shared";
25
+ import { addSymbols, FILE_OPTION, printSymbolRows, removeSymbols, requireSymbolList, retryNotice, SYMBOL_LIST_HELP } from "./bulk-symbols";
22
26
  import { CLI_COMMAND_GROUPS } from "../../../../cli/help";
23
27
 
28
+ const ADD_USAGE = "Usage: gloomberb watchlist add <watchlist> <symbols...> [--file <path>]";
29
+ const REMOVE_USAGE = "Usage: gloomberb watchlist remove <watchlist> <symbols...> [--file <path>]";
30
+
31
+ /** The watchlist the leading arguments name and the symbols after it; fails naming the watchlists there are. */
32
+ function requireWatchlistArgs(config: AppConfig, args: readonly string[], usage: string, ctx: CliCommandContext): { watchlist: Watchlist; rest: string[] } {
33
+ if (args.length === 0) ctx.fail(usage);
34
+ const match = takeCollectionName(args, config.watchlists);
35
+ if (!match) {
36
+ ctx.fail(
37
+ `Watchlist "${args[0]}" was not found.`,
38
+ config.watchlists.length > 0 ? `Watchlists: ${config.watchlists.map((entry) => entry.name).join(", ")}` : undefined,
39
+ );
40
+ }
41
+ return { watchlist: match.collection, rest: match.rest };
42
+ }
43
+
24
44
  async function createWatchlist(name: string, ctx: CliCommandContext) {
25
45
  await withConfigData(ctx, async ({ config }) => {
26
46
  const trimmedName = name.trim();
@@ -58,47 +78,83 @@ async function deleteWatchlist(name: string, ctx: CliCommandContext) {
58
78
  });
59
79
  }
60
80
 
61
- async function addTickerToWatchlistCommand(watchlistName: string, symbol: string, exchange: string | undefined, ctx: CliCommandContext) {
62
- await withMarketData(ctx, async ({ config, store, dataProvider }) => {
63
- const watchlist = findWatchlist(config, watchlistName);
64
- if (!watchlist) ctx.fail(`Watchlist "${watchlistName}" was not found.`);
65
-
66
- try {
67
- const ticker = await resolveTickerForCli(symbol, store, dataProvider, exchange);
68
- const result = addTickerToWatchlist(ticker, watchlist.id);
69
- // Name the listing that was stored: SAN:EPA is not the SAN that a bare SAN means.
70
- const saved = savedListingName(ticker);
71
- const data = { changed: result.changed, ...listingFields(saved), watchlist: watchlist.name };
72
- if (!result.changed) {
73
- ctx.printResult({ data }, { text: () => cliStyles.warning(`${saved.label} is already in "${watchlist.name}".`) });
74
- return;
75
- }
76
-
77
- await store.saveTicker(result.ticker);
78
- ctx.printResult({ data }, { text: () => cliStyles.success(`Added ${saved.label} to "${watchlist.name}".`) });
79
- } catch (error) {
80
- ctx.fail(error instanceof Error ? error.message : `Failed to add ${symbol} to "${watchlist.name}".`);
81
+ async function addTickerToWatchlistCommand(watchlist: Watchlist, symbol: string, exchange: string | undefined, ctx: CliCommandContext, { store, dataProvider }: MarketContext) {
82
+ try {
83
+ // A bare symbol is stored on the listing `quote` reads it as, and the notes say which.
84
+ const { ticker, notes } = await resolveCliTicker(symbol, store, dataProvider, exchange, {
85
+ retry: (key) => `gloomberb watchlist add ${watchlist.name} ${key}`,
86
+ });
87
+ const result = addTickerToWatchlist(ticker, watchlist.id);
88
+ // Name the listing that was stored: SAN:EPA is not the SAN that a bare SAN means.
89
+ const saved = savedListingName(ticker);
90
+ const data = { changed: result.changed, ...listingFields(saved), watchlist: watchlist.name };
91
+ const warnings = notes.length > 0 ? notes : undefined;
92
+ if (!result.changed) {
93
+ ctx.printResult({ data, warnings }, { text: () => cliStyles.warning(`${saved.label} is already in "${watchlist.name}".`) });
94
+ return;
81
95
  }
96
+
97
+ await store.saveTicker(result.ticker);
98
+ ctx.printResult({ data, warnings }, { text: () => cliStyles.success(`Added ${saved.label} to "${watchlist.name}".`) });
99
+ } catch (error) {
100
+ ctx.fail(
101
+ error instanceof Error ? error.message : `Failed to add ${symbol} to "${watchlist.name}".`,
102
+ error instanceof ListingArgError ? error.details : undefined,
103
+ );
104
+ }
105
+ }
106
+
107
+ async function addToWatchlistCommand(args: string[], file: string | undefined, exchange: string | undefined, ctx: CliCommandContext) {
108
+ await withMarketData(ctx, async (market) => {
109
+ const { watchlist, rest } = requireWatchlistArgs(market.config, args, ADD_USAGE, ctx);
110
+ const list = await requireSymbolList(ctx, rest, file, ADD_USAGE);
111
+ if (list.single) {
112
+ await addTickerToWatchlistCommand(watchlist, list.single, exchange, ctx, market);
113
+ return;
114
+ }
115
+ const rows = await addSymbols({
116
+ symbols: list.symbols,
117
+ exchange,
118
+ store: market.store,
119
+ dataProvider: market.dataProvider,
120
+ onRetry: retryNotice(ctx),
121
+ retry: (key) => `gloomberb watchlist add ${watchlist.name} ${key}`,
122
+ add: (ticker) => addTickerToWatchlist(ticker, watchlist.id),
123
+ });
124
+ printSymbolRows(ctx, rows, { verb: "add", collection: { kind: "watchlist", name: watchlist.name }, repeated: list.repeated });
82
125
  });
83
126
  }
84
127
 
85
- async function removeTickerFromWatchlist(watchlistName: string, symbol: string, exchange: string | undefined, ctx: CliCommandContext) {
128
+ async function removeTickerFromWatchlist(watchlist: Watchlist, symbol: string, exchange: string | undefined, ctx: CliCommandContext, { store }: ConfigContext) {
86
129
  // SAN:EPA and SAN --exchange EPA name the stored listing, which a bare SAN may hold under another venue.
87
130
  const listing = await requireListingArg(symbol, exchange, ctx);
88
- await withConfigData(ctx, async ({ config, store }) => {
89
- const watchlist = findWatchlist(config, watchlistName);
90
- if (!watchlist) ctx.fail(`Watchlist "${watchlistName}" was not found.`);
131
+ const ticker = await loadSavedListing(store, listing);
132
+ if (!ticker) ctx.fail(`Ticker "${listing.key}" was not found in your local data.`);
133
+ const saved = savedListingName(ticker);
134
+ const result = removeWatchlistMembership(ticker, watchlist.id);
135
+ if (!result.changed) ctx.fail(`${saved.key} is not in "${watchlist.name}".`);
91
136
 
92
- const ticker = await loadSavedListing(store, listing);
93
- if (!ticker) ctx.fail(`Ticker "${listing.key}" was not found in your local data.`);
94
- const saved = savedListingName(ticker);
95
- const result = removeWatchlistMembership(ticker, watchlist.id);
96
- if (!result.changed) ctx.fail(`${saved.key} is not in "${watchlist.name}".`);
137
+ await store.saveTicker(result.ticker);
138
+ ctx.printResult({ data: { changed: true, ...listingFields(saved), watchlist: watchlist.name } }, {
139
+ text: () => cliStyles.success(`Removed ${saved.label} from "${watchlist.name}".`),
140
+ });
141
+ }
97
142
 
98
- await store.saveTicker(result.ticker);
99
- ctx.printResult({ data: { changed: true, ...listingFields(saved), watchlist: watchlist.name } }, {
100
- text: () => cliStyles.success(`Removed ${saved.label} from "${watchlist.name}".`),
143
+ async function removeFromWatchlistCommand(args: string[], file: string | undefined, exchange: string | undefined, ctx: CliCommandContext) {
144
+ await withConfigData(ctx, async (context) => {
145
+ const { watchlist, rest } = requireWatchlistArgs(context.config, args, REMOVE_USAGE, ctx);
146
+ const list = await requireSymbolList(ctx, rest, file, REMOVE_USAGE);
147
+ if (list.single) {
148
+ await removeTickerFromWatchlist(watchlist, list.single, exchange, ctx, context);
149
+ return;
150
+ }
151
+ const rows = await removeSymbols({
152
+ symbols: list.symbols,
153
+ exchange,
154
+ store: context.store,
155
+ remove: (ticker) => removeWatchlistMembership(ticker, watchlist.id),
101
156
  });
157
+ printSymbolRows(ctx, rows, { verb: "remove", collection: { kind: "watchlist", name: watchlist.name }, repeated: list.repeated });
102
158
  });
103
159
  }
104
160
 
@@ -154,16 +210,28 @@ export const watchlistCliCommand: CliCommandDef = {
154
210
  "watchlist show <name>",
155
211
  "watchlist create <name>",
156
212
  "watchlist delete <name>",
157
- "watchlist add <watchlist> <symbol>",
158
- "watchlist remove <watchlist> <symbol>",
213
+ "watchlist add <watchlist> <symbols...> [--file <path>]",
214
+ "watchlist remove <watchlist> <symbols...> [--file <path>]",
159
215
  ],
160
- options: [EXCHANGE_OPTION],
161
- examples: ["watchlist show Growth", "watchlist create Growth", "watchlist add Growth NVDA", "watchlist add Growth SAN:EPA"],
216
+ options: [EXCHANGE_OPTION, FILE_OPTION],
217
+ examples: [
218
+ "watchlist show Growth",
219
+ "watchlist create Growth",
220
+ "watchlist add Growth NVDA",
221
+ "watchlist add Growth SAN:EPA",
222
+ "watchlist add Growth NVDA AMD,AVGO",
223
+ "watchlist add Growth --file holdings.csv",
224
+ "watchlist show Growth --csv",
225
+ ],
226
+ sections: [SYMBOL_LIST_HELP],
162
227
  },
163
228
  execute: async (rawArgs, ctx) => {
164
229
  const args = [...rawArgs];
165
230
  const exchange = takeOption(args, "--exchange");
231
+ const hasFile = args.some((arg) => arg === "--file" || arg.startsWith("--file="));
232
+ const file = hasFile ? takeOption(args, "--file") ?? "" : undefined;
166
233
  const action = args[0];
234
+ if (file != null && action !== "add" && action !== "remove") ctx.fail(`--file is an option of watchlist add and remove, not watchlist ${action ?? "list"}.`, ADD_USAGE);
167
235
 
168
236
  if (!action || action === "list") {
169
237
  await listWatchlists(ctx);
@@ -192,21 +260,26 @@ export const watchlistCliCommand: CliCommandDef = {
192
260
  }
193
261
 
194
262
  if (action === "add") {
195
- const symbol = args.at(-1);
196
- const name = args.slice(1, -1).join(" ");
197
- if (!name || !symbol) ctx.fail("Usage: gloomberb watchlist add <watchlist> <ticker>");
198
- await addTickerToWatchlistCommand(name!, symbol!, exchange, ctx);
263
+ await addToWatchlistCommand(args.slice(1), file, exchange, ctx);
199
264
  return;
200
265
  }
201
266
 
202
267
  if (action === "remove") {
203
- const symbol = args.at(-1);
204
- const name = args.slice(1, -1).join(" ");
205
- if (!name || !symbol) ctx.fail("Usage: gloomberb watchlist remove <watchlist> <ticker>");
206
- await removeTickerFromWatchlist(name!, symbol!, exchange, ctx);
268
+ await removeFromWatchlistCommand(args.slice(1), file, exchange, ctx);
207
269
  return;
208
270
  }
209
271
 
272
+ if (action === "import") {
273
+ // A list of symbols is what add reads; say how, with the user's own list and file.
274
+ const rest = args.slice(1);
275
+ const path = /\.\w+$/.test(rest.at(-1) ?? "") ? rest.at(-1)! : null;
276
+ const name = (path ? rest.slice(0, -1) : rest).join(" ") || "<watchlist>";
277
+ ctx.fail(
278
+ `watchlist has no import. To add the symbols in ${path ?? "a file"}, run: gloomberb watchlist add ${/\s/.test(name) ? `"${name}"` : name} --file ${path ?? "<path>"}`,
279
+ ADD_USAGE,
280
+ );
281
+ }
282
+
210
283
  await showCollection(args.join(" "), ctx);
211
284
  },
212
285
  };
@@ -49,7 +49,7 @@ import {
49
49
  portfolioPnlPercent,
50
50
  signedPositionDirection,
51
51
  type PortfolioPositionPnl,
52
- } from "./position-metrics";
52
+ } from "../../../portfolio/position-metrics";
53
53
  import { isFiniteNumber } from "../../../utils/guards";
54
54
  import {
55
55
  allocationFigures,
@@ -17,7 +17,7 @@ import { createRowValueCache, type RowValueCache } from "../../../components/ui/
17
17
  import { objectVersion } from "../../../utils/object-version";
18
18
  import { columnContextVersion } from "./cell-version";
19
19
  import { getColumnValue, getSortValue, type ColumnContext } from "./metrics";
20
- import { getPortfolioPositionMetrics, getPortfolioQuoteDisplay } from "./position-metrics";
20
+ import { getPortfolioPositionMetrics, getPortfolioQuoteDisplay } from "../../../portfolio/position-metrics";
21
21
  import { PORTFOLIO_ROW_MENU_KEYS } from "./row-actions";
22
22
  import { PORTFOLIO_REORDER_THROTTLE_MS } from "./use-throttled-ticker-order";
23
23
  import { useThrottledMemo } from "./use-throttled-memo";
@@ -9,12 +9,17 @@ import type {
9
9
  import type { TickerRecord } from "../../../types/ticker";
10
10
  import { formatNumber, formatPercentRaw } from "../../../utils/format";
11
11
  import {
12
+ collectionQuoteHeadline,
13
+ extendedQuoteFields,
14
+ extendedSessionsOf,
12
15
  findCollection,
16
+ listingLabel,
13
17
  loadCollectionQuotes,
14
18
  valuePortfolioAllocation,
15
19
  valuePortfolioPositions,
16
20
  type CollectionMatch,
17
21
  } from "./cli/render";
22
+ import { EXTENDED_SESSION_LABELS, type ExtendedSession } from "../../../market-data/market/status";
18
23
  import {
19
24
  BROKER_ACCOUNT_MISSING_NOTE,
20
25
  CASH_SYMBOL,
@@ -23,9 +28,10 @@ import {
23
28
  formatAllocationWeight,
24
29
  formatTradeUnits,
25
30
  } from "./allocation";
26
- import { currencyMinorDigits, formatMarketPrice, formatMarketQuantity } from "../../../market-data/market/format";
31
+ import { currencyPriceMinDigits, formatMarketPrice, formatMarketQuantity } from "../../../market-data/market/format";
27
32
  import { resolvePortfolioTotalsCurrency } from "./summary/totals";
28
33
  import { quoteFreshnessFields } from "../shared/report-freshness";
34
+ import { importedFromText } from "./imported-from";
29
35
 
30
36
  const DEFAULT_ROW_LIMIT = 50;
31
37
  const MAX_ROW_LIMIT = 200;
@@ -50,7 +56,7 @@ const tradeUnits = (value: unknown, row: HeadlessPaneRow) => (
50
56
  /** Money per unit at the currency's minor digits: $230.00, not 230. */
51
57
  const unitMoney = (currencyKey: string) => (value: unknown, row: HeadlessPaneRow) => (
52
58
  typeof value === "number"
53
- ? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits: Math.min(2, currencyMinorDigits(textOf(row[currencyKey]))) })
59
+ ? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits: currencyPriceMinDigits(textOf(row[currencyKey])) })
54
60
  : formatNumber(undefined)
55
61
  );
56
62
 
@@ -61,6 +67,7 @@ function textOf(value: unknown): string | undefined {
61
67
  const POSITION_COLUMNS: HeadlessPaneColumn[] = [
62
68
  { key: "symbol", header: "Ticker" },
63
69
  { key: "name", header: "Name" },
70
+ { key: "exchange", header: "Exchange" },
64
71
  { key: "shares", header: "Qty", align: "right", format: quantity },
65
72
  { key: "avgCost", header: "Avg Cost", align: "right", format: unitMoney("positionCurrency"), description: "Per unit, in the position's currency." },
66
73
  { key: "price", header: "Last", align: "right", format: unitMoney("priceCurrency"), description: "In the quote's currency." },
@@ -79,6 +86,26 @@ const TARGET_COLUMNS: HeadlessPaneColumn[] = [
79
86
  { key: "tradeValue", header: "Trade Value", align: "right", format: signedAmount, description: "The trade in the portfolio's currency." },
80
87
  ];
81
88
 
89
+ /** The pre-market or after-hours print and its move from the regular close, for the rows that have one. */
90
+ function extendedColumn(session: ExtendedSession): HeadlessPaneColumn {
91
+ return {
92
+ key: "extendedPrice",
93
+ header: EXTENDED_SESSION_LABELS[session],
94
+ align: "right",
95
+ format: (value, row) => row.extendedSession === session && typeof value === "number"
96
+ ? `${unitMoney("priceCurrency")(value, row)} ${percent(row.extendedChangePercent)}`
97
+ : formatNumber(undefined),
98
+ description: "Measured from the regular close in Last.",
99
+ };
100
+ }
101
+
102
+ /** `columns` with an extended column after Chg for each session a row has a print for. */
103
+ function withExtendedColumns(columns: HeadlessPaneColumn[], sessions: readonly ExtendedSession[]): HeadlessPaneColumn[] {
104
+ if (sessions.length === 0) return columns;
105
+ const at = columns.findIndex((column) => column.key === "changePercent") + 1;
106
+ return [...columns.slice(0, at), ...sessions.map(extendedColumn), ...columns.slice(at)];
107
+ }
108
+
82
109
  const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
83
110
  { key: "symbol", header: "Ticker" },
84
111
  { key: "name", header: "Name" },
@@ -88,6 +115,25 @@ const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
88
115
  { key: "changePercent", header: "Chg", align: "right", format: percent },
89
116
  ];
90
117
 
118
+ /**
119
+ * `columns` with the text report's Ticker column naming each listing as
120
+ * `portfolio show` does (SAN:EPA, SAN:NYSE), not by the key it is stored under,
121
+ * which leaves two listings of one symbol looking alike. `textFormat` is text
122
+ * only: JSON and CSV keep the stored key in `symbol`, and the rows stay keyed
123
+ * by it.
124
+ */
125
+ function withListingLabels(columns: HeadlessPaneColumn[], tickers: readonly TickerRecord[]): HeadlessPaneColumn[] {
126
+ const labels = new Map(tickers.map((ticker) => [ticker.metadata.ticker, listingLabel(ticker)]));
127
+ return columns.map((column) => column.key !== "symbol" ? column : {
128
+ ...column,
129
+ textFormat: (value, row) => {
130
+ // The cash line is not a listing, even when a ticker is called CASH; its row carries no exchange.
131
+ if (typeof value !== "string" || !("exchange" in row)) return textOf(value) ?? formatNumber(undefined);
132
+ return labels.get(value) ?? value;
133
+ },
134
+ });
135
+ }
136
+
91
137
  function finite(value: unknown): number | null {
92
138
  return typeof value === "number" && Number.isFinite(value) ? value : null;
93
139
  }
@@ -154,8 +200,9 @@ async function portfolioHoldings(
154
200
  const gross = held.reduce((sum, entry) => sum + Math.abs(finite(entry.row.marketValue) ?? 0), 0);
155
201
  const sum = (key: string) => held.reduce((total, entry) => total + (finite(entry.row[key]) ?? 0), 0);
156
202
  const seen = new Set<string>();
203
+ const extendedSessions = extendedSessionsOf(held.map(({ extended }) => extended?.session));
157
204
  const rows = held
158
- .map(({ ticker, activeQuote, row }) => {
205
+ .map(({ ticker, headline, extended, row }) => {
159
206
  const marketValue = finite(row.marketValue);
160
207
  // A ticker held in several lots carries its allocation on its first row.
161
208
  const figures = seen.has(ticker.metadata.ticker) ? undefined : allocationBySymbol.get(ticker.metadata.ticker);
@@ -170,9 +217,11 @@ async function portfolioHoldings(
170
217
  shares: finite(row.shares),
171
218
  avgCost: finite(row.avgCost),
172
219
  positionCurrency: row.positionCurrency ?? null,
220
+ // Last and Chg are the regular session; market value and P&L are at the live price.
173
221
  price: finite(row.quotePrice),
174
222
  priceCurrency: row.quoteCurrency ?? null,
175
- changePercent: finite(activeQuote?.changePercent),
223
+ changePercent: finite(headline?.changePercent),
224
+ ...extendedQuoteFields(extended),
176
225
  marketValue,
177
226
  unrealizedPnl: finite(row.unrealizedPnl),
178
227
  weight: figures?.weight ?? null,
@@ -206,7 +255,9 @@ async function portfolioHoldings(
206
255
  const broker = !!(target.portfolio.brokerId || target.portfolio.brokerInstanceId);
207
256
  const showTargets = allocation.targetSum != null;
208
257
  const targetNote = describeTargetSum(allocation.targetSum);
258
+ const imported = importedFromText(target.portfolio);
209
259
  const notices = [
260
+ ...(imported ? [imported] : []),
210
261
  ...(rows.length > limit
211
262
  ? [`${rows.length - limit} more position${rows.length - limit === 1 ? "" : "s"} not shown; totals include every position.`]
212
263
  : []),
@@ -216,7 +267,10 @@ async function portfolioHoldings(
216
267
 
217
268
  return {
218
269
  freshness: { source: broker ? "Your broker account and Gloom Cloud" : "Local portfolio and Gloom Cloud" },
219
- columns: showTargets ? [...POSITION_COLUMNS, ...TARGET_COLUMNS] : POSITION_COLUMNS,
270
+ columns: withListingLabels(
271
+ withExtendedColumns(showTargets ? [...POSITION_COLUMNS, ...TARGET_COLUMNS] : POSITION_COLUMNS, extendedSessions),
272
+ tickers,
273
+ ),
220
274
  rows: shown,
221
275
  complete: unavailable.length === 0,
222
276
  ...(unavailable.length
@@ -224,6 +278,7 @@ async function portfolioHoldings(
224
278
  : {}),
225
279
  metadata: {
226
280
  collection: { kind: "portfolio", id: target.id, name: target.name, broker },
281
+ ...(target.portfolio.importedFrom ? { importedFrom: target.portfolio.importedFrom } : {}),
227
282
  currency,
228
283
  positions: rows.length,
229
284
  totals: {
@@ -254,21 +309,27 @@ async function watchlistHoldings(
254
309
  ctx.signal.throwIfAborted();
255
310
  const rows = tickers.map((ticker) => {
256
311
  const quote = quotes.get(ticker.metadata.ticker);
312
+ // As the watchlist pane shows it: the regular session, then any extended print from its close.
313
+ const { headline, extended } = collectionQuoteHeadline(quote);
257
314
  return {
258
315
  ...quoteFreshnessFields(quote),
259
316
  updatedAt: quote?.lastUpdated ?? null,
260
317
  symbol: ticker.metadata.ticker,
261
318
  name: ticker.metadata.name ?? null,
262
319
  exchange: ticker.metadata.exchange || null,
263
- price: finite(quote?.price),
320
+ price: finite(headline?.price ?? quote?.price),
264
321
  priceCurrency: quote?.currency ?? null,
265
- changePercent: finite(quote?.changePercent),
322
+ changePercent: finite(headline ? headline.changePercent : quote?.changePercent),
323
+ ...extendedQuoteFields(extended),
266
324
  };
267
325
  });
268
326
  const shown = rows.slice(0, limit);
269
327
  return {
270
328
  freshness: { source: "Local watchlist and Gloom Cloud" },
271
- columns: WATCHLIST_COLUMNS,
329
+ columns: withListingLabels(
330
+ withExtendedColumns(WATCHLIST_COLUMNS, extendedSessionsOf(shown.map((row) => row.extendedSession))),
331
+ tickers,
332
+ ),
272
333
  rows: shown,
273
334
  metadata: {
274
335
  collection: { kind: "watchlist", id: target.id, name: target.name },
@@ -288,7 +349,7 @@ async function watchlistHoldings(
288
349
  export const collectionHoldingsHeadless: HeadlessPaneDefinition<"rows"> = {
289
350
  shape: "rows",
290
351
  description:
291
- "Positions held in a portfolio, broker or manual: symbol, quantity, average cost, last price, market value, unrealized P&L and weight of the total with cash, largest first, then the cash line and totals. With target weights set, each row adds its target, drift and the trade to reach it. For a watchlist, its tickers with quotes. Takes a portfolio or watchlist ID; the first portfolio when omitted.",
352
+ "Positions held in a portfolio, broker or manual: symbol, exchange, shares, average cost, last price, market value, unrealized P&L and weight of the total with cash, largest first, then the cash line and totals. With target weights set, each row adds its target, drift and the trade to reach it. For a watchlist, its tickers with quotes. Takes a portfolio or watchlist ID; the first portfolio when omitted.",
292
353
  discovery: {
293
354
  dataRequirements: ["Local portfolios, watchlists and synced broker positions; current quotes"],
294
355
  limitations: ["Unrealized P&L on current positions; excludes realized trades, distributions and cash flows"],
@@ -0,0 +1,8 @@
1
+ import type { Portfolio } from "../../../types/ticker";
2
+
3
+ /** One line naming the filing an imported portfolio comes from, as `portfolio show`, `fn PF` and the import print it. */
4
+ export function importedFromText(portfolio: Pick<Portfolio, "importedFrom">): string | null {
5
+ const source = portfolio.importedFrom;
6
+ if (!source) return null;
7
+ return `Weights from ${source.name}'s 13F for ${source.period}, filed ${source.filed}; not your holdings.`;
8
+ }
@@ -1,5 +1,6 @@
1
1
  import type { AnalystResearchData, Fundamentals, Quote } from "../../../types/financials";
2
2
  import { hasLikelyQuoteUnitMismatch } from "../../../utils/currency-units";
3
+ import { priceEarningsEps } from "../../../utils/fundamentals";
3
4
  import { selectMarketCapitalization, type MarketCapitalization } from "../../../utils/market-capitalization";
4
5
  import { priceEarningsOnEarnings, type PriceEarnings } from "../../../utils/price-earnings";
5
6
 
@@ -54,9 +55,12 @@ function repriceMultiple(
54
55
  return price / perShare;
55
56
  }
56
57
 
57
- /** Trailing P/E over the current price; not meaningful when the trailing EPS is zero or a loss. */
58
+ /**
59
+ * Trailing P/E over the current price; not meaningful when the trailing EPS is zero or a loss. An EPS in another
60
+ * currency than the price is repriced at the rate the served P/E converted it at.
61
+ */
58
62
  export function liveTrailingPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): PriceEarnings | undefined {
59
- return priceEarningsOnEarnings(repriceMultiple(fundamentals?.trailingPE, fundamentals?.eps, quote, fundamentals), fundamentals?.eps);
63
+ return priceEarningsOnEarnings(repriceMultiple(fundamentals?.trailingPE, priceEarningsEps(fundamentals), quote, fundamentals), fundamentals?.eps);
60
64
  }
61
65
 
62
66
  /** Forward P/E over the current price; not meaningful when the forward EPS behind it is zero or a loss. */
@@ -88,7 +88,7 @@ import { useThrottledTickerOrder } from "../use-throttled-ticker-order";
88
88
  import { useThrottledMemo } from "../use-throttled-memo";
89
89
  import { useColumnClock } from "../use-column-clock";
90
90
  import { liveMarketCapitalization } from "../live-valuation";
91
- import { hasUnknownOptionMultiplier } from "../position-metrics";
91
+ import { hasUnknownOptionMultiplier } from "../../../../portfolio/position-metrics";
92
92
  import {
93
93
  allocationTotal,
94
94
  buildPortfolioAllocation,
@@ -126,6 +126,8 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
126
126
 
127
127
  const [streamWindow, setStreamWindow] = useState({ start: 0, end: 24 });
128
128
  const [quickAddFocused, setQuickAddFocused] = useState(false);
129
+ // Bumped by the empty table's "+ ticker" button to open the add row.
130
+ const [quickAddRequest, setQuickAddRequest] = useState(0);
129
131
 
130
132
  const {
131
133
  cursorSymbol,
@@ -612,6 +614,7 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
612
614
  return null;
613
615
  }, [activeCollectionId, config, currentPortfolio]);
614
616
  const showQuickAdd = !!(activeCollectionId && activeCollectionEntry && quickAddCollectionKind);
617
+ const requestQuickAdd = useCallback(() => setQuickAddRequest((count) => count + 1), []);
615
618
  const quickAddHeight = showQuickAdd ? 1 : 0;
616
619
  const selectedFinancials = cursorSymbol ? financialsMap.get(cursorSymbol) : undefined;
617
620
  const selectedCap = liveMarketCapitalization(selectedFinancials?.quote, selectedFinancials?.fundamentals);
@@ -636,6 +639,7 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
636
639
  width={width}
637
640
  onAdded={handleTickerAdded}
638
641
  onFocusChange={setQuickAddFocused}
642
+ focusRequest={quickAddRequest}
639
643
  />
640
644
  ) : null;
641
645
 
@@ -674,6 +678,7 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
674
678
  visibleRangeBuffer={3}
675
679
  resetScrollKey={activeCollectionId}
676
680
  onRowActivate={handleRowActivate}
681
+ onAddTicker={showQuickAdd ? requestQuickAdd : undefined}
677
682
  rootHeight={contentHeight}
678
683
  />
679
684
  ) : (
@@ -30,6 +30,8 @@ import {
30
30
  } from "./resolution";
31
31
 
32
32
  const QUICK_ADD_DEBOUNCE_MS = 300;
33
+ /** The pane key that opens the add row, as its footer hint shows it. */
34
+ export const QUICK_ADD_KEY = "a";
33
35
 
34
36
  export type { QuickAddCollectionKind } from "./resolution";
35
37
 
@@ -101,6 +103,7 @@ export function QuickAddTickerInput({
101
103
  width,
102
104
  onAdded,
103
105
  onFocusChange,
106
+ focusRequest = 0,
104
107
  }: {
105
108
  collectionId: string;
106
109
  collectionKind: QuickAddCollectionKind;
@@ -109,6 +112,12 @@ export function QuickAddTickerInput({
109
112
  width: number;
110
113
  onAdded: (symbol: string) => void;
111
114
  onFocusChange?: (focused: boolean) => void;
115
+ /**
116
+ * Bumped by a control outside the row, such as the empty table's
117
+ * "+ ticker" button, to open it. A click there focuses the pane in the same
118
+ * press, so the row opens once the pane is focused.
119
+ */
120
+ focusRequest?: number;
112
121
  }) {
113
122
  const dispatch = useAppDispatch();
114
123
  const { notify } = usePluginAppActions();
@@ -132,6 +141,13 @@ export function QuickAddTickerInput({
132
141
  setInputFocused(false);
133
142
  }, []);
134
143
 
144
+ const handledFocusRequestRef = useRef(focusRequest);
145
+ useEffect(() => {
146
+ if (focusRequest === handledFocusRequestRef.current || !focused) return;
147
+ handledFocusRequestRef.current = focusRequest;
148
+ focusInput();
149
+ }, [focusInput, focusRequest, focused]);
150
+
135
151
  const resetInput = useCallback(() => {
136
152
  setInputValue("");
137
153
  setValidation(IDLE_VALIDATION);
@@ -350,7 +366,7 @@ export function QuickAddTickerInput({
350
366
 
351
367
  // The row shows only its placeholder, so the footer says which key reaches it.
352
368
  usePaneFooter("portfolio-list:quick-add", () => ({
353
- hints: inputFocused ? [] : [{ id: "add", key: "a", label: "dd", onPress: focusInput }],
369
+ hints: inputFocused ? [] : [{ id: "add", key: QUICK_ADD_KEY, label: "dd", onPress: focusInput }],
354
370
  }), [focusInput, inputFocused]);
355
371
 
356
372
  return (
@@ -14,7 +14,7 @@ import {
14
14
  resolvePortfolioPositionPnl,
15
15
  portfolioPnlPercent,
16
16
  type PortfolioPositionPnl,
17
- } from "../position-metrics";
17
+ } from "../../../../portfolio/position-metrics";
18
18
 
19
19
  /** A position lot valued from a current quote, in the totals currency. */
20
20
  interface PricedPortfolioLot {
@@ -1,4 +1,5 @@
1
1
  import { useCallback, useMemo, useRef } from "react";
2
+ import { QUICK_ADD_KEY } from "./quick-add";
2
3
  import {
3
4
  TickerListTableView,
4
5
  type DataTableKeyEvent,
@@ -15,7 +16,7 @@ import type { TickerRecord } from "../../../types/ticker";
15
16
  import { objectVersion } from "../../../utils/object-version";
16
17
  import { columnContextVersion } from "./cell-version";
17
18
  import { getColumnValue, type ColumnContext } from "./metrics";
18
- import { portfolioPnlLabel } from "./position-metrics";
19
+ import { portfolioPnlLabel } from "../../../portfolio/position-metrics";
19
20
  import { PORTFOLIO_ROW_MENU_KEYS } from "./row-actions";
20
21
 
21
22
  export type { QuoteFlashDirection };
@@ -98,6 +99,7 @@ export function PortfolioTickerTable({
98
99
  visibleRangeBuffer,
99
100
  resetScrollKey,
100
101
  onRowActivate,
102
+ onAddTicker,
101
103
  rootHeight,
102
104
  }: {
103
105
  columns: ColumnConfig[];
@@ -117,6 +119,8 @@ export function PortfolioTickerTable({
117
119
  visibleRangeBuffer?: number;
118
120
  resetScrollKey?: unknown;
119
121
  onRowActivate?: (ticker: TickerRecord) => void;
122
+ /** Opens the add row; the empty table offers it as a button. */
123
+ onAddTicker?: () => void;
120
124
  rootHeight?: number;
121
125
  }) {
122
126
  const cellCacheRef = useRef(createRowValueCache<string, ReturnType<typeof getColumnValue>>(5000));
@@ -175,6 +179,8 @@ export function PortfolioTickerTable({
175
179
  resetScrollKey={resetScrollKey}
176
180
  onRowActivate={onRowActivate}
177
181
  rowMenuAccelerators={PORTFOLIO_ROW_MENU_KEYS}
182
+ onAddTicker={onAddTicker}
183
+ addTickerShortcut={onAddTicker ? QUICK_ADD_KEY : undefined}
178
184
  rootHeight={rootHeight}
179
185
  />
180
186
  );
@@ -2,6 +2,8 @@ import { apiClient } from "../../../api-client";
2
2
  import type { PowerBoard, PowerDetail, PowerFilter, PowerHistory, PowerProject } from "../../../api-client/power";
3
3
  import { createPluginCache } from "../../../data/plugin-cache";
4
4
  import { loadCloudResource, unavailableOnServer } from "../shared/cloud-resource";
5
+ import { powerTickerScopes, type PowerTab, type PowerTickerScope } from "./model";
6
+ import { powerQuery } from "./query";
5
7
 
6
8
  const cacheOptions = { source: "gloom-cloud", schemaVersion: 1, policy: { staleMs: 60 * 60_000, expireMs: 30 * 86_400_000 } };
7
9
  export const powerBoardCache = createPluginCache<PowerBoard>({ ...cacheOptions, kind: "power-board" });
@@ -88,6 +90,20 @@ export async function fetchAllPowerHistory(filter: PowerFilter, client: Pick<Pow
88
90
  }
89
91
  return { ...first, points, hasMore: false, nextOffset: null };
90
92
  }
93
+ /**
94
+ * How many records name a ticker on each other tab, for a tab that has none:
95
+ * one single-row page per scope, read for its total, which a free preview
96
+ * reports in full. A scope that fails to answer has no total rather than
97
+ * failing the tab it explains.
98
+ */
99
+ export async function fetchPowerTickerScopes(symbol: string, tab: PowerTab, context: string,
100
+ client: Pick<PowerApi, "getCloudPowerBoard"> = apiClient, signal?: AbortSignal): Promise<PowerTickerScope[]> {
101
+ return Promise.all(powerTickerScopes(tab, context).map((scope) => {
102
+ const count = () => fetchPowerBoard({ ...powerQuery({ tab: scope.tab, context: scope.context }, symbol), limit: 1 }, client, signal).then((board) => board.total);
103
+ // One retry: a count is cheap, and the first of several at once is the one most often refused.
104
+ return count().catch(() => count()).then((total) => ({ ...scope, total }), () => ({ ...scope, total: null }));
105
+ }));
106
+ }
91
107
  const key = (query: unknown, scope: string) => `${scope}:${JSON.stringify(query)}`;
92
108
  export const loadPowerBoard = (filter: PowerFilter, scope: string, force = false, signal?: AbortSignal) =>
93
109
  loadCloudResource(powerBoardCache, key(filter, scope), () => fetchPowerBoard(filter, apiClient, signal), { force, validate: validatePowerBoard });