gloomberb 0.18.2 → 0.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (954) 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 +106 -5
  6. package/src/account/checkout-handoff.tsx +225 -0
  7. package/src/account/device-signin-dialog.tsx +2 -2
  8. package/src/account/device-signin.ts +2 -2
  9. package/src/account/upgrade-dialog.tsx +1 -1
  10. package/src/api-client/askg.ts +2 -2
  11. package/src/api-client/auth.ts +2 -2
  12. package/src/api-client/central-bank-rates.ts +6 -0
  13. package/src/api-client/collections.ts +5 -1
  14. package/src/api-client/cot.ts +2 -0
  15. package/src/api-client/crypto-etf-flows.ts +37 -0
  16. package/src/api-client/crypto-markets.ts +60 -0
  17. package/src/api-client/data.ts +99 -5
  18. package/src/api-client/doe.ts +15 -0
  19. package/src/api-client/equity-screener.ts +28 -0
  20. package/src/api-client/exchange-announcements.ts +38 -0
  21. package/src/api-client/fund-facts.ts +39 -0
  22. package/src/api-client/futures-curve.ts +9 -1
  23. package/src/api-client/hiring.ts +301 -0
  24. package/src/api-client/index.ts +24 -5
  25. package/src/api-client/market-discovery.ts +14 -0
  26. package/src/api-client/members.ts +6 -0
  27. package/src/api-client/mna.ts +6 -0
  28. package/src/api-client/paths.ts +18 -1
  29. package/src/api-client/request.ts +26 -7
  30. package/src/api-client/short-side-publications.ts +37 -0
  31. package/src/api-client/socket.ts +64 -4
  32. package/src/api-client/swap-curve.ts +35 -0
  33. package/src/api-client/telemetry.ts +17 -0
  34. package/src/api-client/themes.ts +7 -1
  35. package/src/api-client/types.ts +90 -2
  36. package/src/app/global-shortcuts.ts +1 -16
  37. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  38. package/src/app/runtime/desktop-deeplink.ts +5 -5
  39. package/src/app/runtime/plugin-bindings.ts +2 -2
  40. package/src/app/runtime/startup.ts +13 -0
  41. package/src/app/runtime/update.ts +28 -8
  42. package/src/app/star-prompt/status-line.tsx +2 -2
  43. package/src/architecture/core-builtin-allowlist.json +5 -2
  44. package/src/architecture/pane-tabs-allowlist.json +65 -0
  45. package/src/architecture/ui-literals-allowlist.json +3 -3
  46. package/src/architecture/ui-tokens-allowlist.json +1 -1
  47. package/src/brokers/broker-portfolio-sync.ts +37 -0
  48. package/src/brokers/directory.ts +11 -0
  49. package/src/brokers/logos.ts +3 -1
  50. package/src/brokers/signed-in/adapter.ts +304 -26
  51. package/src/brokers/signed-in/client.ts +14 -2
  52. package/src/brokers/signed-in/connect.ts +10 -2
  53. package/src/brokers/sync-broker-instance.ts +9 -1
  54. package/src/capabilities/chart-series.ts +22 -6
  55. package/src/cli/bank-section.ts +1 -1
  56. package/src/cli/base-converter.ts +23 -14
  57. package/src/cli/central-bank-events.ts +1 -1
  58. package/src/cli/command-options.ts +59 -4
  59. package/src/cli/commands/api.ts +9 -6
  60. package/src/cli/commands/broker.ts +2 -2
  61. package/src/cli/commands/command-utils.ts +2 -2
  62. package/src/cli/commands/crypto-hints.ts +7 -20
  63. package/src/cli/commands/fred-series.ts +4 -2
  64. package/src/cli/commands/keybindings.ts +2 -2
  65. package/src/cli/commands/market.ts +1189 -296
  66. package/src/cli/commands/news-hints.ts +2 -2
  67. package/src/cli/commands/news-search.ts +59 -6
  68. package/src/cli/commands/options-leaps.ts +41 -26
  69. package/src/cli/commands/overview.ts +121 -48
  70. package/src/cli/commands/plugins.ts +9 -9
  71. package/src/cli/commands/remote.ts +13 -10
  72. package/src/cli/commands/search.ts +64 -44
  73. package/src/cli/commands/system.ts +27 -19
  74. package/src/cli/commands/themes.ts +1 -1
  75. package/src/cli/commands/ticker.ts +272 -70
  76. package/src/cli/context.ts +3 -2
  77. package/src/cli/desktop-pane-shot-view.ts +2 -2
  78. package/src/cli/desktop-pane-shot.ts +1 -1
  79. package/src/cli/earnings-calendar.ts +4 -4
  80. package/src/cli/entry.ts +18 -1
  81. package/src/cli/errors.ts +20 -2
  82. package/src/cli/exit-codes.ts +1 -1
  83. package/src/cli/export-source.ts +10 -4
  84. package/src/cli/freshness.ts +2 -8
  85. package/src/cli/fx-forward.ts +130 -0
  86. package/src/cli/fx-pair.ts +10 -9
  87. package/src/cli/glossary.ts +64 -20
  88. package/src/cli/help.ts +20 -14
  89. package/src/cli/history-export.ts +126 -0
  90. package/src/cli/history-rows.ts +196 -43
  91. package/src/cli/index-roots.ts +5 -45
  92. package/src/cli/index.ts +32 -18
  93. package/src/cli/issuer-membership.ts +103 -0
  94. package/src/cli/known-gaps.ts +118 -25
  95. package/src/cli/listing-arg.ts +315 -43
  96. package/src/cli/name-entries.ts +73 -22
  97. package/src/cli/native-smoke.ts +2 -0
  98. package/src/cli/not-a-ticker.ts +19 -9
  99. package/src/cli/opentui-libc.ts +5 -0
  100. package/src/cli/options.ts +12 -0
  101. package/src/cli/pane-functions/capabilities.ts +77 -20
  102. package/src/cli/pane-functions/catalog.ts +40 -23
  103. package/src/cli/pane-functions/discovery.ts +1 -1
  104. package/src/cli/pane-functions/dom.ts +12 -8
  105. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  106. package/src/cli/pane-functions/freshness.ts +174 -23
  107. package/src/cli/pane-functions/function-help.ts +66 -27
  108. package/src/cli/pane-functions/headless.ts +48 -16
  109. package/src/cli/pane-functions/index.ts +82 -21
  110. package/src/cli/pane-functions/options.ts +22 -2
  111. package/src/cli/pane-functions/report-notices.ts +12 -4
  112. package/src/cli/pane-functions/report.ts +5 -5
  113. package/src/cli/pane-functions/resolver.ts +65 -14
  114. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  115. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  116. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  117. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  118. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  119. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  120. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  121. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  122. package/src/cli/pane-functions/shot-options.ts +8 -3
  123. package/src/cli/peso-dollar-rates.ts +79 -0
  124. package/src/cli/quote-answer.ts +38 -3
  125. package/src/cli/report-tables.ts +190 -27
  126. package/src/cli/restore-plugins.ts +29 -14
  127. package/src/cli/result.ts +122 -25
  128. package/src/cli/series-search.ts +5 -5
  129. package/src/cli/statement-filings.ts +19 -0
  130. package/src/cli/suffixed-listing-rows.ts +49 -0
  131. package/src/cli/symbol-args.ts +50 -15
  132. package/src/cli/symbol-cells.ts +120 -0
  133. package/src/cli/symbol-list.ts +226 -60
  134. package/src/cli/symbol-rows.ts +131 -25
  135. package/src/cli/ticker-resolution.ts +108 -11
  136. package/src/cli/treasury-yields.ts +5 -5
  137. package/src/cli/types.ts +2 -0
  138. package/src/cli/uncovered-instrument.ts +3 -3
  139. package/src/cli/unknown-command.ts +6 -6
  140. package/src/components/chart/composite/chart-layout.ts +131 -0
  141. package/src/components/chart/composite/composite-chart.tsx +387 -21
  142. package/src/components/chart/composite/drawing-store.ts +26 -6
  143. package/src/components/chart/composite/interactions.ts +9 -3
  144. package/src/components/chart/composite/legend.tsx +75 -3
  145. package/src/components/chart/composite/levels.ts +5 -0
  146. package/src/components/chart/composite/panel-gestures.ts +41 -0
  147. package/src/components/chart/composite/panel-labels.ts +2 -1
  148. package/src/components/chart/composite/panel-surface.tsx +316 -11
  149. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  150. package/src/components/chart/composite/rasterizer.ts +44 -19
  151. package/src/components/chart/composite/scene.ts +16 -4
  152. package/src/components/chart/composite/text-renderer.ts +48 -21
  153. package/src/components/chart/composite/toolbar.tsx +52 -5
  154. package/src/components/chart/composite/types.ts +19 -0
  155. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  156. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  157. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  158. package/src/components/chart/composite/value-scale.ts +149 -0
  159. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  160. package/src/components/chart/core/pointer.ts +2 -0
  161. package/src/components/chart-table/index.ts +2 -0
  162. package/src/components/chart-table/read.tsx +74 -0
  163. package/src/components/command-bar/commands/collection-list.ts +41 -19
  164. package/src/components/command-bar/commands/collection.ts +9 -3
  165. package/src/components/command-bar/commands/direct/index.ts +1 -1
  166. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  167. package/src/components/command-bar/pane-templates/items.ts +59 -6
  168. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  169. package/src/components/command-bar/routes/root/command-items.ts +32 -6
  170. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  171. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  172. package/src/components/command-bar/routes/root/results.ts +18 -4
  173. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  174. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  175. package/src/components/command-bar/routes/root/selection.ts +6 -1
  176. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  177. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  178. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  179. package/src/components/command-bar/selection-runtime.ts +50 -10
  180. package/src/components/command-bar/surface/index.tsx +24 -2
  181. package/src/components/command-bar/view-model.ts +7 -0
  182. package/src/components/command-bar/workflow/broker.ts +2 -2
  183. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  184. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  185. package/src/components/command-bar/workflow/fields.ts +8 -2
  186. package/src/components/command-bar/workflow/ops.ts +18 -4
  187. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  188. package/src/components/command-bar/workflow/submit.ts +3 -2
  189. package/src/components/command-bar/workflow/tickers.ts +5 -1
  190. package/src/components/company-logo.tsx +39 -0
  191. package/src/components/data-table/sections.ts +4 -2
  192. package/src/components/data-table/view.tsx +23 -3
  193. package/src/components/form-modal/confirm.tsx +2 -1
  194. package/src/components/form-modal/request.ts +5 -0
  195. package/src/components/form-modal/routes.ts +4 -1
  196. package/src/components/index.ts +13 -6
  197. package/src/components/layout/detached-pane-shell.tsx +1 -0
  198. package/src/components/layout/floating-pane.tsx +1 -0
  199. package/src/components/layout/header.tsx +234 -60
  200. package/src/components/layout/market-summary.ts +9 -6
  201. package/src/components/layout/pane/capture-status.ts +1 -1
  202. package/src/components/layout/pane/footer/model.ts +11 -5
  203. package/src/components/layout/pane/header.tsx +10 -3
  204. package/src/components/layout/pane/index.tsx +1 -0
  205. package/src/components/layout/pane/pane-tabs.tsx +9 -1
  206. package/src/components/layout/shell/chrome.ts +19 -6
  207. package/src/components/layout/shell/index.tsx +2 -1
  208. package/src/components/layout/shell/pane/layers.tsx +19 -1
  209. package/src/components/layout/status-bar.tsx +2 -2
  210. package/src/components/market-board/index.tsx +11 -3
  211. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  212. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  213. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  214. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  215. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  216. package/src/components/pane-settings-dialog/value.ts +8 -1
  217. package/src/components/pane-settings-dialog.tsx +44 -13
  218. package/src/components/sign-in-code-panel.tsx +27 -19
  219. package/src/components/ui/column-grid.tsx +48 -4
  220. package/src/components/ui/country-flag-art.tsx +180 -0
  221. package/src/components/ui/country-flag.tsx +118 -12
  222. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  223. package/src/components/ui/data-table/opentui/model.ts +109 -2
  224. package/src/components/ui/data-table/types.ts +1 -1
  225. package/src/components/ui/display.tsx +5 -1
  226. package/src/components/ui/index.ts +3 -1
  227. package/src/components/ui/logo-mark.tsx +11 -2
  228. package/src/components/ui/query-bar.tsx +1 -1
  229. package/src/components/ui/row-notes.ts +79 -0
  230. package/src/components/ui/stat-grid.tsx +28 -3
  231. package/src/components/ui/status.tsx +3 -1
  232. package/src/core/app-services.ts +4 -0
  233. package/src/core/state/app/layout.ts +4 -4
  234. package/src/data/cached-query.ts +8 -1
  235. package/src/data/config/chart-settings.ts +3 -3
  236. package/src/data/config/home.ts +10 -2
  237. package/src/data/config/layout.ts +4 -1
  238. package/src/data/config/store/node.ts +4 -0
  239. package/src/data/config/store/normalize.ts +13 -3
  240. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  241. package/src/data/json-storage.ts +2 -0
  242. package/src/data/saved-copies.ts +84 -0
  243. package/src/docs/snapshot.json +65 -32
  244. package/src/i18n/es.ts +51 -12
  245. package/src/i18n/ja.ts +51 -12
  246. package/src/i18n/ko.ts +51 -12
  247. package/src/i18n/zh-cn.ts +51 -12
  248. package/src/i18n/zh-tw.ts +51 -12
  249. package/src/layout/desks.ts +1 -1
  250. package/src/layout/launch-layout.ts +1 -1
  251. package/src/layout/pane-manager/floating-actions.ts +5 -3
  252. package/src/layout/pane-manager/floating.ts +43 -1
  253. package/src/layout/pane-manager/index.ts +2 -0
  254. package/src/layout/selected-ticker.ts +74 -0
  255. package/src/market-data/depositary-pair.ts +251 -0
  256. package/src/market-data/futures-board.ts +1 -1
  257. package/src/market-data/futures-contract.ts +124 -40
  258. package/src/market-data/fx-closes.ts +17 -2
  259. package/src/market-data/hooks.tsx +19 -11
  260. package/src/market-data/market/change-basis.ts +49 -7
  261. package/src/market-data/market/freshness.ts +34 -5
  262. package/src/market-data/market/period-return.ts +163 -0
  263. package/src/market-data/market/trading-sessions.ts +13 -0
  264. package/src/market-data/market/year-to-date.ts +8 -13
  265. package/src/market-data/performance.ts +20 -14
  266. package/src/market-data/perpetual-premium.ts +32 -0
  267. package/src/market-data/published-apac-sessions.ts +2 -1
  268. package/src/market-data/published-futures-sessions.ts +69 -0
  269. package/src/market-data/quotes/contributions.ts +5 -1
  270. package/src/market-data/quotes/freshness.ts +42 -0
  271. package/src/market-data/quotes/intraday-bar.ts +37 -0
  272. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  273. package/src/market-data/quotes/resolution.ts +4 -2
  274. package/src/market-data/tax-equivalent.ts +1 -1
  275. package/src/market-data/ticker-price-returns.ts +3 -1
  276. package/src/news/aggregator.ts +5 -1
  277. package/src/news/news-model.ts +4 -0
  278. package/src/news/types.ts +11 -0
  279. package/src/notifications/app-notifier.ts +1 -1
  280. package/src/plugins/auto-update.ts +2 -2
  281. package/src/plugins/builtin/account-management/index.tsx +1 -0
  282. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  283. package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
  284. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  285. package/src/plugins/builtin/alerts/cli.ts +485 -76
  286. package/src/plugins/builtin/alerts/command.ts +5 -10
  287. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  288. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  289. package/src/plugins/builtin/alerts/events.ts +108 -5
  290. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  291. package/src/plugins/builtin/alerts/format.ts +2 -1
  292. package/src/plugins/builtin/alerts/headless.ts +100 -39
  293. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  294. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  295. package/src/plugins/builtin/alerts/index.tsx +45 -18
  296. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  297. package/src/plugins/builtin/alerts/levels.ts +3 -3
  298. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  299. package/src/plugins/builtin/alerts/price.ts +35 -0
  300. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  301. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  302. package/src/plugins/builtin/alerts/research-rules.ts +77 -3
  303. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  304. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  305. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  306. package/src/plugins/builtin/alerts/storage.ts +13 -10
  307. package/src/plugins/builtin/alerts/targets.ts +12 -3
  308. package/src/plugins/builtin/analytics/index.tsx +8 -2
  309. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  310. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  311. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  312. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  313. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  314. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  315. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  316. package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
  317. package/src/plugins/builtin/attention/pane.tsx +22 -16
  318. package/src/plugins/builtin/awards/headless.ts +7 -3
  319. package/src/plugins/builtin/awards/model.ts +18 -0
  320. package/src/plugins/builtin/awards/pane.tsx +12 -9
  321. package/src/plugins/builtin/backtest/export.ts +1 -1
  322. package/src/plugins/builtin/backtest/headless.ts +3 -3
  323. package/src/plugins/builtin/backtest/rules.ts +41 -5
  324. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  325. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  326. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  327. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  328. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  329. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  330. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  331. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  332. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  333. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  334. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  335. package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
  336. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  337. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  338. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  339. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  340. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  341. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  342. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  343. package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
  344. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  345. package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
  346. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  347. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  348. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  349. package/src/plugins/builtin/buildout/pane/index.tsx +34 -18
  350. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  351. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  352. package/src/plugins/builtin/catalysts/client.ts +2 -2
  353. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  354. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  355. package/src/plugins/builtin/catalysts/model.ts +49 -4
  356. package/src/plugins/builtin/catalysts/pane.tsx +9 -11
  357. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  358. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  359. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  360. package/src/plugins/builtin/changelog/index.tsx +1 -0
  361. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  362. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  363. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  364. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  365. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  366. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  367. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  368. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  369. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  370. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  371. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  372. package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
  373. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  374. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  375. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  376. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  377. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  378. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  379. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  380. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  381. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  382. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  383. package/src/plugins/builtin/chat/people.ts +1 -1
  384. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  385. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  386. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  387. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  388. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  389. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  390. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  391. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  392. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  393. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  394. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  395. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  396. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  397. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  398. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  399. package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
  400. package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
  401. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  402. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  403. package/src/plugins/builtin/company-attention/client.ts +117 -1
  404. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  405. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  406. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  407. package/src/plugins/builtin/company-attention/model.ts +33 -7
  408. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  409. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  410. package/src/plugins/builtin/company-attention/pane.tsx +89 -31
  411. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  412. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  413. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  414. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  415. package/src/plugins/builtin/company-kpis/pane.tsx +5 -4
  416. package/src/plugins/builtin/composite-plugins.ts +2 -1
  417. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  418. package/src/plugins/builtin/connections/index.ts +1 -0
  419. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  420. package/src/plugins/builtin/correlation/headless.ts +7 -4
  421. package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
  422. package/src/plugins/builtin/correlation/settings.ts +1 -0
  423. package/src/plugins/builtin/cot/headless.ts +28 -6
  424. package/src/plugins/builtin/cot/model.ts +12 -0
  425. package/src/plugins/builtin/cot/pane.tsx +7 -5
  426. package/src/plugins/builtin/cpi/headless.ts +5 -1
  427. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  428. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  429. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  430. package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
  431. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  432. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  433. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  434. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  435. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  436. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  437. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  438. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  439. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  440. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  441. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  442. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  443. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  444. package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
  445. package/src/plugins/builtin/debug/index.tsx +1 -0
  446. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  447. package/src/plugins/builtin/docs/index.tsx +1 -1
  448. package/src/plugins/builtin/docs/pane.tsx +2 -2
  449. package/src/plugins/builtin/docs/targets.ts +1 -1
  450. package/src/plugins/builtin/doe/client.ts +5 -1
  451. package/src/plugins/builtin/doe/headless.ts +12 -6
  452. package/src/plugins/builtin/doe/model.ts +43 -6
  453. package/src/plugins/builtin/doe/pane.tsx +19 -12
  454. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  455. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  456. package/src/plugins/builtin/earnings/board.tsx +253 -50
  457. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  458. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  459. package/src/plugins/builtin/earnings/client.ts +4 -3
  460. package/src/plugins/builtin/earnings/headless.ts +53 -15
  461. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  462. package/src/plugins/builtin/earnings/index.tsx +15 -22
  463. package/src/plugins/builtin/earnings/model.ts +17 -12
  464. package/src/plugins/builtin/earnings/scope.ts +89 -0
  465. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  466. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  467. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  468. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  469. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  470. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  471. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  472. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  473. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  474. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  475. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  476. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  477. package/src/plugins/builtin/econ/index.tsx +112 -25
  478. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  479. package/src/plugins/builtin/econ/types.ts +32 -1
  480. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  481. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  482. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  483. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  484. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  485. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  486. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  487. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  488. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  489. package/src/plugins/builtin/equity-screener/headless.ts +77 -5
  490. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  491. package/src/plugins/builtin/equity-screener/model.ts +34 -0
  492. package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
  493. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  494. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  495. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  496. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  497. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  498. package/src/plugins/builtin/exposure/headless.ts +51 -6
  499. package/src/plugins/builtin/exposure/index.tsx +28 -2
  500. package/src/plugins/builtin/exposure/model.ts +7 -0
  501. package/src/plugins/builtin/exposure/pane.tsx +16 -10
  502. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  503. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  504. package/src/plugins/builtin/futures/model.ts +10 -9
  505. package/src/plugins/builtin/futures/returns.ts +8 -36
  506. package/src/plugins/builtin/futures/table.tsx +1 -1
  507. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  508. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  509. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  510. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  511. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  512. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  513. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  514. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  515. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  516. package/src/plugins/builtin/gpu/board.tsx +4 -1
  517. package/src/plugins/builtin/gpu/changes.tsx +10 -10
  518. package/src/plugins/builtin/gpu/equities.tsx +4 -1
  519. package/src/plugins/builtin/gpu/headless.ts +9 -4
  520. package/src/plugins/builtin/gpu/history.tsx +4 -2
  521. package/src/plugins/builtin/gpu/pane.tsx +5 -3
  522. package/src/plugins/builtin/help/index.tsx +13 -3
  523. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  524. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  525. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  526. package/src/plugins/builtin/holders/client.ts +15 -2
  527. package/src/plugins/builtin/holders/format.ts +28 -17
  528. package/src/plugins/builtin/holders/headless.ts +48 -8
  529. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  530. package/src/plugins/builtin/holders/pane.tsx +79 -15
  531. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  532. package/src/plugins/builtin/holders/table-model.ts +2 -1
  533. package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
  534. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  535. package/src/plugins/builtin/insider/base-values.ts +11 -7
  536. package/src/plugins/builtin/insider/client.ts +3 -0
  537. package/src/plugins/builtin/insider/headless.ts +20 -7
  538. package/src/plugins/builtin/insider/index.tsx +17 -8
  539. package/src/plugins/builtin/insider/issuer.ts +34 -4
  540. package/src/plugins/builtin/insider/signals-client.ts +3 -3
  541. package/src/plugins/builtin/insider/signals.tsx +1 -1
  542. package/src/plugins/builtin/insider/table-model.ts +35 -13
  543. package/src/plugins/builtin/insider/table.tsx +5 -2
  544. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  545. package/src/plugins/builtin/iv-history/client.ts +20 -0
  546. package/src/plugins/builtin/iv-history/events.ts +145 -0
  547. package/src/plugins/builtin/iv-history/format.ts +3 -0
  548. package/src/plugins/builtin/iv-history/headless.ts +91 -7
  549. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  550. package/src/plugins/builtin/iv-history/model.ts +13 -4
  551. package/src/plugins/builtin/iv-history/series.ts +3 -1
  552. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  553. package/src/plugins/builtin/jobs/model.ts +4 -15
  554. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  555. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  556. package/src/plugins/builtin/jodi/pane.tsx +14 -8
  557. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  558. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  559. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  560. package/src/plugins/builtin/macro-day/model.ts +29 -8
  561. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  562. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  563. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  564. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  565. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  566. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  567. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  568. package/src/plugins/builtin/market-movers/client.ts +36 -21
  569. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  570. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  571. package/src/plugins/builtin/market-movers/screener.ts +33 -11
  572. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  573. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  574. package/src/plugins/builtin/market-movers/table.ts +4 -1
  575. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  576. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  577. package/src/plugins/builtin/members/headless.ts +6 -5
  578. package/src/plugins/builtin/members/pane.tsx +11 -4
  579. package/src/plugins/builtin/mna/client.ts +1 -0
  580. package/src/plugins/builtin/mna/detail.tsx +20 -32
  581. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  582. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  583. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  584. package/src/plugins/builtin/mna/headless.ts +6 -13
  585. package/src/plugins/builtin/mna/model.ts +93 -15
  586. package/src/plugins/builtin/mna/pane.tsx +5 -4
  587. package/src/plugins/builtin/news/headless.ts +12 -6
  588. package/src/plugins/builtin/news/index.tsx +10 -1
  589. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  590. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  591. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  592. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  593. package/src/plugins/builtin/notes/cli.ts +50 -15
  594. package/src/plugins/builtin/notes/export.ts +17 -6
  595. package/src/plugins/builtin/notes/files.ts +16 -5
  596. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  597. package/src/plugins/builtin/options/carry.ts +2 -2
  598. package/src/plugins/builtin/options/enrichment-model.ts +10 -9
  599. package/src/plugins/builtin/options/index.tsx +1 -1
  600. package/src/plugins/builtin/options/model-spot.ts +70 -4
  601. package/src/plugins/builtin/options/view.tsx +51 -23
  602. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  603. package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
  604. package/src/plugins/builtin/options-positioning/headless.ts +11 -3
  605. package/src/plugins/builtin/options-positioning/model.ts +24 -0
  606. package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
  607. package/src/plugins/builtin/options-scenario/client.ts +142 -29
  608. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  609. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  610. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  611. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  612. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  613. package/src/plugins/builtin/options-scenario/headless.ts +49 -21
  614. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  615. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  616. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  617. package/src/plugins/builtin/options-scenario/pane.tsx +22 -10
  618. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  619. package/src/plugins/builtin/perps/freshness.ts +8 -5
  620. package/src/plugins/builtin/perps/headless.ts +3 -1
  621. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  622. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  623. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  624. package/src/plugins/builtin/perps/pane.tsx +36 -17
  625. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  626. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  627. package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
  628. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
  629. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  630. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  631. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  632. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  633. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  634. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  635. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  636. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  637. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  638. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  639. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  640. package/src/plugins/builtin/power/client.ts +6 -3
  641. package/src/plugins/builtin/power/evidence.ts +22 -7
  642. package/src/plugins/builtin/power/gas.tsx +5 -1
  643. package/src/plugins/builtin/power/pane.tsx +44 -32
  644. package/src/plugins/builtin/power/prices.tsx +10 -3
  645. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  646. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  647. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  648. package/src/plugins/builtin/research/event-model.ts +3 -1
  649. package/src/plugins/builtin/research/event-sources.ts +12 -4
  650. package/src/plugins/builtin/research/index.tsx +2 -1
  651. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  652. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  653. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  654. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  655. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  656. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  657. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  658. package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
  659. package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
  660. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  661. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  662. package/src/plugins/builtin/seasonality/client.ts +2 -1
  663. package/src/plugins/builtin/sec/forms.ts +13 -0
  664. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  665. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  666. package/src/plugins/builtin/sec/headless.ts +85 -8
  667. package/src/plugins/builtin/sec/index.tsx +58 -12
  668. package/src/plugins/builtin/sectors/client.ts +6 -4
  669. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  670. package/src/plugins/builtin/series-inventory.ts +2 -0
  671. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  672. package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
  673. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  674. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  675. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  676. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  677. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  678. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  679. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  680. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  681. package/src/plugins/builtin/shared/research-trading.tsx +23 -0
  682. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  683. package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
  684. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  685. package/src/plugins/builtin/shared/volatility/options.ts +2 -1
  686. package/src/plugins/builtin/short-interest/client.ts +2 -0
  687. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  688. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  689. package/src/plugins/builtin/short-interest/model.ts +70 -19
  690. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  691. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  692. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  693. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  694. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  695. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  696. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  697. package/src/plugins/builtin/short-interest/types.ts +9 -0
  698. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  699. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  700. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  701. package/src/plugins/builtin/social-mentions/client.ts +2 -1
  702. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  703. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  704. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  705. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  706. package/src/plugins/builtin/themes/headless.ts +8 -5
  707. package/src/plugins/builtin/themes/model.ts +14 -4
  708. package/src/plugins/builtin/themes/pane.tsx +24 -5
  709. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  710. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  711. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  712. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  713. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  714. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  715. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  716. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  717. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  718. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  719. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  720. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  721. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  722. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  723. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  724. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  725. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  726. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  727. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  728. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  729. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  730. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  731. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  732. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  733. package/src/plugins/builtin/vol-surface/client.ts +28 -7
  734. package/src/plugins/builtin/vol-surface/headless.ts +43 -15
  735. package/src/plugins/builtin/vol-surface/model.ts +34 -12
  736. package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
  737. package/src/plugins/builtin/vol-surface/stored.ts +34 -3
  738. package/src/plugins/builtin/vol-surface/tables.ts +14 -0
  739. package/src/plugins/builtin/volatility/model.ts +5 -10
  740. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  741. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  742. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  743. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  744. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  745. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  746. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  747. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  748. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  749. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  750. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  751. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  752. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  753. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  754. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  755. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  756. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  757. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  758. package/src/plugins/bundle.ts +1 -1
  759. package/src/plugins/catalog-browser.ts +2 -1
  760. package/src/plugins/compat.ts +3 -3
  761. package/src/plugins/dependencies.ts +75 -14
  762. package/src/plugins/extracted-plugins.ts +132 -34
  763. package/src/plugins/host-link.ts +149 -34
  764. package/src/plugins/installer.ts +35 -10
  765. package/src/plugins/loader.ts +206 -38
  766. package/src/plugins/manager-node.ts +2 -2
  767. package/src/plugins/marketplace/deactivation.ts +22 -0
  768. package/src/plugins/marketplace/model.ts +2 -2
  769. package/src/plugins/marketplace/packs.ts +1 -1
  770. package/src/plugins/ownership.ts +1 -1
  771. package/src/plugins/peer-retry.ts +155 -0
  772. package/src/plugins/registry/contributions.ts +3 -1
  773. package/src/plugins/registry/index.ts +4 -3
  774. package/src/plugins/registry/plugin-state.ts +3 -0
  775. package/src/plugins/seed-notice.ts +20 -0
  776. package/src/plugins/shortcut-argument.ts +39 -0
  777. package/src/portfolio/allocation.ts +1 -1
  778. package/src/portfolio/collection-name.ts +31 -0
  779. package/src/portfolio/column-values.ts +10 -8
  780. package/src/portfolio/cost-fx.ts +296 -19
  781. package/src/portfolio/manual-lots.ts +75 -0
  782. package/src/portfolio/mutations.ts +60 -22
  783. package/src/portfolio/suffixed-listings.ts +209 -0
  784. package/src/portfolio/totals-currency.ts +24 -0
  785. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  786. package/src/public/time-series.ts +11 -8
  787. package/src/remote/schema.ts +1 -1
  788. package/src/renderers/browser/config-host.ts +3 -0
  789. package/src/renderers/browser/main.tsx +23 -3
  790. package/src/renderers/dom/boot-frame-page.ts +187 -0
  791. package/src/renderers/dom/boot-frame.ts +237 -0
  792. package/src/renderers/dom/build-assets.ts +46 -8
  793. package/src/renderers/dom/desktop/controls.tsx +1 -1
  794. package/src/renderers/dom/desktop/query-bar.tsx +2 -0
  795. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  796. package/src/renderers/dom/host/ascii-text.ts +16 -2
  797. package/src/renderers/dom/host/box.tsx +43 -2
  798. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  799. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  800. package/src/renderers/dom/host/image-surface.tsx +49 -0
  801. package/src/renderers/dom/host/media-surface.tsx +24 -18
  802. package/src/renderers/dom/host/mouse.ts +30 -0
  803. package/src/renderers/dom/host/size-observer.ts +1 -1
  804. package/src/renderers/dom/host/style.ts +1 -1
  805. package/src/renderers/dom/host/tabs.tsx +16 -5
  806. package/src/renderers/dom/host/top-surface.ts +127 -0
  807. package/src/renderers/dom/styles.css +115 -0
  808. package/src/renderers/dom/test-utils.tsx +2 -1
  809. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  810. package/src/renderers/electrobun/bun/core-capabilities.ts +9 -1
  811. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  812. package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
  813. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  814. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  815. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  816. package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
  817. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  818. package/src/renderers/electrobun/bun/index.ts +11 -1
  819. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  820. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  821. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  822. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  823. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  824. package/src/renderers/electrobun/view/config-host.ts +3 -0
  825. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  826. package/src/renderers/electrobun/view/main.tsx +30 -4
  827. package/src/renderers/electrobun/view/news-source.ts +9 -7
  828. package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
  829. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  830. package/src/renderers/opentui/browser-open.ts +88 -0
  831. package/src/renderers/opentui/host.tsx +5 -14
  832. package/src/renderers/opentui/image/loader.ts +3 -2
  833. package/src/renderers/opentui/native-smoke.ts +10 -1
  834. package/src/renderers/opentui/pane-image/index.ts +2 -1
  835. package/src/renderers/opentui/render-lib.ts +253 -0
  836. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  837. package/src/renderers/opentui/start.tsx +8 -1
  838. package/src/renderers/share/layout-view.tsx +2 -2
  839. package/src/renderers/share/main.tsx +4 -4
  840. package/src/renderers/share/view.tsx +1 -1
  841. package/src/series/resolve.ts +22 -6
  842. package/src/series/standalone.ts +30 -2
  843. package/src/series/types.ts +8 -1
  844. package/src/shares/api.ts +4 -1
  845. package/src/shares/pane.ts +1 -1
  846. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  847. package/src/sources/gloomberb-cloud/index.ts +39 -16
  848. package/src/sources/gloomberb-cloud/news.ts +39 -0
  849. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  850. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  851. package/src/sources/listing-symbols.ts +37 -0
  852. package/src/sources/provider-errors.ts +16 -2
  853. package/src/sources/provider-router/financial-routes.ts +21 -3
  854. package/src/sources/provider-router/financials.ts +15 -2
  855. package/src/sources/provider-router/history.ts +30 -8
  856. package/src/sources/provider-router/index.ts +16 -0
  857. package/src/sources/provider-router/primary.ts +1 -1
  858. package/src/state/app/bootstrap.ts +23 -0
  859. package/src/state/hooks/inline-tickers.ts +30 -5
  860. package/src/sync/controller.ts +1 -1
  861. package/src/sync/core-contributors.ts +46 -14
  862. package/src/team/collections-sync.ts +2 -1
  863. package/src/team/collections.ts +178 -17
  864. package/src/telemetry/crash-reports.ts +21 -4
  865. package/src/telemetry/update-failures-node.ts +59 -0
  866. package/src/telemetry/update-failures.ts +307 -0
  867. package/src/test-support/builtin-panes.ts +1 -1
  868. package/src/theme/colors.ts +3 -30
  869. package/src/theme/ui-tokens.ts +37 -1
  870. package/src/tickers/company-name-listing.ts +215 -36
  871. package/src/tickers/company-name.ts +43 -0
  872. package/src/tickers/index-roots.ts +47 -0
  873. package/src/tickers/instrument-label.ts +5 -1
  874. package/src/tickers/listing-fate.ts +30 -0
  875. package/src/tickers/metadata.ts +10 -0
  876. package/src/tickers/perpetual-listing.ts +5 -2
  877. package/src/tickers/search/home-listing.ts +75 -0
  878. package/src/tickers/search/index.ts +76 -27
  879. package/src/tickers/search/ranking.ts +54 -4
  880. package/src/tickers/search/upsert.ts +29 -0
  881. package/src/tickers/terminal-codes.ts +416 -40
  882. package/src/time-series/bar-aggregation.ts +243 -0
  883. package/src/time-series/base-series.ts +307 -0
  884. package/src/time-series/chart-bounds.ts +349 -0
  885. package/src/time-series/chart-seed.ts +142 -0
  886. package/src/time-series/economic.ts +5 -0
  887. package/src/time-series/fundamentals.ts +18 -3
  888. package/src/time-series/history-acquisition.ts +499 -0
  889. package/src/time-series/leverage.ts +100 -0
  890. package/src/time-series/market-resolution.ts +4 -2
  891. package/src/time-series/market.ts +2 -1
  892. package/src/time-series/price-comparison.ts +175 -30
  893. package/src/time-series/range.ts +9 -1
  894. package/src/time-series/resolution.ts +174 -16
  895. package/src/time-series/resolve-context.ts +157 -0
  896. package/src/time-series/resolve.ts +126 -1577
  897. package/src/time-series/series-name.ts +38 -0
  898. package/src/time-series/series-presentation.ts +208 -0
  899. package/src/time-series/spec.ts +11 -6
  900. package/src/time-series/studies.ts +109 -12
  901. package/src/time-series/tail-reconcile.ts +121 -0
  902. package/src/time-series/types.ts +29 -2
  903. package/src/time-series/use-chart-resolution.ts +4 -5
  904. package/src/types/broker.ts +10 -0
  905. package/src/types/config.ts +14 -0
  906. package/src/types/data-provider.ts +20 -0
  907. package/src/types/exchange-rate.ts +6 -0
  908. package/src/types/financials.ts +104 -7
  909. package/src/types/headless.ts +83 -6
  910. package/src/types/instrument.ts +3 -0
  911. package/src/types/issuer-listings.ts +28 -0
  912. package/src/types/plugin.ts +65 -8
  913. package/src/types/price-history.ts +2 -0
  914. package/src/types/ticker.ts +13 -0
  915. package/src/types/trading.ts +59 -1
  916. package/src/ui/ascii-font.ts +13 -1
  917. package/src/ui/host.tsx +6 -1
  918. package/src/updater/command-names.ts +175 -0
  919. package/src/updater/failure.ts +163 -0
  920. package/src/updater/index.ts +97 -28
  921. package/src/utils/calendar-date.ts +32 -15
  922. package/src/utils/cash-runway.ts +241 -0
  923. package/src/utils/central-banks.ts +42 -0
  924. package/src/utils/cli-output.ts +259 -80
  925. package/src/utils/contract-month.ts +16 -0
  926. package/src/utils/crypto-pair.ts +61 -3
  927. package/src/utils/currency-pair.ts +26 -0
  928. package/src/utils/currency-units.ts +29 -0
  929. package/src/utils/datetime-format.ts +10 -0
  930. package/src/utils/debug-log.ts +1 -1
  931. package/src/utils/decimal-comma.ts +39 -6
  932. package/src/utils/exchange-announcements.ts +71 -0
  933. package/src/utils/exchange-rate-snapshot.ts +10 -0
  934. package/src/utils/financial-statements.ts +83 -4
  935. package/src/utils/format.ts +34 -16
  936. package/src/utils/fundamentals.ts +150 -34
  937. package/src/utils/fx-market-hours.ts +10 -1
  938. package/src/utils/latest-financial-period.ts +8 -0
  939. package/src/utils/linux-libc.ts +54 -0
  940. package/src/utils/market-capitalization.ts +111 -15
  941. package/src/utils/max-drawdown.ts +64 -0
  942. package/src/utils/network-failure.ts +83 -0
  943. package/src/utils/option-expiry.ts +139 -7
  944. package/src/utils/price-earnings.ts +11 -5
  945. package/src/utils/price-history.ts +18 -8
  946. package/src/utils/price-window.ts +131 -0
  947. package/src/utils/release-date.ts +47 -0
  948. package/src/utils/sec.ts +71 -0
  949. package/src/utils/throttled-fetch.ts +11 -4
  950. package/src/utils/trailing-eps.ts +67 -0
  951. package/src/utils/typed-text.ts +21 -0
  952. package/src/utils/utc-time.ts +24 -1
  953. package/src/version.ts +6 -0
  954. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -6,20 +6,25 @@ import { useShortcut } from "../../../react/input";
