gloomberb 0.16.1 → 0.16.3

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 (643) 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 +26 -8
  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 +2 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/paths.ts +30 -1
  10. package/src/api-client/perps.ts +37 -0
  11. package/src/api-client/request.ts +5 -2
  12. package/src/api-client/types.ts +2 -0
  13. package/src/brokers/account-cache.ts +69 -0
  14. package/src/cli/command-options.ts +74 -0
  15. package/src/cli/commands/command-utils.ts +37 -0
  16. package/src/cli/commands/crypto-hints.ts +75 -0
  17. package/src/cli/commands/market.ts +560 -136
  18. package/src/cli/commands/overview.ts +136 -48
  19. package/src/cli/commands/ticker.ts +220 -67
  20. package/src/cli/desktop-pane-shot.ts +37 -4
  21. package/src/cli/freshness.ts +61 -0
  22. package/src/cli/help.ts +27 -6
  23. package/src/cli/helpers.ts +4 -8
  24. package/src/cli/history-rows.ts +187 -15
  25. package/src/cli/index.ts +23 -8
  26. package/src/cli/listing-arg.ts +321 -0
  27. package/src/cli/options.ts +5 -1
  28. package/src/cli/pane-functions/access-gate.ts +42 -0
  29. package/src/cli/pane-functions/capabilities.ts +5 -0
  30. package/src/cli/pane-functions/catalog.ts +28 -1
  31. package/src/cli/pane-functions/data.ts +3 -1
  32. package/src/cli/pane-functions/dom.ts +87 -16
  33. package/src/cli/pane-functions/freshness.ts +400 -0
  34. package/src/cli/pane-functions/function-help.ts +31 -22
  35. package/src/cli/pane-functions/headless.ts +201 -41
  36. package/src/cli/pane-functions/index.ts +24 -6
  37. package/src/cli/pane-functions/options.ts +3 -0
  38. package/src/cli/pane-functions/report.ts +12 -1
  39. package/src/cli/pane-functions/resolver.ts +63 -9
  40. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  41. package/src/cli/pane-functions/screenshot.ts +11 -3
  42. package/src/cli/registry.ts +6 -3
  43. package/src/cli/report-tables.ts +460 -0
  44. package/src/cli/result.ts +53 -29
  45. package/src/cli/ticker-resolution.ts +7 -5
  46. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  47. package/src/components/chart/composite/drawing-store.ts +59 -0
  48. package/src/components/chart/composite/legend.tsx +319 -0
  49. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  50. package/src/components/chart/composite/panel-gestures.ts +59 -0
  51. package/src/components/chart/composite/panel-labels.ts +107 -0
  52. package/src/components/chart/composite/panel-surface.tsx +876 -0
  53. package/src/components/chart/composite/tool-catalog.ts +98 -0
  54. package/src/components/chart/composite/toolbar.tsx +186 -0
  55. package/src/components/chart/composite/tools.ts +8 -0
  56. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  57. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  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/ticker-search/actions.ts +5 -0
  62. package/src/components/command-bar/workflow/ops.ts +1 -1
  63. package/src/components/command-bar/workflow/tickers.ts +6 -0
  64. package/src/components/data-table/export.ts +6 -51
  65. package/src/components/data-table/view.tsx +32 -11
  66. package/src/components/feedback-dialog.tsx +2 -1
  67. package/src/components/form-modal/field-row.tsx +2 -2
  68. package/src/components/layout/detached-pane-shell.tsx +6 -3
  69. package/src/components/layout/pane/content.tsx +23 -10
  70. package/src/components/layout/pane/error-boundary.tsx +103 -0
  71. package/src/components/layout/pane/footer/registration.tsx +68 -23
  72. package/src/components/layout/pane/header.tsx +11 -11
  73. package/src/components/layout/shell/active-drag.ts +67 -35
  74. package/src/components/layout/shell/cursor-occlusion.ts +6 -5
  75. package/src/components/layout/shell/drag/index.ts +12 -7
  76. package/src/components/layout/shell/drag/live.ts +122 -0
  77. package/src/components/layout/shell/drag/overlays.tsx +179 -35
  78. package/src/components/layout/shell/drag/runtime.ts +62 -50
  79. package/src/components/layout/shell/drag/slide.ts +10 -0
  80. package/src/components/layout/shell/index.tsx +37 -51
  81. package/src/components/layout/shell/menu.ts +2 -1
  82. package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
  83. package/src/components/layout/shell/native/surfaces.ts +30 -14
  84. package/src/components/layout/shell/pane/actions.ts +2 -1
  85. package/src/components/layout/shell/pane/layers.tsx +419 -168
  86. package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
  87. package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
  88. package/src/components/metric-treemap/heat-surface.tsx +43 -16
  89. package/src/components/metric-treemap/heat-tiles.ts +18 -0
  90. package/src/components/metric-treemap/layout.ts +2 -0
  91. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  92. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  93. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  94. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  95. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  96. package/src/components/ticker/list-table-view.tsx +13 -1
  97. package/src/components/ui/fields.tsx +8 -0
  98. package/src/components/ui/range-track.tsx +10 -3
  99. package/src/components/ui/status.tsx +8 -2
  100. package/src/components/ui/tabs.tsx +7 -4
  101. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  102. package/src/data/config/store/normalize.ts +17 -1
  103. package/src/data/json-persistence.ts +17 -3
  104. package/src/data/json-storage.ts +2 -0
  105. package/src/data/memory-resource-store.ts +46 -0
  106. package/src/i18n/es.ts +19 -1
  107. package/src/i18n/ja.ts +19 -1
  108. package/src/i18n/ko.ts +19 -1
  109. package/src/i18n/zh-cn.ts +19 -1
  110. package/src/i18n/zh-tw.ts +19 -1
  111. package/src/market-data/coordinator/chart.ts +1 -1
  112. package/src/market-data/coordinator/quotes.ts +23 -4
  113. package/src/market-data/fx-closes.ts +72 -0
  114. package/src/market-data/market/freshness.ts +123 -6
  115. package/src/market-data/market/session-close-note.ts +57 -0
  116. package/src/market-data/market/status.ts +151 -0
  117. package/src/market-data/published-apac-sessions.ts +66 -0
  118. package/src/market-data/quotes/contributions.ts +2 -0
  119. package/src/market-data/quotes/freshness.ts +5 -0
  120. package/src/market-data/quotes/resolution.ts +2 -0
  121. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  122. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  123. package/src/plugins/builtin/alerts/cli.ts +10 -5
  124. package/src/plugins/builtin/alerts/index.tsx +1 -0
  125. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  126. package/src/plugins/builtin/analytics/pane-model.ts +10 -6
  127. package/src/plugins/builtin/analytics/risk-client.ts +191 -66
  128. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  129. package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
  130. package/src/plugins/builtin/analytics/risk-model.ts +45 -17
  131. package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
  132. package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
  133. package/src/plugins/builtin/attention/headless.ts +6 -4
  134. package/src/plugins/builtin/attention/index.tsx +1 -1
  135. package/src/plugins/builtin/attention/pane.tsx +2 -2
  136. package/src/plugins/builtin/awards/headless.ts +1 -0
  137. package/src/plugins/builtin/awards/pane.tsx +1 -1
  138. package/src/plugins/builtin/backtest/headless.ts +1 -0
  139. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  140. package/src/plugins/builtin/buildout/index.tsx +1 -0
  141. package/src/plugins/builtin/catalysts/detail.tsx +1 -1
  142. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  143. package/src/plugins/builtin/cds/headless.ts +2 -0
  144. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  145. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  146. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  147. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  148. package/src/plugins/builtin/chat/channels.ts +19 -3
  149. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  150. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  151. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  152. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  153. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  154. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  155. package/src/plugins/builtin/chat/index.tsx +1 -0
  156. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  157. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  158. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  159. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  160. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  161. package/src/plugins/builtin/chat/message/types.ts +14 -2
  162. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  163. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  164. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  165. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  166. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  167. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  168. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  169. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  170. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  171. package/src/plugins/builtin/company-attention/pane.tsx +2 -2
  172. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  173. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  174. package/src/plugins/builtin/correlation/compute.ts +59 -16
  175. package/src/plugins/builtin/correlation/geo.ts +34 -0
  176. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  177. package/src/plugins/builtin/correlation/headless.ts +42 -8
  178. package/src/plugins/builtin/correlation/history.ts +2 -0
  179. package/src/plugins/builtin/correlation/index.tsx +68 -14
  180. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  181. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  182. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  183. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  184. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  185. package/src/plugins/builtin/correlation/settings.ts +1 -1
  186. package/src/plugins/builtin/cot/headless.ts +6 -3
  187. package/src/plugins/builtin/cot/index.tsx +3 -3
  188. package/src/plugins/builtin/cot/model.ts +36 -3
  189. package/src/plugins/builtin/cpi/headless.ts +4 -0
  190. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  191. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  192. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  193. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  194. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  195. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  196. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  197. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  198. package/src/plugins/builtin/doe/headless.ts +7 -0
  199. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  200. package/src/plugins/builtin/earnings/headless.ts +5 -0
  201. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  202. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  203. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  204. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  205. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  206. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  207. package/src/plugins/builtin/econ/index.tsx +1 -0
  208. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  209. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  210. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  211. package/src/plugins/builtin/executives/index.tsx +1 -0
  212. package/src/plugins/builtin/exposure/headless.ts +3 -1
  213. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  214. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  215. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  216. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  217. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  218. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  219. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  220. package/src/plugins/builtin/gpu/headless.ts +7 -3
  221. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  222. package/src/plugins/builtin/gpu/model.ts +27 -1
  223. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  224. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  225. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  226. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  227. package/src/plugins/builtin/holders/client.ts +3 -6
  228. package/src/plugins/builtin/holders/format.ts +31 -1
  229. package/src/plugins/builtin/holders/headless.ts +161 -6
  230. package/src/plugins/builtin/holders/index.tsx +10 -3
  231. package/src/plugins/builtin/holders/pane.tsx +42 -16
  232. package/src/plugins/builtin/holders/report-header.ts +136 -0
  233. package/src/plugins/builtin/holders/table-model.ts +20 -5
  234. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  235. package/src/plugins/builtin/holders/types.ts +2 -1
  236. package/src/plugins/builtin/insider/headless.ts +2 -0
  237. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  238. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  239. package/src/plugins/builtin/jobs/headless.ts +1 -0
  240. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  241. package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
  242. package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
  243. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  244. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  245. package/src/plugins/builtin/market-heatmap/data.ts +2 -0
  246. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  247. package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
  248. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  249. package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
  250. package/src/plugins/builtin/market-movers/headless.ts +2 -0
  251. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  252. package/src/plugins/builtin/members/client.ts +20 -3
  253. package/src/plugins/builtin/members/headless.ts +5 -3
  254. package/src/plugins/builtin/members/model.ts +10 -2
  255. package/src/plugins/builtin/members/pane.tsx +23 -6
  256. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  257. package/src/plugins/builtin/mna/headless.ts +1 -0
  258. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  259. package/src/plugins/builtin/news/headless.ts +2 -0
  260. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  261. package/src/plugins/builtin/notes/cli.ts +14 -6
  262. package/src/plugins/builtin/notes/index.tsx +1 -0
  263. package/src/plugins/builtin/openfda/index.tsx +1 -0
  264. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  265. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  266. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  267. package/src/plugins/builtin/pe-band/client.ts +48 -3
  268. package/src/plugins/builtin/pe-band/headless.ts +25 -7
  269. package/src/plugins/builtin/pe-band/model.ts +92 -16
  270. package/src/plugins/builtin/pe-band/pane.tsx +33 -16
  271. package/src/plugins/builtin/perps/client.ts +50 -3
  272. package/src/plugins/builtin/perps/headless.ts +144 -16
  273. package/src/plugins/builtin/perps/index.tsx +6 -6
  274. package/src/plugins/builtin/perps/model.ts +189 -12
  275. package/src/plugins/builtin/perps/pane.tsx +249 -48
  276. package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
  277. package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
  278. package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -0
  279. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  280. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  281. package/src/plugins/builtin/portfolio-list/cli/render.ts +232 -39
  282. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  283. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  284. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  285. package/src/plugins/builtin/portfolio-list/headless.ts +100 -16
  286. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  287. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  288. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  289. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  290. package/src/plugins/builtin/portfolio-list/pane/index.tsx +53 -16
  291. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  292. package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
  293. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
  294. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  295. package/src/plugins/builtin/power/headless.ts +3 -1
  296. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  297. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  298. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  299. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  300. package/src/plugins/builtin/research/events-headless.ts +2 -0
  301. package/src/plugins/builtin/research/headless.ts +2 -0
  302. package/src/plugins/builtin/research/index.tsx +1 -0
  303. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  304. package/src/plugins/builtin/research/relative-valuation-model.ts +18 -6
  305. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  306. package/src/plugins/builtin/research-search/index.tsx +1 -0
  307. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  308. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  309. package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
  310. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  311. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  312. package/src/plugins/builtin/scanner/headless.ts +14 -0
  313. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  314. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  315. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  316. package/src/plugins/builtin/sec/forms.ts +12 -0
  317. package/src/plugins/builtin/sec/headless.ts +2 -0
  318. package/src/plugins/builtin/sectors/client.ts +1 -0
  319. package/src/plugins/builtin/sectors/headless.ts +9 -1
  320. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  321. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  322. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  323. package/src/plugins/builtin/shared/members-menu.tsx +260 -0
  324. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  325. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  326. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  327. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  328. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  329. package/src/plugins/builtin/short-volume/pane.tsx +1 -1
  330. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  331. package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
  332. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  333. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  334. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  335. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  336. package/src/plugins/builtin/themes/headless.ts +3 -0
  337. package/src/plugins/builtin/themes/pane.tsx +3 -0
  338. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  339. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  340. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
  341. package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
  342. package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
  343. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  344. package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
  345. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
  346. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  347. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  348. package/src/plugins/builtin/volatility/headless.ts +6 -1
  349. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  350. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +159 -0
  351. package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
  352. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  353. package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
  354. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  355. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  356. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  357. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  358. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  359. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  360. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +448 -0
  361. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  362. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  363. package/src/plugins/builtin/world-venue-map/index.ts +69 -6
  364. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
  365. package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
  366. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  367. package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
  368. package/src/plugins/builtin/world-venue-map/model.ts +23 -4
  369. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
  370. package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
  371. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  372. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  373. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  374. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  375. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  376. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  377. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  378. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  379. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  380. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  381. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  382. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  383. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  384. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  385. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  386. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  387. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  388. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  389. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  390. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  391. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  392. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  393. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  394. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  395. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  396. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  397. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  398. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  399. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  400. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  401. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  402. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  403. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  404. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  405. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  406. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  407. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  408. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  409. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  410. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  411. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  412. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  413. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  414. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  415. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  416. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  417. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  418. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/pane.tsx +35 -44
  564. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  565. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  566. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  567. package/src/plugins/loader.ts +13 -1
  568. package/src/plugins/registry/pane-settings.ts +1 -0
  569. package/src/renderers/browser/app-services.ts +3 -1
  570. package/src/renderers/dom/build-assets.ts +81 -3
  571. package/src/renderers/dom/data-table/dom.ts +31 -0
  572. package/src/renderers/dom/data-table/index.tsx +5 -0
  573. package/src/renderers/dom/data-table/row.tsx +2 -0
  574. package/src/renderers/dom/desktop/controls.tsx +7 -3
  575. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  576. package/src/renderers/dom/desktop/popover.tsx +73 -14
  577. package/src/renderers/dom/host/box.tsx +113 -17
  578. package/src/renderers/dom/host/drag-shield.ts +24 -0
  579. package/src/renderers/dom/host/input.tsx +14 -3
  580. package/src/renderers/dom/host/live-frame.ts +54 -0
  581. package/src/renderers/dom/host/mouse.ts +8 -1
  582. package/src/renderers/dom/host/scroll-box.tsx +6 -5
  583. package/src/renderers/dom/host/tabs.tsx +3 -2
  584. package/src/renderers/dom/styles.css +16 -9
  585. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
  586. package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
  587. package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
  588. package/src/renderers/electrobun/shared/protocol.ts +10 -1
  589. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  590. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
  591. package/src/renderers/electrobun/view/host/native.ts +0 -10
  592. package/src/renderers/electrobun/view/host/window-move.ts +28 -0
  593. package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
  594. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  595. package/src/renderers/electrobun/view/ui-host.tsx +2 -5
  596. package/src/renderers/opentui/host.tsx +5 -0
  597. package/src/renderers/opentui/ui-host.tsx +7 -1
  598. package/src/sources/gloomberb-cloud/index.ts +25 -4
  599. package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
  600. package/src/sources/provider-router/batches.ts +3 -3
  601. package/src/sources/provider-router/cached-routes.ts +4 -1
  602. package/src/sources/provider-router/financial-routes.ts +2 -2
  603. package/src/sources/provider-router/financials.ts +76 -12
  604. package/src/sources/provider-router/history.ts +15 -10
  605. package/src/sources/provider-router/primary.ts +2 -2
  606. package/src/sources/sec-registrant.ts +75 -0
  607. package/src/state/app/context/index.tsx +24 -8
  608. package/src/state/hooks/quote-streaming.ts +41 -26
  609. package/src/state/pane-scroll-registry.tsx +67 -35
  610. package/src/sync/core-contributors.ts +4 -0
  611. package/src/telemetry/crash-reports.ts +4 -1
  612. package/src/test-support/cli-context.ts +10 -2
  613. package/src/test-support/margin-account.ts +108 -0
  614. package/src/theme/heat-colors.ts +266 -84
  615. package/src/time-series/resolution.ts +15 -0
  616. package/src/time-series/resolve.ts +1 -1
  617. package/src/time-series/use-chart-resolution.ts +1 -1
  618. package/src/types/context-menu.ts +6 -0
  619. package/src/types/data-provider.ts +2 -0
  620. package/src/types/financials.ts +35 -3
  621. package/src/types/headless.ts +79 -2
  622. package/src/types/plugin.ts +20 -1
  623. package/src/types/ticker.ts +15 -0
  624. package/src/ui/host.tsx +26 -0
  625. package/src/ui/index.tsx +8 -3
  626. package/src/ui/scroll-box-axis.ts +26 -0
  627. package/src/updater/index.ts +9 -11
  628. package/src/utils/async-deadline.ts +21 -0
  629. package/src/utils/cli-output.ts +5 -1
  630. package/src/utils/crypto-pair.ts +41 -0
  631. package/src/utils/currency-units.ts +19 -0
  632. package/src/utils/depositary-receipt.ts +70 -0
  633. package/src/utils/display-number.ts +63 -0
  634. package/src/utils/exchanges.ts +72 -0
  635. package/src/utils/fire-and-forget.ts +24 -0
  636. package/src/utils/format.ts +13 -0
  637. package/src/utils/fundamentals.ts +17 -1
  638. package/src/utils/price-earnings.ts +70 -3
  639. package/src/utils/price-history-integrity.ts +19 -6
  640. package/src/utils/price-history.ts +58 -13
  641. package/src/utils/rpc-timeout-error.ts +27 -0
  642. package/src/utils/sec.ts +13 -1
  643. package/src/utils/utc-time.ts +79 -0
