gloomberb 0.18.3 → 0.18.4

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 (886) 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/src/account/checkout-handoff.tsx +225 -0
  6. package/src/account/device-signin-dialog.tsx +2 -2
  7. package/src/account/device-signin.ts +2 -2
  8. package/src/account/upgrade-dialog.tsx +1 -1
  9. package/src/api-client/askg.ts +2 -2
  10. package/src/api-client/auth.ts +2 -2
  11. package/src/api-client/central-bank-rates.ts +6 -0
  12. package/src/api-client/collections.ts +5 -1
  13. package/src/api-client/cot.ts +2 -0
  14. package/src/api-client/crypto-etf-flows.ts +37 -0
  15. package/src/api-client/crypto-markets.ts +60 -0
  16. package/src/api-client/data.ts +84 -5
  17. package/src/api-client/doe.ts +15 -0
  18. package/src/api-client/equity-screener.ts +28 -0
  19. package/src/api-client/exchange-announcements.ts +38 -0
  20. package/src/api-client/fund-facts.ts +39 -0
  21. package/src/api-client/futures-curve.ts +9 -1
  22. package/src/api-client/hiring.ts +301 -0
  23. package/src/api-client/index.ts +22 -5
  24. package/src/api-client/market-discovery.ts +14 -0
  25. package/src/api-client/members.ts +6 -0
  26. package/src/api-client/mna.ts +6 -0
  27. package/src/api-client/paths.ts +18 -1
  28. package/src/api-client/request.ts +21 -4
  29. package/src/api-client/short-side-publications.ts +37 -0
  30. package/src/api-client/socket.ts +64 -4
  31. package/src/api-client/swap-curve.ts +35 -0
  32. package/src/api-client/themes.ts +7 -1
  33. package/src/api-client/types.ts +90 -2
  34. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  35. package/src/app/runtime/desktop-deeplink.ts +5 -5
  36. package/src/app/runtime/plugin-bindings.ts +2 -2
  37. package/src/app/runtime/startup.ts +13 -0
  38. package/src/app/star-prompt/status-line.tsx +2 -2
  39. package/src/architecture/core-builtin-allowlist.json +5 -2
  40. package/src/architecture/ui-literals-allowlist.json +3 -3
  41. package/src/architecture/ui-tokens-allowlist.json +1 -1
  42. package/src/brokers/broker-portfolio-sync.ts +37 -0
  43. package/src/brokers/directory.ts +11 -0
  44. package/src/brokers/logos.ts +3 -1
  45. package/src/brokers/signed-in/adapter.ts +304 -26
  46. package/src/brokers/signed-in/client.ts +14 -2
  47. package/src/brokers/signed-in/connect.ts +10 -2
  48. package/src/brokers/sync-broker-instance.ts +9 -1
  49. package/src/capabilities/chart-series.ts +22 -6
  50. package/src/cli/bank-section.ts +1 -1
  51. package/src/cli/base-converter.ts +23 -14
  52. package/src/cli/central-bank-events.ts +1 -1
  53. package/src/cli/command-options.ts +59 -4
  54. package/src/cli/commands/api.ts +9 -6
  55. package/src/cli/commands/broker.ts +2 -2
  56. package/src/cli/commands/command-utils.ts +2 -2
  57. package/src/cli/commands/crypto-hints.ts +7 -20
  58. package/src/cli/commands/fred-series.ts +4 -2
  59. package/src/cli/commands/keybindings.ts +2 -2
  60. package/src/cli/commands/market.ts +1117 -264
  61. package/src/cli/commands/news-hints.ts +2 -2
  62. package/src/cli/commands/news-search.ts +59 -6
  63. package/src/cli/commands/options-leaps.ts +41 -26
  64. package/src/cli/commands/overview.ts +121 -48
  65. package/src/cli/commands/plugins.ts +9 -9
  66. package/src/cli/commands/remote.ts +13 -10
  67. package/src/cli/commands/search.ts +64 -44
  68. package/src/cli/commands/system.ts +27 -19
  69. package/src/cli/commands/themes.ts +1 -1
  70. package/src/cli/commands/ticker.ts +192 -47
  71. package/src/cli/context.ts +3 -2
  72. package/src/cli/desktop-pane-shot-view.ts +2 -2
  73. package/src/cli/desktop-pane-shot.ts +1 -1
  74. package/src/cli/earnings-calendar.ts +4 -4
  75. package/src/cli/entry.ts +18 -1
  76. package/src/cli/errors.ts +20 -2
  77. package/src/cli/exit-codes.ts +1 -1
  78. package/src/cli/export-source.ts +10 -4
  79. package/src/cli/freshness.ts +2 -8
  80. package/src/cli/fx-forward.ts +130 -0
  81. package/src/cli/fx-pair.ts +10 -9
  82. package/src/cli/glossary.ts +64 -20
  83. package/src/cli/help.ts +19 -13
  84. package/src/cli/history-export.ts +126 -0
  85. package/src/cli/history-rows.ts +196 -43
  86. package/src/cli/index-roots.ts +5 -45
  87. package/src/cli/index.ts +24 -18
  88. package/src/cli/known-gaps.ts +118 -25
  89. package/src/cli/listing-arg.ts +300 -41
  90. package/src/cli/name-entries.ts +30 -18
  91. package/src/cli/native-smoke.ts +2 -0
  92. package/src/cli/not-a-ticker.ts +19 -9
  93. package/src/cli/opentui-libc.ts +5 -0
  94. package/src/cli/options.ts +12 -0
  95. package/src/cli/pane-functions/capabilities.ts +75 -20
  96. package/src/cli/pane-functions/catalog.ts +24 -23
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +10 -7
  99. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  100. package/src/cli/pane-functions/freshness.ts +174 -23
  101. package/src/cli/pane-functions/function-help.ts +66 -27
  102. package/src/cli/pane-functions/headless.ts +24 -11
  103. package/src/cli/pane-functions/index.ts +18 -16
  104. package/src/cli/pane-functions/options.ts +22 -2
  105. package/src/cli/pane-functions/report-notices.ts +12 -4
  106. package/src/cli/pane-functions/report.ts +5 -5
  107. package/src/cli/pane-functions/resolver.ts +47 -10
  108. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  109. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  110. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  111. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  112. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  113. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  114. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  115. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  116. package/src/cli/pane-functions/shot-options.ts +8 -3
  117. package/src/cli/peso-dollar-rates.ts +79 -0
  118. package/src/cli/quote-answer.ts +38 -3
  119. package/src/cli/report-tables.ts +61 -16
  120. package/src/cli/restore-plugins.ts +29 -14
  121. package/src/cli/result.ts +111 -22
  122. package/src/cli/series-search.ts +5 -5
  123. package/src/cli/statement-filings.ts +19 -0
  124. package/src/cli/suffixed-listing-rows.ts +49 -0
  125. package/src/cli/symbol-args.ts +50 -15
  126. package/src/cli/symbol-cells.ts +120 -0
  127. package/src/cli/symbol-list.ts +198 -68
  128. package/src/cli/symbol-rows.ts +131 -25
  129. package/src/cli/ticker-resolution.ts +108 -11
  130. package/src/cli/treasury-yields.ts +5 -5
  131. package/src/cli/types.ts +2 -0
  132. package/src/cli/uncovered-instrument.ts +3 -3
  133. package/src/cli/unknown-command.ts +6 -6
  134. package/src/components/chart/composite/chart-layout.ts +131 -0
  135. package/src/components/chart/composite/composite-chart.tsx +373 -16
  136. package/src/components/chart/composite/interactions.ts +7 -2
  137. package/src/components/chart/composite/legend.tsx +75 -3
  138. package/src/components/chart/composite/levels.ts +5 -0
  139. package/src/components/chart/composite/panel-gestures.ts +41 -0
  140. package/src/components/chart/composite/panel-labels.ts +2 -1
  141. package/src/components/chart/composite/panel-surface.tsx +305 -11
  142. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  143. package/src/components/chart/composite/rasterizer.ts +44 -19
  144. package/src/components/chart/composite/scene.ts +16 -4
  145. package/src/components/chart/composite/text-renderer.ts +48 -21
  146. package/src/components/chart/composite/toolbar.tsx +52 -5
  147. package/src/components/chart/composite/types.ts +13 -0
  148. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  149. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  150. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  151. package/src/components/chart/composite/value-scale.ts +149 -0
  152. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  153. package/src/components/chart/core/pointer.ts +2 -0
  154. package/src/components/chart-table/index.ts +2 -0
  155. package/src/components/chart-table/read.tsx +74 -0
  156. package/src/components/command-bar/commands/collection-list.ts +41 -19
  157. package/src/components/command-bar/commands/collection.ts +9 -3
  158. package/src/components/command-bar/commands/direct/index.ts +1 -1
  159. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  160. package/src/components/command-bar/pane-templates/items.ts +59 -6
  161. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  162. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  163. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  164. package/src/components/command-bar/routes/root/results.ts +18 -4
  165. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  166. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  167. package/src/components/command-bar/routes/root/selection.ts +6 -1
  168. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  169. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  170. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  171. package/src/components/command-bar/selection-runtime.ts +50 -10
  172. package/src/components/command-bar/surface/index.tsx +24 -2
  173. package/src/components/command-bar/view-model.ts +7 -0
  174. package/src/components/command-bar/workflow/broker.ts +2 -2
  175. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  176. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  177. package/src/components/command-bar/workflow/fields.ts +8 -2
  178. package/src/components/command-bar/workflow/ops.ts +18 -4
  179. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  180. package/src/components/command-bar/workflow/submit.ts +3 -2
  181. package/src/components/command-bar/workflow/tickers.ts +5 -1
  182. package/src/components/company-logo.tsx +39 -0
  183. package/src/components/data-table/sections.ts +4 -2
  184. package/src/components/form-modal/confirm.tsx +2 -1
  185. package/src/components/form-modal/request.ts +5 -0
  186. package/src/components/form-modal/routes.ts +4 -1
  187. package/src/components/index.ts +12 -6
  188. package/src/components/layout/header.tsx +7 -6
  189. package/src/components/layout/market-summary.ts +9 -6
  190. package/src/components/layout/pane/capture-status.ts +1 -1
  191. package/src/components/layout/pane/footer/model.ts +11 -5
  192. package/src/components/layout/shell/chrome.ts +19 -6
  193. package/src/components/layout/shell/index.tsx +2 -1
  194. package/src/components/layout/shell/pane/layers.tsx +19 -1
  195. package/src/components/layout/status-bar.tsx +2 -2
  196. package/src/components/market-board/index.tsx +11 -3
  197. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  198. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  199. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  200. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  201. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  202. package/src/components/pane-settings-dialog/value.ts +8 -1
  203. package/src/components/pane-settings-dialog.tsx +44 -13
  204. package/src/components/sign-in-code-panel.tsx +27 -19
  205. package/src/components/ui/column-grid.tsx +48 -4
  206. package/src/components/ui/country-flag-art.tsx +180 -0
  207. package/src/components/ui/country-flag.tsx +118 -12
  208. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  209. package/src/components/ui/data-table/opentui/model.ts +109 -2
  210. package/src/components/ui/data-table/types.ts +1 -1
  211. package/src/components/ui/display.tsx +5 -1
  212. package/src/components/ui/index.ts +3 -1
  213. package/src/components/ui/logo-mark.tsx +11 -2
  214. package/src/components/ui/query-bar.tsx +1 -1
  215. package/src/components/ui/row-notes.ts +79 -0
  216. package/src/core/state/app/layout.ts +4 -4
  217. package/src/data/cached-query.ts +8 -1
  218. package/src/data/config/chart-settings.ts +3 -3
  219. package/src/data/config/home.ts +10 -2
  220. package/src/data/config/layout.ts +4 -1
  221. package/src/data/config/store/node.ts +4 -0
  222. package/src/data/config/store/normalize.ts +13 -3
  223. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  224. package/src/data/json-storage.ts +2 -0
  225. package/src/data/saved-copies.ts +84 -0
  226. package/src/docs/snapshot.json +65 -32
  227. package/src/i18n/es.ts +29 -12
  228. package/src/i18n/ja.ts +29 -12
  229. package/src/i18n/ko.ts +29 -12
  230. package/src/i18n/zh-cn.ts +29 -12
  231. package/src/i18n/zh-tw.ts +29 -12
  232. package/src/layout/desks.ts +1 -1
  233. package/src/layout/launch-layout.ts +1 -1
  234. package/src/layout/pane-manager/floating-actions.ts +5 -3
  235. package/src/layout/pane-manager/floating.ts +43 -1
  236. package/src/layout/pane-manager/index.ts +2 -0
  237. package/src/layout/selected-ticker.ts +74 -0
  238. package/src/market-data/depositary-pair.ts +251 -0
  239. package/src/market-data/futures-board.ts +1 -1
  240. package/src/market-data/futures-contract.ts +124 -40
  241. package/src/market-data/fx-closes.ts +17 -2
  242. package/src/market-data/hooks.tsx +19 -11
  243. package/src/market-data/market/change-basis.ts +49 -7
  244. package/src/market-data/market/freshness.ts +34 -5
  245. package/src/market-data/market/period-return.ts +163 -0
  246. package/src/market-data/market/trading-sessions.ts +13 -0
  247. package/src/market-data/market/year-to-date.ts +8 -13
  248. package/src/market-data/performance.ts +20 -14
  249. package/src/market-data/perpetual-premium.ts +32 -0
  250. package/src/market-data/published-apac-sessions.ts +2 -1
  251. package/src/market-data/published-futures-sessions.ts +69 -0
  252. package/src/market-data/quotes/contributions.ts +5 -1
  253. package/src/market-data/quotes/freshness.ts +42 -0
  254. package/src/market-data/quotes/intraday-bar.ts +37 -0
  255. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  256. package/src/market-data/quotes/resolution.ts +4 -2
  257. package/src/market-data/tax-equivalent.ts +1 -1
  258. package/src/market-data/ticker-price-returns.ts +3 -1
  259. package/src/news/aggregator.ts +5 -1
  260. package/src/news/news-model.ts +4 -0
  261. package/src/news/types.ts +11 -0
  262. package/src/notifications/app-notifier.ts +1 -1
  263. package/src/plugins/auto-update.ts +2 -2
  264. package/src/plugins/builtin/account-management/index.tsx +1 -0
  265. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  266. package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
  267. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  268. package/src/plugins/builtin/alerts/cli.ts +485 -76
  269. package/src/plugins/builtin/alerts/command.ts +5 -10
  270. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  271. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  272. package/src/plugins/builtin/alerts/events.ts +107 -5
  273. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  274. package/src/plugins/builtin/alerts/format.ts +2 -1
  275. package/src/plugins/builtin/alerts/headless.ts +100 -39
  276. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  277. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  278. package/src/plugins/builtin/alerts/index.tsx +45 -18
  279. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  280. package/src/plugins/builtin/alerts/levels.ts +3 -3
  281. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  282. package/src/plugins/builtin/alerts/price.ts +35 -0
  283. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  284. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  285. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  286. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  287. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  288. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  289. package/src/plugins/builtin/alerts/storage.ts +13 -10
  290. package/src/plugins/builtin/alerts/targets.ts +12 -3
  291. package/src/plugins/builtin/analytics/index.tsx +8 -2
  292. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  293. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  294. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  295. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  296. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  297. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  298. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  299. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  300. package/src/plugins/builtin/attention/pane.tsx +6 -2
  301. package/src/plugins/builtin/awards/headless.ts +7 -3
  302. package/src/plugins/builtin/awards/model.ts +18 -0
  303. package/src/plugins/builtin/awards/pane.tsx +6 -3
  304. package/src/plugins/builtin/backtest/headless.ts +3 -3
  305. package/src/plugins/builtin/backtest/rules.ts +41 -5
  306. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  307. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  308. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  309. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  310. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  311. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  312. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  313. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  314. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  315. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  316. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  317. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  318. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  319. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  320. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  321. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  322. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  323. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  324. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  325. package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
  326. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  327. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  328. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  329. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  330. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  331. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  332. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  333. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  334. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  335. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  336. package/src/plugins/builtin/catalysts/model.ts +49 -4
  337. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  338. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  339. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  340. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  341. package/src/plugins/builtin/changelog/index.tsx +1 -0
  342. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  343. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  344. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  345. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  346. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  347. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  348. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  349. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  350. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  351. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  352. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  353. package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
  354. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  355. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  356. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  357. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  358. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  359. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  360. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  361. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  362. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  363. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  364. package/src/plugins/builtin/chat/people.ts +1 -1
  365. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  366. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  367. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  368. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  369. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  370. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  371. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  372. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  373. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  374. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  375. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  376. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  377. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  378. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  379. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  380. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  381. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  382. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  383. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  384. package/src/plugins/builtin/company-attention/client.ts +117 -1
  385. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  386. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  387. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  388. package/src/plugins/builtin/company-attention/model.ts +33 -7
  389. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  390. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  391. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  392. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  393. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  394. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  395. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  396. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  397. package/src/plugins/builtin/composite-plugins.ts +2 -1
  398. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  399. package/src/plugins/builtin/connections/index.ts +1 -0
  400. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  401. package/src/plugins/builtin/correlation/headless.ts +5 -3
  402. package/src/plugins/builtin/cot/headless.ts +28 -6
  403. package/src/plugins/builtin/cot/model.ts +12 -0
  404. package/src/plugins/builtin/cot/pane.tsx +3 -2
  405. package/src/plugins/builtin/cpi/headless.ts +5 -1
  406. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  407. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  408. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  409. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  410. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  411. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  412. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  413. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  414. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  415. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  416. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  417. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  418. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  419. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  420. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  421. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  422. package/src/plugins/builtin/debug/index.tsx +1 -0
  423. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  424. package/src/plugins/builtin/docs/index.tsx +1 -1
  425. package/src/plugins/builtin/docs/pane.tsx +2 -2
  426. package/src/plugins/builtin/docs/targets.ts +1 -1
  427. package/src/plugins/builtin/doe/client.ts +5 -1
  428. package/src/plugins/builtin/doe/headless.ts +12 -6
  429. package/src/plugins/builtin/doe/model.ts +43 -6
  430. package/src/plugins/builtin/doe/pane.tsx +18 -11
  431. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  432. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  433. package/src/plugins/builtin/earnings/board.tsx +253 -50
  434. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  435. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  436. package/src/plugins/builtin/earnings/client.ts +4 -3
  437. package/src/plugins/builtin/earnings/headless.ts +53 -15
  438. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  439. package/src/plugins/builtin/earnings/index.tsx +15 -22
  440. package/src/plugins/builtin/earnings/model.ts +17 -12
  441. package/src/plugins/builtin/earnings/scope.ts +89 -0
  442. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  443. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  444. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  445. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  446. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  447. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  448. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  449. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  450. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  451. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  452. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  453. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  454. package/src/plugins/builtin/econ/index.tsx +112 -25
  455. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  456. package/src/plugins/builtin/econ/types.ts +32 -1
  457. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  458. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  459. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  460. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  461. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  462. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  463. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  464. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  465. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  466. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  467. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  468. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  469. package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
  470. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  471. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  472. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  473. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  474. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  475. package/src/plugins/builtin/exposure/headless.ts +51 -6
  476. package/src/plugins/builtin/exposure/index.tsx +28 -2
  477. package/src/plugins/builtin/exposure/model.ts +7 -0
  478. package/src/plugins/builtin/exposure/pane.tsx +6 -1
  479. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  480. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  481. package/src/plugins/builtin/futures/model.ts +10 -9
  482. package/src/plugins/builtin/futures/returns.ts +8 -36
  483. package/src/plugins/builtin/futures/table.tsx +1 -1
  484. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  485. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  486. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  487. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  488. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  489. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  490. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  491. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  492. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  493. package/src/plugins/builtin/gpu/headless.ts +9 -4
  494. package/src/plugins/builtin/help/index.tsx +13 -3
  495. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  496. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  497. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  498. package/src/plugins/builtin/holders/client.ts +13 -1
  499. package/src/plugins/builtin/holders/format.ts +28 -17
  500. package/src/plugins/builtin/holders/headless.ts +46 -7
  501. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  502. package/src/plugins/builtin/holders/pane.tsx +79 -15
  503. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  504. package/src/plugins/builtin/holders/table-model.ts +2 -1
  505. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  506. package/src/plugins/builtin/insider/headless.ts +1 -1
  507. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  508. package/src/plugins/builtin/insider/signals.tsx +1 -1
  509. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  510. package/src/plugins/builtin/iv-history/client.ts +20 -0
  511. package/src/plugins/builtin/iv-history/headless.ts +4 -4
  512. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  513. package/src/plugins/builtin/iv-history/model.ts +13 -4
  514. package/src/plugins/builtin/iv-history/series.ts +3 -1
  515. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  516. package/src/plugins/builtin/jobs/model.ts +4 -15
  517. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  518. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  519. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  520. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  521. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  522. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  523. package/src/plugins/builtin/macro-day/model.ts +29 -8
  524. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  525. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  526. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  527. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  528. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  529. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  530. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  531. package/src/plugins/builtin/market-movers/client.ts +33 -19
  532. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  533. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  534. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  535. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  536. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  537. package/src/plugins/builtin/market-movers/table.ts +4 -1
  538. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  539. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  540. package/src/plugins/builtin/members/headless.ts +6 -5
  541. package/src/plugins/builtin/members/pane.tsx +11 -4
  542. package/src/plugins/builtin/mna/client.ts +1 -0
  543. package/src/plugins/builtin/mna/detail.tsx +20 -32
  544. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  545. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  546. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  547. package/src/plugins/builtin/mna/headless.ts +6 -13
  548. package/src/plugins/builtin/mna/model.ts +93 -15
  549. package/src/plugins/builtin/mna/pane.tsx +5 -4
  550. package/src/plugins/builtin/news/headless.ts +12 -6
  551. package/src/plugins/builtin/news/index.tsx +10 -1
  552. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  553. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  554. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  555. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  556. package/src/plugins/builtin/notes/cli.ts +49 -14
  557. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  558. package/src/plugins/builtin/options/carry.ts +2 -2
  559. package/src/plugins/builtin/options/index.tsx +1 -1
  560. package/src/plugins/builtin/options/view.tsx +10 -10
  561. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  562. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  563. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  564. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  565. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  566. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  567. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  568. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  569. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  570. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  571. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  572. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  573. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  574. package/src/plugins/builtin/perps/freshness.ts +8 -5
  575. package/src/plugins/builtin/perps/headless.ts +3 -1
  576. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  577. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  578. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  579. package/src/plugins/builtin/perps/pane.tsx +36 -17
  580. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  581. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  582. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  583. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  584. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  585. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  586. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  587. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  588. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  589. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  590. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  591. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  592. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  593. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  594. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  595. package/src/plugins/builtin/power/client.ts +4 -1
  596. package/src/plugins/builtin/power/evidence.ts +22 -7
  597. package/src/plugins/builtin/power/gas.tsx +5 -1
  598. package/src/plugins/builtin/power/pane.tsx +8 -1
  599. package/src/plugins/builtin/power/prices.tsx +10 -3
  600. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  601. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  603. package/src/plugins/builtin/research/event-model.ts +3 -1
  604. package/src/plugins/builtin/research/event-sources.ts +12 -4
  605. package/src/plugins/builtin/research/index.tsx +2 -1
  606. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  608. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  609. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  610. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  611. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  612. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  613. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  614. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  615. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  616. package/src/plugins/builtin/sec/forms.ts +13 -0
  617. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  618. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  619. package/src/plugins/builtin/sec/headless.ts +85 -8
  620. package/src/plugins/builtin/sec/index.tsx +58 -12
  621. package/src/plugins/builtin/sectors/client.ts +2 -1
  622. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  623. package/src/plugins/builtin/series-inventory.ts +2 -0
  624. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  625. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  626. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  627. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  628. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  629. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  630. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  631. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  632. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  633. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  634. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  635. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  636. package/src/plugins/builtin/short-interest/client.ts +2 -0
  637. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  638. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  639. package/src/plugins/builtin/short-interest/model.ts +70 -19
  640. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  641. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  642. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  643. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  644. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  645. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  646. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  647. package/src/plugins/builtin/short-interest/types.ts +9 -0
  648. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  649. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  650. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  651. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  652. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  653. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  654. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  655. package/src/plugins/builtin/themes/headless.ts +8 -5
  656. package/src/plugins/builtin/themes/model.ts +14 -4
  657. package/src/plugins/builtin/themes/pane.tsx +24 -5
  658. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  659. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  660. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  661. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  662. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  663. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  664. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  665. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  666. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  667. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  668. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  669. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  670. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  671. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  672. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  673. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  674. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  675. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  676. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  677. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  678. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  679. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  680. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  681. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  682. package/src/plugins/builtin/vol-surface/client.ts +5 -4
  683. package/src/plugins/builtin/vol-surface/headless.ts +12 -3
  684. package/src/plugins/builtin/vol-surface/model.ts +4 -2
  685. package/src/plugins/builtin/volatility/model.ts +5 -10
  686. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  687. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  688. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  689. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  690. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  691. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  692. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  693. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  694. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  695. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  696. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  697. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  698. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  699. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  700. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  701. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  702. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  703. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  704. package/src/plugins/bundle.ts +1 -1
  705. package/src/plugins/catalog-browser.ts +2 -1
  706. package/src/plugins/compat.ts +3 -3
  707. package/src/plugins/dependencies.ts +75 -14
  708. package/src/plugins/extracted-plugins.ts +132 -34
  709. package/src/plugins/host-link.ts +149 -34
  710. package/src/plugins/installer.ts +35 -10
  711. package/src/plugins/loader.ts +206 -38
  712. package/src/plugins/manager-node.ts +2 -2
  713. package/src/plugins/marketplace/deactivation.ts +22 -0
  714. package/src/plugins/marketplace/model.ts +2 -2
  715. package/src/plugins/marketplace/packs.ts +1 -1
  716. package/src/plugins/ownership.ts +1 -1
  717. package/src/plugins/peer-retry.ts +155 -0
  718. package/src/plugins/registry/contributions.ts +3 -1
  719. package/src/plugins/registry/index.ts +4 -3
  720. package/src/plugins/registry/plugin-state.ts +3 -0
  721. package/src/plugins/seed-notice.ts +20 -0
  722. package/src/plugins/shortcut-argument.ts +39 -0
  723. package/src/portfolio/allocation.ts +1 -1
  724. package/src/portfolio/collection-name.ts +31 -0
  725. package/src/portfolio/column-values.ts +10 -8
  726. package/src/portfolio/cost-fx.ts +296 -19
  727. package/src/portfolio/manual-lots.ts +75 -0
  728. package/src/portfolio/mutations.ts +60 -22
  729. package/src/portfolio/suffixed-listings.ts +209 -0
  730. package/src/portfolio/totals-currency.ts +24 -0
  731. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  732. package/src/public/time-series.ts +11 -8
  733. package/src/remote/schema.ts +1 -1
  734. package/src/renderers/browser/config-host.ts +3 -0
  735. package/src/renderers/browser/main.tsx +23 -3
  736. package/src/renderers/dom/boot-frame-page.ts +187 -0
  737. package/src/renderers/dom/boot-frame.ts +237 -0
  738. package/src/renderers/dom/build-assets.ts +46 -8
  739. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  740. package/src/renderers/dom/host/ascii-text.ts +16 -2
  741. package/src/renderers/dom/host/box.tsx +43 -2
  742. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  743. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  744. package/src/renderers/dom/host/image-surface.tsx +49 -0
  745. package/src/renderers/dom/host/media-surface.tsx +24 -18
  746. package/src/renderers/dom/host/mouse.ts +30 -0
  747. package/src/renderers/dom/host/size-observer.ts +1 -1
  748. package/src/renderers/dom/host/style.ts +1 -1
  749. package/src/renderers/dom/styles.css +76 -0
  750. package/src/renderers/dom/test-utils.tsx +2 -1
  751. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  752. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  753. package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
  754. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  755. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  756. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  757. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  758. package/src/renderers/electrobun/bun/index.ts +11 -1
  759. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  760. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  761. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  762. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  763. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  764. package/src/renderers/electrobun/view/config-host.ts +3 -0
  765. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  766. package/src/renderers/electrobun/view/main.tsx +30 -4
  767. package/src/renderers/electrobun/view/news-source.ts +5 -5
  768. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  769. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  770. package/src/renderers/opentui/browser-open.ts +88 -0
  771. package/src/renderers/opentui/host.tsx +5 -14
  772. package/src/renderers/opentui/image/loader.ts +3 -2
  773. package/src/renderers/opentui/native-smoke.ts +10 -1
  774. package/src/renderers/opentui/pane-image/index.ts +2 -1
  775. package/src/renderers/opentui/render-lib.ts +253 -0
  776. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  777. package/src/renderers/opentui/start.tsx +1 -1
  778. package/src/renderers/share/layout-view.tsx +2 -2
  779. package/src/renderers/share/main.tsx +4 -4
  780. package/src/renderers/share/view.tsx +1 -1
  781. package/src/series/resolve.ts +22 -6
  782. package/src/series/standalone.ts +30 -2
  783. package/src/series/types.ts +8 -1
  784. package/src/shares/api.ts +4 -1
  785. package/src/shares/pane.ts +1 -1
  786. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  787. package/src/sources/gloomberb-cloud/index.ts +32 -16
  788. package/src/sources/gloomberb-cloud/news.ts +39 -0
  789. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  790. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  791. package/src/sources/listing-symbols.ts +37 -0
  792. package/src/sources/provider-errors.ts +16 -2
  793. package/src/sources/provider-router/financial-routes.ts +21 -3
  794. package/src/sources/provider-router/financials.ts +15 -2
  795. package/src/sources/provider-router/history.ts +30 -8
  796. package/src/sources/provider-router/primary.ts +1 -1
  797. package/src/state/app/bootstrap.ts +23 -0
  798. package/src/state/hooks/inline-tickers.ts +30 -5
  799. package/src/sync/controller.ts +1 -1
  800. package/src/sync/core-contributors.ts +46 -14
  801. package/src/team/collections-sync.ts +2 -1
  802. package/src/team/collections.ts +178 -17
  803. package/src/telemetry/crash-reports.ts +17 -4
  804. package/src/test-support/builtin-panes.ts +1 -1
  805. package/src/theme/colors.ts +3 -30
  806. package/src/theme/ui-tokens.ts +37 -1
  807. package/src/tickers/company-name-listing.ts +210 -33
  808. package/src/tickers/index-roots.ts +47 -0
  809. package/src/tickers/instrument-label.ts +5 -1
  810. package/src/tickers/metadata.ts +10 -0
  811. package/src/tickers/perpetual-listing.ts +5 -2
  812. package/src/tickers/search/home-listing.ts +75 -0
  813. package/src/tickers/search/index.ts +76 -27
  814. package/src/tickers/search/ranking.ts +54 -4
  815. package/src/tickers/search/upsert.ts +29 -0
  816. package/src/tickers/terminal-codes.ts +416 -40
  817. package/src/time-series/bar-aggregation.ts +243 -0
  818. package/src/time-series/base-series.ts +307 -0
  819. package/src/time-series/chart-bounds.ts +349 -0
  820. package/src/time-series/chart-seed.ts +142 -0
  821. package/src/time-series/economic.ts +5 -0
  822. package/src/time-series/fundamentals.ts +18 -3
  823. package/src/time-series/history-acquisition.ts +499 -0
  824. package/src/time-series/leverage.ts +100 -0
  825. package/src/time-series/market-resolution.ts +4 -2
  826. package/src/time-series/market.ts +2 -1
  827. package/src/time-series/price-comparison.ts +175 -30
  828. package/src/time-series/range.ts +9 -1
  829. package/src/time-series/resolution.ts +174 -16
  830. package/src/time-series/resolve-context.ts +157 -0
  831. package/src/time-series/resolve.ts +126 -1577
  832. package/src/time-series/series-name.ts +38 -0
  833. package/src/time-series/series-presentation.ts +208 -0
  834. package/src/time-series/spec.ts +11 -6
  835. package/src/time-series/studies.ts +109 -12
  836. package/src/time-series/tail-reconcile.ts +121 -0
  837. package/src/time-series/types.ts +29 -2
  838. package/src/time-series/use-chart-resolution.ts +4 -5
  839. package/src/types/broker.ts +10 -0
  840. package/src/types/config.ts +14 -0
  841. package/src/types/data-provider.ts +14 -0
  842. package/src/types/exchange-rate.ts +6 -0
  843. package/src/types/financials.ts +104 -7
  844. package/src/types/headless.ts +76 -6
  845. package/src/types/instrument.ts +3 -0
  846. package/src/types/plugin.ts +65 -8
  847. package/src/types/price-history.ts +2 -0
  848. package/src/types/ticker.ts +13 -0
  849. package/src/types/trading.ts +59 -1
  850. package/src/ui/ascii-font.ts +13 -1
  851. package/src/ui/host.tsx +6 -1
  852. package/src/updater/command-names.ts +175 -0
  853. package/src/updater/index.ts +10 -5
  854. package/src/utils/calendar-date.ts +32 -15
  855. package/src/utils/cash-runway.ts +241 -0
  856. package/src/utils/central-banks.ts +42 -0
  857. package/src/utils/cli-output.ts +259 -80
  858. package/src/utils/contract-month.ts +16 -0
  859. package/src/utils/crypto-pair.ts +61 -3
  860. package/src/utils/currency-units.ts +29 -0
  861. package/src/utils/datetime-format.ts +10 -0
  862. package/src/utils/debug-log.ts +1 -1
  863. package/src/utils/decimal-comma.ts +39 -6
  864. package/src/utils/exchange-announcements.ts +71 -0
  865. package/src/utils/exchange-rate-snapshot.ts +10 -0
  866. package/src/utils/financial-statements.ts +83 -4
  867. package/src/utils/format.ts +34 -16
  868. package/src/utils/fundamentals.ts +150 -34
  869. package/src/utils/fx-market-hours.ts +10 -1
  870. package/src/utils/latest-financial-period.ts +8 -0
  871. package/src/utils/linux-libc.ts +54 -0
  872. package/src/utils/market-capitalization.ts +111 -15
  873. package/src/utils/max-drawdown.ts +64 -0
  874. package/src/utils/network-failure.ts +83 -0
  875. package/src/utils/option-expiry.ts +139 -7
  876. package/src/utils/price-earnings.ts +11 -5
  877. package/src/utils/price-history.ts +18 -8
  878. package/src/utils/price-window.ts +131 -0
  879. package/src/utils/release-date.ts +47 -0
  880. package/src/utils/sec.ts +3 -0
  881. package/src/utils/throttled-fetch.ts +11 -4
  882. package/src/utils/trailing-eps.ts +67 -0
  883. package/src/utils/typed-text.ts +21 -0
  884. package/src/utils/utc-time.ts +24 -1
  885. package/src/version.ts +6 -0
  886. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -0,0 +1,215 @@
