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
@@ -0,0 +1,142 @@
1
+ import { logFailure } from "../../../utils/log-failure";
2
+ import type { ChartSeriesSpec, ChartSpec, ChartStudySpec } from "../../../time-series/types";
3
+ import { isLeverageFactor } from "../../../time-series/leverage";
4
+ import { priceComparisonSeriesIds } from "../../../time-series/price-comparison";
5
+ import { isUsListingExchange, parsePublicTickerKey } from "../../../utils/exchanges";
6
+ import { MAX_CHART_COMPOSER_SERIES } from "./chart-spec";
7
+ import { buildSeriesSpec, reconcilePanels } from "./chart-spec-edit";
8
+ import { normalizeInstrument } from "./series-expression";
9
+
10
+ /** A fund's daily objective as CMP draws it: `factor` times the index fund `proxy` each session. */
11
+ export interface DailyObjective {
12
+ factor: number;
13
+ proxy: string;
14
+ }
15
+
16
+ /** What CMP needs of a fund's facts: a daily objective with an index fund to draw it from. */
17
+ export interface LeverageFacts {
18
+ leverage?: { value: number; reset: string; proxy: { ticker: string } | null } | null;
19
+ }
20
+
21
+ export function dailyObjective(facts: LeverageFacts | null | undefined): DailyObjective | null {
22
+ const leverage = facts?.leverage;
23
+ if (!leverage || leverage.reset !== "daily" || !isLeverageFactor(leverage.value) || !leverage.proxy?.ticker) return null;
24
+ return { factor: leverage.value, proxy: leverage.proxy.ticker.toUpperCase() };
25
+ }
26
+
27
+ const LEVERAGE_STUDY_PREFIX = "leverage:";
28
+ const DECAY_STUDY_PREFIX = "leverage-decay:";
29
+
30
+ /** The bare ticker a compared leg is of (`TQQQ` for TQQQ:NASDAQ). */
31
+ function legTicker(series: ChartSeriesSpec): string | null {
32
+ return series.source.kind === "security" ? parsePublicTickerKey(series.source.instrument.symbol).symbol.toUpperCase() : null;
33
+ }
34
+
35
+ /** A ticker the fund facts read: US-listed, as its symbol is written there (SPY, BRK.B). */
36
+ const US_FUND_TICKER = /^[A-Z][A-Z0-9]{0,5}(?:\.[A-Z])?$/;
37
+
38
+ /** The US-listed tickers of a price comparison, whose facts can say they are leveraged funds. */
39
+ export function comparedFundTickers(spec: ChartSpec): string[] {
40
+ const compared = new Set(priceComparisonSeriesIds(spec) ?? []);
41
+ return [...new Set(spec.series.flatMap((series) => {
42
+ if (!compared.has(series.id) || series.source.kind !== "security") return [];
43
+ const exchange = series.source.instrument.exchange || parsePublicTickerKey(series.source.instrument.symbol).exchange;
44
+ const ticker = legTicker(series);
45
+ return ticker && US_FUND_TICKER.test(ticker) && (!exchange || isUsListingExchange(exchange)) ? [ticker] : [];
46
+ }))];
47
+ }
48
+
49
+ /** Whether the chart already draws a fund's objective, as built here or kept from before. */
50
+ function hasLeverageOverlay(spec: ChartSpec): boolean {
51
+ return spec.studies.some((study) => study.kind === "leverage" || study.kind === "leverage-decay");
52
+ }
53
+
54
+ /**
55
+ * Whether a report of this chart could draw a daily objective at all: a
56
+ * price comparison without one yet, over daily bars. One session's chart, or
57
+ * bars asked for by the week, month or hour, would only warn that the line
58
+ * needs daily bars, so its legs' facts are not asked for.
59
+ */
60
+ export function mayDrawDailyObjective(spec: ChartSpec): boolean {
61
+ if (hasLeverageOverlay(spec) || !priceComparisonSeriesIds(spec)) return false;
62
+ if (spec.viewport.range === "1D" && !spec.viewport.dateWindow) return false;
63
+ return spec.viewport.resolution === "auto" || spec.viewport.resolution === "1d";
64
+ }
65
+
66
+ /**
67
+ * A price comparison with each leveraged or inverse fund's daily objective
68
+ * drawn beside it: `factor` times its index fund each session, compounded
69
+ * from where the chart compares (3× daily QQQ beside TQQQ), with the index
70
+ * fund added as a leg when the chart has no room for it otherwise, and the
71
+ * fund's decay against that line and against the factor times the index
72
+ * fund's period return in a Decay panel. Any other chart, or a chart that
73
+ * already draws an objective, is returned as it was.
74
+ */
75
+ export function withLeverageOverlay(spec: ChartSpec, objectives: ReadonlyMap<string, DailyObjective>): ChartSpec {
76
+ const compared = priceComparisonSeriesIds(spec);
77
+ if (!compared || hasLeverageOverlay(spec) || objectives.size === 0) return spec;
78
+ const series = [...spec.series];
79
+ const studies: ChartStudySpec[] = [...spec.studies];
80
+ for (const fund of spec.series.filter((entry) => compared.includes(entry.id))) {
81
+ const objective = objectives.get(legTicker(fund) ?? "");
82
+ if (!objective || fund.source.kind !== "security") continue;
83
+ // A compared leg of the index fund, or the one added for another fund (TQQQ and SQQQ share QQQ).
84
+ let index = series.find((entry) => legTicker(entry) === objective.proxy && (compared.includes(entry.id) || !spec.series.includes(entry)));
85
+ if (!index) {
86
+ const instrument = normalizeInstrument(objective.proxy, true);
87
+ if (!instrument || series.length >= MAX_CHART_COMPOSER_SERIES) continue;
88
+ index = buildSeriesSpec({ kind: "security", ...instrument, fieldId: fund.source.fieldId }, series.length, {
89
+ style: fund.style, transform: fund.transform, axis: fund.axis, panelId: fund.panelId,
90
+ });
91
+ series.push(index);
92
+ }
93
+ const parameters = { factor: objective.factor };
94
+ studies.push(
95
+ { id: `${LEVERAGE_STUDY_PREFIX}${fund.id}`, kind: "leverage", inputSeriesIds: [index.id], parameters, panelId: fund.panelId, axis: "left" },
96
+ { id: `${DECAY_STUDY_PREFIX}${fund.id}`, kind: "leverage-decay", inputSeriesIds: [fund.id, index.id], parameters, panelId: "decay", axis: "auto" },
97
+ );
98
+ }
99
+ if (studies.length === spec.studies.length) return spec;
100
+ return { ...spec, series, studies, panels: reconcilePanels(spec.panels, series, studies) };
101
+ }
102
+
103
+ /** How long a comparison waits for its legs' fund facts before it is charted without objectives. */
104
+ const DAILY_OBJECTIVES_TIMEOUT_MS = 2_500;
105
+ /** A pane draws its chart meanwhile and adds the objectives when they come. */
106
+ export const LEVERAGE_FACTS_PANE_TIMEOUT_MS = 15_000;
107
+
108
+ /**
109
+ * Each compared fund's daily objective, from its facts. A fund whose facts
110
+ * fail to load, or are not in by `timeoutMs`, is charted without one: the
111
+ * comparison never waits long on them. The reads still running then are
112
+ * aborted through the signal `loadFacts` is given, as they are when `signal`
113
+ * (the caller's) aborts.
114
+ */
115
+ export async function loadDailyObjectives(
116
+ tickers: readonly string[],
117
+ loadFacts: (ticker: string, signal: AbortSignal) => Promise<LeverageFacts | null>,
118
+ { timeoutMs = DAILY_OBJECTIVES_TIMEOUT_MS, signal }: { timeoutMs?: number; signal?: AbortSignal } = {},
119
+ ): Promise<Map<string, DailyObjective>> {
120
+ const objectives = new Map<string, DailyObjective>();
121
+ if (tickers.length === 0) return objectives;
122
+ const deadline = new AbortController();
123
+ const expired = new Promise<null>((resolve) => deadline.signal.addEventListener("abort", () => resolve(null), { once: true }));
124
+ const timer = setTimeout(() => deadline.abort(new DOMException("Fund facts took too long.", "TimeoutError")), timeoutMs);
125
+ const cancel = () => deadline.abort(signal?.reason);
126
+ if (signal?.aborted) cancel();
127
+ else signal?.addEventListener("abort", cancel, { once: true });
128
+ try {
129
+ await Promise.all(tickers.map(async (ticker) => {
130
+ const facts = await Promise.race([loadFacts(ticker, deadline.signal).catch(logFailure("chart-composer.leverage-overlay", "Load chart fund objective failed", null)), expired]);
131
+ const objective = dailyObjective(facts);
132
+ // An index fund charted beside its leveraged fund is not leveraged itself.
133
+ if (objective && objective.proxy !== ticker) objectives.set(ticker, objective);
134
+ }));
135
+ } finally {
136
+ clearTimeout(timer);
137
+ signal?.removeEventListener("abort", cancel);
138
+ // Reads still running are no longer waited for.
139
+ deadline.abort();
140
+ }
141
+ return objectives;
142
+ }
@@ -1,3 +1,4 @@
1
+ import { logFailure } from "../../../utils/log-failure";
1
2
  import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../../../utils/financial-statements";
