gloomberb 0.18.3 → 0.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (886) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/src/account/checkout-handoff.tsx +225 -0
  6. package/src/account/device-signin-dialog.tsx +2 -2
  7. package/src/account/device-signin.ts +2 -2
  8. package/src/account/upgrade-dialog.tsx +1 -1
  9. package/src/api-client/askg.ts +2 -2
  10. package/src/api-client/auth.ts +2 -2
  11. package/src/api-client/central-bank-rates.ts +6 -0
  12. package/src/api-client/collections.ts +5 -1
  13. package/src/api-client/cot.ts +2 -0
  14. package/src/api-client/crypto-etf-flows.ts +37 -0
  15. package/src/api-client/crypto-markets.ts +60 -0
  16. package/src/api-client/data.ts +84 -5
  17. package/src/api-client/doe.ts +15 -0
  18. package/src/api-client/equity-screener.ts +28 -0
  19. package/src/api-client/exchange-announcements.ts +38 -0
  20. package/src/api-client/fund-facts.ts +39 -0
  21. package/src/api-client/futures-curve.ts +9 -1
  22. package/src/api-client/hiring.ts +301 -0
  23. package/src/api-client/index.ts +22 -5
  24. package/src/api-client/market-discovery.ts +14 -0
  25. package/src/api-client/members.ts +6 -0
  26. package/src/api-client/mna.ts +6 -0
  27. package/src/api-client/paths.ts +18 -1
  28. package/src/api-client/request.ts +21 -4
  29. package/src/api-client/short-side-publications.ts +37 -0
  30. package/src/api-client/socket.ts +64 -4
  31. package/src/api-client/swap-curve.ts +35 -0
  32. package/src/api-client/themes.ts +7 -1
  33. package/src/api-client/types.ts +90 -2
  34. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  35. package/src/app/runtime/desktop-deeplink.ts +5 -5
  36. package/src/app/runtime/plugin-bindings.ts +2 -2
  37. package/src/app/runtime/startup.ts +13 -0
  38. package/src/app/star-prompt/status-line.tsx +2 -2
  39. package/src/architecture/core-builtin-allowlist.json +5 -2
  40. package/src/architecture/ui-literals-allowlist.json +3 -3
  41. package/src/architecture/ui-tokens-allowlist.json +1 -1
  42. package/src/brokers/broker-portfolio-sync.ts +37 -0
  43. package/src/brokers/directory.ts +11 -0
  44. package/src/brokers/logos.ts +3 -1
  45. package/src/brokers/signed-in/adapter.ts +304 -26
  46. package/src/brokers/signed-in/client.ts +14 -2
  47. package/src/brokers/signed-in/connect.ts +10 -2
  48. package/src/brokers/sync-broker-instance.ts +9 -1
  49. package/src/capabilities/chart-series.ts +22 -6
  50. package/src/cli/bank-section.ts +1 -1
  51. package/src/cli/base-converter.ts +23 -14
  52. package/src/cli/central-bank-events.ts +1 -1
  53. package/src/cli/command-options.ts +59 -4
  54. package/src/cli/commands/api.ts +9 -6
  55. package/src/cli/commands/broker.ts +2 -2
  56. package/src/cli/commands/command-utils.ts +2 -2
  57. package/src/cli/commands/crypto-hints.ts +7 -20
  58. package/src/cli/commands/fred-series.ts +4 -2
  59. package/src/cli/commands/keybindings.ts +2 -2
  60. package/src/cli/commands/market.ts +1117 -264
  61. package/src/cli/commands/news-hints.ts +2 -2
  62. package/src/cli/commands/news-search.ts +59 -6
  63. package/src/cli/commands/options-leaps.ts +41 -26
  64. package/src/cli/commands/overview.ts +121 -48
  65. package/src/cli/commands/plugins.ts +9 -9
  66. package/src/cli/commands/remote.ts +13 -10
  67. package/src/cli/commands/search.ts +64 -44
  68. package/src/cli/commands/system.ts +27 -19
  69. package/src/cli/commands/themes.ts +1 -1
  70. package/src/cli/commands/ticker.ts +192 -47
  71. package/src/cli/context.ts +3 -2
  72. package/src/cli/desktop-pane-shot-view.ts +2 -2
  73. package/src/cli/desktop-pane-shot.ts +1 -1
  74. package/src/cli/earnings-calendar.ts +4 -4
  75. package/src/cli/entry.ts +18 -1
  76. package/src/cli/errors.ts +20 -2
  77. package/src/cli/exit-codes.ts +1 -1
  78. package/src/cli/export-source.ts +10 -4
  79. package/src/cli/freshness.ts +2 -8
  80. package/src/cli/fx-forward.ts +130 -0
  81. package/src/cli/fx-pair.ts +10 -9
  82. package/src/cli/glossary.ts +64 -20
  83. package/src/cli/help.ts +19 -13
  84. package/src/cli/history-export.ts +126 -0
  85. package/src/cli/history-rows.ts +196 -43
  86. package/src/cli/index-roots.ts +5 -45
  87. package/src/cli/index.ts +24 -18
  88. package/src/cli/known-gaps.ts +118 -25
  89. package/src/cli/listing-arg.ts +300 -41
  90. package/src/cli/name-entries.ts +30 -18
  91. package/src/cli/native-smoke.ts +2 -0
  92. package/src/cli/not-a-ticker.ts +19 -9
  93. package/src/cli/opentui-libc.ts +5 -0
  94. package/src/cli/options.ts +12 -0
  95. package/src/cli/pane-functions/capabilities.ts +75 -20
  96. package/src/cli/pane-functions/catalog.ts +24 -23
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +10 -7
  99. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  100. package/src/cli/pane-functions/freshness.ts +174 -23
  101. package/src/cli/pane-functions/function-help.ts +66 -27
  102. package/src/cli/pane-functions/headless.ts +24 -11
  103. package/src/cli/pane-functions/index.ts +18 -16
  104. package/src/cli/pane-functions/options.ts +22 -2
  105. package/src/cli/pane-functions/report-notices.ts +12 -4
  106. package/src/cli/pane-functions/report.ts +5 -5
  107. package/src/cli/pane-functions/resolver.ts +47 -10
  108. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  109. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  110. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  111. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  112. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  113. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  114. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  115. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  116. package/src/cli/pane-functions/shot-options.ts +8 -3
  117. package/src/cli/peso-dollar-rates.ts +79 -0
  118. package/src/cli/quote-answer.ts +38 -3
  119. package/src/cli/report-tables.ts +61 -16
  120. package/src/cli/restore-plugins.ts +29 -14
  121. package/src/cli/result.ts +111 -22
  122. package/src/cli/series-search.ts +5 -5
  123. package/src/cli/statement-filings.ts +19 -0
  124. package/src/cli/suffixed-listing-rows.ts +49 -0
  125. package/src/cli/symbol-args.ts +50 -15
  126. package/src/cli/symbol-cells.ts +120 -0
  127. package/src/cli/symbol-list.ts +198 -68
  128. package/src/cli/symbol-rows.ts +131 -25
  129. package/src/cli/ticker-resolution.ts +108 -11
  130. package/src/cli/treasury-yields.ts +5 -5
  131. package/src/cli/types.ts +2 -0
  132. package/src/cli/uncovered-instrument.ts +3 -3
  133. package/src/cli/unknown-command.ts +6 -6
  134. package/src/components/chart/composite/chart-layout.ts +131 -0
  135. package/src/components/chart/composite/composite-chart.tsx +373 -16
  136. package/src/components/chart/composite/interactions.ts +7 -2
  137. package/src/components/chart/composite/legend.tsx +75 -3
  138. package/src/components/chart/composite/levels.ts +5 -0
  139. package/src/components/chart/composite/panel-gestures.ts +41 -0
  140. package/src/components/chart/composite/panel-labels.ts +2 -1
  141. package/src/components/chart/composite/panel-surface.tsx +305 -11
  142. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  143. package/src/components/chart/composite/rasterizer.ts +44 -19
  144. package/src/components/chart/composite/scene.ts +16 -4
  145. package/src/components/chart/composite/text-renderer.ts +48 -21
  146. package/src/components/chart/composite/toolbar.tsx +52 -5
  147. package/src/components/chart/composite/types.ts +13 -0
  148. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  149. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  150. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  151. package/src/components/chart/composite/value-scale.ts +149 -0
  152. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  153. package/src/components/chart/core/pointer.ts +2 -0
  154. package/src/components/chart-table/index.ts +2 -0
  155. package/src/components/chart-table/read.tsx +74 -0
  156. package/src/components/command-bar/commands/collection-list.ts +41 -19
  157. package/src/components/command-bar/commands/collection.ts +9 -3
  158. package/src/components/command-bar/commands/direct/index.ts +1 -1
  159. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  160. package/src/components/command-bar/pane-templates/items.ts +59 -6
  161. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  162. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  163. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  164. package/src/components/command-bar/routes/root/results.ts +18 -4
  165. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  166. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  167. package/src/components/command-bar/routes/root/selection.ts +6 -1
  168. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  169. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  170. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  171. package/src/components/command-bar/selection-runtime.ts +50 -10
  172. package/src/components/command-bar/surface/index.tsx +24 -2
  173. package/src/components/command-bar/view-model.ts +7 -0
  174. package/src/components/command-bar/workflow/broker.ts +2 -2
  175. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  176. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  177. package/src/components/command-bar/workflow/fields.ts +8 -2
  178. package/src/components/command-bar/workflow/ops.ts +18 -4
  179. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  180. package/src/components/command-bar/workflow/submit.ts +3 -2
  181. package/src/components/command-bar/workflow/tickers.ts +5 -1
  182. package/src/components/company-logo.tsx +39 -0
  183. package/src/components/data-table/sections.ts +4 -2
  184. package/src/components/form-modal/confirm.tsx +2 -1
  185. package/src/components/form-modal/request.ts +5 -0
  186. package/src/components/form-modal/routes.ts +4 -1
  187. package/src/components/index.ts +12 -6
  188. package/src/components/layout/header.tsx +7 -6
  189. package/src/components/layout/market-summary.ts +9 -6
  190. package/src/components/layout/pane/capture-status.ts +1 -1
  191. package/src/components/layout/pane/footer/model.ts +11 -5
  192. package/src/components/layout/shell/chrome.ts +19 -6
  193. package/src/components/layout/shell/index.tsx +2 -1
  194. package/src/components/layout/shell/pane/layers.tsx +19 -1
  195. package/src/components/layout/status-bar.tsx +2 -2
  196. package/src/components/market-board/index.tsx +11 -3
  197. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  198. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  199. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  200. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  201. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  202. package/src/components/pane-settings-dialog/value.ts +8 -1
  203. package/src/components/pane-settings-dialog.tsx +44 -13
  204. package/src/components/sign-in-code-panel.tsx +27 -19
  205. package/src/components/ui/column-grid.tsx +48 -4
  206. package/src/components/ui/country-flag-art.tsx +180 -0
  207. package/src/components/ui/country-flag.tsx +118 -12
  208. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  209. package/src/components/ui/data-table/opentui/model.ts +109 -2
  210. package/src/components/ui/data-table/types.ts +1 -1
  211. package/src/components/ui/display.tsx +5 -1
  212. package/src/components/ui/index.ts +3 -1
  213. package/src/components/ui/logo-mark.tsx +11 -2
  214. package/src/components/ui/query-bar.tsx +1 -1
  215. package/src/components/ui/row-notes.ts +79 -0
  216. package/src/core/state/app/layout.ts +4 -4
  217. package/src/data/cached-query.ts +8 -1
  218. package/src/data/config/chart-settings.ts +3 -3
  219. package/src/data/config/home.ts +10 -2
  220. package/src/data/config/layout.ts +4 -1
  221. package/src/data/config/store/node.ts +4 -0
  222. package/src/data/config/store/normalize.ts +13 -3
  223. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  224. package/src/data/json-storage.ts +2 -0
  225. package/src/data/saved-copies.ts +84 -0
  226. package/src/docs/snapshot.json +65 -32
  227. package/src/i18n/es.ts +29 -12
  228. package/src/i18n/ja.ts +29 -12
  229. package/src/i18n/ko.ts +29 -12
  230. package/src/i18n/zh-cn.ts +29 -12
  231. package/src/i18n/zh-tw.ts +29 -12
  232. package/src/layout/desks.ts +1 -1
  233. package/src/layout/launch-layout.ts +1 -1
  234. package/src/layout/pane-manager/floating-actions.ts +5 -3
  235. package/src/layout/pane-manager/floating.ts +43 -1
  236. package/src/layout/pane-manager/index.ts +2 -0
  237. package/src/layout/selected-ticker.ts +74 -0
  238. package/src/market-data/depositary-pair.ts +251 -0
  239. package/src/market-data/futures-board.ts +1 -1
  240. package/src/market-data/futures-contract.ts +124 -40
  241. package/src/market-data/fx-closes.ts +17 -2
  242. package/src/market-data/hooks.tsx +19 -11
  243. package/src/market-data/market/change-basis.ts +49 -7
  244. package/src/market-data/market/freshness.ts +34 -5
  245. package/src/market-data/market/period-return.ts +163 -0
  246. package/src/market-data/market/trading-sessions.ts +13 -0
  247. package/src/market-data/market/year-to-date.ts +8 -13
  248. package/src/market-data/performance.ts +20 -14
  249. package/src/market-data/perpetual-premium.ts +32 -0
  250. package/src/market-data/published-apac-sessions.ts +2 -1
  251. package/src/market-data/published-futures-sessions.ts +69 -0
  252. package/src/market-data/quotes/contributions.ts +5 -1
  253. package/src/market-data/quotes/freshness.ts +42 -0
  254. package/src/market-data/quotes/intraday-bar.ts +37 -0
  255. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  256. package/src/market-data/quotes/resolution.ts +4 -2
  257. package/src/market-data/tax-equivalent.ts +1 -1
  258. package/src/market-data/ticker-price-returns.ts +3 -1
  259. package/src/news/aggregator.ts +5 -1
  260. package/src/news/news-model.ts +4 -0
  261. package/src/news/types.ts +11 -0
  262. package/src/notifications/app-notifier.ts +1 -1
  263. package/src/plugins/auto-update.ts +2 -2
  264. package/src/plugins/builtin/account-management/index.tsx +1 -0
  265. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  266. package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
  267. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  268. package/src/plugins/builtin/alerts/cli.ts +485 -76
  269. package/src/plugins/builtin/alerts/command.ts +5 -10
  270. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  271. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  272. package/src/plugins/builtin/alerts/events.ts +107 -5
  273. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  274. package/src/plugins/builtin/alerts/format.ts +2 -1
  275. package/src/plugins/builtin/alerts/headless.ts +100 -39
  276. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  277. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  278. package/src/plugins/builtin/alerts/index.tsx +45 -18
  279. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  280. package/src/plugins/builtin/alerts/levels.ts +3 -3
  281. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  282. package/src/plugins/builtin/alerts/price.ts +35 -0
  283. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  284. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  285. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  286. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  287. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  288. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  289. package/src/plugins/builtin/alerts/storage.ts +13 -10
  290. package/src/plugins/builtin/alerts/targets.ts +12 -3
  291. package/src/plugins/builtin/analytics/index.tsx +8 -2
  292. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  293. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  294. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  295. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  296. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  297. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  298. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  299. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  300. package/src/plugins/builtin/attention/pane.tsx +6 -2
  301. package/src/plugins/builtin/awards/headless.ts +7 -3
  302. package/src/plugins/builtin/awards/model.ts +18 -0
  303. package/src/plugins/builtin/awards/pane.tsx +6 -3
  304. package/src/plugins/builtin/backtest/headless.ts +3 -3
  305. package/src/plugins/builtin/backtest/rules.ts +41 -5
  306. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  307. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  308. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  309. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  310. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  311. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  312. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  313. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  314. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  315. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  316. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  317. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  318. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  319. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  320. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  321. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  322. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  323. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  324. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  325. package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
  326. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  327. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  328. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  329. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  330. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  331. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  332. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  333. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  334. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  335. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  336. package/src/plugins/builtin/catalysts/model.ts +49 -4
  337. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  338. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  339. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  340. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  341. package/src/plugins/builtin/changelog/index.tsx +1 -0
  342. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  343. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  344. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  345. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  346. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  347. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  348. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  349. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  350. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  351. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  352. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  353. package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
  354. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  355. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  356. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  357. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  358. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  359. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  360. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  361. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  362. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  363. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  364. package/src/plugins/builtin/chat/people.ts +1 -1
  365. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  366. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  367. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  368. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  369. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  370. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  371. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  372. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  373. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  374. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  375. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  376. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  377. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  378. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  379. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  380. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  381. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  382. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  383. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  384. package/src/plugins/builtin/company-attention/client.ts +117 -1
  385. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  386. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  387. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  388. package/src/plugins/builtin/company-attention/model.ts +33 -7
  389. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  390. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  391. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  392. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  393. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  394. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  395. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  396. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  397. package/src/plugins/builtin/composite-plugins.ts +2 -1
  398. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  399. package/src/plugins/builtin/connections/index.ts +1 -0
  400. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  401. package/src/plugins/builtin/correlation/headless.ts +5 -3
  402. package/src/plugins/builtin/cot/headless.ts +28 -6
  403. package/src/plugins/builtin/cot/model.ts +12 -0
  404. package/src/plugins/builtin/cot/pane.tsx +3 -2
  405. package/src/plugins/builtin/cpi/headless.ts +5 -1
  406. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  407. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  408. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  409. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  410. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  411. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  412. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  413. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  414. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  415. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  416. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  417. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  418. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  419. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  420. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  421. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  422. package/src/plugins/builtin/debug/index.tsx +1 -0
  423. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  424. package/src/plugins/builtin/docs/index.tsx +1 -1
  425. package/src/plugins/builtin/docs/pane.tsx +2 -2
  426. package/src/plugins/builtin/docs/targets.ts +1 -1
  427. package/src/plugins/builtin/doe/client.ts +5 -1
  428. package/src/plugins/builtin/doe/headless.ts +12 -6
  429. package/src/plugins/builtin/doe/model.ts +43 -6
  430. package/src/plugins/builtin/doe/pane.tsx +18 -11
  431. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  432. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  433. package/src/plugins/builtin/earnings/board.tsx +253 -50
  434. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  435. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  436. package/src/plugins/builtin/earnings/client.ts +4 -3
  437. package/src/plugins/builtin/earnings/headless.ts +53 -15
  438. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  439. package/src/plugins/builtin/earnings/index.tsx +15 -22
  440. package/src/plugins/builtin/earnings/model.ts +17 -12
  441. package/src/plugins/builtin/earnings/scope.ts +89 -0
  442. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  443. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  444. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  445. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  446. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  447. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  448. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  449. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  450. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  451. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  452. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  453. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  454. package/src/plugins/builtin/econ/index.tsx +112 -25
  455. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  456. package/src/plugins/builtin/econ/types.ts +32 -1
  457. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  458. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  459. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  460. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  461. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  462. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  463. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  464. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  465. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  466. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  467. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  468. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  469. package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
  470. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  471. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  472. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  473. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  474. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  475. package/src/plugins/builtin/exposure/headless.ts +51 -6
  476. package/src/plugins/builtin/exposure/index.tsx +28 -2
  477. package/src/plugins/builtin/exposure/model.ts +7 -0
  478. package/src/plugins/builtin/exposure/pane.tsx +6 -1
  479. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  480. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  481. package/src/plugins/builtin/futures/model.ts +10 -9
  482. package/src/plugins/builtin/futures/returns.ts +8 -36
  483. package/src/plugins/builtin/futures/table.tsx +1 -1
  484. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  485. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  486. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  487. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  488. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  489. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  490. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  491. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  492. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  493. package/src/plugins/builtin/gpu/headless.ts +9 -4
  494. package/src/plugins/builtin/help/index.tsx +13 -3
  495. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  496. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  497. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  498. package/src/plugins/builtin/holders/client.ts +13 -1
  499. package/src/plugins/builtin/holders/format.ts +28 -17
  500. package/src/plugins/builtin/holders/headless.ts +46 -7
  501. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  502. package/src/plugins/builtin/holders/pane.tsx +79 -15
  503. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  504. package/src/plugins/builtin/holders/table-model.ts +2 -1
  505. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  506. package/src/plugins/builtin/insider/headless.ts +1 -1
  507. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  508. package/src/plugins/builtin/insider/signals.tsx +1 -1
  509. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  510. package/src/plugins/builtin/iv-history/client.ts +20 -0
  511. package/src/plugins/builtin/iv-history/headless.ts +4 -4
  512. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  513. package/src/plugins/builtin/iv-history/model.ts +13 -4
  514. package/src/plugins/builtin/iv-history/series.ts +3 -1
  515. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  516. package/src/plugins/builtin/jobs/model.ts +4 -15
  517. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  518. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  519. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  520. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  521. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  522. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  523. package/src/plugins/builtin/macro-day/model.ts +29 -8
  524. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  525. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  526. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  527. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  528. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  529. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  530. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  531. package/src/plugins/builtin/market-movers/client.ts +33 -19
  532. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  533. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  534. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  535. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  536. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  537. package/src/plugins/builtin/market-movers/table.ts +4 -1
  538. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  539. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  540. package/src/plugins/builtin/members/headless.ts +6 -5
  541. package/src/plugins/builtin/members/pane.tsx +11 -4
  542. package/src/plugins/builtin/mna/client.ts +1 -0
  543. package/src/plugins/builtin/mna/detail.tsx +20 -32
  544. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  545. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  546. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  547. package/src/plugins/builtin/mna/headless.ts +6 -13
  548. package/src/plugins/builtin/mna/model.ts +93 -15
  549. package/src/plugins/builtin/mna/pane.tsx +5 -4
  550. package/src/plugins/builtin/news/headless.ts +12 -6
  551. package/src/plugins/builtin/news/index.tsx +10 -1
  552. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  553. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  554. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  555. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  556. package/src/plugins/builtin/notes/cli.ts +49 -14
  557. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  558. package/src/plugins/builtin/options/carry.ts +2 -2
  559. package/src/plugins/builtin/options/index.tsx +1 -1
  560. package/src/plugins/builtin/options/view.tsx +10 -10
  561. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  562. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  563. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  564. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  565. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  566. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  567. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  568. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  569. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  570. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  571. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  572. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  573. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  574. package/src/plugins/builtin/perps/freshness.ts +8 -5
  575. package/src/plugins/builtin/perps/headless.ts +3 -1
  576. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  577. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  578. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  579. package/src/plugins/builtin/perps/pane.tsx +36 -17
  580. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  581. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  582. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  583. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  584. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  585. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  586. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  587. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  588. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  589. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  590. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  591. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  592. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  593. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  594. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  595. package/src/plugins/builtin/power/client.ts +4 -1
  596. package/src/plugins/builtin/power/evidence.ts +22 -7
  597. package/src/plugins/builtin/power/gas.tsx +5 -1
  598. package/src/plugins/builtin/power/pane.tsx +8 -1
  599. package/src/plugins/builtin/power/prices.tsx +10 -3
  600. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  601. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  603. package/src/plugins/builtin/research/event-model.ts +3 -1
  604. package/src/plugins/builtin/research/event-sources.ts +12 -4
  605. package/src/plugins/builtin/research/index.tsx +2 -1
  606. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  608. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  609. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  610. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  611. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  612. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  613. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  614. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  615. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  616. package/src/plugins/builtin/sec/forms.ts +13 -0
  617. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  618. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  619. package/src/plugins/builtin/sec/headless.ts +85 -8
  620. package/src/plugins/builtin/sec/index.tsx +58 -12
  621. package/src/plugins/builtin/sectors/client.ts +2 -1
  622. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  623. package/src/plugins/builtin/series-inventory.ts +2 -0
  624. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  625. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  626. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  627. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  628. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  629. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  630. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  631. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  632. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  633. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  634. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  635. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  636. package/src/plugins/builtin/short-interest/client.ts +2 -0
  637. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  638. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  639. package/src/plugins/builtin/short-interest/model.ts +70 -19
  640. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  641. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  642. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  643. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  644. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  645. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  646. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  647. package/src/plugins/builtin/short-interest/types.ts +9 -0
  648. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  649. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  650. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  651. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  652. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  653. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  654. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  655. package/src/plugins/builtin/themes/headless.ts +8 -5
  656. package/src/plugins/builtin/themes/model.ts +14 -4
  657. package/src/plugins/builtin/themes/pane.tsx +24 -5
  658. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  659. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  660. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  661. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  662. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  663. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  664. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  665. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  666. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  667. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  668. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  669. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  670. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  671. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  672. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  673. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  674. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  675. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  676. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  677. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  678. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  679. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  680. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  681. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  682. package/src/plugins/builtin/vol-surface/client.ts +5 -4
  683. package/src/plugins/builtin/vol-surface/headless.ts +12 -3
  684. package/src/plugins/builtin/vol-surface/model.ts +4 -2
  685. package/src/plugins/builtin/volatility/model.ts +5 -10
  686. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  687. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  688. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  689. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  690. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  691. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  692. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  693. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  694. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  695. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  696. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  697. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  698. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  699. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  700. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  701. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  702. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  703. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  704. package/src/plugins/bundle.ts +1 -1
  705. package/src/plugins/catalog-browser.ts +2 -1
  706. package/src/plugins/compat.ts +3 -3
  707. package/src/plugins/dependencies.ts +75 -14
  708. package/src/plugins/extracted-plugins.ts +132 -34
  709. package/src/plugins/host-link.ts +149 -34
  710. package/src/plugins/installer.ts +35 -10
  711. package/src/plugins/loader.ts +206 -38
  712. package/src/plugins/manager-node.ts +2 -2
  713. package/src/plugins/marketplace/deactivation.ts +22 -0
  714. package/src/plugins/marketplace/model.ts +2 -2
  715. package/src/plugins/marketplace/packs.ts +1 -1
  716. package/src/plugins/ownership.ts +1 -1
  717. package/src/plugins/peer-retry.ts +155 -0
  718. package/src/plugins/registry/contributions.ts +3 -1
  719. package/src/plugins/registry/index.ts +4 -3
  720. package/src/plugins/registry/plugin-state.ts +3 -0
  721. package/src/plugins/seed-notice.ts +20 -0
  722. package/src/plugins/shortcut-argument.ts +39 -0
  723. package/src/portfolio/allocation.ts +1 -1
  724. package/src/portfolio/collection-name.ts +31 -0
  725. package/src/portfolio/column-values.ts +10 -8
  726. package/src/portfolio/cost-fx.ts +296 -19
  727. package/src/portfolio/manual-lots.ts +75 -0
  728. package/src/portfolio/mutations.ts +60 -22
  729. package/src/portfolio/suffixed-listings.ts +209 -0
  730. package/src/portfolio/totals-currency.ts +24 -0
  731. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  732. package/src/public/time-series.ts +11 -8
  733. package/src/remote/schema.ts +1 -1
  734. package/src/renderers/browser/config-host.ts +3 -0
  735. package/src/renderers/browser/main.tsx +23 -3
  736. package/src/renderers/dom/boot-frame-page.ts +187 -0
  737. package/src/renderers/dom/boot-frame.ts +237 -0
  738. package/src/renderers/dom/build-assets.ts +46 -8
  739. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  740. package/src/renderers/dom/host/ascii-text.ts +16 -2
  741. package/src/renderers/dom/host/box.tsx +43 -2
  742. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  743. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  744. package/src/renderers/dom/host/image-surface.tsx +49 -0
  745. package/src/renderers/dom/host/media-surface.tsx +24 -18
  746. package/src/renderers/dom/host/mouse.ts +30 -0
  747. package/src/renderers/dom/host/size-observer.ts +1 -1
  748. package/src/renderers/dom/host/style.ts +1 -1
  749. package/src/renderers/dom/styles.css +76 -0
  750. package/src/renderers/dom/test-utils.tsx +2 -1
  751. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  752. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  753. package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
  754. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  755. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  756. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  757. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  758. package/src/renderers/electrobun/bun/index.ts +11 -1
  759. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  760. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  761. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  762. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  763. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  764. package/src/renderers/electrobun/view/config-host.ts +3 -0
  765. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  766. package/src/renderers/electrobun/view/main.tsx +30 -4
  767. package/src/renderers/electrobun/view/news-source.ts +5 -5
  768. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  769. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  770. package/src/renderers/opentui/browser-open.ts +88 -0
  771. package/src/renderers/opentui/host.tsx +5 -14
  772. package/src/renderers/opentui/image/loader.ts +3 -2
  773. package/src/renderers/opentui/native-smoke.ts +10 -1
  774. package/src/renderers/opentui/pane-image/index.ts +2 -1
  775. package/src/renderers/opentui/render-lib.ts +253 -0
  776. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  777. package/src/renderers/opentui/start.tsx +1 -1
  778. package/src/renderers/share/layout-view.tsx +2 -2
  779. package/src/renderers/share/main.tsx +4 -4
  780. package/src/renderers/share/view.tsx +1 -1
  781. package/src/series/resolve.ts +22 -6
  782. package/src/series/standalone.ts +30 -2
  783. package/src/series/types.ts +8 -1
  784. package/src/shares/api.ts +4 -1
  785. package/src/shares/pane.ts +1 -1
  786. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  787. package/src/sources/gloomberb-cloud/index.ts +32 -16
  788. package/src/sources/gloomberb-cloud/news.ts +39 -0
  789. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  790. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  791. package/src/sources/listing-symbols.ts +37 -0
  792. package/src/sources/provider-errors.ts +16 -2
  793. package/src/sources/provider-router/financial-routes.ts +21 -3
  794. package/src/sources/provider-router/financials.ts +15 -2
  795. package/src/sources/provider-router/history.ts +30 -8
  796. package/src/sources/provider-router/primary.ts +1 -1
  797. package/src/state/app/bootstrap.ts +23 -0
  798. package/src/state/hooks/inline-tickers.ts +30 -5
  799. package/src/sync/controller.ts +1 -1
  800. package/src/sync/core-contributors.ts +46 -14
  801. package/src/team/collections-sync.ts +2 -1
  802. package/src/team/collections.ts +178 -17
  803. package/src/telemetry/crash-reports.ts +17 -4
  804. package/src/test-support/builtin-panes.ts +1 -1
  805. package/src/theme/colors.ts +3 -30
  806. package/src/theme/ui-tokens.ts +37 -1
  807. package/src/tickers/company-name-listing.ts +210 -33
  808. package/src/tickers/index-roots.ts +47 -0
  809. package/src/tickers/instrument-label.ts +5 -1
  810. package/src/tickers/metadata.ts +10 -0
  811. package/src/tickers/perpetual-listing.ts +5 -2
  812. package/src/tickers/search/home-listing.ts +75 -0
  813. package/src/tickers/search/index.ts +76 -27
  814. package/src/tickers/search/ranking.ts +54 -4
  815. package/src/tickers/search/upsert.ts +29 -0
  816. package/src/tickers/terminal-codes.ts +416 -40
  817. package/src/time-series/bar-aggregation.ts +243 -0
  818. package/src/time-series/base-series.ts +307 -0
  819. package/src/time-series/chart-bounds.ts +349 -0
  820. package/src/time-series/chart-seed.ts +142 -0
  821. package/src/time-series/economic.ts +5 -0
  822. package/src/time-series/fundamentals.ts +18 -3
  823. package/src/time-series/history-acquisition.ts +499 -0
  824. package/src/time-series/leverage.ts +100 -0
  825. package/src/time-series/market-resolution.ts +4 -2
  826. package/src/time-series/market.ts +2 -1
  827. package/src/time-series/price-comparison.ts +175 -30
  828. package/src/time-series/range.ts +9 -1
  829. package/src/time-series/resolution.ts +174 -16
  830. package/src/time-series/resolve-context.ts +157 -0
  831. package/src/time-series/resolve.ts +126 -1577
  832. package/src/time-series/series-name.ts +38 -0
  833. package/src/time-series/series-presentation.ts +208 -0
  834. package/src/time-series/spec.ts +11 -6
  835. package/src/time-series/studies.ts +109 -12
  836. package/src/time-series/tail-reconcile.ts +121 -0
  837. package/src/time-series/types.ts +29 -2
  838. package/src/time-series/use-chart-resolution.ts +4 -5
  839. package/src/types/broker.ts +10 -0
  840. package/src/types/config.ts +14 -0
  841. package/src/types/data-provider.ts +14 -0
  842. package/src/types/exchange-rate.ts +6 -0
  843. package/src/types/financials.ts +104 -7
  844. package/src/types/headless.ts +76 -6
  845. package/src/types/instrument.ts +3 -0
  846. package/src/types/plugin.ts +65 -8
  847. package/src/types/price-history.ts +2 -0
  848. package/src/types/ticker.ts +13 -0
  849. package/src/types/trading.ts +59 -1
  850. package/src/ui/ascii-font.ts +13 -1
  851. package/src/ui/host.tsx +6 -1
  852. package/src/updater/command-names.ts +175 -0
  853. package/src/updater/index.ts +10 -5
  854. package/src/utils/calendar-date.ts +32 -15
  855. package/src/utils/cash-runway.ts +241 -0
  856. package/src/utils/central-banks.ts +42 -0
  857. package/src/utils/cli-output.ts +259 -80
  858. package/src/utils/contract-month.ts +16 -0
  859. package/src/utils/crypto-pair.ts +61 -3
  860. package/src/utils/currency-units.ts +29 -0
  861. package/src/utils/datetime-format.ts +10 -0
  862. package/src/utils/debug-log.ts +1 -1
  863. package/src/utils/decimal-comma.ts +39 -6
  864. package/src/utils/exchange-announcements.ts +71 -0
  865. package/src/utils/exchange-rate-snapshot.ts +10 -0
  866. package/src/utils/financial-statements.ts +83 -4
  867. package/src/utils/format.ts +34 -16
  868. package/src/utils/fundamentals.ts +150 -34
  869. package/src/utils/fx-market-hours.ts +10 -1
  870. package/src/utils/latest-financial-period.ts +8 -0
  871. package/src/utils/linux-libc.ts +54 -0
  872. package/src/utils/market-capitalization.ts +111 -15
  873. package/src/utils/max-drawdown.ts +64 -0
  874. package/src/utils/network-failure.ts +83 -0
  875. package/src/utils/option-expiry.ts +139 -7
  876. package/src/utils/price-earnings.ts +11 -5
  877. package/src/utils/price-history.ts +18 -8
  878. package/src/utils/price-window.ts +131 -0
  879. package/src/utils/release-date.ts +47 -0
  880. package/src/utils/sec.ts +3 -0
  881. package/src/utils/throttled-fetch.ts +11 -4
  882. package/src/utils/trailing-eps.ts +67 -0
  883. package/src/utils/typed-text.ts +21 -0
  884. package/src/utils/utc-time.ts +24 -1
  885. package/src/version.ts +6 -0
  886. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -1,6 +1,7 @@
