gloomberb 0.18.3 → 0.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1018) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/patches/electrobun@1.18.1.patch +32 -1
  6. package/src/account/auth-model.ts +7 -3
  7. package/src/account/checkout-handoff.tsx +225 -0
  8. package/src/account/device-signin-dialog.tsx +2 -2
  9. package/src/account/device-signin.ts +2 -2
  10. package/src/account/upgrade-dialog.tsx +1 -1
  11. package/src/api-client/askg.ts +2 -2
  12. package/src/api-client/auth.ts +11 -6
  13. package/src/api-client/catalysts.ts +2 -1
  14. package/src/api-client/central-bank-rates.ts +6 -0
  15. package/src/api-client/collections.ts +5 -1
  16. package/src/api-client/cot.ts +2 -0
  17. package/src/api-client/crypto-etf-flows.ts +37 -0
  18. package/src/api-client/crypto-markets.ts +60 -0
  19. package/src/api-client/data.ts +98 -5
  20. package/src/api-client/doe.ts +15 -0
  21. package/src/api-client/equity-screener.ts +28 -0
  22. package/src/api-client/exchange-announcements.ts +38 -0
  23. package/src/api-client/fund-facts.ts +39 -0
  24. package/src/api-client/futures-curve.ts +9 -1
  25. package/src/api-client/hiring.ts +301 -0
  26. package/src/api-client/index.ts +182 -16
  27. package/src/api-client/live-scan.ts +91 -0
  28. package/src/api-client/market-discovery.ts +14 -0
  29. package/src/api-client/members.ts +18 -0
  30. package/src/api-client/mna.ts +6 -0
  31. package/src/api-client/paths.ts +18 -1
  32. package/src/api-client/request.ts +224 -26
  33. package/src/api-client/research-activity.ts +3 -10
  34. package/src/api-client/short-side-publications.ts +37 -0
  35. package/src/api-client/socket.ts +64 -4
  36. package/src/api-client/swap-curve.ts +35 -0
  37. package/src/api-client/themes.ts +7 -1
  38. package/src/api-client/types.ts +96 -2
  39. package/src/app/keybindings/index.ts +3 -0
  40. package/src/app/keybindings/labels.ts +18 -1
  41. package/src/app/keybindings/resolve.ts +14 -0
  42. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  43. package/src/app/runtime/broker-import.ts +43 -26
  44. package/src/app/runtime/desktop-deeplink.ts +5 -5
  45. package/src/app/runtime/plugin-bindings.ts +2 -2
  46. package/src/app/runtime/startup.ts +13 -0
  47. package/src/app/star-prompt/status-line.tsx +2 -2
  48. package/src/architecture/core-builtin-allowlist.json +5 -2
  49. package/src/architecture/ui-literals-allowlist.json +3 -3
  50. package/src/architecture/ui-tokens-allowlist.json +1 -1
  51. package/src/brokers/broker-portfolio-sync.ts +37 -0
  52. package/src/brokers/directory.ts +11 -0
  53. package/src/brokers/logos.ts +3 -1
  54. package/src/brokers/signed-in/adapter.ts +304 -26
  55. package/src/brokers/signed-in/client.ts +14 -2
  56. package/src/brokers/signed-in/connect.ts +10 -2
  57. package/src/brokers/sync-broker-instance.ts +9 -1
  58. package/src/capabilities/chart-series.ts +22 -6
  59. package/src/cli/bank-section.ts +1 -1
  60. package/src/cli/base-converter.ts +23 -14
  61. package/src/cli/central-bank-events.ts +1 -1
  62. package/src/cli/command-options.ts +59 -4
  63. package/src/cli/commands/api.ts +9 -6
  64. package/src/cli/commands/broker.ts +2 -2
  65. package/src/cli/commands/command-utils.ts +2 -2
  66. package/src/cli/commands/crypto-hints.ts +7 -20
  67. package/src/cli/commands/fred-series.ts +9 -2
  68. package/src/cli/commands/keybindings.ts +25 -2
  69. package/src/cli/commands/market.ts +1177 -278
  70. package/src/cli/commands/news-hints.ts +2 -2
  71. package/src/cli/commands/news-search.ts +59 -6
  72. package/src/cli/commands/options-chain.ts +59 -3
  73. package/src/cli/commands/options-leaps.ts +41 -26
  74. package/src/cli/commands/overview.ts +222 -61
  75. package/src/cli/commands/plugins.ts +9 -9
  76. package/src/cli/commands/remote.ts +13 -10
  77. package/src/cli/commands/search.ts +82 -46
  78. package/src/cli/commands/system.ts +27 -19
  79. package/src/cli/commands/themes.ts +1 -1
  80. package/src/cli/commands/ticker.ts +194 -48
  81. package/src/cli/context.ts +3 -2
  82. package/src/cli/desktop-pane-shot-view.ts +2 -2
  83. package/src/cli/desktop-pane-shot.ts +1 -1
  84. package/src/cli/earnings-calendar.ts +4 -4
  85. package/src/cli/entry.ts +18 -1
  86. package/src/cli/errors.ts +21 -3
  87. package/src/cli/exit-codes.ts +1 -1
  88. package/src/cli/export-source.ts +38 -4
  89. package/src/cli/freshness.ts +2 -8
  90. package/src/cli/fx-forward.ts +130 -0
  91. package/src/cli/fx-pair.ts +10 -9
  92. package/src/cli/glossary.ts +113 -20
  93. package/src/cli/help.ts +19 -13
  94. package/src/cli/history-export.ts +126 -0
  95. package/src/cli/history-rows.ts +226 -50
  96. package/src/cli/index-roots.ts +5 -45
  97. package/src/cli/index.ts +24 -18
  98. package/src/cli/known-gaps.ts +123 -27
  99. package/src/cli/listing-arg.ts +316 -46
  100. package/src/cli/name-entries.ts +30 -18
  101. package/src/cli/native-smoke.ts +2 -0
  102. package/src/cli/not-a-ticker.ts +19 -9
  103. package/src/cli/opentui-libc.ts +5 -0
  104. package/src/cli/options.ts +12 -0
  105. package/src/cli/pane-functions/capabilities.ts +75 -20
  106. package/src/cli/pane-functions/catalog.ts +24 -23
  107. package/src/cli/pane-functions/discovery.ts +1 -1
  108. package/src/cli/pane-functions/dom.ts +10 -7
  109. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  110. package/src/cli/pane-functions/freshness.ts +193 -30
  111. package/src/cli/pane-functions/function-help.ts +76 -30
  112. package/src/cli/pane-functions/headless.ts +59 -12
  113. package/src/cli/pane-functions/index.ts +28 -19
  114. package/src/cli/pane-functions/market-session.ts +15 -5
  115. package/src/cli/pane-functions/options.ts +22 -2
  116. package/src/cli/pane-functions/report-notices.ts +12 -4
  117. package/src/cli/pane-functions/report.ts +10 -6
  118. package/src/cli/pane-functions/resolver.ts +64 -11
  119. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  120. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  121. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  122. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  123. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  124. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  125. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  126. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  127. package/src/cli/pane-functions/shot-options.ts +8 -3
  128. package/src/cli/peso-dollar-rates.ts +79 -0
  129. package/src/cli/quote-answer.ts +45 -4
  130. package/src/cli/report-tables.ts +75 -19
  131. package/src/cli/restore-plugins.ts +42 -15
  132. package/src/cli/result.ts +164 -23
  133. package/src/cli/series-search.ts +5 -5
  134. package/src/cli/statement-filings.ts +19 -0
  135. package/src/cli/suffixed-listing-rows.ts +49 -0
  136. package/src/cli/symbol-args.ts +50 -15
  137. package/src/cli/symbol-cells.ts +120 -0
  138. package/src/cli/symbol-list.ts +198 -68
  139. package/src/cli/symbol-rows.ts +131 -25
  140. package/src/cli/ticker-resolution.ts +108 -11
  141. package/src/cli/treasury-yields.ts +5 -5
  142. package/src/cli/types.ts +2 -0
  143. package/src/cli/uncovered-instrument.ts +3 -3
  144. package/src/cli/unknown-command.ts +6 -6
  145. package/src/components/chart/composite/chart-layout.ts +131 -0
  146. package/src/components/chart/composite/composite-chart.tsx +395 -20
  147. package/src/components/chart/composite/format.ts +27 -0
  148. package/src/components/chart/composite/interactions.ts +7 -2
  149. package/src/components/chart/composite/legend.tsx +75 -3
  150. package/src/components/chart/composite/levels.ts +7 -0
  151. package/src/components/chart/composite/panel-gestures.ts +41 -0
  152. package/src/components/chart/composite/panel-labels.ts +2 -1
  153. package/src/components/chart/composite/panel-series.ts +1 -0
  154. package/src/components/chart/composite/panel-surface.tsx +314 -13
  155. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  156. package/src/components/chart/composite/range-statistics.ts +62 -0
  157. package/src/components/chart/composite/rasterizer.ts +44 -19
  158. package/src/components/chart/composite/scene.ts +20 -4
  159. package/src/components/chart/composite/series-axis-tags.tsx +16 -9
  160. package/src/components/chart/composite/text-renderer.ts +48 -21
  161. package/src/components/chart/composite/toolbar.tsx +52 -5
  162. package/src/components/chart/composite/types.ts +17 -0
  163. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  164. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  165. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  166. package/src/components/chart/composite/value-scale.ts +149 -0
  167. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  168. package/src/components/chart/core/pointer.ts +2 -0
  169. package/src/components/chart-table/index.ts +2 -0
  170. package/src/components/chart-table/read.tsx +74 -0
  171. package/src/components/command-bar/commands/collection-list.ts +41 -19
  172. package/src/components/command-bar/commands/collection.ts +9 -3
  173. package/src/components/command-bar/commands/direct/index.ts +1 -1
  174. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  175. package/src/components/command-bar/pane-templates/items.ts +59 -6
  176. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  177. package/src/components/command-bar/panel/prompt-binding.ts +0 -8
  178. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  179. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  180. package/src/components/command-bar/routes/root/results.ts +18 -4
  181. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  182. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  183. package/src/components/command-bar/routes/root/selection.ts +6 -1
  184. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  185. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  186. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  187. package/src/components/command-bar/selection-runtime.ts +50 -10
  188. package/src/components/command-bar/surface/index.tsx +24 -2
  189. package/src/components/command-bar/view-model.ts +7 -0
  190. package/src/components/command-bar/workflow/alert.ts +1 -1
  191. package/src/components/command-bar/workflow/broker.ts +2 -2
  192. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  193. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  194. package/src/components/command-bar/workflow/fields.ts +8 -2
  195. package/src/components/command-bar/workflow/ops.ts +18 -4
  196. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  197. package/src/components/command-bar/workflow/submit.ts +3 -2
  198. package/src/components/command-bar/workflow/tickers.ts +5 -1
  199. package/src/components/company-logo.tsx +39 -0
  200. package/src/components/data-table/sections.ts +4 -2
  201. package/src/components/form-modal/confirm.tsx +2 -1
  202. package/src/components/form-modal/request.ts +5 -0
  203. package/src/components/form-modal/routes.ts +4 -1
  204. package/src/components/index.ts +12 -6
  205. package/src/components/layout/header.tsx +33 -46
  206. package/src/components/layout/market-summary.ts +9 -6
  207. package/src/components/layout/pane/capture-status.ts +1 -1
  208. package/src/components/layout/pane/footer/index.tsx +1 -0
  209. package/src/components/layout/pane/footer/model.ts +38 -5
  210. package/src/components/layout/shell/chrome.ts +19 -6
  211. package/src/components/layout/shell/index.tsx +2 -1
  212. package/src/components/layout/shell/pane/layers.tsx +19 -1
  213. package/src/components/layout/status-bar.tsx +2 -2
  214. package/src/components/market-board/index.tsx +11 -3
  215. package/src/components/onboarding/onboarding-frame.tsx +1 -1
  216. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  217. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  218. package/src/components/onboarding/portfolio-step/positions-panel.tsx +2 -2
  219. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  220. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  221. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  222. package/src/components/pane-settings-dialog/value.ts +8 -1
  223. package/src/components/pane-settings-dialog.tsx +44 -13
  224. package/src/components/sign-in-code-panel.tsx +27 -19
  225. package/src/components/ui/column-grid.tsx +48 -4
  226. package/src/components/ui/country-flag-art.tsx +180 -0
  227. package/src/components/ui/country-flag.tsx +118 -12
  228. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  229. package/src/components/ui/data-table/opentui/model.ts +109 -2
  230. package/src/components/ui/data-table/types.ts +1 -1
  231. package/src/components/ui/display.tsx +10 -2
  232. package/src/components/ui/index.ts +3 -1
  233. package/src/components/ui/logo-mark.tsx +11 -2
  234. package/src/components/ui/query-bar.tsx +1 -1
  235. package/src/components/ui/row-notes.ts +79 -0
  236. package/src/core/state/app/layout.ts +6 -4
  237. package/src/core/state/app/state.ts +9 -0
  238. package/src/core/state/app/types.ts +3 -0
  239. package/src/data/cached-query.ts +8 -1
  240. package/src/data/config/chart-settings.ts +3 -3
  241. package/src/data/config/home.ts +10 -2
  242. package/src/data/config/layout.ts +4 -1
  243. package/src/data/config/store/node.ts +4 -0
  244. package/src/data/config/store/normalize.ts +13 -3
  245. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  246. package/src/data/json-storage.ts +2 -0
  247. package/src/data/saved-copies.ts +123 -0
  248. package/src/docs/snapshot.json +422 -112
  249. package/src/i18n/es.ts +30 -13
  250. package/src/i18n/ja.ts +30 -13
  251. package/src/i18n/ko.ts +30 -13
  252. package/src/i18n/zh-cn.ts +30 -13
  253. package/src/i18n/zh-tw.ts +30 -13
  254. package/src/layout/desks.ts +1 -1
  255. package/src/layout/launch-layout.ts +1 -1
  256. package/src/layout/pane-manager/floating-actions.ts +5 -3
  257. package/src/layout/pane-manager/floating.ts +43 -1
  258. package/src/layout/pane-manager/index.ts +2 -0
  259. package/src/layout/selected-ticker.ts +74 -0
  260. package/src/market-data/coordinator/financials.ts +10 -2
  261. package/src/market-data/coordinator/index.ts +3 -1
  262. package/src/market-data/coordinator/quotes.ts +4 -2
  263. package/src/market-data/depositary-pair.ts +251 -0
  264. package/src/market-data/futures-board.ts +1 -1
  265. package/src/market-data/futures-contract.ts +124 -40
  266. package/src/market-data/fx-closes.ts +17 -2
  267. package/src/market-data/hooks.tsx +19 -11
  268. package/src/market-data/market/change-basis.ts +81 -11
  269. package/src/market-data/market/dated-previous-close.ts +203 -0
  270. package/src/market-data/market/freshness.ts +34 -5
  271. package/src/market-data/market/futures-week.ts +68 -0
  272. package/src/market-data/market/period-return.ts +163 -0
  273. package/src/market-data/market/status.ts +16 -4
  274. package/src/market-data/market/trading-sessions.ts +13 -0
  275. package/src/market-data/market/year-to-date.ts +8 -13
  276. package/src/market-data/options-alternatives.ts +60 -0
  277. package/src/market-data/performance.ts +20 -14
  278. package/src/market-data/perpetual-premium.ts +32 -0
  279. package/src/market-data/published-apac-sessions.ts +2 -1
  280. package/src/market-data/published-futures-sessions.ts +69 -0
  281. package/src/market-data/quotes/contributions.ts +25 -3
  282. package/src/market-data/quotes/freshness.ts +42 -0
  283. package/src/market-data/quotes/intraday-bar.ts +37 -0
  284. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  285. package/src/market-data/quotes/resolution.ts +7 -2
  286. package/src/market-data/selectors.ts +3 -0
  287. package/src/market-data/tax-equivalent.ts +1 -1
  288. package/src/market-data/ticker-price-returns.ts +3 -1
  289. package/src/news/aggregator.ts +5 -1
  290. package/src/news/news-model.ts +4 -0
  291. package/src/news/types.ts +11 -0
  292. package/src/notifications/app-notifier.ts +1 -1
  293. package/src/notifications/notification-log.ts +6 -4
  294. package/src/plugins/auto-update.ts +2 -2
  295. package/src/plugins/builtin/account-management/index.tsx +1 -0
  296. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  297. package/src/plugins/builtin/alerts/alert-engine.ts +34 -20
  298. package/src/plugins/builtin/alerts/calendar-events.ts +429 -0
  299. package/src/plugins/builtin/alerts/cli.ts +533 -85
  300. package/src/plugins/builtin/alerts/command.ts +12 -10
  301. package/src/plugins/builtin/alerts/constants.ts +1 -1
  302. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  303. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  304. package/src/plugins/builtin/alerts/events.ts +107 -5
  305. package/src/plugins/builtin/alerts/fired-log.ts +119 -0
  306. package/src/plugins/builtin/alerts/format.ts +10 -3
  307. package/src/plugins/builtin/alerts/headless.ts +107 -41
  308. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  309. package/src/plugins/builtin/alerts/history-rows.ts +92 -0
  310. package/src/plugins/builtin/alerts/history.ts +2 -0
  311. package/src/plugins/builtin/alerts/index.tsx +107 -30
  312. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  313. package/src/plugins/builtin/alerts/levels.ts +3 -3
  314. package/src/plugins/builtin/alerts/live.ts +3 -3
  315. package/src/plugins/builtin/alerts/metric-command.ts +61 -0
  316. package/src/plugins/builtin/alerts/metric-data.ts +70 -0
  317. package/src/plugins/builtin/alerts/metric-model.ts +175 -0
  318. package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
  319. package/src/plugins/builtin/alerts/pane.tsx +130 -49
  320. package/src/plugins/builtin/alerts/price.ts +35 -0
  321. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  322. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  323. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  324. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  325. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  326. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  327. package/src/plugins/builtin/alerts/storage.ts +38 -12
  328. package/src/plugins/builtin/alerts/targets.ts +12 -3
  329. package/src/plugins/builtin/alerts/types.ts +3 -0
  330. package/src/plugins/builtin/analytics/index.tsx +8 -2
  331. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  332. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  333. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  334. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  335. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  336. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  337. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  338. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  339. package/src/plugins/builtin/attention/pane.tsx +6 -2
  340. package/src/plugins/builtin/awards/headless.ts +7 -3
  341. package/src/plugins/builtin/awards/model.ts +18 -0
  342. package/src/plugins/builtin/awards/pane.tsx +6 -3
  343. package/src/plugins/builtin/backtest/headless.ts +13 -8
  344. package/src/plugins/builtin/backtest/pane.tsx +9 -4
  345. package/src/plugins/builtin/backtest/presets.ts +29 -3
  346. package/src/plugins/builtin/backtest/rules.ts +41 -5
  347. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  348. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  349. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  350. package/src/plugins/builtin/broker-manager/index.tsx +24 -14
  351. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  352. package/src/plugins/builtin/broker-manager/model.ts +18 -3
  353. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  354. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  355. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  356. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  357. package/src/plugins/builtin/broker-trading/controller.ts +66 -24
  358. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  359. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  360. package/src/plugins/builtin/broker-trading/index.tsx +19 -1
  361. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  362. package/src/plugins/builtin/broker-trading/order-feed.ts +83 -10
  363. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  364. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  365. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  366. package/src/plugins/builtin/broker-trading/pane.tsx +111 -24
  367. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  368. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  369. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  370. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  371. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  372. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  373. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  374. package/src/plugins/builtin/builtin-plugin-meta.ts +2 -2
  375. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  376. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  377. package/src/plugins/builtin/catalysts/model.ts +51 -5
  378. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  379. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  380. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  381. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  382. package/src/plugins/builtin/changelog/index.tsx +1 -0
  383. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +4 -1
  384. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +3 -2
  385. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  386. package/src/plugins/builtin/chart-composer/cli-options.ts +7 -10
  387. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -3
  388. package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -0
  389. package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
  390. package/src/plugins/builtin/chart-composer/editor.tsx +9 -4
  391. package/src/plugins/builtin/chart-composer/formula.ts +71 -18
  392. package/src/plugins/builtin/chart-composer/headless-schema.ts +42 -29
  393. package/src/plugins/builtin/chart-composer/headless.ts +266 -37
  394. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  395. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  396. package/src/plugins/builtin/chart-composer/pane.tsx +144 -30
  397. package/src/plugins/builtin/chart-composer/presets.ts +50 -15
  398. package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
  399. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  400. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  401. package/src/plugins/builtin/chart-composer/session-history.ts +31 -28
  402. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  403. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  404. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +44 -31
  405. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  406. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  407. package/src/plugins/builtin/chat/content/command-suggestions.ts +92 -0
  408. package/src/plugins/builtin/chat/content/composer.tsx +13 -6
  409. package/src/plugins/builtin/chat/content/footer.tsx +6 -3
  410. package/src/plugins/builtin/chat/content/index.tsx +51 -22
  411. package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
  412. package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
  413. package/src/plugins/builtin/chat/index.tsx +23 -0
  414. package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
  415. package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
  416. package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
  417. package/src/plugins/builtin/chat/pane-links/commands.ts +265 -0
  418. package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
  419. package/src/plugins/builtin/chat/pane-links/open.ts +9 -2
  420. package/src/plugins/builtin/chat/people.ts +1 -1
  421. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
  422. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  423. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  424. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  425. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  426. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  427. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  428. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  429. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  430. package/src/plugins/builtin/cloud/plugin.tsx +1 -1
  431. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  432. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  433. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  434. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  435. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  436. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  437. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  438. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  439. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  440. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  441. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  442. package/src/plugins/builtin/company-attention/client.ts +117 -1
  443. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  444. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  445. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  446. package/src/plugins/builtin/company-attention/model.ts +33 -7
  447. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  448. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  449. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  450. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  451. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  452. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  453. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  454. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  455. package/src/plugins/builtin/composite-plugins.ts +2 -1
  456. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  457. package/src/plugins/builtin/connections/index.ts +1 -0
  458. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  459. package/src/plugins/builtin/correlation/headless.ts +5 -3
  460. package/src/plugins/builtin/cot/headless.ts +28 -6
  461. package/src/plugins/builtin/cot/model.ts +12 -0
  462. package/src/plugins/builtin/cot/pane.tsx +3 -2
  463. package/src/plugins/builtin/cpi/headless.ts +5 -1
  464. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  465. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  466. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  467. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  468. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  469. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  470. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  471. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  472. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  473. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  474. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  475. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  476. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  477. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  478. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  479. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  480. package/src/plugins/builtin/debug/index.tsx +1 -0
  481. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  482. package/src/plugins/builtin/docs/index.tsx +1 -1
  483. package/src/plugins/builtin/docs/pane.tsx +2 -2
  484. package/src/plugins/builtin/docs/targets.ts +1 -1
  485. package/src/plugins/builtin/doe/client.ts +5 -1
  486. package/src/plugins/builtin/doe/headless.ts +12 -6
  487. package/src/plugins/builtin/doe/model.ts +43 -6
  488. package/src/plugins/builtin/doe/pane.tsx +18 -11
  489. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  490. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  491. package/src/plugins/builtin/earnings/board.tsx +253 -50
  492. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  493. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  494. package/src/plugins/builtin/earnings/client.ts +4 -3
  495. package/src/plugins/builtin/earnings/headless.ts +53 -15
  496. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  497. package/src/plugins/builtin/earnings/index.tsx +15 -22
  498. package/src/plugins/builtin/earnings/model.ts +17 -12
  499. package/src/plugins/builtin/earnings/scope.ts +89 -0
  500. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  501. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  502. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  503. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  504. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  505. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  506. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  507. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  508. package/src/plugins/builtin/econ/calendar-model.ts +144 -27
  509. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  510. package/src/plugins/builtin/econ/figures.ts +72 -0
  511. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  512. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  513. package/src/plugins/builtin/econ/index.tsx +144 -27
  514. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  515. package/src/plugins/builtin/econ/types.ts +34 -1
  516. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  517. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  518. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  519. package/src/plugins/builtin/econ-statistics/headless.ts +87 -28
  520. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  521. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  522. package/src/plugins/builtin/econ-statistics/stats.ts +104 -0
  523. package/src/plugins/builtin/econ-statistics/view.ts +19 -1
  524. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  525. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  526. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  527. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  528. package/src/plugins/builtin/equity-screener/pane.tsx +47 -12
  529. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  530. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  531. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  532. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  533. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  534. package/src/plugins/builtin/exposure/charts.tsx +2 -2
  535. package/src/plugins/builtin/exposure/headless.ts +51 -6
  536. package/src/plugins/builtin/exposure/index.tsx +28 -2
  537. package/src/plugins/builtin/exposure/model.ts +20 -1
  538. package/src/plugins/builtin/exposure/pane.tsx +10 -5
  539. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  540. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  541. package/src/plugins/builtin/futures/index.tsx +1 -0
  542. package/src/plugins/builtin/futures/model.ts +12 -10
  543. package/src/plugins/builtin/futures/returns.ts +8 -36
  544. package/src/plugins/builtin/futures/table.tsx +3 -3
  545. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  546. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  547. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  548. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  549. package/src/plugins/builtin/fx-matrix/client.ts +20 -8
  550. package/src/plugins/builtin/fx-matrix/headless.ts +37 -16
  551. package/src/plugins/builtin/fx-matrix/index.tsx +25 -13
  552. package/src/plugins/builtin/fx-matrix/live-legs.ts +34 -0
  553. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  554. package/src/plugins/builtin/gpu/headless.ts +9 -4
  555. package/src/plugins/builtin/help/index.tsx +13 -3
  556. package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
  557. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  558. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  559. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  560. package/src/plugins/builtin/holders/client.ts +13 -1
  561. package/src/plugins/builtin/holders/format.ts +28 -17
  562. package/src/plugins/builtin/holders/headless.ts +46 -7
  563. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  564. package/src/plugins/builtin/holders/pane.tsx +79 -15
  565. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  566. package/src/plugins/builtin/holders/table-model.ts +2 -1
  567. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  568. package/src/plugins/builtin/insider/headless.ts +1 -1
  569. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  570. package/src/plugins/builtin/insider/signals.tsx +1 -1
  571. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  572. package/src/plugins/builtin/iv-history/client.ts +20 -0
  573. package/src/plugins/builtin/iv-history/headless.ts +7 -4
  574. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  575. package/src/plugins/builtin/iv-history/model.ts +13 -4
  576. package/src/plugins/builtin/iv-history/series.ts +3 -1
  577. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  578. package/src/plugins/builtin/jobs/model.ts +4 -15
  579. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  580. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  581. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  582. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  583. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  584. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  585. package/src/plugins/builtin/macro-day/model.ts +29 -8
  586. package/src/plugins/builtin/macro-day/pane.tsx +51 -13
  587. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  588. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  589. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  590. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  591. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  592. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  593. package/src/plugins/builtin/market-movers/client.ts +33 -19
  594. package/src/plugins/builtin/market-movers/footer.ts +2 -2
  595. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  596. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  597. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  598. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  599. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  600. package/src/plugins/builtin/market-movers/table.ts +4 -1
  601. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  602. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  603. package/src/plugins/builtin/members/breadth-pane.tsx +81 -0
  604. package/src/plugins/builtin/members/client.ts +19 -4
  605. package/src/plugins/builtin/members/headless.ts +24 -10
  606. package/src/plugins/builtin/members/index.tsx +9 -9
  607. package/src/plugins/builtin/members/model.ts +23 -4
  608. package/src/plugins/builtin/members/pane.tsx +31 -14
  609. package/src/plugins/builtin/mna/client.ts +1 -0
  610. package/src/plugins/builtin/mna/detail.tsx +20 -32
  611. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  612. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  613. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  614. package/src/plugins/builtin/mna/headless.ts +6 -13
  615. package/src/plugins/builtin/mna/model.ts +93 -15
  616. package/src/plugins/builtin/mna/pane.tsx +5 -4
  617. package/src/plugins/builtin/news/headless.ts +12 -6
  618. package/src/plugins/builtin/news/index.tsx +10 -1
  619. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  620. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  621. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  622. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  623. package/src/plugins/builtin/notes/cli.ts +49 -14
  624. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  625. package/src/plugins/builtin/options/analytics.ts +26 -2
  626. package/src/plugins/builtin/options/carry.ts +2 -2
  627. package/src/plugins/builtin/options/index.tsx +1 -1
  628. package/src/plugins/builtin/options/model-spot.ts +5 -2
  629. package/src/plugins/builtin/options/strike-window.ts +2 -1
  630. package/src/plugins/builtin/options/table.ts +1 -7
  631. package/src/plugins/builtin/options/view.tsx +30 -13
  632. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  633. package/src/plugins/builtin/options-positioning/client.ts +19 -0
  634. package/src/plugins/builtin/options-positioning/headless.ts +54 -14
  635. package/src/plugins/builtin/options-positioning/index.tsx +3 -3
  636. package/src/plugins/builtin/options-positioning/model.ts +47 -8
  637. package/src/plugins/builtin/options-positioning/pane.tsx +68 -38
  638. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  639. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  640. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  641. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  642. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  643. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  644. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  645. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  646. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  647. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  648. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  649. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  650. package/src/plugins/builtin/perps/freshness.ts +14 -9
  651. package/src/plugins/builtin/perps/headless.ts +3 -1
  652. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  653. package/src/plugins/builtin/perps/live-rows.ts +168 -0
  654. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  655. package/src/plugins/builtin/perps/pane.tsx +49 -26
  656. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  657. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  658. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  659. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  660. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  661. package/src/plugins/builtin/portfolio-list/cli/render.ts +54 -22
  662. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  663. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  664. package/src/plugins/builtin/portfolio-list/headless.ts +7 -4
  665. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  666. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  667. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  668. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  669. package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
  670. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  671. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  672. package/src/plugins/builtin/power/client.ts +4 -1
  673. package/src/plugins/builtin/power/evidence.ts +22 -7
  674. package/src/plugins/builtin/power/gas.tsx +5 -1
  675. package/src/plugins/builtin/power/pane.tsx +8 -1
  676. package/src/plugins/builtin/power/prices.tsx +10 -3
  677. package/src/plugins/builtin/rate-path/pane.tsx +2 -2
  678. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  679. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  680. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  681. package/src/plugins/builtin/research/event-model.ts +3 -1
  682. package/src/plugins/builtin/research/event-sources.ts +12 -4
  683. package/src/plugins/builtin/research/index.tsx +2 -1
  684. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  685. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  686. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  687. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  688. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  689. package/src/plugins/builtin/research/relative-valuation-pane.tsx +80 -13
  690. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  691. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  692. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  693. package/src/plugins/builtin/scanner/feed.ts +2 -2
  694. package/src/plugins/builtin/scanner/index.ts +24 -1
  695. package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
  696. package/src/plugins/builtin/scanner/live-feed.ts +168 -0
  697. package/src/plugins/builtin/scanner/live-headless.ts +114 -0
  698. package/src/plugins/builtin/scanner/live-model.ts +351 -0
  699. package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
  700. package/src/plugins/builtin/scanner/live-track.ts +186 -0
  701. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  702. package/src/plugins/builtin/sec/forms.ts +13 -0
  703. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  704. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  705. package/src/plugins/builtin/sec/headless.ts +85 -8
  706. package/src/plugins/builtin/sec/index.tsx +58 -12
  707. package/src/plugins/builtin/sectors/client.ts +2 -1
  708. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  709. package/src/plugins/builtin/series-inventory.ts +3 -0
  710. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  711. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  712. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  713. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  714. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  715. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  716. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  717. package/src/plugins/builtin/shared/macro-releases.ts +65 -0
  718. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  719. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  720. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  721. package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
  722. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  723. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  724. package/src/plugins/builtin/shared/use-quote-board.ts +8 -2
  725. package/src/plugins/builtin/shared/volatility/pricing.ts +7 -1
  726. package/src/plugins/builtin/short-interest/client.ts +2 -0
  727. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  728. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  729. package/src/plugins/builtin/short-interest/model.ts +70 -19
  730. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  731. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  732. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  733. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  734. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  735. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  736. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  737. package/src/plugins/builtin/short-interest/types.ts +9 -0
  738. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  739. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  740. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  741. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  742. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  743. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  744. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  745. package/src/plugins/builtin/themes/headless.ts +11 -6
  746. package/src/plugins/builtin/themes/model.ts +15 -5
  747. package/src/plugins/builtin/themes/pane.tsx +27 -8
  748. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  749. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  750. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  751. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  752. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  753. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  754. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  755. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  756. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  757. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  758. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  759. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  760. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  761. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  762. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  763. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  764. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  765. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  766. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  767. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  768. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  769. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  770. package/src/plugins/builtin/ticker-detail/quote-footer.ts +14 -4
  771. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  772. package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
  773. package/src/plugins/builtin/vol-surface/client.ts +7 -4
  774. package/src/plugins/builtin/vol-surface/headless.ts +71 -13
  775. package/src/plugins/builtin/vol-surface/index.tsx +2 -2
  776. package/src/plugins/builtin/vol-surface/model.ts +26 -9
  777. package/src/plugins/builtin/vol-surface/pane.tsx +44 -7
  778. package/src/plugins/builtin/vol-surface/tables.ts +31 -3
  779. package/src/plugins/builtin/volatility/dvol.ts +46 -0
  780. package/src/plugins/builtin/volatility/model.ts +5 -10
  781. package/src/plugins/builtin/volatility/pane.tsx +2 -2
  782. package/src/plugins/builtin/volatility/series.ts +26 -0
  783. package/src/plugins/builtin/world-indices/footer.ts +1 -1
  784. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  785. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  786. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  787. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  788. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  789. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  790. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  791. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  792. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  793. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  794. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  795. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  796. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  797. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  798. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  799. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  800. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  801. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  802. package/src/plugins/bundle.ts +1 -1
  803. package/src/plugins/catalog-browser.ts +15 -9
  804. package/src/plugins/compat.ts +3 -3
  805. package/src/plugins/dependencies.ts +75 -14
  806. package/src/plugins/extracted-plugins.ts +132 -34
  807. package/src/plugins/host-link.ts +149 -34
  808. package/src/plugins/installer.ts +35 -10
  809. package/src/plugins/loader.ts +206 -38
  810. package/src/plugins/manager-node.ts +2 -2
  811. package/src/plugins/marketplace/deactivation.ts +22 -0
  812. package/src/plugins/marketplace/model.ts +2 -2
  813. package/src/plugins/marketplace/packs.ts +1 -1
  814. package/src/plugins/ownership.ts +1 -1
  815. package/src/plugins/peer-retry.ts +155 -0
  816. package/src/plugins/registry/contributions.ts +3 -1
  817. package/src/plugins/registry/index.ts +4 -3
  818. package/src/plugins/registry/plugin-state.ts +3 -0
  819. package/src/plugins/seed-notice.ts +20 -0
  820. package/src/plugins/shortcut-argument.ts +39 -0
  821. package/src/portfolio/allocation.ts +1 -1
  822. package/src/portfolio/collection-name.ts +31 -0
  823. package/src/portfolio/column-values.ts +15 -13
  824. package/src/portfolio/cost-fx.ts +296 -19
  825. package/src/portfolio/manual-lots.ts +75 -0
  826. package/src/portfolio/mutations.ts +60 -22
  827. package/src/portfolio/suffixed-listings.ts +209 -0
  828. package/src/portfolio/totals-currency.ts +24 -0
  829. package/src/public/__snapshots__/public-api.test.ts.snap +15 -0
  830. package/src/public/time-series.ts +11 -8
  831. package/src/remote/schema.ts +1 -1
  832. package/src/renderers/browser/app-services.ts +1 -7
  833. package/src/renderers/browser/config-host.ts +5 -55
  834. package/src/renderers/browser/main.tsx +30 -60
  835. package/src/renderers/dom/boot-frame-page.ts +187 -0
  836. package/src/renderers/dom/boot-frame.ts +237 -0
  837. package/src/renderers/dom/build-assets.ts +46 -8
  838. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  839. package/src/renderers/dom/host/ascii-text.ts +16 -2
  840. package/src/renderers/dom/host/box.tsx +43 -2
  841. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  842. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  843. package/src/renderers/dom/host/image-surface.tsx +49 -0
  844. package/src/renderers/dom/host/media-surface.tsx +24 -18
  845. package/src/renderers/dom/host/mouse.ts +30 -0
  846. package/src/renderers/dom/host/size-observer.ts +1 -1
  847. package/src/renderers/dom/host/style.ts +1 -1
  848. package/src/renderers/dom/styles.css +76 -0
  849. package/src/renderers/dom/test-utils.tsx +2 -1
  850. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  851. package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
  852. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  853. package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
  854. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  855. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  856. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  857. package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
  858. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
  859. package/src/renderers/electrobun/bun/desktop/update.ts +70 -3
  860. package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
  861. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  862. package/src/renderers/electrobun/bun/index.ts +36 -2
  863. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  864. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  865. package/src/renderers/electrobun/shared/app-name.ts +17 -0
  866. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  867. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  868. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  869. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  870. package/src/renderers/electrobun/view/config-host.ts +3 -0
  871. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
  872. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  873. package/src/renderers/electrobun/view/main.tsx +30 -4
  874. package/src/renderers/electrobun/view/news-source.ts +5 -5
  875. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  876. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  877. package/src/renderers/opentui/browser-open.ts +88 -0
  878. package/src/renderers/opentui/host.tsx +5 -14
  879. package/src/renderers/opentui/image/loader.ts +3 -2
  880. package/src/renderers/opentui/native-smoke.ts +10 -1
  881. package/src/renderers/opentui/pane-image/index.ts +2 -1
  882. package/src/renderers/opentui/render-lib.ts +253 -0
  883. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  884. package/src/renderers/opentui/start.tsx +1 -1
  885. package/src/renderers/opentui/toast-host.tsx +71 -43
  886. package/src/renderers/share/layout-view.tsx +2 -2
  887. package/src/renderers/share/main.tsx +4 -4
  888. package/src/renderers/share/view.tsx +1 -1
  889. package/src/series/resolve.ts +22 -6
  890. package/src/series/standalone.ts +30 -2
  891. package/src/series/types.ts +8 -1
  892. package/src/shares/api.ts +4 -1
  893. package/src/shares/pane.ts +1 -1
  894. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  895. package/src/sources/gloomberb-cloud/index.ts +32 -16
  896. package/src/sources/gloomberb-cloud/news.ts +39 -0
  897. package/src/sources/gloomberb-cloud/normalizers.ts +16 -1
  898. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  899. package/src/sources/listing-symbols.ts +37 -0
  900. package/src/sources/provider-errors.ts +16 -2
  901. package/src/sources/provider-router/batches.ts +10 -2
  902. package/src/sources/provider-router/financial-routes.ts +21 -3
  903. package/src/sources/provider-router/financials.ts +15 -2
  904. package/src/sources/provider-router/history.ts +58 -15
  905. package/src/sources/provider-router/index.ts +146 -10
  906. package/src/sources/provider-router/primary.ts +1 -1
  907. package/src/sources/provider-router/search.ts +13 -2
  908. package/src/state/app/bootstrap.ts +23 -0
  909. package/src/state/app/context/index.tsx +3 -0
  910. package/src/state/hooks/inline-tickers.ts +30 -5
  911. package/src/sync/auth-transition.ts +19 -9
  912. package/src/sync/baseline.ts +10 -4
  913. package/src/sync/controller.ts +67 -17
  914. package/src/sync/core-contributors.ts +46 -14
  915. package/src/sync/react.ts +4 -1
  916. package/src/sync/types.ts +3 -0
  917. package/src/team/collections-sync.ts +2 -1
  918. package/src/team/collections.ts +178 -17
  919. package/src/telemetry/crash-reports.ts +17 -4
  920. package/src/telemetry/usage-counts.ts +0 -18
  921. package/src/test-support/builtin-panes.ts +1 -1
  922. package/src/theme/colors.ts +11 -30
  923. package/src/theme/ui-tokens.ts +37 -1
  924. package/src/tickers/company-name-listing.ts +210 -33
  925. package/src/tickers/company-name.ts +59 -0
  926. package/src/tickers/index-roots.ts +47 -0
  927. package/src/tickers/instrument-label.ts +5 -1
  928. package/src/tickers/listing-venues.ts +23 -0
  929. package/src/tickers/metadata.ts +10 -0
  930. package/src/tickers/perpetual-listing.ts +5 -2
  931. package/src/tickers/search/bare-symbol.ts +36 -0
  932. package/src/tickers/search/home-listing.ts +75 -0
  933. package/src/tickers/search/index.ts +111 -33
  934. package/src/tickers/search/ranking.ts +64 -5
  935. package/src/tickers/search/types.ts +5 -0
  936. package/src/tickers/search/upsert.ts +29 -0
  937. package/src/tickers/terminal-codes.ts +416 -40
  938. package/src/time-series/bar-aggregation.ts +243 -0
  939. package/src/time-series/base-series.ts +315 -0
  940. package/src/time-series/chart-bounds.ts +349 -0
  941. package/src/time-series/chart-seed.ts +142 -0
  942. package/src/time-series/daily-valuation.ts +62 -0
  943. package/src/time-series/economic.ts +5 -0
  944. package/src/time-series/field-catalog.ts +1 -3
  945. package/src/time-series/forward-valuation.ts +32 -0
  946. package/src/time-series/fundamentals.ts +173 -10
  947. package/src/time-series/history-acquisition.ts +499 -0
  948. package/src/time-series/hooks.ts +1 -0
  949. package/src/time-series/leverage.ts +100 -0
  950. package/src/time-series/market-resolution.ts +4 -2
  951. package/src/time-series/market.ts +2 -1
  952. package/src/time-series/price-comparison.ts +175 -30
  953. package/src/time-series/price-units.ts +72 -2
  954. package/src/time-series/range.ts +9 -1
  955. package/src/time-series/resolution.ts +174 -16
  956. package/src/time-series/resolve-context.ts +161 -0
  957. package/src/time-series/resolve.ts +185 -1587
  958. package/src/time-series/series-name.ts +38 -0
  959. package/src/time-series/series-presentation.ts +242 -0
  960. package/src/time-series/spec.ts +13 -7
  961. package/src/time-series/studies.ts +377 -82
  962. package/src/time-series/tail-reconcile.ts +121 -0
  963. package/src/time-series/transforms.ts +1 -0
  964. package/src/time-series/types.ts +34 -2
  965. package/src/time-series/use-chart-resolution.ts +4 -5
  966. package/src/time-series/valuation-releases.ts +39 -0
  967. package/src/types/broker.ts +10 -0
  968. package/src/types/config.ts +14 -0
  969. package/src/types/data-provider.ts +23 -1
  970. package/src/types/desktop-window.ts +2 -0
  971. package/src/types/exchange-rate.ts +6 -0
  972. package/src/types/financials.ts +145 -8
  973. package/src/types/headless.ts +117 -9
  974. package/src/types/instrument.ts +6 -0
  975. package/src/types/plugin.ts +66 -9
  976. package/src/types/price-history.ts +2 -0
  977. package/src/types/ticker.ts +13 -0
  978. package/src/types/trading.ts +59 -1
  979. package/src/ui/ascii-font.ts +13 -1
  980. package/src/ui/host.tsx +6 -1
  981. package/src/updater/command-names.ts +180 -0
  982. package/src/updater/index.ts +10 -5
  983. package/src/utils/calendar-date.ts +32 -15
  984. package/src/utils/cash-runway.ts +241 -0
  985. package/src/utils/central-banks.ts +42 -0
  986. package/src/utils/cli-output.ts +259 -80
  987. package/src/utils/contract-month.ts +16 -0
  988. package/src/utils/crypto-pair.ts +61 -3
  989. package/src/utils/currency-units.ts +29 -0
  990. package/src/utils/datetime-format.ts +10 -0
  991. package/src/utils/debug-log.ts +1 -1
  992. package/src/utils/decimal-comma.ts +39 -6
  993. package/src/utils/exchange-announcements.ts +71 -0
  994. package/src/utils/exchange-rate-snapshot.ts +10 -0
  995. package/src/utils/financial-statements.ts +89 -5
  996. package/src/utils/format.ts +34 -16
  997. package/src/utils/fundamentals.ts +150 -34
  998. package/src/utils/fx-market-hours.ts +10 -1
  999. package/src/utils/latest-financial-period.ts +8 -0
  1000. package/src/utils/linux-libc.ts +54 -0
  1001. package/src/utils/market-capitalization.ts +111 -15
  1002. package/src/utils/max-drawdown.ts +64 -0
  1003. package/src/utils/network-failure.ts +86 -0
  1004. package/src/utils/option-expiry.ts +186 -7
  1005. package/src/utils/options.ts +10 -0
  1006. package/src/utils/plugin-proxy-hosts.json +1 -0
  1007. package/src/utils/price-earnings.ts +11 -5
  1008. package/src/utils/price-history.ts +23 -8
  1009. package/src/utils/price-window.ts +131 -0
  1010. package/src/utils/release-date.ts +47 -0
  1011. package/src/utils/sec.ts +3 -0
  1012. package/src/utils/throttled-fetch.ts +11 -4
  1013. package/src/utils/trailing-eps.ts +67 -0
  1014. package/src/utils/typed-text.ts +21 -0
  1015. package/src/utils/utc-time.ts +24 -1
  1016. package/src/version.ts +6 -0
  1017. package/src/cli/pane-functions/screenshot.ts +0 -2122
  1018. package/src/renderers/browser/first-screen.ts +0 -193