2
3
  import { usePaneSharePreparation } from "../../../shares/prepare";
3
4
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -26,10 +27,13 @@ import type { PaneProps, TickerResearchTabProps } from "../../../types/plugin";
26
27
  import type { ChartResolution, TimeRange } from "../../../components/chart/core/types";
27
28
  import type { ChartSpec, ResolvedSeries } from "../../../time-series/types";
28
29
  import {
29
- getSupportedChartResolutionsForViewport,
30
+ getSupportedChartBarSizesForViewport,
30
31
  isIntradayResolution,
32
+ parseChartBarSize,
33
+ type ChartBarSize,
31
34
  type ManualChartResolution,
32
35
  } from "../../../time-series/resolution";
36
+ import { futuresSessionOpenMinute } from "../../../market-data/market/trading-sessions";
33
37
  import { useResolvedChartSpec } from "../../../time-series/hooks";
34
38
  import { shortCompanyName } from "../../../tickers/company-name";
35
39
  import { useSeriesListings } from "./series-listings";
@@ -50,15 +54,19 @@ import {
50
54
  } from "../../../state/app/context";
51
55
  import { colors } from "../../../theme/colors";
52
56
  import { isUsListingExchange, parsePublicTickerKey, publicTickerKey } from "../../../utils/exchanges";