@@ -1,7 +1,8 @@
1
1
  import { formatShortDate, parseDisplayDate } from "../../utils/datetime-format";
2
2
  import { formatReportedMoney } from "../../utils/reported-money";
3
+ import { fundamentalsCurrency, reportedEnterpriseValue } from "../../utils/fundamentals";
3
4
  import { latestFinancialPeriod } from "../../utils/latest-financial-period";
4
- import { formatPriceEarnings } from "../../utils/price-earnings";
5
+ import { exportedFundamentals, formatPriceEarnings, priceEarningsOnEarnings } from "../../utils/price-earnings";
5
6
  import { describeFundamentalMarketCap, selectMarketCapitalization } from "../../utils/market-capitalization";
6
7
  import {
7
8
  formatCompact,
@@ -20,7 +21,12 @@ import {
20
21
  wrapText,
21
22
  type CliStatEntry,
22
23
  } from "../../utils/cli-output";
23
- import { exchangeShortName, marketStateLabel } from "../../market-data/market/status";
24
+ import {
25
+ exchangeShortName,
26
+ getExtendedSessionDisplay,
27
+ getRegularSessionDisplay,
28
+ marketStateLabel,
29
+ } from "../../market-data/market/status";
24
30
  import type { AppConfig } from "../../types/config";
25
31
  import type { FinancialStatement, TickerFinancials } from "../../types/financials";
26
32
  import { computeTickerPriceReturns } from "../../market-data/ticker-price-returns";
@@ -44,6 +50,13 @@ import {
44
50
  } from "../helpers";
45
51
  import { NotesFiles } from "../../plugins/builtin/notes/files";
46
52
  import { isUsEquityTicker } from "../../utils/sec";
53
+ import { canonicalExchange, exchangeLabel, isKnownExchangeCode } from "../../utils/exchanges";
54
+ import { failIfNotTraded, ListingArgError, listingIdentity, resolveCliListing, type CliListing } from "../listing-arg";
55
+ import { sharesOutstandingInReceipts } from "../../utils/depositary-receipt";
56
+ import { cliFreshnessFooter } from "../result";
57
+ import { exportEntriesTable, reportFooterLines, type CliReportTables } from "../report-tables";
58
+ import type { ReportFreshness } from "../pane-functions/freshness";
59
+ import { fundamentalsFreshness, quotesFreshness } from "../freshness";
47
60
 
48
61
  const NEWS_ITEM_LIMIT = 5;
49
62
  const SEC_FILING_LIMIT = 5;
@@ -52,6 +65,8 @@ const MAX_PROSE_WIDTH = 100;
52
65
  const METADATA_SEPARATOR = " · ";
53
66
 
54
67
  interface TickerCommandDependencies {
68
+ /** `--exchange`: the listing, for a symbol that trades in several places. */
69
+ exchange?: string;
55
70
  initMarketData?: () => Promise<MarketContext>;
56
71
  fail?: (message: string, details?: string) => never;
57
72
  printResult?: CliCommandContext["printResult"];
@@ -87,10 +102,26 @@ function buildStatementMetrics(statement: FinancialStatement, currency?: string)
87
102
  ["Total Debt", money(statement.totalDebt)],
88
103
  ["Equity", money(statement.totalEquity)],
89
104
  ["Diluted EPS", money(statement.eps, true)],
90
- ["Diluted Shares", formatCompact(statement.dilutedShares)],
105
+ // Labelled only when the service says the row counts receipts.
106
+ ["Diluted Shares", statement.dilutedShares != null && statement.shareBasis === "depositary_receipt"
107
+ ? `${formatCompact(statement.dilutedShares)} (ADR equivalent)`
108
+ : formatCompact(statement.dilutedShares)],
91
109
  ];
92
110
  }