1
+ import type { Portfolio } from "../../../types/ticker";
2
+ import type { BrokerAccount } from "../../../types/trading";
3
+ import { resolvePortfolioCash } from "../../../portfolio/allocation";
4
+ import { resolveCurrencyUnit } from "../../../utils/currency-units";
5
+ import { canonicalExchange, normalizeSymbol } from "../../../utils/exchanges";
6
+
7
+ /**
8
+ * The whole book beside the equity basket: the cash it holds by currency, and
9
+ * the stress shocks that reprice every line of it (holdings and cash) through
10
+ * its currency or its own price, rather than through a basket regression.
11
+ */
12
+
13
+ /** One currency of the cash a portfolio holds beside its positions. */
14
+ export interface RiskCashLine {
15
+ currency: string;
16
+ /** In `currency`; negative for a balance owed. */
17
+ amount: number;
18
+ }
19
+
20
+ const ISO_CURRENCY = /^[A-Z]{3}$/;
21
+
22
+ /**
23
+ * The portfolio's cash by currency: the broker account's own balances when it
24
+ * reports them per currency, else its total cash (in the portfolio's currency
25
+ * when the account names none), else the amount entered with `portfolio cash set`.
26
+ */
27
+ export function riskCashLines(
28
+ portfolio: Pick<Portfolio, "cash" | "currency">,
29
+ account: Pick<BrokerAccount, "cashBalances" | "totalCashValue" | "currency"> | null | undefined,
30
+ ): RiskCashLine[] {
31
+ const byCurrency = new Map<string, number>();
32
+ for (const balance of account?.cashBalances ?? []) {
33
+ const currency = balance.currency?.trim().toUpperCase() ?? "";
34
+ // A broker's summary row (IBKR's BASE) is no currency of its own.
35
+ if (!ISO_CURRENCY.test(currency) || !Number.isFinite(balance.quantity) || Math.abs(balance.quantity) < 1e-9) continue;
36
+ byCurrency.set(currency, (byCurrency.get(currency) ?? 0) + balance.quantity);
37
+ }
38
+ if (byCurrency.size) return [...byCurrency].map(([currency, amount]) => ({ currency, amount }));
39
+ const line = resolvePortfolioCash(portfolio, account);
40
+ const currency = (line?.currency.trim() || portfolio.currency || "").toUpperCase();
41
+ return line && ISO_CURRENCY.test(currency) && Number.isFinite(line.amount) && line.amount !== 0
42
+ ? [{ currency, amount: line.amount }]
43
+ : [];
44
+ }
45
+
46
+ /** A currency's move against USD, in percent of its USD value: TRY -20 is the lira 20% weaker. */
47
+ export interface RiskFxShift {
48
+ currency: string;
49
+ percent: number;
50
+ }
51
+ /** A holding's own price move, in percent, in its listing currency. */
52
+ export interface RiskAssetShift {
53
+ symbol: string;
54
+ exchange?: string;
55
+ percent: number;
56
+ }
57
+
58
+ /** The moves a shock takes, in percent: a fall to nothing is no scenario, a rise past six times is no stress. */
59
+ export const RISK_SHOCK_LIMITS = { minimum: -99, maximum: 500 } as const;
60
+
61
+ /** `-20%` and `+10%` as a shock names its move. */
62
+ const signedPercent = (percent: number) => `${percent > 0 ? "+" : ""}${percent}%`;
63
+
64
+ /** The commas that separate shocks: not a decimal comma between two digits (`TRY -2,5`). */
65
+ const SHOCK_SEPARATOR = /(?<!\d),|,(?!\d)/;
66
+
67
+ /** `TRY -20, EUR 5`: each item a name and a percent, or why one is not. */
68
+ function shockItems(text: string, flag: string, what: string, example: string): Array<{ name: string; percent: number }> {
69
+ const items = text.split(SHOCK_SEPARATOR).map((item) => item.trim()).filter(Boolean);
70
+ if (!items.length) throw new Error(`${flag} takes ${what} and a percent, such as ${example}.`);
71
+ return items.map((item) => {
72
+ const match = /^(\S+)\s+([-+]?\d+(?:[.,]\d+)?)\s*%?$/.exec(item);
73
+ if (!match) throw new Error(`${flag} takes ${what} and a percent, such as ${example}; got "${item}".`);
74
+ const percent = Number(match[2]!.replace(",", "."));
75
+ if (percent < RISK_SHOCK_LIMITS.minimum || percent > RISK_SHOCK_LIMITS.maximum)
76
+ throw new Error(`${flag} moves by ${RISK_SHOCK_LIMITS.minimum}% to +${RISK_SHOCK_LIMITS.maximum}%; got ${match[2]} for ${match[1]}.`);
77
+ return { name: match[1]!, percent };
78
+ });
79
+ }
80
+
81
+ /** `--fx-shift TRY -20, EUR 5`, read; throws naming what is wrong. */
82
+ export function parseFxShifts(text: string, flag = "--fx-shift"): RiskFxShift[] {
83
+ const shifts = shockItems(text, flag, "a currency", "TRY -20").map(({ name, percent }) => {
84
+ const currency = name.toUpperCase();
85
+ if (!ISO_CURRENCY.test(currency)) throw new Error(`${flag} takes a three-letter currency code such as TRY or EUR; got "${name}".`);
86
+ if (currency === "USD")
87
+ throw new Error(`${flag} moves a currency against USD, so USD itself does not shift: a stronger dollar is the other currency falling (TRY -20).`);
88
+ return { currency, percent };
89
+ });
90
+ const twice = shifts.find((shift, index) => shifts.findIndex((other) => other.currency === shift.currency) !== index);
91
+ if (twice) throw new Error(`${flag} names ${twice.currency} twice.`);
92
+ return shifts;
93
+ }
94
+
95
+ /** `--asset-shift GLD 10, BTC-USD -30`, read; throws naming what is wrong. */
96
+ export function parseAssetShifts(text: string, flag = "--asset-shift"): RiskAssetShift[] {
97
+ const shifts = shockItems(text, flag, "a holding", "GLD 10").map(({ name, percent }) => {
98
+ if (!/^[A-Za-z0-9^][A-Za-z0-9.=^&/-]{0,23}(?::[A-Za-z0-9.]{1,12})?$/.test(name))
99
+ throw new Error(`${flag} takes a holding's symbol, such as GLD or BTC-USD; got "${name}".`);
100
+ const [symbol, exchange] = name.toUpperCase().split(":");
101
+ return { symbol: symbol!, ...(exchange ? { exchange } : {}), percent };
102
+ });
103
+ const key = (shift: RiskAssetShift) => `${shift.symbol}:${shift.exchange ?? ""}`;
104
+ const twice = shifts.find((shift, index) => shifts.findIndex((other) => key(other) === key(shift)) !== index);
105
+ if (twice) throw new Error(`${flag} names ${twice.symbol} twice.`);
106
+ return shifts;
107
+ }
108
+
109
+ /** The canonical text of shocks, as an option keeps it (`TRY -20, EUR 5`). */
110
+ export function formatShocks(shifts: readonly (RiskFxShift | RiskAssetShift)[]): string {
111
+ return shifts.map((shift) => {
112
+ const name = "currency" in shift ? shift.currency : `${shift.symbol}${shift.exchange ? `:${shift.exchange}` : ""}`;
113
+ return `${name} ${shift.percent}`;
114
+ }).join(", ");
115
+ }
116
+
117
+ /** One line of the book to reprice: a holding or a currency's cash. */
118
+ export interface RiskBookLine {
119
+ id: string;
120
+ label: string;
121
+ /** The currency its value moves with against USD: a listing's own (GBP for pence), or the cash's. */
122
+ currency: string;
123
+ /** Signed value in the account currency; null when nothing values it. */
124
+ value: number | null;
125
+ /** The listing an asset shift names; null for cash. */
126
+ listing: { symbol: string; exchange: string } | null;
127
+ }
128
+ interface RiskRepricedLine {
129
+ id: string;
130
+ label: string;
131
+ /** The shocks that move it, as named: "TRY -20% vs USD", "BTC-USD -30%". */
132
+ shocks: string[];
133
+ before: number | null;
134
+ after: number | null;
135
+ change: number | null;
136
+ /** Change in percent of the line's own gross value. */
137
+ percent: number | null;
138
+ }
139
+ /** Every given shock applied at once, each line of the book repriced at its own currency and price. */
140
+ export interface RiskRepricing {
141
+ /** "TRY -20% vs USD, BTC-USD -30%". */
142
+ scenario: string;
143
+ /** Lines a shock moves, largest change first; lines without a value last. */
144
+ lines: RiskRepricedLine[];
145
+ /** The book's net value before the shocks, cash included, in the account currency. */
146
+ bookValue: number;
147
+ change: number;
148
+ /** Change in percent of `bookValue`; null when the book is worth nothing net. */
149
+ percent: number | null;
150
+ /** Lines a shock moves that have no value, so are not in the change. */
151
+ unvalued: string[];
152
+ /** Shocks nothing in the book moves with: a currency it holds nothing in, a holding it does not hold. */
153
+ unmatched: Array<{ kind: "currency" | "holding"; name: string }>;
154
+ }
155
+
156
+ const fxName = (shift: RiskFxShift) => `${shift.currency} ${signedPercent(shift.percent)} vs USD`;
157
+ const assetName = (shift: RiskAssetShift) => `${shift.symbol}${shift.exchange ? `:${shift.exchange}` : ""} ${signedPercent(shift.percent)}`;
158
+
159
+ /**
160
+ * Reprices every line of the book under the shocks at once. A line's value in
161
+ * the account currency is its USD value over the USD price of one account
162
+ * unit, so a currency's move changes it by (1 + its currency's move) and (for
163
+ * a listing a shock names) (1 + its own move), over (1 + the account
164
+ * currency's move): TRY -20 takes a fifth off lira cash in a USD account, and
165
+ * adds a quarter to a USD holding in a lira account. Null without a shock.
166
+ */
167
+ export function repriceBook(
168
+ lines: readonly RiskBookLine[],
169
+ accountCurrency: string,
170
+ fx: readonly RiskFxShift[] = [],
171
+ assets: readonly RiskAssetShift[] = [],
172
+ ): RiskRepricing | null {
173
+ if (!fx.length && !assets.length) return null;
174
+ const currencyOf = (currency: string) => resolveCurrencyUnit(currency).currency || "USD";
175
+ const account = currencyOf(accountCurrency);
176
+ const fxShift = new Map(fx.map((shift) => [shift.currency, shift]));
177
+ const matches = (shift: RiskAssetShift, line: RiskBookLine) =>
178
+ !!line.listing && normalizeSymbol(line.listing.symbol) === normalizeSymbol(shift.symbol)
179
+ && (!shift.exchange || canonicalExchange(line.listing.exchange) === canonicalExchange(shift.exchange));
180
+ const moved = new Set<string>();
181
+ const repriced = lines.flatMap((line): RiskRepricedLine[] => {
182
+ const own = currencyOf(line.currency);
183
+ const ownShift = own === account ? undefined : fxShift.get(own);
184
+ const accountShift = own === account ? undefined : fxShift.get(account);
185
+ const asset = assets.find((shift) => matches(shift, line));
186
+ const factor = (1 + (ownShift?.percent ?? 0) / 100) * (1 + (asset?.percent ?? 0) / 100) / (1 + (accountShift?.percent ?? 0) / 100);
187
+ if (Math.abs(factor - 1) < 1e-12) return [];
188
+ for (const shift of [ownShift, accountShift]) if (shift) moved.add(shift.currency);
189
+ if (asset) moved.add(assetName(asset));
190
+ const shocks = [...(ownShift ? [fxName(ownShift)] : []), ...(accountShift ? [fxName(accountShift)] : []), ...(asset ? [assetName(asset)] : [])];
191
+ if (line.value == null)
192
+ return [{ id: line.id, label: line.label, shocks, before: null, after: null, change: null, percent: null }];
193
+ const after = line.value * factor;
194
+ return [{
195
+ id: line.id, label: line.label, shocks, before: line.value, after, change: after - line.value,
196
+ percent: line.value === 0 ? 0 : ((after - line.value) / Math.abs(line.value)) * 100,
197
+ }];
198
+ }).sort((left, right) => (left.change == null ? 1 : 0) - (right.change == null ? 1 : 0)
199
+ || Math.abs(right.change ?? 0) - Math.abs(left.change ?? 0));
200
+ const bookValue = lines.reduce((sum, line) => sum + (line.value ?? 0), 0);
201
+ const change = repriced.reduce((sum, line) => sum + (line.change ?? 0), 0);
202
+ return {
203
+ scenario: [...fx.map(fxName), ...assets.map(assetName)].join(", "),
204
+ lines: repriced,
205
+ bookValue,
206
+ change,
207
+ percent: bookValue > 0 ? (change / bookValue) * 100 : null,
208
+ unvalued: repriced.filter((line) => line.change == null).map((line) => line.label),
209
+ unmatched: [
210
+ ...fx.filter((shift) => !moved.has(shift.currency)).map((shift) => ({ kind: "currency" as const, name: shift.currency })),
211
+ ...assets.filter((shift) => !moved.has(assetName(shift)))
212
+ .map((shift) => ({ kind: "holding" as const, name: `${shift.symbol}${shift.exchange ? `:${shift.exchange}` : ""}` })),
213
+ ],
214
+ };
215
+ }
@@ -68,7 +68,7 @@ export interface RiskMarketSnapshot {
68
68
  fetchedAt: string;
69
69
  warnings: string[];
70
70
  brokerOptions?: import("./risk-options").PortfolioOptionBook;
71
- /** USD per unit of the account currency and of each listing or position currency of the holdings, at load time. */
71
+ /** USD per unit of the account currency, of each listing or position currency of the holdings and of each currency of cash, at load time. */
72
72
  fxRates?: Record<string, number>;
73
73
  /** For an account not in USD: the daily closes its returns convert at, or why they cannot. */
74
74
  accountFx?: AccountFx;
@@ -321,7 +321,8 @@ const largestFirst = (
321
321
  * USD. Holdings with no FX pair, positions the caller marks unsupported and
322
322
  * holdings past the limit get no history request; their entry says why. An
323
323
  * account in another currency than USD also loads that currency's current
324
- * rate and daily FX history, which the model converts every return with. The
324
+ * rate and daily FX history, which the model converts every return with, and
325
+ * each currency of the book's cash its current rate, which values it. The
325
326
  * signal stops the fetch: no request starts once it
326
327
  * aborts, the ones in flight are cancelled, and the call rejects instead of
327
328
  * returning a partial snapshot nobody is waiting for.
@@ -332,6 +333,7 @@ export async function fetchPortfolioRiskMarket(
332
333
  now = new Date(),
333
334
  signal?: AbortSignal,
334
335
  accountCurrency = "USD",
336
+ cashCurrencies: readonly string[] = [],
335
337
  ): Promise<RiskMarketSnapshot> {
336
338
  signal?.throwIfAborted();
337
339
  const normalized = (row: RiskInstrument): RiskInstrument => ({
@@ -435,6 +437,9 @@ export async function fetchPortfolioRiskMarket(
435
437
  listings.get(row.id)?.currency ?? (quotes.has(row.id) ? null : row.request.currency),
436
438
  ).currency;
437
439
  return currency && currency !== "USD" ? [currency] : [];
440
+ }), ...cashCurrencies.flatMap((code) => {
441
+ const currency = resolveCurrencyUnit(code).currency;
442
+ return currency && currency !== "USD" ? [currency] : [];
438
443
  })],
439
444
  ),
440
445
  ].slice(0, MAX_FX_CURRENCIES);