6
6
  import { afterLayout, revealInScrollBox } from "../../../components/ui/reveal-in-scroll-box";
7
7
  import { useThemeColors } from "../../../theme/theme-context";
8
8
  import type { Quote } from "../../../types/financials";
9
+ import { quoteAgeText } from "../../../market-data/quotes/freshness";
9
10
  import { formatPercentRaw } from "../../../utils/format";
10
11
  import type { BrokerAccount, BrokerOrder, BrokerOrderPreview, BrokerOrderRequest, BrokerTradingCapabilities } from "../../../types/trading";
11
12
  import { Box, ScrollBox, Text, TextAttributes, useUiCapabilities, type BoxRenderable, type ScrollBoxRenderable } from "../../../ui";
12
13
  import { useDialogState } from "../../../ui/dialog";
13
14
  import { BrokerAccountPicker, type BrokerAccountChoice } from "./account-picker";
14
- import { TicketLegs, TicketSection, TicketOrderHeadline, TicketOrderSummary, TicketReceiptRow, TicketStatus, ticketMoney as money, ticketNumber as number, ticketTifName, ticketTypeName as typeName } from "./ticket-parts";
15
+ import { TicketExits, TicketLegs, TicketSection, TicketOrderHeadline, TicketOrderSummary, TicketReceiptRow, TicketStatus, ticketImpactMoney, ticketImpactSource, ticketMoney as money, ticketNumber as number, ticketTifName, ticketTypeName as typeName } from "./ticket-parts";
15
16
  import { brokerOrderDone, orderEstimatePrice, ticketEditingPriceStep } from "./orders-data";