93
111
 
112
+ /**
113
+ * A receipt's count is its ordinary shares expressed in receipts, as its
114
+ * market cap is; the ordinary count follows when the service gives it.
115
+ */
116
+ function sharesOutstandingText(fundamentals: TickerFinancials["fundamentals"], inReceipts: boolean): string {
117
+ const shares = fundamentals?.sharesOutstanding;
118
+ if (shares == null || !inReceipts) return formatCompact(shares);
119
+ const ordinary = fundamentals?.shareBasis === "depositary_receipt" ? fundamentals.underlyingOrdinaryShares : undefined;
120
+ return ordinary != null && Number.isFinite(ordinary) && ordinary > 0
121
+ ? `${formatCompact(shares)} (ADR equivalent = ${formatCompact(ordinary)} ordinary shares)`
122
+ : `${formatCompact(shares)} (ADR equivalent)`;
123
+ }
124
+
94
125
  /** Provider prose is wrapped; `verbatim` keeps the user's own spacing, such as a table in a note. */
95
126
  function appendTextSection(lines: string[], title: string, content: string | undefined, verbatim = false) {
96
127
  const text = content?.trim();
@@ -229,72 +260,171 @@ function enterpriseValueCurrency(
229
260
  || undefined;
230
261
  }
231
262
 
263
+ /** A fundamentals line: the text the report prints, and for CSV the figure behind it in `unit`. */
264
+ interface FundamentalsMetric {
265
+ label: string;
266
+ text: string;
267
+ value?: number | string | null;
268
+ unit?: string;
269
+ }
270
+
271
+ type MetricFigure = Omit<FundamentalsMetric, "label">;
272
+
273
+ /** An amount in the currency the source reported it in; `ccy?` when it named none, as the text says. */
274
+ function reportedMoney(value: number | undefined, currency: string | undefined, perShare = false): MetricFigure {
275
+ return { text: formatReportedMoney(value, currency, perShare), value, unit: currency?.trim() || "ccy?" };
276
+ }
277
+
278
+ function percentFigure(fraction: number | null | undefined, format: (value: number) => string): MetricFigure {
279
+ return fraction != null ? { text: format(fraction), value: fraction * 100, unit: "%" } : { text: "—" };
280
+ }
281
+
282
+ function multipleFigure(value: ReturnType<typeof priceEarningsOnEarnings> | number | undefined): MetricFigure {
283
+ const text = formatPriceEarnings(value, 2);
284
+ return { text, value: typeof value === "number" && Number.isFinite(value) && value > 0 ? value : text === "N/M" ? text : null };
285
+ }
286
+
232
287
  function fundamentalsMetrics(
233
288
  quote: TickerFinancials["quote"],
234
289
  fundamentals: TickerFinancials["fundamentals"],
235
- marketCapText: string,
290
+ profile: TickerFinancials["profile"],
291
+ marketCap: MetricFigure,
236
292
  priceReturns: { return1Y?: number | null; return3Y?: number | null },
237
- enterpriseValueText = formatReportedMoney(fundamentals?.enterpriseValue, enterpriseValueCurrency(quote, fundamentals)),
238
- ): Array<[string, string]> {
293
+ reportingCurrency: string | undefined,
294
+ enterpriseValue = reportedMoney(reportedEnterpriseValue(fundamentals), enterpriseValueCurrency(quote, fundamentals)),
295
+ ): FundamentalsMetric[] {
296
+ const signed = (value: number) => colorBySign(formatPercent(value), value);
297
+ const receipt = fundamentals?.sharesOutstanding != null && sharesOutstandingInReceipts(quote, fundamentals, profile?.description);
239
298
  return [
240
- ["Market Cap", marketCapText],
241
- ["Enterprise Value", enterpriseValueText],
242
- ["P/E (TTM)", formatPriceEarnings(fundamentals?.trailingPE, 2)],
243
- ["Forward P/E", formatPriceEarnings(fundamentals?.forwardPE, 2)],
244
- ["PEG", fundamentals?.pegRatio != null ? formatNumber(fundamentals.pegRatio, 2) : "—"],
245
- ["EPS", formatReportedMoney(fundamentals?.eps, fundamentals?.financialCurrency, true)],
246
- [`Dividend Yield${fundamentals?.dividendYieldBasis ? ` (${fundamentals.dividendYieldBasis})` : ""}`, fundamentals?.dividendYield != null ? formatFractionPercentCell(fundamentals.dividendYield) : "—"],
247
- ["Revenue", formatReportedMoney(fundamentals?.revenue, fundamentals?.financialCurrency)],
248
- ["Net Income", formatReportedMoney(fundamentals?.netIncome, fundamentals?.financialCurrency)],
249
- ["Operating Cash Flow", formatReportedMoney(fundamentals?.operatingCashFlow, fundamentals?.financialCurrency)],
250
- ["Free Cash Flow", formatReportedMoney(fundamentals?.freeCashFlow, fundamentals?.financialCurrency)],
299
+ { label: "Market Cap", ...marketCap },
300
+ { label: "Enterprise Value", ...enterpriseValue },
301
+ // A multiple over a loss is N/M, even beside a positive one the source served from an older period.
302
+ { label: "P/E (TTM)", ...multipleFigure(priceEarningsOnEarnings(fundamentals?.trailingPE, fundamentals?.eps)) },
303
+ { label: "Forward P/E", ...multipleFigure(priceEarningsOnEarnings(fundamentals?.forwardPE, fundamentals?.forwardEps)) },
304
+ { label: "PEG", ...multipleFigure(fundamentals?.pegRatio) },
305
+ // The flows and EPS are one trailing-twelve-month block, the same twelve months for each line.
306
+ { label: "EPS (TTM)", ...reportedMoney(fundamentals?.eps, reportingCurrency, true) },
307
+ {
308
+ label: `Dividend Yield${fundamentals?.dividendYieldBasis ? ` (${fundamentals.dividendYieldBasis})` : ""}`,
309
+ ...percentFigure(fundamentals?.dividendYield, formatFractionPercentCell),
310
+ },
311
+ { label: "Revenue (TTM)", ...reportedMoney(fundamentals?.revenue, reportingCurrency) },
312
+ { label: "Net Income (TTM)", ...reportedMoney(fundamentals?.netIncome, reportingCurrency) },
313
+ { label: "Operating Cash Flow (TTM)", ...reportedMoney(fundamentals?.operatingCashFlow, reportingCurrency) },
314
+ { label: "Free Cash Flow (TTM)", ...reportedMoney(fundamentals?.freeCashFlow, reportingCurrency) },
251
315
  // Levels, not changes, so they carry no sign.
252
- ["Operating Margin", fundamentals?.operatingMargin != null ? formatFractionPercentCell(fundamentals.operatingMargin) : "—"],
253
- ["Profit Margin", fundamentals?.profitMargin != null ? formatFractionPercentCell(fundamentals.profitMargin) : "—"],
254
- ["Revenue Growth", fundamentals?.revenueGrowth != null ? colorBySign(formatPercent(fundamentals.revenueGrowth), fundamentals.revenueGrowth) : "—"],
255
- ["Last Quarter Growth", fundamentals?.lastQuarterGrowth != null ? colorBySign(formatPercent(fundamentals.lastQuarterGrowth), fundamentals.lastQuarterGrowth) : "—"],
256
- ["1Y Return", priceReturns.return1Y != null ? colorBySign(formatPercent(priceReturns.return1Y), priceReturns.return1Y) : "—"],
257
- ["3Y Return", priceReturns.return3Y != null ? colorBySign(formatPercent(priceReturns.return3Y), priceReturns.return3Y) : "—"],
258
- ["Shares Outstanding", formatCompact(fundamentals?.sharesOutstanding)],
316
+ { label: "Operating Margin", ...percentFigure(fundamentals?.operatingMargin, formatFractionPercentCell) },
317
+ { label: "Profit Margin", ...percentFigure(fundamentals?.profitMargin, formatFractionPercentCell) },
318
+ { label: "Revenue Growth", ...percentFigure(fundamentals?.revenueGrowth, signed) },
319
+ { label: "Last Quarter Growth", ...percentFigure(fundamentals?.lastQuarterGrowth, signed) },
320
+ { label: "1Y Return", ...percentFigure(priceReturns.return1Y, signed) },
321
+ { label: "3Y Return", ...percentFigure(priceReturns.return3Y, signed) },
322
+ {
323
+ label: "Shares Outstanding",
324
+ text: sharesOutstandingText(fundamentals, receipt),
325
+ value: fundamentals?.sharesOutstanding,
326
+ ...(receipt ? { unit: "ADR equivalent" } : {}),
327
+ },
259
328
  ];
260
329
  }
261
330
 
262
- const VALUATION_METRICS = new Set(["Market Cap", "Enterprise Value", "P/E (TTM)", "Forward P/E", "PEG", "EPS"]);
331
+ function metricLines(metrics: readonly FundamentalsMetric[]): Array<[string, string]> {
332
+ return metrics.map((metric) => [metric.label, metric.text]);
333
+ }
334
+
335
+ const VALUATION_METRICS = new Set(["Market Cap", "Enterprise Value", "P/E (TTM)", "Forward P/E", "PEG", "EPS (TTM)"]);
336
+
337
+ type FundamentalsReportData = TickerFinancials & { symbol: string; exchange?: string };
338
+
339
+ /** The lines `fundamentals` or `valuation` reports, the ones with a value. */
340
+ function fundamentalsReportMetrics(financials: FundamentalsReportData, view: "fundamentals" | "valuation"): FundamentalsMetric[] {
341
+ const quote = financials.quote;
342
+ const fundamentals = financials.fundamentals;
343
+ const capitalization = selectMarketCapitalization(quote, fundamentals);
344
+ const marketCap: MetricFigure = capitalization
345
+ ? { text: `${formatCompact(capitalization.value)} ${capitalization.currency}`, value: capitalization.value, unit: capitalization.currency }
346
+ : { text: "—" };
347
+ const metrics = fundamentalsMetrics(quote, fundamentals, financials.profile, marketCap, computeTickerPriceReturns(financials), fundamentalsCurrency(financials));
348
+ return (view === "valuation"
349
+ ? metrics.filter(({ label }) => VALUATION_METRICS.has(label) || label.startsWith("Dividend Yield"))
350
+ : metrics).filter((metric) => metric.text !== "—");
351
+ }
263
352
 
264
353
  /** Text for `gloomberb fundamentals` and `gloomberb valuation`: the ticker report's fundamentals without the rest. */
265
354
  export function renderFundamentalsReport(
266
- financials: TickerFinancials & { symbol: string },
355
+ financials: FundamentalsReportData,
267
356
  view: "fundamentals" | "valuation",
268
357
  ): string {
269
358
  const quote = financials.quote;
270
- const fundamentals = financials.fundamentals;
271
359
  const profile = financials.profile;
272
- const capitalization = selectMarketCapitalization(quote, fundamentals);
273
- const marketCapText = capitalization
274
- ? `${formatCompact(capitalization.value)} ${capitalization.currency}`
275
- : "—";
276
- const metrics = fundamentalsMetrics(quote, fundamentals, marketCapText, computeTickerPriceReturns(financials));
277
360
  const symbol = quote?.symbol ?? financials.symbol;
278
361
  const name = quote?.name && quote.name !== symbol ? ` ${cliStyles.bold(quote.name)}` : "";
279
362
  const lines = [`${cliStyles.accent(symbol)}${name}`];
280
363
  const profileParts = [
364
+ financials.exchange ? exchangeLabel(financials.exchange) : undefined,
281
365
  profile?.sector ? `Sector ${profile.sector}` : undefined,
282
366
  profile?.industry ? `Industry ${profile.industry}` : undefined,
283
367
  ].filter((part): part is string => !!part);
284
368
  if (profileParts.length > 0) lines.push(cliStyles.muted(profileParts.join(METADATA_SEPARATOR)));
285
369
 
286
- const shown = view === "valuation"
287
- ? metrics.filter(([label]) => VALUATION_METRICS.has(label) || label.startsWith("Dividend Yield"))
288
- : metrics;
289
370
  const before = lines.length;
290
- appendMetricSection(lines, view === "valuation" ? "Valuation" : "Fundamentals", shown);
371
+ appendMetricSection(lines, view === "valuation" ? "Valuation" : "Fundamentals", metricLines(fundamentalsReportMetrics(financials, view)));
291
372
  if (lines.length === before) lines.push("", cliStyles.muted(`No ${view} reported for ${financials.symbol}.`));
292
373
  if (view === "fundamentals") appendTextSection(lines, "Description", profile?.description);
293
374
  return lines.join("\n");
294
375
  }
295
376
 
377
+ /**
378
+ * `fundamentals` and `valuation` for `--csv` and `--ndjson`: the metrics as
379
+ * `Metric,Value` with each unit in its label, and for `fundamentals` the
380
+ * company profile the text prints around them.
381
+ */
382
+ export function fundamentalsReportTables(
383
+ financials: FundamentalsReportData,
384
+ view: "fundamentals" | "valuation",
385
+ freshness: ReportFreshness,
386
+ ): CliReportTables {
387
+ const metrics = fundamentalsReportMetrics(financials, view);
388
+ const tables = [exportEntriesTable(
389
+ view === "valuation" ? "Valuation" : "Fundamentals",
390
+ metrics.map((metric) => ({ label: metric.label, value: metric.value, formatted: metric.text, unit: metric.unit })),
391
+ )];
392
+ if (view === "fundamentals") {
393
+ const quote = financials.quote;
394
+ const profile = financials.profile;
395
+ tables.push(exportEntriesTable("Profile", [
396
+ { label: "Symbol", value: quote?.symbol ?? financials.symbol },
397
+ { label: "Name", value: quote?.name },
398
+ { label: "Exchange", value: financials.exchange ? exchangeLabel(financials.exchange) : undefined },
399
+ { label: "Sector", value: profile?.sector },
400
+ { label: "Industry", value: profile?.industry },
401
+ { label: "Description", value: profile?.description?.trim() },
402
+ ].filter((entry) => typeof entry.value === "string" && entry.value.trim().length > 0)));
403
+ }
404
+ return {
405
+ tables,
406
+ footer: reportFooterLines({
407
+ freshness,
408
+ notes: metrics.length === 0 ? [`No ${view} reported for ${financials.symbol}.`] : [],
409
+ }),
410
+ };
411
+ }
412
+
413
+ /** "Euronext Paris (EPA)": the venue the report is for, named in full when the app knows it. */
414
+ function listingVenueLabel(
415
+ listingExchange: string | undefined,
416
+ quote: TickerFinancials["quote"],
417
+ financials: TickerFinancials,
418
+ tickerFile: TickerRecord | null,
419
+ ): string {
420
+ const exchangeName = quote?.exchangeName ?? financials.quoteMetadata?.listingExchangeName ?? tickerFile?.metadata.exchange;
421
+ const venue = canonicalExchange(listingExchange || quote?.listingExchangeName || exchangeName);
422
+ return isKnownExchangeCode(venue) ? exchangeLabel(venue) : exchangeShortName(exchangeName, quote?.fullExchangeName);
423
+ }
424
+
296
425
  export async function buildTickerReport({
297
426
  symbol,
427
+ listingExchange,
298
428
  tickerFile,
299
429
  financials,
300
430
  config,
@@ -304,6 +434,8 @@ export async function buildTickerReport({
304
434
  recentSecFilings = [],
305
435
  }: {
306
436
  symbol: string;
437
+ /** The exchange the command named, as a canonical code. */
438
+ listingExchange?: string;
307
439
  tickerFile: TickerRecord | null;
308
440
  financials: TickerFinancials;
309
441
  config: AppConfig;
@@ -326,7 +458,7 @@ export async function buildTickerReport({
326
458
  if (!quote) lines.push(cliStyles.muted("Quote unavailable."));
327
459
 
328
460
  const summaryParts = [
329
- exchangeShortName(quote?.exchangeName ?? financials.quoteMetadata?.listingExchangeName ?? tickerFile?.metadata.exchange, quote?.fullExchangeName) || undefined,
461
+ listingVenueLabel(listingExchange, quote, financials, tickerFile) || undefined,
330
462
  (quote?.currency || financials.quoteMetadata?.currency || tickerFile?.metadata.currency)
331
463
  ? `Currency ${quote?.currency || financials.quoteMetadata?.currency || tickerFile?.metadata.currency}` : undefined,
332
464
  quote?.marketState ? marketStateLabel(quote.marketState) : undefined,
@@ -370,19 +502,28 @@ export async function buildTickerReport({
370
502
  : `${formatCompact(capitalization.value)} ${capitalization.currency}`
371
503
  : "—";
372
504
  // Shown in the same currency as the market cap, so the two can be compared.
373
- const enterpriseValue = fundamentals?.enterpriseValue;
505
+ const enterpriseValue = reportedEnterpriseValue(fundamentals);
374
506
  const evCurrency = enterpriseValueCurrency(quote, fundamentals);
375
507
  // A minor unit such as GBp stays as reported: the converter would read it as the major currency.
376
- const convertedEnterpriseValue = enterpriseValue != null && Number.isFinite(enterpriseValue) && evCurrency && /^[A-Z]{3}$/.test(evCurrency)
508
+ const convertedEnterpriseValue = enterpriseValue != null && evCurrency && /^[A-Z]{3}$/.test(evCurrency)
377
509
  ? await toBase(enterpriseValue, evCurrency) : Number.NaN;
378
510
  const enterpriseValueText = Number.isFinite(convertedEnterpriseValue)
379
511
  ? `${formatCompact(convertedEnterpriseValue)} ${config.baseCurrency}`
380
512
  : formatReportedMoney(enterpriseValue, evCurrency);
381
513
 
382
514
  if (quote) {
515
+ // As the Overview reads it: the regular session, then the extended-hours print against its close.
516
+ const session = getRegularSessionDisplay(quote)!;
517
+ const extended = getExtendedSessionDisplay(quote);
518
+ const extendedRow = (kind: "PRE" | "POST") => extended?.session === kind
519
+ ? colorBySign(
520
+ `${formatMarketPriceWithCurrency(extended.price, quote.currency, quoteOptions)} (${formatPercentRaw(extended.changePercent)})`,
521
+ extended.change,
522
+ )
523
+ : "—";
383
524
  appendMetricSection(lines, "Quote", [
384
- ["Last", colorBySign(formatMarketPriceWithCurrency(quote.price, quote.currency, quoteOptions), quote.change)],
385
- ["Change", colorBySign(`${formatMarketChangeWithCurrency(quote.change, quote.currency, quoteOptions, quote.price)} (${formatPercentRaw(quote.changePercent)})`, quote.change)],
525
+ ["Last", colorBySign(formatMarketPriceWithCurrency(session.price, quote.currency, quoteOptions), session.change)],
526
+ ["Change", colorBySign(`${formatMarketChangeWithCurrency(session.change, quote.currency, quoteOptions, session.price)} (${formatPercentRaw(session.changePercent)})`, session.change)],
386
527
  ["Open", quote.open != null ? formatMarketPriceWithCurrency(quote.open, quote.currency, quoteOptions) : "—"],
387
528
  ["Day Range", quote.low != null || quote.high != null
388
529
  ? formatPriceRange(quote.low, quote.high, quote.currency, quoteOptions)
@@ -396,22 +537,12 @@ export async function buildTickerReport({
396
537
  ]);
397
538
 
398
539
  appendMetricSection(lines, "Extended Hours", [
399
- ["Pre-Market", quote.preMarketPrice != null
400
- ? colorBySign(
401
- `${formatMarketPriceWithCurrency(quote.preMarketPrice, quote.currency, quoteOptions)} (${formatPercentRaw(quote.preMarketChangePercent)})`,
402
- quote.preMarketChange ?? 0,
403
- )
404
- : "—"],
405
- ["After Hours", quote.postMarketPrice != null
406
- ? colorBySign(
407
- `${formatMarketPriceWithCurrency(quote.postMarketPrice, quote.currency, quoteOptions)} (${formatPercentRaw(quote.postMarketChangePercent)})`,
408
- quote.postMarketChange ?? 0,
409
- )
410
- : "—"],
540
+ ["Pre-Market", extendedRow("PRE")],
541
+ ["After Hours", extendedRow("POST")],
411
542
  ]);
412
543
  }
413
544
 
414
- appendMetricSection(lines, "Fundamentals", fundamentalsMetrics(quote, fundamentals, marketCapText, priceReturns, enterpriseValueText));
545
+ appendMetricSection(lines, "Fundamentals", metricLines(fundamentalsMetrics(quote, fundamentals, profile, { text: marketCapText }, priceReturns, fundamentalsCurrency(financials), { text: enterpriseValueText })));
415
546
 
416
547
  if (capitalization?.provenance.kind === "fundamentals") {
417
548
  lines.push(cliStyles.muted(`Market cap: ${describeFundamentalMarketCap(capitalization.provenance)}.`));
@@ -469,6 +600,7 @@ export async function buildTickerReport({
469
600
 
470
601
  function buildTickerStructuredData({
471
602
  symbol,
603
+ listing,
472
604
  tickerFile,
473
605
  financials,
474
606
  config,
@@ -477,6 +609,7 @@ function buildTickerStructuredData({
477
609
  recentSecFilings,
478
610
  }: {
479
611
  symbol: string;
612
+ listing: CliListing;
480
613
  tickerFile: TickerRecord | null;
481
614
  financials: TickerFinancials;
482
615
  config: AppConfig;
@@ -486,8 +619,10 @@ function buildTickerStructuredData({
486
619
  }) {
487
620
  const quote = financials.quote;
488
621
  const priceReturns = computeTickerPriceReturns(financials, tickerFile?.metadata.assetCategory);
622
+ const identity = listingIdentity(listing, quote);
489
623
  return {
490
624
  symbol,
625
+ listing: { symbol: identity.symbol, exchange: identity.exchange || null, name: identity.name },
491
626
  quote: quote ? {
492
627
  symbol: quote.symbol,
493
628
  instrumentType: quote.instrumentType,
@@ -518,10 +653,10 @@ function buildTickerStructuredData({
518
653
  watchlists: formatWatchlistNames(config, tickerFile.metadata.watchlists),
519
654
  positions: tickerFile.metadata.positions,
520
655
  } : null,
521
- fundamentals: financials.fundamentals || priceReturns.return1Y != null || priceReturns.return3Y != null ? {
656
+ fundamentals: financials.fundamentals || priceReturns.return1Y != null || priceReturns.return3Y != null ? exportedFundamentals({
522
657
  ...financials.fundamentals,
523
658
  ...priceReturns,
524
- } : undefined,
659
+ }) : undefined,
525
660
  profile: financials.profile,
526
661
  financialCurrency: financials.financialCurrency ?? null,
527
662
  latestAnnual: latestFinancialPeriod(financials.annualStatements, row => row.date) ?? null,
@@ -551,19 +686,26 @@ export async function ticker(symbol: string, dependencies: TickerCommandDependen
551
686
  const initMarketDataFn = dependencies.initMarketData ?? initMarketData;
552
687
  const failCommand = dependencies.fail ?? fail;
553
688
  await withMarketData(initMarketDataFn, async ({ config, store, dataProvider, dataDir }) => {
554
- const normalized = symbol.trim().toUpperCase();
555
- const tickerFile = await store.loadTicker(normalized);
556
- const exchange = tickerFile?.metadata.exchange ?? "";
689
+ let listing: CliListing;
690
+ try {
691
+ listing = await resolveCliListing(symbol, dependencies.exchange, { store, dataProvider });
692
+ } catch (error) {
693
+ if (error instanceof ListingArgError) failCommand(error.message, error.details);
694
+ throw error;
695
+ }
696
+ // A named listing goes by its key (SAN:EPA); a bare symbol by its saved listing, as before.
697
+ const normalized = listing.key;
698
+ const tickerFile = listing.saved;
699
+ const { symbol: requestSymbol, exchange } = listing.request;
557
700
  const toBase = createBaseConverter(dataProvider, config.baseCurrency);
558
701
 
559
702
  let financials: TickerFinancials | null = null;
560
703
  try {
561
- financials = await dataProvider.getTickerFinancials(normalized, exchange);
704
+ financials = await dataProvider.getTickerFinancials(requestSymbol, exchange);
562
705
  } catch (error) {
563
- failCommand(
564
- `Failed to fetch data for ${normalized}.`,
565
- error instanceof Error ? error.message : String(error),
566
- );
706
+ // A known exchange the symbol is not listed on: say where it is.
707
+ await failIfNotTraded(listing, { store, dataProvider }, { fail: failCommand });
708
+ failCommand(`Failed to fetch data for ${normalized}.`, error instanceof Error ? error.message : String(error));
567
709
  }
568
710
 
569
711
  const hasResearchData = financials && (
@@ -579,25 +721,30 @@ export async function ticker(symbol: string, dependencies: TickerCommandDependen
579
721
  || financials.quarterlyStatements.length > 0
580
722
  );
581
723
  if (!financials || (!hasResearchData && !tickerFile?.metadata.positions.some((position) => position.shares !== 0))) {
724
+ await failIfNotTraded(listing, { store, dataProvider }, { fail: failCommand });
582
725
  failCommand(`No research data available for ${normalized}.`);
583
726
  }
584
727
  const resolvedFinancials = financials as TickerFinancials;
585
728
  const quote = resolvedFinancials.quote;
586
729
 
587
730
  const notesFiles = new NotesFiles(dataDir);
731
+ const listingName = listingIdentity(listing, quote).name;
588
732
  const [notesResult, newsResult, secFilingsResult] = await Promise.allSettled([
589
- notesFiles.load(normalized),
733
+ notesFiles.load(tickerFile?.metadata.ticker ?? normalized),
590
734
  dataProvider.getNews({
591
735
  feed: "ticker",
592
736
  // Still set for news plugins that read the deprecated scope.
593
737
  scope: "ticker",
594
- ticker: normalized,
738
+ ticker: requestSymbol,
595
739
  exchange: exchange || quote?.exchangeName || "",
596
740
  tickerTier: "primary",
597
741
  limit: NEWS_ITEM_LIMIT,
598
742
  }),
743
+ // Outside the US the lookup checks the SEC registrant against the listing's company,
744
+ // and refuses another company's filings.
599
745
  shouldFetchSecFilings(tickerFile, resolvedFinancials) && dataProvider.getSecFilings
600
- ? dataProvider.getSecFilings(normalized, SEC_FILING_LIMIT, exchange || quote?.exchangeName || "")
746
+ ? dataProvider.getSecFilings(requestSymbol, SEC_FILING_LIMIT, exchange || quote?.exchangeName || "",
747
+ listingName ? { listingName } : undefined)
601
748
  : Promise.resolve([]),
602
749
  ]);
603
750
 
@@ -605,11 +752,15 @@ export async function ticker(symbol: string, dependencies: TickerCommandDependen
605
752
  const recentNews = newsResult.status === "fulfilled" ? newsResult.value : [];
606
753
  const recentSecFilings = secFilingsResult.status === "fulfilled" ? secFilingsResult.value : [];
607
754
 
755
+ // The quote is the feed in this report; without one, the fundamentals date it.
756
+ const freshness = quote ? quotesFreshness([quote]) : fundamentalsFreshness(resolvedFinancials);
608
757
  if (dependencies.printResult) {
609
758
  dependencies.printResult({
759
+ freshness,
610
760
  warnings: quote ? undefined : ["Quote unavailable."],
611
761
  data: buildTickerStructuredData({
612
762
  symbol: normalized,
763
+ listing,
613
764
  tickerFile,
614
765
  financials: resolvedFinancials,
615
766
  config,
@@ -623,6 +774,7 @@ export async function ticker(symbol: string, dependencies: TickerCommandDependen
623
774
 
624
775
  console.log(await buildTickerReport({
625
776
  symbol: normalized,
777
+ listingExchange: listing.exchange,
626
778
  tickerFile,
627
779
  financials: resolvedFinancials,
628
780
  config,
@@ -631,5 +783,6 @@ export async function ticker(symbol: string, dependencies: TickerCommandDependen
631
783
  recentNews,
632
784
  recentSecFilings,
633
785
  }));
786
+ if (freshness) console.log(`\n${cliFreshnessFooter(freshness)}`);
634
787
  });
635
788
  }
@@ -10,11 +10,13 @@ import type { ManualChartResolution } from "../time-series/resolution";
10
10
  import type { SnapshotMarketData } from "../market-data/snapshot-provider";
11
11
  import type { InstrumentRef } from "../market-data/request-types";
12
12
  import type { TickerRecord } from "../types/ticker";
13
+ import type { BrokerAccount } from "../types/trading";
13
14
  import type { PaneRuntimeState } from "../core/state/app/state";
14
15
  import type { RemoteUiNodeSnapshot } from "../remote/types";
15
16
  import type { DatedObservation } from "../plugins/builtin/market-valuation/series";
16
17
  import type { DesktopExternalPluginBundle } from "../renderers/electrobun/shared/protocol";
17
18
  import type { HttpProxyRequestEnvelope, HttpProxyResponseEnvelope } from "../utils/http-proxy-response";
19
+ import type { PaneAccessGate } from "./pane-functions/access-gate";
18
20
  import { readVisibleKeyValues } from "./visible-key-values";
19
21
  import { SHOT_API_PROXY_PREFIX, SHOT_HTTP_BRIDGE_PATH, SHOT_MARKET_BRIDGE_PATH } from "./desktop-pane-shot-routes";
20
22
  import { SESSION_COOKIE_NAMES } from "../api-client/session-cookie";
@@ -53,6 +55,8 @@ export interface DesktopPaneShotPayload {
53
55
  /** Label drawn at the right edge of the pane title bar; null draws nothing. */
54
56
  watermark?: string | null;
55
57
  tickers: TickerRecord[];
58
+ /** Broker accounts as last synced, by profile, so a broker portfolio shows its equity and cash. */
59
+ brokerAccounts?: Record<string, BrokerAccount[]>;
56
60
  financials: Array<[string, TickerFinancials]>;
57
61
  instrumentFinancials?: SnapshotMarketData["instrumentFinancials"];
58
62
  historyVariants?: SnapshotMarketData["historyVariants"];
@@ -93,6 +97,8 @@ interface DesktopPaneShotRenderedCell {
93
97
  columnId?: string;
94
98
  columnLabel: string;
95
99
  text: string;
100
+ /** The ISO instant behind a cell whose text shortens a time ("Wed 11:27"), from the table cell's export value. */
101
+ instant?: string;
96
102
  }
97
103
 
98
104
  export interface DesktopPaneShotRenderedRow {
@@ -105,6 +111,8 @@ export interface DesktopPaneShotRenderedRow {
105
111
 
106
112
  export interface DesktopPaneShotRenderResult {
107
113
  visibleText: string;
114
+ /** Text of the pane footers, where a pane says whether its data is live, delayed or stale. */
115
+ footerText?: string;
108
116
  visibleKeyValues?: Array<{ label: string; text: string }>;
109
117
  rows: DesktopPaneShotRenderedRow[];
110
118
  truncated: boolean;
@@ -114,6 +122,8 @@ export interface DesktopPaneShotRenderResult {
114
122
  errorStateMarkers: string[];
115
123
  emptyStateDetected: boolean;
116
124
  emptyStateMarkers: string[];
125
+ /** A wall that needs an account, or a Pro lock on part of the pane. */
126
+ accessGate?: PaneAccessGate | null;
117
127
  semanticUi: RemoteUiNodeSnapshot[];
118
128
  }
119
129
 
@@ -472,14 +482,22 @@ const LOADING_STATE_PATTERNS = [
472
482
  /\bRendering pane\.{3}/gi,
473
483
  ];
474
484
 
475
- const ERROR_STATE_PATTERNS = [
476
- /\b[^.]{1,100} unavailable\./gi,
477
- /\bFailed to fetch\b/gi,
478
- /\bCould not load\b/gi,
485
+ const SIGN_IN_WALL_PATTERNS = [
479
486
  /\bSign in to\b/gi,
480
487
  /\bVerify your email\b/gi,
481
488
  /\brequires signup and email verification\b/gi,
489
+ ];
490
+
491
+ const PRO_WALL_PATTERNS = [
482
492
  /\bpart of Gloom Cloud Pro\b/gi,
493
+ ];
494
+
495
+ const ERROR_STATE_PATTERNS = [
496
+ /\b[^.]{1,100} unavailable\./gi,
497
+ /\bFailed to fetch\b/gi,
498
+ /\bCould not load\b/gi,
499
+ ...SIGN_IN_WALL_PATTERNS,
500
+ ...PRO_WALL_PATTERNS,
483
501
  /\bCloud API request failed\b/gi,
484
502
  ];
485
503
 
@@ -569,12 +587,14 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
569
587
  ) {
570
588
  truncationReasons.add("one or more cells are visibly clipped");
571
589
  }
590
+ const instant = cell.getAttribute("data-gloom-cell-instant");
572
591
  return {
573
592
  ...(typeof semanticColumn.id === "string" ? { columnId: semanticColumn.id } : {}),
574
593
  columnLabel: typeof semanticColumn.label === "string"
575
594
  ? semanticColumn.label
576
595
  : headers[cellIndex] || (values.length === 1 ? "Row" : String(cellIndex + 1)),
577
596
  text,
597
+ ...(instant ? { instant } : {}),
578
598
  };
579
599
  }).filter((cell) => cell.text.length > 0);
580
600
  if (cells.length === 0) return;
@@ -605,6 +625,10 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
605
625
  }
606
626
  return {
607
627
  visibleText: root.innerText || root.textContent || "",
628
+ footerText: [...root.querySelectorAll('[data-gloom-role="pane-footer"]')]
629
+ .map((footer) => normalize(footer.innerText || footer.textContent))
630
+ .filter(Boolean)
631
+ .join(" "),
608
632
  visibleKeyValues: (${readVisibleKeyValues.toString()})(root),
609
633
  error: window.__GLOOM_CLI_SHOT_ERROR__ || "",
610
634
  loadingStateDetected: root.querySelector('[data-gloom-status="loading"]') !== null,
@@ -612,6 +636,9 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
612
636
  // An empty sub-section off screen, such as a ticker's news list below
613
637
  // the fold, does not make the captured view empty.
614
638
  emptyStateDetected: [...root.querySelectorAll('[data-gloom-status="empty"]')].some(isVisible),
639
+ // The shared sign-in wall and the Pro lock prompt every gated pane draws.
640
+ accessGate: [...root.querySelectorAll('[data-gloom-ui="sign-in-wall"]')].some(isVisible) ? "sign-in"
641
+ : [...root.querySelectorAll('[data-gloom-ui="pro-lock"]')].some(isVisible) ? "pro" : "",
615
642
  rows,
616
643
  truncated: truncationReasons.size > 0,
617
644
  truncationReasons: [...truncationReasons],
@@ -623,11 +650,13 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
623
650
  result?: {
624
651
  value?: {
625
652
  visibleText?: string;
653
+ footerText?: string;
626
654
  visibleKeyValues?: Array<{ label: string; text: string }>;
627
655
  error?: string;
628
656
  loadingStateDetected?: boolean;
629
657
  errorStateDetected?: boolean;
630
658
  emptyStateDetected?: boolean;
659
+ accessGate?: string;
631
660
  rows?: DesktopPaneShotRenderedRow[];
632
661
  truncated?: boolean;
633
662
  truncationReasons?: string[];
@@ -641,6 +670,8 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
641
670
  const loadingStateMarkers = stateMarkers(visibleText, LOADING_STATE_PATTERNS);
642
671
  const errorStateMarkers = stateMarkers(visibleText, ERROR_STATE_PATTERNS);
643
672
  const emptyStateMarkers = stateMarkers(visibleText, EMPTY_STATE_PATTERNS);
673
+ const accessGate: PaneAccessGate | null = value?.accessGate === "sign-in" || stateMarkers(visibleText, SIGN_IN_WALL_PATTERNS).length > 0 ? "sign-in"
674
+ : value?.accessGate === "pro" || stateMarkers(visibleText, PRO_WALL_PATTERNS).length > 0 ? "pro" : null;
644
675
  const rows = Array.isArray(value?.rows) ? value.rows : [];
645
676
  const textShowsEllipsis = rows.some((row) => row.cells.some((cell) => /\u2026|\.\.\./.test(cell.text)));
646
677
  const truncationReasons = Array.isArray(value?.truncationReasons)
@@ -651,6 +682,7 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
651
682
  }
652
683
  return {
653
684
  visibleText,
685
+ footerText: typeof value?.footerText === "string" ? value.footerText : "",
654
686
  visibleKeyValues: Array.isArray(value?.visibleKeyValues) ? value.visibleKeyValues : [],
655
687
  rows,
656
688
  truncated: value?.truncated === true || textShowsEllipsis,
@@ -660,6 +692,7 @@ async function readRenderedPaneState(session: CdpSession): Promise<DesktopPaneSh
660
692
  errorStateMarkers,
661
693
  emptyStateDetected: value?.emptyStateDetected === true || emptyStateMarkers.length > 0,
662
694
  emptyStateMarkers,
695
+ accessGate,
663
696
  semanticUi: Array.isArray(value?.semanticUi) ? value.semanticUi : [],
664
697
  };
665
698
  }