gloomberb 0.18.0 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/package.json +1 -1
  2. package/src/api-client/commodity-balances.ts +6 -0
  3. package/src/api-client/company-kpis.ts +9 -0
  4. package/src/api-client/crypto-markets.ts +9 -0
  5. package/src/api-client/data.ts +6 -5
  6. package/src/api-client/equity-screener.ts +2 -0
  7. package/src/api-client/market-movers.ts +7 -0
  8. package/src/api-client/types.ts +14 -0
  9. package/src/app/pane-runtime/plugin-bindings.ts +3 -1
  10. package/src/app/pane-runtime/ticker-open-runtime.ts +17 -5
  11. package/src/app/runtime/plugin-bindings.ts +6 -2
  12. package/src/brokers/logos.ts +66 -0
  13. package/src/brokers/profile-form.ts +3 -0
  14. package/src/brokers/remote-broker-adapter.ts +13 -3
  15. package/src/capabilities/index.ts +1 -1
  16. package/src/capabilities/service-capabilities.ts +7 -1
  17. package/src/cli/base-converter.ts +60 -18
  18. package/src/cli/commands/fred-series.ts +15 -5
  19. package/src/cli/commands/market.ts +290 -159
  20. package/src/cli/commands/news-search.ts +35 -8
  21. package/src/cli/commands/overview.ts +31 -6
  22. package/src/cli/commands/system.ts +35 -1
  23. package/src/cli/commands/ticker.ts +105 -52
  24. package/src/cli/currency-hints.ts +27 -0
  25. package/src/cli/fx-pair.ts +41 -4
  26. package/src/cli/glossary.ts +57 -4
  27. package/src/cli/helpers.ts +36 -3
  28. package/src/cli/index.ts +4 -1
  29. package/src/cli/known-gaps.ts +37 -1
  30. package/src/cli/listing-arg.ts +37 -2
  31. package/src/cli/pane-functions/catalog.ts +3 -1
  32. package/src/cli/pane-functions/discovery.ts +15 -1
  33. package/src/cli/pane-functions/dom.ts +9 -4
  34. package/src/cli/pane-functions/freshness.ts +4 -4
  35. package/src/cli/pane-functions/function-help.ts +31 -7
  36. package/src/cli/pane-functions/headless.ts +6 -5
  37. package/src/cli/pane-functions/index.ts +3 -2
  38. package/src/cli/pane-functions/lock-note.ts +7 -4
  39. package/src/cli/pane-functions/resolver.ts +2 -1
  40. package/src/cli/quote-answer.ts +179 -0
  41. package/src/cli/series-search.ts +2 -1
  42. package/src/cli/symbol-list.ts +51 -16
  43. package/src/cli/types.ts +4 -0
  44. package/src/components/chart/composite/composite-chart.tsx +22 -7
  45. package/src/components/chart/composite/format.ts +13 -1
  46. package/src/components/chart/composite/level-labels.ts +30 -0
  47. package/src/components/chart/composite/levels.ts +17 -6
  48. package/src/components/chart/composite/panel-surface.tsx +64 -16
  49. package/src/components/chart/composite/price-axis-labels.tsx +2 -1
  50. package/src/components/chart/composite/types.ts +4 -0
  51. package/src/components/command-bar/routes/ticker-search/actions.ts +6 -0
  52. package/src/components/command-bar/workflow/collection-actions.ts +4 -0
  53. package/src/components/index.ts +2 -0
  54. package/src/components/layout/pane/content.tsx +16 -14
  55. package/src/components/layout/pane/footer/index.tsx +22 -3
  56. package/src/components/layout/pane/footer/model.ts +99 -4
  57. package/src/components/layout/pane/header-tabs.tsx +15 -1
  58. package/src/components/onboarding/onboarding-frame.tsx +9 -11
  59. package/src/components/onboarding/use-onboarding-broker-form.ts +5 -2
  60. package/src/components/onboarding/wizard-model.ts +10 -3
  61. package/src/components/onboarding/wizard-positions.ts +8 -0
  62. package/src/components/ui/button.tsx +11 -4
  63. package/src/components/ui/choice-dialog.tsx +8 -5
  64. package/src/components/ui/display.tsx +11 -6
  65. package/src/components/ui/fields.tsx +100 -20
  66. package/src/components/ui/icon.tsx +6 -1
  67. package/src/components/ui/list-row-lines.tsx +87 -0
  68. package/src/components/ui/list-view.tsx +14 -0
  69. package/src/components/ui/logo-mark.tsx +64 -0
  70. package/src/components/ui/number-step.ts +54 -0
  71. package/src/components/ui/select-button.tsx +5 -4
  72. package/src/components/ui/select-field.tsx +3 -3
  73. package/src/components/ui/status.tsx +17 -3
  74. package/src/components/ui/tabs.tsx +9 -1
  75. package/src/components/ui/toggle.tsx +17 -3
  76. package/src/core/state/app/instrument.ts +8 -3
  77. package/src/data/config/store/normalize.ts +4 -1
  78. package/src/data/plugin-cache.ts +32 -6
  79. package/src/docs/snapshot.json +57 -22
  80. package/src/i18n/es.ts +9 -3
  81. package/src/i18n/ja.ts +9 -3
  82. package/src/i18n/ko.ts +9 -3
  83. package/src/i18n/zh-cn.ts +10 -4
  84. package/src/i18n/zh-tw.ts +10 -4
  85. package/src/market-data/commodity-names.ts +80 -0
  86. package/src/market-data/coordinator/auxiliary.ts +3 -1
  87. package/src/market-data/coordinator/chart.ts +3 -1
  88. package/src/market-data/futures-board.ts +38 -1
  89. package/src/market-data/futures-contract.ts +91 -0
  90. package/src/market-data/fx-closes.ts +78 -1
  91. package/src/market-data/market/change-basis.ts +219 -0
  92. package/src/market-data/market/format.ts +28 -12
  93. package/src/market-data/market/freshness.ts +38 -0
  94. package/src/market-data/market/status.ts +55 -9
  95. package/src/market-data/market/year-to-date.ts +46 -0
  96. package/src/market-data/quotes/contributions.ts +12 -0
  97. package/src/market-data/quotes/delisting.ts +34 -0
  98. package/src/market-data/quotes/live-valuation.ts +23 -0
  99. package/src/market-data/quotes/resolution.ts +8 -2
  100. package/src/market-data/tax-equivalent.ts +10 -2
  101. package/src/notifications/app-notifier.ts +2 -2
  102. package/src/notifications/notification-log.ts +8 -6
  103. package/src/plugins/builtin/alerts/cli.ts +26 -18
  104. package/src/plugins/builtin/alerts/headless.ts +1 -1
  105. package/src/plugins/builtin/alerts/index.tsx +13 -4
  106. package/src/plugins/builtin/analytics/index.tsx +1 -1
  107. package/src/plugins/builtin/analytics/risk-client.ts +44 -11
  108. package/src/plugins/builtin/analytics/risk-fx.ts +61 -0
  109. package/src/plugins/builtin/analytics/risk-headless.ts +10 -1
  110. package/src/plugins/builtin/analytics/risk-model.ts +79 -16
  111. package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
  112. package/src/plugins/builtin/analytics/risk-test-data.ts +3 -0
  113. package/src/plugins/builtin/attention/trending.tsx +8 -6
  114. package/src/plugins/builtin/backtest/client.ts +5 -2
  115. package/src/plugins/builtin/backtest/window.ts +16 -3
  116. package/src/plugins/builtin/broker-manager/add-flow.tsx +40 -8
  117. package/src/plugins/builtin/broker-manager/detail.tsx +26 -1
  118. package/src/plugins/builtin/broker-manager/index.tsx +20 -9
  119. package/src/plugins/builtin/broker-manager/model.ts +5 -0
  120. package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -1
  121. package/src/plugins/builtin/broker-manager/table.ts +5 -1
  122. package/src/plugins/builtin/broker-trading/account-picker.tsx +91 -0
  123. package/src/plugins/builtin/broker-trading/chart-levels.ts +54 -0
  124. package/src/plugins/builtin/broker-trading/command.ts +103 -0
  125. package/src/plugins/builtin/broker-trading/controller.ts +688 -0
  126. package/src/plugins/builtin/broker-trading/dock.tsx +182 -0
  127. package/src/plugins/builtin/broker-trading/headless.ts +76 -0
  128. package/src/plugins/builtin/broker-trading/index.tsx +77 -0
  129. package/src/plugins/builtin/broker-trading/order-feed.ts +383 -0
  130. package/src/plugins/builtin/broker-trading/orders-data.ts +133 -0
  131. package/src/plugins/builtin/broker-trading/orders.tsx +437 -0
  132. package/src/plugins/builtin/broker-trading/overview-orders.tsx +121 -0
  133. package/src/plugins/builtin/broker-trading/pane-model.ts +207 -0
  134. package/src/plugins/builtin/broker-trading/pane.tsx +505 -0
  135. package/src/plugins/builtin/broker-trading/strategy.ts +153 -0
  136. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +117 -0
  137. package/src/plugins/builtin/broker-trading/ticket.tsx +573 -0
  138. package/src/plugins/builtin/buildout/data-runtime.ts +1 -1
  139. package/src/plugins/builtin/buildout/format.ts +1 -0
  140. package/src/plugins/builtin/buildout/model/index.ts +16 -7
  141. package/src/plugins/builtin/buildout/pane/index.tsx +3 -2
  142. package/src/plugins/builtin/buildout/pane/status.tsx +3 -3
  143. package/src/plugins/builtin/chart-composer/cli-options.ts +19 -0
  144. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  145. package/src/plugins/builtin/chart-composer/headless-schema.ts +3 -3
  146. package/src/plugins/builtin/chart-composer/headless.ts +2 -1
  147. package/src/plugins/builtin/chart-composer/option-range.ts +39 -0
  148. package/src/plugins/builtin/chart-composer/pane.tsx +31 -11
  149. package/src/plugins/builtin/chart-composer/presets.ts +2 -2
  150. package/src/plugins/builtin/chart-composer/series-catalog.ts +4 -2
  151. package/src/plugins/builtin/chart-composer/shortcuts.ts +3 -3
  152. package/src/plugins/builtin/chart-composer/viewport-labels.ts +5 -2
  153. package/src/plugins/builtin/chat/index.tsx +1 -1
  154. package/src/plugins/builtin/chat/status-widget.tsx +1 -1
  155. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +6 -1
  156. package/src/plugins/builtin/chat/unread-inbox.ts +1 -1
  157. package/src/plugins/builtin/cloud/team/pane-sections.tsx +10 -3
  158. package/src/plugins/builtin/cloud/team/pane.tsx +30 -9
  159. package/src/plugins/builtin/commodity-balances/client.ts +6 -4
  160. package/src/plugins/builtin/commodity-balances/headless.ts +41 -7
  161. package/src/plugins/builtin/commodity-balances/index.tsx +19 -4
  162. package/src/plugins/builtin/commodity-balances/model.ts +22 -0
  163. package/src/plugins/builtin/commodity-balances/pane.tsx +36 -5
  164. package/src/plugins/builtin/company-kpis/client.ts +3 -2
  165. package/src/plugins/builtin/company-kpis/headless.ts +5 -7
  166. package/src/plugins/builtin/company-kpis/model.ts +85 -2
  167. package/src/plugins/builtin/company-kpis/pane.tsx +26 -12
  168. package/src/plugins/builtin/composite-plugins.ts +3 -2
  169. package/src/plugins/builtin/cot/headless.ts +1 -1
  170. package/src/plugins/builtin/cot/index.tsx +1 -1
  171. package/src/plugins/builtin/cot/model.ts +35 -12
  172. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +2 -1
  173. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +2 -1
  174. package/src/plugins/builtin/credit-conditions/index.tsx +2 -1
  175. package/src/plugins/builtin/crypto-board/client.ts +33 -2
  176. package/src/plugins/builtin/crypto-board/headless.ts +5 -2
  177. package/src/plugins/builtin/crypto-board/model.ts +28 -8
  178. package/src/plugins/builtin/custom-view/loader.ts +3 -2
  179. package/src/plugins/builtin/custom-view/pane.tsx +5 -4
  180. package/src/plugins/builtin/custom-view/view-spec.ts +1 -0
  181. package/src/plugins/builtin/dividend-yield/headless.ts +30 -8
  182. package/src/plugins/builtin/dividend-yield/provider-client.ts +3 -1
  183. package/src/plugins/builtin/earnings-calls/headless.ts +4 -4
  184. package/src/plugins/builtin/earnings-calls/lock-note.ts +12 -3
  185. package/src/plugins/builtin/econ/calendar-model.ts +38 -2
  186. package/src/plugins/builtin/econ/fred-catalog.ts +6 -2
  187. package/src/plugins/builtin/econ/fred-series-map.ts +12 -1
  188. package/src/plugins/builtin/econ/index.tsx +31 -4
  189. package/src/plugins/builtin/econ/print-watch.ts +279 -0
  190. package/src/plugins/builtin/equity-screener/headless.ts +20 -5
  191. package/src/plugins/builtin/equity-screener/model.ts +40 -2
  192. package/src/plugins/builtin/equity-screener/pane.tsx +24 -21
  193. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -2
  194. package/src/plugins/builtin/estimate-revisions/lock-note.ts +29 -7
  195. package/src/plugins/builtin/executives/data.ts +24 -8
  196. package/src/plugins/builtin/executives/index.tsx +2 -18
  197. package/src/plugins/builtin/executives/pane.tsx +34 -10
  198. package/src/plugins/builtin/exposure/client.ts +4 -1
  199. package/src/plugins/builtin/exposure/editor.tsx +3 -3
  200. package/src/plugins/builtin/exposure/evidence.ts +4 -1
  201. package/src/plugins/builtin/exposure/holdings.ts +3 -1
  202. package/src/plugins/builtin/exposure/pane.tsx +37 -16
  203. package/src/plugins/builtin/filing-events/index.tsx +9 -3
  204. package/src/plugins/builtin/futures/table.tsx +6 -3
  205. package/src/plugins/builtin/futures-curve/pane.tsx +2 -2
  206. package/src/plugins/builtin/insider/base-values.ts +72 -0
  207. package/src/plugins/builtin/insider/headless.ts +29 -4
  208. package/src/plugins/builtin/jobs/headless.ts +2 -2
  209. package/src/plugins/builtin/jobs/lock-note.ts +14 -3
  210. package/src/plugins/builtin/market-halts/model.ts +31 -6
  211. package/src/plugins/builtin/market-halts/pane.tsx +3 -0
  212. package/src/plugins/builtin/market-movers/client.ts +2 -2
  213. package/src/plugins/builtin/market-movers/index.tsx +0 -3
  214. package/src/plugins/builtin/market-movers/session-body.tsx +27 -11
  215. package/src/plugins/builtin/market-movers/session.ts +25 -10
  216. package/src/plugins/builtin/market-valuation/pane.tsx +2 -1
  217. package/src/plugins/builtin/members/pane.tsx +8 -3
  218. package/src/plugins/builtin/news/wire/feed-config.ts +33 -13
  219. package/src/plugins/builtin/news/wire/index.tsx +7 -2
  220. package/src/plugins/builtin/news/wire/letters/client.ts +1 -0
  221. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +6 -3
  222. package/src/plugins/builtin/news/wire/news/detail-view.tsx +2 -1
  223. package/src/plugins/builtin/news/wire/news/preset-pane.tsx +11 -3
  224. package/src/plugins/builtin/news/wire/news/table.tsx +2 -1
  225. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -2
  226. package/src/plugins/builtin/news/wire/rss/feed-xml.ts +6 -1
  227. package/src/plugins/builtin/news/wire/rss/managed-feed.ts +1 -0
  228. package/src/plugins/builtin/news/wire/rss/source.ts +13 -4
  229. package/src/plugins/builtin/notes/cli.ts +33 -8
  230. package/src/plugins/builtin/notes/export.ts +49 -3
  231. package/src/plugins/builtin/notes/files.ts +14 -3
  232. package/src/plugins/builtin/notes/index.tsx +3 -3
  233. package/src/plugins/builtin/notes/quick-notes-pane.tsx +45 -10
  234. package/src/plugins/builtin/notes/store.ts +13 -3
  235. package/src/plugins/builtin/options/footer.ts +25 -20
  236. package/src/plugins/builtin/options/live-quotes.ts +33 -18
  237. package/src/plugins/builtin/options/view.tsx +77 -22
  238. package/src/plugins/builtin/options-calculator/pane.tsx +4 -2
  239. package/src/plugins/builtin/options-scenario/pane.tsx +41 -6
  240. package/src/plugins/builtin/portfolio-list/account-metrics.ts +3 -0
  241. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +8 -7
  242. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +166 -15
  243. package/src/plugins/builtin/portfolio-list/cli/render.ts +69 -15
  244. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +2 -2
  245. package/src/plugins/builtin/portfolio-list/headless.ts +3 -1
  246. package/src/plugins/builtin/portfolio-list/pane/data.ts +23 -1
  247. package/src/plugins/builtin/portfolio-list/pane/index.tsx +44 -17
  248. package/src/plugins/builtin/portfolio-list/settings.ts +20 -2
  249. package/src/plugins/builtin/portfolio-list/summary/index.tsx +22 -1
  250. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +42 -7
  251. package/src/plugins/builtin/portfolio-list/summary/totals.ts +24 -3
  252. package/src/plugins/builtin/primary-dealers/client.ts +137 -62
  253. package/src/plugins/builtin/primary-dealers/headless.ts +30 -5
  254. package/src/plugins/builtin/primary-dealers/index.tsx +3 -2
  255. package/src/plugins/builtin/primary-dealers/model.ts +179 -129
  256. package/src/plugins/builtin/primary-dealers/pane.tsx +135 -15
  257. package/src/plugins/builtin/research/analyst-model.ts +5 -1
  258. package/src/plugins/builtin/risk-factors/index.tsx +12 -3
  259. package/src/plugins/builtin/scanner/feed.ts +6 -1
  260. package/src/plugins/builtin/scanner/headless.ts +1 -1
  261. package/src/plugins/builtin/scanner/lock-note.ts +3 -2
  262. package/src/plugins/builtin/series-inventory.ts +1 -0
  263. package/src/plugins/builtin/shared/broker-reconnect.ts +105 -0
  264. package/src/plugins/builtin/shared/cloud-denied.ts +7 -6
  265. package/src/plugins/builtin/shared/cloud-upgrade.ts +10 -11
  266. package/src/plugins/builtin/shared/free-routes.ts +24 -0
  267. package/src/plugins/builtin/shared/headless-options.ts +11 -0
  268. package/src/plugins/builtin/shared/pro-feature-wall.tsx +9 -4
  269. package/src/plugins/builtin/shared/pro-lock-note.ts +89 -7
  270. package/src/plugins/builtin/shared/research-trading.tsx +62 -0
  271. package/src/plugins/builtin/social-mentions/headless.ts +1 -1
  272. package/src/plugins/builtin/social-mentions/lock-note.ts +1 -1
  273. package/src/plugins/builtin/themes/headless.ts +8 -2
  274. package/src/plugins/builtin/themes/model.ts +43 -10
  275. package/src/plugins/builtin/themes/pane.tsx +8 -6
  276. package/src/plugins/builtin/thirteenf/api.ts +4 -1
  277. package/src/plugins/builtin/thirteenf/data.ts +5 -1
  278. package/src/plugins/builtin/thirteenf/headless.ts +3 -1
  279. package/src/plugins/builtin/thirteenf/pane.tsx +8 -3
  280. package/src/plugins/builtin/ticker-detail/overview/model.ts +44 -10
  281. package/src/plugins/builtin/ticker-detail/overview/option-contract.ts +64 -0
  282. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +82 -21
  283. package/src/plugins/builtin/ticker-detail/pane.tsx +21 -14
  284. package/src/plugins/builtin/ticker-detail/quote-footer.ts +5 -1
  285. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +37 -8
  286. package/src/plugins/builtin/time-sales/pane.tsx +2 -2
  287. package/src/plugins/builtin/trace-bonds/client.ts +14 -3
  288. package/src/plugins/builtin/trace-bonds/headless.ts +1 -1
  289. package/src/plugins/builtin/vol-surface/pane.tsx +2 -2
  290. package/src/plugins/builtin-editorial.ts +1 -1
  291. package/src/plugins/compat.ts +3 -0
  292. package/src/plugins/external-runtime.ts +5 -0
  293. package/src/plugins/loader.ts +6 -0
  294. package/src/plugins/plugin-icon.ts +61 -0
  295. package/src/plugins/registry/host-actions.ts +2 -1
  296. package/src/plugins/registry/index.ts +9 -1
  297. package/src/plugins/runtime/context.tsx +5 -0
  298. package/src/plugins/runtime/index.tsx +3 -0
  299. package/src/portfolio/column-values.ts +13 -4
  300. package/src/portfolio/cost-fx.ts +61 -0
  301. package/src/portfolio/mutations.ts +16 -2
  302. package/src/portfolio/position-metrics.ts +45 -4
  303. package/src/portfolio/position-quantity.ts +43 -0
  304. package/src/public/__snapshots__/public-api.test.ts.snap +5 -0
  305. package/src/public/broker.ts +8 -0
  306. package/src/public/market-data.ts +5 -0
  307. package/src/renderers/dom/desktop/control-styles.ts +7 -1
  308. package/src/renderers/dom/desktop/controls.tsx +39 -7
  309. package/src/renderers/dom/desktop/icons.tsx +14 -0
  310. package/src/renderers/dom/desktop/list-view.tsx +51 -19
  311. package/src/renderers/dom/desktop/menu.tsx +10 -1
  312. package/src/renderers/dom/desktop/select-field.tsx +8 -6
  313. package/src/renderers/dom/host/style.ts +6 -1
  314. package/src/renderers/dom/host/tabs.tsx +6 -0
  315. package/src/renderers/dom/styles.css +12 -5
  316. package/src/renderers/electrobun/bun/core-capabilities.ts +12 -0
  317. package/src/renderers/electrobun/bun/external-plugins.ts +3 -0
  318. package/src/renderers/electrobun/shared/protocol.ts +2 -0
  319. package/src/renderers/electrobun/view/broker-remote-client.ts +16 -0
  320. package/src/renderers/electrobun/view/external-plugins.ts +1 -0
  321. package/src/series/validate.ts +2 -2
  322. package/src/sources/gloomberb-cloud/fred-series.ts +27 -2
  323. package/src/sources/gloomberb-cloud/index.ts +50 -17
  324. package/src/sources/gloomberb-cloud/normalizers.ts +4 -0
  325. package/src/sources/history-result.ts +3 -0
  326. package/src/sources/provider-errors.ts +3 -1
  327. package/src/sources/provider-router/history.ts +49 -6
  328. package/src/sources/provider-router/index.ts +2 -1
  329. package/src/state/app/activity.ts +13 -0
  330. package/src/sync/controller.ts +4 -0
  331. package/src/sync/core-contributors.ts +63 -11
  332. package/src/sync/local-only.ts +121 -0
  333. package/src/sync/react.ts +6 -0
  334. package/src/sync/types.ts +3 -0
  335. package/src/team/collections.ts +2 -0
  336. package/src/tickers/listing-fate.ts +27 -8
  337. package/src/tickers/metadata.ts +10 -0
  338. package/src/tickers/search/index.ts +24 -3
  339. package/src/time-series/price-comparison.ts +35 -0
  340. package/src/time-series/resolve.ts +52 -11
  341. package/src/time-series/spec.ts +1 -1
  342. package/src/time-series/types.ts +5 -0
  343. package/src/types/broker.ts +56 -1
  344. package/src/types/config.ts +6 -0
  345. package/src/types/data-provider.ts +5 -1
  346. package/src/types/financials.ts +23 -0
  347. package/src/types/headless.ts +12 -2
  348. package/src/types/instrument.ts +4 -0
  349. package/src/types/plugin.ts +24 -6
  350. package/src/types/price-history.ts +6 -1
  351. package/src/types/ticker.ts +9 -0
  352. package/src/types/trading.ts +67 -0
  353. package/src/ui/host.tsx +4 -0
  354. package/src/utils/base-currency.ts +108 -0
  355. package/src/utils/currency-names.ts +128 -0
  356. package/src/utils/currency-pair.ts +2 -1
  357. package/src/utils/currency-units.ts +41 -1
  358. package/src/utils/dom-screenshot.ts +22 -9
  359. package/src/utils/exchange-notation.generated.ts +360 -0
  360. package/src/utils/exchanges.ts +15 -322
  361. package/src/utils/format.ts +31 -1
  362. package/src/utils/instrument-identity.ts +38 -1
  363. package/src/utils/options.ts +46 -1
  364. package/src/utils/price-history.ts +4 -0
  365. package/src/utils/reported-money.ts +8 -4
