gloomberb 0.16.4 → 0.16.6

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 (852) hide show
  1. package/README.md +14 -91
  2. package/package.json +5 -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 +16 -15
  11. package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
  12. package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
  13. package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
  14. package/src/api-client/central-bank-rates.ts +6 -1
  15. package/src/api-client/chat.ts +26 -0
  16. package/src/api-client/credit-boards.ts +2 -0
  17. package/src/api-client/data.ts +73 -3
  18. package/src/api-client/earnings.ts +6 -0
  19. package/src/api-client/europe-energy.ts +106 -0
  20. package/src/api-client/futures-curve.ts +56 -0
  21. package/src/api-client/index.ts +13 -1
  22. package/src/api-client/market-discovery.ts +13 -1
  23. package/src/api-client/normalizers.ts +32 -0
  24. package/src/api-client/paths.ts +7 -0
  25. package/src/api-client/perps.ts +8 -0
  26. package/src/api-client/request.ts +9 -2
  27. package/src/api-client/research-activity.ts +15 -10
  28. package/src/api-client/socket.ts +29 -0
  29. package/src/api-client/themes.ts +22 -1
  30. package/src/api-client/types.ts +78 -2
  31. package/src/api-client/yield-curves.ts +8 -0
  32. package/src/app/global-shortcuts.ts +50 -2
  33. package/src/app/keybindings/actions.ts +12 -1
  34. package/src/app/pane-runtime/plugin-bindings.ts +2 -2
  35. package/src/app/pane-runtime/ticker-open-runtime.ts +16 -6
  36. package/src/app/runtime/desktop-deeplink.ts +10 -5
  37. package/src/app/runtime/startup.ts +1 -1
  38. package/src/app.tsx +6 -0
  39. package/src/architecture/core-builtin-allowlist.json +8 -26
  40. package/src/ask-gloom/pane-context.ts +114 -0
  41. package/src/ask-gloom/pane-request.ts +70 -0
  42. package/src/ask-gloom/pane-text.ts +201 -0
  43. package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
  44. package/src/capabilities/chart-series.ts +19 -2
  45. package/src/capabilities/factories.ts +1 -0
  46. package/src/cli/central-bank-events.ts +23 -0
  47. package/src/cli/command-options.ts +17 -5
  48. package/src/cli/commands/crypto-hints.ts +35 -2
  49. package/src/cli/commands/fred-series.ts +146 -0
  50. package/src/cli/commands/market.ts +501 -115
  51. package/src/cli/commands/news-hints.ts +62 -0
  52. package/src/cli/commands/news-search.ts +53 -0
  53. package/src/cli/commands/options-leaps.ts +5 -2
  54. package/src/cli/commands/overview.ts +132 -26
  55. package/src/cli/commands/remote.ts +2 -1
  56. package/src/cli/commands/search.ts +317 -13
  57. package/src/cli/commands/system.ts +55 -8
  58. package/src/cli/commands/ticker.ts +155 -18
  59. package/src/cli/context.ts +45 -14
  60. package/src/cli/desktop-pane-shot.ts +76 -7
  61. package/src/cli/earnings-calendar.ts +71 -0
  62. package/src/cli/errors.ts +7 -5
  63. package/src/cli/exit-codes.ts +8 -0
  64. package/src/cli/export-source.ts +58 -0
  65. package/src/cli/freshness.ts +18 -7
  66. package/src/cli/glossary.ts +483 -0
  67. package/src/cli/help.ts +10 -0
  68. package/src/cli/helpers.ts +2 -5
  69. package/src/cli/history-rows.ts +118 -7
  70. package/src/cli/index-roots.ts +7 -0
  71. package/src/cli/index.ts +29 -9
  72. package/src/cli/known-gaps.ts +84 -0
  73. package/src/cli/listing-arg.ts +551 -97
  74. package/src/cli/not-a-ticker.ts +24 -9
  75. package/src/cli/pane-functions/access-gate.ts +13 -2
  76. package/src/cli/pane-functions/capabilities.ts +4 -3
  77. package/src/cli/pane-functions/catalog.ts +214 -40
  78. package/src/cli/pane-functions/data.ts +42 -8
  79. package/src/cli/pane-functions/discovery.ts +1 -0
  80. package/src/cli/pane-functions/dom.ts +37 -8
  81. package/src/cli/pane-functions/freshness.ts +393 -49
  82. package/src/cli/pane-functions/function-help.ts +31 -15
  83. package/src/cli/pane-functions/headless.ts +98 -30
  84. package/src/cli/pane-functions/index.ts +101 -19
  85. package/src/cli/pane-functions/market-session.ts +22 -8
  86. package/src/cli/pane-functions/options.ts +71 -22
  87. package/src/cli/pane-functions/report-notices.ts +25 -7
  88. package/src/cli/pane-functions/report.ts +15 -8
  89. package/src/cli/pane-functions/resolver.ts +74 -19
  90. package/src/cli/pane-functions/screenshot.ts +250 -27
  91. package/src/cli/perpetual-contract.ts +60 -0
  92. package/src/cli/registry.ts +3 -1
  93. package/src/cli/report-tables.ts +26 -7
  94. package/src/cli/result.ts +45 -11
  95. package/src/cli/series-search.ts +111 -0
  96. package/src/cli/staged-tickers.ts +52 -0
  97. package/src/cli/symbol-args.ts +27 -0
  98. package/src/cli/symbol-list.ts +154 -0
  99. package/src/cli/symbol-rows.ts +154 -0
  100. package/src/cli/ticker-resolution.ts +311 -27
  101. package/src/cli/types.ts +5 -0
  102. package/src/components/chart/composite/axis-overlays.tsx +14 -3
  103. package/src/components/chart/composite/composite-chart.tsx +71 -11
  104. package/src/components/chart/composite/crosshair-readout.tsx +150 -0
  105. package/src/components/chart/composite/downsample.ts +1 -1
  106. package/src/components/chart/composite/format.ts +29 -0
  107. package/src/components/chart/composite/interactions.ts +9 -2
  108. package/src/components/chart/composite/legend.tsx +100 -33
  109. package/src/components/chart/composite/panel-bitmap.ts +70 -35
  110. package/src/components/chart/composite/panel-labels.ts +18 -17
  111. package/src/components/chart/composite/panel-series.ts +1 -0
  112. package/src/components/chart/composite/panel-surface.tsx +46 -21
  113. package/src/components/chart/composite/price-axis-labels.tsx +3 -1
  114. package/src/components/chart/composite/rasterizer.ts +50 -8
  115. package/src/components/chart/composite/scene.ts +2 -1
  116. package/src/components/chart/composite/time-scale.ts +26 -9
  117. package/src/components/chart/composite/types.ts +18 -0
  118. package/src/components/chart/composite/use-composite-viewport.ts +30 -2
  119. package/src/components/chart/native/raster/crosshair.ts +8 -3
  120. package/src/components/chart/native/raster/primitives.ts +85 -21
  121. package/src/components/chart/native/surface/manager.ts +33 -8
  122. package/src/components/chart/surface3d/chart.tsx +1 -1
  123. package/src/components/command-bar/action-runtime.ts +1 -1
  124. package/src/components/command-bar/commands/collection-list.ts +210 -0
  125. package/src/components/command-bar/commands/collection.ts +40 -1
  126. package/src/components/command-bar/commands/direct/index.ts +4 -0
  127. package/src/components/command-bar/commands/registry.ts +8 -0
  128. package/src/components/command-bar/panel/index.tsx +11 -3
  129. package/src/components/command-bar/panel/runtime.ts +3 -0
  130. package/src/components/command-bar/panel/types.ts +2 -0
  131. package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
  132. package/src/components/command-bar/routes/root/provider-search.ts +4 -3
  133. package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
  134. package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
  135. package/src/components/command-bar/routing/actions.ts +1 -1
  136. package/src/components/command-bar/workflow/tickers.ts +42 -17
  137. package/src/components/layout/detached-pane-shell.tsx +68 -39
  138. package/src/components/layout/floating-pane.tsx +10 -1
  139. package/src/components/layout/header.tsx +25 -5
  140. package/src/components/layout/missing-pane.tsx +3 -3
  141. package/src/components/layout/pane/capture-stamp.ts +41 -0
  142. package/src/components/layout/pane/capture-status.ts +12 -0
  143. package/src/components/layout/pane/content.tsx +7 -13
  144. package/src/components/layout/pane/footer/index.tsx +6 -2
  145. package/src/components/layout/pane/footer/keyboard.ts +3 -0
  146. package/src/components/layout/pane/footer/model.ts +41 -1
  147. package/src/components/layout/pane/header.tsx +50 -1
  148. package/src/components/layout/pane/index.tsx +21 -3
  149. package/src/components/layout/pane/sidebar.tsx +88 -21
  150. package/src/components/layout/shell/active-drag.ts +21 -5
  151. package/src/components/layout/shell/cursor-occlusion.ts +2 -1
  152. package/src/components/layout/shell/drag/index.ts +39 -9
  153. package/src/components/layout/shell/drag/live.ts +61 -51
  154. package/src/components/layout/shell/drag/runtime.ts +54 -12
  155. package/src/components/layout/shell/index.tsx +84 -65
  156. package/src/components/layout/shell/menu.ts +14 -1
  157. package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
  158. package/src/components/layout/shell/pane/actions.ts +32 -10
  159. package/src/components/layout/shell/pane/ask.ts +131 -0
  160. package/src/components/layout/shell/pane/capture.ts +162 -0
  161. package/src/components/layout/shell/pane/layers.tsx +218 -50
  162. package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
  163. package/src/components/layout/shell/shortcuts.ts +21 -4
  164. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
  165. package/src/components/markdown-text.tsx +62 -20
  166. package/src/components/metric-treemap/heat-surface.tsx +8 -1
  167. package/src/components/onboarding/account-step/form-panel.tsx +1 -1
  168. package/src/components/onboarding/account-step/index.tsx +1 -1
  169. package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
  170. package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
  171. package/src/components/onboarding/onboarding-keyboard.ts +1 -1
  172. package/src/components/onboarding/onboarding-wizard.tsx +2 -2
  173. package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
  174. package/src/components/onboarding/wizard-account.ts +2 -2
  175. package/src/components/pane-template-wizard.tsx +9 -1
  176. package/src/components/price-selector-dialog.tsx +11 -2
  177. package/src/components/reader/article-reader.tsx +642 -0
  178. package/src/components/reader/article-text.ts +527 -0
  179. package/src/components/sign-in-gate.tsx +3 -3
  180. package/src/components/ticker/list-table-view.tsx +43 -2
  181. package/src/components/ui/action-row.tsx +2 -1
  182. package/src/components/ui/button.tsx +7 -1
  183. package/src/components/ui/choice-dialog.tsx +6 -4
  184. package/src/components/ui/confirm-dialog.tsx +28 -18
  185. package/src/components/ui/data-table/index.tsx +18 -6
  186. package/src/components/ui/data-table/opentui/index.tsx +37 -6
  187. package/src/components/ui/data-table/types.ts +12 -0
  188. package/src/components/ui/dialog-actions.tsx +64 -0
  189. package/src/components/ui/display.tsx +17 -3
  190. package/src/components/ui/frame.tsx +35 -2
  191. package/src/components/ui/icon.tsx +6 -1
  192. package/src/components/ui/query-bar.tsx +10 -1
  193. package/src/components/ui/text-prompt-dialog.tsx +11 -9
  194. package/src/data/cached-query.ts +2 -0
  195. package/src/data/config/store/migrations.ts +7 -0
  196. package/src/data/config/store/normalize.ts +7 -2
  197. package/src/data/config/store/portfolio-as-of-column.ts +57 -0
  198. package/src/data/ticker-repository.ts +5 -0
  199. package/src/data/ticker-store.ts +15 -0
  200. package/src/docs/content.ts +215 -0
  201. package/src/docs/load.ts +139 -0
  202. package/src/docs/requests.ts +39 -0
  203. package/src/docs/snapshot.chunk.ts +8 -0
  204. package/src/docs/snapshot.json +7555 -0
  205. package/src/docs/topics.ts +216 -0
  206. package/src/i18n/es.ts +65 -5
  207. package/src/i18n/ja.ts +65 -5
  208. package/src/i18n/ko.ts +65 -5
  209. package/src/i18n/zh-cn.ts +65 -5
  210. package/src/i18n/zh-tw.ts +65 -5
  211. package/src/layout/desks.ts +1 -1
  212. package/src/layout/pane-manager/dock-tree.ts +18 -0
  213. package/src/layout/pane-manager/index.ts +1 -0
  214. package/src/layout-marketplace/gallery.tsx +1 -1
  215. package/src/market-data/coordinator/chart.ts +10 -4
  216. package/src/market-data/coordinator/index.ts +6 -3
  217. package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
  218. package/src/market-data/futures-contract.ts +151 -0
  219. package/src/market-data/hooks.tsx +10 -2
  220. package/src/market-data/market/format.ts +39 -21
  221. package/src/market-data/market/freshness.ts +84 -20
  222. package/src/market-data/market/session-close-note.ts +3 -2
  223. package/src/market-data/market/status.ts +19 -23
  224. package/src/market-data/published-apac-sessions.ts +23 -1
  225. package/src/market-data/quotes/contributions.ts +5 -0
  226. package/src/market-data/quotes/metadata.ts +19 -24
  227. package/src/market-data/quotes/resolution.ts +5 -0
  228. package/src/market-data/quotes/screener-live-quotes.ts +5 -4
  229. package/src/market-data/result-types.ts +2 -0
  230. package/src/notifications/app-notifier.ts +17 -1
  231. package/src/notifications/notification-log.ts +180 -0
  232. package/src/plugins/auto-update-node.ts +2 -2
  233. package/src/plugins/auto-update.ts +2 -2
  234. package/src/plugins/builtin/account-management/index.tsx +1 -0
  235. package/src/plugins/builtin/account-management/model.ts +1 -56
  236. package/src/plugins/builtin/account-management/pane.tsx +6 -4
  237. package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
  238. package/src/plugins/builtin/alerts/catalysts.ts +1 -1
  239. package/src/plugins/builtin/alerts/cli.ts +313 -47
  240. package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
  241. package/src/plugins/builtin/alerts/events.ts +23 -2
  242. package/src/plugins/builtin/alerts/focus.ts +27 -0
  243. package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
  244. package/src/plugins/builtin/alerts/history.ts +2 -0
  245. package/src/plugins/builtin/alerts/index.tsx +47 -11
  246. package/src/plugins/builtin/alerts/pane.tsx +27 -1
  247. package/src/plugins/builtin/alerts/research-builder.ts +8 -3
  248. package/src/plugins/builtin/alerts/research-rules.ts +18 -2
  249. package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
  250. package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
  251. package/src/plugins/builtin/alerts/scheduled.ts +254 -0
  252. package/src/plugins/builtin/alerts/targets.ts +92 -0
  253. package/src/plugins/builtin/analytics/index.tsx +8 -3
  254. package/src/plugins/builtin/analytics/risk-headless.ts +60 -27
  255. package/src/plugins/builtin/analytics/risk-math.ts +91 -27
  256. package/src/plugins/builtin/analytics/risk-model.ts +35 -5
  257. package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
  258. package/src/plugins/builtin/attention/headless.ts +1 -1
  259. package/src/plugins/builtin/attention/index.tsx +2 -0
  260. package/src/plugins/builtin/attention/pane.tsx +3 -1
  261. package/src/plugins/builtin/attention/series.ts +26 -0
  262. package/src/plugins/builtin/awards/headless.ts +88 -18
  263. package/src/plugins/builtin/awards/index.tsx +2 -0
  264. package/src/plugins/builtin/awards/model.ts +41 -1
  265. package/src/plugins/builtin/awards/pane.tsx +22 -13
  266. package/src/plugins/builtin/awards/series.ts +29 -0
  267. package/src/plugins/builtin/backtest/headless.ts +2 -2
  268. package/src/plugins/builtin/bond-calculator/model.ts +2 -1
  269. package/src/plugins/builtin/broker-manager/index.tsx +1 -0
  270. package/src/plugins/builtin/catalysts/headless.ts +1 -1
  271. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  272. package/src/plugins/builtin/cds/client.ts +49 -12
  273. package/src/plugins/builtin/cds/headless.ts +119 -19
  274. package/src/plugins/builtin/cds/index.tsx +3 -1
  275. package/src/plugins/builtin/cds/model.ts +214 -32
  276. package/src/plugins/builtin/cds/pane.tsx +58 -14
  277. package/src/plugins/builtin/cds/series.ts +19 -0
  278. package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
  279. package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
  280. package/src/plugins/builtin/central-bank-rates/index.tsx +3 -1
  281. package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
  282. package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
  283. package/src/plugins/builtin/central-bank-rates/series.ts +36 -0
  284. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +193 -255
  285. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
  286. package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
  287. package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
  288. package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
  289. package/src/plugins/builtin/chart-composer/headless.ts +70 -5
  290. package/src/plugins/builtin/chart-composer/index.tsx +15 -3
  291. package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
  292. package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
  293. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
  294. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
  295. package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
  296. package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
  297. package/src/plugins/builtin/chat/content/composer.tsx +5 -1
  298. package/src/plugins/builtin/chat/content/footer.tsx +12 -0
  299. package/src/plugins/builtin/chat/content/index.tsx +89 -5
  300. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
  301. package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
  302. package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
  303. package/src/plugins/builtin/chat/content/scroll.ts +127 -27
  304. package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
  305. package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
  306. package/src/plugins/builtin/chat/content/types.ts +1 -0
  307. package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
  308. package/src/plugins/builtin/chat/controller/index.ts +123 -1
  309. package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
  310. package/src/plugins/builtin/chat/controller/messages.ts +7 -2
  311. package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
  312. package/src/plugins/builtin/chat/controller/send.ts +61 -1
  313. package/src/plugins/builtin/chat/controller/state.ts +8 -0
  314. package/src/plugins/builtin/chat/ghost-user.ts +20 -0
  315. package/src/plugins/builtin/chat/index.tsx +23 -5
  316. package/src/plugins/builtin/chat/layout.ts +78 -5
  317. package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
  318. package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
  319. package/src/plugins/builtin/chat/message/header.tsx +16 -4
  320. package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
  321. package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
  322. package/src/plugins/builtin/chat/message/render-state.ts +18 -2
  323. package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
  324. package/src/plugins/builtin/chat/message/types.ts +12 -0
  325. package/src/plugins/builtin/chat/reactions.ts +197 -0
  326. package/src/plugins/builtin/chat/share/flow.tsx +87 -0
  327. package/src/plugins/builtin/chat/share/targets.ts +27 -0
  328. package/src/plugins/builtin/chat/status-widget.tsx +6 -3
  329. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
  330. package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
  331. package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
  332. package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
  333. package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
  334. package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
  335. package/src/plugins/builtin/cloud/askg/model.ts +27 -8
  336. package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
  337. package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
  338. package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
  339. package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
  340. package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
  341. package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
  342. package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
  343. package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
  344. package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
  345. package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
  346. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
  347. package/src/plugins/builtin/cloud/plugin.tsx +19 -2
  348. package/src/plugins/builtin/cloud/team/model.ts +5 -0
  349. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  350. package/src/plugins/builtin/cloud/team/store.ts +8 -3
  351. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
  352. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
  353. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
  354. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
  355. package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
  356. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  357. package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
  358. package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
  359. package/src/plugins/builtin/company-attention/headless.ts +21 -7
  360. package/src/plugins/builtin/company-attention/index.tsx +2 -0
  361. package/src/plugins/builtin/company-attention/model.ts +26 -7
  362. package/src/plugins/builtin/company-attention/pane.tsx +12 -9
  363. package/src/plugins/builtin/company-attention/series.ts +52 -0
  364. package/src/plugins/builtin/company-kpis/headless.ts +97 -10
  365. package/src/plugins/builtin/company-kpis/model.ts +24 -2
  366. package/src/plugins/builtin/company-kpis/pane.tsx +17 -16
  367. package/src/plugins/builtin/composite-plugins.ts +19 -13
  368. package/src/plugins/builtin/connections/index.ts +1 -0
  369. package/src/plugins/builtin/cot/headless.ts +1 -1
  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/cpi/headless.ts +3 -3
  374. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
  375. package/src/plugins/builtin/credit-boards/client.ts +6 -2
  376. package/src/plugins/builtin/credit-boards/headless.ts +108 -31
  377. package/src/plugins/builtin/credit-boards/index.tsx +2 -0
  378. package/src/plugins/builtin/credit-boards/model.ts +11 -1
  379. package/src/plugins/builtin/credit-boards/series.ts +66 -0
  380. package/src/plugins/builtin/credit-conditions/client.ts +12 -9
  381. package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
  382. package/src/plugins/builtin/credit-conditions/index.tsx +18 -9
  383. package/src/plugins/builtin/credit-conditions/model.ts +19 -11
  384. package/src/plugins/builtin/credit-conditions/series.ts +16 -0
  385. package/src/plugins/builtin/credit-documents/headless.ts +33 -3
  386. package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
  387. package/src/plugins/builtin/crypto-board/headless.ts +2 -3
  388. package/src/plugins/builtin/crypto-board/index.tsx +2 -0
  389. package/src/plugins/builtin/crypto-board/model.ts +12 -0
  390. package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
  391. package/src/plugins/builtin/crypto-board/series.ts +48 -0
  392. package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
  393. package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
  394. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  395. package/src/plugins/builtin/debt-maturities/series.ts +45 -0
  396. package/src/plugins/builtin/dividend-yield/client.ts +3 -0
  397. package/src/plugins/builtin/dividend-yield/headless.ts +7 -4
  398. package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
  399. package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
  400. package/src/plugins/builtin/dividend-yield/series.ts +20 -0
  401. package/src/plugins/builtin/dividend-yield/types.ts +2 -0
  402. package/src/plugins/builtin/docs/blocks.tsx +181 -0
  403. package/src/plugins/builtin/docs/index.tsx +68 -0
  404. package/src/plugins/builtin/docs/pane.tsx +426 -0
  405. package/src/plugins/builtin/docs/targets.ts +72 -0
  406. package/src/plugins/builtin/docs/use-docs.ts +60 -0
  407. package/src/plugins/builtin/doe/headless.ts +12 -8
  408. package/src/plugins/builtin/doe/index.tsx +2 -0
  409. package/src/plugins/builtin/doe/series.ts +62 -0
  410. package/src/plugins/builtin/earnings/client.ts +3 -2
  411. package/src/plugins/builtin/earnings/format.ts +1 -5
  412. package/src/plugins/builtin/earnings/headless.ts +58 -6
  413. package/src/plugins/builtin/earnings/history-model.ts +15 -1
  414. package/src/plugins/builtin/earnings/history-table.ts +13 -2
  415. package/src/plugins/builtin/earnings/history.tsx +7 -3
  416. package/src/plugins/builtin/earnings/index.tsx +9 -0
  417. package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
  418. package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
  419. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
  420. package/src/plugins/builtin/econ/fred-catalog.ts +198 -0
  421. package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
  422. package/src/plugins/builtin/econ/index.tsx +2 -0
  423. package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
  424. package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
  425. package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
  426. package/src/plugins/builtin/equity-screener/headless.ts +3 -3
  427. package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
  428. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
  429. package/src/plugins/builtin/exposure/drivers.ts +13 -0
  430. package/src/plugins/builtin/exposure/headless.ts +205 -13
  431. package/src/plugins/builtin/exposure/holdings.ts +1 -1
  432. package/src/plugins/builtin/exposure/index.tsx +1 -0
  433. package/src/plugins/builtin/exposure/model.ts +23 -3
  434. package/src/plugins/builtin/exposure/pane.tsx +14 -12
  435. package/src/plugins/builtin/fear-greed/index.tsx +18 -10
  436. package/src/plugins/builtin/fear-greed/series.ts +52 -0
  437. package/src/plugins/builtin/futures/index.tsx +43 -3
  438. package/src/plugins/builtin/futures/model.ts +1 -1
  439. package/src/plugins/builtin/futures/returns.ts +1 -1
  440. package/src/plugins/builtin/futures/series.ts +13 -0
  441. package/src/plugins/builtin/futures/table.tsx +1 -1
  442. package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
  443. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  444. package/src/plugins/builtin/futures-curve/headless.ts +71 -10
  445. package/src/plugins/builtin/futures-curve/index.tsx +1 -1
  446. package/src/plugins/builtin/futures-curve/model.ts +66 -11
  447. package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
  448. package/src/plugins/builtin/fx-matrix/client.ts +63 -0
  449. package/src/plugins/builtin/fx-matrix/export.ts +2 -1
  450. package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
  451. package/src/plugins/builtin/fx-matrix/index.tsx +4 -4
  452. package/src/plugins/builtin/gpu/board.tsx +13 -10
  453. package/src/plugins/builtin/gpu/changes.tsx +4 -4
  454. package/src/plugins/builtin/gpu/client.ts +19 -1
  455. package/src/plugins/builtin/gpu/equities.tsx +14 -10
  456. package/src/plugins/builtin/gpu/headless.ts +58 -27
  457. package/src/plugins/builtin/gpu/history.tsx +3 -3
  458. package/src/plugins/builtin/gpu/index.tsx +2 -0
  459. package/src/plugins/builtin/gpu/model.ts +101 -16
  460. package/src/plugins/builtin/gpu/pane.tsx +28 -12
  461. package/src/plugins/builtin/gpu/series.ts +38 -0
  462. package/src/plugins/builtin/help/function-card.tsx +25 -6
  463. package/src/plugins/builtin/help/function-index.ts +2 -0
  464. package/src/plugins/builtin/help/index.tsx +31 -9
  465. package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
  466. package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
  467. package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
  468. package/src/plugins/builtin/holders/client.ts +22 -3
  469. package/src/plugins/builtin/holders/format.ts +18 -3
  470. package/src/plugins/builtin/holders/headless.ts +36 -133
  471. package/src/plugins/builtin/holders/pane.tsx +11 -4
  472. package/src/plugins/builtin/holders/report-header.ts +40 -5
  473. package/src/plugins/builtin/holders/report-rows.ts +240 -0
  474. package/src/plugins/builtin/insider/client.ts +35 -20
  475. package/src/plugins/builtin/insider/headless.ts +41 -11
  476. package/src/plugins/builtin/insider/index.tsx +26 -9
  477. package/src/plugins/builtin/insider/insider-data.ts +10 -0
  478. package/src/plugins/builtin/insider/issuer.ts +49 -0
  479. package/src/plugins/builtin/insider/model.ts +3 -0
  480. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
  481. package/src/plugins/builtin/iv-history/client.ts +20 -6
  482. package/src/plugins/builtin/iv-history/format.ts +9 -0
  483. package/src/plugins/builtin/iv-history/headless.ts +56 -21
  484. package/src/plugins/builtin/iv-history/index.tsx +2 -0
  485. package/src/plugins/builtin/iv-history/model.ts +143 -8
  486. package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
  487. package/src/plugins/builtin/iv-history/series.ts +29 -0
  488. package/src/plugins/builtin/jobs/headless.ts +26 -3
  489. package/src/plugins/builtin/jobs/index.tsx +3 -1
  490. package/src/plugins/builtin/jobs/series.ts +19 -0
  491. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  492. package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
  493. package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
  494. package/src/plugins/builtin/macro-day/client.ts +44 -3
  495. package/src/plugins/builtin/macro-day/headless.ts +13 -10
  496. package/src/plugins/builtin/macro-day/model.ts +56 -10
  497. package/src/plugins/builtin/macro-day/pane.tsx +30 -20
  498. package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
  499. package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
  500. package/src/plugins/builtin/market-heatmap/model.ts +19 -11
  501. package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
  502. package/src/plugins/builtin/market-movers/client.ts +7 -5
  503. package/src/plugins/builtin/market-movers/index.tsx +3 -2
  504. package/src/plugins/builtin/market-movers/model.ts +30 -0
  505. package/src/plugins/builtin/market-movers/screener.ts +31 -0
  506. package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
  507. package/src/plugins/builtin/market-valuation/index.tsx +3 -3
  508. package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
  509. package/src/plugins/builtin/members/headless.ts +8 -3
  510. package/src/plugins/builtin/members/model.ts +31 -3
  511. package/src/plugins/builtin/members/pane.tsx +6 -8
  512. package/src/plugins/builtin/mna/distress/headless.ts +4 -4
  513. package/src/plugins/builtin/mna/headless.ts +18 -6
  514. package/src/plugins/builtin/money-markets/headless.ts +5 -4
  515. package/src/plugins/builtin/money-markets/index.tsx +2 -0
  516. package/src/plugins/builtin/money-markets/series.ts +41 -0
  517. package/src/plugins/builtin/news/index.tsx +0 -2
  518. package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
  519. package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
  520. package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
  521. package/src/plugins/builtin/notes/cli.ts +12 -7
  522. package/src/plugins/builtin/notes/index.tsx +1 -0
  523. package/src/plugins/builtin/options/index.tsx +3 -0
  524. package/src/plugins/builtin/options/view.tsx +1 -1
  525. package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
  526. package/src/plugins/builtin/options-positioning/client.ts +7 -3
  527. package/src/plugins/builtin/options-positioning/headless.ts +4 -3
  528. package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
  529. package/src/plugins/builtin/options-scenario/client.ts +2 -1
  530. package/src/plugins/builtin/options-scenario/headless.ts +1 -0
  531. package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
  532. package/src/plugins/builtin/perps/client.ts +90 -16
  533. package/src/plugins/builtin/perps/equity-row.tsx +52 -17
  534. package/src/plugins/builtin/perps/freshness.ts +66 -0
  535. package/src/plugins/builtin/perps/headless.ts +47 -32
  536. package/src/plugins/builtin/perps/index.tsx +23 -4
  537. package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
  538. package/src/plugins/builtin/perps/model.ts +20 -5
  539. package/src/plugins/builtin/perps/open-market.ts +15 -0
  540. package/src/plugins/builtin/perps/pane.tsx +76 -20
  541. package/src/plugins/builtin/perps/series.ts +76 -0
  542. package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
  543. package/src/plugins/builtin/plugin-marketplace/pane.tsx +73 -67
  544. package/src/plugins/builtin/plugin-module.ts +3 -0
  545. package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
  546. package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
  547. package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
  548. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +161 -0
  549. package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
  550. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +384 -74
  551. package/src/plugins/builtin/portfolio-list/cli/render.ts +437 -71
  552. package/src/plugins/builtin/portfolio-list/cli/shared.ts +21 -4
  553. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +121 -47
  554. package/src/plugins/builtin/portfolio-list/column-values.ts +104 -26
  555. package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
  556. package/src/plugins/builtin/portfolio-list/headless.ts +84 -18
  557. package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
  558. package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
  559. package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
  560. package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
  561. package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
  562. package/src/plugins/builtin/portfolio-list/pane/index.tsx +52 -9
  563. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +33 -11
  564. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
  565. package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
  566. package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
  567. package/src/plugins/builtin/portfolio-list/summary/totals.ts +9 -4
  568. package/src/plugins/builtin/portfolio-list/table.tsx +37 -7
  569. package/src/plugins/builtin/power/client.ts +16 -0
  570. package/src/plugins/builtin/power/evidence.ts +63 -10
  571. package/src/plugins/builtin/power/headless.ts +77 -9
  572. package/src/plugins/builtin/power/index.tsx +28 -3
  573. package/src/plugins/builtin/power/model.ts +73 -2
  574. package/src/plugins/builtin/power/pane.tsx +37 -9
  575. package/src/plugins/builtin/power/prices-client.ts +139 -0
  576. package/src/plugins/builtin/power/prices-headless.ts +137 -0
  577. package/src/plugins/builtin/power/prices-model.ts +103 -0
  578. package/src/plugins/builtin/power/prices.tsx +179 -0
  579. package/src/plugins/builtin/rate-path/headless.ts +46 -18
  580. package/src/plugins/builtin/realized-vol/headless.ts +5 -0
  581. package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
  582. package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
  583. package/src/plugins/builtin/research/event-model.ts +68 -24
  584. package/src/plugins/builtin/research/events-headless.ts +2 -1
  585. package/src/plugins/builtin/research/headless.ts +2 -1
  586. package/src/plugins/builtin/research/index.tsx +2 -0
  587. package/src/plugins/builtin/research-search/article.ts +65 -0
  588. package/src/plugins/builtin/research-search/document-view.tsx +33 -215
  589. package/src/plugins/builtin/research-search/model.ts +0 -9
  590. package/src/plugins/builtin/research-search/pane.tsx +41 -30
  591. package/src/plugins/builtin/research-search/snippet.ts +0 -29
  592. package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
  593. package/src/plugins/builtin/seasonality/client.ts +15 -7
  594. package/src/plugins/builtin/seasonality/headless.ts +36 -12
  595. package/src/plugins/builtin/seasonality/index.tsx +2 -2
  596. package/src/plugins/builtin/seasonality/model.ts +119 -0
  597. package/src/plugins/builtin/seasonality/pane.tsx +108 -37
  598. package/src/plugins/builtin/sec/headless.ts +25 -3
  599. package/src/plugins/builtin/sec/index.tsx +2 -1
  600. package/src/plugins/builtin/series-inventory.ts +93 -0
  601. package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
  602. package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
  603. package/src/plugins/builtin/shared/command-tab.ts +30 -12
  604. package/src/plugins/builtin/shared/earnings-report.ts +55 -0
  605. package/src/plugins/builtin/shared/fred-points.ts +20 -0
  606. package/src/plugins/builtin/shared/free-preview.ts +47 -0
  607. package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
  608. package/src/plugins/builtin/shared/open-description.ts +29 -0
  609. package/src/plugins/builtin/shared/report-freshness.ts +12 -1
  610. package/src/plugins/builtin/shared/series-warning.ts +5 -0
  611. package/src/plugins/builtin/shared/volatility/options.ts +4 -1
  612. package/src/plugins/builtin/short-interest/headless.ts +1 -0
  613. package/src/plugins/builtin/short-interest/index.tsx +2 -0
  614. package/src/plugins/builtin/short-interest/series.ts +36 -0
  615. package/src/plugins/builtin/short-interest/watch-headless.ts +3 -2
  616. package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
  617. package/src/plugins/builtin/short-volume/headless.ts +2 -1
  618. package/src/plugins/builtin/short-volume/index.tsx +2 -0
  619. package/src/plugins/builtin/short-volume/series.ts +23 -0
  620. package/src/plugins/builtin/social-mentions/headless.ts +1 -1
  621. package/src/plugins/builtin/social-mentions/index.tsx +2 -0
  622. package/src/plugins/builtin/social-mentions/series.ts +23 -0
  623. package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
  624. package/src/plugins/builtin/supply-chain/headless.ts +43 -11
  625. package/src/plugins/builtin/supply-chain/model.ts +13 -0
  626. package/src/plugins/builtin/supply-chain/pane.tsx +8 -6
  627. package/src/plugins/builtin/themes/headless.ts +74 -10
  628. package/src/plugins/builtin/themes/model.ts +71 -4
  629. package/src/plugins/builtin/themes/pane.tsx +22 -5
  630. package/src/plugins/builtin/thirteenf/api.ts +1 -0
  631. package/src/plugins/builtin/thirteenf/data.ts +6 -4
  632. package/src/plugins/builtin/thirteenf/headless.ts +217 -36
  633. package/src/plugins/builtin/thirteenf/model.ts +39 -1
  634. package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
  635. package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
  636. package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
  637. package/src/plugins/builtin/thirteenf/types.ts +2 -0
  638. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
  639. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
  640. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
  641. package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
  642. package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
  643. package/src/plugins/builtin/ticker-detail/index.tsx +26 -11
  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 +49 -5
  649. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
  650. package/src/plugins/builtin/time-sales/headless.ts +2 -1
  651. package/src/plugins/builtin/time-sales/index.tsx +2 -1
  652. package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
  653. package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
  654. package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
  655. package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
  656. package/src/plugins/builtin/vol-surface/headless.ts +51 -17
  657. package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
  658. package/src/plugins/builtin/vol-surface/model.ts +39 -6
  659. package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
  660. package/src/plugins/builtin/vol-surface/stored.ts +63 -3
  661. package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
  662. package/src/plugins/builtin/volatility/index.tsx +2 -0
  663. package/src/plugins/builtin/volatility/series.ts +84 -0
  664. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
  665. package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
  666. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
  667. package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
  668. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
  669. package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
  670. package/src/plugins/builtin/world-venue-map/index.ts +2 -1
  671. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +24 -13
  672. package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
  673. package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
  674. package/src/plugins/builtin/world-venue-map/model.ts +56 -19
  675. package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
  676. package/src/plugins/builtin/yield-curve/chart.ts +2 -2
  677. package/src/plugins/builtin/yield-curve/curves.ts +21 -8
  678. package/src/plugins/builtin/yield-curve/headless.ts +71 -18
  679. package/src/plugins/builtin/yield-curve/index.tsx +4 -2
  680. package/src/plugins/builtin/yield-curve/series.ts +86 -0
  681. package/src/plugins/catalog-browser.ts +2 -1
  682. package/src/plugins/installer.ts +2 -2
  683. package/src/plugins/loader.ts +15 -0
  684. package/src/plugins/manager-node.ts +1 -1
  685. package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
  686. package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
  687. package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
  688. package/src/plugins/registry/host-actions.ts +11 -0
  689. package/src/plugins/registry/index.ts +89 -4
  690. package/src/portfolio/collection-name.ts +31 -0
  691. package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
  692. package/src/portfolio/position-value.ts +40 -0
  693. package/src/portfolio/valuation-basis.ts +79 -0
  694. package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
  695. package/src/public/time-series.ts +17 -0
  696. package/src/react/auto-refresh.ts +13 -3
  697. package/src/react/input.ts +33 -1
  698. package/src/react/key-repeat.ts +86 -0
  699. package/src/remote/app-host.tsx +20 -4
  700. package/src/remote/confirm-change.tsx +85 -0
  701. package/src/remote/controller-utils.ts +8 -1
  702. package/src/remote/controller.ts +144 -7
  703. package/src/remote/pane-screenshot.ts +47 -0
  704. package/src/remote/schema.ts +65 -2
  705. package/src/remote/types.ts +30 -0
  706. package/src/remote/watchlist.ts +306 -0
  707. package/src/renderers/browser/main.tsx +4 -3
  708. package/src/renderers/browser/research-entry.ts +4 -2
  709. package/src/renderers/cloudflare/worker.ts +1 -1
  710. package/src/renderers/dom/data-table/frozen-column.ts +3 -1
  711. package/src/renderers/dom/data-table/index.tsx +33 -6
  712. package/src/renderers/dom/data-table/row.tsx +30 -1
  713. package/src/renderers/dom/desktop/control-styles.ts +63 -1
  714. package/src/renderers/dom/desktop/controls.tsx +30 -23
  715. package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
  716. package/src/renderers/dom/desktop/icons.tsx +16 -0
  717. package/src/renderers/dom/dom-ui-host.tsx +3 -0
  718. package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
  719. package/src/renderers/dom/host/box.tsx +8 -0
  720. package/src/renderers/dom/host/chart-surface.tsx +33 -2
  721. package/src/renderers/dom/host/live-frame.ts +6 -2
  722. package/src/renderers/dom/host/overflow-fade.ts +14 -1
  723. package/src/renderers/dom/host/scroll-box.tsx +32 -0
  724. package/src/renderers/dom/host/size-observer.ts +41 -0
  725. package/src/renderers/dom/host/sticky-scroll.ts +128 -0
  726. package/src/renderers/dom/host/style.ts +1 -1
  727. package/src/renderers/dom/host/surface-3d.tsx +19 -7
  728. package/src/renderers/dom/host/surface-fit.ts +406 -0
  729. package/src/renderers/dom/host/text.tsx +1 -1
  730. package/src/renderers/dom/input-host.tsx +1 -0
  731. package/src/renderers/dom/styles.css +102 -5
  732. package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
  733. package/src/renderers/electrobun/bun/index.ts +3 -2
  734. package/src/renderers/electrobun/shared/protocol.ts +1 -1
  735. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +29 -2
  736. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +63 -20
  737. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
  738. package/src/renderers/electrobun/view/main.tsx +5 -3
  739. package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
  740. package/src/renderers/opentui/chart-surface.tsx +1 -0
  741. package/src/renderers/opentui/frame-capture.ts +33 -0
  742. package/src/renderers/opentui/host.tsx +10 -13
  743. package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
  744. package/src/renderers/opentui/pane-image/glyphs.json +1 -0
  745. package/src/renderers/opentui/pane-image/index.ts +107 -0
  746. package/src/renderers/opentui/pane-image/raster.ts +428 -0
  747. package/src/renderers/opentui/start.tsx +3 -3
  748. package/src/renderers/opentui/test-utils.tsx +3 -0
  749. package/src/renderers/opentui/ui-host.tsx +29 -1
  750. package/src/series/capability.ts +75 -0
  751. package/src/series/csv.ts +160 -0
  752. package/src/series/files.ts +107 -0
  753. package/src/series/registry.ts +198 -0
  754. package/src/series/resolve.ts +108 -0
  755. package/src/series/standalone.ts +48 -0
  756. package/src/series/types.ts +153 -0
  757. package/src/series/validate.ts +171 -0
  758. package/src/shares/chat.ts +34 -0
  759. package/src/shares/dialog.tsx +295 -0
  760. package/src/shares/flow.tsx +56 -0
  761. package/src/shares/live.ts +14 -22
  762. package/src/shares/pane-image.ts +152 -0
  763. package/src/shares/personal-pane.ts +64 -0
  764. package/src/shares/portable-layout.ts +4 -2
  765. package/src/shares/prepare.ts +20 -0
  766. package/src/sources/gloomberb-cloud/index.ts +109 -10
  767. package/src/sources/gloomberb-cloud/normalizers.ts +3 -0
  768. package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
  769. package/src/sources/history-result.ts +1 -0
  770. package/src/sources/history-retention.ts +11 -0
  771. package/src/sources/listing-symbols.ts +4 -1
  772. package/src/sources/listing-target.ts +4 -0
  773. package/src/sources/provider-router/batches.ts +4 -1
  774. package/src/sources/provider-router/cache.ts +4 -2
  775. package/src/sources/provider-router/cached-routes.ts +1 -1
  776. package/src/sources/provider-router/financial-routes.ts +1 -0
  777. package/src/sources/provider-router/financials.ts +13 -0
  778. package/src/sources/provider-router/history.ts +43 -25
  779. package/src/sources/provider-router/index.ts +14 -0
  780. package/src/sources/provider-router/search.ts +1 -0
  781. package/src/state/hooks/inline-tickers.ts +49 -11
  782. package/src/sync/core-contributors.ts +1 -0
  783. package/src/test-support/shell-pane-keys.tsx +1 -0
  784. package/src/theme/theme-context.tsx +15 -1
  785. package/src/tickers/company-name.ts +75 -0
  786. package/src/tickers/instrument-kind.ts +34 -1
  787. package/src/tickers/listing-name.ts +34 -0
  788. package/src/tickers/listing-venues.ts +132 -0
  789. package/src/tickers/open-target.ts +13 -4
  790. package/src/tickers/perpetual-listing.ts +151 -0
  791. package/src/tickers/prediction-listing.ts +26 -0
  792. package/src/tickers/search/index.ts +72 -11
  793. package/src/tickers/search/ranking.ts +98 -20
  794. package/src/tickers/search/types.ts +7 -1
  795. package/src/tickers/ticker-changes.ts +213 -0
  796. package/src/tickers/us-listing.ts +34 -0
  797. package/src/time-series/economic.ts +2 -6
  798. package/src/time-series/hooks.ts +9 -0
  799. package/src/time-series/ice-credit.ts +39 -0
  800. package/src/time-series/resolve.ts +211 -29
  801. package/src/time-series/studies.ts +1 -0
  802. package/src/time-series/types.ts +12 -2
  803. package/src/time-series/use-chart-resolution.ts +32 -0
  804. package/src/types/config.ts +10 -2
  805. package/src/types/data-provider.ts +11 -0
  806. package/src/types/financials.ts +62 -1
  807. package/src/types/headless.ts +113 -0
  808. package/src/types/instrument.ts +4 -0
  809. package/src/types/plugin.ts +52 -2
  810. package/src/types/price-history.ts +7 -0
  811. package/src/types/ticker-changes.ts +26 -0
  812. package/src/types/ticker.ts +14 -0
  813. package/src/ui/context-menu.tsx +13 -1
  814. package/src/ui/host.tsx +57 -3
  815. package/src/ui/live-resize.ts +91 -0
  816. package/src/ui/live-stretch.ts +153 -0
  817. package/src/ui/measured-cells.ts +58 -0
  818. package/src/ui/sticky-scroll.ts +7 -0
  819. package/src/utils/basis-points.ts +17 -0
  820. package/src/utils/central-banks.ts +76 -0
  821. package/src/utils/cli-output.ts +131 -15
  822. package/src/utils/concurrency.ts +25 -0
  823. package/src/utils/crypto-pair.ts +20 -0
  824. package/src/utils/currency-pair.ts +19 -0
  825. package/src/utils/currency-units.ts +11 -0
  826. package/src/utils/datetime-format.ts +27 -6
  827. package/src/utils/decimal-comma.ts +19 -0
  828. package/src/utils/dom-screenshot-css.ts +265 -0
  829. package/src/utils/dom-screenshot-rasters.ts +276 -0
  830. package/src/utils/dom-screenshot.ts +439 -52
  831. package/src/utils/double-escape-close.ts +15 -1
  832. package/src/utils/exchange-rate-snapshot.ts +6 -2
  833. package/src/utils/exchanges.ts +143 -1
  834. package/src/utils/format.ts +35 -5
  835. package/src/utils/forward-dividend.ts +14 -0
  836. package/src/utils/fundamentals.ts +66 -0
  837. package/src/utils/futures-generic.ts +6 -12
  838. package/src/utils/fx-market-hours.ts +15 -5
  839. package/src/utils/fx-status.ts +6 -1
  840. package/src/utils/inline-content-tokenizer.ts +22 -3
  841. package/src/utils/market-capitalization.ts +8 -0
  842. package/src/utils/one-shot.ts +73 -0
  843. package/src/utils/options.ts +37 -8
  844. package/src/utils/price-history.ts +99 -42
  845. package/src/utils/sec-eps-basis.ts +24 -11
  846. package/src/utils/sec.ts +61 -7
  847. package/src/utils/utc-time.ts +63 -4
  848. package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
  849. /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
  850. /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
  851. /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
  852. /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