@@ -663,23 +668,25 @@ export async function fetchPortfolioRiskMarket(
663
668
  * What changes the requests: identity, size, whether a holding can enter the
664
669
  * basket, and an account currency other than USD (whose daily FX the load adds).
665
670
  */
666
- const cacheKey = (holdings: readonly RiskHoldingRequest[], accountCurrency: string) =>
671
+ const cacheKey = (holdings: readonly RiskHoldingRequest[], accountCurrency: string, cashCurrencies: readonly string[]) =>
667
672
  [
668
673
  ...new Set(
669
674
  holdings.map(
670
675
  (row) => `${riskInstrumentId(row)}|${row.quantity ?? ""}|${row.currency ?? ""}|${row.unsupported ? 1 : 0}`,
671
676
  ),
672
677
  ),
673
- ].sort().join(",") + (accountCurrency === "USD" ? "" : `@${accountCurrency}`);
678
+ ].sort().join(",") + (accountCurrency === "USD" ? "" : `@${accountCurrency}`)
679
+ + (cashCurrencies.length ? `+${[...new Set(cashCurrencies)].sort().join(",")}` : "");
674
680
  export async function loadPortfolioRiskMarket(
675
681
  holdings: readonly RiskHoldingRequest[],
676
682
  force = false,
677
683
  accountCurrency = "USD",
684
+ cashCurrencies: readonly string[] = [],
678
685
  ) {
679
686
  const { payload, stale, refreshError } = await loadCloudResource(
680
687
  portfolioRiskCache,
681
- cacheKey(holdings, accountCurrency),
682
- () => fetchPortfolioRiskMarket(holdings, undefined, undefined, undefined, accountCurrency),
688
+ cacheKey(holdings, accountCurrency, cashCurrencies),
689
+ () => fetchPortfolioRiskMarket(holdings, undefined, undefined, undefined, accountCurrency, cashCurrencies),
683
690
  { force },
684
691
  );
685
692
  return {
@@ -3,15 +3,17 @@ import type { HeadlessPaneDefinition } from "../../../types/plugin";
3
3
  import { fetchPortfolioRiskMarket, RISK_HISTORY_LIMIT } from "./risk-client";
4
4
  import { parsePortfolioRiskEvidence } from "./risk-evidence";
5
5
  import { describeCollections } from "../../../portfolio/collection-name";
6
+ import { formatShocks, parseAssetShifts, parseFxShifts, riskCashLines } from "./risk-book";
6
7
  import {
7
8
  BASKET_VIEWS,
9
+ BOOK_TOTAL_ROW_ID,
8
10
  buildPortfolioRisk,
9
11
  portfolioRiskRequests,
10
12
  portfolioRiskTickers,
13
+ riskCoverageLine,
11
14
  riskCoverageNotices,
12
15
  riskCoverageShortfall,
13
- riskCoverageText,
14
- riskExclusionText,
16
+ riskHoldingsLeftOut,
15
17
  RISK_VIEWS,
16
18
  riskEvidence,
17
19
  riskPercentile,
@@ -53,16 +55,17 @@ const COMPACT_PAIR_LIMIT = 25;
53
55
 
54
56
  /**
55
57
  * Formatted like the pane; metadata.model keeps full precision. A tail loss in
56
- * money is of the covered basket, so its evidence names what the basket leaves
57
- * out, as the pane's footer does beside the same figure.
58
+ * money is of the covered basket, so its evidence names how it is estimated,
59
+ * the basket's share of the book and what it leaves out, as the pane's footer
60
+ * does beside the same figure.
58
61
  */
59
- function displayRow(row: RiskDisplayRow, exclusion: string | null) {
62
+ function displayRow(row: RiskDisplayRow) {
60
63
  return {
61
64
  label: row.label,
62
65
  value: riskValue(row),
63
66
  percentile: riskPercentile(row),
64
67
  asOf: row.asOf?.slice(0, 10) ?? null,
65
- detail: exclusion && row.amount != null ? `${riskEvidence(row)}; ${exclusion}` : riskEvidence(row),
68
+ detail: riskEvidence(row),
66
69
  ...(row.amount != null ? { amount: row.amount, currency: row.amountCurrency ?? null } : {}),
67
70
  };
68
71
  }
@@ -77,19 +80,22 @@ const COMPACT_LEFT_OUT_LIMIT = 40;
77
80
  /** What the basket views cover, so a report never reads as the whole account when it is not. */
78
81
  function coverageSummary(coverage: RiskCoverage, limit = Infinity) {
79
82
  return {
83
+ // Of the book, cash included; the minimum is of the holdings' value.
80
84
  share: coverage.share,
81
85
  shareIsUpperBound: coverage.unvalued > 0,
86
+ holdingsShare: coverage.holdingsShare ?? coverage.share,
82
87
  minimumShare: coverage.minimumShare,
83
88
  estimated: coverage.sufficient,
84
89
  currency: coverage.currency,
85
90
  marketValue: coverage.marketValue,
91
+ cashValue: coverage.cashValue ?? 0,
86
92
  coveredValue: coverage.coveredValue,
87
93
  holdings: coverage.holdings,
88
94
  covered: coverage.covered,
89
95
  convertedFromLocalCurrency: coverage.converted,
90
96
  leftOut: coverage.leftOut
91
97
  .slice(0, limit)
92
- .map((row) => ({ symbol: row.symbol, reason: row.reason, share: row.share })),
98
+ .map((row) => ({ symbol: row.symbol, reason: row.reason, share: row.share, ...(row.cash ? { cash: true } : {}) })),
93
99
  ...(coverage.leftOut.length > limit ? { moreLeftOut: coverage.leftOut.length - limit } : {}),
94
100
  };
95
101
  }
@@ -99,9 +105,8 @@ function coverageLine(coverage: RiskCoverage | undefined): { error?: string; not
99
105
  const shortfall = riskCoverageShortfall(coverage);
100
106
  // No estimate at all is a failure; an estimate that leaves holdings out is a caveat.
101
107
  if (shortfall) return { error: `Basket estimates unavailable: ${shortfall.title} ${shortfall.message}`.trim() };
102
- return coverage?.leftOut.length
103
- ? { note: `Basket ${riskCoverageText(coverage)}; metadata.coverage lists each with its reason.` }
104
- : {};
108
+ const line = coverage?.leftOut.length ? riskCoverageLine(coverage) : null;
109
+ return line ? { note: `${line[0]!.toUpperCase()}${line.slice(1)}; metadata.coverage lists each with its reason.` } : {};
105
110
  }
106
111
 
107
112
  /** One view, its strongest or first rows, and the portfolio's totals instead of the model. */
@@ -120,15 +125,18 @@ function compactRiskRows(model: PortfolioRiskModel, view: RiskView): { rows: Ris
120
125
  };
121
126
  }
122
127
  if (all.length <= COMPACT_ROW_LIMIT) return { rows: all, notices: [] };
128
+ // The book's total of the shocks is what they come to: the lines go before it does.
129
+ const total = all.filter((row) => row.id === BOOK_TOTAL_ROW_ID);
130
+ const rows = [...all.filter((row) => row.id !== BOOK_TOTAL_ROW_ID).slice(0, COMPACT_ROW_LIMIT - total.length), ...total];
123
131
  return {
124
- rows: all.slice(0, COMPACT_ROW_LIMIT),
125
- notices: [`${all.length - COMPACT_ROW_LIMIT} more ${view} rows not shown.`],
132
+ rows,
133
+ notices: [`${all.length - rows.length} more ${view} rows not shown.`],
126
134
  };
127
135
  }
128
136
 
129
137
  export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
130
138
  shape: "bundle",
131
- freshness: { source: "Local portfolio and Gloom Cloud", status: "not-a-feed", basis: "risk model on daily closes" },
139
+ freshness: { source: "Local portfolio and Gloom Cloud", status: "not-a-feed", basis: "daily closes" },
132
140
  argument: {
133
141
  kind: "free-text",
134
142
  optional: true,
@@ -143,8 +151,9 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
143
151
  "Explicit local evidence for account returns and attribution",
144
152
  ],
145
153
  limitations: [
146
- `Fixed-current-weight equity basket over the holdings that qualify, largest ${RISK_HISTORY_LIMIT} by value, in the account's currency; foreign listings convert to USD at daily FX closes, and a non-USD account's returns then convert into its currency at its own daily FX closes; metadata.coverage states the covered share of market value and each holding left out.`,
154
+ `Fixed-current-weight equity basket over the holdings that qualify, largest ${RISK_HISTORY_LIMIT} by value, in the account's currency; foreign listings convert to USD at daily FX closes, and a non-USD account's returns then convert into its currency at its own daily FX closes; metadata.coverage states the covered share of the book (cash included) and each holding and currency's cash left out.`,
147
155
  "--since filed buys the 13F's own weights at the filing-date close and holds them (--weights current holds today's weights fixed instead).",
156
+ "--fx-shift and --asset-shift reprice every holding and the cash at once; the index, 10Y and VIX shifts are separate basket regressions.",
148
157
  "No account performance inferred.",
149
158
  "ETF price-return factor proxies.",
150
159
  "Historical percentiles need 20 rolling samples.",
@@ -204,6 +213,27 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
204
213
  maximum: 100,
205
214
  description: "Independent VIX shock in index points (10 when left out).",
206
215
  },
216
+ {
217
+ key: "fx-shift",
218
+ type: "string",
219
+ settingKey: "fxShift",
220
+ valueWords: 2,
221
+ placeholder: "CCY pct",
222
+ example: "--fx-shift TRY -20",
223
+ // "TRY -20" read as the lira's move against USD, not USD's against the lira.
224
+ description: "A currency's move against USD in percent: TRY -20 is the lira 20% weaker. Reprices every holding and the cash in that currency, and in a lira account every other line against it. Several separated by commas: TRY -20, EUR 5.",
225
+ normalize: (value) => formatShocks(parseFxShifts(value)),
226
+ },
227
+ {
228
+ key: "asset-shift",
229
+ type: "string",
230
+ settingKey: "assetShift",
231
+ valueWords: 2,
232
+ placeholder: "SYMBOL pct",
233
+ example: "--asset-shift BTC-USD -30",
234
+ description: "A holding's own price move in percent, in its listing currency: GLD 10, BTC-USD -30. Applied with --fx-shift as one scenario. Several separated by commas.",
235
+ normalize: (value) => formatShocks(parseAssetShifts(value)),
236
+ },
207
237
  ],
208
238
  // The portfolio as configured, so `Family`, `family` and `FAMILY` head the report alike.
209
239
  describe: (args, result) =>
@@ -217,6 +247,8 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
217
247
  if (!local) throw new Error(unknownPortfolio(requested, ctx.config.portfolios));
218
248
  const id = local.portfolio.id;
219
249
  const tickers = portfolioRiskTickers(local.tickers, id);
250
+ // The cash beside the holdings: the broker account's by currency, else the portfolio's own.
251
+ const cash = riskCashLines(local.portfolio, local.account);
220
252
  const evidence = parsePortfolioRiskEvidence(
221
253
  String(args.options.evidence ?? ctx.settings?.riskEvidence ?? ""),
222
254
  );
@@ -248,6 +280,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
248
280
  new Date(),
249
281
  ctx.signal,
250
282
  local.portfolio.currency,
283
+ cash.map((line) => line.currency),
251
284
  ),