@@ -1,6 +1,7 @@
1
1
  import { logFailure } from "../utils/log-failure";
2
2
  import { resolveAssetDisplayKind } from "../market-data/market/format";
3
3
  import { hasValidQuoteObservationTime } from "../market-data/quotes/freshness";
4
+ import { delistingLabel } from "../market-data/quotes/delisting";
4
5
  import { SnapshotHistoryUnavailableError } from "../market-data/snapshot-provider";
5
6
  import { financialPeriodCoverage, financialPeriodCoverageWarnings, limitSeriesObservations } from "./financial-period-coverage";
6
7
  import { HistoryCoverageError, historyCoverageNotice } from "../sources/history-coverage";
@@ -10,6 +11,7 @@ import { getRouterEntityKey } from "../sources/provider-router/cache";
10
11
  import { publicListingTarget } from "../sources/listing-target";
11
12
  import { fetchHistoryResult } from "../sources/history-result";
12
13
  import type { HistorySession, PriceHistoryResult } from "../types/price-history";
14
+ import type { BrokerContractRef } from "../types/instrument";
13
15
  import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../utils/financial-statements";
14
16
  import { appendLiveQuotePoint, hasUnknownBondHistoryBasis } from "./chart-data";
15
17
  import { LiveBarAccumulator } from "./live-bars";