1
- import { Box } from "../../../ui";
1
+ import { Box, useUiCapabilities } from "../../../ui";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { TextAttributes, type ScrollBoxRenderable } from "../../../ui";
4
+ import { COUNTRY_FLAG_CELLS, withCountryFlag } from "../../../components/ui/country-flag";
4
5
  import {
5
6
  Button,
6
7
  DataTableStackView,
@@ -12,18 +13,25 @@ import {
12
13
  type PaneFooterSegment,
13
14
  } from "../../../components";
14
15
  import { usePluginPaneState } from "../../runtime";
16
+ import { useAppConfig, usePaneSettingValue } from "../../../public/react";
17
+ import { readerTimeZone, timeZoneCity, zonedClock } from "../../../utils/utc-time";
18
+ import { usePaneInstance } from "../../../state/app/context";
19
+ import { commandRequestParams } from "../shared/command-tab";
15
20
  import { useAsyncResource } from "../../../react/async-resource";
16
21
  import { useAutoRefresh } from "../../../react/auto-refresh";
17
22
  import { usePaneVisible } from "../../../state/app/activity";
23
+ import { formatCountdown } from "../../../utils/datetime-format";
18
24
  import type { PaneProps } from "../../../types/plugin";
19
25
  import type { PluginModule } from "../plugin-module";
20
26
  import { colors, blendHex } from "../../../theme/colors";
21
- import type { EconEvent } from "./types";
27
+ import { hasNoReleaseTime, hasNoStatedTime, isAllDayEvent, type EconEvent } from "./types";
22
28
  import { FRED_CATALOG_SERIES } from "./fred-catalog";
23
29
  import { ECON_PRINT_NOTIFICATIONS_ENABLED_KEY, retainVisiblePrintRefresh, setupHighImpactPrintNotifications } from "./print-watch";
24
30
  import { EconDetailView } from "./detail-view";
25
31
  import {
26
32
  COUNTRY_CYCLE,
33
+ COUNTRY_FILTER_HINT,
34
+ countriesWithoutEvents,
27
35
  DEFAULT_IMPACT_FILTER,
28
36
  FILTER_CYCLE,
29
37
  attachEconCalendarPersistence,
@@ -33,18 +41,21 @@ import {
33
41
  dateKey,
34
42
  dayLabel,
35
43
  filteredEmptyTitle,
36
- formatCountdown,
37
44
  formatStaleness,
38
45
  getCalendarCache,
39
46
  subscribeCalendar,
40
47
  impactIndicator,
41
48
  loadCalendar,
49
+ eventCountry,
42
50
  matchesCountry,
43
51
  matchesImpact,
52
+ noScheduledReleasesMessage,
53
+ parseCountryFilter,
44
54
  resetEconCalendarPersistence,
45
55
  shortCalendarEnd,
46
56
  shortDayLabel,
47
57
  timeLabel,
58
+ valueColumnWidth,
48
59
  type CountryFilter,
49
60
  type DisplayRow,
50
61
  type EconCalendarColumn,
@@ -93,7 +104,21 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
93
104
  // reload or a shared layout comes back to the same release.
94
105
  const [selectedKey, setSelectedKey] = usePluginPaneState<string | null>("selectedKey", null);
95
106
  const [impactFilter, setImpactFilter] = usePluginPaneState<ImpactFilter>("impactFilter", DEFAULT_IMPACT_FILTER);
96
- const [countryFilter, setCountryFilter] = usePluginPaneState<CountryFilter>("countryFilter", "all");
107
+ const [chosenCountry, setCountryFilter] = usePluginPaneState<CountryFilter>("countryFilter", "all");
108
+ // Countries a caller named (`ECO MX,BR`, `fn ECO --country MX`) are shown once per request; a later choice is the reader's.
109
+ const pane = usePaneInstance();
110
+ const [countrySetting] = usePaneSettingValue<string>("country", "");
111
+ const requestedCountry = pane?.params?.country || countrySetting || null;
112
+ const countryRequest = pane?.params?.country ? `${pane.params.country}|${pane.params.tabAt ?? ""}`
113
+ : countrySetting ? `setting|${countrySetting}` : "";
114
+ const [shownCountryRequest, setShownCountryRequest] = usePluginPaneState("countryRequest", "");
115
+ const countryPending = !!countryRequest && countryRequest !== shownCountryRequest;
116
+ const countryFilter: CountryFilter = countryPending && requestedCountry ? requestedCountry : chosenCountry;
117
+ useEffect(() => {
118
+ if (!countryPending || !requestedCountry) return;
119
+ setShownCountryRequest(countryRequest);
120
+ setCountryFilter(requestedCountry);
121
+ }, [countryPending, countryRequest, requestedCountry, setCountryFilter, setShownCountryRequest]);
97
122
  const [now, setNow] = useState(Date.now());
98
123
  const [openKey, setOpenKey] = usePluginPaneState<string | null>("openKey", null);
99
124
 
@@ -221,35 +246,47 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
221
246
  handleRefreshKey(event, () => void calendar.reload(), { stopPropagation: true })
222
247
  ), [calendar.reload]);
223
248
 
249
+ // The desktop and the web lead each country's code with its flag.
250
+ const flagged = useUiCapabilities().nativePaneChrome === true;
251
+ // A reader who set a time zone (`config set timezone`) gets their clock in a column beside UTC.
252
+ const readerZone = readerTimeZone(useAppConfig().timezone);
224
253
  const columns = useMemo<EconCalendarColumn[]>(() => {
225
254
  // The header names the zone, so the column is as wide as the header needs.
226
255
  const timeLabelText = `TIME (${CALENDAR_TIME_ZONE_LABEL})`;
227
256
  const timeWidth = tableColumnWidth({ width: 6, label: timeLabelText });
228
- const actualWidth = 9;
229
- const forecastWidth = 10;
230
- const priorWidth = 9;
257
+ const actualWidth = valueColumnWidth(filtered, "actual", 9);
258
+ const forecastWidth = valueColumnWidth(filtered, "forecast", 10);
259
+ const priorWidth = valueColumnWidth(filtered, "prior", 9);
231
260
  const minEventWidth = 12;
261
+ // The reader's clock, with the weekday on rows where it is another day than the UTC one they are listed under.
262
+ const readerLabel = readerZone ? timeZoneCity(readerZone).toUpperCase() : null;
263
+ const readerWidth = !readerZone || !readerLabel ? 0 : tableColumnWidth({ label: readerLabel,
264
+ width: filtered.some((ev) => !hasNoReleaseTime(ev) && zonedClock(ev.date.getTime(), readerZone).label.length > 5) ? 9 : 5 });
232
265
  // Padding, one gap per column boundary, and the vertical scrollbar lane;
233
266
  // one column short of that clipped the PRIOR values at the right edge.
234
- const columnCount = 7;
235
- const eventRoom = (impactWidth: number, countryWidth: number) => (
236
- width - 3 - columnCount - (timeWidth + impactWidth + countryWidth + actualWidth + forecastWidth + priorWidth)
267
+ const roomBeside = (count: number, timesWidth: number) => (impactWidth: number, countryWidth: number) => (
268
+ width - 3 - count - (timesWidth + impactWidth + countryWidth + actualWidth + forecastWidth + priorWidth)
237
269
  );
270
+ const codeWidth = 2 + (flagged ? COUNTRY_FLAG_CELLS : 0);
271
+ // The reader's column only where the event names keep room to read beside it, under the short headers.
272
+ const withReader = readerWidth > 0 && roomBeside(8, timeWidth + readerWidth)(4, Math.max(3, codeWidth)) >= minEventWidth;
273
+ const eventRoom = withReader ? roomBeside(8, timeWidth + readerWidth) : roomBeside(7, timeWidth);
238
274
  // IMPACT and COUNTRY in words while event names keep room to read; the
239
275
  // short labels otherwise, with the word on hover where there is one.
240
276
  const spelledImpactWidth = tableColumnWidth({ width: 1, label: SPELLED_IMPACT });
241
- const spelledCountryWidth = tableColumnWidth({ width: 1, label: SPELLED_COUNTRY });
277
+ const spelledCountryWidth = Math.max(codeWidth, tableColumnWidth({ width: 1, label: SPELLED_COUNTRY }));
242
278
  const spelled = eventRoom(spelledImpactWidth, spelledCountryWidth) >= SPELLED_HEADER_MIN_EVENT_WIDTH;
243
279
  const impactColumn = spelled
244
280
  ? { label: SPELLED_IMPACT, width: spelledImpactWidth }
245
281
  : { label: "IMP", width: 4, title: "Impact" };
246
282
  const countryColumn = spelled
247
283
  ? { label: SPELLED_COUNTRY, width: spelledCountryWidth }
248
- : { label: "CTY", width: 3, title: "Country" };
284
+ : { label: "CTY", width: Math.max(3, codeWidth), title: "Country" };
249
285
  const eventWidth = Math.max(minEventWidth, eventRoom(impactColumn.width, countryColumn.width));
250
286
 
251
287
  return [
252
288
  { id: "time", label: timeLabelText, width: timeWidth, align: "left" },
289
+ ...withReader ? [{ id: "readerTime" as const, label: readerLabel!, width: readerWidth, align: "left" as const, title: readerZone! }] : [],
253
290
  { id: "impact", ...impactColumn, align: "left" },
254
291
  { id: "country", ...countryColumn, align: "left" },
255
292
  { id: "event", label: "EVENT", width: eventWidth, align: "left" },
@@ -257,11 +294,15 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
257
294
  { id: "forecast", label: "FORECAST", width: forecastWidth, align: "right" },
258
295
  { id: "prior", label: "PRIOR", width: priorWidth, align: "right" },
259
296
  ];
260
- }, [width]);
297
+ }, [filtered, flagged, readerZone, width]);
261
298
  const separatorBg = blendHex(colors.bg, colors.border, 0.3);