252
285
  localOnly
253
286
  ? Promise.resolve(undefined)
@@ -264,14 +297,17 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
264
297
  equity: Number(args.options["equity-shift"] ?? -10),
265
298
  rates: Number(args.options["rate-shift"] ?? 100),
266
299
  volatility: Number(args.options["vol-shift"] ?? 10),
300
+ fx: args.options["fx-shift"] ? parseFxShifts(String(args.options["fx-shift"])) : [],
301
+ assets: args.options["asset-shift"] ? parseAssetShifts(String(args.options["asset-shift"])) : [],
267
302
  },
268
303
  args.options.since === "filed"
269
304
  ? { since: "filed", weights: args.options.weights === "current" ? "current" : "13f" }
270
305
  : {},
306
+ cash,
271
307
  );
272
308
  // Options for views the report does not print are named, not dropped silently; the fallback from --since opens the report.
273
309
  const fallback = sinceFallbackNote(local.portfolio);
274
- const shifted = ["equity-shift", "rate-shift", "vol-shift"].filter((key) => args.options[key] != null);
310
+ const shifted = ["equity-shift", "rate-shift", "vol-shift", "fx-shift", "asset-shift"].filter((key) => args.options[key] != null);
275
311
  // A non-USD account's returns were converted, and the basket views say into what.