@@ -63,7 +65,7 @@ import {
63
65
  } from "./studies";
64
66
  import { applyResolvedSeriesTransform } from "./transforms";
65
67
  import { clipSeriesToWindow } from "./alignment";
66
- import { clipPriceComparison, priceComparisonBoundsForSeries, priceComparisonSeriesIds, priceObservationWindowFilter, resolvePriceComparison, type PriceComparison } from "./price-comparison";
68
+ import { bufferPriceComparison, clipPriceComparison, comparedBufferPoints, priceComparisonBoundsForSeries, priceComparisonSeriesIds, priceObservationWindowFilter, resolvePriceComparison, type PriceComparison } from "./price-comparison";
67
69
  import { reportingCurrencySeries } from "./reporting-currency";
68
70
  import { chartQuoteOverrideKeyForSource, compareChartQuoteRecency } from "./live-quotes";
69
71
  import { chartSeriesSourceKey } from "../capabilities/chart-series";
@@ -754,8 +756,8 @@ export function seedChartResolutionResult(
754
756
  const axisWarnings: string[] = [];
755
757
  const bufferedSeries = assignAxes([
756
758
  ...baseSeries,
757
- ...applyStudyPresentationTransforms(studies.series, spec.studies, series, comparisonBounds, undefined, priceComparison),
758
- ], [...spec.series, ...spec.studies], axisWarnings).map((entry) => clipPriceComparison(entry, priceComparison));
759
+ ...applyStudyPresentationTransforms(studies.series, spec.studies, series, comparisonBounds, undefined, priceComparison, bounds),
760
+ ], [...spec.series, ...spec.studies], axisWarnings).map((entry) => bufferPriceComparison(entry, priceComparison, bounds));
759
761
  const visible = bufferedSeries.map((entry) => {
760
762
  const entryBounds = presentationBounds(entry, spec.studies, priceComparison, bounds);
761
763
  const clipped = entryBounds.start !== null && entryBounds.end !== null
@@ -1168,6 +1170,17 @@ async function loadPriceHistory(
1168
1170
  return { ...result, expiresAt: retryAt ?? Date.now() + HISTORY_RETENTION_MAX_AGE_MS };
1169
1171
  }
1170
1172
 
1173
+ /**
1174
+ * A US stock or fund listing, including one a broker contract routes through
1175
+ * SMART in dollars. Options and futures have no pre-market session.
1176
+ */
1177
+ function tradesUsExtendedHours(exchange: string | undefined, contract: BrokerContractRef | null | undefined): boolean {
1178
+ if (contract?.secType && !["STK", "ETF"].includes(contract.secType.toUpperCase())) return false;
1179
+ const venue = exchange || contract?.primaryExchange || contract?.exchange;
1180
+ return isUsListingExchange(venue) || isUsListingExchange(contract?.primaryExchange)
1181
+ || (!!contract && canonicalExchange(venue) === "SMART" && (!contract.currency || contract.currency.toUpperCase() === "USD"));
1182
+ }
1183
+
1171
1184
  function baseSecuritySeries(
1172
1185
  spec: ChartSeriesSpec,
1173
1186
  financials: TickerFinancials,
@@ -1185,7 +1198,8 @@ function baseSecuritySeries(
1185
1198
  const symbol = instrumentLabel(spec.source);
1186
1199
  const statementCurrency = field.id.startsWith("fundamental.") && field.unit.startsWith("currency")
1187
1200
  ? reportingCurrencySeries(points, financials.financialCurrency) : null;
1188
- const currency = statementCurrency ? statementCurrency.currency : financials.quote?.currency || quoteMetadata?.currency;
1201
+ // A broker contract names its currency even before (or without) a quote.
1202
+ const currency = statementCurrency ? statementCurrency.currency : financials.quote?.currency || quoteMetadata?.currency || spec.source.instrument.instrument?.currency;
1189
1203
  const assetKind = resolveAssetDisplayKind({ assetCategory: financials.quote?.instrumentType || quoteMetadata?.instrumentType });
1190
1204
  const unknownBondBasis = hasUnknownBondHistoryBasis(financials.quote,
1191
1205
  spec.source.instrument.instrument?.secType, quoteMetadata?.instrumentType);
@@ -1220,10 +1234,25 @@ function baseSecuritySeries(
1220
1234
  || financials.quote?.listingExchangeName
1221
1235
  || financials.quote?.exchangeName;
1222
1236
  const marketField = isMarketFieldId(spec.source.fieldId);
1237
+ // A routing code such as a broker's SMART names no venue. The quote's
1238
+ // listing then supplies the session clock, so closed hours stay off the axis.
1239
+ const sessionExchange = [marketExchange, financials.quote?.listingExchangeName, quoteMetadata?.listingExchangeName, financials.quote?.exchangeName]
1240
+ .find((value) => resolveExchangeTimeZone(value));
1241
+ // A dollar listing saved with IBKR's SMART route and no other venue trades on
1242
+ // the US session, and so does a dollar option, which names no venue at all.
1243
+ const dollars = !currency || currency === "USD";
1244
+ const usOption = dollars && (spec.source.instrument.instrument?.secType?.toUpperCase() === "OPT"
1245
+ || /^OPTION$/i.test(financials.quote?.instrumentType ?? quoteMetadata?.instrumentType ?? ""));
1246
+ const routedUsListing = !sessionExchange && ((canonicalExchange(marketExchange) === "SMART" && dollars) || usOption);
1223
1247
  const marketTimeZone = marketField
1224
1248
  && canonicalExchange(marketExchange) !== "CCC"
1225
- ? resolveExchangeTimeZone(marketExchange)
1249
+ ? resolveExchangeTimeZone(sessionExchange) ?? (routedUsListing ? "America/New_York" : null)
1226
1250
  : null;
1251
+ // A route has no hours of its own: its sessions, which the day view and
1252
+ // VWAP follow, are the venue's, and NYSE's for an unnamed dollar listing.
1253
+ const listingExchange = canonicalExchange(marketExchange) === "SMART" || usOption
1254
+ ? canonicalExchange(sessionExchange) || (routedUsListing ? "NYSE" : marketExchange)
1255
+ : marketExchange;
1227
1256
  const latestChangePercent = marketField && field.unit.startsWith("currency")
1228
1257
  && !unknownBondBasis
1229
1258
  && financials.quote && hasValidQuoteObservationTime(financials.quote)
@@ -1259,12 +1288,12 @@ function baseSecuritySeries(
1259
1288
  panelId: spec.panelId,
1260
1289
  interpolation: spec.interpolation,
1261
1290
  observationKind: marketField ? "market" : undefined,
1262
- ...(marketField ? { listing: { symbol: spec.source.instrument.symbol, exchange: marketExchange ?? "" } } : {}),
1291
+ ...(marketField ? { listing: { symbol: spec.source.instrument.symbol, exchange: listingExchange ?? "" } } : {}),
1263
1292
  timeBasis: marketTimeZone
1264
1293
  ? {
1265
1294
  kind: "market",
1266
1295
  timeZone: marketTimeZone,
1267
- exchange: canonicalExchange(marketExchange) || undefined,
1296
+ exchange: canonicalExchange(sessionExchange) || undefined,
1268
1297
  cadenceMs: marketResolution
1269
1298
  ? CHART_RESOLUTION_STEP_MS[marketResolution]
1270
1299
  : undefined,
@@ -1487,6 +1516,7 @@ function applyStudyPresentationTransforms(
1487
1516
  visibleBounds: DateBounds,
1488
1517
  fallbackBaselineBounds?: DateBounds,
1489
1518
  priceComparison?: PriceComparison | null,
1519
+ view: DateBounds = visibleBounds,
1490
1520
  ): ResolvedSeries[] {
1491
1521
  const rawById = new Map(rawSeries.map((series) => [series.id, series] as const));
1492
1522
  return outputs.map((output) => {
@@ -1502,7 +1532,7 @@ function applyStudyPresentationTransforms(
1502
1532
  : undefined;
1503
1533
  const transformed = applyResolvedSeriesTransform(output, input.transform, { baseline });
1504
1534
  const inputBounds = priceComparison?.sourceBounds?.[input.id];
1505
- return inputBounds ? { ...transformed, points: filterPoints(transformed.points, inputBounds) } : transformed;
1535
+ return inputBounds ? { ...transformed, points: comparedBufferPoints(transformed.points, inputBounds, view) } : transformed;
1506
1536
  });
1507
1537
  }
1508
1538
 
@@ -1612,6 +1642,7 @@ async function resolveChartSpecPass(
1612
1642
  && entry.source.kind === "security" && isFundamentalFieldId(entry.source.fieldId))
1613
1643
  ? [FINANCIAL_VINTAGE_NOTICE] : [];
1614
1644
  const priorityWarnings: string[] = [];
1645
+ const delistings = new Map<string, { symbol: string; label: string; notice: string }>();
1615
1646
  const baseSeriesIds = new Set(spec.series.map((entry) => entry.id));
1616
1647
  const visibleSeriesIds = new Set(spec.series
1617
1648
  .filter((entry) => entry.visible !== false)
@@ -1813,10 +1844,10 @@ async function resolveChartSpecPass(
1813
1844
  const hasExplicitWindow = explicitBounds(spec) !== null || movedWindow;
1814
1845
  const initialCalculationBounds = calculationBounds(spec, requestVisibleBounds, initialResolution);
1815
1846
 
1816
- // Only US listings trade before and after the regular session; asking elsewhere costs a request for nothing.
1847
+ // Only US stocks and funds trade before and after the regular session; asking elsewhere costs a request for nothing.
1817
1848
  const extendedHoursFor = (source: Extract<ChartSeriesSpec["source"], { kind: "security" }>, resolution: ManualChartResolution) => (
1818
1849
  spec.viewport.extendedHours === true && isMarketFieldId(source.fieldId) && isIntradayResolution(resolution)
1819
- && !source.instrument.instrument && isUsListingExchange(source.instrument.exchange)
1850
+ && tradesUsExtendedHours(source.instrument.exchange, source.instrument.instrument)
1820
1851
  );
1821
1852
  // A history starts after the visible window because its source keeps no more.
1822
1853
  let retainedHistoryOnly = false;
@@ -1952,6 +1983,14 @@ async function resolveChartSpecPass(
1952
1983
  const history = loaded.points;
1953
1984
  const coverageNotice = historyCoverageNotice(loaded.coverageStart, request.visibleBounds.start);
1954
1985
  if (coverageNotice) priorityWarnings.push(coverageNotice);
1986
+ // A listing that no longer trades is named so beside its bars, which end on its last session.
1987
+ if (loaded.delisting) {
1988
+ const symbol = parsePublicTickerKey(source.instrument.symbol).symbol;
1989
+ const label = delistingLabel(loaded.delisting);
1990
+ const notice = `${symbol}: ${label}`;
1991
+ priorityWarnings.push(notice);
1992
+ if (!delistings.has(notice)) delistings.set(notice, { symbol, label, notice });
1993
+ }
1955
1994
  // Read per request: one recovered window answers every visible window that shares its acquisition.
1956
1995
  if (loaded.recovery && request.visibleBounds.start !== null && request.visibleBounds.start < loaded.recovery.start) {
1957
1996
  priorityWarnings.push(historyRetentionNotice(loaded.recovery.retention, loaded.resolution ?? request.resolution,
@@ -2294,6 +2333,7 @@ async function resolveChartSpecPass(
2294
2333
  comparisonBounds,
2295
2334
  priceComparison ? undefined : requestVisibleBounds,
2296
2335
  priceComparison,
2336
+ bounds,
2297
2337
  ),
2298
2338
  ];
2299
2339
  warnings.push(...studyResult.warnings);
@@ -2301,7 +2341,7 @@ async function resolveChartSpecPass(
2301
2341
  }
2302
2342
 
2303
2343
  const bufferedSeries = assignAxes(adoptPriceUnits(resolved, spec.series), [...spec.series, ...spec.studies], warnings)
2304
- .map((entry) => clipPriceComparison(entry, priceComparison));
2344
+ .map((entry) => bufferPriceComparison(entry, priceComparison, bounds));
2305
2345
  resolved = bufferedSeries.map((entry) => {
2306
2346
  const entryBounds = presentationBounds(entry, spec.studies, priceComparison, bounds);
2307
2347
  return entryBounds.start !== null && entryBounds.end !== null
@@ -2388,6 +2428,7 @@ async function resolveChartSpecPass(
2388
2428
  loading: false,
2389
2429
  errors,
2390
2430
  warnings: [...new Set([...priorityWarnings, ...warnings])],
2431
+ ...(delistings.size ? { delistings: [...delistings.values()] } : {}),
2391
2432
  viewport,
2392
2433
  resolution,
2393
2434
  };
@@ -85,7 +85,7 @@ export function coerceSeriesInterpolationForStyle(
85
85
  return style === "step" ? "step-after" : "none";
86
86
  }
87
87
 
88
- export const MAX_CHART_SERIES = 10;
88
+ export const MAX_CHART_SERIES = 20;
89
89
 
90
90
  export const DEFAULT_CHART_SPEC: ChartSpec = Object.freeze({
91
91
  version: CHART_SPEC_VERSION,
@@ -281,6 +281,11 @@ export interface ChartResolutionResult {
281
281
  loading: boolean;
282
282
  errors: string[];
283
283
  warnings: string[];
284
+ /**
285
+ * Each charted listing that no longer trades: its symbol and label
286
+ * ("Delisted Oct 27, 2022"), which `warnings` carries as "TWTR: Delisted Oct 27, 2022".
287
+ */
288
+ delistings?: { symbol: string; label: string; notice: string }[];
284
289
  /** Effective inclusive bounds used to clip the resolved chart data. */
285
290
  viewport?: { start: Date; end: Date };
286
291
  /** Bar resolution the loaded market history was fetched at. */
@@ -11,6 +11,7 @@ import type {
11
11
  BrokerOrderPreview,
12
12
  BrokerOrderRequest,
13
13
  BrokerPortfolioPerformance,
14
+ BrokerTradingCapabilities,
14
15
  } from "./trading";
15
16
  import type { CachePolicy, CachePolicyMap } from "./persistence";
16
17
 
@@ -85,10 +86,44 @@ export interface BrokerProfileAction {
85
86
  disabledReason?: string;
86
87
  }
87
88
 
89
+ /** How a chart asks a broker for history beyond the regular session. */
90
+ export interface BrokerHistoryOptions {
91
+ /** Include pre-market and after-hours bars. Only a broker that sets `extendedHoursHistory` is asked. */
92
+ session?: "extended";
93
+ }
94
+
95
+ /** What a broker's order stream calls. */
96
+ export interface BrokerOrderListener {
97
+ /**
98
+ * An order as the broker now reports it: placed, partly or wholly filled,
99
+ * replaced, cancelled, rejected or expired. The same `orderId` names the
100
+ * order through all of them, as `getOrderStatus` and `cancelOrder` take it.
101
+ */
102
+ order(order: BrokerOrder): void;
103
+ /**
104
+ * Whether changes are being pushed now. While false, as before the first
105
+ * call, the host polls open orders instead; on true it reconciles once.
106
+ */
107
+ live?(live: boolean): void;
108
+ }
109
+
88
110
  export interface BrokerAdapter {
89
111
  readonly id: string;
90
112
  readonly name: string;
91
113
  readonly cachePolicy?: CachePolicyMap;
114
+ /**
115
+ * Intraday history includes pre-market and after-hours bars when its
116
+ * `BrokerHistoryOptions` ask for the extended session. The chart then
117
+ * starts the day at the pre-market open; without it, the regular session.
118
+ */
119
+ readonly extendedHoursHistory?: boolean;
120
+ /**
121
+ * The quotes and bars this broker supplies stay on the user's device: Gloom Cloud sync never
122
+ * uploads them, for a broker whose terms restrict redistributing its market data. Its accounts
123
+ * sync like any broker's, unless the user keeps a connection on the device (`localOnly` on the
124
+ * profile). Hosts that honor it export `LOCAL_BROKER_MARKET_DATA` from `gloomberb/broker`.
125
+ */
126
+ readonly localMarketData?: boolean;
92
127
  validate(instance: BrokerInstanceConfig): Promise<boolean>;
93
128
  importPositions(instance: BrokerInstanceConfig): Promise<BrokerPosition[]>;
94
129
  importPortfolioSnapshot?(instance: BrokerInstanceConfig): Promise<{ accounts: BrokerAccount[]; positions: BrokerPosition[] }>;
@@ -116,9 +151,10 @@ export interface BrokerAdapter {
116
151
  bufferRange: TimeRange,
117
152
  resolution: ManualChartResolution,
118
153
  instrument?: BrokerContractRef | null,
154
+ options?: BrokerHistoryOptions,
119
155
  ): Promise<PricePoint[]>;
120
156
  /** Fetch higher-resolution price data for a specific date window (e.g. when zoomed in). */
121
- getDetailedPriceHistory?(ticker: string, instance: BrokerInstanceConfig, exchange: string, startDate: Date, endDate: Date, barSize: string, instrument?: BrokerContractRef | null): Promise<PricePoint[]>;
157
+ getDetailedPriceHistory?(ticker: string, instance: BrokerInstanceConfig, exchange: string, startDate: Date, endDate: Date, barSize: string, instrument?: BrokerContractRef | null, options?: BrokerHistoryOptions): Promise<PricePoint[]>;
122
158
  getChartResolutionSupport?(
123
159
  ticker: string,
124
160
  instance: BrokerInstanceConfig,
@@ -136,6 +172,8 @@ export interface BrokerAdapter {
136
172
  * Whether this profile can stream quotes at all. Return false for modes that
137
173
  * only sync statements, so their positions stream from the cloud instead.
138
174
  * Quotes are also only routed to a broker whose status is "connected".
175
+ * Answer from the profile's configuration, not from session state: the
176
+ * desktop app asks in its view, while the session lives in the backend.
139
177
  */
140
178
  canStreamQuotes?(instance: BrokerInstanceConfig): boolean;
141
179
  subscribeQuotes?(
@@ -144,8 +182,25 @@ export interface BrokerAdapter {
144
182
  onQuote: (target: QuoteSubscriptionTarget, quote: Quote) => void,
145
183
  ): () => void;
146
184
  listOpenOrders?(instance: BrokerInstanceConfig): Promise<BrokerOrder[]>;
185
+ /**
186
+ * Pushes order changes as the broker reports them, for every account the
187
+ * profile includes. The host baselines from `listOpenOrders` and polls it
188
+ * while `live` is false or never called; see BrokerOrderListener.
189
+ */
190
+ subscribeOrders?(instance: BrokerInstanceConfig, listener: BrokerOrderListener): () => void;
191
+ /** Explicit status, including terminal orders. Null means unconfirmed, never cancelled by absence. */
192
+ getOrderStatus?(instance: BrokerInstanceConfig, orderId: number): Promise<BrokerOrder | null>;
147
193
  listExecutions?(instance: BrokerInstanceConfig): Promise<BrokerExecution[]>;
194
+ /** Opt into the shared ticket with supported combinations and current trading permission. */
195
+ getTradingCapabilities?(instance: BrokerInstanceConfig, contract?: BrokerContractRef, orderType?: BrokerOrderRequest["orderType"]): BrokerTradingCapabilities;
196
+ /** Config patch for the host's explicit enable/disable trading confirmation. Must not perform I/O. */
197
+ getTradingConfigUpdate?(instance: BrokerInstanceConfig, enabled: boolean): Record<string, unknown>;
148
198
  previewOrder?(instance: BrokerInstanceConfig, request: BrokerOrderRequest): Promise<BrokerOrderPreview>;
199
+ /**
200
+ * Place, change and cancel throw when the broker did not take the action. An error with `refused: true` says the
201
+ * broker answered no, or nothing was sent: the order is as it was, and its message is one short line the app shows as
202
+ * it is ("Aries cannot find this order"). Any other error is a lost answer, whose outcome the app treats as unknown.
203
+ */
149
204
  placeOrder?(instance: BrokerInstanceConfig, request: BrokerOrderRequest): Promise<BrokerOrder>;
150
205
  modifyOrder?(instance: BrokerInstanceConfig, orderId: number, request: BrokerOrderRequest): Promise<BrokerOrder>;
151
206
  cancelOrder?(instance: BrokerInstanceConfig, orderId: number): Promise<void>;
@@ -18,6 +18,12 @@ export interface BrokerInstanceConfig {
18
18
  config: Record<string, unknown>;
19
19
  enabled?: boolean;
20
20
  lastSyncedAt?: number;
21
+ /**
22
+ * The user keeps this connection's data on this device: Cloud sync leaves out the profile, its
23
+ * accounts' portfolios and account values, and the positions in them. Daily roundups, the weekly
24
+ * brief, position alerts, the mobile app and Ask Gloom's portfolio context then go without it.
25
+ */
26
+ localOnly?: boolean;
21
27
  }
22
28
 
23
29
  export interface ColumnConfig {
@@ -119,7 +119,11 @@ export interface MarketDataRequestContext {
119
119
  brokerId?: string;
120
120
  brokerInstanceId?: string;
121
121
  instrument?: BrokerContractRef | null;
122
- cacheMode?: "default" | "refresh";
122
+ /**
123
+ * "refresh" always fetches. "current" refetches a stored value past its stale time before answering, and
124
+ * answers with it only if that fetch fails: for a caller that cannot see a refresh landing in the background.
125
+ */
126
+ cacheMode?: "default" | "refresh" | "current";
123
127
  statementHistory?: "extended";
124
128
  /** A validated, same-target detailed retry constrained to one exhausted source. */
125
129
  historyRecovery?: import("../sources/history-retention").HistoryRecoveryCandidate;
@@ -34,6 +34,20 @@ export interface QuoteProvenance {
34
34
  rejectedPriceProviders?: string[];
35
35
  }
36
36
 
37
+ /**
38
+ * A US listing that no longer trades, as Gloom Cloud states it: TWTR, last
39
+ * traded 2022-10-27 and removed from NYSE the next day. Its daily history is
40
+ * still served, ending on that session. Dates are New York trading dates.
41
+ */
42
+ export interface ListingDelisting {
43
+ /** "delisted": the exchange's removal of the listing is on record; "inactive": only its last trade is known. */
44
+ status: "delisted" | "inactive";
45
+ /** The last session with a trade (YYYY-MM-DD). */
46
+ lastTradeDate: string;
47
+ /** The first session served (YYYY-MM-DD). */
48
+ historyStart: string;
49
+ }
50
+
37
51
  /** Static listing facts from a quote observation, without an investable price. */
38
52
  export interface QuoteMetadataSource {
39
53
  providerId?: string;
@@ -81,6 +95,13 @@ export interface Quote extends DepositaryReceiptFacts {
81
95
  providerPriceDivisor?: number;
82
96
  change: number;
83
97
  changePercent: number;
98
+ /**
99
+ * What change and changePercent measure from when it is not previousClose,
100
+ * as Gloom Cloud says of a coin whose previous close it cannot date to the
101
+ * last two days: the last 24 hours ("24h", previousClose absent), or
102
+ * nothing ("none", no move). Absent on every other quote.
103
+ */
104
+ changeBasis?: "24h" | "none";
84
105
  previousClose?: number;
85
106
  /** Official close of a completed regular session, in this quote's currency. */
86
107
  regularClose?: number;
@@ -100,6 +121,8 @@ export interface Quote extends DepositaryReceiptFacts {
100
121
  receivedAt?: number; // local receipt timestamp ms for streamed/display freshness
101
122
  delivery?: QuoteDelivery;
102
123
  stale?: boolean;
124
+ /** The listing no longer trades: the price is its last trade (ListingDelisting). */
125
+ delisting?: ListingDelisting;
103
126
  exchangeName?: string;
104
127
  fullExchangeName?: string;
105
128
  listingExchangeName?: string;
@@ -103,6 +103,8 @@ export interface HeadlessPaneContext {
103
103
  /** Effective instance settings, after template creation and option normalization. */
104
104
  settings?: Record<string, unknown>;
105
105
  capabilities?: CapabilityInvoker;
106
+ /** Locally registered broker adapters. Reports may read account data; they never submit orders. */
107
+ resolveBroker?: (brokerType: string) => import("./broker").BrokerAdapter | null;
106
108
  /** Read one local portfolio without passing holdings through a remote endpoint. */
107
109
  resolvePortfolio?: (id: string) => Promise<{
108
110
  portfolio: import("./ticker").Portfolio;
@@ -131,6 +133,12 @@ export interface HeadlessPaneColumn {
131
133
  header: string;
132
134
  /** Print `header` as written, a field name such as `source`, where reports would otherwise title-case it. */
133
135
  literalHeader?: boolean;
136
+ /**
137
+ * What the text report heads the column with when it can say more than an
138
+ * export's header should (`Chg % UTC` over `Chg %`), printed as written;
139
+ * CSV keeps `header`, so a column read by its name stays where it was.
140
+ */
141
+ textHeader?: string;
134
142
  align?: "left" | "right" | "center";
135
143
  width?: number;
136
144
  /** False keeps the column whole when the text table is fitted to a narrow width, so a time or an id is never cut. */
@@ -229,9 +237,11 @@ export interface HeadlessPaneFreshness {
229
237
  /**
230
238
  * How often the data is published, when its dates mark the start of a period
231
239
  * (a monthly statistic is dated the 1st). The report then names the month,
232
- * quarter or year, not a day it was never observed on.
240
+ * quarter or year, not a day it was never observed on. A semiannual estimate
241
+ * is dated by the month it was made in (USDA's coffee and sugar balances),
242
+ * so it names that month.
233
243
  */
234
- periodicity?: "monthly" | "quarterly" | "annual";
244
+ periodicity?: "monthly" | "quarterly" | "semiannual" | "annual";
235
245
  /**
236
246
  * The newest row is a weekly or monthly bar whose period had not ended when
237
247
  * it was served (October's bar on 16 Oct), and the last day it covers so
@@ -1,3 +1,5 @@
1
+ import type { ListingDelisting } from "./financials";
2
+
1
3
  /**
2
4
  * What a ticker is, at the grain that decides which research has data for it:
3
5
  * filings, executives and analyst coverage exist for a company's stock,
@@ -77,4 +79,6 @@ export interface InstrumentSearchResult {
77
79
  * carries that name. A leftover listing of the merged company (GOGLC on
78
80
  * BYMA) is linked to it by search, naming the `successor`. */
79
81
  formerIssuer?: { symbol: string; name: string; until: string; successor?: { symbol: string; name: string | null } };
82
+ /** A US listing that no longer trades, found by its exact symbol (TWTR). Untrusted until parsed. */
83
+ delisting?: ListingDelisting;
80
84
  }
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { AppTickerRepositoryPort } from "../core/app-service-ports";
3
- import type { HeadlessPaneDefinition, HeadlessPaneFreshness, HeadlessPaneOptionDef } from "./headless";
3
+ import type { HeadlessPaneContext, HeadlessPaneDefinition, HeadlessPaneFreshness, HeadlessPaneOptionDef } from "./headless";
4
4
 
5
5
  export type {
6
6
  HeadlessArgumentExpansion,
@@ -123,6 +123,12 @@ export interface PaneLock {
123
123
  token?: string;
124
124
  /** The session is signed in and its email is not verified yet. */
125
125
  verifyEmail?: boolean;
126
+ /**
127
+ * Reads data as the report does, so a note can check that a free route it
128
+ * would name has data for the symbol before naming it. Absent where nothing
129
+ * can be read.
130
+ */
131
+ context?: HeadlessPaneContext;
126
132
  }
127
133
 
128
134
  export interface PaneDef {
@@ -195,9 +201,10 @@ export interface PaneDef {
195
201
  * read without it and where, and how to unlock it. A `headless` pane's report
196
202
  * prints it when the server refuses the read (401, 402 or 403). Without it
197
203
  * the report prints the wall's own words, or the refusal. Either way it cites
198
- * no source, since nothing was read.
204
+ * no source, since nothing was read. A free route it names must have data
205
+ * for the symbol (`lock.context` reads it), so the note may resolve later.
199
206
  */
200
- reportLockNote?(lock: PaneLock): string;
207
+ reportLockNote?(lock: PaneLock): string | Promise<string>;
201
208
  /**
202
209
  * What a rendered-view report needs before it shows anything, such as a
203
210
  * sign-in: `gloomberb catalog` lists it under Requires, as it does a
@@ -880,8 +887,8 @@ export interface AppNotificationRequest {
880
887
  };
881
888
  /**
882
889
  * What a built-in notice is about, so the Unread list can keep it after the
883
- * toast is gone and open it again: `price:<alertId>`, `catalyst:<eventId>`
884
- * or `team:<cardId>`. Other values are not kept.
890
+ * toast is gone and open it again: `price:<alertId>`, `catalyst:<eventId>`,
891
+ * `econ:<eventId>` or `team:<cardId>`. Other values are not kept.
885
892
  */
886
893
  refId?: string;
887
894
  /** Rendered next to `action`. Use for a dismissing counterpart such as snooze. */
@@ -895,6 +902,13 @@ export interface BrokerInstanceUpdateOptions {
895
902
  label?: string;
896
903
  enabled?: boolean;
897
904
  replaceConfig?: boolean;
905
+ /** Keep this connection's data on this device, out of Gloom Cloud sync (`BrokerInstanceConfig.localOnly`). */
906
+ localOnly?: boolean;
907
+ }
908
+
909
+ export interface BrokerInstanceCreateOptions {
910
+ /** Keep the new connection's data on this device from the start, before its first import. */
911
+ localOnly?: boolean;
898
912
  }
899
913
 
900
914
  export interface PinTickerOptions {
@@ -906,6 +920,8 @@ export interface PinTickerOptions {
906
920
  listing?: TickerListingRef;
907
921
  /** Select this research tab once the requested ticker has resolved. */
908
922
  tabId?: string;
923
+ /** Merge this state into the resolved research pane when selecting `tabId`. */
924
+ tabState?: Record<string, unknown>;
909
925
  }
910
926
 
911
927
  export interface GloomPluginContext {
@@ -937,6 +953,8 @@ export interface GloomPluginContext {
937
953
  getData(ticker: string): TickerFinancials | null;
938
954
  getTicker(ticker: string): TickerRecord | null;
939
955
  getConfig(): import("./config").AppConfig;
956
+ /** Resolve a broker registered by another plugin, without connecting it. */
957
+ getBrokerAdapter?(brokerType: string): BrokerAdapter | null;
940
958
  getPaneDef(paneId: string): PaneDef | undefined;
941
959
 
942
960
  readonly marketData: DataProvider;
@@ -949,7 +967,7 @@ export interface GloomPluginContext {
949
967
  readonly paneSettings: PluginPaneSettingsState;
950
968
  readonly teamState: PluginTeamState;
951
969
 
952
- createBrokerInstance(brokerType: string, label: string, values: Record<string, unknown>): Promise<BrokerInstanceConfig>;
970
+ createBrokerInstance(brokerType: string, label: string, values: Record<string, unknown>, options?: BrokerInstanceCreateOptions): Promise<BrokerInstanceConfig>;
953
971
  updateBrokerInstance(instanceId: string, values: Record<string, unknown>, options?: BrokerInstanceUpdateOptions): Promise<void>;
954
972
  syncBrokerInstance(instanceId: string): Promise<void>;
955
973
  removeBrokerInstance(instanceId: string): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import type { ManualChartResolution } from "../time-series/resolution";
2
- import type { PricePoint } from "./financials";
2
+ import type { ListingDelisting, PricePoint } from "./financials";
3
3
 
4
4
  /** Declared by the actual history source, independently of quote session state. */
5
5
  export interface HistorySession {
@@ -42,4 +42,9 @@ export interface PriceHistoryResult {
42
42
  * current copy, whatever its last bar, and for a source's own answer.
43
43
  */
44
44
  savedCopyBehind?: true;
45
+ /**
46
+ * The listing no longer trades: its bars end on `lastTradeDate` and no later
47
+ * session will add one, so a copy ending there is complete.
48
+ */
49
+ delisting?: ListingDelisting;
45
50
  }
@@ -8,6 +8,15 @@ export interface TickerPosition {
8
8
  priceBasis?: PriceBasis;
9
9
  currency?: string;
10
10
  dateAcquired?: string;
11
+ /**
12
+ * What one unit of the lot's `currency` cost in `costFxCurrency` when it was
13
+ * bought: entered with the position, or the FX close of its purchase date.
14
+ * Valued in that currency, the lot's cost converts at this rate rather than
15
+ * today's, so its P&L carries the currency's move since.
16
+ */
17
+ costFxRate?: number;
18
+ /** The currency `costFxRate` converts the cost into: the portfolio's when it was entered. */
19
+ costFxCurrency?: string;
11
20
  broker: string; // "manual" | future broker plugin IDs
12
21
  side?: "long" | "short";
13
22
  marketValue?: number;