262
299
  const staleness = fetchedAt ? formatStaleness(fetchedAt, now) : "";
263
300
  // The calendar has events and the filters hid them all: say which, with the way back.
264
- const filterEmptyTitle = events.length > 0 ? filteredEmptyTitle(impactFilter, countryFilter) : null;
301
+ // Countries named one by one with nothing in the calendar: a quiet window there, said plainly.
302
+ const unscheduled = useMemo(() => countriesWithoutEvents(countryFilter, events), [countryFilter, events]);
303
+ const filterEmptyTitle = events.length === 0 ? null
304
+ : unscheduled.length > 0 && unscheduled.length === countryFilter.split(",").length ? noScheduledReleasesMessage(unscheduled).replace(/\.$/, "")
305
+ : filteredEmptyTitle(impactFilter, countryFilter);
265
306
  const emptyStateHint = !loading && !error
266
307
  ? [
267
308
  impactFilter !== "all" ? `impact: ${impactFilter}` : null,
@@ -271,7 +312,10 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
271
312
 
272
313
  // Next upcoming event for countdown
273
314
  const nextEvent = nextUpcomingEventIdx >= 0 ? filtered[nextUpcomingEventIdx] : undefined;
274
- const nextCountdown = nextEvent ? formatCountdown(nextEvent.date.getTime() - now) : null;
315
+ // A bank that states no time, or an all-day event, has a day to count to, not an hour.
316
+ const nextCountdown = !nextEvent ? null
317
+ : hasNoReleaseTime(nextEvent) ? shortDayLabel(nextEvent.date)
318
+ : formatCountdown(nextEvent.date.getTime() - now);
275
319
  // The countdown changes every tick, so it is footer status, not query bar
276
320
  // context; the footer ellipsizes a long event name.
277
321
  const nextText = nextEvent && nextCountdown ? `next ${nextEvent.event} ${nextCountdown}` : null;
@@ -285,7 +329,7 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
285
329
  ...(showStale ? [{ id: "stale", parts: [{ text: "STALE", tone: "warning" as const }] }] : []),
286
330
  ...(staleness ? [{ id: "updated", parts: [{ text: staleness, tone: "muted" as const }] }] : []),
287
331
  ], [detailEvent, listedAfterStatus, nextText, showStale, staleness]);