276
312
  const returnsCurrency = riskReturnsCurrency(model);
277
313
  const notices = [
@@ -284,8 +320,8 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
284
320
  ...(requestedView && args.options.since != null && requestedView !== "risk" ? [`--since changes the risk view only, not --view ${requestedView}`] : []),
285
321
  ...(args.options.weights != null && args.options.since !== "filed" ? ["--weights applies with --since filed only"] : []),
286
322
  ];
287
- // A basket view is complete only when the basket covers every holding.
288
- const covered = model.coverage.leftOut.length === 0;
323
+ // A basket view is complete only when the basket covers every holding; cash is never in it.
324
+ const covered = !riskHoldingsLeftOut(model.coverage);
289
325
  const complete =
290
326
  view === "performance"
291
327
  ? model.performance != null
@@ -300,7 +336,6 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
300
336
  : model.complete;
301
337
  // A basket view with too little covered shows no estimate, and the report says why rather than leaving dashes.
302
338
  const shortfall = BASKET_VIEWS.has(view as RiskView) ? coverageLine(model.coverage).error : undefined;
303
- const exclusion = riskExclusionText(model.coverage);
304
339
  return {
305
340
  complete,
306
341
  errors: [...(shortfall ? [shortfall] : []), ...model.warnings],
@@ -308,7 +343,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
308
343
  sections: (requestedView ? [requestedView] : RISK_VIEWS).map((view) => ({
309
344
  title: view,
310
345
  columns: RISK_COLUMNS,
311
- rows: model.rows[view].map((row) => displayRow(row, exclusion)),
346
+ rows: model.rows[view].map(displayRow),
312
347
  })),
313
348
  metadata: { coverage: coverageSummary(model.coverage), model, benchmark: model.benchmark, window: model.window, notices },
314
349
  };
