gloomberb 0.16.0 → 0.16.2

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 (691) hide show
  1. package/README.md +2 -1
  2. package/package.json +2 -1
  3. package/src/api-client/beneficial-owners.ts +92 -0
  4. package/src/api-client/data.ts +44 -11
  5. package/src/api-client/errors.ts +12 -0
  6. package/src/api-client/geo.ts +363 -0
  7. package/src/api-client/index.ts +5 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/members.ts +26 -0
  10. package/src/api-client/paths.ts +30 -1
  11. package/src/api-client/perps.ts +41 -0
  12. package/src/api-client/request.ts +5 -2
  13. package/src/api-client/types.ts +9 -1
  14. package/src/app/global-shortcuts.ts +14 -6
  15. package/src/app/keybindings/actions.ts +1 -1
  16. package/src/app/runtime/update.ts +38 -2
  17. package/src/app.tsx +10 -6
  18. package/src/brokers/account-cache.ts +24 -0
  19. package/src/cli/commands/command-utils.ts +8 -0
  20. package/src/cli/commands/crypto-hints.ts +75 -0
  21. package/src/cli/commands/market.ts +414 -106
  22. package/src/cli/commands/overview.ts +77 -32
  23. package/src/cli/commands/ticker.ts +101 -43
  24. package/src/cli/desktop-pane-shot.ts +34 -4
  25. package/src/cli/freshness.ts +61 -0
  26. package/src/cli/help.ts +1 -0
  27. package/src/cli/helpers.ts +4 -8
  28. package/src/cli/index.ts +12 -2
  29. package/src/cli/listing-arg.ts +321 -0
  30. package/src/cli/pane-functions/access-gate.ts +42 -0
  31. package/src/cli/pane-functions/catalog.ts +28 -1
  32. package/src/cli/pane-functions/data.ts +3 -1
  33. package/src/cli/pane-functions/dom.ts +20 -2
  34. package/src/cli/pane-functions/freshness.ts +400 -0
  35. package/src/cli/pane-functions/function-help.ts +36 -22
  36. package/src/cli/pane-functions/headless.ts +39 -11
  37. package/src/cli/pane-functions/index.ts +15 -4
  38. package/src/cli/pane-functions/options.ts +3 -0
  39. package/src/cli/pane-functions/report.ts +4 -0
  40. package/src/cli/pane-functions/resolver.ts +35 -7
  41. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  42. package/src/cli/pane-functions/screenshot.ts +7 -3
  43. package/src/cli/result.ts +41 -27
  44. package/src/cli/ticker-resolution.ts +7 -5
  45. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  46. package/src/components/chart/composite/drawing-store.ts +59 -0
  47. package/src/components/chart/composite/legend.tsx +319 -0
  48. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  49. package/src/components/chart/composite/panel-gestures.ts +59 -0
  50. package/src/components/chart/composite/panel-labels.ts +107 -0
  51. package/src/components/chart/composite/panel-surface.tsx +876 -0
  52. package/src/components/chart/composite/tool-catalog.ts +98 -0
  53. package/src/components/chart/composite/toolbar.tsx +186 -0
  54. package/src/components/chart/composite/tools.ts +8 -0
  55. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  56. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  57. package/src/components/command-bar/commands/collection.ts +5 -1
  58. package/src/components/command-bar/list/model.ts +5 -0
  59. package/src/components/command-bar/list/view.tsx +16 -3
  60. package/src/components/command-bar/pane-templates/workflow.ts +1 -0
  61. package/src/components/command-bar/routes/root/command-items.ts +9 -2
  62. package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
  63. package/src/components/command-bar/routes/root/provider-search.ts +19 -5
  64. package/src/components/command-bar/routes/root/runtime.ts +14 -5
  65. package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
  66. package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
  67. package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
  68. package/src/components/command-bar/routing/actions.ts +2 -0
  69. package/src/components/command-bar/selection-runtime.ts +38 -0
  70. package/src/components/command-bar/surface/index.tsx +7 -2
  71. package/src/components/command-bar/workflow/ops.ts +1 -1
  72. package/src/components/command-bar/workflow/tickers.ts +6 -0
  73. package/src/components/data-table/view.tsx +29 -10
  74. package/src/components/feedback-dialog.tsx +2 -1
  75. package/src/components/form-modal/field-row.tsx +2 -2
  76. package/src/components/index.ts +2 -2
  77. package/src/components/layout/detached-pane-shell.tsx +6 -3
  78. package/src/components/layout/floating-pane.tsx +6 -0
  79. package/src/components/layout/header.tsx +24 -7
  80. package/src/components/layout/missing-pane.tsx +2 -2
  81. package/src/components/layout/pane/content.tsx +23 -10
  82. package/src/components/layout/pane/error-boundary.tsx +103 -0
  83. package/src/components/layout/pane/footer/registration.tsx +68 -23
  84. package/src/components/layout/pane/header.tsx +61 -28
  85. package/src/components/layout/pane/index.tsx +6 -0
  86. package/src/components/layout/pane/title.ts +31 -7
  87. package/src/components/layout/shell/drag/index.ts +6 -5
  88. package/src/components/layout/shell/drag/runtime.ts +3 -0
  89. package/src/components/layout/shell/index.tsx +6 -0
  90. package/src/components/layout/shell/menu.ts +2 -1
  91. package/src/components/layout/shell/pane/actions.ts +2 -1
  92. package/src/components/layout/shell/pane/layers.tsx +29 -10
  93. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
  94. package/src/components/layout/shell/ticker-link-menu.ts +23 -9
  95. package/src/components/metric-treemap/heat-surface.tsx +745 -0
  96. package/src/components/metric-treemap/heat-tiles.ts +228 -0
  97. package/src/components/metric-treemap/index.tsx +2 -0
  98. package/src/components/metric-treemap/layout.ts +8 -0
  99. package/src/components/metric-treemap/scene.ts +432 -0
  100. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  101. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  102. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  103. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  104. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  105. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
  106. package/src/components/ticker/list-table-view.tsx +13 -1
  107. package/src/components/toggle-list.tsx +38 -12
  108. package/src/components/ui/country-flag-art.tsx +449 -0
  109. package/src/components/ui/country-flag.tsx +41 -0
  110. package/src/components/ui/data-table/types.ts +13 -0
  111. package/src/components/ui/fields.tsx +8 -0
  112. package/src/components/ui/icon.tsx +2 -0
  113. package/src/components/ui/index.ts +4 -0
  114. package/src/components/ui/multi-select/dialog.tsx +108 -22
  115. package/src/components/ui/range-track.tsx +53 -0
  116. package/src/components/ui/status.tsx +8 -2
  117. package/src/components/ui/tabs.tsx +11 -4
  118. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  119. package/src/core/state/app/types.ts +10 -1
  120. package/src/data/config/store/normalize.ts +17 -1
  121. package/src/i18n/es.ts +24 -4
  122. package/src/i18n/ja.ts +24 -4
  123. package/src/i18n/ko.ts +24 -4
  124. package/src/i18n/zh-cn.ts +24 -4
  125. package/src/i18n/zh-tw.ts +24 -4
  126. package/src/layout/ticker-navigation.ts +28 -2
  127. package/src/market-data/coordinator/chart.ts +1 -1
  128. package/src/market-data/coordinator/quotes.ts +23 -4
  129. package/src/market-data/fx-closes.ts +72 -0
  130. package/src/market-data/market/freshness.ts +78 -6
  131. package/src/market-data/market/session-close-note.ts +57 -0
  132. package/src/market-data/market/status.ts +151 -0
  133. package/src/market-data/published-apac-sessions.ts +66 -0
  134. package/src/market-data/quotes/contributions.ts +8 -0
  135. package/src/market-data/quotes/freshness.ts +36 -0
  136. package/src/market-data/quotes/resolution.ts +24 -8
  137. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  138. package/src/market-data/quotes/time.ts +16 -0
  139. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  140. package/src/plugins/builtin/alerts/cli.ts +10 -5
  141. package/src/plugins/builtin/alerts/index.tsx +1 -0
  142. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  143. package/src/plugins/builtin/analytics/risk-client.ts +330 -79
  144. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  145. package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
  146. package/src/plugins/builtin/analytics/risk-math.ts +33 -13
  147. package/src/plugins/builtin/analytics/risk-model.ts +282 -64
  148. package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
  149. package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
  150. package/src/plugins/builtin/attention/headless.ts +6 -4
  151. package/src/plugins/builtin/attention/index.tsx +1 -1
  152. package/src/plugins/builtin/attention/pane.tsx +1 -1
  153. package/src/plugins/builtin/awards/headless.ts +1 -0
  154. package/src/plugins/builtin/awards/pane.tsx +1 -1
  155. package/src/plugins/builtin/backtest/headless.ts +1 -0
  156. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  157. package/src/plugins/builtin/buildout/cells.tsx +15 -12
  158. package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
  159. package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
  160. package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
  161. package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
  162. package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
  163. package/src/plugins/builtin/buildout/index.tsx +1 -0
  164. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  165. package/src/plugins/builtin/catalysts/index.tsx +2 -2
  166. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  167. package/src/plugins/builtin/cds/headless.ts +2 -0
  168. package/src/plugins/builtin/cds/index.tsx +1 -0
  169. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  170. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  171. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  172. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  173. package/src/plugins/builtin/chat/channels.ts +19 -3
  174. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  175. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  176. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  177. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  178. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  179. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  180. package/src/plugins/builtin/chat/index.tsx +1 -0
  181. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  182. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  183. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  184. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  185. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  186. package/src/plugins/builtin/chat/message/types.ts +14 -2
  187. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  188. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  189. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  190. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  191. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  192. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  193. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  194. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  195. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  196. package/src/plugins/builtin/company-attention/pane.tsx +1 -1
  197. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  198. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  199. package/src/plugins/builtin/correlation/compute.ts +59 -16
  200. package/src/plugins/builtin/correlation/geo.ts +34 -0
  201. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  202. package/src/plugins/builtin/correlation/headless.ts +42 -8
  203. package/src/plugins/builtin/correlation/history.ts +2 -0
  204. package/src/plugins/builtin/correlation/index.tsx +68 -14
  205. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  206. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  207. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  208. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  209. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  210. package/src/plugins/builtin/correlation/settings.ts +1 -1
  211. package/src/plugins/builtin/cot/headless.ts +6 -3
  212. package/src/plugins/builtin/cot/index.tsx +3 -3
  213. package/src/plugins/builtin/cot/model.ts +36 -3
  214. package/src/plugins/builtin/cpi/headless.ts +4 -0
  215. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  216. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  217. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  218. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  219. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  220. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  221. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  222. package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
  223. package/src/plugins/builtin/dividend-yield/client.ts +4 -2
  224. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  225. package/src/plugins/builtin/doe/headless.ts +7 -0
  226. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  227. package/src/plugins/builtin/earnings/client.ts +2 -2
  228. package/src/plugins/builtin/earnings/headless.ts +5 -0
  229. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  230. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  231. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  232. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  233. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  234. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  235. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  236. package/src/plugins/builtin/econ/index.tsx +1 -0
  237. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  238. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  239. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  240. package/src/plugins/builtin/executives/index.tsx +1 -0
  241. package/src/plugins/builtin/exposure/headless.ts +3 -1
  242. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  243. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  244. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  245. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  246. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  247. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  248. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  249. package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
  250. package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
  251. package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
  252. package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
  253. package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
  254. package/src/plugins/builtin/gpu/headless.ts +7 -3
  255. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  256. package/src/plugins/builtin/gpu/model.ts +27 -1
  257. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  258. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  259. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  260. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  261. package/src/plugins/builtin/holders/headless.ts +139 -5
  262. package/src/plugins/builtin/holders/index.tsx +10 -3
  263. package/src/plugins/builtin/holders/pane.tsx +20 -3
  264. package/src/plugins/builtin/holders/report-header.ts +95 -0
  265. package/src/plugins/builtin/holders/table-model.ts +20 -5
  266. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  267. package/src/plugins/builtin/holders/types.ts +2 -1
  268. package/src/plugins/builtin/insider/headless.ts +2 -0
  269. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  270. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  271. package/src/plugins/builtin/jobs/headless.ts +1 -0
  272. package/src/plugins/builtin/jobs/index.tsx +1 -0
  273. package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
  274. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  275. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  276. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  277. package/src/plugins/builtin/market-heatmap/data.ts +30 -2
  278. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  279. package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
  280. package/src/plugins/builtin/market-heatmap/live.ts +88 -0
  281. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  282. package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
  283. package/src/plugins/builtin/market-movers/client.ts +3 -2
  284. package/src/plugins/builtin/market-movers/headless.ts +10 -1
  285. package/src/plugins/builtin/market-movers/screener.ts +18 -5
  286. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  287. package/src/plugins/builtin/members/client.ts +53 -0
  288. package/src/plugins/builtin/members/headless.ts +35 -0
  289. package/src/plugins/builtin/members/index.tsx +20 -0
  290. package/src/plugins/builtin/members/model.ts +68 -0
  291. package/src/plugins/builtin/members/pane.tsx +175 -0
  292. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  293. package/src/plugins/builtin/mna/headless.ts +1 -0
  294. package/src/plugins/builtin/mna/index.tsx +2 -1
  295. package/src/plugins/builtin/mna/pane.tsx +5 -2
  296. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  297. package/src/plugins/builtin/news/headless.ts +2 -0
  298. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  299. package/src/plugins/builtin/notes/cli.ts +14 -6
  300. package/src/plugins/builtin/notes/index.tsx +1 -0
  301. package/src/plugins/builtin/openfda/index.tsx +1 -0
  302. package/src/plugins/builtin/options/index.tsx +2 -1
  303. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  304. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  305. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  306. package/src/plugins/builtin/pe-band/client.ts +74 -2
  307. package/src/plugins/builtin/pe-band/headless.ts +26 -8
  308. package/src/plugins/builtin/pe-band/model.ts +102 -22
  309. package/src/plugins/builtin/pe-band/pane.tsx +34 -16
  310. package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
  311. package/src/plugins/builtin/perps/client.ts +66 -5
  312. package/src/plugins/builtin/perps/equity-identity.ts +16 -0
  313. package/src/plugins/builtin/perps/equity-row.tsx +6 -4
  314. package/src/plugins/builtin/perps/headless.ts +144 -16
  315. package/src/plugins/builtin/perps/index.tsx +6 -6
  316. package/src/plugins/builtin/perps/model.ts +189 -12
  317. package/src/plugins/builtin/perps/pane.tsx +248 -47
  318. package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
  319. package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
  320. package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
  321. package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
  322. package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
  323. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  324. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  325. package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
  326. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  327. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  328. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  329. package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
  330. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  331. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  332. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  333. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  334. package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
  335. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
  336. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
  337. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  338. package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
  339. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  340. package/src/plugins/builtin/power/headless.ts +3 -1
  341. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  342. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  343. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  344. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  345. package/src/plugins/builtin/research/events-headless.ts +2 -0
  346. package/src/plugins/builtin/research/headless.ts +2 -0
  347. package/src/plugins/builtin/research/index.tsx +1 -0
  348. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  349. package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
  350. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  351. package/src/plugins/builtin/research-search/index.tsx +1 -0
  352. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  353. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  354. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  355. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  356. package/src/plugins/builtin/scanner/headless.ts +14 -0
  357. package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
  358. package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
  359. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  360. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  361. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  362. package/src/plugins/builtin/sec/forms.ts +12 -0
  363. package/src/plugins/builtin/sec/headless.ts +2 -0
  364. package/src/plugins/builtin/sectors/client.ts +1 -0
  365. package/src/plugins/builtin/sectors/headless.ts +9 -1
  366. package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
  367. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  368. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  369. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  370. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  371. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  372. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  373. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  374. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  375. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  376. package/src/plugins/builtin/social-mentions/index.tsx +1 -1
  377. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  378. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  379. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  380. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  381. package/src/plugins/builtin/themes/headless.ts +3 -0
  382. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  383. package/src/plugins/builtin/thirteenf/index.tsx +2 -1
  384. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  385. package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
  386. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  387. package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
  388. package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
  389. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
  390. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
  391. package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
  392. package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
  393. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
  394. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
  395. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  396. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  397. package/src/plugins/builtin/vol-surface/index.tsx +1 -1
  398. package/src/plugins/builtin/volatility/headless.ts +6 -1
  399. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  400. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
  401. package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
  402. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  403. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  404. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  405. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  406. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  407. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  408. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  409. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
  410. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  411. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  412. package/src/plugins/builtin/world-venue-map/index.ts +67 -4
  413. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
  414. package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
  415. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  416. package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
  417. package/src/plugins/builtin/world-venue-map/model.ts +7 -4
  418. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  564. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  565. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  566. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  567. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  568. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  569. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  570. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  571. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  572. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  573. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  574. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  575. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  576. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  577. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  578. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  579. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  580. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  581. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  582. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  583. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  584. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  585. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  586. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  587. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  588. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  589. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  590. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  591. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  592. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  593. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  594. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  595. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  596. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  597. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  598. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  599. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  600. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  601. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  602. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  603. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  604. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  605. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  606. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  607. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  608. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  609. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  610. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  611. package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
  612. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  613. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  614. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  615. package/src/plugins/catalog-browser.ts +2 -0
  616. package/src/plugins/catalog-manifest.ts +1 -0
  617. package/src/plugins/catalog-ui.ts +3 -1
  618. package/src/plugins/catalog.ts +1 -1
  619. package/src/plugins/host-link.ts +33 -1
  620. package/src/plugins/installer.ts +48 -12
  621. package/src/plugins/loader.ts +30 -3
  622. package/src/plugins/manager-node.ts +15 -5
  623. package/src/plugins/registry/index.ts +1 -1
  624. package/src/plugins/registry/pane-settings.ts +26 -7
  625. package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
  626. package/src/renderers/dom/build-assets.ts +81 -3
  627. package/src/renderers/dom/data-table/row.tsx +52 -16
  628. package/src/renderers/dom/desktop/controls.tsx +7 -3
  629. package/src/renderers/dom/desktop/icons.tsx +1 -0
  630. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  631. package/src/renderers/dom/desktop/popover.tsx +73 -14
  632. package/src/renderers/dom/host/box.tsx +69 -26
  633. package/src/renderers/dom/host/input.tsx +14 -3
  634. package/src/renderers/dom/host/tabs.tsx +37 -1
  635. package/src/renderers/dom/styles.css +41 -7
  636. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
  637. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
  638. package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
  639. package/src/renderers/electrobun/bun/index.ts +73 -6
  640. package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
  641. package/src/renderers/electrobun/shared/protocol.ts +3 -0
  642. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  643. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
  644. package/src/renderers/electrobun/view/main.tsx +7 -1
  645. package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
  646. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  647. package/src/renderers/electrobun/view/update-host.ts +45 -21
  648. package/src/renderers/opentui/host.tsx +5 -0
  649. package/src/sources/gloomberb-cloud/index.ts +25 -4
  650. package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
  651. package/src/sources/provider-router/cached-routes.ts +4 -1
  652. package/src/sources/provider-router/financials.ts +11 -8
  653. package/src/sources/provider-router/history.ts +15 -10
  654. package/src/sources/sec-registrant.ts +75 -0
  655. package/src/state/app/context/index.tsx +24 -8
  656. package/src/state/hooks/quote-streaming.ts +41 -26
  657. package/src/sync/core-contributors.ts +4 -0
  658. package/src/telemetry/benign-window-error.ts +7 -0
  659. package/src/telemetry/crash-reports-dom.ts +2 -0
  660. package/src/telemetry/crash-reports.ts +4 -1
  661. package/src/test-support/cli-context.ts +10 -2
  662. package/src/test-support/daily-nav.ts +25 -0
  663. package/src/theme/heat-colors.ts +357 -2
  664. package/src/tickers/instrument-kind.ts +34 -7
  665. package/src/tickers/search/asset-classes.ts +24 -9
  666. package/src/tickers/search/index.ts +44 -11
  667. package/src/tickers/search/ranking.ts +23 -3
  668. package/src/time-series/resolve.ts +1 -1
  669. package/src/time-series/use-chart-resolution.ts +1 -1
  670. package/src/types/context-menu.ts +6 -0
  671. package/src/types/data-provider.ts +2 -0
  672. package/src/types/financials.ts +5 -0
  673. package/src/types/headless.ts +79 -2
  674. package/src/types/plugin.ts +38 -6
  675. package/src/types/ticker.ts +15 -0
  676. package/src/ui/context-menu.tsx +1 -0
  677. package/src/ui/host.tsx +16 -0
  678. package/src/updater/index.ts +38 -13
  679. package/src/utils/async-deadline.ts +21 -0
  680. package/src/utils/cli-output.ts +5 -1
  681. package/src/utils/crypto-pair.ts +41 -0
  682. package/src/utils/currency-units.ts +14 -0
  683. package/src/utils/depositary-receipt.ts +26 -0
  684. package/src/utils/exchanges.ts +72 -0
  685. package/src/utils/fire-and-forget.ts +24 -0
  686. package/src/utils/format.ts +13 -0
  687. package/src/utils/price-earnings.ts +70 -3
  688. package/src/utils/price-history.ts +58 -13
  689. package/src/utils/rpc-timeout-error.ts +27 -0
  690. package/src/utils/sec.ts +13 -1
  691. package/src/utils/utc-time.ts +79 -0