288
- // A report of the pane (`gloomberb fn ECO`) says it too.
332
+ // A report of the pane (`gloom fn ECO`) says it too.
289
333
  const listedThrough = listedEnd ? dateKey(listedEnd) : null;
290
334
  useRemoteUiNode(listedAfter && listedThrough ? {
291
335
  role: "report-notice",
@@ -346,7 +390,10 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
346
390
  const ev = row.event;
347
391
  switch (column.id) {
348
392
  case "time":
349
- return { text: timeLabel(ev.date), color: colors.textMuted };
393
+ // A bank that states no time has none here, and its detail says why; an all-day event (a plenum, an election) says so.
394
+ return { text: hasNoStatedTime(ev) ? "" : isAllDayEvent(ev) ? "All day" : timeLabel(ev.date), color: colors.textMuted };
395
+ case "readerTime":
396
+ return { text: hasNoReleaseTime(ev) || !readerZone ? "" : zonedClock(ev.date.getTime(), readerZone).label, color: colors.textMuted };
350
397
  case "impact": {
351
398
  const indicator = impactIndicator(ev.impact);
352
399
  return {
@@ -354,10 +401,14 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
354
401
  color: indicator.color,
355
402
  };
356
403
  }
357
- case "country":
358
- // The ISO code, not a flag emoji: emoji widths do not match a fixed
359
- // column and pushed the right-hand columns off the pane.
360
- return { text: ev.country, color: colors.textMuted };
404
+ case "country": {
405
+ // The ISO code, led on the desktop by the flag drawn as art, never a
406
+ // flag emoji: emoji widths do not match a fixed column and pushed the
407
+ // right-hand columns off the pane. A national euro-area release is
408
+ // its member's (DE for German Ifo), the ECB's the euro area's.
409
+ const country = eventCountry(ev);
410
+ return withCountryFlag({ text: country, color: colors.textMuted }, country, flagged);
411
+ }
361
412
  case "event":
362
413
  return { text: ev.event, color: colors.text };
363
414
  case "actual":
@@ -370,7 +421,7 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
370
421
  case "prior":
371
422
  return { text: ev.prior ?? "—", color: colors.textDim };
372
423
  }
373
- }, []);
424
+ }, [flagged, readerZone]);
374
425
 