17
+ import { linkedFeature, trailingText, trailingUnit, type LinkedFeature } from "./linked-orders";
16
18
 
17
- export type TicketAction = "enable" | "review" | "submit" | "back" | "confirm" | "refresh" | "orders" | "new" | "cancel" | "all" | "quantity25" | "quantity50" | "priceBid" | "priceMid" | "priceAsk" | "priceLast";
18
- export type TicketField = "action" | "orderType" | "quantity" | "limitPrice" | "stopPrice" | "tif" | "outsideRth" | "typedConfirmation" | "confirmOrders";
19
+ export type TicketAction = "enable" | "review" | "submit" | "back" | "confirm" | "refresh" | "orders" | "new" | "cancel" | "all" | "quantity25" | "quantity50" | "priceBid" | "priceMid" | "priceAsk" | "priceLast" | "priceChart";
20
+ export type TicketField = "action" | "orderType" | "quantity" | "limitPrice" | "stopPrice" | "tif" | "outsideRth" | "typedConfirmation" | "confirmOrders"
21
+ | "bracket" | "takeProfitPrice" | "stopLossPrice" | "trailing" | "trailingUnit";
19
22
  export interface TicketViewModel {
20
23
  brokerName: string; symbol: string; accounts: BrokerAccount[]; accountId?: string;
21
24
  accountChoices?: readonly BrokerAccountChoice[]; accountChoiceValue?: string;
22
25
  quote?: Quote; quoteData?: "realtime" | "delayed";
26
+ /** The quote is not current (older than the ticket accepts, or of unknown age): it shows its age beside it. */
27
+ quoteStale?: boolean;
23
28
  /** A spread's legs' quotes, in leg order. `quote` is then the spread's own. */
24
29
  legQuotes?: Quote[];
25
30
  phase: "enable" | "editing" | "previewing" | "review" | "submitting" | "result" | "cancel-review" | "cancelling";
@@ -49,21 +54,26 @@ export interface BrokerTicketViewProps {
49
54
  onClose?(): void;
50
55
  /** Terminal content measurement; the DOM uses intrinsic flex layout. */
51
56
  onContentHeight?(height: number): void;
57
+ /** With a chart beside the ticket: pick a price on it for this field, or for the entry's without one. */
58
+ onPickPrice?(field?: TicketField): void;
52
59
  }
53
- /** "Limit at $759.50 · Day", "Stop $750.00 · Day": an order's terms, each named once. */
54
- function orderTerms(order: Pick<BrokerOrder, "orderType" | "limitPrice" | "stopPrice" | "tif"> & { outsideRth?: boolean }, limitWord: string, money: (value: number) => string): string {
60
+ /**
61
+ * "Limit at $759.50 · Day", "Stop $750.00 · Day", "Trailing $1.50 · Day", "Limit $790.00 · stop $740.00, one cancels
62
+ * the other · GTC": an order's terms, each named once.
63
+ */
64
+ function orderTerms(order: Pick<BrokerOrder, "orderType" | "limitPrice" | "stopPrice" | "tif" | "trailingAmount" | "trailingPercent"> & Pick<BrokerOrderRequest, "orderClass" | "stopLossPrice"> & { outsideRth?: boolean },
65
+ limitWord: string, money: (value: number) => string): string {
55
66
  const limit = order.limitPrice !== undefined ? `${limitWord} ${money(order.limitPrice)}` : "";
56
67
  const stop = order.stopPrice !== undefined ? `Stop ${money(order.stopPrice)}` : "";
57
- const price = order.orderType === "STP" && stop ? [stop] : order.orderType === "STP LMT" && stop ? [stop, ...(order.limitPrice !== undefined ? [`limit ${money(order.limitPrice)}`] : [])]
68
+ const price = order.orderType === "TRAIL" ? [trailingText(order, money)]
69
+ : order.orderClass === "oco" ? [`Limit ${money(order.limitPrice ?? NaN)}`, `stop ${money(order.stopLossPrice ?? NaN)}, one cancels the other`]
70
+ : order.orderType === "STP" && stop ? [stop] : order.orderType === "STP LMT" && stop ? [stop, ...(order.limitPrice !== undefined ? [`limit ${money(order.limitPrice)}`] : [])]
58
71
  : [`${typeName[order.orderType] ?? order.orderType}${limit ? ` ${limit}` : ""}`, ...(stop ? [stop] : [])];
59
72
  return [...price, ...(order.tif ? [ticketTifName[order.tif] ?? order.tif] : []), ...(order.outsideRth ? ["Outside RTH"] : [])].join(" · ");
60
73
  }
61
74
 
62
75
  export function ticketQuoteAge(quote: Quote | undefined, now = Date.now()): string {
63
- const at = quote?.lastTradeTime ?? quote?.lastUpdated;
64
- if (!at || at > now) return "Age unknown";
65
- const seconds = Math.max(0, Math.floor((now - at) / 1000));
66
- return seconds < 60 ? `${seconds}s old` : seconds < 3600 ? `${Math.floor(seconds / 60)}m old` : `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m old`;
76
+ return quoteAgeText(quote?.lastTradeTime ?? quote?.lastUpdated, now);
67
77
  }
68
78
  /** The decimals a price step needs: 0.01 and 0.05 take two, 0.0001 four. Never fewer than two. */
69
79
  function stepDecimals(step: number): number {
@@ -84,6 +94,8 @@ function replacementChanges(original: BrokerOrder, draft: BrokerOrderRequest, pr
84
94
  original.quantity !== draft.quantity ? `Quantity ${number(original.quantity)} → ${number(draft.quantity)}` : "",
85
95
  original.limitPrice !== draft.limitPrice && draft.limitPrice !== undefined ? `Limit ${price(original.limitPrice)} → ${price(draft.limitPrice)}` : "",
86
96
  original.stopPrice !== draft.stopPrice && draft.stopPrice !== undefined ? `Stop ${price(original.stopPrice)} → ${price(draft.stopPrice)}` : "",
97
+ original.trailingAmount !== draft.trailingAmount && draft.trailingAmount !== undefined ? `Trail ${price(original.trailingAmount)} → ${price(draft.trailingAmount)}` : "",
98
+ original.trailingPercent !== draft.trailingPercent && draft.trailingPercent !== undefined ? `Trail ${number(original.trailingPercent)}% → ${number(draft.trailingPercent)}%` : "",
87
99
  ].filter(Boolean);
88
100
  return changes.length ? changes.join(" · ") : "No change from the working order";
89
101
  }
@@ -119,10 +131,11 @@ function TicketNumberInput({ value, focused, onChange, ...props }: {
119
131
  /**
120
132
  * The docked quote: last price and change first, then bid in green and ask in
121
133
  * red with their sizes, as a broker's quote panel reads. A delayed quote shows
122
- * a clock whose tooltip names the source and its age.
134
+ * a clock whose tooltip names the source and its age; a stale one says its age
135
+ * beside the price, so the last session's book never reads as the market.
123
136
  */
124
- function DockedQuote({ quote, delayed, source, updated, price, change, width }: {
125
- quote?: Quote; delayed: boolean; source: string; updated: string; price(value: number | undefined): string; change: string; width: number;
137
+ function DockedQuote({ quote, delayed, stale, source, updated, price, change, width }: {
138
+ quote?: Quote; delayed: boolean; stale?: string; source: string; updated: string; price(value: number | undefined): string; change: string; width: number;
126
139
  }) {
127
140
  const c = useThemeColors();
128
141
  const native = useUiCapabilities().nativePaneChrome;
@@ -139,6 +152,7 @@ function DockedQuote({ quote, delayed, source, updated, price, change, width }:
139
152
  <FigureText>{quote?.price === undefined ? "--" : price(quote.price)}</FigureText>
140
153
  <Box flexGrow={1} minWidth={0}><FigureText part="sub" change={quote?.change}>{change}</FigureText></Box>
141
154
  {delayed ? <Box flexShrink={0} title={`${source} · ${updated}`}><Icon name="clock" color={c.warning} /></Box> : null}
155
+ {stale ? <Text fg={c.warning} flexShrink={0}>{stale}</Text> : null}
142
156
  </Box>
143
157
  <Box flexDirection="row" gap={2}>
144
158
  {side("Bid", quote?.bid, quote?.bidSize, c.positive)}
@@ -147,8 +161,11 @@ function DockedQuote({ quote, delayed, source, updated, price, change, width }:
147
161
  </Box>;
148
162
  }
149
163
 
164
+ /** The ticket prices a pick on the chart can set. */
165
+ const PRICE_FIELDS: readonly string[] = ["limitPrice", "stopPrice", "takeProfitPrice", "stopLossPrice"];
166
+
150
167
  /** One ticket presentation, with the same review and focus gates on every renderer. */
151
- export function BrokerTicketView({ model: m, width, height, focused, onEdit, onAction, onAccountChange, onCapture, docked = false, blocked = false, asking = false, onClose, onContentHeight }: BrokerTicketViewProps) {
168
+ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onAction, onAccountChange, onCapture, docked = false, blocked = false, asking = false, onClose, onContentHeight, onPickPrice }: BrokerTicketViewProps) {
152
169
  const c = useThemeColors();
153
170
  const native = useUiCapabilities().nativePaneChrome;
154
171
  const dialogOpen = useDialogState((state) => state.isOpen);
@@ -167,6 +184,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
167
184
  // A credit spread's preview reports what it receives as a negative cost.
168
185
  const previewCredit = (m.preview?.estimatedCost ?? 0) < 0;
169
186
  const previewCost = m.preview?.estimatedCost === undefined ? undefined : Math.abs(m.preview.estimatedCost);
187
+ const impactSource = ticketImpactSource(m.preview);
170
188
  const unit = strategy ? "spreads" : draft?.contract.secType === "OPT" ? "contracts" : "shares";
171
189
  const busy = blocked || ["previewing", "submitting", "cancelling"].includes(m.phase);
172
190
  const fast = mode === "simulation" && m.confirmOrders === false && !m.modifying;
@@ -175,6 +193,21 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
175
193
  const editing = m.phase === "editing" || m.phase === "previewing" || fastSubmitting;
176
194
  const showLimit = draft?.orderType === "LMT" || draft?.orderType === "STP LMT";
177
195
  const showStop = draft?.orderType === "STP" || draft?.orderType === "STP LMT";
196
+ // An OCO is a limit and a stop on one side; a bracket adds exits to an entry; a trailing stop follows the market.
197
+ const oco = draft?.orderClass === "oco";
198
+ const bracket = draft?.orderClass === "bracket";
199
+ const trailing = draft?.orderType === "TRAIL";
200
+ // A price can come from the chart beside the ticket; a spread's net premium is not on it.
201
+ const chartPick = !!onPickPrice && !strategy && (showLimit || showStop);
202
+ const trailUnit = draft ? trailingUnit(draft) : "amount";
203
+ const trailValue = trailUnit === "percent" ? draft?.trailingPercent : draft?.trailingAmount;
204
+ // What the broker cannot take is not offered. A draft that already holds one still shows it, to be taken off;
205
+ // review refuses it with the reason.
206
+ const offers = (feature: LinkedFeature, held: boolean) => held || linkedFeature(m.capabilities, feature, m.brokerName).available;
207
+ const showBracket = !!draft && !strategy && !m.modifying && !trailing && !oco && offers("bracket", bracket);
208
+ // One unit needs no switch: the field's suffix says which it is.
209
+ const trailUnits = m.capabilities?.trailing ?? [];
210
+ const showTrailUnit = trailUnits.length > 1 || !trailUnits.includes(trailUnit);
178
211
  const extendedHours = m.capabilities?.extendedHours && (!m.capabilities.extendedHoursTif || m.capabilities.extendedHoursTif.includes(draft?.tif ?? "DAY"));
179
212
  const inner = Math.max(28, width - (docked ? 2 : native ? 6 : 2));
180
213
  const formWidth = wide ? Math.min(74, Math.floor((inner - 3) * 0.58)) : inner;
@@ -203,8 +236,12 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
203
236
  if (m.phase === "enable") return ["enable", "back"];
204
237
  if (editing) return [
205
238
  "account", "action", "orderType", "quantity", "quantity25", "quantity50", "all",
206
- ...(showLimit ? ["limitPrice", "priceBid", "priceMid", "priceAsk", "priceLast"] : []),
207
- ...(showStop ? ["stopPrice"] : []),
239
+ ...(showLimit ? ["limitPrice", "priceBid", "priceMid", "priceAsk", "priceLast", ...(chartPick ? ["priceChart"] : [])] : []),
240
+ ...(showStop ? ["stopPrice", ...(chartPick && !showLimit ? ["priceChart"] : [])] : []),
241
+ ...(oco ? ["stopLossPrice"] : []),
242
+ ...(trailing ? ["trailing", ...(showTrailUnit ? ["trailingUnit"] : [])] : []),
243
+ ...(showBracket ? ["bracket"] : []),
244
+ ...(bracket ? ["takeProfitPrice", "stopLossPrice"] : []),
208
245
  "tif",
209
246
  ...(extendedHours ? ["outsideRth"] : []),
210
247
  ...(mode === "simulation" && !m.modifying ? ["confirmOrders"] : []),
@@ -216,7 +253,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
216
253
  if (finished) return ["new", "orders"];
217
254
  if (resultStatus === "UNKNOWN") return ["refresh", "orders"];
218
255
  return ["refresh", "orders", "new"];
219
- }, [m.phase, editing, review, live, showLimit, showStop, extendedHours, resultStatus, finished, m.tradingEnabled, mode, m.modifying]);
256
+ }, [m.phase, editing, review, live, showLimit, showStop, oco, trailing, showTrailUnit, showBracket, bracket, extendedHours, resultStatus, finished, m.tradingEnabled, mode, m.modifying, chartPick]);
220
257
  const previousFocus = useRef<{ phase: TicketViewModel["phase"]; revision?: number } | undefined>(undefined);
221
258
  useEffect(() => {
222
259
  if (previousFocus.current?.phase !== m.phase || previousFocus.current?.revision !== m.focusRevision) {
@@ -237,11 +274,15 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
237
274
  const typedMatches = !live || m.typedConfirmation?.trim().toUpperCase() === confirmationSymbol;
238
275
  const holdingBlocked = sell && !strategy && !m.capabilities?.shortSelling && (m.position === undefined || (draft?.quantity ?? 0) > Math.max(0, m.position));
239
276
  const validPrice = (value: number | undefined) => value !== undefined && Number.isFinite(value) && value > 0;
277
+ // A bracket needs one exit at least; each one shown is a price or left empty.
278
+ const exitOk = (value: number | undefined) => value === undefined || validPrice(value);
240
279
  const canReview = m.connected && m.tradingEnabled && !!account && !!draft && validPrice(draft.quantity) && !holdingBlocked && !busy
241
- && (!showLimit || validPrice(draft.limitPrice)) && (!showStop || validPrice(draft.stopPrice));
280
+ && (!showLimit || validPrice(draft.limitPrice)) && (!showStop || validPrice(draft.stopPrice)) && (!oco || validPrice(draft.stopLossPrice))
281
+ && (!trailing || validPrice(trailValue))
282
+ && (!bracket || exitOk(draft.takeProfitPrice) && exitOk(draft.stopLossPrice) && (validPrice(draft.takeProfitPrice) || validPrice(draft.stopLossPrice)));
242
283
  const blockingPreview = !!m.preview?.errors?.length;
243
284
  const canConfirm = review && typedMatches && !blockingPreview && m.connected && m.tradingEnabled && !busy;
244
- const textActive = ["quantity", "limitPrice", "stopPrice", "typedConfirmation"].includes(active);
285
+ const textActive = ["quantity", "limitPrice", "stopPrice", "takeProfitPrice", "stopLossPrice", "trailing", "typedConfirmation"].includes(active);
245
286
  // Leaving a field must return h/l to the research strip, including after a command.
246
287
  useEffect(() => {
247
288
  onCapture?.(focused && textActive);
@@ -259,8 +300,15 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
259
300
  if (active === "confirmOrders") { if (mode === "simulation" && !m.modifying) onEdit("confirmOrders", m.confirmOrders === false); return; }
260
301
  if (active === "tif") { if (!m.modifying) tifControl.current?.open(); return; }
261
302
  if (active === "outsideRth") { if (!m.modifying && extendedHours) onEdit("outsideRth", !draft?.outsideRth); return; }
303
+ if (active === "bracket") { onEdit("bracket", !bracket); return; }
304
+ if (active === "trailingUnit") {
305
+ const other = trailUnit === "percent" ? "amount" : "percent";
306
+ if (m.capabilities?.trailing?.includes(other)) onEdit("trailingUnit", other);
307
+ return;
308
+ }
262
309
  if (active === "review") { if (canReview) onAction("submit"); return; }
263
310
  if (active === "confirm") { if (canConfirm) onAction("confirm"); return; }
311
+ if (active === "priceChart") { onPickPrice?.(showLimit ? "limitPrice" : "stopPrice"); return; }
264
312
  if (quickActions.includes(active as TicketAction)) { if (!quickDisabled(active as TicketAction)) onAction(active as TicketAction); return; }
265
313
  if (active === "enable" && !m.connected) return;
266
314
  if (["back", "refresh", "orders", "new", "enable", "cancel"].includes(active)) onAction(active as TicketAction);
@@ -279,6 +327,8 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
279
327
  ...(showLimit || showStop ? ([["8", "Bid", "priceBid"], ["9", "Mid", "priceMid"], ["0", "Ask", "priceAsk"], ...(strategy ? [] : [["p", "Last", "priceLast"]] as const)] as const)
280
328
  .map(([key, label, action]) => actionShortcut(key, label, action, quickDisabled(action))) : []),
281
329
  ...(extendedHours ? [editShortcut("x", "Extended", "outsideRth", !draft?.outsideRth, !!m.modifying)] : []),
330
+ // The price being typed, or the entry's, from the chart beside the ticket.
331
+ ...(chartPick ? [keyAction("c", "hart price", () => onPickPrice!(PRICE_FIELDS.includes(active) ? active as TicketField : undefined))] : []),
282
332
  ] : review ? [actionShortcut("e", "dit", "back"), actionShortcut("o", "rders", "orders")]
283
333
  : m.phase === "enable" ? [actionShortcut("e", "nable", "enable", !m.connected)]
284
334
  : m.phase === "cancel-review" ? [actionShortcut("e", "dit", "back")]
@@ -301,6 +351,12 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
301
351
  if (!event.repeat) activate();
302
352
  return;
303
353
  }
354
+ // A price holds no letters: c in a price field picks that price on the chart beside the ticket.
355
+ if (chartPick && editing && !busy && event.name === "c" && !event.shift && PRICE_FIELDS.includes(active)) {
356
+ event.preventDefault(); event.stopPropagation();
357
+ if (!event.repeat) onPickPrice!(active as TicketField);
358
+ return;
359
+ }
304
360
  if (event.shift || event.targetEditable || textActive) return;
305
361
  const shortcut = shortcuts.find((item) => item.key === event.name);
306
362
  if (!shortcut) return;
@@ -344,8 +400,9 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
344
400
  };
345
401
  const quick = (key: TicketAction, label: string, disabled = false) => <Box ref={nodeRef(key)} key={key}>
346
402
  <Button label={label} displayLabel={!native && marker(key) ? `> ${label}` : undefined} variant="quiet" compact active={active === key && focused}
347
- disabled={disabled || busy} onPress={() => { setActive(key); onAction(key); }} />
403
+ disabled={disabled || busy} onPress={() => { setActive(key); if (key === "priceChart") onPickPrice?.(showLimit ? "limitPrice" : "stopPrice"); else onAction(key); }} />
348
404
  </Box>;
405
+ const numericLabels: Partial<Record<TicketField, string>> = { limitPrice: "Limit price", stopPrice: "Stop price", takeProfitPrice: "Take profit price", stopLossPrice: oco ? "Stop price" : "Stop loss price", trailing: trailUnit === "percent" ? "Trailing percent" : "Trailing amount" };
349
406
  const numeric = (key: TicketField, label: string, value: number | undefined, suffix: string, picks?: ReactNode) => {
350
407
  const inlinePicks = !!picks && formWidth >= 60;
351
408
  const quantity = key === "quantity";
@@ -353,12 +410,13 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
353
410
  const quantityStep = m.capabilities?.fractionalQuantity ? reportedStep : wholeNumberStep(reportedStep) ?? NaN;
354
411
  // Decimal precision is not a declared exchange tick. The fallback is an editing convenience only.
355
412
  const priceStep = m.capabilities?.priceStep ?? ticketEditingPriceStep(value ?? m.quote?.price, m.capabilities?.priceDecimals);
356
- const step = quantity ? quantityStep : priceStep;
413
+ // A trailing percent steps by a tenth of a point.
414
+ const step = quantity ? quantityStep : key === "trailing" && trailUnit === "percent" ? 0.1 : priceStep;
357
415
  return <Box flexDirection="column" gap={0}>
358
416
  <Box flexDirection="row" alignItems="center" gap={1}>
359
417
  <Box ref={nodeRef(key)} onMouseDown={() => { if (!busy) setActive(key); }} flexDirection="row" alignItems="center" gap={1} flexGrow={1}>
360
418
  <FieldLabel label={label} width={labelWidth} active={active === key} />
361
- <Box flexGrow={1}><TicketNumberInput accessibleLabel={key === "limitPrice" ? "Limit price" : key === "stopPrice" ? "Stop price" : label} value={value}
419
+ <Box flexGrow={1}><TicketNumberInput accessibleLabel={numericLabels[key] ?? label} value={value}
362
420
  width={Math.max(14, formWidth - (docked ? 11 : native ? 21 : 24) - (inlinePicks ? 20 : 0))} focused={focused && active === key && !busy} active={active === key} disabled={busy}
363
421
  step={step} min={quantity ? Math.max(step, m.capabilities?.minQuantity ?? step) : step} max={quantity && sell && !m.capabilities?.shortSelling ? Math.max(0, m.position ?? 0) : undefined}
364
422
  onChange={(text) => { if (!busy) onEdit(key, text); }} onSubmit={() => setActive(m.tradingEnabled ? "review" : "enable")} /></Box>
@@ -377,6 +435,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
377
435
  const updated = sourceAt && Number.isFinite(sourceAt) ? `${new Date(sourceAt).toISOString().slice(11, 19)} UTC` : "unknown";
378
436
  const delayed = m.quoteData !== "realtime" || m.quote?.dataSource !== "live";
379
437
  const age = ticketQuoteAge(m.quote, m.now).replace(" old", "");
438
+ const stale = m.quote && m.quoteStale ? ticketQuoteAge(m.quote, m.now) : undefined;
380
439
  const source = `${m.brokerName}, ${delayed ? "delayed" : "real-time"} ${age}`;
381
440
  const accountPicker = (pickerWidth: number) => <BrokerAccountPicker
382
441
  accounts={m.accountChoices ?? m.accounts.map((a) => ({ value: a.accountId, label: a.name, tradingMode: a.tradingMode }))}
@@ -402,7 +461,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
402
461
  <Box ref={nodeRef("account")} flexShrink={1} minWidth={0}>{accountPicker(width - (onClose ? 6 : 2))}</Box>
403
462
  {onClose ? <IconButton icon="close" label="Close trade panel" shortcut="Esc" onPress={onClose} /> : null}
404
463
  </Box>
405
- <DockedQuote quote={m.quote} delayed={delayed} source={source} updated={updated} price={quotePrice} change={change} width={width - 2} />
464
+ <DockedQuote quote={m.quote} delayed={delayed} stale={stale} source={source} updated={updated} price={quotePrice} change={change} width={width - 2} />
406
465
  </Box> : <Box flexShrink={0}>
407
466
  <Box flexDirection="column" data-gloom-selectable="true" paddingX={native ? 3 : 1} paddingY={native ? wide ? 1 : 0.5 : 0} gap={native ? wide ? 0.65 : 0.2 : 0} >
408
467
  <Box flexDirection={narrow ? "column" : "row"} justifyContent="space-between" alignItems={narrow ? "flex-start" : "center"} gap={narrow ? 0.4 : 1}>
@@ -429,7 +488,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
429
488
  <Box flexDirection="row" flexWrap={native ? "wrap" : "nowrap"} alignItems="center" gap={1}>
430
489
  {/* A delayed quote is the yellow clock, as in pane footers, with the detail on hover. */}
431
490
  {delayed ? <Box flexShrink={0} title={source}><Icon name="clock" color={c.warning} /></Box> : null}
432
- <Text fg={c.textDim}>{delayed ? `${m.brokerName} ${age}` : source}</Text>
491
+ <Text fg={stale ? c.warning : c.textDim}>{stale ? `${m.brokerName}, ${stale}` : delayed ? `${m.brokerName} ${age}` : source}</Text>
433
492
  <Text fg={c.textDim}>{`${updated}${m.synthetic && !wide && !narrow ? " · SYNTHETIC" : ""}`}</Text>
434
493
  </Box>
435
494
  </Box>
@@ -447,7 +506,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
447
506
  <TicketSection width={formWidth} title={m.modifying ? "Modify order" : docked ? undefined : "Order details"}>
448
507
  <Box flexDirection="column" gap={rowGap}>
449
508
  {!m.connected ? m.reconnecting ? <Notice tone="muted">{`Reconnecting to ${m.brokerName}...`}</Notice> : <Notice variant="callout">Broker disconnected. Connect in Brokers.</Notice>
450
- : !m.tradingEnabled ? <Notice variant="callout">Trading is off for this profile.</Notice> : null}
509
+ : !m.tradingEnabled ? <Notice variant="callout">{m.capabilities?.disabledReason ?? "Trading is off for this profile."}</Notice> : null}
451
510
  <Box ref={nodeRef("action")} flexDirection="row" onMouseDown={() => setActive("action")}>
452
511
  {!native ? <FieldLabel label="" width={2} active={focused && active === "action"} /> : null}
453
512
  <Box flexGrow={1}><SegmentedControl variant="flat" accessibleLabel="Order side" value={draft.action} size="large" width="100%"
@@ -456,8 +515,13 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
456
515
  </Box>
457
516
  <Box ref={nodeRef("orderType")} flexDirection="row" gap={1} alignItems="center" onMouseDown={() => { if (!busy) setActive("orderType"); }}>
458
517
  <FieldLabel label={docked ? "Type" : "Order type"} width={labelWidth} active={active === "orderType"} />
459
- <SelectButton label="Order type" showLabel={false} variant="well" width={selectWidth} value={draft.orderType}
460
- options={(m.capabilities?.orderTypes ?? ["LMT"]).map((t) => ({ value: t, label: typeName[t] ?? t }))} disabled={busy || m.modifying}
518
+ <SelectButton label="Order type" showLabel={false} variant="well" width={selectWidth} value={oco ? "OCO" : draft.orderType}
519
+ options={[...(m.capabilities?.orderTypes ?? ["LMT"]).filter((t) => t !== "TRAIL").map((t) => ({ value: t, label: typeName[t] ?? t })),
520
+ // A spread takes neither; elsewhere each is listed where the broker takes it.
521
+ ...(strategy ? [] : [
522
+ ...(offers("trailing", trailing) ? [{ value: "TRAIL", label: typeName.TRAIL! }] : []),
523
+ ...(offers("oco", oco) ? [{ value: "OCO", label: "OCO", description: "A limit and a stop: one filling cancels the other" }] : []),
524
+ ])]} disabled={busy || m.modifying}
461
525
  emphasized={focused && active === "orderType"} controlRef={orderTypeControl} onFocus={() => setActive("orderType")} onChange={(v) => onEdit("orderType", v)} />
462
526
  </Box>
463
527
  {strategy ? <TicketLegs model={m} width={formWidth} inset /> : null}
@@ -471,8 +535,23 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
471
535
  {quick("priceMid", "Mid", !(m.quote?.bid! > 0) || !(m.quote?.ask! > 0))}
472
536
  {quick("priceAsk", "Ask", !(m.quote?.ask! > 0))}
473
537
  {strategy ? null : quick("priceLast", "Last", !m.quote?.price)}
538
+ {chartPick ? quick("priceChart", "Chart") : null}
474
539
  </>) : null}
475
- {showStop ? numeric("stopPrice", docked ? "Stop" : "Stop price", draft.stopPrice, currency) : null}
540
+ {showStop ? numeric("stopPrice", docked ? "Stop" : "Stop price", draft.stopPrice, currency, chartPick && !showLimit ? quick("priceChart", "Chart") : undefined) : null}
541
+ {oco ? numeric("stopLossPrice", docked ? "Stop" : "Stop price", draft.stopLossPrice, currency) : null}
542
+ {trailing ? numeric("trailing", "Trail", trailValue, trailUnit === "percent" ? "%" : currency, showTrailUnit ? <Box ref={nodeRef("trailingUnit")} onMouseDown={() => { if (!busy) setActive("trailingUnit"); }}>
543
+ <SegmentedControl accessibleLabel="Trailing unit" value={trailUnit} focused={focused && active === "trailingUnit"} shortcutScope={scope}
544
+ options={[{ value: "amount", label: "Price", disabled: busy || !m.capabilities?.trailing?.includes("amount") },
545
+ { value: "percent", label: "%", disabled: busy || !m.capabilities?.trailing?.includes("percent") }]}
546
+ onChange={(value) => { setActive("trailingUnit"); onEdit("trailingUnit", value); }} />
547
+ </Box> : undefined) : null}
548
+ {showBracket ? <Box ref={nodeRef("bracket")} flexDirection="column" onMouseDown={() => { if (!busy) setActive("bracket"); }}>
549
+ <Checkbox label="Take profit / stop loss" checked={bracket} disabled={busy} active={focused && active === "bracket"}
550
+ onChange={(value) => { setActive("bracket"); onEdit("bracket", value); }} />
551
+ </Box> : null}
552
+ {/* Beside the chart, under "Take profit / stop loss", as the order rows tag them. */}
553
+ {bracket ? numeric("takeProfitPrice", docked ? "TP" : "Take profit", draft.takeProfitPrice, currency) : null}
554
+ {bracket ? numeric("stopLossPrice", docked ? "SL" : "Stop loss", draft.stopLossPrice, currency) : null}
476
555
  <Box flexDirection="row" flexWrap="wrap" alignItems="center" gap={docked ? rowGap : 1}>
477
556
  <Box ref={nodeRef("tif")} flexDirection="row" alignItems="center" gap={1} onMouseDown={() => setActive("tif")}>
478
557
  <FieldLabel label="TIF" width={labelWidth} active={active === "tif"} />
@@ -513,17 +592,22 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
513
592
  <TicketOrderHeadline model={m} large />
514
593
  {strategy ? <TicketLegs model={m} width={formWidth} /> : null}
515
594
  <Text fg={c.textDim}>{orderTerms({ orderType: draft?.orderType ?? "LMT", limitPrice: showLimit ? draft?.limitPrice : undefined,
516
- stopPrice: showStop ? draft?.stopPrice : undefined, tif: draft?.tif ?? "DAY", outsideRth: draft?.outsideRth }, strategy ? sell ? "net credit" : "net debit" : "at", (value) => money(value, currency))}</Text>
595
+ stopPrice: showStop ? draft?.stopPrice : undefined, tif: draft?.tif ?? "DAY", outsideRth: draft?.outsideRth, trailingAmount: draft?.trailingAmount, trailingPercent: draft?.trailingPercent,
596
+ orderClass: draft?.orderClass, stopLossPrice: draft?.stopLossPrice }, strategy ? sell ? "net credit" : "net debit" : "at", (value) => money(value, currency))}</Text>
517
597
  {m.original && draft ? <Text fg={c.warning}>{replacementChanges(m.original, draft, (value) => money(value, currency))}</Text> : null}
598
+ {bracket ? <TicketExits model={m} width={formWidth} currency={currency} /> : null}
518
599
  <Box marginTop={native && wide ? 1 : 0} flexDirection="column" gap={native && wide ? 0.4 : 0}>
519
- <TicketReceiptRow label="Fees" value={money(m.preview?.fees, currency)} width={formWidth} />
520
- <TicketReceiptRow label="Commission" value={money(m.preview?.commission, m.preview?.commissionCurrency ?? currency)} width={formWidth} />
600
+ {impactSource ? <TicketReceiptRow label="Impact source" value={impactSource} width={formWidth} /> : null}
601
+ <TicketReceiptRow label="Fees" value={ticketImpactMoney(m.preview, m.preview?.fees, currency)} width={formWidth} />
602
+ <TicketReceiptRow label="Commission" value={ticketImpactMoney(m.preview, m.preview?.commission, m.preview?.commissionCurrency ?? currency)} width={formWidth} />
521
603
  {!wide ? <TicketOrderSummary model={m} width={formWidth} compact receipt /> : null}
522
604
  </Box>
523
605
  <Box flexDirection="row" justifyContent="space-between" alignItems={native ? "baseline" : "center"} paddingTop={native && wide ? 0.7 : 0}>
524
606
  <Text fg={c.textDim}>{previewCredit ? "Estimated credit" : "Estimated cost"}</Text>
525
- <FigureText>{money(previewCost, currency)}</FigureText>
607
+ <FigureText>{ticketImpactMoney(m.preview, previewCost, currency)}</FigureText>
526
608
  </Box>
609
+ {/* The broker's terms for its figures, before the order is confirmed. */}
610
+ {m.preview?.disclosure ? <Text fg={c.textDim} wrapText>{m.preview.disclosure}</Text> : null}
527
611
  {/* Beside the chart, warnings are lines, so the place button fits without scrolling. */}
528
612
  {warnings.map((warning, index) => <Notice key={index} variant={docked ? undefined : "callout"} tone="warning">{warning}</Notice>)}
529
613
  {m.preview?.errors?.map((error, index) => <Notice key={index} variant={docked ? undefined : "callout"} tone="negative">{error}</Notice>)}
@@ -545,16 +629,18 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
545
629
  </TicketSection> : null}
546
630
  {m.phase === "result" ? <Box flexDirection={wide ? "row" : "column"} gap={3}><TicketSection width={formWidth} title={title} selectable>
547
631
  <TicketOrderHeadline model={m} large />{strategy ? <TicketLegs model={m} width={formWidth} /> : null}
548
- {m.result ? <Text fg={c.textDim}>{orderTerms(m.result, strategy ? "net" : "at", (value) => money(value, currency))}</Text> : null}
632
+ {m.result ? <Text fg={c.textDim}>{orderTerms({ ...m.result, orderClass: draft?.orderClass, stopLossPrice: draft?.stopLossPrice }, strategy ? "net" : "at", (value) => money(value, currency))}</Text> : null}
633
+ {bracket ? <TicketExits model={m} width={formWidth} currency={currency} /> : null}
549
634
  <TicketStatus model={m} width={formWidth} />
550
635
  {m.resultQuantities === "last-known" ? <Text fg={c.warning}>Last known quantities</Text> : null}
551
636
  {!["PARTIALLY_FILLED", "FILLED"].includes(resultStatus) ? <TicketReceiptRow label="Filled" value={resultQuantity(m.result?.filled)} width={formWidth} /> : null}
552
637
  <TicketReceiptRow label="Remaining" value={resultQuantity(m.result?.remaining)} width={formWidth} />
553
638
  <Text fg={c.textDim}>Estimates from order preview</Text>
554
- <TicketReceiptRow label={previewCredit ? "Preview credit" : "Preview cost"} value={money(previewCost, currency)} width={formWidth} />
555
- <TicketReceiptRow label="Fees" value={money(m.preview?.fees, currency)} width={formWidth} />
556
- <TicketReceiptRow label="Commission" value={money(m.preview?.commission, m.preview?.commissionCurrency ?? currency)} width={formWidth} />
639
+ <TicketReceiptRow label={previewCredit ? "Preview credit" : "Preview cost"} value={ticketImpactMoney(m.preview, previewCost, currency)} width={formWidth} />
640
+ <TicketReceiptRow label="Fees" value={ticketImpactMoney(m.preview, m.preview?.fees, currency)} width={formWidth} />
641
+ <TicketReceiptRow label="Commission" value={ticketImpactMoney(m.preview, m.preview?.commission, m.preview?.commissionCurrency ?? currency)} width={formWidth} />
557
642
  {m.preview?.buyingPowerAfter !== undefined ? <TicketReceiptRow label="Buying power after" value={money(m.preview.buyingPowerAfter, currency)} width={formWidth} /> : null}
643
+ {m.preview?.cashAfter !== undefined ? <TicketReceiptRow label="Cash after" value={money(m.preview.cashAfter, currency)} width={formWidth} /> : null}
558
644
  {m.error && !["UNKNOWN", "REJECTED"].includes(resultStatus) ? <Notice variant="callout" tone="negative">{m.error}</Notice> : null}
559
645
  {!finished && resultStatus !== "UNKNOWN" ? <Box flexDirection="row" alignItems="center" gap={1}>
560
646
  {action("refresh", "Refresh status", false, false, "neutral", true)}<Text fg={c.textDim}>·</Text>
@@ -19,6 +19,8 @@ import { favoriteKey } from "./table-model";
19
19
 
20
20
  interface BuildoutCellContext {
21
21
  favoriteBusyKey: string | null;
22
+ /** The row's last star did not take. */
23
+ favoriteFailed?: boolean;
22
24
  toggleFavorite: (row: BuildoutRow) => void | Promise<void>;
23
25
  }
24
26
 
@@ -60,6 +62,7 @@ export function renderBuildoutCell(
60
62
  <FavoriteCell
61
63
  starred={company.starred === true}
62
64
  busy={busy}
65
+ failed={context.favoriteFailed}
63
66
  selected={rowState.selected}
64
67
  onPress={() => { void context.toggleFavorite(row); }}
65
68
  />
@@ -120,6 +123,7 @@ export function renderBuildoutCell(
120
123
  <FavoriteCell
121
124
  starred={site.starred === true}
122
125
  busy={busy}
126
+ failed={context.favoriteFailed}
123
127
  selected={rowState.selected}
124
128
  onPress={() => { void context.toggleFavorite(row); }}
125
129
  />
@@ -1,5 +1,5 @@
1
1
  import { Box, ScrollBox } from "../../../../ui";
2
- import { EmptyState } from "../../../../components";
2
+ import { EmptyState, Notice } from "../../../../components";
3
3
  import type { BuildoutRow } from "../model/types";
4
4
  import type { InlineTickerCatalog } from "./ui";
5
5
  import { CompanyDetail } from "./company";
@@ -13,12 +13,15 @@ export {
13
13
 
14
14
  export function BuildoutDetail({
15
15
  row,
16
+ note = null,
16
17
  width,
17
18
  height,
18
19
  catalog,
19
20
  openTicker,
20
21
  }: {
21
22
  row: BuildoutRow | null;
23
+ /** What the row's last star ran into, in full. */
24
+ note?: string | null;
22
25
  width: number;
23
26
  height: number;
24
27
  catalog: InlineTickerCatalog;
@@ -45,6 +48,7 @@ export function BuildoutDetail({
45
48
  focusable={false}
46
49
  >
47
50
  <Box flexDirection="column" paddingX={1} width={bodyWidth}>
51
+ {note ? <Box paddingBottom={1}><Notice tone="negative">{note}</Notice></Box> : null}
48
52
  {row.kind === "company" ? (
49
53
  <CompanyDetail
50
54
  company={row.item}
@@ -5,7 +5,7 @@ import { ExternalLinkText } from "../../../../components/ui/external-link";
5
5
  import { ClippedText } from "../../../../components/ui/display";
6
6
  import type { InlineTickerCatalogEntry } from "../../../../state/hooks/inline-tickers";
7
7
  import { colors } from "../../../../theme/colors";
8
- import { Box, Text } from "../../../../ui";
8
+ import { Box, Text, TextAttributes } from "../../../../ui";
9
9
  import { truncateWithEllipsis } from "../../../../utils/text-wrap";
10
10
  import { sourceDetailEntries, text, textOrNull, tickerSymbol } from "../format";
11
11
  import type { BuildoutCompany, BuildoutRelatedCompany, BuildoutSource } from "../model/types";
@@ -182,18 +182,21 @@ export function MarkdownBlock({
182
182
  export function FavoriteCell({
183
183
  starred,
184
184
  busy,
185
+ failed = false,
185
186
  selected,
186
187
  onPress,
187
188
  }: {
188
189
  starred: boolean;
189
190
  busy: boolean;
191
+ /** The last star did not take: a `!` in the error tone, the reason in the row's detail. */
192
+ failed?: boolean;
190
193
  selected: boolean;
191
194
  onPress?: () => void;
192
195
  }) {
193
196
  return (
194
197
  <Button
195
- label={starred ? "Remove favorite" : "Add favorite"}
196
- displayLabel={busy ? "*" : starred ? "★" : "☆"}
198
+ label={failed ? starred ? "Unstarring failed. Remove favorite" : "Starring failed. Add favorite" : starred ? "Remove favorite" : "Add favorite"}
199
+ displayLabel={busy ? "*" : failed ? "!" : starred ? "★" : "☆"}
197
200
  width={2}
198
201
  compact
199
202
  variant="plain"
@@ -201,7 +204,7 @@ export function FavoriteCell({
201
204
  disabled={busy || !onPress}
202
205
  stopPropagation
203
206
  onPress={onPress}
204
- />
207
+ >{failed && !busy ? <Text fg={colors.negative} attributes={TextAttributes.BOLD}>!</Text> : undefined}</Button>
205
208
  );
206
209
  }
207
210