package/src/cli/result.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { CliGlobalOptions } from "./options";
2
2
  import {
3
+ cliPlainEnabled,
3
4
  cliStyles,
4
5
  cliTerminalWidth,
5
6
  renderStats,
@@ -13,11 +14,14 @@ import {
13
14
  } from "../utils/cli-output";
14
15
  import { serializeCsv } from "../utils/csv";
15
16
  import { formatUtcTime, isEpochMilliseconds, isZonedIsoDateTime } from "../utils/utc-time";
16
- import { formatFreshnessLine, type ReportFreshness } from "./pane-functions/freshness";
17
+ import { formatFreshnessLine, withSavedCopy, type ReportFreshness } from "./pane-functions/freshness";
17
18
  import { withSearchHints, type FredSeriesCheck } from "./not-a-ticker";
18
19
  import { renderReportCsv, renderReportNdjson, withCsvFooter, type CliReportTables } from "./report-tables";
19
20
  import {
21
+ EXPORT_DATING_COLUMNS,
20
22
  EXPORT_IDENTITY_COLUMNS,
23
+ exportDatingCells,
24
+ exportDatingFields,
21
25
  exportIdentityCells,
22
26
  exportIdentityFields,
23
27
  exportSource,
@@ -98,6 +102,11 @@ export interface CliResultRenderOptions<T = unknown, Row = Record<string, unknow
98
102
  * `metadata.rows` in JSON.
99
103
  */
100
104
  dateKey?: string;
105
+ /**
106
+ * The row key that splits the rows into series of their own, each windowed
107
+ * apart: with `symbol`, `--tail 5` keeps every symbol's newest five rows.
108
+ */
109
+ seriesKey?: string;
101
110
  /** How many rows to show when neither `--limit` nor `--tail` is given; every row when absent. */
102
111
  defaultLimit?: number;
103
112
  /**
@@ -114,6 +123,24 @@ export interface CliResultRenderOptions<T = unknown, Row = Record<string, unknow
114
123
  exportIdentity?: ExportIdentity | ((row: Row) => ExportIdentity);
115
124
  /** What CSV says after the source lines as `# note:` lines: what the rows do not show, such as where a series begins. */
116
125
  exportNotes?: readonly string[];
126
+ /**
127
+ * The rows are statistics dated by a period and a release (`econ`, `fred`):
128
+ * CSV and NDJSON rows also end with `period`, `released` and `retrieved`
129
+ * (`EXPORT_DATING_COLUMNS`) after the five fixed columns, from the `period`
130
+ * and `released` of each row's `exportIdentity`, and `as_of` is the release.
131
+ * A column the rows already have by name keeps its own values. Needs a
132
+ * cited source, as the fixed columns do.
133
+ */
134
+ exportDated?: boolean;
135
+ /**
136
+ * Why a row's figures are empty (`Not a ticker: ZZZZQQ.`, `Chg%: no previous
137
+ * close`), for the `status` column CSV writes after the row's own columns and
138
+ * the `status` field of an NDJSON row; empty for a whole row. The column is
139
+ * there whenever this is, with rows or without, so the header never depends
140
+ * on what loaded. A figure that is no number (NaN) is written empty and,
141
+ * without a reason here, named as `<header>: not available`.
142
+ */
143
+ exportStatus?: (row: Row) => string | null | undefined;
117
144
  }
118
145
 
119
146
  interface CliResultJsonEnvelope<T> extends Omit<CliResult<T>, "freshness" | "exportFreshness" | "failure"> {
@@ -149,11 +176,28 @@ function rowWindowOptions(options: CliGlobalOptions, renderOptions: Pick<CliResu
149
176
  function windowed<Row>(
150
177
  rows: readonly Row[],
151
178
  options: CliGlobalOptions,
152
- renderOptions: Pick<CliResultRenderOptions, "dateKey" | "defaultLimit">,
179
+ renderOptions: Pick<CliResultRenderOptions, "dateKey" | "defaultLimit" | "seriesKey">,
153
180
  ): RowWindow<Row> {
154
- const { dateKey } = renderOptions;
181
+ const { dateKey, seriesKey } = renderOptions;
155
182
  const dateOf = dateKey ? (row: Row) => (isPlainObject(row) ? row[dateKey] : undefined) : undefined;
156
- return windowRows(rows, rowWindowOptions(options, renderOptions), dateOf);
183
+ const windowOptions = rowWindowOptions(options, renderOptions);
184
+ if (!seriesKey) return windowRows(rows, windowOptions, dateOf);
185
+ const series = new Map<unknown, Row[]>();
186
+ for (const row of rows) {
187
+ const key = isPlainObject(row) ? row[seriesKey] : undefined;
188
+ const group = series.get(key);
189
+ if (group) group.push(row);
190
+ else series.set(key, [row]);
191
+ }
192
+ const windows = [...series.values()].map((group) => windowRows(group, windowOptions, dateOf));
193
+ const count = windowOptions.tail ?? windowOptions.limit;
194
+ return {
195
+ rows: windows.flatMap((window) => window.rows),
196
+ total: rows.length,
197
+ kept: windows.find((window) => window.kept)?.kept ?? null,
198
+ note: windows.some((window) => window.note)
199
+ ? `showing the oldest ${count} ${count === 1 ? "row" : "rows"} of each ${seriesKey}; --tail ${count} for the latest` : null,
200
+ };
157
201
  }
158
202
 
159
203
  function asRows<T, Row>(data: T, rows?: (data: T) => Row[]): Row[] {
@@ -206,7 +250,7 @@ function formatTextValue(
206
250
  depth = 0,
207
251
  width: number | null = null,
208
252
  ): string {
209
- const missing = context === "record" ? cliStyles.muted("-") : "";
253
+ const missing = context === "record" ? cliPlainEnabled() ? "—" : cliStyles.muted("-") : "";
210
254
  if (value == null || value === "") return missing;
211
255
  // Times print in UTC with the zone named, never in the host's zone; JSON and CSV keep the raw value.
212
256
  if (value instanceof Date) return formatUtcTime(value);
@@ -291,23 +335,80 @@ function serializeColumns<Row>(columns?: CliResultColumn<Row>[]) {
291
335
  }));
292
336
  }
293
337
 
338
+ /** A number a spreadsheet cannot read: NaN or an infinity, which exports write empty, never as the word. */
339
+ function isNonFiniteNumber(value: unknown): boolean {
340
+ return typeof value === "number" && !Number.isFinite(value);
341
+ }
342
+
343
+ /**
344
+ * What a row's status cell says: the command's reason, else the figures
345
+ * written empty for being no number. Empty when nothing is missing.
346
+ */
347
+ function exportStatusText(reason: string | null | undefined, blanked: readonly string[]): string {
348
+ const own = reason?.trim();
349
+ if (own) return own;
350
+ return blanked.length > 0 ? `${blanked.join(", ")}: not available` : "";
351
+ }
352
+
353
+ /** `status`, or `value_status` beside a column of the table's own named Status. */
354
+ function statusHeader(headers: readonly string[]): string {
355
+ return headers.some((header) => header.trim().toLowerCase() === "status") ? "value_status" : "status";
356
+ }
357
+
294
358
  function renderCsv<Row extends Record<string, unknown>>(
295
359
  rows: Row[],
296
360
  columns?: CliResultColumn<Row>[],
297
361
  identity?: (row: Row) => string[],
362
+ status?: (row: Row) => string | null | undefined,
363
+ dating?: (row: Row) => string[],
298
364
  ): string {
299
365
  const resolvedColumns = columns && columns.length > 0
300
366
  ? columns
301
367
  : inferColumns(rows as Record<string, unknown>[]) as CliResultColumn<Row>[];
368
+ const headers = resolvedColumns.map((column) => column.header);
369
+ // A dated export's own `released` column keeps its values; the others close the row.
370
+ const datingAdded = dating
371
+ ? EXPORT_DATING_COLUMNS.flatMap((column, index) => headers.includes(column) ? [] : [index]) : [];
302
372
  return serializeCsv([
303
- [...resolvedColumns.map((column) => column.header), ...identity ? EXPORT_IDENTITY_COLUMNS : []],
304
- ...rows.map((row) => [
305
- ...resolvedColumns.map((column) => (column.value ? column.value(row) : row[column.key])),
306
- ...identity?.(row) ?? [],
307
- ]),
373
+ [
374
+ ...headers,
375
+ ...status ? [statusHeader(headers)] : [],
376
+ ...identity ? EXPORT_IDENTITY_COLUMNS : [],
377
+ ...datingAdded.map((index) => EXPORT_DATING_COLUMNS[index]!),
378
+ ],
379
+ ...rows.map((row) => {
380
+ const values = resolvedColumns.map((column) => (column.value ? column.value(row) : row[column.key]));
381
+ const blanked = resolvedColumns.flatMap((column, index) => isNonFiniteNumber(values[index]) ? [column.header] : []);
382
+ const datingCells = dating?.(row) ?? [];
383
+ return [
384
+ ...values.map((value) => isNonFiniteNumber(value) ? "" : value),
385
+ ...status ? [exportStatusText(status(row), blanked)] : [],
386
+ ...identity?.(row) ?? [],
387
+ ...datingAdded.map((index) => datingCells[index] ?? ""),
388
+ ];
389
+ }),
308
390
  ]);
309
391
  }
310
392
 
393
+ /**
394
+ * The key an NDJSON row says why its figures are empty under: `status`, or
395
+ * `value_status` beside a field of the row's own that the export writes under
396
+ * that name (an order's status), as CSV's header does.
397
+ */
398
+ function ndjsonStatusKey(rows: readonly unknown[], columns?: readonly CliResultColumn<never>[]): string {
399
+ const own = columns && columns.length > 0
400
+ ? columns.some((column) => column.key === "status")
401
+ : rows.some((row) => isPlainObject(row) && "status" in row);
402
+ return own ? "value_status" : "status";
403
+ }
404
+
405
+ /** An NDJSON row: a figure that is no number is null, and the row says why its figures are empty when the command does. */
406
+ function ndjsonRow<Row extends Record<string, unknown>>(row: Row, status: ((row: Row) => string | null | undefined) | undefined, statusKey: string): Record<string, unknown> {
407
+ const blanked = Object.entries(row).flatMap(([key, value]) => isNonFiniteNumber(value) ? [key] : []);
408
+ const own = blanked.length > 0 ? { ...row, ...Object.fromEntries(blanked.map((key) => [key, null])) } : row;
409
+ return status ? { ...own, [statusKey]: exportStatusText(status(row), blanked) || null } : own;
410
+ }
411
+
311
412
  function stringField(row: Record<string, unknown>, key: string): string | null {
312
413
  const value = row?.[key];
313
414
  return typeof value === "string" && value.trim() ? value : null;
@@ -348,10 +449,11 @@ function renderTextTable<Row extends Record<string, unknown>>(
348
449
  ): string {
349
450
  const resolvedColumns = textColumns(rows, columns);
350
451
  const cells = rows.map((row) => resolvedColumns.map((column) => formatTextCell(column, row, "table")));
351
- // A column no row fills is noise in a table; exports keep it.
452
+ // A column no row fills is noise in a table; exports keep it, and so does plain output, whose
453
+ // tables keep one shape from query to query with "—" in the empty cells.
352
454
  const filled = resolvedColumns
353
455
  .map((column, index) => ({ column, index }))
354
- .filter(({ column, index }) => column.width != null || cells.some((row) => row[index] !== ""));
456
+ .filter(({ column, index }) => cliPlainEnabled() || column.width != null || cells.some((row) => row[index] !== ""));
355
457
  const shown = filled.length > 0 ? filled : resolvedColumns.map((column, index) => ({ column, index }));
356
458
  return renderTable(
357
459
  shown.map(({ column }) => ({
@@ -395,9 +497,13 @@ function overflowsTerminal<Row extends Record<string, unknown>>(rows: Row[]): bo
395
497
  return width > terminalWidth;
396
498
  }
397
499
 
398
- /** The closing source, as-of and status line of a text result, for output printed without `printResult`. */
399
- export function cliFreshnessFooter(freshness: ReportFreshness): string {
400
- return cliStyles.muted(wrapToTerminal(formatFreshnessLine(freshness)));
500
+ /**
501
+ * The closing source, as-of and status line of a text result, for output
502
+ * printed without `printResult`; `shown` is the data the line is drawn from,
503
+ * which says whether it came from a saved copy.
504
+ */
505
+ export function cliFreshnessFooter(freshness: ReportFreshness, shown?: unknown): string {
506
+ return cliStyles.muted(wrapToTerminal(formatFreshnessLine(withSavedCopy(freshness, shown))));
401
507
  }
402
508
 
403
509
  export function serializeCliResult<T, Row extends Record<string, unknown> = Record<string, unknown>>(
@@ -405,8 +511,10 @@ export function serializeCliResult<T, Row extends Record<string, unknown> = Reco
405
511
  options: CliGlobalOptions,
406
512
  renderOptions: CliResultRenderOptions<T, Row> = {},
407
513
  ): string {
408
- const { freshness, exportFreshness, failure, ...rest } = result;
409
- const cited = freshness ?? exportFreshness;
514
+ const { freshness: reported, exportFreshness, failure, ...rest } = result;
515
+ // Rows shown from a saved copy, its refresh having failed, say so in place of live or delayed.
516
+ const freshness = reported && withSavedCopy(reported, result.data);
517
+ const cited = freshness ?? (exportFreshness && withSavedCopy(exportFreshness, result.data));
410
518
  if (options.format === "json") {
411
519
  const columns = serializeColumns(renderOptions.columns);
412
520
  const window = Array.isArray(result.data) ? windowed(result.data as unknown[], options, renderOptions) : null;
@@ -443,15 +551,32 @@ function serializeCliRows<T, Row extends Record<string, unknown>>(
443
551
  }
444
552
  const window = windowed(asRows(result.data, renderOptions.rows), options, renderOptions);
445
553
  const rows = window.rows;
554
+ const status = renderOptions.exportStatus;
446
555
  if (options.format === "ndjson") {
447
- return rows.map((row) => JSON.stringify(cited && isPlainObject(row)
448
- ? { ...row, ...exportIdentityFields(cited, rowIdentity(row as Row, renderOptions.exportIdentity)) }
449
- : row)).join("\n");
556
+ const statusKey = ndjsonStatusKey(rows, renderOptions.columns as readonly CliResultColumn<never>[] | undefined);
557
+ return rows.map((row) => {
558
+ if (!isPlainObject(row)) return JSON.stringify(row);
559
+ const fields = ndjsonRow(row as Row, status, statusKey);
560
+ if (!cited) return JSON.stringify(fields);
561
+ const identity = rowIdentity(row as Row, renderOptions.exportIdentity);
562
+ // A dated export's own fields (a row's `released`) keep their values.
563
+ const dating = renderOptions.exportDated
564
+ ? Object.fromEntries(Object.entries(exportDatingFields(cited, identity)).filter(([key]) => !(key in fields))) : {};
565
+ return JSON.stringify({ ...fields, ...exportIdentityFields(cited, identity), ...dating });
566
+ }).join("\n");
450
567
  }
451
568
  if (options.format === "csv") {
452
- if (!cited) return renderCsv(rows as Row[], renderOptions.columns);
453
- const csv = renderCsv(rows as Row[], renderOptions.columns, (row) => exportIdentityCells(cited, rowIdentity(row, renderOptions.exportIdentity)));
454
- return withCsvFooter(csv, [...exportSourceLines(cited), ...(renderOptions.exportNotes ?? []).map((note) => `note: ${note}`)]);
569
+ // The rows a window cut say so after them, as text and JSON do: a script has no other way to know.
570
+ const cutNote = window.note ? [`note: ${window.note}`] : [];
571
+ if (!cited) return withCsvFooter(renderCsv(rows as Row[], renderOptions.columns, undefined, status), cutNote);
572
+ const csv = renderCsv(
573
+ rows as Row[],
574
+ renderOptions.columns,
575
+ (row) => exportIdentityCells(cited, rowIdentity(row, renderOptions.exportIdentity)),
576
+ status,
577
+ renderOptions.exportDated ? (row) => exportDatingCells(cited, rowIdentity(row, renderOptions.exportIdentity)) : undefined,
578
+ );
579
+ return withCsvFooter(csv, [...exportSourceLines(cited), ...cutNote, ...(renderOptions.exportNotes ?? []).map((note) => `note: ${note}`)]);
455
580
  }
456
581
  if (renderOptions.text) {
457
582
  return renderOptions.text(result.data);
@@ -519,6 +644,22 @@ export function printCliResult<T, Row extends Record<string, unknown> = Record<s
519
644
  console.error(`${cliStyles.warning("warning:")} ${hinted(warning)}`);
520
645
  }
521
646
  }
647
+ // CSV says what its rows do not in closing `# note:` lines; NDJSON has no place for one among its rows,
648
+ // so the same notes go to stderr, where the warnings are.
649
+ if (options.format === "ndjson" && !options.quiet) {
650
+ for (const note of exportNdjsonNotes(result, options, renderOptions)) console.error(`note: ${note}`);
651
+ }
652
+ }
653
+
654
+ /** What a `--limit`, or the default a command caps its rows at, left out of a list, then the command's own notes: what CSV closes with as `# note:` lines. */
655
+ function exportNdjsonNotes<T, Row extends Record<string, unknown>>(
656
+ result: CliResult<T>,
657
+ options: CliGlobalOptions,
658
+ renderOptions: CliResultRenderOptions<T, Row>,
659
+ ): string[] {
660
+ if (renderOptions.tables || renderOptions.text) return [];
661
+ const cut = windowed(asRows(result.data, renderOptions.rows), options, renderOptions).note;
662
+ return [...cut ? [cut] : [], ...renderOptions.exportNotes ?? []];
522
663
  }
523
664
 
524
665
  export function serializeCliError(error: CliErrorObject, options: CliGlobalOptions): string {
@@ -27,7 +27,7 @@ function fredSeriesIdOf(expression: string): string | null {
27
27
  return /^FRED:([A-Z0-9]+)$/i.exec(expression)?.[1]?.toUpperCase() ?? null;
28
28
  }
29
29
 
30
- /** The FRED series the plugins' catalog charts, as `gloomberb fred` takes them: DFEDTARU, ECBDFR. */
30
+ /** The FRED series the plugins' catalog charts, as `gloom fred` takes them: DFEDTARU, ECBDFR. */
31
31
  export function catalogFredSeriesIds(plugins: readonly SeriesSource[]): Set<string> {
32
32
  return new Set(plugins.flatMap((plugin) => plugin.series ?? [])
33
33
  .flatMap((definition) => definition.expression ? [fredSeriesIdOf(definition.expression)] : [])
@@ -96,14 +96,14 @@ export function renderSeriesMatches(
96
96
  const shown = matches.slice(0, limit);
97
97
  const count = shown.length < matches.length ? `${shown.length} of ${matches.length}` : String(matches.length);
98
98
  const quoted = `"${query.replace(/"/g, "")}"`;
99
- // A FRED series named by its id is also one `gloomberb fred` prints.
99
+ // A FRED series named by its id is also one `gloom fred` prints.
100
100
  const asked = query.trim().toUpperCase().replace(/^FRED:/, "");
101
101
  const fred = matches.find((match) => match.exact && fredSeriesIdOf(match.expression) === asked);
102
102
  const hint = fred
103
- ? `Print it with gloomberb fred ${asked}; chart it with gloomberb fn G ${fred.expression}.`
103
+ ? `Print it with gloom fred ${asked}; chart it with gloom fn G ${fred.expression}.`
104
104
  : shown.length < matches.length
105
- ? `Chart one with gloomberb fn G <chart>; gloomberb ${rest === "catalog" ? `catalog ${quoted}` : `shot CAT ${quoted}`} lists all ${matches.length}.`
106
- : "Chart one with gloomberb fn G <chart>.";
105
+ ? `Chart one with gloom fn G <chart>; gloom ${rest === "catalog" ? `catalog ${quoted}` : `shot CAT ${quoted}`} lists all ${matches.length}.`
106
+ : "Chart one with gloom fn G <chart>.";
107
107
  return [
108
108
  `${renderSection(`Series for "${query}"`)} ${cliStyles.muted(`(${count})`)}`,
109
109
  renderTable(
@@ -1,6 +1,7 @@
1
1
  import { apiClient } from "../api-client";
2
2
  import type { BankFiguresPayload } from "../api-client/bank-figures";
3
3
  import type { FinancialStatement } from "../types/financials";
4
+ import { fetchOfferingFilings, type OfferingFiling } from "../utils/cash-runway";
4
5
  import { logFailure } from "../utils/log-failure";
5
6
  import { nonUsSecListingVenue } from "../utils/sec";
6
7
 
@@ -42,6 +43,8 @@ export interface StatementReportSources {
42
43
  /** The company's 10-K, 10-Q, 8-K, 20-F and 40-F filings, newest first. */
43
44
  statementFilings(symbol: string): Promise<PeriodicFiling[]>;
44
45
  bankFigures(symbol: string): Promise<BankFiguresPayload>;
46
+ /** The company's latest offering prospectuses (424B5, 424B4), newest first. */
47
+ offeringFilings?(symbol: string): Promise<OfferingFiling[]>;
45
48
  }
46
49
 
47
50
  export const cloudStatementReportSources: StatementReportSources = {
@@ -62,8 +65,24 @@ export const cloudStatementReportSources: StatementReportSources = {
62
65
  });
63
66
  },
64
67
  bankFigures: (symbol) => apiClient.getCloudBankFigures(symbol),
68
+ offeringFilings: (symbol) => fetchOfferingFilings(apiClient, symbol),
65
69
  };
66
70
 
71
+ /**
72
+ * A US listing's latest offering prospectuses, for the note that its cash
73
+ * predates one; nothing (and no request) for any other listing, or when
74
+ * `wanted` is false. A failed read leaves the note out.
75
+ */
76
+ export async function loadOfferingFilings(
77
+ sources: StatementReportSources | undefined,
78
+ listing: { symbol: string; exchange?: string },
79
+ wanted: boolean,
80
+ ): Promise<OfferingFiling[]> {
81
+ if (!wanted || !sources?.offeringFilings || nonUsSecListingVenue(listing.symbol, listing.exchange)) return [];
82
+ return sources.offeringFilings(listing.symbol)
83
+ .catch(logFailure("cli.statement-filings", "Reading the offering filings failed", [] as OfferingFiling[]));
84
+ }
85
+
67
86
  /** The filing a statement row's period was read from: its form when the filing list names it, and its filed date. */
68
87
  export interface StatementFiling {
69
88
  /** 10-Q, 10-K, 20-F or 40-F; null when the filing is not among those listed. */
@@ -0,0 +1,49 @@
1
+ import { saveConfig } from "../data/config/store";
2
+ import { mergeSavedSuffixedListings } from "../portfolio/suffixed-listings";
3
+ import type { CliCommandContext } from "../types/plugin";
4
+ import { debugLog } from "../utils/debug-log";
5
+ import { logFailure } from "../utils/log-failure";
6
+ import { withConfigData, withMarketData } from "./scoped-context";
7
+ import type { ConfigContext, MarketContext } from "./types";
8
+
9
+ const log = debugLog.createLogger("cli.suffixed-listings");
10
+
11
+ /**
12
+ * The profile with the rows a collection holds under a vendor's suffixed key
13
+ * (GARAN.IS) merged into their listing's row (`mergeSuffixedListings`), as
14
+ * the app does at launch, for a command about to change a portfolio or
15
+ * watchlist: what it reads is then what it saves over. A dry run writes
16
+ * nothing and reads the profile as it is. A merge that fails leaves the rows
17
+ * as they were.
18
+ */
19
+ async function mergedForWrite<TContext extends ConfigContext>(ctx: Pick<CliCommandContext, "cliOptions">, context: TContext): Promise<TContext> {
20
+ if (ctx.cliOptions.dryRun) return context;
21
+ try {
22
+ const merged = await mergeSavedSuffixedListings(await context.store.loadAllTickers(), context.config, {
23
+ config: saveConfig,
24
+ tickers: (rows) => context.store.saveTickers(rows),
25
+ });
26
+ // In place: a market context's provider reads the config through this object.
27
+ if (merged) context.config = merged.config;
28
+ for (const kept of merged?.keptCustom ?? []) log.info("custom fields kept on the suffixed row", kept);
29
+ } catch (error) {
30
+ logFailure("cli.suffixed-listings", "Merging suffixed listing rows failed")(error);
31
+ }
32
+ return context;
33
+ }
34
+
35
+ /** `withConfigData` for a command that changes a portfolio or watchlist (`mergedForWrite`). Commands that only read use `withConfigData`. */
36
+ export function withCollectionConfigData<TResult>(
37
+ ctx: Pick<CliCommandContext, "initConfigData" | "cliOptions">,
38
+ operation: (context: ConfigContext) => TResult | Promise<TResult>,
39
+ ): Promise<TResult> {
40
+ return withConfigData(async () => mergedForWrite(ctx, await ctx.initConfigData()), operation);
41
+ }
42
+
43
+ /** `withMarketData` for a command that changes a portfolio or watchlist (`mergedForWrite`). */
44
+ export function withCollectionMarketData<TResult>(
45
+ ctx: Pick<CliCommandContext, "initMarketData" | "cliOptions">,
46
+ operation: (context: MarketContext) => TResult | Promise<TResult>,
47
+ ): Promise<TResult> {
48
+ return withMarketData(async () => mergedForWrite(ctx, await ctx.initMarketData()), operation);
49
+ }
@@ -1,3 +1,6 @@
1
+ import { isFigure, isNumberCell, protectFigureCommas, restoreFigureCommas } from "./symbol-cells";
2
+ import { readTerminalListingCode, unknownBloombergMarket } from "../tickers/terminal-codes";
3
+
1
4
  /** The quote marks a pasted list wraps its entries in: "AAPL", 'MSFT', “NVDA”. */
2
5
  const QUOTE_MARKS = "\"'`\u2018\u2019\u201C\u201D";
3
6
  const QUOTE_EDGES = new RegExp(`^[${QUOTE_MARKS}]+|[${QUOTE_MARKS}]+$`, "g");
@@ -12,18 +15,37 @@ const LIST_SEPARATOR = /[,;\t\r\n]/;
12
15
  * in it is split on those, so an entry may be a company's name (`WHR,
13
16
  * Whirlpool Corporation, BRK.B`) or several symbols with spaces between them
14
17
  * (`brk.b bf-b` on a pasted line); one without them is split on spaces (`JNK
15
- * EMB BRK.B`). Which an entry with a space is takes a search: a command that
18
+ * EMB BRK.B`), or with `phrases` kept whole (`splitSymbolArgLines`). Which an
19
+ * entry with a space is takes a search: a command that
16
20
  * resolves its symbols reads them with `readNameEntries`, and a parser that
17
- * looks nothing up takes `splitSymbolWords`.
21
+ * looks nothing up takes `splitSymbolWords`. A comma inside a figure
22
+ * (`2.582,52`, `1,899.21`) is no separator: the figure stays one entry. One
23
+ * between plain digits is a decimal comma only on a line with another
24
+ * separator (`ED 2,5`); alone it splits codes (`9988,5`, `700,388`).
18
25
  */
19
- export function splitSymbolArgs(args: readonly string[]): string[] {
20
- return args
21
- .flatMap((arg) => {
22
- const text = arg.replace(/^\uFEFF/, "");
23
- return LIST_SEPARATOR.test(text) ? text.split(LIST_SEPARATOR) : text.split(/\s+/);
24
- })
25
- .map((entry) => entry.trim().replace(QUOTE_EDGES, "").trim().replace(/\s+/g, " "))
26
- .filter(Boolean);
26
+ export function splitSymbolArgs(args: readonly string[], options: { phrases?: boolean } = {}): string[] {
27
+ return args.flatMap((arg) => splitSymbolArgLines(arg, options).flat());
28
+ }
29
+
30
+ /**
31
+ * `splitSymbolArgs` of one argument, its entries kept by the line they are
32
+ * on, so a figure can be told to sit beside the symbol on its line. With
33
+ * `phrases`, an argument with spaces and no list separator is one entry, as
34
+ * an entry between commas is: a company's name (`"Beyond Meat"`) or symbols
35
+ * typed on one line (`"GME AMC"`), which `readNameEntries` tells apart.
36
+ */
37
+ export function splitSymbolArgLines(arg: string, { phrases = false }: { phrases?: boolean } = {}): string[][] {
38
+ const lines = arg.replace(/^\uFEFF/, "").split(/\r\n?|\n/).map((line) => protectFigureCommas(line));
39
+ const separated = lines.length > 1 || lines.some((line) => LIST_SEPARATOR.test(line));
40
+ // A terminal's code (`VOD LN`, `JPM US Equity`), or words written as one (`AAPL GP`), is one entry.
41
+ return lines.map((line) => (separated ? line.split(/[,;\t]/) : phrases || isTerminalCodeLine(line) ? [line] : line.split(/\s+/))
42
+ .map((entry) => restoreFigureCommas(entry).trim().replace(QUOTE_EDGES, "").trim().replace(/\s+/g, " "))
43
+ .filter(Boolean));
44
+ }
45
+
46
+ function isTerminalCodeLine(line: string): boolean {
47
+ const text = line.trim().replace(QUOTE_EDGES, "").trim();
48
+ return /\s/.test(text) && (readTerminalListingCode(text) != null || unknownBloombergMarket(text) != null);
27
49
  }
28
50
 
29
51
  /**
@@ -31,15 +53,28 @@ export function splitSymbolArgs(args: readonly string[]): string[] {
31
53
  * spaces and no list separator into it: `quote "10 year yield"`, `quote
32
54
  * "Apple Inc"` or a pasted line `quote "AAPL MSFT"`. Which of those it is
33
55
  * takes a lookup (`readPhraseArgument`); `splitSymbolArgs` would split it
34
- * into words, each a symbol (10, YEAR, YIELD). Null for anything else:
35
- * several arguments, one word, or a list with commas.
56
+ * into words, each a symbol (10, YEAR, YIELD). A figure in it is part of
57
+ * the phrase (`"10.5 year yield"`, `"fed funds rate 5.25%"`). Null for
58
+ * anything else: several arguments, one word, a list with commas, or a
59
+ * pasted row of symbols each followed by its prices (`ED 2.582,52`, `AAPL
60
+ * 150.00 MSFT 300.00`), which is read as a list is.
36
61
  */
37
62
  export function quotedPhrase(args: readonly string[]): string | null {
38
63
  if (args.length !== 1) return null;
39
64
  const text = args[0]!.replace(/^\uFEFF/, "");
40
- if (LIST_SEPARATOR.test(text)) return null;
65
+ if (LIST_SEPARATOR.test(protectFigureCommas(text))) return null;
41
66
  const phrase = text.trim().replace(QUOTE_EDGES, "").trim().replace(/\s+/g, " ");
42
- return phrase.includes(" ") ? phrase : null;
67
+ return phrase.includes(" ") && !isPricedRow(phrase.split(" ")) ? phrase : null;
68
+ }
69
+
70
+ /**
71
+ * Words that are a sheet's row rather than a phrase: a number (`2.582,52`)
72
+ * among them, and each word that is no figure followed by one (`ED
73
+ * 2.582,52`), so no two words of a name or a phrase sit side by side.
74
+ */
75
+ function isPricedRow(words: readonly string[]): boolean {
76
+ if (!words.some(isNumberCell) || isFigure(words[0]!)) return false;
77
+ return words.every((word, index) => isFigure(word) || (index + 1 < words.length && isFigure(words[index + 1]!)));
43
78
  }
44
79
 
45
80
  /**
@@ -50,7 +85,7 @@ export function quotedPhrase(args: readonly string[]): string | null {
50
85
  */
51
86
  export function splitSymbolWords(args: readonly string[]): string[] {
52
87
  return splitSymbolArgs(args)
53
- .flatMap((entry) => entry.split(" "))
88
+ .flatMap((entry) => isTerminalCodeLine(entry) ? [entry] : entry.split(" "))
54
89
  .map((word) => word.replace(QUOTE_EDGES, ""))
55
90
  .filter(Boolean);
56
91
  }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * What one cell of a pasted list or a typed argument is before anything is
3
+ * looked up: a symbol, a figure (a price, a weight, a share count) or junk
4
+ * a sheet leaves where a value is missing (`N/A`, `--`, `$$$`). Every list
5
+ * reader and every lookup of a list's symbols decide it here, so a price
6
+ * from a European sheet (`2.582,52`) is never searched for as a ticker.
7
+ */
8
+
9
+ /** A sign before a figure: plus, hyphen-minus or the minus sign. */
10
+ const SIGN = "[+\\-\u2212]";
11
+ /** The currency marks a sheet writes beside an amount. */
12
+ const CURRENCY = "[$\u20ac\u00a3\u00a5\u20b9\u20a9\u20bd\u20ba\u20aa\u0e3f\u20ab\u00a2]";
13
+ /** Thousands written with an apostrophe (1'234.50) or a no-break or thin space (1 234,50). */
14
+ const GROUP_MARK = "['\u2019\u00a0\u202f\u2009]";
15
+ const FIGURE_BODY = [
16
+ // 1,899.21 and 1,899: commas between thousands.
17
+ "\\d{1,3}(?:,\\d{3})+(?:\\.\\d+)?",
18
+ // 2.582,52, 1.899 and 1.234.567: dots between thousands, a decimal comma.
19
+ "\\d{1,3}(?:\\.\\d{3})+(?:,\\d+)?",
20
+ `\\d{1,3}(?:${GROUP_MARK}\\d{3})+(?:[.,]\\d+)?`,
21
+ // 2,5 and 12,345, and 1234,56: a decimal comma.
22
+ "\\d{1,3},\\d+",
23
+ "\\d+,\\d{1,2}",
24
+ "\\d*\\.\\d+",
25
+ "\\d+",
26
+ ].join("|");
27
+ const FIGURE = new RegExp(
28
+ `^(?:${SIGN}?${CURRENCY}?${SIGN}?(?:${FIGURE_BODY})(?:%|\u2030|${CURRENCY})?|\\(${CURRENCY}?(?:${FIGURE_BODY})%?\\))$`,
29
+ "u",
30
+ );
31
+ /** A run of digits and the marks between them, where a comma may be a decimal comma rather than a list's separator. */
32
+ const FIGURE_RUN = new RegExp(`(?<![\\p{L}\\p{N}.])(?:${SIGN}|${CURRENCY})*\\d[\\d.,'\u2019\u00a0\u202f\u2009]*(?:%|\u2030|${CURRENCY})?`, "gu");
33
+ /** Placeholders a sheet writes for a missing value, and its error values: N/A, n.a., #N/A, #VALUE!. */
34
+ const PLACEHOLDER = /^(?:#?n\/a|n\.a\.?|#(?:value!|ref!|div\/0!|name\?|num!|null!|spill!|calc!|getting_data))$/i;
35
+ /** Stands in for a comma inside a figure while a line is split on its separators. */
36
+ const FIGURE_COMMA = "\u0000";
37
+ /** Plain digits split by commas (`7203,10`, `5,700`): a decimal comma, or the line's separator between two codes. */
38
+ const PLAIN_COMMA_RUN = /^\d+(?:,\d+)+$/;
39
+
40
+ /**
41
+ * A figure as a sheet or a keyboard writes it, a bare whole number (7203)
42
+ * included: `2.582,52`, `1,899.21`, `-3.2%`, `€1.234,56`, `(1,234.56)`.
43
+ */
44
+ export function isFigure(cell: string): boolean {
45
+ return FIGURE.test(cell.trim());
46
+ }
47
+
48
+ /**
49
+ * A figure that is never a symbol: one with a decimal or thousands mark, a
50
+ * sign, a percent or a currency mark (`1.899`, `2,5`, `+4`, `12%`, `$12`). A
51
+ * bare whole number is not one, as `7203` and `0700` are tickers on their own.
52
+ */
53
+ export function isNumberCell(cell: string): boolean {
54
+ const text = cell.trim();
55
+ return FIGURE.test(text) && !/^\d+$/.test(text);
56
+ }
57
+
58
+ /** A cell that names nothing: no letter or digit (`$$$`, `--`, `-`, `…`), or a placeholder for a missing value (`N/A`, `#N/A`). */
59
+ export function isJunkCell(cell: string): boolean {
60
+ const text = cell.trim();
61
+ return !/[\p{L}\p{N}]/u.test(text) || PLACEHOLDER.test(text);
62
+ }
63
+
64
+ /** Why a cell is not a symbol, as a lookup refuses it without asking anything; null for one that may be. */
65
+ function notASymbolReason(cell: string): string | null {
66
+ if (isJunkCell(cell)) return "not a symbol";
67
+ if (isNumberCell(cell)) return "a number, not a symbol";
68
+ return null;
69
+ }
70
+
71
+ /** An entry of a list that cannot be a symbol, refused before any lookup and never looked up again. */
72
+ export class NotASymbolError extends Error {
73
+ constructor(readonly input: string, readonly reason: string) {
74
+ super(`${input.trim()} is ${reason}.`);
75
+ this.name = "NotASymbolError";
76
+ }
77
+ }
78
+
79
+ /** `NotASymbolError` for a cell that is not a symbol, else null. */
80
+ export function notASymbolError(cell: string): NotASymbolError | null {
81
+ const reason = notASymbolReason(cell);
82
+ return reason ? new NotASymbolError(cell, reason) : null;
83
+ }
84
+
85
+ /**
86
+ * Whether a comma between plain digits on a line is a decimal comma (`ED
87
+ * 2,5`, `CNX;1899,21`): the line has another separator, a tab, a semicolon or
88
+ * spaces between its cells. Otherwise the comma is the line's only separator
89
+ * and splits the digits into cells, as a sheet of codes exports them
90
+ * (`0700,25`, `7203,10`). Quoted cells and separators at the ends are not
91
+ * counted.
92
+ */
93
+ export function hasDecimalCommas(line: string): boolean {
94
+ const bare = line.replace(/"(?:[^"]|"")*"/g, "\"\"").replace(/^[\s,;]+|[\s,;]+$/g, "");
95
+ return /[\t;]/.test(bare) || /[^\s,;]\s+[^\s,;]/.test(bare);
96
+ }
97
+
98
+ /**
99
+ * The text with each comma inside a figure swapped for a stand-in, so
100
+ * splitting on commas leaves the figure whole; `restoreFigureCommas` puts
101
+ * them back. A figure only a number can be (`2.582,52`, `1,899.21`, `2,5%`)
102
+ * keeps its comma. One of plain digits (`7203,10`) keeps it only where its
103
+ * comma is a decimal comma: `decimalCommas`, else `hasDecimalCommas` of each
104
+ * line. A run that is no figure keeps its commas as separators.
105
+ */
106
+ export function protectFigureCommas(text: string, decimalCommas?: boolean): string {
107
+ if (decimalCommas == null) {
108
+ return text.split(/(\r\n?|\n)/).map((part, index) => index % 2 === 1 ? part : protectFigureCommas(part, hasDecimalCommas(part))).join("");
109
+ }
110
+ return text.replace(FIGURE_RUN, (run) => {
111
+ const body = run.replace(/[.,'\u2019]+$/, "");
112
+ const tail = run.slice(body.length);
113
+ const figure = body.includes(",") && isFigure(body) && (decimalCommas || !PLAIN_COMMA_RUN.test(body));
114
+ return figure ? `${body.replaceAll(",", FIGURE_COMMA)}${tail}` : run;
115
+ });
116
+ }
117
+
118
+ export function restoreFigureCommas(text: string): string {
119
+ return text.replaceAll(FIGURE_COMMA, ",");
120
+ }