53
- import { isMarketFieldId } from "../../../time-series/field-catalog";
57
+ import { getTimeSeriesField, isMarketFieldId } from "../../../time-series/field-catalog";
54
58
  import { isDatasetChart } from "../../../time-series/spec";
59
+ import { seriesMessageName, studyMessageName } from "../../../time-series/series-name";
55
60
  import { CHART_COMPOSER_PANE_ID } from "../../../types/config";
56
61
  import { useRemoteUiNode } from "../../../remote/semantic-tree";
57
62
  import { SeriesEditorDialog } from "./editor";
58
63
  import { chartComposerSemanticMetadata } from "./semantic";
64
+ import { comparedFundTickers, LEVERAGE_FACTS_PANE_TIMEOUT_MS, loadDailyObjectives, withLeverageOverlay } from "./leverage-overlay";
65
+ import { loadFundFacts } from "../sec/fund-facts";
59
66
  import {
60
67
  canToggleChartSeries,
61
68
  CHART_INTERACTION_VIEWPORT_SETTING_KEY,
69
+ CHART_LEVERAGE_PENDING_SETTING_KEY,
62
70
  CHART_PINNED_MOMENT_SETTING_KEY,
63
71
  CHART_SPEC_SETTING_KEY,
64
72
  parseChartInteractionViewport,
@@ -106,11 +114,13 @@ import { buildEmptyChartPreset, buildPriceChartPreset } from "./presets";
106
114
  import type { ChartInteractionViewport } from "./chart-spec";
107
115
  import {
108
116
  CHART_FORMULA_OPTIONS,
117
+ CHART_BAR_SIZE_PRESETS,
109
118
  CHART_RANGES as RANGES,
110
- CHART_RESOLUTIONS as RESOLUTIONS,
119
+ CHART_RESOLUTIONS,
111
120
  chartStudyOptionsFor,
112
121
  chartStudyPeriodTitle,
113
122
  chartStudySettingLabel,
123
+ withChartBarSize,
114
124
  } from "./settings";
115
125
  import { resolveChartComposerShortcut } from "./shortcuts";
116
126
  import { describeChartResolution, formatChartDateWindow, formatChartResolution } from "./viewport-labels";
@@ -134,6 +144,9 @@ import { CHART_FOLLOW_SERIES_SETTING_KEY, rebindFollowChartSpec, resolveFollowSe
134
144
  import type { InstrumentRef } from "../../../market-data/request-types";
135
145
 
136
146
  const RANGE_OPTIONS = RANGES.map((range, index) => ({ label: range, value: range, hint: String(index + 1) }));
147
+ const SOURCE_BAR_SIZES = CHART_RESOLUTIONS.filter((value): value is ManualChartResolution => value !== "auto");
148
+ /** The bar size dialog's last choice, which asks for a size to type. */
149
+ const CUSTOM_BAR_SIZE_CHOICE = "custom";
137
150
  const AUTO_VIEWPORT_DEBOUNCE_MS = 350;
138
151
  /** A load for a moving view that has not answered in this long no longer holds the next one back. */
139
152
  const LOAD_AHEAD_TIMEOUT_MS = 4_000;
@@ -379,28 +392,46 @@ function ChartComposerSurface({
379
392
  const hasMarketSeries = spec.series.some((entry) => (
380
393
  entry.source.kind === "security" && isMarketFieldId(entry.source.fieldId)
381
394
  ));
382
- const availableResolutions = useMemo<ChartResolution[]>(() => {
395
+ // Bars built from a future's clock-aligned bars must not straddle its session's open.
396
+ const openMinute = useMemo(() => {
397
+ const listing = spec.series.find((entry) => entry.source.kind === "security" && isMarketFieldId(entry.source.fieldId));
398
+ return listing?.source.kind === "security" ? futuresSessionOpenMinute(listing.source.instrument.symbol, listing.source.instrument.exchange) : null;
399
+ }, [spec.series]);
400
+ // The sizes of `sizes` this chart can draw now, after Auto.
401
+ const availableOf = useCallback((sizes: readonly ChartBarSize[]): ChartResolution[] => {
383
402
  if (!resolution.resolutionSupport) {
384
403
  if (!hasMarketSeries) return ["auto"];
385
- if (!resolution.loading) return RESOLUTIONS;
404
+ if (!resolution.loading) return ["auto", ...sizes];
386
405
  return spec.viewport.resolution === "auto"
387
406
  ? ["auto"]
388
407
  : ["auto", spec.viewport.resolution];
389
408
  }
390
- const supported = new Set(getSupportedChartResolutionsForViewport(
409
+ return ["auto", ...getSupportedChartBarSizesForViewport(
391
410
  spec.viewport.range,
392
411
  resolution.resolutionSupport,
412
+ sizes,
393
413
  spec.viewport.dateWindow,
394
- ));
395
- return RESOLUTIONS.filter((value) => value === "auto" || supported.has(value));
414
+ openMinute,
415
+ )];
396
416
  }, [
397
417
  hasMarketSeries,
418
+ openMinute,
398
419
  resolution.loading,
399
420
  resolution.resolutionSupport,
400
421
  spec.viewport.dateWindow,
401
422
  spec.viewport.range,
402
423
  spec.viewport.resolution,
403
424
  ]);
425
+ // The bar lists the sizes sources serve, and a built one (4h) while the chart is set to it;
426
+ // the bar size dialog (b) lists the built ones too, and takes any other typed in.
427
+ const availableResolutions = useMemo(
428
+ () => availableOf(withChartBarSize(SOURCE_BAR_SIZES, spec.viewport.resolution)),
429
+ [availableOf, spec.viewport.resolution],
430
+ );
431
+ const dialogResolutions = useMemo(
432
+ () => availableOf(withChartBarSize(CHART_BAR_SIZE_PRESETS, spec.viewport.resolution)),
433
+ [availableOf, spec.viewport.resolution],
434
+ );
404
435
  // Auto names the bars it is on, which change as the view moves: a pan back
405
436
  // past where a source keeps 30-minute bars charts days instead.
406
437
  const autoBars = spec.viewport.resolution === "auto" ? resolution.resolution ?? null : null;
@@ -415,6 +446,14 @@ function ChartComposerSurface({
415
446
  const selectedPairStudies = getSelectedPairStudies(spec);
416
447
  const viewport = resolution.viewport;
417
448
  const baseSeriesIds = useMemo(() => new Set(spec.series.map((series) => series.id)), [spec.series]);
449
+ const rangeStatisticsSeriesId = spec.series.length === 1
450
+ && spec.series[0]!.source.kind === "security"
451
+ && spec.series[0]!.source.fieldId.startsWith("valuation.")
452
+ && spec.series[0]!.source.period === "daily"
453
+ && resolution.series.find(series => series.id === spec.series[0]!.id)?.nativeFrequency === "daily"
454
+ && spec.series[0]!.transform === "raw"
455
+ && spec.series[0]!.visible !== false
456
+ ? spec.series[0]!.id : undefined;
418
457
  // Hidden series are never loaded, so the resolver has nothing to report for
419
458
  // them. Without a placeholder they vanish from the legend entirely and the
420
459
  // only way back is the series dialog.
@@ -422,6 +461,12 @@ function ChartComposerSurface({
422
461
  // Each security series names its company once, beside its label: "AAPL Price · Apple".
423
462
  const named = new Set<string>();
424
463
  const resolved = (resolution.legendSeries ?? []).map((entry) => {
464
+ const authored = spec.series.find((series) => series.id === entry.id);
465
+ if (authored?.source.kind === "security" && authored.source.fieldId.startsWith("valuation.")) {
466
+ const field = getTimeSeriesField(authored.source.fieldId);
467
+ return { ...entry, label: authored.label?.trim()
468
+ || `${authored.source.instrument.symbol} ${field?.shortLabel ?? "Multiple"}` };
469
+ }
425
470
  const name = nameSeries ? listings.names.get(entry.id) : undefined;
426
471
  const company = name ? shortCompanyName(name) : "";
427
472
  if (!company || named.has(company)) return entry;
@@ -430,7 +475,7 @@ function ChartComposerSurface({
430
475
  });
431
476
  const resolvedIds = new Set(resolved.map((entry) => entry.id));
432
477
  const missing = spec.series.filter((entry) => !resolvedIds.has(entry.id));
433
- if (missing.length === 0) return named.size > 0 ? resolved : resolution.legendSeries;
478
+ if (missing.length === 0) return resolved;
434
479
  const bySpecOrder = new Map(spec.series.map((entry, index) => [entry.id, index] as const));
435
480
  return [
436
481
  ...resolved,
@@ -474,7 +519,15 @@ function ChartComposerSurface({
474
519
  () => listingRef.current,
475
520
  [freshListing?.seriesId, freshListing?.key, freshListing?.target.symbol, freshListing?.target.exchange],
476
521
  );
522
+ // The ticket's levels (its draft and working orders) move through the ticket, which reviews any change.
523
+ const tradeRef = useRef(trade);
524
+ tradeRef.current = trade;
477
525
  const editLevels = useCallback((edit: CompositeLevelEdit) => {
526
+ const ticket = tradeRef.current;
527
+ if (ticket?.levels.some((level) => level.id === edit.id)) {
528
+ if (edit.kind === "move") ticket.moveLevel?.(edit.id, edit.value);
529
+ return;
530
+ }
478
531
  const key = listingRef.current?.key;
479
532
  if (!key) return;
480
533
  setLevelStore((current: unknown) => {
@@ -578,7 +631,7 @@ function ChartComposerSurface({
578
631
  ]}
579
632
  />
580
633
  ),
581
- }).catch(() => undefined);
634
+ }).catch(logFailure("chart-composer.pane", "Open VWAP anchor choices failed"));
582
635
  if (choice === "pick") {
583
636
  pickAnchorAfterDialogRef.current = true;
584
637
  return { close: true };
@@ -594,7 +647,7 @@ function ChartComposerSurface({
594
647
  content: (ctx: PromptContext<string>) => (
595
648
  <TextPromptDialog {...ctx} title="Anchor VWAP at" placeholder="2026-09-30 or 2026-09-30 10:00" confirmLabel="Anchor" width={44} />
596
649
  ),
597
- }).catch(() => undefined);
650
+ }).catch(logFailure("chart-composer.pane", "Open VWAP date prompt failed"));
598
651
  if (!text) return;
599
652
  const anchor = parseVwapAnchor(text, anchorInputRef.current);
600
653
  if (anchor === null) {
@@ -661,6 +714,11 @@ function ChartComposerSurface({
661
714
  },
662
715
  onCancel: () => setPickingAnchor(false),
663
716
  } : null, [pickingAnchor, updateSpec]);
717
+ // The ticket beside the chart asks for a price: a press on the plot, or Enter at the cursor, sets it.
718
+ const tradeOnChart = !!trade && !!listing && researchTradeMatches(trade, { ...listing.instrument, exchange: listing.target.exchange });
719
+ const pricePick = useMemo(() => tradeOnChart && trade?.picking && trade.finishPick && trade.cancelPick ? {
720
+ label: `set ${trade.picking.label}`, onPick: trade.finishPick, onCancel: trade.cancelPick,
721
+ } : null, [tradeOnChart, trade?.picking, trade?.finishPick, trade?.cancelPick]);
664
722
  const formulasDialogRef = useRef<MultiSelectDialogButtonHandle | null>(null);
665
723
  const indicatorsDisabled = !isPriceStudyTarget(spec);
666
724
  const formulasDisabled = spec.series.filter((series) => series.visible !== false).length < 2;
@@ -830,7 +888,7 @@ function ChartComposerSurface({
830
888
  content: (context: PromptContext<ChartSpec | null>) => (
831
889
  <SeriesEditorDialog {...context} initialSpec={spec} />
832
890
  ),
833
- }).catch(() => null);
891
+ }).catch(logFailure("chart-composer.pane", "Open chart series editor failed", null));
834
892
  if (next) setSpec(next);
835
893
  } finally {
836
894
  setInteractionCaptured("prompt", false);
@@ -871,23 +929,57 @@ function ChartComposerSurface({
871
929
  content: (context: PromptContext<string>) => (
872
930
  <ChoiceDialog
873
931
  {...context}
874
- title="Chart Resolution"
932
+ title="Bar Size"
875
933
  selectedChoiceId={spec.viewport.resolution}
876
- choices={availableResolutions.map((value) => ({
877
- id: value,
878
- label: formatChartResolution(value),
879
- description: describeChartResolution(value),
880
- }))}
934
+ choices={[
935
+ ...dialogResolutions.map((value) => ({
936
+ id: value,
937
+ label: formatChartResolution(value),
938
+ description: describeChartResolution(value),
939
+ })),
940
+ ...(hasMarketSeries ? [{ id: CUSTOM_BAR_SIZE_CHOICE, label: "Custom…", description: "Type any number of minutes, hours, days, weeks or months." }] : []),
941
+ ]}
881
942
  />
882
943
  ),
883
- }).catch(() => "");
884
- if (availableResolutions.includes(next as ChartResolution)) setResolution(next as ChartResolution);
944
+ }).catch(logFailure("chart-composer.pane", "Open chart bar size choices failed", ""));
945
+ if (next === CUSTOM_BAR_SIZE_CHOICE) {
946
+ // A row picked with the mouse closes on mousedown; the field opens after the
947
+ // click has placed the focus, or the desktop leaves it on the dialog.
948
+ await new Promise((resolve) => setTimeout(resolve, 0));
949
+ const typed = await dialog.prompt<string>({
950
+ content: (ctx: PromptContext<string>) => (
951
+ <TextPromptDialog {...ctx} title="Custom Bar Size" placeholder="10m, 90m, 4h, 2D, 3W, 6mo" confirmLabel="Chart" width={44} />
952
+ ),
953
+ }).catch(logFailure("chart-composer.pane", "Open custom chart bar size prompt failed"));
954
+ if (!typed) return;
955
+ const size = parseChartBarSize(typed);
956
+ const count = /^\s*(\d+)\s*M\s*$/.exec(typed)?.[1];
957
+ if (!size) {
958
+ notify({
959
+ body: count
960
+ ? `Write ${count}m for ${count} minutes or ${count}mo for ${count} months.`
961
+ : `${typed} is not a bar size. Use a number and a unit: 10m, 4h, 2D, 3W, 6mo; up to a day of minutes or hours, a year of days or weeks, or 12 months.`,
962
+ type: "error",
963
+ });
964
+ return;
965
+ }
966
+ if (!availableOf(withChartBarSize([], size)).includes(size)) {
967
+ notify({ body: `${formatChartResolution(size)} bars are unavailable for this range.`, type: "error" });
968
+ return;
969
+ }
970
+ setResolution(size);
971
+ return;
972
+ }
973
+ if (dialogResolutions.includes(next as ChartResolution)) setResolution(next as ChartResolution);
885
974
  } finally {
886
975
  setInteractionCaptured("prompt", false);
887
976
  }
888
977
  }, [
889
- availableResolutions,
978
+ availableOf,
890
979
  dialog,
980
+ dialogResolutions,
981
+ hasMarketSeries,
982
+ notify,
891
983
  setInteractionCaptured,
892
984
  setResolution,
893
985
  spec.viewport.resolution,
@@ -923,7 +1015,7 @@ function ChartComposerSurface({
923
1015
  void openSeriesEditor();
924
1016
  return;
925
1017
  case "resolution":
926
- if (availableResolutions.length > 1) void openResolutionPicker();
1018
+ if (dialogResolutions.length > 1) void openResolutionPicker();
927
1019
  }
928
1020
  }, { enabled: focused && !dialogOpen });
929
1021
 
@@ -936,13 +1028,13 @@ function ChartComposerSurface({
936
1028
  const loading = resolution.loading || listings.pending;
937
1029
  // A bare code several companies list asks which, as `quote` does, before anything else is said.
938
1030
  const statusError = listings.errors[0] ?? resolution.errors[0];
939
- // A spread or formula error names its legs and their units; the study's id adds nothing to it.
1031
+ // A spread or formula error names its legs and their units; the study's name adds nothing to it.
940
1032
  const formulaStudy = spec.studies.find((study) => (study.kind === "spread" || study.kind === "formula")
941
- && statusError?.startsWith(`${study.id}: `));
942
- const statusErrorNotice = formulaStudy ? statusError?.slice(`${formulaStudy.id}: `.length) : statusError;
943
- // Failed series use their authored id in errors and their display label in warnings.
944
- const errorSeries = spec.series.find((entry) => statusError?.startsWith(`${entry.label ?? entry.id}: `));
945
- const errorMessage = errorSeries ? statusError?.slice(`${errorSeries.label ?? errorSeries.id}: `.length) : undefined;
1033
+ && statusError?.startsWith(`${studyMessageName(study)}: `));
1034
+ const statusErrorNotice = formulaStudy ? statusError?.slice(`${studyMessageName(formulaStudy)}: `.length) : statusError;
1035
+ // Failed series name what was asked for in errors and their display label in warnings.
1036
+ const errorSeries = spec.series.find((entry) => statusError?.startsWith(`${seriesMessageName(entry)}: `));
1037
+ const errorMessage = errorSeries ? statusError?.slice(`${seriesMessageName(errorSeries)}: `.length) : undefined;
946
1038
  // The label the resolver wrote its warnings with, before the legend named the company.
947
1039
  const errorSeriesLabel = (resolution.legendSeries?.find((entry) => entry.id === errorSeries?.id)
948
1040
  ?? legendSeries?.find((entry) => entry.id === errorSeries?.id))?.label;
@@ -965,9 +1057,9 @@ function ChartComposerSurface({
965
1057
  && !FORWARD_VALUATION_BASIS_NOTICES.has(warning)
966
1058
  && !duplicateErrorNotices.has(warning) && !comparisonEmptyNotices.has(warning)
967
1059
  && !spec.studies.some((study) => (
968
- (study.kind === "ratio" && warning.startsWith(`${study.id}: ratio inputs use different currencies (`)
1060
+ (study.kind === "ratio" && warning.startsWith(`${studyMessageName(study)}: ratio inputs use different currencies (`)
969
1061
  && warning.endsWith("); raw values are not FX-converted."))
970
- || (study.kind === "correlation" && warning.startsWith(`${study.id}: correlation mixes `)
1062
+ || (study.kind === "correlation" && warning.startsWith(`${studyMessageName(study)}: correlation mixes `)
971
1063
  && warning.endsWith("; only matching observation times contribute."))
972
1064
  ))
973
1065
  ));
@@ -1192,7 +1284,9 @@ function ChartComposerSurface({
1192
1284
  onToggleSeries={toggleSeries}
1193
1285
  isSeriesToggleable={isSeriesToggleable}
1194
1286
  timePick={timePick}
1287
+ pricePick={pricePick}
1195
1288
  levels={chartLevels}
1289
+ rangeStatisticsSeriesId={rangeStatisticsSeriesId}
1196
1290
  emptyMessage={emptyMessage}
1197
1291
  emptyDetail={emptyDetail}
1198
1292
  legendAccessory={(
@@ -1287,6 +1381,26 @@ export function ChartComposerPane({ paneId, focused, width, height }: PaneProps)
1287
1381
  savedForTarget.current = targetKey;
1288
1382
  }
1289
1383
  }, [follows, ownedIds, savedIds, setSpec, spec, stored, target, unlinkedFrom, updateSettings]);
1384
+ // A comparison CMP opened draws each leveraged or inverse fund's daily objective once its facts are read.
1385
+ const leveragePending = instance?.settings?.[CHART_LEVERAGE_PENDING_SETTING_KEY] === true;
1386
+ const storedRef = useRef(stored);
1387
+ storedRef.current = stored;
1388
+ useEffect(() => {
1389
+ if (!leveragePending) return;
1390
+ const mounted = new AbortController();
1391
+ // The chart draws meanwhile, so it can wait longer for them than a report does.
1392
+ void loadDailyObjectives(comparedFundTickers(storedRef.current),
1393
+ async (ticker, signal) => (await loadFundFacts(ticker, false, { signal })).payload,
1394
+ { timeoutMs: LEVERAGE_FACTS_PANE_TIMEOUT_MS, signal: mounted.signal })
1395
+ .then((objectives) => {
1396
+ if (mounted.signal.aborted) return;
1397
+ updateSettings({
1398
+ [CHART_SPEC_SETTING_KEY]: withLeverageOverlay(storedRef.current, objectives),
1399
+ [CHART_LEVERAGE_PENDING_SETTING_KEY]: undefined,
1400
+ });
1401
+ });
1402
+ return () => mounted.abort();
1403
+ }, [leveragePending, updateSettings]);
1290
1404
  if (follows && !target && ownedIds.length > 0) {
1291
1405
  return <EmptyState title={error ?? "Select a ticker."} />;
1292
1406
  }
@@ -6,7 +6,7 @@ import {
6
6
  } from "../../../time-series/types";
7
7
  import type { ChartResolution, TimeRange } from "../../../components/chart/core/types";
8
8
  import { MAX_CHART_COMPOSER_SERIES } from "./chart-spec";
9
- import { appendChartSeries, appendPlacedSeries, buildCustomSeries, buildSeriesSpec, panelsForSeries } from "./chart-spec-edit";
9
+ import { appendChartSeries, appendPlacedSeries, buildCustomSeries, buildSeriesSpec, nextGeneratedPanelId, panelsForSeries } from "./chart-spec-edit";
10
10
  import { currencyPairSpelling } from "../../../utils/currency-pair";
11
11
  import { dashedCoinPair } from "../../../utils/crypto-pair";
12
12
  import {
@@ -82,21 +82,51 @@ function placeFormulaLeg(formula: ParsedFormula, index: number, series: ChartSer
82
82
  return mixed && series.panelId === "main" && !formula.legs[index]!.perBarrel ? { ...series, axis: "right" } : series;
83
83
  }
84
84
 
85
- /** The study that weighs a formula's legs, charted as the given series, in the Formula panel. */
85
+ /**
86
+ * A series the formula is divided or multiplied by (an FX rate) counts
87
+ * something else again: it is drawn in a panel of its own, not on the legs' axes.
88
+ */
89
+ function placeFormulaFactor(spec: Pick<ChartSpec, "panels" | "series" | "studies">, series: ChartSeriesSpec): ChartSeriesSpec {
90
+ return { ...series, panelId: nextGeneratedPanelId(spec), axis: "auto" };
91
+ }
92
+
93
+ /** A factor's panel is shorter than a series panel, so the legs and the formula keep their room. */
94
+ const FACTOR_PANEL_HEIGHT = 0.2;
95
+
96
+ /** The panels with each new factor's last and short: the formula reads right under its legs. */
97
+ function withFactorPanels(panels: ChartSpec["panels"], factors: readonly ChartSeriesSpec[]): ChartSpec["panels"] {
98
+ const ids = new Set(factors.map((series) => series.panelId));
99
+ return [
100
+ ...panels.filter((panel) => !ids.has(panel.id)),
101
+ ...panels.filter((panel) => ids.has(panel.id)).map((panel) => ({ ...panel, height: FACTOR_PANEL_HEIGHT })),
102
+ ];
103
+ }
104
+
105
+ /** The study that weighs a formula's legs and scales the sum, charted as the given series, in the Formula panel. */
86
106
  function formulaStudy(formula: ParsedFormula, inputSeriesIds: string[]): ChartStudySpec {
87
107
  const parameters: ChartStudySpec["parameters"] = { divisor: formula.divisor };
88
108
  formula.legs.forEach((leg, index) => {
89
109
  parameters[`weight${index + 1}`] = leg.weight;
90
110
  if (leg.perBarrel) parameters[`perBarrel${index + 1}`] = 1;
111
+ if (leg.perTonne) parameters[`perTonne${index + 1}`] = leg.perTonne;
112
+ });
113
+ formula.factors.forEach((factor, index) => {
114
+ parameters[`power${formula.legs.length + index + 1}`] = factor.power;
91
115
  });
92
116
  return { id: FORMULA_STUDY_ID, kind: "formula", inputSeriesIds, parameters, panelId: "formula", axis: "auto" };
93
117
  }
94
118
 
95
- /** A formula's legs as series, with the study that sums them in the Formula panel. */
119
+ /** A formula's legs and factors as series, with the study that sums them in the Formula panel. */
96
120
  function formulaChartPreset(formula: ParsedFormula): ChartSpec {
97
- const series = buildCustomSeries(formula.legs.map((leg) => leg.series))
98
- .map((entry, index) => placeFormulaLeg(formula, index, entry));
99
- return chartSpec(series, { studies: [formulaStudy(formula, series.map((entry) => entry.id))] });
121
+ const legs = buildCustomSeries([...formula.legs, ...formula.factors].map((entry) => entry.series));
122
+ const series: ChartSeriesSpec[] = [];
123
+ legs.forEach((entry, index) => {
124
+ series.push(index < formula.legs.length
125
+ ? placeFormulaLeg(formula, index, entry)
126
+ : placeFormulaFactor({ panels: [], series, studies: [] }, entry));
127
+ });
128
+ const spec = chartSpec(series, { studies: [formulaStudy(formula, series.map((entry) => entry.id))] });
129
+ return { ...spec, panels: withFactorPanels(spec.panels, series.slice(formula.legs.length)) };
100
130
  }
101
131
 
102
132
  /**
@@ -107,17 +137,22 @@ function appendChartFormula(spec: ChartSpec, expression: string): { spec: ChartS
107
137
  const formula = parseFormulaExpression(expression);
108
138
  if (!formula) throw new Error(`"${expression}" is not a formula.`);
109
139
  const key = (series: ChartSeriesSpec) => formatSeriesExpression(series).toLowerCase();
110
- const legs = formula.legs.map((leg) => key(buildSeriesSpec(leg.series, 0)));
140
+ const terms = [...formula.legs, ...formula.factors];
141
+ const legs = terms.map((leg) => key(buildSeriesSpec(leg.series, 0)));
111
142
  const missing = legs.filter((leg) => !spec.series.some((series) => key(series) === leg)).length;
112
143
  if (spec.series.length + missing > MAX_CHART_COMPOSER_SERIES) {
113
144
  throw new Error(`Charts support up to ${MAX_CHART_COMPOSER_SERIES} base series.`);
114
145
  }
115
146
  let next: ChartSpec = { ...spec, studies: spec.studies.filter((study) => study.id !== FORMULA_STUDY_ID) };
116
- const inputs = formula.legs.map((leg, index) => {
147
+ const placedFactors: ChartSeriesSpec[] = [];
148
+ const inputs = terms.map((leg, index) => {
117
149
  const charted = next.series.find((series) => key(series) === legs[index]);
118
150
  if (charted) return charted;
119
151
  const appended = appendChartSeries(next, leg.series);
120
- const placed = placeFormulaLeg(formula, index, appended.series);
152
+ const placed = index < formula.legs.length
153
+ ? placeFormulaLeg(formula, index, appended.series)
154
+ : placeFormulaFactor(next, appended.series);
155
+ if (index >= formula.legs.length) placedFactors.push(placed);
121
156
  next = { ...appended.spec, series: appended.spec.series.map((series) => series.id === placed.id ? placed : series) };
122
157
  return placed;
123
158
  });
@@ -127,7 +162,10 @@ function appendChartFormula(spec: ChartSpec, expression: string): { spec: ChartS
127
162
  spec: {
128
163
  ...next,
129
164
  studies,
130
- panels: [...next.panels, ...panelsForSeries(next.series, studies).filter((panel) => !known.has(panel.id))],
165
+ panels: withFactorPanels(
166
+ [...next.panels, ...panelsForSeries(next.series, studies).filter((panel) => !known.has(panel.id))],
167
+ placedFactors,
168
+ ),
131
169
  },
132
170
  series: inputs.at(-1)!,
133
171
  };
@@ -275,11 +313,8 @@ export function buildValuationChartPreset(
275
313
  const series = buildSeriesSpec(
276
314
  { kind: "security", ...instrument, fieldId: resolvedField },
277
315
  index,
278
- { style: normalized.length === 1 ? "line" : "columns", axis: "left" },
316
+ { style: "line", axis: "left" },
279
317
  );
280
- // Fiscal years: most US filers report no Q4 EPS, which charts do not
281
- // reconstruct, so a quarterly trailing multiple has only its latest few
282
- // quarters. Quarterly is the series' Period control away.
283
- return series.source.kind === "security" ? { ...series, source: { ...series.source, period: "annual" } } : series;
318
+ return series.source.kind === "security" ? { ...series, source: { ...series.source, period: "daily" } } : series;
284
319
  }));
285
320
  }