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
@@ -1,6 +1,6 @@
1
1
  import type { CliCommandDef } from "../../types/plugin";
2
2
  import { TIME_RANGES, type TimeRange } from "../../time-series/range";
3
- import type { EarningsEvent, QuoteBatchResult, SecFilingItem } from "../../types/data-provider";
3
+ import type { EarningsEvent, QuoteBatchResult, QuoteSubscriptionTarget, SecFilingItem } from "../../types/data-provider";
4
4
  import type { NewsArticle, NewsFeed, NewsQuery } from "../../news/types";
5
5
  import type {
6
6
  AnalystResearchData,
@@ -13,7 +13,7 @@ import { currencyMinorDigits, formatMarketPrice, formatMarketPriceWithCurrency,
13
13
  import { getActiveQuoteDisplay, marketStateLabel } from "../../market-data/market/status";
14
14
  import { formatCompact, formatDistributionAmount, formatPercent } from "../../utils/format";
15
15
  import { withCliServices, withMarketData } from "../context";
16
- import { isoDate, parsePositiveInt, requireArg, takeOption } from "./command-utils";
16
+ import { isoDate, parsePositiveInt, requireArg, takeFlag, takeOption } from "./command-utils";
17
17
  import { CLI_COMMAND_GROUPS } from "../help";
18
18
  import {
19
19
  formatChangePercentCell,
@@ -35,12 +35,57 @@ import { optionQuoteSide } from "../../plugins/builtin/options/market-reference"
35
35
  import { getPublishedUsEquityCalendarYears, getPublishedUsEquitySession } from "../../market-data/published-us-sessions";
36
36
  import { renderFundamentalsReport } from "./ticker";
37
37
  import { historyPriceDecimals, historyRows } from "../history-rows";
38
+ import { CRYPTO_BOARD_HINT, quoteNotes } from "./crypto-hints";
39
+ import { formatUtcTime } from "../../utils/utc-time";
40
+ import { exportedFundamentals } from "../../utils/price-earnings";
41
+ import { fundamentalsFreshness, quotesFreshness, rowsFreshness } from "../freshness";
42
+ import {
43
+ barHistoryFreshness,
44
+ barResolutionFromDates,
45
+ REPORTED_DATA,
46
+ SEC_FILINGS,
47
+ } from "../../plugins/builtin/shared/report-freshness";
48
+ import {
49
+ EXCHANGE_OPTION,
50
+ listingHeading,
51
+ listingIdentity,
52
+ listingTitle,
53
+ listingVenues,
54
+ loadForListing,
55
+ loadListingQuote,
56
+ notTradedMessage,
57
+ requireCliListing,
58
+ type CliListing,
59
+ type ListingIdentity,
60
+ } from "../listing-arg";
61
+ import { secRegistrantMismatchMessage, SecRegistrantMismatchError, areDifferentCompanies } from "../../sources/sec-registrant";
62
+ import { isCryptoPairSymbol } from "../../utils/crypto-pair";
63
+ import { isUsListingExchange } from "../../utils/exchanges";
64
+ import { nonUsSecListingVenue } from "../../utils/sec";
65
+ import type { MarketContext } from "../types";
66
+ import {
67
+ holderListFacts,
68
+ holderValueBasis,
69
+ moneyColumnHeader,
70
+ nonUsHolderCaveat,
71
+ sharedReportDate,
72
+ } from "../../plugins/builtin/holders/report-header";
73
+ import { fetchBeneficialOwners } from "../../plugins/builtin/holders/beneficial-client";
74
+ import { filingFormMatches, SEC_FILING_FETCH_LIMIT } from "../../plugins/builtin/sec/forms";
75
+ import {
76
+ BENEFICIAL_REPORT_COLUMNS,
77
+ beneficialCoverageNotices,
78
+ beneficialListComplete,
79
+ beneficialListFacts,
80
+ beneficialListUnreadable,
81
+ beneficialRouteForm,
82
+ buildBeneficialReportRows,
83
+ HOLDER_FORMS,
84
+ parseHolderForm,
85
+ type HolderForm,
86
+ } from "../../plugins/builtin/holders/beneficial-report";
38
87
 
39
88
  const VALID_RANGES = new Set<TimeRange>(TIME_RANGES);
40
- const EXCHANGE_OPTION = {
41
- flags: "--exchange <code>",
42
- description: "Listing exchange, for a symbol that trades in several places",
43
- };
44
89
  const VALID_NEWS_FEEDS = new Set<NewsFeed>(["latest", "top", "breaking", "ticker", "sector", "topic"]);
45
90
 
46
91
  type QuoteCliRecord = Omit<QuoteBatchResult, "error"> & { error: string | null };
@@ -67,6 +112,11 @@ function normalizeSymbols(args: string[]): string[] {
67
112
  .filter(Boolean);
68
113
  }
69
114
 
115
+ /** What JSON metadata says about the listing a command resolved. */
116
+ function listingMetadata(identity: ListingIdentity) {
117
+ return { symbol: identity.symbol, exchange: identity.exchange || null, name: identity.name };
118
+ }
119
+
70
120
  const QUOTE_LEAD_COLUMNS = [
71
121
  { key: "symbol", header: "Symbol" },
72
122
  { key: "name", header: "Name" },
@@ -86,7 +136,8 @@ function quoteColumns() {
86
136
  return [
87
137
  ...QUOTE_LEAD_COLUMNS,
88
138
  { key: "currency", header: "Cur" },
89
- { key: "source", header: "Source" },
139
+ // Whether the price is real-time or delayed: a feed state, not where it came from.
140
+ { key: "source", header: "Feed", format: (value: unknown) => value === "live" || value === "delayed" ? value : "" },
90
141
  { key: "updatedAt", header: "Updated" },
91
142
  ];
92
143
  }
@@ -332,40 +383,78 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
332
383
  if (symbols.length === 0) ctx.fail(`Usage: gloomberb ${commandName} <symbol...>`);
333
384
 
334
385
  await withMarketData(ctx, async (market) => {
335
- const results = await market.dataProvider.getQuotesBatch(
336
- symbols.map((symbol) => ({ symbol, exchange })),
337
- { forceRefresh: ctx.cliOptions.refresh },
338
- );
339
- const data = results.map((result) => ({
386
+ // With several symbols, --exchange is for the ones that name no exchange of their own.
387
+ const listings = await Promise.all(symbols.map((symbol) => requireCliListing(
388
+ symbol, exchange, market, ctx, { ownExchangeWins: symbols.length > 1 },
389
+ )));
390
+ const targets: QuoteSubscriptionTarget[] = listings.map((listing) => ({ symbol: listing.request.symbol, exchange: listing.request.exchange }));
391
+ const results = await market.dataProvider.getQuotesBatch(targets, { forceRefresh: ctx.cliOptions.refresh });
392
+ const listingOf = (result: QuoteBatchResult, index: number) => listings[targets.indexOf(result.target)] ?? listings[index]!;
393
+ // A listing with no quote on an exchange its symbol is not listed on says so; venues are only looked up for those.
394
+ const notTraded = await Promise.all(results.map((result, index) => (
395
+ result.quote ? null : notTradedMessage(listingOf(result, index), market)
396
+ )));
397
+ if (listings.length === 1 && notTraded[0]) ctx.fail(notTraded[0]);
398
+ // Each row names its listing by key (SAN:EPA) and company, so the table needs no line above it.
399
+ const data = results.map((result, index) => ({
340
400
  target: result.target,
401
+ listing: listingMetadata(listingIdentity(listingOf(result, index), result.quote)),
341
402
  quote: result.quote,
342
- error: errorMessage(result.error),
403
+ error: notTraded[index] ?? errorMessage(result.error),
343
404
  }));
344
- ctx.printResult({ data }, { rows: quoteRows, columns: commandName === "compare" ? compareColumns() : quoteColumns() });
405
+ // Text mode shows only "unavailable" in the cell; the JSON rows already carry each reason.
406
+ const notes = ctx.cliOptions.format === "text" ? quoteNotes(data, { exchange }) : [];
407
+ ctx.printResult({
408
+ data,
409
+ warnings: notes.length > 0 ? notes : undefined,
410
+ freshness: quotesFreshness(data.map((row) => row.quote)),
411
+ }, {
412
+ rows: quoteRows,
413
+ columns: commandName === "compare" ? compareColumns() : quoteColumns(),
414
+ });
345
415
  });
346
416
  }
347
417
 
418
+ /** A crypto pair that will not load points at the crypto board. Structured formats keep the error as thrown. */
419
+ function failHistory(error: unknown, symbol: string, ctx: Parameters<CliCommandDef["execute"]>[1]): never {
420
+ if (ctx.cliOptions.format !== "text" || !isCryptoPairSymbol(symbol)) throw error;
421
+ return ctx.fail(errorMessage(error) ?? `No history available for ${symbol}`, CRYPTO_BOARD_HINT);
422
+ }
423
+
348
424
  async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
349
425
  const args = [...rawArgs];
350
426
  const range = parseRange(takeOption(args, "--range"), ctx);
351
- const requestedExchange = takeOption(args, "--exchange") ?? "";
352
- const symbol = requireArg(args[0]?.toUpperCase(), "Usage: gloomberb history <symbol> [--range <range>]", ctx);
427
+ const requestedExchange = takeOption(args, "--exchange");
428
+ const raw = requireArg(args[0], "Usage: gloomberb history <symbol> [--range <range>]", ctx);
353
429
  await withMarketData(ctx, async (market) => {
354
- const localTicker = requestedExchange ? null : await market.store.loadTicker(symbol);
355
- const exchange = requestedExchange || localTicker?.metadata.exchange || "";
430
+ const listing = await requireCliListing(raw, requestedExchange, market, ctx);
431
+ const { symbol, exchange } = listing.request;
356
432
  const context = { cacheMode: ctx.cliOptions.refresh ? "refresh" as const : "default" as const };
357
- const { points, resolution } = market.dataProvider.getPriceHistoryWithMetadata
358
- ? await market.dataProvider.getPriceHistoryWithMetadata(symbol, exchange, range, context)
359
- : { points: await market.dataProvider.getPriceHistory(symbol, exchange, range, context), resolution: null };
433
+ const load = () => market.dataProvider.getPriceHistoryWithMetadata
434
+ ? market.dataProvider.getPriceHistoryWithMetadata(symbol, exchange, range, context)
435
+ : market.dataProvider.getPriceHistory(symbol, exchange, range, context).then((points) => ({ points, resolution: null }));
436
+ const [{ points, resolution }, quote] = await Promise.all([
437
+ loadForListing(listing, market, ctx, load, (loaded) => loaded.points.length === 0)
438
+ .catch((error) => failHistory(error, listing.key, ctx)),
439
+ loadListingQuote(market.dataProvider, listing),
440
+ ]);
441
+ const identity = listingIdentity(listing, quote);
360
442
  const data = historyRows(points, resolution);
361
- const decimals = historyPriceDecimals(data, localTicker?.metadata.assetCategory);
443
+ const decimals = historyPriceDecimals(data, listing.saved?.metadata.assetCategory);
362
444
  const price = (value: unknown) => typeof value === "number" ? value.toFixed(decimals) : "";
363
445
  // Intraday bars print in UTC, as the charts and time and sales label them, not the host zone.
364
446
  const intraday = data.some((row) => row.date.length > 10);
365
- ctx.printResult({ data, metadata: { symbol, range, exchange, resolution } }, {
447
+ // A bar history: dated by its last bar, stale once bars of its size stop arriving.
448
+ const freshness = rowsFreshness(data, {
449
+ ...barHistoryFreshness(intraday ? null : barResolutionFromDates(data.map((row) => row.date))),
450
+ observedKey: "date",
451
+ oldest: null,
452
+ });
453
+ ctx.printResult({ data, metadata: { ...listingMetadata(identity), range, resolution }, freshness }, {
454
+ heading: listingHeading(identity),
366
455
  columns: [
367
456
  intraday
368
- ? { key: "date", header: "Time (UTC)", format: (value) => typeof value === "string" ? value.slice(0, 16).replace("T", " ") : "" }
457
+ ? { key: "date", header: "Time", format: (value) => typeof value === "string" ? formatUtcTime(value) : "" }
369
458
  : { key: "date", header: "Date" },
370
459
  { key: "open", header: "Open", align: "right", format: price },
371
460
  { key: "high", header: "High", align: "right", format: price },
@@ -381,34 +470,44 @@ type FinancialsView = "statements" | "fundamentals" | "valuation";
381
470
 
382
471
  async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1], view: FinancialsView) {
383
472
  const args = [...rawArgs];
384
- const exchange = takeOption(args, "--exchange") ?? "";
473
+ const exchangeOption = takeOption(args, "--exchange");
385
474
  const commandName = view === "statements" ? "financials" : view;
386
- const symbol = requireArg(args[0]?.toUpperCase(), `Usage: gloomberb ${commandName} <symbol>`, ctx);
475
+ const raw = requireArg(args[0], `Usage: gloomberb ${commandName} <symbol>`, ctx);
387
476
  await withMarketData(ctx, async (market) => {
388
- const financials = await market.dataProvider.getTickerFinancials(symbol, exchange, {
389
- cacheMode: ctx.cliOptions.refresh ? "refresh" : "default",
390
- });
477
+ const listing = await requireCliListing(raw, exchangeOption, market, ctx);
478
+ const financials = await loadForListing(listing, market, ctx, () => market.dataProvider.getTickerFinancials(
479
+ listing.request.symbol, listing.request.exchange, { cacheMode: ctx.cliOptions.refresh ? "refresh" : "default" },
480
+ ));
481
+ const identity = listingIdentity(listing, financials.quote);
391
482
  const data: FinancialsCliData = {
392
- symbol,
393
- exchange,
483
+ symbol: listing.key,
484
+ exchange: identity.exchange,
394
485
  providerId: financials.quote?.providerId ?? null,
395
486
  ...financials,
396
487
  };
397
488
  if (view !== "statements") {
398
- ctx.printResult({ data }, { text: (financialsData) => renderFundamentalsReport(financialsData, view) });
489
+ ctx.printResult({
490
+ // JSON reads a multiple over a loss as null with its reason, never as a number.
491
+ data: { ...data, fundamentals: exportedFundamentals(data.fundamentals) },
492
+ freshness: fundamentalsFreshness(financials),
493
+ }, { text: () => renderFundamentalsReport(data, view) });
399
494
  return;
400
495
  }
401
496
  ctx.printResult({
402
497
  data,
403
498
  metadata: {
404
- symbol,
499
+ ...listingMetadata(identity),
405
500
  providerId: financials.quote?.providerId,
406
501
  annualStatements: financials.annualStatements.length,
407
502
  quarterlyStatements: financials.quarterlyStatements.length,
408
- fundamentals: financials.fundamentals,
503
+ fundamentals: exportedFundamentals(financials.fundamentals),
409
504
  profile: financials.profile,
410
505
  },
506
+ freshness: rowsFreshness(financialStatementRows(data), {
507
+ ...REPORTED_DATA, basis: "financial statements", observedKey: "date", oldest: null,
508
+ }),
411
509
  }, {
510
+ heading: listingHeading(identity),
412
511
  rows: financialStatementRows,
413
512
  columns: [
414
513
  { key: "date", header: "Date" },
@@ -426,24 +525,39 @@ async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["e
426
525
  async function runNews(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
427
526
  const args = [...rawArgs];
428
527
  const feed = parseNewsFeed(takeOption(args, "--feed"));
429
- const ticker = args[0]?.toUpperCase();
528
+ const exchangeOption = takeOption(args, "--exchange");
529
+ if (exchangeOption && !args[0]) ctx.fail("--exchange needs a symbol: gloomberb news <symbol> --exchange <code>");
430
530
  await withMarketData(ctx, async (market) => {
531
+ const listing = args[0] ? await requireCliListing(args[0], exchangeOption, market, ctx) : null;
431
532
  const limit = ctx.cliOptions.limit ?? 20;
432
- const articles = await market.dataProvider.getNews({
433
- feed: feed ?? (ticker ? "ticker" : "latest"),
533
+ const loadNews = () => market.dataProvider.getNews({
534
+ feed: feed ?? (listing ? "ticker" : "latest"),
434
535
  // Still set for news plugins that read the deprecated scope.
435
- scope: ticker ? "ticker" : "global",
436
- ticker,
536
+ scope: listing ? "ticker" : "global",
537
+ ticker: listing?.request.symbol,
538
+ exchange: listing?.request.exchange || undefined,
437
539
  limit,
438
540
  });
439
- ctx.printResult({ data: articles, metadata: { ticker: ticker ?? null, feed: feed ?? null } }, {
541
+ const [articles, quote] = await Promise.all([
542
+ listing ? loadForListing(listing, market, ctx, loadNews, (found) => found.length === 0) : loadNews(),
543
+ listing ? loadListingQuote(market.dataProvider, listing) : null,
544
+ ]);
545
+ const identity = listing ? listingIdentity(listing, quote) : null;
546
+ ctx.printResult({
547
+ data: articles,
548
+ metadata: { ticker: listing?.key ?? null, ...(identity ? listingMetadata(identity) : {}), feed: feed ?? null },
549
+ freshness: rowsFreshness(newsRows(articles), {
550
+ status: "not-a-feed", basis: "published stories", observedKey: "publishedAt", oldest: null,
551
+ }),
552
+ }, {
553
+ ...(identity ? { heading: listingHeading(identity) } : {}),
440
554
  rows: newsRows,
441
555
  columns: [
442
- // UTC, as the news panes print it, rather than the host zone unlabeled.
556
+ // UTC with the zone named, as every CLI time prints, rather than the host zone unlabeled.
443
557
  {
444
558
  key: "publishedAt",
445
- header: "Published (UTC)",
446
- format: (value) => typeof value === "string" ? value.slice(0, 16).replace("T", " ") : "",
559
+ header: "Published",
560
+ format: (value) => typeof value === "string" ? formatUtcTime(value) : "",
447
561
  },
448
562
  { key: "source", header: "Source", maxWidth: 20 },
449
563
  { key: "title", header: "Title" },
@@ -454,22 +568,67 @@ async function runNews(rawArgs: string[], ctx: Parameters<CliCommandDef["execute
454
568
  });
455
569
  }
456
570
 
571
+ const FILING_COLUMNS = [
572
+ { key: "filingDate", header: "Date" },
573
+ { key: "form", header: "Form" },
574
+ { key: "companyName", header: "Company", maxWidth: 24 },
575
+ { key: "url", header: "URL", optional: true },
576
+ ];
577
+
578
+ /** The US listing the SEC files a symbol under, from the symbol's venues: NYSE for SAN's Banco Santander. */
579
+ async function registrantUsExchange(market: MarketContext, symbol: string, registrantName: string): Promise<string | null> {
580
+ const venues = (await listingVenues(symbol, market).catch(() => []))
581
+ .filter((venue) => !nonUsSecListingVenue(symbol, venue.exchange) && !areDifferentCompanies(venue.name, registrantName));
582
+ return (venues.find((venue) => isUsListingExchange(venue.exchange)) ?? venues[0])?.exchange ?? null;
583
+ }
584
+
457
585
  async function runFilings(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
458
586
  const args = [...rawArgs];
459
587
  const count = parsePositiveInt(takeOption(args, "--count"), ctx.cliOptions.limit ?? 15, "Count", ctx);
460
- const exchange = takeOption(args, "--exchange") ?? "";
461
- const symbol = requireArg(args[0]?.toUpperCase(), "Usage: gloomberb filings <symbol>", ctx);
588
+ const exchangeOption = takeOption(args, "--exchange");
589
+ const form = takeOption(args, "--form")?.trim() || null;
590
+ const raw = requireArg(args[0], "Usage: gloomberb filings <symbol>", ctx);
462
591
  await withMarketData(ctx, async (market) => {
463
- const filings = await market.dataProvider.getSecFilings(symbol, count, exchange);
464
- ctx.printResult({ data: filings, metadata: { symbol } }, {
465
- rows: filingRows,
466
- columns: [
467
- { key: "filingDate", header: "Date" },
468
- { key: "form", header: "Form" },
469
- { key: "companyName", header: "Company", maxWidth: 24 },
470
- { key: "url", header: "URL", optional: true },
471
- ],
472
- });
592
+ const listing = await requireCliListing(raw, exchangeOption, market, ctx);
593
+ const { symbol, exchange } = listing.request;
594
+ // A listing outside the US sends its company to the lookup, which needs its quote first.
595
+ const quotePromise = loadListingQuote(market.dataProvider, listing);
596
+ const identity = nonUsSecListingVenue(symbol, exchange) ? listingIdentity(listing, await quotePromise) : null;
597
+ try {
598
+ const context = identity?.name ? { listingName: identity.name } : undefined;
599
+ const [filings, quote] = await Promise.all([
600
+ loadForListing(listing, market, ctx, () => form
601
+ // A form filter searches every filing the service lists for the issuer, as the SEC pane does.
602
+ ? market.dataProvider.getSecFilings(symbol, SEC_FILING_FETCH_LIMIT, exchange, context)
603
+ .then((all) => all.filter((filing) => filingFormMatches(filing.form, form)).slice(0, count))
604
+ : market.dataProvider.getSecFilings(symbol, count, exchange, context),
605
+ (found) => found.length === 0),
606
+ quotePromise,
607
+ ]);
608
+ const resolved = identity ?? listingIdentity(listing, quote);
609
+ ctx.printResult({
610
+ data: filings,
611
+ metadata: { ...listingMetadata(resolved), ...(form ? { form } : {}) },
612
+ freshness: rowsFreshness(filingRows(filings), { ...SEC_FILINGS, observedKey: "filingDate" }),
613
+ }, {
614
+ heading: listingHeading(resolved),
615
+ rows: filingRows,
616
+ columns: FILING_COLUMNS,
617
+ empty: form ? `No ${form} filings found for ${listingTitle(resolved)}.` : `No SEC filings found for ${listingTitle(resolved)}.`,
618
+ });
619
+ } catch (error) {
620
+ if (!(error instanceof SecRegistrantMismatchError)) throw error;
621
+ // Another company's filings never show under this listing; say whose they were.
622
+ const message = secRegistrantMismatchMessage(
623
+ error.listing, error.registrantName, await registrantUsExchange(market, error.listing.symbol, error.registrantName),
624
+ );
625
+ const resolved = identity ?? listingIdentity(listing, await quotePromise);
626
+ ctx.printResult({
627
+ data: [] as SecFilingItem[],
628
+ metadata: { ...listingMetadata(resolved), secRegistrant: error.registrantName },
629
+ warnings: ctx.cliOptions.format === "text" ? undefined : [message],
630
+ }, { rows: filingRows, columns: FILING_COLUMNS, empty: message });
631
+ }
473
632
  });
474
633
  }
475
634
 
@@ -487,6 +646,52 @@ function insiderSummary(data: HolderData, ownerTypes: Set<string>): string {
487
646
  return [share, transactions].filter(Boolean).join("\n");
488
647
  }
489
648
 
649
+ /** `holders --form 13d|13g|all`: the 13D/13G beneficial owners, joined by name to the 13F holders. */
650
+ async function printBeneficialOwners(
651
+ listing: CliListing,
652
+ market: MarketContext,
653
+ form: Exclude<HolderForm, "13f">,
654
+ history: boolean,
655
+ ctx: Parameters<CliCommandDef["execute"]>[1],
656
+ ) {
657
+ const { symbol, exchange } = listing.request;
658
+ const [payload, holders, quote] = await Promise.all([
659
+ loadForListing(listing, market, ctx, () => fetchBeneficialOwners(symbol, { form: beneficialRouteForm(form), history })),
660
+ market.dataProvider.getHolders?.(symbol, exchange).catch(() => null) ?? null,
661
+ loadListingQuote(market.dataProvider, listing),
662
+ ]);
663
+ const identity = listingIdentity(listing, quote);
664
+ const rows = buildBeneficialReportRows(payload, { history, holders });
665
+ const notices = beneficialCoverageNotices(payload.coverage);
666
+ ctx.printResult({
667
+ data: rows,
668
+ ...(notices.length ? { warnings: notices } : {}),
669
+ metadata: {
670
+ ...listingMetadata(identity),
671
+ name: identity.name ?? (payload.companyName || null),
672
+ cik: payload.cik || null,
673
+ form,
674
+ history,
675
+ asOf: payload.asOf,
676
+ coverage: payload.coverage,
677
+ complete: beneficialListComplete(payload),
678
+ },
679
+ }, {
680
+ heading: `${listingHeading(identity)}${cliStyles.muted(beneficialListFacts(payload, form, rows.length, history).map((fact) => ` · ${fact}`).join(""))}`,
681
+ textColumns: BENEFICIAL_REPORT_COLUMNS,
682
+ columns: [
683
+ ...BENEFICIAL_REPORT_COLUMNS,
684
+ { key: "status", header: "Status" },
685
+ { key: "filerCik", header: "Filer CIK" },
686
+ { key: "accessionNumber", header: "Accession" },
687
+ { key: "filingUrl", header: "URL" },
688
+ ],
689
+ empty: beneficialListUnreadable(payload)
690
+ ? `13D/13G filings for ${listingTitle(identity)} are listed but could not be read.`
691
+ : `No 13D/13G filings in the last 4 years for ${listingTitle(identity)}.`,
692
+ });
693
+ }
694
+
490
695
  async function runHolders(
491
696
  rawArgs: string[],
492
697
  ctx: Parameters<CliCommandDef["execute"]>[1],
@@ -494,43 +699,98 @@ async function runHolders(
494
699
  ownerTypes?: Set<string>,
495
700
  ) {
496
701
  const args = [...rawArgs];
497
- const exchange = takeOption(args, "--exchange") ?? "";
498
- const symbol = requireArg(args[0]?.toUpperCase(), `Usage: gloomberb ${commandName} <symbol>`, ctx);
702
+ const exchangeOption = takeOption(args, "--exchange");
703
+ const formOption = commandName === "holders" ? takeOption(args, "--form") : undefined;
704
+ const history = commandName === "holders" && takeFlag(args, "--history");
705
+ const raw = requireArg(args[0], `Usage: gloomberb ${commandName} <symbol>`, ctx);
706
+ const form = formOption == null ? "13f" : parseHolderForm(formOption);
707
+ if (!form) ctx.fail(`Unknown form "${formOption}".`, `Use one of ${HOLDER_FORMS.join(", ")}.`);
708
+ if (form === "13f" && history) ctx.fail("--history lists 13D/13G reports.", "Add --form 13d, 13g or all.");
499
709
  await withMarketData(ctx, async (market) => {
500
- const data = await market.dataProvider.getHolders(symbol, exchange);
501
- ctx.printResult({ data, metadata: { symbol, summary: data.summary } }, {
502
- rows: (holderData) => holderRows(holderData, ownerTypes),
710
+ const listing = await requireCliListing(raw, exchangeOption, market, ctx);
711
+ if (form !== "13f") return printBeneficialOwners(listing, market, form, history, ctx);
712
+ const [data, quote] = await Promise.all([
713
+ loadForListing(
714
+ listing, market, ctx,
715
+ () => market.dataProvider.getHolders(listing.request.symbol, listing.request.exchange),
716
+ (found) => found.holders.length === 0,
717
+ ),
718
+ loadListingQuote(market.dataProvider, listing),
719
+ ]);
720
+ const identity = listingIdentity(listing, quote);
721
+ const rows = holderRows(data, ownerTypes);
722
+ const limit = ctx.cliOptions.limit;
723
+ const shown = limit == null ? rows.length : Math.min(limit, rows.length);
724
+ const institutional = !ownerTypes?.has("insider");
725
+ const total = institutional ? data.summary?.institutionsCount ?? null : null;
726
+ const reportDate = sharedReportDate(rows);
727
+ const valueBasis = rows.length > 0 ? holderValueBasis(reportDate) : null;
728
+ const positionsBasis = rows.length > 0 ? nonUsHolderCaveat(identity.exchange || data.exchange, data.currency) : null;
729
+ // The heading names the listing; its unit, date and how much of the list follows on the same line.
730
+ const facts = holderListFacts({ currency: data.currency, asOf: data.asOf, shown, reported: rows.length, total });
731
+ ctx.printResult({
732
+ data,
733
+ metadata: {
734
+ ...listingMetadata(identity),
735
+ summary: data.summary,
736
+ currency: data.currency ?? null,
737
+ asOf: data.asOf ?? null,
738
+ shown,
739
+ reported: rows.length,
740
+ total,
741
+ truncated: shown < (total ?? rows.length),
742
+ valueBasis,
743
+ positionsBasis,
744
+ },
745
+ }, {
746
+ heading: `${listingHeading(identity)}${cliStyles.muted(facts.map((fact) => ` · ${fact}`).join(""))}`,
747
+ rows: () => rows,
503
748
  columns: [
504
749
  { key: "type", header: "Type" },
505
750
  { key: "name", header: "Holder" },
506
751
  { key: "reportDate", header: "Date" },
507
752
  { key: "shares", header: "Shares", align: "right", format: formatCountCell },
508
- { key: "value", header: "Value", align: "right", value: (row) => row.value == null ? "" : formatCompact(Number(row.value)) },
753
+ {
754
+ key: "value",
755
+ header: moneyColumnHeader("Value", data.currency),
756
+ align: "right",
757
+ value: (row) => row.value == null ? "" : formatCompact(Number(row.value)),
758
+ },
509
759
  { key: "percentHeld", header: "% Held", align: "right", format: formatFractionPercentCell },
510
760
  ],
511
- ...(commandName === "insider" && ownerTypes
512
- ? { summary: (holderData: HolderData) => insiderSummary(holderData, ownerTypes) }
513
- : {}),
514
- empty: `No holders reported for ${symbol}.`,
761
+ summary: (holderData: HolderData) => [
762
+ [valueBasis ? `Value = ${valueBasis}.` : "", positionsBasis ?? ""].filter(Boolean).join(" "),
763
+ commandName === "insider" && ownerTypes ? insiderSummary(holderData, ownerTypes) : "",
764
+ ].filter(Boolean).join("\n"),
765
+ empty: `No holders reported for ${listingTitle(identity)}.`,
515
766
  });
516
767
  });
517
768
  }
518
769
 
519
770
  async function runAnalyst(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
520
771
  const args = [...rawArgs];
521
- const exchange = takeOption(args, "--exchange") ?? "";
522
- const symbol = requireArg(args[0]?.toUpperCase(), "Usage: gloomberb analyst <symbol>", ctx);
772
+ const exchangeOption = takeOption(args, "--exchange");
773
+ const raw = requireArg(args[0], "Usage: gloomberb analyst <symbol>", ctx);
523
774
  await withMarketData(ctx, async (market) => {
524
- const data = await market.dataProvider.getAnalystResearch(symbol, exchange);
775
+ const listing = await requireCliListing(raw, exchangeOption, market, ctx);
776
+ const [data, quote] = await Promise.all([
777
+ loadForListing(listing, market, ctx, () => market.dataProvider.getAnalystResearch(listing.request.symbol, listing.request.exchange)),
778
+ loadListingQuote(market.dataProvider, listing),
779
+ ]);
780
+ const identity = listingIdentity(listing, quote);
525
781
  ctx.printResult({
526
782
  data,
527
783
  metadata: {
528
- symbol,
784
+ ...listingMetadata(identity),
529
785
  recommendationRating: data.recommendationRating,
530
786
  priceTarget: data.priceTarget,
531
787
  recommendations: data.recommendations,
532
788
  },
789
+ freshness: rowsFreshness(analystRows(data), {
790
+ ...REPORTED_DATA, basis: "analyst ratings", observedKey: "date", oldest: null,
791
+ }, { stale: data.stale === true }),
533
792
  }, {
793
+ heading: listingHeading(identity),
534
794
  rows: analystRows,
535
795
  summary: analystSummary,
536
796
  columns: [
@@ -546,11 +806,23 @@ async function runAnalyst(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
546
806
 
547
807
  async function runEvents(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
548
808
  const args = [...rawArgs];
549
- const exchange = takeOption(args, "--exchange") ?? "";
550
- const symbol = requireArg(args[0]?.toUpperCase(), "Usage: gloomberb events <symbol>", ctx);
809
+ const exchangeOption = takeOption(args, "--exchange");
810
+ const raw = requireArg(args[0], "Usage: gloomberb events <symbol>", ctx);
551
811
  await withMarketData(ctx, async (market) => {
552
- const data = await market.dataProvider.getCorporateActions(symbol, exchange);
553
- ctx.printResult({ data, metadata: { symbol } }, {
812
+ const listing = await requireCliListing(raw, exchangeOption, market, ctx);
813
+ const [data, quote] = await Promise.all([
814
+ loadForListing(listing, market, ctx, () => market.dataProvider.getCorporateActions(listing.request.symbol, listing.request.exchange)),
815
+ loadListingQuote(market.dataProvider, listing),
816
+ ]);
817
+ const identity = listingIdentity(listing, quote);
818
+ ctx.printResult({
819
+ data,
820
+ metadata: listingMetadata(identity),
821
+ freshness: rowsFreshness(corporateActionRows(data), {
822
+ ...REPORTED_DATA, basis: "corporate actions", observedKey: "date", oldest: null,
823
+ }),
824
+ }, {
825
+ heading: listingHeading(identity),
554
826
  rows: corporateActionRows,
555
827
  columns: [
556
828
  { key: "date", header: "Date" },
@@ -564,22 +836,38 @@ async function runEvents(rawArgs: string[], ctx: Parameters<CliCommandDef["execu
564
836
  async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
565
837
  const args = [...rawArgs];
566
838
  const expiration = takeOption(args, "--expiration");
567
- const exchange = takeOption(args, "--exchange") ?? "";
568
- const symbol = requireArg(args[0]?.toUpperCase(), "Usage: gloomberb options <symbol> [--expiration <unix>]", ctx);
839
+ const exchangeOption = takeOption(args, "--exchange");
840
+ const raw = requireArg(args[0], "Usage: gloomberb options <symbol> [--expiration <unix>]", ctx);
569
841
  await withMarketData(ctx, async (market) => {
842
+ const listing = await requireCliListing(raw, exchangeOption, market, ctx);
843
+ const { symbol, exchange } = listing.request;
570
844
  const expirationDate = expiration == null ? undefined : Number(expiration);
571
- const result = await market.dataProvider.getCachedQuery?.("getOptionsChain", [symbol, exchange, expirationDate, undefined])
572
- .load({ force: ctx.cliOptions.refresh });
573
- const chain = result?.value ?? await market.dataProvider.getOptionsChain(symbol, exchange, expirationDate, {
574
- cacheMode: ctx.cliOptions.refresh ? "refresh" : "default",
845
+ const quotePromise = loadListingQuote(market.dataProvider, listing);
846
+ const { result, chain } = await loadForListing(listing, market, ctx, async () => {
847
+ const cached = await market.dataProvider.getCachedQuery?.("getOptionsChain", [symbol, exchange, expirationDate, undefined])
848
+ .load({ force: ctx.cliOptions.refresh });
849
+ return {
850
+ result: cached,
851
+ chain: cached?.value ?? await market.dataProvider.getOptionsChain(symbol, exchange, expirationDate, {
852
+ cacheMode: ctx.cliOptions.refresh ? "refresh" : "default",
853
+ }),
854
+ };
575
855
  });
856
+ const identity = listingIdentity(listing, await quotePromise);
576
857
  // A failed refresh falls back to the stored chain, which can be days old.
577
858
  const refreshWarning = result?.refreshError == null ? null
578
859
  : `Options refresh failed; showing the chain stored ${new Date(result.fetchedAt).toISOString()}`
579
860
  + (chain.asOf ? ` (last trade ${chain.asOf})` : "");
580
- const sessionWarning = refreshWarning ? null : priorSessionChainWarning(chain, exchange, Date.now());
861
+ const sessionWarning = refreshWarning ? null : priorSessionChainWarning(chain, identity.exchange, Date.now());
581
862
  const warnings = refreshWarning ? [refreshWarning] : sessionWarning ? [sessionWarning] : undefined;
582
- ctx.printResult({ data: chain, metadata: { symbol, expirations: chain.expirationDates }, warnings }, {
863
+ // Dated by the chain's last trade; a chain that failed to refresh is the stored one, stale.
864
+ const freshness = rowsFreshness([], { asOf: chain.asOf ?? null }, {
865
+ ...(chain.dataSource ? { dataSource: chain.dataSource } : {}),
866
+ ...(chain.delayMinutes != null ? { delayMinutes: chain.delayMinutes } : {}),
867
+ stale: refreshWarning != null,
868
+ });
869
+ ctx.printResult({ data: chain, metadata: { ...listingMetadata(identity), expirations: chain.expirationDates }, warnings, freshness }, {
870
+ heading: listingHeading(identity),
583
871
  rows: optionRows,
584
872
  columns: [
585
873
  { key: "side", header: "Side" },
@@ -619,9 +907,10 @@ async function runFx(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]
619
907
  ...(asOf || stale ? [{
620
908
  key: "asOf",
621
909
  header: "As Of",
622
- format: (value: unknown, row: { stale: boolean }) => (
623
- row.stale ? cliStyles.warning(`${value ?? ""} stale`.trim()) : String(value ?? "")
624
- ),
910
+ format: (value: unknown, row: { stale: boolean }) => {
911
+ const time = typeof value === "string" ? formatUtcTime(value) : "";
912
+ return row.stale ? cliStyles.warning(`${time} stale`.trim()) : time;
913
+ },
625
914
  }] : []),
626
915
  ],
627
916
  });
@@ -629,11 +918,23 @@ async function runFx(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]
629
918
  }
630
919
 
631
920
  async function runEarnings(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
632
- const symbols = normalizeSymbols([...rawArgs]);
921
+ const args = [...rawArgs];
922
+ const exchangeOption = takeOption(args, "--exchange");
923
+ const symbols = normalizeSymbols(args);
633
924
  if (symbols.length === 0) ctx.fail("Usage: gloomberb earnings <symbol...>");
634
925
  await withCliServices(ctx, async (services) => {
635
- const events = await services.dataProvider.getEarningsCalendar(symbols);
636
- ctx.printResult({ data: events }, {
926
+ const listings = await Promise.all(symbols.map((symbol) => requireCliListing(
927
+ symbol, exchangeOption, services, ctx, { ownExchangeWins: symbols.length > 1 },
928
+ )));
929
+ const events = await loadForListing(
930
+ listings, services, ctx,
931
+ () => services.dataProvider.getEarningsCalendar(listings.map((listing) => listing.key)),
932
+ (found) => found.length === 0,
933
+ );
934
+ ctx.printResult({
935
+ data: events,
936
+ freshness: rowsFreshness(earningsRows(events), { status: "not-a-feed", basis: "calendar", observedKey: "date", oldest: null }),
937
+ }, {
637
938
  rows: earningsRows,
638
939
  columns: [
639
940
  { key: "date", header: "Date" },
@@ -655,7 +956,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
655
956
  group: CLI_COMMAND_GROUPS.research,
656
957
  usage: ["quote <symbol...>"],
657
958
  options: [EXCHANGE_OPTION],
658
- examples: ["quote AAPL MSFT NVDA", "quote BTC-USD EURUSD=X", "quote AAPL --json"],
959
+ examples: ["quote AAPL MSFT NVDA", "quote SAN:EPA BHP:ASX", "quote BTC-USD EURUSD=X", "quote AAPL --json"],
659
960
  },
660
961
  execute: (args, ctx) => runQuote(args, ctx, "quote"),
661
962
  },
@@ -666,7 +967,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
666
967
  group: CLI_COMMAND_GROUPS.research,
667
968
  usage: ["compare <symbol...>"],
668
969
  options: [EXCHANGE_OPTION],
669
- examples: ["compare KO PEP", "compare SPY QQQ IWM --csv"],
970
+ examples: ["compare KO PEP", "compare SAN:EPA SAN:NYSE", "compare SPY QQQ IWM --csv"],
670
971
  },
671
972
  execute: (args, ctx) => runQuote(args, ctx, "compare"),
672
973
  },
@@ -680,7 +981,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
680
981
  { flags: "--range <range>", description: `${TIME_RANGES.join(", ")} (default 1Y)` },
681
982
  EXCHANGE_OPTION,
682
983
  ],
683
- examples: ["history AAPL", "history AAPL --range 5Y --csv > aapl.csv"],
984
+ examples: ["history AAPL", "history BHP:ASX --range 5Y", "history AAPL --range 5Y --csv > aapl.csv"],
684
985
  },
685
986
  execute: runHistory,
686
987
  },
@@ -694,7 +995,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
694
995
  { flags: "--expiration <unix>", description: "Expiration as Unix seconds; defaults to the nearest one" },
695
996
  EXCHANGE_OPTION,
696
997
  ],
697
- examples: ["options AAPL", "options AAPL --json"],
998
+ examples: ["options AAPL", "options AAPL:NASDAQ --json"],
698
999
  },
699
1000
  execute: runOptions,
700
1001
  },
@@ -732,7 +1033,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
732
1033
  group: CLI_COMMAND_GROUPS.companyData,
733
1034
  usage: ["financials <symbol>"],
734
1035
  options: [EXCHANGE_OPTION],
735
- examples: ["financials MSFT", "financials MSFT --json"],
1036
+ examples: ["financials MSFT", "financials SAN:EPA", "financials MSFT --json"],
736
1037
  },
737
1038
  execute: (args, ctx) => runFinancials(args, ctx, "statements"),
738
1039
  },
@@ -743,7 +1044,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
743
1044
  group: CLI_COMMAND_GROUPS.companyData,
744
1045
  usage: ["fundamentals <symbol>"],
745
1046
  options: [EXCHANGE_OPTION],
746
- examples: ["fundamentals NVDA"],
1047
+ examples: ["fundamentals NVDA", "fundamentals ASML:AMS"],
747
1048
  },
748
1049
  execute: (args, ctx) => runFinancials(args, ctx, "fundamentals"),
749
1050
  },
@@ -754,7 +1055,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
754
1055
  group: CLI_COMMAND_GROUPS.companyData,
755
1056
  usage: ["valuation <symbol>"],
756
1057
  options: [EXCHANGE_OPTION],
757
- examples: ["valuation NVDA"],
1058
+ examples: ["valuation NVDA", "valuation BP:LSE"],
758
1059
  },
759
1060
  execute: (args, ctx) => runFinancials(args, ctx, "valuation"),
760
1061
  },
@@ -764,7 +1065,8 @@ export const marketDataCliCommands: CliCommandDef[] = [
764
1065
  help: {
765
1066
  group: CLI_COMMAND_GROUPS.companyData,
766
1067
  usage: ["earnings <symbol...>"],
767
- examples: ["earnings AAPL MSFT GOOGL"],
1068
+ options: [EXCHANGE_OPTION],
1069
+ examples: ["earnings AAPL MSFT GOOGL", "earnings SAN:EPA"],
768
1070
  },
769
1071
  execute: runEarnings,
770
1072
  },
@@ -775,7 +1077,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
775
1077
  group: CLI_COMMAND_GROUPS.companyData,
776
1078
  usage: ["events <symbol>"],
777
1079
  options: [EXCHANGE_OPTION],
778
- examples: ["events KO"],
1080
+ examples: ["events KO", "events BHP:ASX"],
779
1081
  },
780
1082
  execute: runEvents,
781
1083
  },
@@ -786,18 +1088,22 @@ export const marketDataCliCommands: CliCommandDef[] = [
786
1088
  group: CLI_COMMAND_GROUPS.companyData,
787
1089
  usage: ["analyst <symbol>"],
788
1090
  options: [EXCHANGE_OPTION],
789
- examples: ["analyst TSLA"],
1091
+ examples: ["analyst TSLA", "analyst SAN:EPA"],
790
1092
  },
791
1093
  execute: runAnalyst,
792
1094
  },
793
1095
  {
794
1096
  name: "holders",
795
- description: "Fetch institutional, fund, and insider holders",
1097
+ description: "Fetch institutional holders, or the 13D/13G beneficial owners",
796
1098
  help: {
797
1099
  group: CLI_COMMAND_GROUPS.companyData,
798
- usage: ["holders <symbol>"],
799
- options: [EXCHANGE_OPTION],
800
- examples: ["holders AAPL"],
1100
+ usage: ["holders <symbol> [--form 13f|13d|13g|all] [--history]"],
1101
+ options: [
1102
+ { flags: "--form <form>", description: "13f for the holder table (default); 13d, 13g or all for beneficial owners over 5%" },
1103
+ { flags: "--history", description: "With --form 13d, 13g or all, every report newest first instead of the latest per filer" },
1104
+ EXCHANGE_OPTION,
1105
+ ],
1106
+ examples: ["holders AAPL", "holders SAN:EPA", "holders CAR --form all", "holders CAR --form 13g --history --json"],
801
1107
  },
802
1108
  execute: (args, ctx) => runHolders(args, ctx, "holders"),
803
1109
  },
@@ -808,7 +1114,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
808
1114
  group: CLI_COMMAND_GROUPS.companyData,
809
1115
  usage: ["insider <symbol>"],
810
1116
  options: [EXCHANGE_OPTION],
811
- examples: ["insider NVDA"],
1117
+ examples: ["insider NVDA", "insider BP:LSE"],
812
1118
  },
813
1119
  execute: (args, ctx) => runHolders(args, ctx, "insider", new Set(["insider", "direct"])),
814
1120
  },
@@ -823,7 +1129,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
823
1129
  title: "13F filings",
824
1130
  lines: ["For each fund's reported position and its change over the quarter, run gloomberb fn 13F <symbol>."],
825
1131
  }],
826
- examples: ["13f AAPL"],
1132
+ examples: ["13f AAPL", "13f BP:NYSE"],
827
1133
  },
828
1134
  execute: (args, ctx) => runHolders(args, ctx, "13f", new Set(["institution", "fund"])),
829
1135
  },
@@ -832,12 +1138,13 @@ export const marketDataCliCommands: CliCommandDef[] = [
832
1138
  description: "Fetch recent SEC filings",
833
1139
  help: {
834
1140
  group: CLI_COMMAND_GROUPS.companyData,
835
- usage: ["filings <symbol> [--count <n>]"],
1141
+ usage: ["filings <symbol> [--count <n>] [--form <form>]"],
836
1142
  options: [
837
1143
  { flags: "--count <n>", description: "Number of filings (default 15)" },
1144
+ { flags: "--form <form>", description: "Only this form and its amendments, such as 10-K or 13D" },
838
1145
  EXCHANGE_OPTION,
839
1146
  ],
840
- examples: ["filings AAPL", "filings AAPL --count 40 --json"],
1147
+ examples: ["filings AAPL", "filings BHP:ASX", "filings AAPL --count 40 --json", "filings CAR --form 13G"],
841
1148
  },
842
1149
  execute: runFilings,
843
1150
  },
@@ -849,8 +1156,9 @@ export const marketDataCliCommands: CliCommandDef[] = [
849
1156
  usage: ["news [symbol] [--feed <feed>]"],
850
1157
  options: [
851
1158
  { flags: "--feed <feed>", description: "latest, top, or breaking for market news (default latest)" },
1159
+ EXCHANGE_OPTION,
852
1160
  ],
853
- examples: ["news", "news TSLA", "news --feed top --limit 10"],
1161
+ examples: ["news", "news TSLA", "news SAN:EPA", "news --feed top --limit 10"],
854
1162
  },
855
1163
  execute: runNews,
856
1164
  },