@@ -18,6 +18,7 @@ import type { TickerRecord } from "../../../../types/ticker";
18
18
  import { addTickerToPortfolio, addTickerToWatchlist } from "../mutations";
19
19
  import { captureAttentionAction } from "../../../../telemetry/attention-counts";
20
20
  import { publicTickerKey } from "../../../../utils/exchanges";
21
+ import { tickerChangeLine } from "../../../../tickers/ticker-changes";
21
22
  import {
22
23
  IDLE_VALIDATION,
23
24
  isPlausibleTickerQuery,
@@ -30,6 +31,8 @@ import {
30
31
  } from "./resolution";
31
32
 
32
33
  const QUICK_ADD_DEBOUNCE_MS = 300;
34
+ /** The pane key that opens the add row, as its footer hint shows it. */
35
+ export const QUICK_ADD_KEY = "a";
33
36
 
34
37
  export type { QuickAddCollectionKind } from "./resolution";
35
38
 
@@ -80,15 +83,20 @@ function QuickAddPreview({
80
83
  const exchange = exchangeLabelFromValidation(validation);
81
84
  const showSymbol = normalizeQuickAddQuery(validation.symbol) !== validation.query;
82
85
  const symbolPrefix = showSymbol ? `${validation.symbol} ` : "";
86
+ // A symbol whose company moved on says where it went before it is added, ahead of the
87
+ // name of what lists there now; the add notice prints the whole line.
88
+ const change = validation.change?.kind === "moved" ? validation.change : null;
89
+ const moved = change?.listed ? `${change.issuer ?? `the former ${change.symbol}`} trades as ${change.tradesAs}` : change?.note;
83
90
 
84
91
  return (
85
92
  <Box flexDirection="row" overflow="hidden">
86
- <Text fg={colors.textDim}>{`${symbolPrefix}${priceText} `}</Text>
87
- <Text fg={changeValue == null ? colors.textDim : priceColor(changeValue)}>
93
+ <Text fg={colors.textDim} flexShrink={0}>{`${symbolPrefix}${priceText} `}</Text>
94
+ <Text fg={changeValue == null ? colors.textDim : priceColor(changeValue)} flexShrink={0}>
88
95
  {formatPercentRaw(changeValue)}
89
96
  </Text>
90
- {name ? <Text fg={colors.textMuted}>{` ${name}`}</Text> : null}
91
- {exchange ? <Text fg={colors.textDim}>{` ${exchange}`}</Text> : null}
97
+ {moved ? <Text fg={colors.warning} flexShrink={0}>{` ${moved}`}</Text> : null}
98
+ {name && (!change || change.listed) ? <Text fg={colors.textMuted}>{` ${name}`}</Text> : null}
99
+ {exchange && !change ? <Text fg={colors.textDim}>{` ${exchange}`}</Text> : null}
92
100
  </Box>
93
101
  );
94
102
  }
@@ -101,6 +109,7 @@ export function QuickAddTickerInput({
101
109
  width,
102
110
  onAdded,
103
111
  onFocusChange,
112
+ focusRequest = 0,
104
113
  }: {
105
114
  collectionId: string;
106
115
  collectionKind: QuickAddCollectionKind;
@@ -109,6 +118,12 @@ export function QuickAddTickerInput({
109
118
  width: number;
110
119
  onAdded: (symbol: string) => void;
111
120
  onFocusChange?: (focused: boolean) => void;
121
+ /**
122
+ * Bumped by a control outside the row, such as the empty table's
123
+ * "+ ticker" button, to open it. A click there focuses the pane in the same
124
+ * press, so the row opens once the pane is focused.
125
+ */
126
+ focusRequest?: number;
112
127
  }) {
113
128
  const dispatch = useAppDispatch();
114
129
  const { notify } = usePluginAppActions();
@@ -132,6 +147,13 @@ export function QuickAddTickerInput({
132
147
  setInputFocused(false);
133
148
  }, []);
134
149
 
150
+ const handledFocusRequestRef = useRef(focusRequest);
151
+ useEffect(() => {
152
+ if (focusRequest === handledFocusRequestRef.current || !focused) return;
153
+ handledFocusRequestRef.current = focusRequest;
154
+ focusInput();
155
+ }, [focusInput, focusRequest, focused]);
156
+
135
157
  const resetInput = useCallback(() => {
136
158
  setInputValue("");
137
159
  setValidation(IDLE_VALIDATION);
@@ -295,13 +317,13 @@ export function QuickAddTickerInput({
295
317
  }
296
318
 
297
319
  onAdded(result.ticker.metadata.ticker);
298
- notify({
299
- type: "success",
300
- body: tf("Added {symbol} to {collection}.", {
301
- symbol: result.ticker.metadata.ticker,
302
- collection: collectionName,
303
- }),
320
+ const added = tf("Added {symbol} to {collection}.", {
321
+ symbol: result.ticker.metadata.ticker,
322
+ collection: collectionName,
304
323
  });
324
+ // As `watchlist add` prints it: FB now lists another security, Meta trades as META.
325
+ const change = tickerChangeLine(currentValidation.change);
326
+ notify({ type: "success", body: change ? `${added} ${change}.` : added });
305
327
  resetInput();
306
328
  queueMicrotask(() => inputRef.current?.focus?.());
307
329
  } catch {
@@ -350,7 +372,7 @@ export function QuickAddTickerInput({
350
372
 
351
373
  // The row shows only its placeholder, so the footer says which key reaches it.
352
374
  usePaneFooter("portfolio-list:quick-add", () => ({
353
- hints: inputFocused ? [] : [{ id: "add", key: "a", label: "dd", onPress: focusInput }],
375
+ hints: inputFocused ? [] : [{ id: "add", key: QUICK_ADD_KEY, label: "dd", onPress: focusInput }],
354
376
  }), [focusInput, inputFocused]);
355
377
 
356
378
  return (
@@ -8,6 +8,14 @@ import {
8
8
  import type { Quote } from "../../../../types/financials";
9
9
  import type { TickerRecord } from "../../../../types/ticker";
10
10
  import { canonicalExchange, parsePublicTickerKey, publicTickerKey } from "../../../../utils/exchanges";
11
+ import {
12
+ describeTickerChange,
13
+ isUsSymbolVenue,
14
+ quotedListing,
15
+ startTickerChangeLookup,
16
+ tickerChangeLine,
17
+ type TickerChange,
18
+ } from "../../../../tickers/ticker-changes";
11
19
 
12
20
  const QUICK_ADD_MAX_QUERY_LENGTH = 32;
13
21
  const QUICK_ADD_SYMBOL_RE = /^[A-Z0-9][A-Z0-9.\-\s]*$/;
@@ -20,6 +28,8 @@ interface ResolvedQuickAdd {
20
28
  resolved: ResolvedTickerSearch;
21
29
  ticker: TickerRecord | null;
22
30
  quote: Quote | null;
31
+ /** The symbol changed (FB became META), as `watchlist add` says it. */
32
+ change: TickerChange | null;
23
33
  }
24
34
 
25
35
  export type QuickAddValidation =
@@ -135,6 +145,8 @@ export async function resolveQuickAddValidation({
135
145
  if (!registry) {
136
146
  return { status: "error", query, message: "Ticker lookup unavailable" };
137
147
  }
148
+ // Beside the search, so a symbol that changed (FB is now META) costs no wait.
149
+ const changes = startTickerChangeLookup(registry.marketData, query);
138
150
 
139
151
  try {
140
152
  const resolved = await resolveTickerSearch({
@@ -144,7 +156,8 @@ export async function resolveQuickAddValidation({
144
156
  dataProvider: registry.marketData,
145
157
  });
146
158
  if (!resolved) {
147
- return { status: "missing", query, message: "No exact ticker match" };
159
+ const change = describeTickerChange(query, await changes.settle(), null);
160
+ return { status: "missing", query, message: tickerChangeLine(change) ?? "No exact ticker match" };
148
161
  }
149
162
 
150
163
  const symbol = resolved.symbol;
@@ -163,6 +176,12 @@ export async function resolveQuickAddValidation({
163
176
  }
164
177
  }
165
178
 
179
+ // A listing abroad is not the US symbol the changes are of.
180
+ const venue = resolved.kind === "provider" && resolved.result.exchange === "SMART"
181
+ ? resolved.result.primaryExchange
182
+ : exchangeFromResolved(resolved);
183
+ const payload = isUsSymbolVenue(venue) ? await changes.settle() : null;
184
+ const name = ticker?.metadata.name || (resolved.kind === "provider" ? resolved.result.name : "");
166
185
  return {
167
186
  status: tickerBelongsToCollection(ticker, collectionKind, collectionId) ? "duplicate" : "ready",
168
187
  query,
@@ -170,6 +189,7 @@ export async function resolveQuickAddValidation({
170
189
  resolved,
171
190
  ticker,
172
191
  quote,
192
+ change: describeTickerChange(query, payload, quote ? quotedListing(quote) : { name }),
173
193
  };
174
194
  } catch (error) {
175
195
  if (error instanceof AmbiguousTickerError && !(error instanceof AmbiguousContractError)) {
@@ -13,6 +13,8 @@ export interface PortfolioPaneSettings {
13
13
  viewMode: PortfolioViewMode;
14
14
  hideHeader: boolean;
15
15
  hideCash: boolean;
16
+ /** Value a portfolio at the regular close rather than the latest print (`fn PF --close`). */
17
+ valueAtClose: boolean;
16
18
  }
17
19
 
18
20
  export interface CollectionEntry {
@@ -47,6 +49,9 @@ const PORTFOLIO_COLUMN_DEFS: ColumnConfig[] = [
47
49
  { id: "rating", label: "RATING", width: 7, align: "right", format: "number" },
48
50
  { id: "ex_div", label: "EX-DIV", width: 7, align: "right" },
49
51
  { id: "next_earn", label: "ERN", width: 7, align: "right" },
52
+ // The stock's perpetual: its premium to the stock's last price and its funding per eight hours.
53
+ { id: "perp_premium", label: "PERP%", width: 7, align: "right", format: "percent" },
54
+ { id: "perp_funding", label: "FUND 8H", width: 8, align: "right", format: "percent" },
50
55
  { id: "side", label: "SIDE", width: 5, align: "left" },
51
56
  { id: "shares", label: "SHARES", width: 9, align: "right", format: "number" },
52
57
  { id: "avg_cost", label: "AVG COST", width: 10, align: "right", format: "currency" },
@@ -64,6 +69,8 @@ const PORTFOLIO_COLUMN_DEFS: ColumnConfig[] = [
64
69
  { id: "mark_delta", label: "MARK%", width: 8, align: "right", format: "percent" },
65
70
  { id: "acq_date", label: "ACQ", width: 7, align: "right" },
66
71
  { id: "held", label: "HELD", width: 6, align: "right" },
72
+ // When the price a row is valued at is from: its print, or the regular close.
73
+ { id: "as_of", label: "AS OF UTC", width: 10, align: "right" },
67
74
  ];
68
75
 
69
76
  const PORTFOLIO_COLUMNS_BY_ID = new Map(PORTFOLIO_COLUMN_DEFS.map((column) => [column.id, column]));
@@ -171,6 +178,9 @@ function withTargetColumns(columnIds: string[]): string[] {
171
178
  function describeColumnOption(column: ColumnConfig): string {
172
179
  if (column.id === PRICE_SPARKLINE_COLUMN_ID) return "One-month price sparkline.";
173
180
  if (TARGET_COLUMN_IDS.has(column.id)) return "Shown by default once the portfolio has target weights.";
181
+ if (column.id === "perp_premium") return "Premium of the stock's perpetual to its last price.";
182
+ if (column.id === "perp_funding") return "Funding of the stock's perpetual, per 8 hours.";
183
+ if (column.id === "as_of") return "When each row's price is from: its last print, or the regular close.";
174
184
  return PORTFOLIO_ONLY_COLUMN_IDS.has(column.id)
175
185
  ? "Visible only when this pane is showing a portfolio."
176
186
  : "Visible for watchlists and portfolios.";
@@ -191,6 +201,7 @@ export function getPortfolioPaneSettings(settings: Record<string, unknown> | und
191
201
  viewMode: isPortfolioViewMode(settings?.viewMode) ? settings.viewMode : "table",
192
202
  hideHeader: settings?.hideHeader === true,
193
203
  hideCash: settings?.hideCash === true,
204
+ valueAtClose: settings?.valueAtClose === true,
194
205
  };
195
206
  }
196
207
 
@@ -306,6 +317,12 @@ export function buildPortfolioPaneSettingsDef(
306
317
  type: "select",
307
318
  options: VIEW_MODE_OPTIONS,
308
319
  });
320
+ fields.push({
321
+ key: "valueAtClose",
322
+ label: "Value at Regular Close",
323
+ description: "Price holdings at the regular close instead of the latest print, which includes extended hours.",
324
+ type: "toggle",
325
+ });
309
326
  }
310
327
 
311
328
  if (settings.collectionScope === "custom") {
@@ -22,6 +22,13 @@ import { formatAllocationDrift, formatAllocationWeight, type PortfolioCashLine }
22
22
  import { getMostRecentQuoteUpdate } from "../../../../market-data/quotes/time";
23
23
  import { fxStatusLabel, type FxRateStatus } from "../../../../utils/fx-status";
24
24
  import { t } from "../../../../i18n";
25
+ import type { PortfolioValuationBasis } from "../../../../portfolio/valuation-basis";
26
+
27
+ /** What the value beside it is priced at, short enough that the header row keeps it with the value. */
28
+ const PRICED_AT_TEXT: Record<PortfolioValuationBasis, string> = {
29
+ "latest-print": "(latest print)",
30
+ "regular-close": "(regular close)",
31
+ };
25
32
 
26
33
  export interface PortfolioSummarySegment {
27
34
  id: string;
@@ -225,8 +232,11 @@ export function buildPortfolioSummarySegments({
225
232
  baseCurrency = "USD",
226
233
  manualCash = null,
227
234
  brokerPortfolio = false,
235
+ valuationBasis,
228
236
  }: {
229
237
  totals: PortfolioSummaryTotals;
238
+ /** What the values are priced at, said beside the value; left out when absent. */
239
+ valuationBasis?: PortfolioValuationBasis;
230
240
  accountState: PortfolioSummaryAccountState | null;
231
241
  isPortfolioTab?: boolean;
232
242
  /** Synced from a broker, so it is worth its account's equity even while the account is missing. */
@@ -285,9 +295,11 @@ export function buildPortfolioSummarySegments({
285
295
  ]));
286
296
  }
287
297
 
298
+ // Which price the value uses goes with it, so a narrow row never shows one without the other.
288
299
  candidates.push(createSummarySegment("val", [
289
300
  { text: broker || totals.hasShorts ? "Gross" : "Val", tone: "label" },
290
301
  { text: money(totalMarketValue), tone: "value", bold: true },
302
+ ...(valuationBasis ? [{ text: PRICED_AT_TEXT[valuationBasis], tone: "muted" as const }] : []),
291
303
  ]));
292
304
 
293
305
  if (totals.hasShorts && totals.netMktValue != null) {
@@ -7,14 +7,14 @@ import { isQuoteStaleForCurrentSession } from "../../../../market-data/quotes/fr
7
7
  import { headlineQuoteDisplay } from "../column-values";
8
8
  import { isManualPortfolio } from "../mutations";
9
9
  import type { AllocationHolding } from "../allocation";
10
+ import { getPortfolioValuationDisplay, type PortfolioValuationBasis } from "../../../../portfolio/valuation-basis";
10
11
  import {
11
12
  getPortfolioPositionMetrics,
12
- getPortfolioQuoteDisplay,
13
13
  resolvePortfolioMarketValue,
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 {
@@ -90,7 +90,11 @@ export function formatPortfolioAmount(
90
90
  return `${sign}${getCurrencySymbol(currency)}${text.slice(sign.length)}`;
91
91
  }
92
92
 
93
- /** Totals over the collection, every amount converted into `totalsCurrency`. */
93
+ /**
94
+ * Totals over the collection, every amount converted into `totalsCurrency`,
95
+ * valued at `valuationBasis`: the latest print unless given, or the regular
96
+ * close, whose day is that session's move.
97
+ */
94
98
  export function calculatePortfolioSummaryTotals(
95
99
  tickers: TickerRecord[],
96
100
  financialsMap: Map<string, TickerFinancials>,
@@ -98,6 +102,7 @@ export function calculatePortfolioSummaryTotals(
98
102
  exchangeRates: Map<string, number>,
99
103
  isPortfolio: boolean,
100
104
  collectionId: string | null,
105
+ valuationBasis: PortfolioValuationBasis = "latest-print",
101
106
  ): PortfolioSummaryTotals {
102
107
  let totalMktValue = 0;
103
108
  let netMktValue = 0;
@@ -144,7 +149,7 @@ export function calculatePortfolioSummaryTotals(
144
149
  const positionMetrics = getPortfolioPositionMetrics(ticker, collectionId ?? undefined, quoteCurrency, {
145
150
  currency: totalsCurrency, convert: toBase,
146
151
  }, quote);
147
- activeQuote = getPortfolioQuoteDisplay(positionMetrics, quote);
152
+ activeQuote = getPortfolioValuationDisplay(positionMetrics, quote, valuationBasis);
148
153
  const { totalPriceUnits, grossPriceUnits, totalCost } = positionMetrics;
149
154
  if (positionMetrics.positionCount === 0) {
150
155
  // Not held, so a missing rate is no gap in the totals: it only leaves the trade in units out.
@@ -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,
@@ -8,18 +9,29 @@ import { useDataTableSortMenu } from "../../../components/data-table/sort-menu";
8
9
  import { followLiveSparklinePrice } from "../../../components/price-sparkline/model";
9
10
  import { PRICE_SPARKLINE_COLUMN_ID } from "../../../components/price-sparkline/view";
10
11
  import type { QuoteFlashDirection } from "../../../components/quote-flash";
12
+ import type { TickerTableCell } from "../../../components/ticker/list-table-view";
11
13
  import { createRowValueCache } from "../../../components/ui/row-value-cache";
12
14
  import type { ColumnConfig } from "../../../types/config";
13
15
  import type { PricePoint, TickerFinancials } from "../../../types/financials";
14
16
  import type { TickerRecord } from "../../../types/ticker";
15
17
  import { objectVersion } from "../../../utils/object-version";
16
- import { columnContextVersion } from "./cell-version";
18
+ import { columnContextVersion, PERPETUAL_COLUMN_IDS } from "./cell-version";
17
19
  import { getColumnValue, type ColumnContext } from "./metrics";
18
- import { portfolioPnlLabel } from "./position-metrics";
20
+ import { tickerDisplayName } from "./column-values";
21
+ import { displayWidth } from "../../../utils/format";
22
+ import { portfolioPnlLabel } from "../../../portfolio/position-metrics";
19
23
  import { PORTFOLIO_ROW_MENU_KEYS } from "./row-actions";
20
24
 
21
25
  export type { QuoteFlashDirection };
22
26
 
27
+ /** The market-state dot and the space after it, before each symbol in the Ticker column. */
28
+ const TICKER_DOT_WIDTH = 2;
29
+ /**
30
+ * The widest the Ticker column grows for its symbols: a perpetual as its venue writes it (`xyz:BRENTOIL`) and an
31
+ * option as its terms (`NVDA C $1250 Dec'26`) fit, so only a list holding options is given the width.
32
+ */
33
+ const MAX_TICKER_COLUMN_WIDTH = 22;
34
+
23
35
  /** A cell recomputes only when its row's records or a context input it reads change. */
24
36
  function buildCellVersion(
25
37
  column: ColumnConfig,
@@ -98,6 +110,8 @@ export function PortfolioTickerTable({
98
110
  visibleRangeBuffer,
99
111
  resetScrollKey,
100
112
  onRowActivate,
113
+ onAddTicker,
114
+ onOpenPerpetual,
101
115
  rootHeight,
102
116
  }: {
103
117
  columns: ColumnConfig[];
@@ -117,18 +131,26 @@ export function PortfolioTickerTable({
117
131
  visibleRangeBuffer?: number;
118
132
  resetScrollKey?: unknown;
119
133
  onRowActivate?: (ticker: TickerRecord) => void;
134
+ /** Opens the add row; the empty table offers it as a button. */
135
+ onAddTicker?: () => void;
136
+ /** Opens PERP on a row's stock perpetual: its PERP% and FUND 8H cells link to it. */
137
+ onOpenPerpetual?: (marketId: string) => void;
120
138
  rootHeight?: number;
121
139
  }) {
122
- const cellCacheRef = useRef(createRowValueCache<string, ReturnType<typeof getColumnValue>>(5000));
140
+ const cellCacheRef = useRef(createRowValueCache<string, ReturnType<typeof getColumnValue> & TickerTableCell>(5000));
141
+ const openPerpetualRef = useRef(onOpenPerpetual);
142
+ openPerpetualRef.current = onOpenPerpetual;
123
143
  const sparklineVisible = columns.some((column) => column.id === PRICE_SPARKLINE_COLUMN_ID);
124
144
  const tableFinancialsMap = useLiveSparklineFinancials(financialsMap, sortedTickers, sparklineVisible);
125
145
  const resolveCell = useCallback(
126
146
  (column: ColumnConfig, ticker: TickerRecord, financials: TickerFinancials | undefined) => {
127
147
  const key = `${ticker.metadata.ticker}:${column.id}`;
128
148
  const version = buildCellVersion(column, ticker, financials, columnContext);
129
- return cellCacheRef.current.get(key, version, () => (
130
- getColumnValue(column, ticker, financials, columnContext)
131
- ));
149
+ return cellCacheRef.current.get(key, version, () => {
150
+ const cell = getColumnValue(column, ticker, financials, columnContext);
151
+ const marketId = PERPETUAL_COLUMN_IDS.has(column.id) ? columnContext.perpetuals?.get(ticker.metadata.ticker)?.marketId : undefined;
152
+ return marketId ? { ...cell, onPress: () => openPerpetualRef.current?.(marketId) } : cell;
153
+ });
132
154
  },
133
155
  [columnContext],
134
156
  );
@@ -139,11 +161,17 @@ export function PortfolioTickerTable({
139
161
  const hasNonShareQuantity = useMemo(() => sortedTickers.some(ticker => ticker.metadata.positions.some(position =>
140
162
  (!columnContext.activeTab || position.portfolio === columnContext.activeTab) && position.shares !== 0 && (position.priceBasis === "percent-of-par" || ticker.metadata.assetCategory?.toUpperCase() === "BOND"))),
141
163
  [columnContext.activeTab, sortedTickers]);
164
+ // The Ticker column grows to its longest symbol, so ETH-USD shows whole beside its market-state dot.
165
+ const tickerWidth = useMemo(() => Math.min(MAX_TICKER_COLUMN_WIDTH, sortedTickers.reduce(
166
+ (widest, ticker) => Math.max(widest, TICKER_DOT_WIDTH + displayWidth(tickerDisplayName(ticker))),
167
+ 0,
168
+ )), [sortedTickers]);
142
169
  const displayColumns = useMemo(() => columns.map((column) => column.id === "shares" && hasNonShareQuantity ? { ...column, label: "QTY" }
170
+ : column.id === "ticker" && tickerWidth > column.width ? { ...column, width: tickerWidth }
143
171
  : pnlLabel !== "P&L" && (column.id === "pnl" || column.id === "pnl_pct") ? {
144
172
  ...column,
145
173
  label: column.id === "pnl_pct" ? pnlLabel.replace("P&L", "%") : pnlLabel,
146
- } : column), [columns, hasNonShareQuantity, pnlLabel]);
174
+ } : column), [columns, hasNonShareQuantity, pnlLabel, tickerWidth]);
147
175
  // The table offers "Sort by…" while it has a sort column. A watchlist starts
148
176
  // unsorted and a third header click turns sorting off, so the unsorted state
149
177
  // needs its own entry until TickerListTableView takes `sortable`.
@@ -175,6 +203,8 @@ export function PortfolioTickerTable({
175
203
  resetScrollKey={resetScrollKey}
176
204
  onRowActivate={onRowActivate}
177
205
  rowMenuAccelerators={PORTFOLIO_ROW_MENU_KEYS}
206
+ onAddTicker={onAddTicker}
207
+ addTickerShortcut={onAddTicker ? QUICK_ADD_KEY : undefined}
178
208
  rootHeight={rootHeight}
179
209
  />
180
210
  );
@@ -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 });
@@ -1,56 +1,109 @@
1
+ import type { CarbonBoard, CarbonHistory, EuropePowerBoard, EuropePowerHistory } from "../../../api-client/europe-energy";
1
2
  import type { PowerBoard, PowerHistory } from "../../../api-client/power";
2
3
  import type { PaneScreenshotEvidenceHook } from "../../../cli/pane-functions/screenshot-evidence";
3
4
  import { useRemoteUiNode } from "../../../remote/semantic-tree";
4
5
  import { isRecord } from "../../../utils/guards";
5
- import { fetchPowerBoard, fetchAllPowerHistory, validatePowerBoard, validatePowerHistory } from "./client";
6
+ import { fetchPowerBoard, fetchAllPowerHistory, fetchPowerTickerScopes, validatePowerBoard, validatePowerHistory } from "./client";
6
7
  import { otherRows, powerTab, projectRows } from "./model";
8
+ import { fetchCarbonHistory, fetchCarbonPrice, fetchPowerPriceHistory, fetchPowerPrices, validateCarbonPrice, validatePowerPrices } from "./prices-client";
9
+ import { DEFAULT_PRICE_MARKET, isCarbonQuery, powerPriceMarket } from "./prices-model";
7
10
  import { powerQuery } from "./query";
8
11
  interface PowerEvidence {
9
12
  kind: "power";
10
13
  version: 1;
11
14
  complete: boolean;
12
15
  plottedValueCount: number;
13
- board: PowerBoard;
16
+ /** The grid board, on every tab but Prices. */
17
+ board: PowerBoard | null;
14
18
  history: PowerHistory | null;
19
+ /** The day-ahead board and the EUA board, on the Prices tab. */
20
+ prices?: EuropePowerBoard | null;
21
+ carbon?: CarbonBoard | null;
15
22
  tab: string;
16
23
  rowIds: string[];
17
24
  }
25
+ /** What the Prices tab draws, frozen by `shot` so the capture and its check read the same days. */
26
+ export interface PowerPricesSnapshot {
27
+ board: EuropePowerBoard;
28
+ /** The charted history: the selected market's, or the carbon allowance's for EPWR EUA. */
29
+ history: EuropePowerHistory | CarbonHistory | null;
30
+ /** Null when the server has no EUA price yet; the tab then shows the board alone. */
31
+ carbon: CarbonBoard | null;
32
+ }
18
33
  export function usePowerEvidence(board: PowerBoard | undefined, history: PowerHistory | undefined, tab: string, rowIds: string[], loading: boolean) {
19
34
  useRemoteUiNode({ role: "chart-data", label: "Rendered power and grid observations", getMetadata: () => ({
20
35
  kind: "power", version: 1, complete: !!board && !loading, ready: !!board && !loading,
21
36
  plottedValueCount: rowIds.length, board, history: history ?? null, tab, rowIds,
22
37
  }) });
23
38
  }
39
+ export function usePowerPricesEvidence(prices: EuropePowerBoard | null, carbon: CarbonBoard | null, rowIds: string[], loading: boolean) {
40
+ useRemoteUiNode({ role: "chart-data", label: "Rendered day-ahead power and carbon prices", getMetadata: () => ({
41
+ kind: "power", version: 1, complete: !!prices && !loading, ready: !!prices && !loading,
42
+ plottedValueCount: rowIds.length, board: null, history: null, prices, carbon, tab: "prices", rowIds,
43
+ }) });
44
+ }
45
+ const instanceSettings = (payload: Parameters<PaneScreenshotEvidenceHook["mismatches"]>[1]["payload"]) =>
46
+ payload.config.layout.instances.find((entry) => entry.instanceId === payload.paneId)?.settings;
24
47
  export const powerScreenshotEvidence: PaneScreenshotEvidenceHook<PowerEvidence> = {
25
48
  paneId: "power", kind: "power", label: "power and grid",
26
49
  async prepare({ resolved, settings }) {
27
50
  const tab = powerTab(settings.tab ?? resolved.options.tab);
51
+ if (tab === "prices") {
52
+ const board = await fetchPowerPrices();
53
+ // The carbon figures are captured when the server has them, and left out when it does not.
54
+ const carbon = await fetchCarbonPrice().catch(() => null);
55
+ const arg = resolved.createOptions?.arg;
56
+ const market = powerPriceMarket(arg)?.code ?? DEFAULT_PRICE_MARKET;
57
+ const history = isCarbonQuery(arg) && carbon?.row.date ? await fetchCarbonHistory()
58
+ : board.rows.some((row) => row.code === market && row.date) ? await fetchPowerPriceHistory(market) : null;
59
+ return { settings: { powerPricesSnapshot: { board, history, carbon } satisfies PowerPricesSnapshot }, financials: [] };
60
+ }
28
61
  const symbol = resolved.createOptions?.symbol ?? resolved.createOptions?.arg;
29
62
  const filter = powerQuery({ ...settings, ...resolved.options, tab }, symbol);
30
63
  const board = await fetchPowerBoard({ ...filter, limit: 100 });
31
64
  const history = tab === "history" ? await fetchAllPowerHistory(filter) : undefined;
32
- return { settings: { powerSnapshot: { board, ...(history ? { history } : {}) } }, financials: [] };
65
+ // A ticker with nothing on this tab: the counts that say where its records are, captured with the rest.
66
+ const empty = !!symbol && tab !== "coverage" && !(tab === "history" ? history?.points.length : tab === "outcomes" ? board.rates.length
67
+ : tab === "utilities" ? board.exposure.length : board.projects.length);
68
+ const tickerScopes = empty && symbol ? await fetchPowerTickerScopes(symbol, tab, String(settings.context ?? resolved.options.context ?? "capacity")) : undefined;
69
+ return { settings: { powerSnapshot: { board, ...(history ? { history } : {}), ...(tickerScopes ? { tickerScopes } : {}) } }, financials: [] };
33
70
  },
34
71
  read(value) {
35
- if (!isRecord(value) || value.kind !== "power" || value.version !== 1 || value.complete !== true || !isRecord(value.board)
72
+ if (!isRecord(value) || value.kind !== "power" || value.version !== 1 || value.complete !== true
36
73
  || !Array.isArray(value.rowIds) || !value.rowIds.every((id) => typeof id === "string") || value.plottedValueCount !== value.rowIds.length) return null;
37
74
  try {
75
+ const tab = powerTab(value.tab);
76
+ if (tab === "prices") {
77
+ if (!isRecord(value.prices)) return null;
78
+ const prices = validatePowerPrices(value.prices as unknown as EuropePowerBoard);
79
+ if (value.carbon != null) validateCarbonPrice(value.carbon as unknown as CarbonBoard);
80
+ if (value.rowIds.some((id) => !prices.rows.some((row) => row.code === id))) return null;
81
+ return value as unknown as PowerEvidence;
82
+ }
83
+ if (!isRecord(value.board)) return null;
38
84
  const board = validatePowerBoard(value.board as unknown as PowerBoard);
39
85
  const history = value.history ? validatePowerHistory(value.history as PowerHistory) : null;
40
- const tab = powerTab(value.tab);
41
86
  const rows = ["queue", "loads", "capacity"].includes(tab) ? projectRows(board.projects) : otherRows(tab, board, history?.points ?? []);
42
87
  if (value.rowIds.some((id) => !rows.some((r) => r.id === id))) return null;
43
88
  return value as unknown as PowerEvidence;
44
89
  } catch { return null; }
45
90
  },
46
91
  mismatches(evidence, { resolved, payload }) {
47
- const snapshot = payload.config.layout.instances.find((entry) => entry.instanceId === payload.paneId)?.settings?.powerSnapshot;
92
+ const settings = instanceSettings(payload);
48
93
  const errors: string[] = [];
49
- if (!isRecord(snapshot) || JSON.stringify(snapshot.board) !== JSON.stringify(evidence.board)
50
- || JSON.stringify(snapshot.history ?? null) !== JSON.stringify(evidence.history)) errors.push("Power observations differ from the captured data.");
51
- if (evidence.tab !== powerTab(resolved.options.tab)) errors.push("Power tab does not match the requested view.");
94
+ if (evidence.tab === "prices") {
95
+ const snapshot = settings?.powerPricesSnapshot;
96
+ if (!isRecord(snapshot) || JSON.stringify(snapshot.board) !== JSON.stringify(evidence.prices)
97
+ || JSON.stringify(snapshot.carbon ?? null) !== JSON.stringify(evidence.carbon ?? null)) errors.push("Power prices differ from the captured data.");
98
+ } else {
99
+ const snapshot = settings?.powerSnapshot;
100
+ if (!isRecord(snapshot) || JSON.stringify(snapshot.board) !== JSON.stringify(evidence.board)
101
+ || JSON.stringify(snapshot.history ?? null) !== JSON.stringify(evidence.history)) errors.push("Power observations differ from the captured data.");
102
+ }
103
+ // EPWR opens the Prices tab by its settings; POWER by --tab.
104
+ if (evidence.tab !== powerTab(resolved.options.tab ?? settings?.tab)) errors.push("Power tab does not match the requested view.");
52
105
  return errors;
53
106
  },
54
- unavailable(evidence) { return evidence?.complete ? [] : ["power observations"]; },
107
+ unavailable(evidence) { return evidence?.complete ? [] : [evidence?.tab === "prices" ? "power prices" : "power observations"]; },
55
108
  symbols() { return []; },
56
109
  };