@@ -17,11 +17,14 @@ import {
17
17
  formatMarketPriceWithCurrency,
18
18
  formatMarketQuantity,
19
19
  formatSignedMarketPrice,
20
+ withCurrencyMinorDigits,
20
21
  withStablePriceDigits,
21
22
  type MarketFormatOptions,
22
23
  } from "../../../market-data/market/format";
23
24
  import {
24
25
  getActiveQuoteDisplay,
26
+ getCompletedRegularSessionDisplay,
27
+ getExtendedSessionDisplay,
25
28
  marketChangeColor,
26
29
  marketPriceColor,
27
30
  marketStateDot,
@@ -48,6 +51,14 @@ import {
48
51
  type PortfolioPositionPnl,
49
52
  } from "./position-metrics";
50
53
  import { isFiniteNumber } from "../../../utils/guards";
54
+ import {
55
+ allocationFigures,
56
+ formatAllocationDrift,
57
+ formatAllocationWeight,
58
+ formatTradeUnits,
59
+ holdingTarget,
60
+ type AllocationFigures,
61
+ } from "./allocation";
51
62
 
52
63
  export interface ColumnContext {
53
64
  activeTab?: string;
@@ -56,8 +67,14 @@ export interface ColumnContext {
56
67
  exchangeRates: Map<string, number>;
57
68
  /** Clock for quote age (per second while shown) and day-based columns. */
58
69
  now: number;
59
- /** Gross market value of the collection; weights may trail it by about a second. */
70
+ /**
71
+ * The total a portfolio's weights divide by: its priced holdings at net
72
+ * market value plus its cash (see allocation.ts). It may trail the rows by
73
+ * about a second.
74
+ */
60
75
  portfolioTotalMarketValue?: number;
76
+ /** The portfolio's target weights in percent, by symbol. */
77
+ portfolioTargets?: Readonly<Record<string, number>>;
61
78
  supplementalVersion?: number;
62
79
  analystResearch?: Map<string, AnalystResearchData | null>;
63
80
  corporateActions?: Map<string, CorporateActionsData | null>;
@@ -169,19 +186,61 @@ function tradedQuoteDisplay(
169
186
  return valuation && metrics.valuesAtMark ? getActiveQuoteDisplay(quote) : valuation;
170
187
  }
171
188
 
189
+ /**
190
+ * LAST, CHG and CHG% once the regular session is over, and in the pre-market
191
+ * while the quote carries the last session's close and move: that close and its
192
+ * move, frozen, because the EXT% column carries the extended print measured
193
+ * from that close. Until the close, and wherever no close is reported (a
194
+ * pre-market quote without it, venues without extended hours), the traded price
195
+ * as above.
196
+ * Valuation columns (DAY P&L, MKT VAL, weight, P&L) keep the live price.
197
+ * A watchlist's Avg Day averages this CHG%.
198
+ */
199
+ export function headlineQuoteDisplay(
200
+ traded: ActiveQuoteDisplay | null,
201
+ quote: TickerFinancials["quote"],
202
+ ): ActiveQuoteDisplay | null {
203
+ return traded ? getCompletedRegularSessionDisplay(quote) ?? traded : null;
204
+ }
205
+
206
+ /** CHG% as shown: the headline's, else the quote's own when no position price is usable. */
207
+ function headlineChangePercent(
208
+ headline: ActiveQuoteDisplay | null,
209
+ quote: TickerFinancials["quote"],
210
+ ): number | undefined {
211
+ if (headline) return headline.changePercent;
212
+ return quote ? (getCompletedRegularSessionDisplay(quote) ?? quote).changePercent : undefined;
213
+ }
214
+
172
215
  function fiftyTwoWeekPosition(displayQuote: ActiveQuoteDisplay | null, quote: TickerFinancials["quote"]): number | null {
173
216
  const range = displayQuote ? liveFiftyTwoWeekRange(quote, displayQuote.price) : null;
174
217
  return displayQuote && range ? ((displayQuote.price - range.low) / (range.high - range.low)) * 100 : null;
175
218
  }
176
219
 
177
- function getActiveMarketValue(
220
+ /** The row's weight, target, drift and trade, from its own live value and the pane's total. */
221
+ function rowAllocation(
222
+ ticker: TickerRecord,
178
223
  activeQuote: ActiveQuoteDisplay | null,
179
- positionMetrics: ReturnType<typeof getPortfolioPositionMetrics>,
224
+ baseMetrics: ReturnType<typeof getPortfolioPositionMetrics>,
180
225
  toBaseQuote: (value: number) => number,
181
- ): number | null {
182
- return resolvePortfolioMarketValue(positionMetrics, activeQuote ? toBaseQuote(activeQuote.price) : null)?.gross ?? null;
226
+ ctx: ColumnContext,
227
+ ): AllocationFigures & { unpriced: boolean } {
228
+ const held = baseMetrics.positionCount > 0;
229
+ const unitPrice = activeQuote ? toBaseQuote(activeQuote.price) : null;
230
+ const marketValue = held ? resolvePortfolioMarketValue(baseMetrics, unitPrice)?.net ?? null : 0;
231
+ return {
232
+ ...allocationFigures(
233
+ { held, marketValue, units: baseMetrics.totalShares, unitPrice },
234
+ ctx.portfolioTotalMarketValue,
235
+ holdingTarget(ctx.portfolioTargets, ticker.metadata.ticker),
236
+ ),
237
+ unpriced: held && marketValue == null,
238
+ };
183
239
  }
184
240
 
241
+ /** A held position without a price says so where its allocation would be. */
242
+ const UNPRICED = "n/a";
243
+
185
244
  export function resolvePortfolioPriceValue(
186
245
  activeQuote: ActiveQuoteDisplay | null,
187
246
  brokerMarkPrice: number | undefined,
@@ -215,6 +274,7 @@ export function getColumnValue(
215
274
  const positionMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, undefined, quote);
216
275
  const activeQuote = getPortfolioQuoteDisplay(positionMetrics, quote);
217
276
  const displayQuote = tradedQuoteDisplay(positionMetrics, activeQuote, quote);
277
+ const headlineQuote = headlineQuoteDisplay(displayQuote, quote);
218
278
  const { positionCurrency, totalShares, totalCost, totalCostUnits, totalPriceUnits, multiplierHint, brokerMarkPrice } = positionMetrics;
219
279
  const baseMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, {
220
280
  currency: ctx.baseCurrency,
@@ -270,12 +330,12 @@ export function getColumnValue(
270
330
  case "tags":
271
331
  return { text: ticker.metadata.tags.length > 0 ? ticker.metadata.tags.join(",") : "—" };
272
332
  case "price":
273
- return resolvePortfolioPriceValue(displayQuote, brokerMarkPrice, displayQuote ? currentQuoteOptions : markOptions, col.width, quote?.marketState);
333
+ return resolvePortfolioPriceValue(headlineQuote, brokerMarkPrice, headlineQuote ? currentQuoteOptions : markOptions, col.width, quote?.marketState);
274
334
  case "change":
275
- if (!displayQuote) return { text: "—" };
335
+ if (!headlineQuote) return { text: "—" };
276
336
  return {
277
- text: formatSignedMarketPrice(displayQuote.change, { ...currentQuoteOptions, maxWidth: col.width }),
278
- color: marketChangeColor(displayQuote.change, quote?.marketState),
337
+ text: formatSignedMarketPrice(headlineQuote.change, { ...currentQuoteOptions, maxWidth: col.width }),
338
+ color: marketChangeColor(headlineQuote.change, quote?.marketState),
279
339
  };
280
340
  case "bid":
281
341
  return { text: quote?.bid != null ? formatMarketPrice(quote.bid, { ...currentQuoteOptions, maxWidth: col.width }) : "—" };
@@ -297,10 +357,12 @@ export function getColumnValue(
297
357
  if (!isFiniteNumber(quote?.bidSize) && !isFiniteNumber(quote?.askSize)) return { text: "—" };
298
358
  return { text: `${formatCompact(quote?.bidSize)}/${formatCompact(quote?.askSize)}` };
299
359
  }
300
- case "change_pct":
301
- return displayQuote
302
- ? { text: formatPercentRaw(displayQuote.changePercent), color: marketChangeColor(displayQuote.changePercent, quote?.marketState) }
303
- : { text: quote ? formatPercentRaw(quote.changePercent) : "—", color: quote ? marketChangeColor(quote.changePercent, quote.marketState) : undefined };
360
+ case "change_pct": {
361
+ const changePercent = headlineChangePercent(headlineQuote, quote);
362
+ return quote
363
+ ? { text: formatPercentRaw(changePercent), color: marketChangeColor(changePercent, quote.marketState) }
364
+ : { text: "—" };
365
+ }
304
366
  case "volume":
305
367
  return { text: isFiniteNumber(quote?.volume) ? formatCompact(quote.volume, { fixedDecimals: true }) : "—" };
306
368
  case "dollar_volume": {
@@ -324,34 +386,50 @@ export function getColumnValue(
324
386
  const dividendYield = liveDividendYield(quote, fundamentals);
325
387
  return { text: dividendYield != null ? `${(dividendYield * 100).toFixed(2)}%` : "—" };
326
388
  }
327
- case "ext_hours":
328
- if ((quote?.marketState === "PRE" || quote?.marketState === "PREPRE") && quote.preMarketPrice != null) {
329
- const changePercent = quote.preMarketChangePercent;
330
- if (!isFiniteNumber(changePercent)) return { text: "—" };
331
- return { text: formatPercentRaw(changePercent), color: priceColor(changePercent) };
332
- }
333
- if ((quote?.marketState === "POST" || quote?.marketState === "POSTPOST") && quote.postMarketPrice != null) {
334
- const changePercent = quote.postMarketChangePercent;
335
- if (!isFiniteNumber(changePercent)) return { text: "—" };
336
- return { text: formatPercentRaw(changePercent), color: priceColor(changePercent) };
337
- }
338
- return { text: "—" };
389
+ case "ext_hours": {
390
+ const changePercent = getExtendedSessionDisplay(quote)?.changePercent;
391
+ if (!isFiniteNumber(changePercent)) return { text: "—" };
392
+ return { text: formatPercentRaw(changePercent), color: priceColor(changePercent) };
393
+ }
339
394
  case "side":
340
395
  return { text: positionSideLabel(ticker, ctx.activeTab) ?? "—" };
341
396
  case "shares":
342
397
  return { text: positionMetrics.positionCount > 0 ? formatMarketQuantity(totalShares, { ...formatOptions, maxWidth: col.width }) : "—" };
343
398
  case "avg_cost":
344
399
  if (totalCostUnits === 0 || !Number.isFinite(totalCost)) return { text: "—" };
345
- return { text: formatMarketCost(totalCost / Math.abs(totalCostUnits), { ...formatOptions, maxWidth: col.width }) };
400
+ // A money cost keeps its currency's minor unit, as `portfolio show` prints it: 45.50, not 45.5.
401
+ return { text: formatMarketCost(totalCost / Math.abs(totalCostUnits), { ...withCurrencyMinorDigits(formatOptions, positionCurrency), maxWidth: col.width }) };
346
402
  case "cost_basis":
347
403
  if (baseMetrics.positionCount === 0 || !Number.isFinite(baseMetrics.totalCost)) return { text: "—" };
348
404
  return { text: formatCompact(baseMetrics.totalCost) };
349
- case "mkt_value":
350
- return { text: formatCompactAmount(resolvePortfolioMarketValue(baseMetrics, activeQuote ? toBaseQuote(activeQuote.price) : null)?.gross ?? Number.NaN) };
405
+ case "mkt_value": {
406
+ if (baseMetrics.positionCount === 0) return { text: "—" };
407
+ const marketValue = resolvePortfolioMarketValue(baseMetrics, activeQuote ? toBaseQuote(activeQuote.price) : null)?.gross;
408
+ return { text: marketValue == null ? UNPRICED : formatCompactAmount(marketValue) };
409
+ }
351
410
  case "weight": {
352
- const marketValue = getActiveMarketValue(activeQuote, baseMetrics, toBaseQuote);
353
- if (marketValue == null || !ctx.portfolioTotalMarketValue) return { text: "—" };
354
- return { text: formatPercentRaw((marketValue / ctx.portfolioTotalMarketValue) * 100) };
411
+ const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
412
+ return { text: allocation.unpriced ? UNPRICED : formatAllocationWeight(allocation.weight) };
413
+ }
414
+ case "target_weight":
415
+ return { text: formatAllocationWeight(holdingTarget(ctx.portfolioTargets, ticker.metadata.ticker)) };
416
+ case "drift": {
417
+ const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
418
+ if (allocation.unpriced && allocation.targetWeight != null) return { text: UNPRICED };
419
+ const text = formatAllocationDrift(allocation.drift);
420
+ return { text, color: /[1-9]/.test(text) ? priceColor(allocation.drift!) : undefined };
421
+ }
422
+ case "trade": {
423
+ const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
424
+ if (allocation.unpriced && allocation.targetWeight != null) return { text: UNPRICED };
425
+ const text = formatTradeUnits(allocation.tradeUnits, { units: totalShares, assetCategory: ticker.metadata.assetCategory });
426
+ return { text, color: /[1-9]/.test(text) ? priceColor(allocation.tradeUnits!) : undefined };
427
+ }
428
+ case "trade_value": {
429
+ const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
430
+ if (allocation.unpriced && allocation.targetWeight != null) return { text: UNPRICED };
431
+ const text = formatCompactAmount(allocation.tradeValue ?? undefined, { signed: true });
432
+ return { text, color: /[1-9]/.test(text) ? priceColor(allocation.tradeValue!) : undefined };
355
433
  }
356
434
  case "day_pnl":
357
435
  if (activeQuote && isFiniteNumber(activeQuote.change) && Number.isFinite(positionMetrics.grossPriceUnits) && positionMetrics.grossPriceUnits !== 0) {
@@ -438,6 +516,7 @@ export function getSortValue(
438
516
  const positionMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, undefined, quote);
439
517
  const activeQuote = getPortfolioQuoteDisplay(positionMetrics, quote);
440
518
  const displayQuote = tradedQuoteDisplay(positionMetrics, activeQuote, quote);
519
+ const headlineQuote = headlineQuoteDisplay(displayQuote, quote);
441
520
  const { positionCurrency, totalShares, totalCost, totalCostUnits, totalPriceUnits, brokerMarkPrice } = positionMetrics;
442
521
  const baseMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, {
443
522
  currency: ctx.baseCurrency,
@@ -471,7 +550,7 @@ export function getSortValue(
471
550
  case "tags":
472
551
  return ticker.metadata.tags.join(",");
473
552
  case "price":
474
- if (displayQuote) return displayQuote.price;
553
+ if (headlineQuote) return headlineQuote.price;
475
554
  if (brokerMarkPrice != null) return brokerMarkPrice;
476
555
  return null;
477
556
  case "bid":
@@ -490,9 +569,9 @@ export function getSortValue(
490
569
  ? (quote?.bidSize ?? 0) + (quote?.askSize ?? 0)
491
570
  : null;
492
571
  case "change":
493
- return displayQuote?.change ?? null;
572
+ return headlineQuote?.change ?? null;
494
573
  case "change_pct":
495
- return displayQuote?.changePercent ?? null;
574
+ return headlineChangePercent(headlineQuote, quote) ?? null;
496
575
  case "volume":
497
576
  return quote?.volume ?? null;
498
577
  case "dollar_volume":
@@ -512,13 +591,7 @@ export function getSortValue(
512
591
  case "dividend_yield":
513
592
  return liveDividendYield(quote, fundamentals) ?? null;
514
593
  case "ext_hours":
515
- if ((quote?.marketState === "PRE" || quote?.marketState === "PREPRE") && quote.preMarketPrice != null) {
516
- return quote.preMarketChangePercent ?? null;
517
- }
518
- if ((quote?.marketState === "POST" || quote?.marketState === "POSTPOST") && quote.postMarketPrice != null) {
519
- return quote.postMarketChangePercent ?? null;
520
- }
521
- return null;
594
+ return getExtendedSessionDisplay(quote)?.changePercent ?? null;
522
595
  case "side":
523
596
  return positionSideLabel(ticker, ctx.activeTab);
524
597
  case "shares":
@@ -529,12 +602,16 @@ export function getSortValue(
529
602
  return baseMetrics.positionCount > 0 && Number.isFinite(baseMetrics.totalCost) ? baseMetrics.totalCost : null;
530
603
  case "mkt_value":
531
604
  return resolvePortfolioMarketValue(baseMetrics, activeQuote ? toBaseQuote(activeQuote.price) : null)?.gross ?? null;
532
- case "weight": {
533
- const marketValue = getActiveMarketValue(activeQuote, baseMetrics, toBaseQuote);
534
- return marketValue != null && ctx.portfolioTotalMarketValue
535
- ? (marketValue / ctx.portfolioTotalMarketValue) * 100
536
- : null;
537
- }
605
+ case "weight":
606
+ return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).weight;
607
+ case "target_weight":
608
+ return holdingTarget(ctx.portfolioTargets, ticker.metadata.ticker) ?? null;
609
+ case "drift":
610
+ return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).drift;
611
+ case "trade":
612
+ return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).tradeUnits;
613
+ case "trade_value":
614
+ return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).tradeValue;
538
615
  case "day_pnl":
539
616
  if (activeQuote && isFiniteNumber(activeQuote.change) && Number.isFinite(positionMetrics.grossPriceUnits) && positionMetrics.grossPriceUnits !== 0) {
540
617
  return toBaseQuote(totalPriceUnits * activeQuote.change);
@@ -3,6 +3,7 @@ import type {
3
3
  HeadlessPaneColumn,
4
4
  HeadlessPaneContext,
5
5
  HeadlessPaneDefinition,
6
+ HeadlessPaneRow,
6
7
  HeadlessRowsResult,
7
8
  } from "../../../types/plugin";
8
9
  import type { TickerRecord } from "../../../types/ticker";
@@ -10,10 +11,20 @@ import { formatNumber, formatPercentRaw } from "../../../utils/format";
10
11
  import {
11
12
  findCollection,
12
13
  loadCollectionQuotes,
14
+ valuePortfolioAllocation,
13
15
  valuePortfolioPositions,
14
16
  type CollectionMatch,
15
17
  } from "./cli/render";
18
+ import {
19
+ CASH_SYMBOL,
20
+ describeTargetSum,
21
+ formatAllocationDrift,
22
+ formatAllocationWeight,
23
+ formatTradeUnits,
24
+ } from "./allocation";
25
+ import { currencyMinorDigits, formatMarketPrice, formatMarketQuantity } from "../../../market-data/market/format";
16
26
  import { resolvePortfolioTotalsCurrency } from "./summary/totals";
27
+ import { quoteFreshnessFields } from "../shared/report-freshness";
17
28
 
18
29
  const DEFAULT_ROW_LIMIT = 50;
19
30
  const MAX_ROW_LIMIT = 200;
@@ -21,22 +32,50 @@ const MAX_ROW_LIMIT = 200;
21
32
  const LISTED_COLLECTION_IDS = 12;
22
33
 
23
34
  const amount = (value: unknown) => formatNumber(typeof value === "number" ? value : undefined, 2);
35
+ /** Market values and trades in whole units, as `portfolio show` prints them. */
36
+ const wholeAmount = (value: unknown) => formatNumber(typeof value === "number" ? value : undefined, 0);
37
+ const signedAmount = (value: unknown) => (
38
+ typeof value === "number" && Number.isFinite(value) ? `${value > 0 && /[1-9]/.test(wholeAmount(value)) ? "+" : ""}${wholeAmount(value)}` : formatNumber(undefined)
39
+ );
24
40
  const percent = (value: unknown) => formatPercentRaw(typeof value === "number" ? value : undefined);
25
- const share = (value: unknown) => (
26
- typeof value === "number" && Number.isFinite(value) ? `${formatNumber(value, 2)}%` : formatNumber(undefined)
41
+ const weight = (value: unknown) => formatAllocationWeight(typeof value === "number" ? value : null);
42
+ const drift = (value: unknown) => formatAllocationDrift(typeof value === "number" ? value : null);
43
+ const quantity = (value: unknown, row: HeadlessPaneRow) => (
44
+ typeof value === "number" ? formatMarketQuantity(value, { assetCategory: textOf(row.assetCategory) }) : formatNumber(undefined)
45
+ );
46
+ const tradeUnits = (value: unknown, row: HeadlessPaneRow) => (
47
+ typeof value === "number" ? formatTradeUnits(value, { units: finite(row.shares) ?? 0, assetCategory: textOf(row.assetCategory) }) : formatNumber(undefined)
27
48
  );
49
+ /** Money per unit at the currency's minor digits: $230.00, not 230. */
50
+ const unitMoney = (currencyKey: string) => (value: unknown, row: HeadlessPaneRow) => (
51
+ typeof value === "number"
52
+ ? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits: Math.min(2, currencyMinorDigits(textOf(row[currencyKey]))) })
53
+ : formatNumber(undefined)
54
+ );
55
+
56
+ function textOf(value: unknown): string | undefined {
57
+ return typeof value === "string" && value ? value : undefined;
58
+ }
28
59
 
29
60
  const POSITION_COLUMNS: HeadlessPaneColumn[] = [
30
61
  { key: "symbol", header: "Ticker" },
31
62
  { key: "name", header: "Name" },
32
- { key: "shares", header: "Qty", align: "right" },
33
- { key: "avgCost", header: "Avg Cost", align: "right", description: "Per unit, in the position's currency." },
34
- { key: "price", header: "Last", align: "right", description: "In the quote's currency." },
63
+ { key: "shares", header: "Qty", align: "right", format: quantity },
64
+ { key: "avgCost", header: "Avg Cost", align: "right", format: unitMoney("positionCurrency"), description: "Per unit, in the position's currency." },
65
+ { key: "price", header: "Last", align: "right", format: unitMoney("priceCurrency"), description: "In the quote's currency." },
35
66
  { key: "priceCurrency", header: "Ccy" },
36
67
  { key: "changePercent", header: "Chg", align: "right", format: percent },
37
- { key: "marketValue", header: "Mkt Val", align: "right", format: amount, description: "In the portfolio's currency; negative for shorts." },
68
+ { key: "marketValue", header: "Mkt Val", align: "right", format: wholeAmount, description: "In the portfolio's currency; negative for shorts." },
38
69
  { key: "unrealizedPnl", header: "P&L", align: "right", format: amount, description: "Unrealized, in the portfolio's currency." },
39
- { key: "weight", header: "Weight", align: "right", format: share, description: "Percent of the portfolio's gross market value." },
70
+ { key: "weight", header: "Weight", align: "right", format: weight, description: "Percent of the total value, cash included; unpriced holdings are left out." },
71
+ ];
72
+
73
+ /** Shown once the portfolio has a target weight. */
74
+ const TARGET_COLUMNS: HeadlessPaneColumn[] = [
75
+ { key: "targetWeight", header: "Target", align: "right", format: weight, description: "Target weight, in percent." },
76
+ { key: "drift", header: "Drift", align: "right", format: drift, description: "Weight minus target, in percentage points." },
77
+ { key: "tradeShares", header: "Trade", align: "right", format: tradeUnits, description: "Units to buy (+) or sell (-) to reach the target at the current price." },
78
+ { key: "tradeValue", header: "Trade Value", align: "right", format: signedAmount, description: "The trade in the portfolio's currency." },
40
79
  ];
41
80
 
42
81
  const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
@@ -97,26 +136,36 @@ async function portfolioHoldings(
97
136
  const currency = resolvePortfolioTotalsCurrency(target.portfolio, ctx.config.baseCurrency);
98
137
  const quotes = await loadCollectionQuotes(tickers, target, ctx.marketData);
99
138
  ctx.signal.throwIfAborted();
139
+ const toBase = createBaseConverter(ctx.marketData, currency);
100
140
  const valuation = await valuePortfolioPositions({
101
141
  tickers,
102
142
  quotes,
103
143
  portfolioId: target.id,
104
144
  currency,
105
145
  baseCurrency: ctx.config.baseCurrency,
106
- toBase: createBaseConverter(ctx.marketData, currency),
146
+ toBase,
107
147
  });
148
+ const { allocation, cash } = await valuePortfolioAllocation({ valuation, portfolio: resolved.portfolio, account: resolved.account, toBase });
108
149
  ctx.signal.throwIfAborted();
109
150
 
151
+ const allocationBySymbol = new Map(allocation.rows.map((row) => [row.symbol, row]));
110
152
  const held = valuation.positions.filter((entry) => entry.position);
111
153
  const gross = held.reduce((sum, entry) => sum + Math.abs(finite(entry.row.marketValue) ?? 0), 0);
112
154
  const sum = (key: string) => held.reduce((total, entry) => total + (finite(entry.row[key]) ?? 0), 0);
155
+ const seen = new Set<string>();
113
156
  const rows = held
114
157
  .map(({ ticker, activeQuote, row }) => {
115
158
  const marketValue = finite(row.marketValue);
159
+ // A ticker held in several lots carries its allocation on its first row.
160
+ const figures = seen.has(ticker.metadata.ticker) ? undefined : allocationBySymbol.get(ticker.metadata.ticker);
161
+ seen.add(ticker.metadata.ticker);
116
162
  return {
163
+ ...quoteFreshnessFields(quotes.get(ticker.metadata.ticker)),
164
+ updatedAt: quotes.get(ticker.metadata.ticker)?.lastUpdated ?? null,
117
165
  symbol: ticker.metadata.ticker,
118
166
  name: ticker.metadata.name ?? null,
119
167
  exchange: ticker.metadata.exchange || null,
168
+ assetCategory: ticker.metadata.assetCategory ?? null,
120
169
  shares: finite(row.shares),
121
170
  avgCost: finite(row.avgCost),
122
171
  positionCurrency: row.positionCurrency ?? null,
@@ -125,7 +174,11 @@ async function portfolioHoldings(
125
174
  changePercent: finite(activeQuote?.changePercent),
126
175
  marketValue,
127
176
  unrealizedPnl: finite(row.unrealizedPnl),
128
- weight: marketValue != null && gross > 0 ? (Math.abs(marketValue) / gross) * 100 : null,
177
+ weight: figures?.weight ?? null,
178
+ targetWeight: figures?.targetWeight ?? null,
179
+ drift: figures?.drift ?? null,
180
+ tradeShares: figures?.tradeUnits ?? null,
181
+ tradeValue: figures?.tradeValue ?? null,
129
182
  };
130
183
  })
131
184
  // Largest exposure first; a position without a market value sorts last.
@@ -133,16 +186,39 @@ async function portfolioHoldings(
133
186
  exposure(right.marketValue) - exposure(left.marketValue)
134
187
  || left.symbol.localeCompare(right.symbol)
135
188
  ));
136
- const shown = rows.slice(0, limit);
189
+ const shown: HeadlessPaneRow[] = rows.slice(0, limit);
190
+ // The cash line follows the positions, whatever the limit.
191
+ if (allocation.cash) {
192
+ shown.push({
193
+ symbol: CASH_SYMBOL,
194
+ name: cash?.source === "broker" ? "Cash (broker account)" : "Cash",
195
+ priceCurrency: cash?.currency ?? null,
196
+ marketValue: finite(allocation.cash.value),
197
+ weight: allocation.cash.weight,
198
+ targetWeight: allocation.cash.targetWeight,
199
+ drift: allocation.cash.drift,
200
+ tradeShares: null,
201
+ tradeValue: allocation.cash.tradeValue,
202
+ });
203
+ }
137
204
  const unavailable = [...new Set([...valuation.unavailableMarketValue, ...valuation.unavailablePnl])];
138
205
  const broker = !!(target.portfolio.brokerId || target.portfolio.brokerInstanceId);
206
+ const showTargets = allocation.targetSum != null;
207
+ const targetNote = describeTargetSum(allocation.targetSum);
208
+ const notices = [
209
+ ...(rows.length > limit
210
+ ? [`${rows.length - limit} more position${rows.length - limit === 1 ? "" : "s"} not shown; totals include every position.`]
211
+ : []),
212
+ ...(targetNote ? [targetNote] : []),
213
+ ];
139
214
 
140
215
  return {
141
- columns: POSITION_COLUMNS,
216
+ freshness: { source: broker ? "Your broker account and Gloom Cloud" : "Local portfolio and Gloom Cloud" },
217
+ columns: showTargets ? [...POSITION_COLUMNS, ...TARGET_COLUMNS] : POSITION_COLUMNS,
142
218
  rows: shown,
143
219
  complete: unavailable.length === 0,
144
220
  ...(unavailable.length
145
- ? { errors: [`No market value or P&L for ${unavailable.join(", ")}; totals leave them out.`] }
221
+ ? { errors: [`No market value or P&L for ${unavailable.join(", ")}; totals and weights leave them out.`] }
146
222
  : {}),
147
223
  metadata: {
148
224
  collection: { kind: "portfolio", id: target.id, name: target.name, broker },
@@ -153,10 +229,13 @@ async function portfolioHoldings(
153
229
  grossMarketValue: gross,
154
230
  costBasis: sum("costBasis"),
155
231
  unrealizedPnl: valuation.totalPnl,
232
+ cash: allocation.cash ? finite(allocation.cash.value) : null,
233
+ total: allocation.total,
156
234
  },
157
- ...(rows.length > shown.length
158
- ? { notices: [`${rows.length - shown.length} more position${rows.length - shown.length === 1 ? "" : "s"} not shown; totals include every position.`] }
159
- : {}),
235
+ ...(cash ? { cash } : {}),
236
+ ...(showTargets ? { targetSum: allocation.targetSum } : {}),
237
+ unpricedCount: allocation.unpriced.length,
238
+ ...(notices.length > 0 ? { notices } : {}),
160
239
  },
161
240
  };
162
241
  }
@@ -174,6 +253,8 @@ async function watchlistHoldings(
174
253
  const rows = tickers.map((ticker) => {
175
254
  const quote = quotes.get(ticker.metadata.ticker);
176
255
  return {
256
+ ...quoteFreshnessFields(quote),
257
+ updatedAt: quote?.lastUpdated ?? null,
177
258
  symbol: ticker.metadata.ticker,
178
259
  name: ticker.metadata.name ?? null,
179
260
  exchange: ticker.metadata.exchange || null,
@@ -184,6 +265,7 @@ async function watchlistHoldings(
184
265
  });
185
266
  const shown = rows.slice(0, limit);
186
267
  return {
268
+ freshness: { source: "Local watchlist and Gloom Cloud" },
187
269
  columns: WATCHLIST_COLUMNS,
188
270
  rows: shown,
189
271
  metadata: {
@@ -204,7 +286,7 @@ async function watchlistHoldings(
204
286
  export const collectionHoldingsHeadless: HeadlessPaneDefinition<"rows"> = {
205
287
  shape: "rows",
206
288
  description:
207
- "Positions held in a portfolio, broker or manual: symbol, quantity, average cost, last price, market value, unrealized P&L and weight, largest first, with totals. For a watchlist, its tickers with quotes. Takes a portfolio or watchlist ID; the first portfolio when omitted.",
289
+ "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.",
208
290
  discovery: {
209
291
  dataRequirements: ["Local portfolios, watchlists and synced broker positions; current quotes"],
210
292
  limitations: ["Unrealized P&L on current positions; excludes realized trades, distributions and cash flows"],
@@ -9,6 +9,7 @@ import {
9
9
  import { portfolioCliCommand } from "./cli/portfolio-command";
10
10
  import { watchlistCliCommand } from "./cli/watchlist-command";
11
11
  import { collectionHoldingsHeadless } from "./headless";
12
+ import { findCollection } from "./cli/render";
12
13
  import {
13
14
  LIVE_STREAMING_QUICK_SETTING,
14
15
  withLiveStreamingSetting,
@@ -30,8 +31,13 @@ function resolveCollectionIdForKind(context: PaneTemplateContext, kind: "portfol
30
31
  function createCollectionPaneInstance(
31
32
  context: PaneTemplateContext,
32
33
  kind?: "portfolio" | "watchlist",
34
+ argument?: string,
33
35
  ): PaneTemplateInstanceConfig | null {
34
- const collectionId = kind ? resolveCollectionIdForKind(context, kind) : resolveCollectionPaneId(context);
36
+ // `PF Retirement` (or `shot PF Retirement`) opens the collection it names.
37
+ const named = argument?.trim() ? findCollection(context.config, argument) : null;
38
+ const collectionId = named && (!kind || named.kind === kind)
39
+ ? named.id
40
+ : kind ? resolveCollectionIdForKind(context, kind) : resolveCollectionPaneId(context);
35
41
  return collectionId ? { params: { collectionId } } : null;
36
42
  }
37
43
 
@@ -39,6 +45,7 @@ export const portfolioListModule: PluginModule = {
39
45
  panes: [
40
46
  {
41
47
  id: "portfolio-list",
48
+ reportFreshness: { source: "Local portfolio and Gloom Cloud" },
42
49
  name: "Portfolio",
43
50
  icon: "P",
44
51
  component: PortfolioListPane,
@@ -75,11 +82,15 @@ export const portfolioListModule: PluginModule = {
75
82
  paneId: "portfolio-list",
76
83
  label: "Collection Pane",
77
84
  description: "Open another pane for the current portfolio or watchlist",
78
- keywords: ["portfolio", "watchlist", "collection", "pane", "list"],
85
+ // Phrases rather than bare words, so `fn rebalance` and `fn target` keep resolving where they did.
86
+ keywords: [
87
+ "portfolio", "watchlist", "collection", "pane", "list",
88
+ "portfolio rebalance", "allocation drift", "target weights", "asset allocation", "cash balance",
89
+ ],
79
90
  shortcut: { prefix: "PF" },
80
91
  headless: collectionHoldingsHeadless,
81
92
  canCreate: (context) => resolveCollectionPaneId(context) !== null,
82
- createInstance: (context) => createCollectionPaneInstance(context),
93
+ createInstance: (context, options) => createCollectionPaneInstance(context, undefined, options?.arg),
83
94
  },
84
95
  {
85
96
  id: "new-portfolio-pane",
@@ -1,6 +1,7 @@
1
1
  import type { AnalystResearchData, Fundamentals, Quote } from "../../../types/financials";
2
2
  import { hasLikelyQuoteUnitMismatch } from "../../../utils/currency-units";
3
3
  import { selectMarketCapitalization, type MarketCapitalization } from "../../../utils/market-capitalization";
4
+ import { priceEarningsOnEarnings, type PriceEarnings } from "../../../utils/price-earnings";
4
5
 
5
6
  /**
6
7
  * Price-derived statistics repriced from the current quote with the base
@@ -53,13 +54,14 @@ function repriceMultiple(
53
54
  return price / perShare;
54
55
  }
55
56
 
56
- /** Trailing P/E over the current price. Zero or negative EPS keeps the stored multiple. */
57
- export function liveTrailingPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): number | undefined {
58
- return repriceMultiple(fundamentals?.trailingPE, fundamentals?.eps, quote, fundamentals);
57
+ /** Trailing P/E over the current price; not meaningful when the trailing EPS is zero or a loss. */
58
+ export function liveTrailingPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): PriceEarnings | undefined {
59
+ return priceEarningsOnEarnings(repriceMultiple(fundamentals?.trailingPE, fundamentals?.eps, quote, fundamentals), fundamentals?.eps);
59
60
  }
60
61
 
61
- export function liveForwardPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): number | undefined {
62
- return repriceMultiple(fundamentals?.forwardPE, fundamentals?.forwardEps, quote, fundamentals);
62
+ /** Forward P/E over the current price; not meaningful when the forward EPS behind it is zero or a loss. */
63
+ export function liveForwardPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): PriceEarnings | undefined {
64
+ return priceEarningsOnEarnings(repriceMultiple(fundamentals?.forwardPE, fundamentals?.forwardEps, quote, fundamentals), fundamentals?.forwardEps);
63
65
  }
64
66
 
65
67
  /** Forward dividend yield over the current price, as a ratio like the stored yield. */