@@ -321,7 +356,6 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
321
356
  // Each left-out holding is in metadata.coverage; the notes keep one line for all of them.
322
357
  const perHolding = new Set(riskCoverageNotices(model.coverage));
323
358
  const basketView = BASKET_VIEWS.has(view);
324
- const exclusion = riskExclusionText(model.coverage);
325
359
  const coverage = basketView ? coverageLine(model.coverage) : {};
326
360
  const errors = [...new Set([...(coverage.error ? [coverage.error] : []), ...(result.errors ?? [])])];
327
361
  const notes = [...(coverage.note ? [coverage.note] : []), ...(result.notes ?? []).filter((note) => !perHolding.has(note))];
@@ -329,7 +363,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
329
363
  complete: result.complete,
330
364
  ...(errors.length ? { errors } : {}),
331
365
  ...(notes.length ? { notes } : {}),
332
- sections: [{ title: view, columns: RISK_COLUMNS, rows: rows.map((row) => displayRow(row, exclusion)) }],
366
+ sections: [{ title: view, columns: RISK_COLUMNS, rows: rows.map(displayRow) }],
333
367
  metadata: {
334
368
  portfolio: {
335
369
  id: model.portfolio.id,
@@ -46,13 +46,16 @@ function sampleVolatility(values: readonly number[]): number | null {
46
46
  ) * Math.sqrt(252)
47
47
  );
48
48
  }