375
426
  const selectedEvent = filtered[selectedIdx];
376
427
  const filterControls = (
@@ -381,7 +432,9 @@ function EconCalendarPane({ focused, width, height }: PaneProps) {
381
432
  options: FILTER_CYCLE.map((value) => ({ value, label: IMPACT_LABELS[value] })),
382
433
  onChange: (value: string) => selectImpactFilter(value as ImpactFilter) },
383
434
  { id: "region", label: "Region", inline: true, value: countryFilter, defaultValue: "all",
384
- options: COUNTRY_CYCLE.map((value) => ({ value, label: value === "all" ? "All" : value })),
435
+ // Countries a command named stay a choice beside the regions while they are shown.
436
+ options: [...COUNTRY_CYCLE, ...(COUNTRY_CYCLE.includes(countryFilter) ? [] : [countryFilter])]
437
+ .map((value) => ({ value, label: value === "all" ? "All" : value.split(",").join(", ") })),
385
438
  onChange: (value: string) => selectCountryFilter(value as CountryFilter) },
386
439
  ]}
387
440
  meta={selectedEvent ? dayLabel(selectedEvent.date, today) : undefined}
@@ -462,6 +515,19 @@ export const economicCalendarModule: PluginModule = {
462
515
  defaultMode: "floating",
463
516
  defaultFloatingSize: { width: 100, height: 30 },
464
517
  tableExport: true,
518
+ reportOptions: [{
519
+ key: "country",
520
+ type: "string",
521
+ placeholder: "countries",
522
+ description: "Regions or two-letter country codes to list, comma separated: US, G7, EU, or such as MX,BR,ZA",
523
+ example: "--country MX,BR,ZA",
524
+ exampleWithoutArgument: true,
525
+ normalize: (value) => {
526
+ const parsed = parseCountryFilter(value);
527
+ if ("error" in parsed) throw new Error(`${parsed.error} ${COUNTRY_FILTER_HINT}`);
528
+ return parsed.filter;
529
+ },
530
+ }],
465
531
  settings: {
466
532
  title: "Economic Calendar Settings",
467
533
  fields: [{
@@ -479,8 +545,29 @@ export const economicCalendarModule: PluginModule = {
479
545
  label: "Economic Calendar",
480
546
  description: "Upcoming economic events, releases, and indicators.",
481
547
  // "econ" stays a keyword so the old ECON prefix still finds this pane.
482
- keywords: ["econ", "economic", "calendar", "events", "macro", "releases", "fed", "cpi", "gdp"],
483
- shortcut: { prefix: "ECO" },
548
+ keywords: ["econ", "economic", "calendar", "events", "macro", "releases", "fed", "cpi", "gdp", "rate decision", "ipca",
549
+ "brazil inflation"],
550
+ // ECO MX,BR opens the calendar on those countries.
551
+ shortcut: {
552
+ prefix: "ECO",
553
+ argKind: "text",
554
+ argPlaceholder: "countries",
555
+ argOptional: true,
556
+ openWithoutArg: true,
557
+ argOptions: () => [
558
+ { value: "US", label: "United States" },
559
+ { value: "G7", label: "G7" },
560
+ { value: "EU", label: "Euro area" },
561
+ { value: "MX,BR,ZA,IN,KR", label: "Mexico, Brazil, South Africa, India and Korea" },
562
+ ],
563
+ },
564
+ createInstance: (_context, options) => {
565
+ const typed = options?.arg?.trim();
566
+ if (!typed) return {};
567
+ const parsed = parseCountryFilter(typed);
568
+ if ("error" in parsed) throw new Error(`${parsed.error} ${COUNTRY_FILTER_HINT}`);
569
+ return { params: commandRequestParams({ country: parsed.filter }) };
570
+ },
484
571
  }],
485
572
  setup(ctx) {
486
573
  attachEconCalendarPersistence(ctx.persistence);
@@ -1,5 +1,6 @@
1
1
  import type { GloomPluginContext } from "../../../types/plugin";
2
2
  import {
3
+ eventCountry,
3
4
  getCalendarCache,
4
5
  landedHighImpactPrints,
5
6
  loadCalendar,
@@ -92,7 +93,7 @@ export function startHighImpactPrintWatch(
92
93
 
93
94
  const toast = (event: EconEvent) => {
94
95
  ctx.notify({
95
- title: event.country,
96
+ title: eventCountry(event),
96
97
  body: printBody(event),
97
98
  type: "info",
98
99
  desktop: "always",
@@ -1,4 +1,3 @@
1
-
2
1
  export type EconImpact = "high" | "medium" | "low";
3
2
 
4
3
  export interface EconEvent {
@@ -11,4 +10,36 @@ export interface EconEvent {
11
10
  forecast: string | null;
12
11
  prior: string | null;
13
12
  impact: EconImpact;
13
+ /**
14
+ * Rows Gloom Cloud adds beside its feeds: a central bank's kept decision or
15
+ * a statistics office's listed release. The feeds' own rows carry none of
16
+ * the fields below.
17
+ */
18
+ kind?: "central-bank-decision" | "statistics-release";
19
+ /** The publisher's own clock time and its IANA zone; null when it states no time. */
20
+ localTime?: string | null;
21
+ timeZone?: string;
22
+ /** Why a row has no time, when its publisher states none. */
23
+ timeNote?: string | null;
24
+ /** The day the prior level was observed. */
25
+ priorAsOf?: string | null;
26
+ /** The period a release covers, as its publisher names it. */
27
+ referencePeriod?: string | null;
28
+ /** Who publishes it (Freddie Mac for the 30-year mortgage rate), and its page when one is named. */
29
+ source?: { name: string; url?: string };
30
+ }
31
+
32
+ /** Whether a row's time is blank because its publisher states none (a bank whose calendar gives the day only). */
33
+ export function hasNoStatedTime(event: Pick<EconEvent, "timeNote">): boolean {
34
+ return typeof event.timeNote === "string" && event.timeNote.length > 0;
35
+ }
36
+
37
+ /** A row that takes its whole day (a plenum, an election, a summit): it has a day and no release time. */
38
+ export function isAllDayEvent(event: Pick<EconEvent, "time" | "timeNote">): boolean {
39
+ return event.time === "All Day" && !hasNoStatedTime(event);
40
+ }
41
+
42
+ /** A row with a day and no clock time to count to: an all-day event, or a bank that states no time. */
43
+ export function hasNoReleaseTime(event: Pick<EconEvent, "time" | "timeNote">): boolean {
44
+ return hasNoStatedTime(event) || isAllDayEvent(event);
14
45
  }
@@ -12,6 +12,8 @@ export interface StatBuild {
12
12
  stat: StatDef;
13
13
  points: StatPoint[];
14
14
  trend: TrendFit;
15
+ /** The day the latest point's figure was released (`YYYY-MM-DD`), when FRED says. */
16
+ releasedOn?: string;
15
17
  cache?: SeriesCacheMetadata;
16
18
  }
17
19
 
@@ -45,10 +47,12 @@ function build(def: StatDef, result: DatedObservation[] | SeriesCacheLoadResult)
45
47
  ? observations
46
48
  : observations.map((entry) => ({
47
49
  date: entry.date,
48
- value: entry.value == null ? null : entry.value * scale,
50
+ // Rounded off the float's last digits: 2.36 × 100 is 236, not 236.00000000000003.
51
+ value: entry.value == null ? null : Number((entry.value * scale).toPrecision(12)),
49
52
  }));
50
53
  const points = applyTransform(scaled, def.transform);
51
54
  if (points.length === 0) return null;
55
+ const releasedOn = latestRelease(observations, points.at(-1)!.date);
52
56
  const cache = Array.isArray(result) ? undefined : {
53
57
  fetchedAt: result.fetchedAt,
54
58
  stale: result.stale,
@@ -56,7 +60,14 @@ function build(def: StatDef, result: DatedObservation[] | SeriesCacheLoadResult)
56
60
  ...(result.refreshError ? { refreshError: result.refreshError } : {}),
57
61
  };
58
62
  // These go negative routinely, so the fit stays linear.
59
- return { stat: def, points, trend: fitTrend(points, "linear"), ...(cache ? { cache } : {}) };
63
+ return { stat: def, points, trend: fitTrend(points, "linear"), ...(releasedOn ? { releasedOn } : {}), ...(cache ? { cache } : {}) };
64
+ }
65
+
66
+ /** When the newest observation was released, if the latest point is that observation's. */
67
+ function latestRelease(observations: readonly DatedObservation[], latestDate: string): string | undefined {
68
+ const newest = observations.reduce<DatedObservation | null>((best, entry) =>
69
+ entry.value != null && (!best || entry.date > best.date) ? entry : best, null);
70
+ return newest?.date === latestDate && typeof newest.releasedOn === "string" ? newest.releasedOn : undefined;
60
71
  }
61
72
 
62
73
  /**
@@ -72,7 +83,9 @@ function alignDerivedBuilds(builds: StatBuild[]): StatBuild[] {
72
83
  const cap = (legs as string[]).reduce((oldest, date) => date < oldest ? date : oldest);
73
84
  if ((entry.points.at(-1)?.date ?? "") <= cap) return entry;
74
85
  const points = entry.points.filter((point) => point.date <= cap);
75
- return points.length > 0 ? { ...entry, points, trend: fitTrend(points, "linear") } : entry;
86
+ if (points.length === 0) return entry;
87
+ const { releasedOn: _cutRelease, ...rest } = entry;
88
+ return { ...rest, points, trend: fitTrend(points, "linear") };
76
89
  });
77
90
  }
78
91
 
@@ -5,6 +5,7 @@ export type StatCategoryId =
5
5
  | "inflation"
6
6
  | "labor"
7
7
  | "growth"
8
+ | "nowcasts"
8
9
  | "consumer"
9
10
  | "housing"
10
11
  | "rates"
@@ -14,6 +15,7 @@ export const STAT_CATEGORIES: ReadonlyArray<{ id: StatCategoryId; label: string
14
15
  { id: "inflation", label: "Inflation" },
15
16
  { id: "labor", label: "Labor" },
16
17
  { id: "growth", label: "Growth" },
18
+ { id: "nowcasts", label: "Nowcasts & conditions" },
17
19
  { id: "consumer", label: "Consumer" },
18
20
  { id: "housing", label: "Housing" },
19
21
  { id: "rates", label: "Rates & Money" },
@@ -56,6 +58,8 @@ export interface StatDef {
56
58
  staleAfterMs: number;
57
59
  /** Searchable description; the long-form reference lives in docs/economics-reference.md. */
58
60
  note: string;
61
+ /** Other words the catalog and the pane's filter find it by: `PMMS` for the mortgage rate. */
62
+ keywords?: readonly string[];
59
63
  /** Concise measurement identity that must remain beside the values. */
60
64
  measurementBasis?: string;
61
65
  /**
@@ -1,6 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import { ExternalLinkText, type StatItem } from "../../../components/ui";
3
- import { fredSeriesUrl } from "../../../sources/gloomberb-cloud/fred-series";
3
+ import { fredSeriesUrl, fredSourceLabel } from "../../../sources/gloomberb-cloud/fred-series";
4
4
  import { colors } from "../../../theme/colors";
5
5
  import { Box, Text } from "../../../ui";
6
6
  import { formatBasisPoints } from "../../../utils/basis-points";
@@ -74,7 +74,7 @@ export function StatDetail({
74
74
  <Box flexDirection="row" flexWrap="wrap" paddingX={1} flexShrink={0}>
75
75
  <ExternalLinkText
76
76
  url={fredSeriesUrl(stat.seriesId)}
77
- label={`FRED ${stat.seriesId}`}
77
+ label={fredSourceLabel(stat.seriesId)}
78
78
  color={colors.text}
79
79
  />
80
80
  {stat.measurementBasis ? <Text fg={colors.textDim}>{` · ${stat.measurementBasis}`}</Text> : null}
@@ -3,6 +3,7 @@ import type {
3
3
  HeadlessPaneDefinition,
4
4
  HeadlessPaneEntry,
5
5
  } from "../../../types/plugin";
6
+ import { fredSourceLabel } from "../../../sources/gloomberb-cloud/fred-series";
6
7
  import { formatBasisPoints, toBasisPoints } from "../../../utils/basis-points";
7
8
  import { formatNumber } from "../../../utils/format";
8
9
  import type { StatDef } from "./defs";
@@ -70,8 +71,9 @@ function detailEntries(view: StatViewModel, cutoffShown: boolean): HeadlessPaneE
70
71
  })),
71
72
  // FRED dates a monthly reading at the month's first day; the text says which period it is.
72
73
  // A Treasury yield adds when in the day it was taken, so it is not read against ^TNX's earlier close.
73
- { label: "Period", value: view.latest.date, formatted: view.stat.cutoff && !cutoffShown ? `${view.reading} ${view.stat.cutoff}` : view.reading },
74
- { label: "Source", value: `FRED ${view.stat.seriesId}` },
74
+ // A figure dated by its period also says when it was released: "Sep 2026, released Tue 20 Oct".
75
+ { label: "Period", value: view.latest.date, formatted: view.stat.cutoff && !cutoffShown ? `${view.reading} ${view.stat.cutoff}` : view.readingReleased },
76
+ { label: "Source", value: fredSourceLabel(view.stat.seriesId) },
75
77
  ];
76
78
  }
77
79
 
@@ -115,6 +117,11 @@ export function projectStatsHeadlessBundle(
115
117
  format: (value: unknown) => formatNumber(Number(value), 0),
116
118
  },
117
119
  { key: "asOf", header: "Period", format: (_value: unknown, row: Record<string, unknown>) => String(row.reading) },
120
+ {
121
+ key: "releasedOn",
122
+ header: "Released",
123
+ format: (_value: unknown, row: Record<string, unknown>) => typeof row.released === "string" ? row.released.replace(/^released /, "") : "",
124
+ },
118
125
  ],
119
126
  rows: categoryViews.map((view) => ({
120
127
  id: view.stat.id,
@@ -129,8 +136,12 @@ export function projectStatsHeadlessBundle(
129
136
  previousBasisPoints: view.previous ? toBasisPoints(view.previous.value) : null,
130
137
  } : {}),
131
138
  percentile: view.percentile,
139
+ // The period the figure covers; `releasedOn` is when it was published, which the report is as of.
132
140
  asOf: view.latest.date,
141
+ releasedOn: view.releasedOn,
142
+ ...(view.periodicity ? { periodicity: view.periodicity } : {}),
133
143
  reading: view.reading,
144
+ released: view.released,
134
145
  stale: view.observationStale || view.cacheStale,
135
146
  fetchedAt: view.fetchedAt,
136
147
  cacheStale: view.cacheStale,
@@ -23,15 +23,15 @@ export const econStatisticsModule: PluginModule = {
23
23
  paneId: ECON_STATISTICS_PANE_ID,
24
24
  label: "Economic Statistics",
25
25
  description: "Inflation, labour, growth, housing and rates against their own history.",
26
- keywords: [
26
+ keywords: [...new Set([
27
27
  "economic",
28
28
  "statistics",
29
29
  "macro",
30
30
  "indicators",
31
31
  "data",
32
32
  ...STAT_CATEGORIES.map((entry) => entry.label.toLowerCase()),
33
- ...STATS.map((entry) => entry.shortLabel.toLowerCase()),
34
- ],
33
+ ...STATS.flatMap((entry) => [entry.shortLabel, ...entry.keywords ?? []].map((keyword) => keyword.toLowerCase())),
34
+ ])],
35
35
  shortcut: {
36
36
  prefix: "ECST",
37
37
  argPlaceholder: "statistic",
@@ -63,6 +63,7 @@ function matchesQuery(view: StatViewModel, query: string): boolean {
63
63
  view.stat.seriesId,
64
64
  categoryLabel(view.stat.category),
65
65
  view.stat.note,
66
+ ...view.stat.keywords ?? [],
66
67
  ].join(" ").toLowerCase();
67
68
  return query.split(/\s+/).every((token) => haystack.includes(token));
68
69
  }
@@ -150,7 +151,7 @@ export function EconStatisticsPane({ focused, width, height }: PaneProps) {
150
151
  // A Treasury yield names when in the day it was taken, as GC does, so it is not read against ^TNX's earlier close.
151
152
  const cutoff = selected.stat.cutoff ? ` ${selected.stat.cutoff}` : "";
152
153
  const info: PaneFooterSegment[] = [
153
- { id: "as-of", parts: [{ text: `reading for ${selected.reading}${cutoff}`, tone: "muted" }] },
154
+ { id: "as-of", parts: [{ text: `reading for ${cutoff ? selected.reading : selected.readingReleased}${cutoff}`, tone: "muted" }] },
154
155
  ];
155
156
  // The cached first paint is being replaced; its age only counts once that load fails.
156
157
  const seeding = resource.loading && resource.updatedAt === null && !selected.refreshError;
@@ -5,6 +5,9 @@ import type { StatDef } from "./defs";
5
5
  const DAY_MS = 24 * 60 * 60 * 1000;
6
6
  const DAILY = 6 * DAY_MS;
7
7
  const WEEKLY = 21 * DAY_MS;
8
+ // GDPNow is dated at quarter start but updated through the following month's
9
+ // advance GDP release; allow that ~120-day span plus two weeks.
10
+ const NOWCAST_QUARTERLY = 135 * DAY_MS;
8
11
  // FRED dates a print at the start of its period, so an on-time print is two
9
12
  // periods plus the release lag old just before the next one lands. Each limit
10
13
  // adds about two weeks to the slowest normal lag of its group.
@@ -16,11 +19,14 @@ const QUARTERLY = 235 * DAY_MS; // GDP, productivity: two quarters plus a lag up
16
19
  const pct = (value: number) => `${formatNumber(value, 1)}%`;
17
20
  const pct2 = (value: number) => `${formatNumber(value, 2)}%`;
18
21
  const plain = (value: number) => formatNumber(value, 1);
22
+ const index2 = (value: number) => formatNumber(value, 2);
19
23
  /** FRED reports payrolls and claims in thousands already. */
20
24
  const thousands = (value: number) => `${formatNumber(value / 1000, value >= 10_000 ? 1 : 2)}M`;
21
25
  const signedThousands = (value: number) =>
22
26
  `${value > 0 ? "+" : ""}${formatNumber(value, 0)}k`;
23
27
  const billions = (value: number) => `${formatNumber(value, 0)}B`;
28
+ /** A spread already scaled to basis points; the label says the unit. */
29
+ const basisPoints = (value: number) => formatNumber(value, 0);
24
30
 
25
31
  function stat(def: StatDef): StatDef {
26
32
  return def;
@@ -249,6 +255,68 @@ export const STATS: readonly StatDef[] = [
249
255
  limit: 500,
250
256
  }),
251
257
 
258
+ // ---- Nowcasts & conditions --------------------------------------------
259
+ stat({
260
+ id: "gdpnow",
261
+ measurementBasis: "Estimate · q/q annualized",
262
+ label: "Atlanta Fed GDPNow",
263
+ shortLabel: "GDPNow",
264
+ category: "nowcasts",
265
+ seriesId: "GDPNOW",
266
+ transform: "level",
267
+ direction: "higher-is-good",
268
+ axisUnit: "%",
269
+ formatValue: pct,
270
+ reference: { value: 0, label: "flat" },
271
+ staleAfterMs: NOWCAST_QUARTERLY,
272
+ note: "Atlanta Fed model estimate of real GDP growth, updated within the quarter. Already an annualized percentage change, not a GDP level.",
273
+ }),
274
+ stat({
275
+ id: "nfci",
276
+ measurementBasis: "Weekly · index",
277
+ label: "Chicago Fed Financial Conditions",
278
+ shortLabel: "Chicago NFCI",
279
+ category: "nowcasts",
280
+ seriesId: "NFCI",
281
+ transform: "level",
282
+ direction: "higher-is-bad",
283
+ axisUnit: "",
284
+ formatValue: index2,
285
+ reference: { value: 0, label: "average" },
286
+ staleAfterMs: WEEKLY,
287
+ note: "Chicago Fed National Financial Conditions Index. Positive values mean tighter-than-average conditions; negative values mean looser conditions.",
288
+ }),
289
+ stat({
290
+ id: "financial-stress",
291
+ measurementBasis: "Weekly · index",
292
+ label: "St. Louis Fed Financial Stress",
293
+ shortLabel: "St. Louis FSI",
294
+ category: "nowcasts",
295
+ seriesId: "STLFSI4",
296
+ transform: "level",
297
+ direction: "higher-is-bad",
298
+ axisUnit: "",
299
+ formatValue: index2,
300
+ reference: { value: 0, label: "average" },
301
+ staleAfterMs: WEEKLY,
302
+ note: "St. Louis Fed Financial Stress Index, current fourth version. Positive values mean above-average stress; negative values mean below-average stress.",
303
+ }),
304
+ stat({
305
+ id: "median-cpi",
306
+ measurementBasis: "m/m annualized · seasonally adjusted",
307
+ label: "Cleveland Fed Median CPI",
308
+ shortLabel: "Median CPI",
309
+ category: "nowcasts",
310
+ seriesId: "MEDCPIM158SFRBCLE",
311
+ transform: "level",
312
+ direction: "higher-is-bad",
313
+ axisUnit: "%",
314
+ formatValue: pct,
315
+ reference: null,
316
+ staleAfterMs: MONTHLY_EARLY,
317
+ note: "Cleveland Fed weighted median consumer price change. Published as an annualized monthly percentage change, not a year-over-year inflation rate.",
318
+ }),
319
+
252
320
  // ---- Consumer --------------------------------------------------------
253
321
  stat({
254
322
  id: "retail-sales",
@@ -378,6 +446,41 @@ export const STATS: readonly StatDef[] = [
378
446
  note: "Newly built homes sold, at an annual rate.",
379
447
  limit: 900,
380
448
  }),
449
+ stat({
450
+ id: "mortgage-30y",
451
+ measurementBasis: "Weekly · Freddie Mac PMMS",
452
+ label: "30-Year Mortgage Rate",
453
+ shortLabel: "30Y mortgage rate",
454
+ category: "housing",
455
+ seriesId: "MORTGAGE30US",
456
+ transform: "level",
457
+ direction: "neutral",
458
+ axisUnit: "%",
459
+ formatValue: pct2,
460
+ reference: null,
461
+ staleAfterMs: WEEKLY,
462
+ note: "Freddie Mac's weekly average 30-year fixed mortgage rate, what a home purchase is financed at.",
463
+ keywords: ["mortgage rates", "PMMS", "Freddie Mac", "homebuilders"],
464
+ }),
465
+ stat({
466
+ id: "mortgage-spread",
467
+ measurementBasis: "30Y mortgage minus 10Y Treasury on the PMMS date",
468
+ label: "Mortgage–10Y Spread (bp)",
469
+ shortLabel: "Mortgage–10Y (bp)",
470
+ category: "housing",
471
+ seriesId: "MORTGAGE30US10Y",
472
+ derivedFrom: ["mortgage-30y", "ten-year"],
473
+ transform: "level",
474
+ // Gloom Cloud serves it in percentage points, as FRED does its spreads.
475
+ scale: 100,
476
+ direction: "neutral",
477
+ axisUnit: "",
478
+ formatValue: basisPoints,
479
+ reference: null,
480
+ staleAfterMs: WEEKLY,
481
+ note: "The 30-year mortgage rate less the 10-year Treasury yield on each survey date, how much mortgages pay over Treasuries.",
482
+ keywords: ["mortgage spread", "PMMS", "homebuilders"],
483
+ }),
381
484
  // ---- Rates & money ---------------------------------------------------
382
485
  stat({
383
486
  id: "fed-funds",