49
+ /** The confidence of the one-day VaR and expected shortfall, and the fewest daily returns they are read from. */
50
+ export const RISK_TAIL_CONFIDENCE = 0.95;
51
+ export const RISK_TAIL_MINIMUM = 60;
49
52
  /** Nearest-rank historical loss, without distribution or square-root horizon assumptions. */
50
53
  export function historicalTail(
51
54
  values: readonly number[],
52
- confidence = 0.95,
55
+ confidence = RISK_TAIL_CONFIDENCE,
53
56
  ): { var: number; expectedShortfall: number } | null {
54
57
  if (
55
- values.length < 60 ||
58
+ values.length < RISK_TAIL_MINIMUM ||
56
59
  confidence <= 0 ||
57
60
  confidence >= 1 ||
58
61
  values.some((value) => !Number.isFinite(value))
@@ -225,7 +228,7 @@ function basketRiskDefinitions(benchmark: string) {
225
228
  },
226
229
  {
227
230
  id: "var",
228
- name: "1D VaR 95%",
231
+ name: `1D VaR ${Math.round(RISK_TAIL_CONFIDENCE * 100)}%`,
229
232
  value: (rows: RiskSamplePoint[]) => {
230
233
  const tail = historicalTail(rows.map((row) => row.value));
231
234
  return tail == null ? null : 100 * tail.var;