gloomberb 0.18.4 → 0.19.0

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 (600) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/package.json +1 -1
  4. package/patches/electrobun@1.18.1.patch +169 -5
  5. package/src/account/auth-model.ts +7 -3
  6. package/src/api-client/auth.ts +9 -4
  7. package/src/api-client/catalysts.ts +2 -1
  8. package/src/api-client/cot.ts +6 -2
  9. package/src/api-client/credit-documents.ts +6 -0
  10. package/src/api-client/data.ts +31 -6
  11. package/src/api-client/equity-screener.ts +24 -0
  12. package/src/api-client/fund-facts.ts +45 -4
  13. package/src/api-client/index.ts +171 -11
  14. package/src/api-client/live-scan.ts +91 -0
  15. package/src/api-client/market-discovery.ts +10 -0
  16. package/src/api-client/market-movers.ts +7 -0
  17. package/src/api-client/members.ts +13 -1
  18. package/src/api-client/perps.ts +43 -0
  19. package/src/api-client/request.ts +222 -41
  20. package/src/api-client/research-activity.ts +6 -12
  21. package/src/api-client/types.ts +74 -0
  22. package/src/app/keybindings/index.ts +3 -0
  23. package/src/app/keybindings/labels.ts +18 -1
  24. package/src/app/keybindings/resolve.ts +14 -0
  25. package/src/app/pane-runtime/plugin-bindings.ts +9 -5
  26. package/src/app/runtime/broker-import.ts +42 -27
  27. package/src/app/runtime/plugin-bindings.ts +73 -56
  28. package/src/architecture/core-builtin-allowlist.json +1 -1
  29. package/src/architecture/pane-tabs-allowlist.json +3 -0
  30. package/src/architecture/ttl-caches-allowlist.json +19 -0
  31. package/src/brokers/sync-broker-instance.ts +2 -8
  32. package/src/capabilities/chart-series.ts +1 -1
  33. package/src/cli/commands/crypto-hints.ts +40 -24
  34. package/src/cli/commands/fred-series.ts +5 -0
  35. package/src/cli/commands/keybindings.ts +23 -0
  36. package/src/cli/commands/market.ts +138 -46
  37. package/src/cli/commands/options-chain.ts +107 -10
  38. package/src/cli/commands/options-leaps.ts +9 -3
  39. package/src/cli/commands/overview.ts +176 -39
  40. package/src/cli/commands/search.ts +39 -3
  41. package/src/cli/commands/themes.ts +11 -2
  42. package/src/cli/commands/ticker.ts +57 -35
  43. package/src/cli/company-name-hint.ts +41 -0
  44. package/src/cli/earnings-calendar.ts +1 -1
  45. package/src/cli/errors.ts +10 -2
  46. package/src/cli/export-source.ts +29 -1
  47. package/src/cli/glossary.ts +73 -1
  48. package/src/cli/history-rows.ts +87 -16
  49. package/src/cli/index.ts +2 -0
  50. package/src/cli/known-gaps.ts +5 -2
  51. package/src/cli/listing-arg.ts +195 -56
  52. package/src/cli/output-file.ts +68 -0
  53. package/src/cli/pane-functions/capabilities.ts +3 -0
  54. package/src/cli/pane-functions/catalog.ts +80 -7
  55. package/src/cli/pane-functions/dom.ts +13 -3
  56. package/src/cli/pane-functions/freshness.ts +111 -16
  57. package/src/cli/pane-functions/function-help.ts +23 -13
  58. package/src/cli/pane-functions/headless.ts +56 -12
  59. package/src/cli/pane-functions/index.ts +58 -16
  60. package/src/cli/pane-functions/market-session.ts +81 -9
  61. package/src/cli/pane-functions/options.ts +19 -1
  62. package/src/cli/pane-functions/report.ts +5 -1
  63. package/src/cli/pane-functions/resolver.ts +35 -8
  64. package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
  65. package/src/cli/pane-functions/screenshot-types.ts +5 -0
  66. package/src/cli/quote-answer.ts +30 -13
  67. package/src/cli/report-tables.ts +18 -7
  68. package/src/cli/restore-plugins.ts +13 -1
  69. package/src/cli/result.ts +57 -5
  70. package/src/cli/ticker-resolution.ts +3 -2
  71. package/src/components/chart/composite/composite-chart.tsx +26 -4
  72. package/src/components/chart/composite/format.ts +27 -0
  73. package/src/components/chart/composite/interactions.ts +6 -0
  74. package/src/components/chart/composite/legend.tsx +45 -7
  75. package/src/components/chart/composite/levels.ts +2 -0
  76. package/src/components/chart/composite/panel-gestures.ts +33 -0
  77. package/src/components/chart/composite/panel-series.ts +1 -0
  78. package/src/components/chart/composite/panel-surface.tsx +61 -5
  79. package/src/components/chart/composite/range-statistics.ts +62 -0
  80. package/src/components/chart/composite/rasterizer.ts +24 -13
  81. package/src/components/chart/composite/scene.ts +46 -7
  82. package/src/components/chart/composite/series-axis-tags.tsx +16 -9
  83. package/src/components/chart/composite/series-cues.ts +14 -0
  84. package/src/components/chart/composite/text-renderer.ts +9 -2
  85. package/src/components/chart/composite/tool-catalog.ts +36 -0
  86. package/src/components/chart/composite/tools.ts +203 -44
  87. package/src/components/chart/composite/types.ts +4 -0
  88. package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
  89. package/src/components/command-bar/assist/inventory.ts +2 -1
  90. package/src/components/command-bar/commands/direct/index.ts +28 -13
  91. package/src/components/command-bar/pane-templates/items.ts +3 -2
  92. package/src/components/command-bar/panel/prompt-binding.ts +0 -8
  93. package/src/components/command-bar/workflow/alert.ts +1 -1
  94. package/src/components/command-bar/workflow/collection-actions.ts +3 -3
  95. package/src/components/layout/header.tsx +26 -40
  96. package/src/components/layout/pane/footer/index.tsx +1 -0
  97. package/src/components/layout/pane/footer/model.ts +27 -0
  98. package/src/components/onboarding/onboarding-frame.tsx +1 -1
  99. package/src/components/onboarding/onboarding-wizard.tsx +4 -1
  100. package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -9
  101. package/src/components/onboarding/wizard-broker-sync.ts +0 -1
  102. package/src/components/onboarding/wizard-positions.ts +3 -3
  103. package/src/components/ticker/list-table-view.tsx +4 -1
  104. package/src/components/ui/choice-dialog.tsx +23 -18
  105. package/src/components/ui/choice-groups.ts +18 -0
  106. package/src/components/ui/data-table/opentui/index.tsx +9 -7
  107. package/src/components/ui/data-table/opentui/model.ts +26 -1
  108. package/src/components/ui/data-table/types.ts +2 -0
  109. package/src/components/ui/display.tsx +5 -1
  110. package/src/components/ui/list-view.tsx +8 -4
  111. package/src/components/ui/query-bar-keys.tsx +2 -0
  112. package/src/components/ui/query-bar.tsx +1 -0
  113. package/src/components/ui/select-button.tsx +5 -1
  114. package/src/components/ui/select-field.tsx +1 -0
  115. package/src/components/ui/table-layout.ts +8 -5
  116. package/src/core/app-runtime.ts +2 -0
  117. package/src/core/app-services.ts +2 -2
  118. package/src/core/state/app/layout.ts +2 -0
  119. package/src/core/state/app/state.ts +9 -0
  120. package/src/core/state/app/types.ts +3 -0
  121. package/src/data/config/chart-settings.ts +1 -1
  122. package/src/data/json-ticker-repository.ts +17 -8
  123. package/src/data/saved-copies.ts +55 -16
  124. package/src/data/ticker-repository.ts +16 -9
  125. package/src/data/ticker-writes.ts +81 -0
  126. package/src/data/ttl-cache.ts +165 -0
  127. package/src/docs/snapshot.json +427 -216
  128. package/src/i18n/es.ts +19 -3
  129. package/src/i18n/ja.ts +19 -3
  130. package/src/i18n/ko.ts +19 -3
  131. package/src/i18n/zh-cn.ts +19 -3
  132. package/src/i18n/zh-tw.ts +19 -3
  133. package/src/market-data/coordinator/financials.ts +10 -2
  134. package/src/market-data/coordinator/index.ts +3 -1
  135. package/src/market-data/coordinator/quotes.ts +4 -2
  136. package/src/market-data/depositary-pair.ts +2 -2
  137. package/src/market-data/fund-facts.ts +50 -0
  138. package/src/market-data/market/change-basis.ts +48 -7
  139. package/src/market-data/market/dated-previous-close.ts +203 -0
  140. package/src/market-data/market/format.ts +25 -0
  141. package/src/market-data/market/freshness.ts +2 -1
  142. package/src/market-data/market/futures-week.ts +68 -0
  143. package/src/market-data/market/status.ts +16 -4
  144. package/src/market-data/options-alternatives.ts +141 -4
  145. package/src/market-data/quotes/contributions.ts +20 -2
  146. package/src/market-data/quotes/resolution.ts +3 -0
  147. package/src/market-data/selectors.ts +3 -0
  148. package/src/news/aggregator.ts +113 -9
  149. package/src/news/cloud-session.ts +21 -0
  150. package/src/news/hooks.ts +1 -0
  151. package/src/news/news-model.ts +1 -0
  152. package/src/news/types.ts +11 -0
  153. package/src/notifications/notification-log.ts +6 -4
  154. package/src/plugins/builtin/alerts/alert-engine.ts +25 -2
  155. package/src/plugins/builtin/alerts/alert-log.ts +33 -0
  156. package/src/plugins/builtin/alerts/calendar-events.ts +57 -6
  157. package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
  158. package/src/plugins/builtin/alerts/cli.ts +380 -82
  159. package/src/plugins/builtin/alerts/command.ts +31 -0
  160. package/src/plugins/builtin/alerts/constants.ts +1 -1
  161. package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
  162. package/src/plugins/builtin/alerts/fired-log.ts +113 -8
  163. package/src/plugins/builtin/alerts/format.ts +80 -4
  164. package/src/plugins/builtin/alerts/headless.ts +30 -7
  165. package/src/plugins/builtin/alerts/history-rows.ts +7 -3
  166. package/src/plugins/builtin/alerts/history.ts +2 -0
  167. package/src/plugins/builtin/alerts/index.tsx +135 -22
  168. package/src/plugins/builtin/alerts/live.ts +3 -3
  169. package/src/plugins/builtin/alerts/metric-command.ts +134 -0
  170. package/src/plugins/builtin/alerts/metric-data.ts +111 -0
  171. package/src/plugins/builtin/alerts/metric-model.ts +324 -0
  172. package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
  173. package/src/plugins/builtin/alerts/pane.tsx +90 -39
  174. package/src/plugins/builtin/alerts/quotes.ts +6 -0
  175. package/src/plugins/builtin/alerts/storage.ts +37 -10
  176. package/src/plugins/builtin/alerts/types.ts +7 -0
  177. package/src/plugins/builtin/analytics/index.tsx +2 -1
  178. package/src/plugins/builtin/analytics/risk-client.ts +16 -5
  179. package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
  180. package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
  181. package/src/plugins/builtin/analytics/risk-model.ts +55 -9
  182. package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
  183. package/src/plugins/builtin/attention/index.tsx +2 -1
  184. package/src/plugins/builtin/attention/listing.ts +14 -0
  185. package/src/plugins/builtin/backtest/headless.ts +10 -5
  186. package/src/plugins/builtin/backtest/pane.tsx +9 -4
  187. package/src/plugins/builtin/backtest/presets.ts +29 -3
  188. package/src/plugins/builtin/broker-manager/index.tsx +10 -5
  189. package/src/plugins/builtin/broker-manager/model.ts +6 -1
  190. package/src/plugins/builtin/broker-trading/controller.ts +22 -12
  191. package/src/plugins/builtin/broker-trading/index.tsx +13 -1
  192. package/src/plugins/builtin/broker-trading/order-feed.ts +9 -4
  193. package/src/plugins/builtin/broker-trading/pane.tsx +1 -1
  194. package/src/plugins/builtin/buildout/cells.tsx +12 -4
  195. package/src/plugins/builtin/buildout/format.ts +38 -0
  196. package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
  197. package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
  198. package/src/plugins/builtin/buildout/table-model.ts +23 -2
  199. package/src/plugins/builtin/builtin-plugin-meta.ts +7 -3
  200. package/src/plugins/builtin/catalysts/model.ts +2 -1
  201. package/src/plugins/builtin/changelog/index.tsx +9 -6
  202. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +6 -1
  203. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +1 -1
  204. package/src/plugins/builtin/chart-composer/cli-options.ts +9 -5
  205. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +12 -2
  206. package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -2
  207. package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
  208. package/src/plugins/builtin/chart-composer/editor.tsx +7 -5
  209. package/src/plugins/builtin/chart-composer/formula.ts +71 -18
  210. package/src/plugins/builtin/chart-composer/headless-schema.ts +21 -4
  211. package/src/plugins/builtin/chart-composer/headless.ts +19 -3
  212. package/src/plugins/builtin/chart-composer/index.tsx +1 -1
  213. package/src/plugins/builtin/chart-composer/pane.tsx +53 -9
  214. package/src/plugins/builtin/chart-composer/presets.ts +50 -15
  215. package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
  216. package/src/plugins/builtin/chart-composer/session-history.ts +18 -9
  217. package/src/plugins/builtin/chart-composer/settings.ts +27 -0
  218. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +40 -26
  219. package/src/plugins/builtin/chat/content/command-suggestions.ts +93 -0
  220. package/src/plugins/builtin/chat/content/composer.tsx +13 -6
  221. package/src/plugins/builtin/chat/content/footer.tsx +6 -3
  222. package/src/plugins/builtin/chat/content/index.tsx +50 -21
  223. package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
  224. package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
  225. package/src/plugins/builtin/chat/index.tsx +23 -0
  226. package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
  227. package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
  228. package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
  229. package/src/plugins/builtin/chat/pane-links/commands.ts +271 -0
  230. package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
  231. package/src/plugins/builtin/chat/pane-links/open.ts +8 -1
  232. package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
  233. package/src/plugins/builtin/clinical-trials/model.ts +0 -9
  234. package/src/plugins/builtin/clinical-trials/pane.tsx +15 -22
  235. package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +8 -6
  236. package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
  237. package/src/plugins/builtin/cloud/plugin.tsx +1 -1
  238. package/src/plugins/builtin/company-attention/building.tsx +5 -1
  239. package/src/plugins/builtin/company-attention/client.ts +8 -9
  240. package/src/plugins/builtin/company-attention/evidence.ts +4 -1
  241. package/src/plugins/builtin/company-attention/moves.tsx +5 -1
  242. package/src/plugins/builtin/company-attention/pane.tsx +9 -2
  243. package/src/plugins/builtin/company-attention/signals.tsx +5 -1
  244. package/src/plugins/builtin/correlation/headless.ts +13 -5
  245. package/src/plugins/builtin/correlation/history.ts +22 -0
  246. package/src/plugins/builtin/cot/client.ts +22 -18
  247. package/src/plugins/builtin/cot/headless.ts +15 -10
  248. package/src/plugins/builtin/cot/model.ts +14 -1
  249. package/src/plugins/builtin/cot/pane.tsx +22 -14
  250. package/src/plugins/builtin/credit-boards/client.ts +6 -10
  251. package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
  252. package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
  253. package/src/plugins/builtin/credit-conditions/model.ts +4 -0
  254. package/src/plugins/builtin/credit-conditions/series.ts +3 -1
  255. package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
  256. package/src/plugins/builtin/credit-documents/export.ts +173 -0
  257. package/src/plugins/builtin/credit-documents/headless.ts +7 -7
  258. package/src/plugins/builtin/credit-documents/model.ts +104 -14
  259. package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
  260. package/src/plugins/builtin/custom-view/sources.ts +2 -0
  261. package/src/plugins/builtin/dividend-yield/client.ts +131 -23
  262. package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
  263. package/src/plugins/builtin/dividend-yield/model.ts +8 -5
  264. package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
  265. package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
  266. package/src/plugins/builtin/dividend-yield/types.ts +20 -2
  267. package/src/plugins/builtin/dividend-yield/view.ts +30 -2
  268. package/src/plugins/builtin/docs/targets.ts +5 -1
  269. package/src/plugins/builtin/earnings/board-model.ts +16 -15
  270. package/src/plugins/builtin/earnings/board.tsx +62 -71
  271. package/src/plugins/builtin/earnings/headless.ts +40 -4
  272. package/src/plugins/builtin/earnings/scope.ts +31 -43
  273. package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
  274. package/src/plugins/builtin/earnings-calls/format.ts +31 -2
  275. package/src/plugins/builtin/earnings-calls/headless.ts +7 -2
  276. package/src/plugins/builtin/earnings-calls/model.ts +6 -1
  277. package/src/plugins/builtin/earnings-calls/pane.tsx +5 -4
  278. package/src/plugins/builtin/econ/calendar-model.ts +14 -9
  279. package/src/plugins/builtin/econ/figures.ts +72 -0
  280. package/src/plugins/builtin/econ/index.tsx +33 -3
  281. package/src/plugins/builtin/econ/types.ts +4 -0
  282. package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
  283. package/src/plugins/builtin/econ-statistics/headless.ts +85 -35
  284. package/src/plugins/builtin/econ-statistics/stats.ts +37 -9
  285. package/src/plugins/builtin/econ-statistics/view.ts +3 -0
  286. package/src/plugins/builtin/equity-screener/categories.ts +179 -0
  287. package/src/plugins/builtin/equity-screener/client.ts +4 -2
  288. package/src/plugins/builtin/equity-screener/headless.ts +144 -13
  289. package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
  290. package/src/plugins/builtin/equity-screener/model.ts +99 -10
  291. package/src/plugins/builtin/equity-screener/pane.tsx +70 -15
  292. package/src/plugins/builtin/exposure/charts.tsx +2 -2
  293. package/src/plugins/builtin/exposure/model.ts +13 -1
  294. package/src/plugins/builtin/exposure/pane.tsx +4 -4
  295. package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
  296. package/src/plugins/builtin/futures/index.tsx +1 -0
  297. package/src/plugins/builtin/futures/model.ts +2 -1
  298. package/src/plugins/builtin/futures/table.tsx +2 -2
  299. package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
  300. package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
  301. package/src/plugins/builtin/fx-matrix/client.ts +11 -3
  302. package/src/plugins/builtin/fx-matrix/headless.ts +6 -3
  303. package/src/plugins/builtin/fx-matrix/index.tsx +16 -4
  304. package/src/plugins/builtin/fx-matrix/live-legs.ts +54 -3
  305. package/src/plugins/builtin/gpu/headless.ts +8 -2
  306. package/src/plugins/builtin/help/function-index.ts +4 -1
  307. package/src/plugins/builtin/help/index.tsx +1 -0
  308. package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
  309. package/src/plugins/builtin/help/shortcut-model.ts +1 -1
  310. package/src/plugins/builtin/holders/fund-holders.ts +51 -0
  311. package/src/plugins/builtin/holders/headless.ts +18 -1
  312. package/src/plugins/builtin/iv-history/client.ts +52 -11
  313. package/src/plugins/builtin/iv-history/format.ts +36 -23
  314. package/src/plugins/builtin/iv-history/headless.ts +36 -18
  315. package/src/plugins/builtin/iv-history/index.tsx +2 -2
  316. package/src/plugins/builtin/iv-history/model.ts +163 -27
  317. package/src/plugins/builtin/iv-history/pane.tsx +10 -6
  318. package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
  319. package/src/plugins/builtin/iv-history/universe.ts +5 -1
  320. package/src/plugins/builtin/jobs/client.ts +25 -29
  321. package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
  322. package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
  323. package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
  324. package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
  325. package/src/plugins/builtin/macro-day/pane.tsx +7 -5
  326. package/src/plugins/builtin/macro-day/release-table.ts +2 -2
  327. package/src/plugins/builtin/market-heatmap/data.ts +8 -33
  328. package/src/plugins/builtin/market-movers/client.ts +25 -7
  329. package/src/plugins/builtin/market-movers/footer.ts +2 -2
  330. package/src/plugins/builtin/market-movers/headless.ts +32 -12
  331. package/src/plugins/builtin/market-movers/index.tsx +26 -14
  332. package/src/plugins/builtin/market-movers/min-float.ts +74 -0
  333. package/src/plugins/builtin/market-movers/model.ts +4 -1
  334. package/src/plugins/builtin/market-movers/screener.ts +14 -0
  335. package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
  336. package/src/plugins/builtin/market-movers/session-table.ts +4 -3
  337. package/src/plugins/builtin/market-movers/table.ts +17 -5
  338. package/src/plugins/builtin/members/breadth-pane.tsx +82 -0
  339. package/src/plugins/builtin/members/client.ts +19 -4
  340. package/src/plugins/builtin/members/headless.ts +20 -7
  341. package/src/plugins/builtin/members/index.tsx +9 -9
  342. package/src/plugins/builtin/members/model.ts +23 -4
  343. package/src/plugins/builtin/members/pane.tsx +25 -15
  344. package/src/plugins/builtin/news/index.tsx +1 -0
  345. package/src/plugins/builtin/news/wire/categories.ts +19 -3
  346. package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
  347. package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
  348. package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
  349. package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
  350. package/src/plugins/builtin/openfda/client.ts +14 -2
  351. package/src/plugins/builtin/openfda/index.tsx +3 -2
  352. package/src/plugins/builtin/openfda/model.ts +9 -0
  353. package/src/plugins/builtin/openfda/pane.tsx +42 -6
  354. package/src/plugins/builtin/options/analytics.ts +54 -6
  355. package/src/plugins/builtin/options/enrichment.ts +17 -5
  356. package/src/plugins/builtin/options/model-spot.ts +5 -2
  357. package/src/plugins/builtin/options/strike-window.ts +2 -1
  358. package/src/plugins/builtin/options/table.ts +6 -9
  359. package/src/plugins/builtin/options/types.ts +2 -0
  360. package/src/plugins/builtin/options/view.tsx +42 -12
  361. package/src/plugins/builtin/options-positioning/client.ts +30 -0
  362. package/src/plugins/builtin/options-positioning/headless.ts +74 -21
  363. package/src/plugins/builtin/options-positioning/index.tsx +4 -4
  364. package/src/plugins/builtin/options-positioning/model.ts +122 -14
  365. package/src/plugins/builtin/options-positioning/pane.tsx +87 -42
  366. package/src/plugins/builtin/options-scenario/client.ts +116 -47
  367. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
  368. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
  369. package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
  370. package/src/plugins/builtin/options-scenario/csp.ts +8 -2
  371. package/src/plugins/builtin/options-scenario/index.tsx +9 -7
  372. package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
  373. package/src/plugins/builtin/pe-band/model.ts +12 -49
  374. package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
  375. package/src/plugins/builtin/perps/cascade.ts +236 -0
  376. package/src/plugins/builtin/perps/client.ts +56 -2
  377. package/src/plugins/builtin/perps/freshness.ts +12 -10
  378. package/src/plugins/builtin/perps/headless.ts +65 -9
  379. package/src/plugins/builtin/perps/index.tsx +7 -5
  380. package/src/plugins/builtin/perps/live-rows.ts +10 -3
  381. package/src/plugins/builtin/perps/model.ts +18 -4
  382. package/src/plugins/builtin/perps/pane.tsx +32 -31
  383. package/src/plugins/builtin/perps/status-line.ts +25 -0
  384. package/src/plugins/builtin/plugin-module.ts +5 -1
  385. package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
  386. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
  387. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
  388. package/src/plugins/builtin/portfolio-list/cli/render.ts +12 -7
  389. package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
  390. package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
  391. package/src/plugins/builtin/portfolio-list/pane/index.tsx +4 -1
  392. package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
  393. package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
  394. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +3 -1
  395. package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
  396. package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
  397. package/src/plugins/builtin/primary-dealers/client.ts +13 -38
  398. package/src/plugins/builtin/rate-path/pane.tsx +2 -2
  399. package/src/plugins/builtin/realized-vol/index.tsx +2 -2
  400. package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
  401. package/src/plugins/builtin/relative-rotation/client.ts +18 -4
  402. package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
  403. package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
  404. package/src/plugins/builtin/relative-rotation/model.ts +16 -40
  405. package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
  406. package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
  407. package/src/plugins/builtin/research/event-model.ts +10 -8
  408. package/src/plugins/builtin/research/headless.ts +1 -1
  409. package/src/plugins/builtin/research/relative-valuation-headless.ts +5 -1
  410. package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
  411. package/src/plugins/builtin/research/relative-valuation-pane.tsx +11 -9
  412. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
  413. package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
  414. package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
  415. package/src/plugins/builtin/scanner/feed.ts +2 -2
  416. package/src/plugins/builtin/scanner/flow-model.ts +50 -4
  417. package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
  418. package/src/plugins/builtin/scanner/flow-session.ts +146 -0
  419. package/src/plugins/builtin/scanner/headless.ts +204 -35
  420. package/src/plugins/builtin/scanner/index.ts +40 -6
  421. package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
  422. package/src/plugins/builtin/scanner/live-feed.ts +168 -0
  423. package/src/plugins/builtin/scanner/live-headless.ts +138 -0
  424. package/src/plugins/builtin/scanner/live-model.ts +362 -0
  425. package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
  426. package/src/plugins/builtin/scanner/live-track.ts +186 -0
  427. package/src/plugins/builtin/scanner/lock-note.ts +3 -2
  428. package/src/plugins/builtin/seasonality/headless.ts +10 -1
  429. package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
  430. package/src/plugins/builtin/sec/fund-facts.ts +116 -34
  431. package/src/plugins/builtin/sec/headless.ts +2 -1
  432. package/src/plugins/builtin/series-inventory.ts +3 -0
  433. package/src/plugins/builtin/shared/cloud-resource.ts +3 -2
  434. package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
  435. package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
  436. package/src/plugins/builtin/shared/earnings-report.ts +2 -2
  437. package/src/plugins/builtin/shared/job-posting.ts +1 -0
  438. package/src/plugins/builtin/shared/macro-releases.ts +65 -0
  439. package/src/plugins/builtin/shared/members-menu.tsx +3 -2
  440. package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
  441. package/src/plugins/builtin/shared/report-freshness.ts +3 -2
  442. package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
  443. package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
  444. package/src/plugins/builtin/shared/ticker-company.ts +77 -0
  445. package/src/plugins/builtin/shared/use-quote-board.ts +10 -3
  446. package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
  447. package/src/plugins/builtin/shared/volatility/pricing.ts +26 -1
  448. package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
  449. package/src/plugins/builtin/themes/headless.ts +6 -4
  450. package/src/plugins/builtin/themes/model.ts +17 -8
  451. package/src/plugins/builtin/themes/pane.tsx +7 -7
  452. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
  453. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
  454. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
  455. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
  456. package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
  457. package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
  458. package/src/plugins/builtin/ticker-detail/pane.tsx +3 -2
  459. package/src/plugins/builtin/ticker-detail/quote-footer.ts +6 -1
  460. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
  461. package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
  462. package/src/plugins/builtin/time-sales/pane.tsx +31 -19
  463. package/src/plugins/builtin/treasury-daily/client.ts +41 -5
  464. package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
  465. package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
  466. package/src/plugins/builtin/treasury-daily/model.ts +50 -3
  467. package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
  468. package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
  469. package/src/plugins/builtin/vol-surface/client.ts +9 -17
  470. package/src/plugins/builtin/vol-surface/headless.ts +63 -14
  471. package/src/plugins/builtin/vol-surface/index.tsx +2 -2
  472. package/src/plugins/builtin/vol-surface/model.ts +22 -7
  473. package/src/plugins/builtin/vol-surface/pane.tsx +48 -9
  474. package/src/plugins/builtin/vol-surface/tables.ts +31 -3
  475. package/src/plugins/builtin/volatility/dvol.ts +46 -0
  476. package/src/plugins/builtin/volatility/index.tsx +2 -2
  477. package/src/plugins/builtin/volatility/pane.tsx +4 -4
  478. package/src/plugins/builtin/volatility/series.ts +26 -0
  479. package/src/plugins/builtin/world-indices/footer.ts +1 -1
  480. package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
  481. package/src/plugins/catalog-browser.ts +13 -8
  482. package/src/plugins/catalog-manifest.ts +2 -1
  483. package/src/plugins/marketplace/model.ts +18 -5
  484. package/src/portfolio/column-values.ts +5 -5
  485. package/src/portfolio/futures-positions.ts +6 -3
  486. package/src/portfolio/position-quantity.ts +15 -9
  487. package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
  488. package/src/remote/resources.ts +2 -1
  489. package/src/renderers/browser/app-services.ts +1 -7
  490. package/src/renderers/browser/config-host.ts +2 -55
  491. package/src/renderers/browser/main.tsx +7 -57
  492. package/src/renderers/dom/data-table/row.tsx +26 -0
  493. package/src/renderers/dom/desktop/list-view.tsx +13 -10
  494. package/src/renderers/dom/desktop/query-bar.tsx +4 -2
  495. package/src/renderers/dom/desktop/select-field.tsx +4 -2
  496. package/src/renderers/dom/host/chart-surface.tsx +21 -0
  497. package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
  498. package/src/renderers/electrobun/bun/desktop/backend.ts +29 -7
  499. package/src/renderers/electrobun/bun/desktop/host-requests.ts +7 -0
  500. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
  501. package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
  502. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
  503. package/src/renderers/electrobun/bun/desktop/update.ts +173 -5
  504. package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
  505. package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
  506. package/src/renderers/electrobun/bun/index.ts +25 -1
  507. package/src/renderers/electrobun/shared/app-name.ts +30 -0
  508. package/src/renderers/electrobun/shared/protocol.ts +10 -0
  509. package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
  510. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  511. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
  512. package/src/renderers/electrobun/view/main.tsx +24 -1
  513. package/src/renderers/electrobun/view/news-source.ts +3 -1
  514. package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
  515. package/src/renderers/electrobun/view/view-ids.ts +85 -0
  516. package/src/renderers/opentui/start.tsx +5 -0
  517. package/src/renderers/opentui/toast-host.tsx +71 -43
  518. package/src/series/registry.ts +1 -0
  519. package/src/series/types.ts +6 -0
  520. package/src/series/validate.ts +1 -0
  521. package/src/sources/gloomberb-cloud/index.ts +1 -0
  522. package/src/sources/gloomberb-cloud/news.ts +47 -7
  523. package/src/sources/gloomberb-cloud/normalizers.ts +2 -0
  524. package/src/sources/provider-router/batches.ts +10 -2
  525. package/src/sources/provider-router/financial-routes.ts +3 -3
  526. package/src/sources/provider-router/financials.ts +15 -3
  527. package/src/sources/provider-router/history.ts +28 -7
  528. package/src/sources/provider-router/index.ts +149 -10
  529. package/src/sources/provider-router/search.ts +13 -2
  530. package/src/state/app/context/index.tsx +3 -0
  531. package/src/state/ticker-cleanup.ts +50 -0
  532. package/src/sync/auth-transition.ts +19 -9
  533. package/src/sync/baseline.ts +10 -4
  534. package/src/sync/controller.ts +70 -19
  535. package/src/sync/core-contributors.ts +90 -31
  536. package/src/sync/react.ts +4 -1
  537. package/src/sync/types.ts +3 -0
  538. package/src/telemetry/stall-reports-dom.ts +38 -0
  539. package/src/telemetry/stall-reports-node.ts +75 -0
  540. package/src/telemetry/stall-reports.ts +214 -0
  541. package/src/telemetry/usage-counts.ts +0 -18
  542. package/src/test-support/preload.ts +14 -0
  543. package/src/theme/colors.ts +8 -0
  544. package/src/theme/themes.ts +10 -0
  545. package/src/tickers/company-name.ts +103 -3
  546. package/src/tickers/listing-venues.ts +38 -3
  547. package/src/tickers/search/bare-symbol.ts +36 -0
  548. package/src/tickers/search/index.ts +36 -7
  549. package/src/tickers/search/ranking.ts +10 -1
  550. package/src/tickers/search/types.ts +5 -0
  551. package/src/tickers/terminal-codes.ts +19 -0
  552. package/src/time-series/alignment.ts +1 -1
  553. package/src/time-series/base-series.ts +13 -5
  554. package/src/time-series/daily-valuation.ts +62 -0
  555. package/src/time-series/economic.ts +18 -4
  556. package/src/time-series/field-catalog.ts +2 -4
  557. package/src/time-series/filed-trailing-eps.ts +197 -0
  558. package/src/time-series/forward-valuation.ts +32 -0
  559. package/src/time-series/fundamentals.ts +198 -7
  560. package/src/time-series/hooks.ts +1 -0
  561. package/src/time-series/ice-credit.ts +3 -0
  562. package/src/time-series/price-comparison.ts +30 -2
  563. package/src/time-series/price-units.ts +72 -2
  564. package/src/time-series/resolve-context.ts +7 -1
  565. package/src/time-series/resolve.ts +116 -15
  566. package/src/time-series/series-presentation.ts +40 -6
  567. package/src/time-series/session-bar.ts +11 -0
  568. package/src/time-series/spec.ts +5 -3
  569. package/src/time-series/studies.ts +278 -74
  570. package/src/time-series/total-return.ts +160 -0
  571. package/src/time-series/transforms.ts +3 -3
  572. package/src/time-series/types.ts +27 -1
  573. package/src/time-series/valuation-releases.ts +39 -0
  574. package/src/types/data-provider.ts +9 -1
  575. package/src/types/desktop-window.ts +2 -0
  576. package/src/types/financials.ts +73 -2
  577. package/src/types/headless.ts +61 -5
  578. package/src/types/instrument.ts +3 -0
  579. package/src/types/news-source.ts +1 -0
  580. package/src/types/plugin.ts +10 -1
  581. package/src/ui/host.tsx +3 -0
  582. package/src/updater/command-names.ts +12 -7
  583. package/src/updater/failure.ts +4 -1
  584. package/src/utils/cli-output.ts +42 -1
  585. package/src/utils/crypto-pair.ts +44 -0
  586. package/src/utils/financial-statements.ts +6 -1
  587. package/src/utils/forward-dividend.ts +2 -0
  588. package/src/utils/fundamentals.ts +24 -3
  589. package/src/utils/fx-market-hours.ts +26 -3
  590. package/src/utils/main-thread-stall.ts +35 -2
  591. package/src/utils/market-capitalization.ts +24 -1
  592. package/src/utils/network-failure.ts +9 -6
  593. package/src/utils/option-expiry.ts +48 -1
  594. package/src/utils/options.ts +10 -0
  595. package/src/utils/plugin-proxy-hosts.json +1 -0
  596. package/src/utils/price-history.ts +12 -1
  597. package/src/utils/shell-word.ts +8 -0
  598. package/src/utils/trailing-dividend.ts +53 -4
  599. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
  600. package/src/renderers/browser/first-screen.ts +0 -193
@@ -1,21 +1,28 @@
1
1
  import type { HeadlessPaneDefinition, HeadlessPaneEntry } from "../../../types/plugin";
2
+ import { formatStrikeLabel } from "../../../utils/options";
2
3
  import { expirationOptionSeconds, expiryIsoDate, OPTION_EXPIRATION_FORMAT, OPTION_EXPIRATION_PLACEHOLDER } from "../../../utils/option-expiry";
3
4
  import { formatUtcTime } from "../../../utils/utc-time";
4
5
  import { loadGamma, loadOpenInterest, positioningSymbol, type GammaPayload, type OpenInterestPayload } from "./client";
5
6
  import { listingFateReport, loadListingFate } from "../../../tickers/listing-fate";
6
7
  import { resolveHeadlessInstrument } from "../shared/headless-market-data";
8
+ import { coinOptionsAlias, coinWithoutOptionsRefusal } from "../../../market-data/options-alternatives";
7
9
  import {
8
10
  ALL_EXPIRIES,
9
11
  expiryLabel,
12
+ expiryWithTimeLabel,
13
+ formatContracts,
14
+ isCoinContract,
15
+ settlementTime,
16
+ wallsByExpiry,
10
17
  formatCount,
11
18
  formatCountChange,
12
19
  formatDistance,
13
20
  formatGamma,
21
+ formatGammaTimes,
14
22
  formatLevel,
15
23
  formatPositioningSpot,
16
24
  formatPayout,
17
25
  formatRatio,
18
- formatStrike,
19
26
  GAMMA_UNIT,
20
27
  gammaWalls,
21
28
  netGammaByExpiry,
@@ -25,8 +32,9 @@ import {
25
32
 
26
33
  const METHODOLOGY = "https://gloom.sh/docs/options-positioning";
27
34
  const UNIT_TEXT = "$ of dealer delta per 1% move";
28
- const strike = (value: unknown) => typeof value === "number" ? formatStrike(value) : "--";
35
+ const strike = (value: unknown) => typeof value === "number" ? formatStrikeLabel(value) : "--";
29
36
  const count = (value: unknown) => formatCount(typeof value === "number" ? value : null);
37
+ const coinCount = (value: unknown) => formatContracts(typeof value === "number" ? value : null, true);
30
38
  const change = (value: unknown) => formatCountChange(typeof value === "number" ? value : null);
31
39
  const gamma = (value: unknown) => formatGamma(typeof value === "number" ? value : null);
32
40
  const failure = (error: unknown) => error instanceof Error ? error : new Error(String(error));
@@ -34,27 +42,47 @@ const time = (value: string | null) => value ? formatUtcTime(value) : "--";
34
42
  const level = (value: number | null, spot: number | null, none = "--") =>
35
43
  value == null ? none : `${formatLevel(value)}, ${formatDistance(value, spot)} vs spot`;
36
44
  const wall = (value: number | null, spot: number | null) =>
37
- value == null ? "--" : `${formatStrike(value)}, ${formatDistance(value, spot)} vs spot`;
45
+ value == null ? "--" : `${formatStrikeLabel(value)}, ${formatDistance(value, spot)} vs spot`;
38
46
 
39
47
  /**
40
- * What the report opens with: spot and the quote time gamma was priced at,
41
- * apart from the open interest session, then the figures the GEX tab shows.
42
- * Exports keep each figure whole; the text says them as the pane does.
48
+ * What the report opens with: spot, the instant gamma is evaluated at and
49
+ * when the quotes behind its volatilities were taken, apart from the open
50
+ * interest session, then the figures the GEX tab shows. Exports keep each
51
+ * figure whole; the text says them as the pane does.
43
52
  */
44
53
  function summary(openInterest: OpenInterestPayload, dealer: GammaPayload | null): { entries: HeadlessPaneEntry[]; textEntries: HeadlessPaneEntry[] } {
45
54
  // Gamma is priced at its own read of spot; the figures and their distances use that one.
46
55
  const spot = dealer?.spot ?? openInterest.spot;
47
56
  const spotAsOf = dealer ? dealer.spotAsOf : openInterest.spotAsOf;
57
+ const spotBasis = dealer ? dealer.spotBasis : openInterest.spotBasis;
58
+ const venue = openInterest.venue;
59
+ // Older servers send no gamma time: their quote time stands alone, as it did.
60
+ const gammaTimes = dealer ? formatGammaTimes(dealer.gammaAsOf, dealer.quotesAsOf) : null;
61
+ // A venue that publishes open interest live (Deribit) dates it to the read, not to a session.
62
+ const oiAsOf = venue && openInterest.oiAsOf ? openInterest.oiAsOf : null;
63
+ const contract = openInterest.contract;
64
+ const settles = settlementTime(openInterest.expiries[0]?.expiresAt);
48
65
  const entries: HeadlessPaneEntry[] = [
66
+ ...(venue ? [{ key: "venue", label: "Venue", value: venue }] : []),
49
67
  { key: "spot", label: "Spot", value: spot },
50
68
  { key: "spotAsOf", label: "Spot as of", value: spotAsOf },
51
- ...(dealer ? [{ key: "quotesAsOf", label: "Quotes as of", value: dealer.quotesAsOf }] : []),
52
- { key: "oiDate", label: "Open interest as of", value: openInterest.oiDate },
69
+ // An index outside its session: spot is the close, spotAsOf its time.
70
+ ...(spotBasis ? [{ key: "spotBasis", label: "Spot basis", value: spotBasis }] : []),
71
+ ...(dealer && gammaTimes ? [{ key: "gammaAsOf", label: "Gamma at", value: dealer.gammaAsOf ?? null },
72
+ { key: "quotesAsOf", label: "Vols from", value: dealer.quotesAsOf }]
73
+ : dealer ? [{ key: "quotesAsOf", label: "Quotes as of", value: dealer.quotesAsOf }] : []),
74
+ { key: "oiDate", label: "Open interest as of", value: oiAsOf ?? openInterest.oiDate },
75
+ ...(contract ? [{ key: "contract", label: "Contract", value: contract }] : []),
76
+ ...(settles ? [{ key: "settles", label: "Expiries settle", value: settles }] : []),
53
77
  ];
54
78
  const textEntries: HeadlessPaneEntry[] = [
55
- { label: "Spot", value: spot, formatted: formatPositioningSpot(spot, spotAsOf) },
56
- ...(dealer ? [{ label: "Quotes as of", value: dealer.quotesAsOf, formatted: time(dealer.quotesAsOf) }] : []),
57
- { label: "Open interest as of", value: openInterest.oiDate, formatted: openInterest.oiDate ?? "--" },
79
+ ...(venue ? [{ label: "Venue", value: venue }] : []),
80
+ { label: "Spot", value: spot, formatted: formatPositioningSpot(spot, spotAsOf, venue, spotBasis) },
81
+ ...(dealer && gammaTimes ? [{ label: "Gamma at", value: dealer.gammaAsOf ?? null, formatted: gammaTimes }]
82
+ : dealer ? [{ label: "Quotes as of", value: dealer.quotesAsOf, formatted: time(dealer.quotesAsOf) }] : []),
83
+ { label: "Open interest as of", value: oiAsOf ?? openInterest.oiDate, formatted: oiAsOf ? `${time(oiAsOf)}, live` : openInterest.oiDate ?? "--" },
84
+ ...(contract ? [{ label: "Contract", value: contract, formatted: `${contract.size} ${contract.unit}; OI counts ${contract.unit}` }] : []),
85
+ ...(settles ? [{ label: "Expiries settle", value: settles, formatted: `${settles}, the day each expiry names` }] : []),
58
86
  ];
59
87
  if (!dealer?.total) return { entries, textEntries };
60
88
  const { callWall, putWall } = gammaWalls(dealer.strikes);
@@ -86,8 +114,10 @@ function summary(openInterest: OpenInterestPayload, dealer: GammaPayload | null)
86
114
  export const optionsPositioningHeadless = (initialTab: PositioningTab): HeadlessPaneDefinition<"bundle"> => ({
87
115
  shape: "bundle",
88
116
  freshness: { status: "not-a-feed", basis: "daily open interest", cadence: "daily" },
89
- argument: { kind: "ticker", optional: true, description: "US option underlying, or SPX; SPY when omitted" },
117
+ argument: { kind: "ticker", optional: true, description: "US option underlying, BTC-USD or ETH-USD, or SPX; SPY when omitted" },
90
118
  usListingsOnly: "Options data",
119
+ symbolAlias: coinOptionsAlias(initialTab === "gex" ? "GEX" : "OPX"),
120
+ refuseSymbol: coinWithoutOptionsRefusal(initialTab === "gex" ? "GEX" : "OPX"),
91
121
  describe: (args) => `${initialTab === "gex" ? "GEX" : "OPX"} ${args.symbols[0] ?? "SPY"}`,
92
122
  discovery: {
93
123
  aliases: initialTab === "gex" ? ["GEX"] : ["OPX", "MAXPAIN"],
@@ -97,6 +127,7 @@ export const optionsPositioningHeadless = (initialTab: PositioningTab): Headless
97
127
  "Open interest is about two sessions old; the Expiries heading names its date.",
98
128
  "Dealer gamma assumes dealers are long every call and short every put.",
99
129
  "NDX and RUT index options are not covered; use QQQ and IWM.",
130
+ "BTC-USD and ETH-USD are Deribit's options: open interest is live and counted in coins, and expiries settle at 08:00 UTC.",
100
131
  ],
101
132
  },
102
133
  options: [
@@ -135,34 +166,52 @@ export const optionsPositioningHeadless = (initialTab: PositioningTab): Headless
135
166
  : listingFateReport(await loadListingFate(await resolveHeadlessInstrument(ctx, symbol), ctx.marketData), { served: false }, loadErrors);
136
167
  const errors = fate?.errors ?? loadErrors;
137
168
  const changes = openInterest.previousOiDate != null;
169
+ const coin = isCoinContract(openInterest.contract);
170
+ const contracts = coin ? coinCount : count;
171
+ const unit = coin ? ` (${openInterest.contract!.unit})` : "";
172
+ // Each expiry's walls, from the all-expiries gamma; absent from older servers.
173
+ const expiryWalls = allExpiries instanceof Error ? null : wallsByExpiry(allExpiries);
174
+ const settles = openInterest.expiries.some((row) => settlementTime(row.expiresAt));
175
+ const oiStamp = openInterest.venue && openInterest.oiAsOf ? `${time(openInterest.oiAsOf)}, live` : openInterest.oiDate ?? "--";
138
176
  const gammaShown = dealer instanceof Error || !dealer.total ? null : dealer;
139
177
  const scope = dealer instanceof Error ? null : dealer.expiry ? expiryLabel(dealer.expiry) : "all expiries";
140
178
  const walls = gammaShown ? gammaWalls(gammaShown.strikes) : null;
141
179
  return {
142
180
  // Open interest is counted once a day and arrives about two sessions late, dated in the heading and the summary;
143
181
  // spot and the quotes have their own times in the summary.
144
- freshness: { asOf: openInterest.oiDate },
182
+ // A venue's live book (Deribit's) is a feed: read a minute ago, or held back 15 minutes for delayed access.
183
+ freshness: openInterest.venue && openInterest.oiAsOf
184
+ ? { asOf: openInterest.oiAsOf, status: openInterest.delayed ? "delayed" as const : "live" as const,
185
+ ...(openInterest.delayed ? { delayMinutes: 15 } : {}) }
186
+ : { asOf: openInterest.oiDate },
145
187
  sections: [
146
188
  { title: scope ? `Summary · ${scope}` : "Summary", ...summary(openInterest, dealer instanceof Error ? null : dealer) },
147
- { title: `Expiries · OI as of ${openInterest.oiDate ?? "--"}`, columns: [
148
- { key: "date", header: "Expiry" }, { key: "days", header: "Days" },
149
- { key: "callOI", header: "Call OI", format: count }, { key: "putOI", header: "Put OI", format: count },
189
+ { title: `Expiries · OI as of ${oiStamp}`, columns: [
190
+ { key: "date", header: "Expiry" },
191
+ // Deribit's expiries settle at 08:00 UTC on the day they name.
192
+ ...(settles ? [{ key: "settles", header: "Settles" }] : []),
193
+ { key: "days", header: "Days" },
194
+ { key: "callOI", header: `Call OI${unit}`, format: contracts }, { key: "putOI", header: `Put OI${unit}`, format: contracts },
150
195
  { key: "putCallRatio", header: "P/C", format: (value: unknown) => formatRatio(value as number | null) },
151
196
  ...(changes ? [{ key: "change", header: "OI chg", format: change }] : []),
152
197
  { key: "maxPain", header: "Max pain", format: strike },
153
198
  { key: "distance", header: "Vs spot" },
199
+ ...(expiryWalls ? [{ key: "callWall", header: "Call wall", format: strike }, { key: "putWall", header: "Put wall", format: strike }] : []),
154
200
  ...(gammaColumn ? [{ key: "netGamma", header: "Net GEX $", format: gamma, unitKey: "netGammaUnit" }] : []),
155
201
  ], rows: openInterest.expiries.map((row) => ({
156
202
  ...row,
203
+ ...(settles ? { settles: settlementTime(row.expiresAt) } : {}),
157
204
  change: row.callChange == null ? null : row.callChange + (row.putChange ?? 0),
158
205
  distance: formatDistance(row.maxPain, spot),
206
+ ...(expiryWalls ? { callWall: expiryWalls.get(row.date)?.callWall ?? null, putWall: expiryWalls.get(row.date)?.putWall ?? null } : {}),
159
207
  ...(gammaColumn ? { netGamma: expiryGamma?.get(row.date) ?? null, netGammaUnit: GAMMA_UNIT } : {}),
160
208
  })) },
161
- { title: `Strikes · ${openInterest.expiry ? expiryLabel(openInterest.expiry) : "--"}`, columns: [
209
+ { title: `Strikes · ${openInterest.expiry
210
+ ? expiryWithTimeLabel(openInterest.expiries.find((row) => row.date === openInterest.expiry) ?? { date: openInterest.expiry }) : "--"}`, columns: [
162
211
  { key: "strike", header: "Strike", format: strike },
163
- { key: "callOI", header: "Call OI", format: count },
212
+ { key: "callOI", header: `Call OI${unit}`, format: contracts },
164
213
  ...(changes ? [{ key: "callChange", header: "Call chg", format: change }] : []),
165
- { key: "putOI", header: "Put OI", format: count },
214
+ { key: "putOI", header: `Put OI${unit}`, format: contracts },
166
215
  ...(changes ? [{ key: "putChange", header: "Put chg", format: change }] : []),
167
216
  { key: "payout", header: "Payout $", format: (value: unknown) => formatPayout(value as number | null) },
168
217
  ], rows: openInterest.strikes.map((row) => ({ ...row })) },
@@ -188,12 +237,16 @@ export const optionsPositioningHeadless = (initialTab: PositioningTab): Headless
188
237
  previousOiDate: openInterest.previousOiDate,
189
238
  spot,
190
239
  spotAsOf: openInterest.spotAsOf,
240
+ ...(openInterest.spotBasis ? { spotBasis: openInterest.spotBasis } : {}),
191
241
  delayed: openInterest.delayed,
242
+ ...(openInterest.venue ? { venue: openInterest.venue, oiAsOf: openInterest.oiAsOf ?? null, contract: openInterest.contract ?? null } : {}),
192
243
  ...(dealer instanceof Error ? {} : {
193
- gamma: { expiry: dealer.expiry ?? ALL_EXPIRIES, spot: dealer.spot, spotAsOf: dealer.spotAsOf, total: dealer.total, band: dealer.band,
244
+ gamma: { expiry: dealer.expiry ?? ALL_EXPIRIES, spot: dealer.spot, spotAsOf: dealer.spotAsOf,
245
+ ...(dealer.spotBasis ? { spotBasis: dealer.spotBasis } : {}), total: dealer.total, band: dealer.band,
194
246
  bandWithBoxes: dealer.bandWithBoxes ?? null, boxes: dealer.boxes ?? [], flip: dealer.flip,
195
247
  callWall: walls?.callWall ?? null, putWall: walls?.putWall ?? null,
196
- unit: "dollars of dealer delta per 1% move", assumption: "dealers long calls, short puts", quotesAsOf: dealer.quotesAsOf },
248
+ unit: "dollars of dealer delta per 1% move", assumption: "dealers long calls, short puts",
249
+ gammaAsOf: dealer.gammaAsOf ?? null, quotesAsOf: dealer.quotesAsOf },
197
250
  }),
198
251
  methodology: METHODOLOGY,
199
252
  },
@@ -56,16 +56,16 @@ export const optionsPositioningModule: PluginModule = {
56
56
  positioningTemplate({
57
57
  id: "options-positioning-pane",
58
58
  label: "Options Positioning",
59
- description: "Open interest by strike and expiry, max pain, and dealer gamma (GEX).",
60
- keywords: ["opx", "open interest", "max pain", "put call", "expiry", "options"],
59
+ description: "Open interest by strike and expiry, max pain, walls and dealer gamma (GEX); BTC-USD and ETH-USD from Deribit.",
60
+ keywords: ["opx", "open interest", "max pain", "put call", "expiry", "options", "deribit", "bitcoin options", "ether options", "crypto options"],
61
61
  shortcut: "OPX",
62
62
  shortcutAliases: ["MAXPAIN"],
63
- }, "strikes", "Options open interest by strike and expiry, max pain, and dealer gamma (GEX) for a US underlying."),
63
+ }, "strikes", "Options open interest by strike and expiry, max pain, and dealer gamma (GEX) for a US underlying, or Deribit's BTC-USD and ETH-USD options."),
64
64
  positioningTemplate({
65
65
  id: "options-positioning-gex",
66
66
  label: "Dealer Gamma",
67
67
  description: "Net dealer gamma by strike, its total, flip level, call and put walls and the range for the dealer assumption.",
68
- keywords: ["gex", "gamma", "dealer gamma", "gamma exposure", "gamma flip", "call wall", "put wall"],
68
+ keywords: ["gex", "gamma", "dealer gamma", "gamma exposure", "gamma flip", "zero gamma", "gamma level", "call wall", "put wall", "0dte"],
69
69
  shortcut: "GEX",
70
70
  }, "gex"),
71
71
  ],
@@ -1,6 +1,15 @@
1
1
  import { formatCompact, formatCompactAmount } from "../../../utils/format";
2
- import { formatExpDate } from "../../../utils/options";
3
- import { modelSpotLabel, modelSpotStamp, modelSpotStampVariants, observedModelSpot } from "../options/model-spot";
2
+ import { formatExpDate, formatStrikeLabel } from "../../../utils/options";
3
+ import { formatUtcTime } from "../../../utils/utc-time";
4
+ import {
5
+ formatModelSpotPrice,
6
+ formatSpotTime,
7
+ modelSpotLabel,
8
+ modelSpotStamp,
9
+ modelSpotStampVariants,
10
+ observedModelSpot,
11
+ type OptionModelSpot,
12
+ } from "../options/model-spot";
4
13
 
5
14
  export type PositioningTab = "strikes" | "expiries" | "gex";
6
15
  export const POSITIONING_TABS: { value: PositioningTab; label: string }[] = [
@@ -46,13 +55,44 @@ export function netGammaByExpiry(
46
55
  return new Map(payload.byExpiry.map((row) => [row.expiry, row.net]));
47
56
  }
48
57
 
58
+ /**
59
+ * Each expiry's call and put walls, from an all-expiries gamma answer: the
60
+ * strikes of that expiry with the most call and put gamma. Null when the
61
+ * answer is for one expiry or the server is older than the fields.
62
+ */
63
+ export function wallsByExpiry(
64
+ payload: { expiry: string | null; byExpiry?: readonly { expiry: string; callWall?: number | null; putWall?: number | null }[] } | null | undefined,
65
+ ): Map<string, { callWall: number | null; putWall: number | null }> | null {
66
+ if (!payload || payload.expiry != null || !payload.byExpiry?.some((row) => "callWall" in row)) return null;
67
+ return new Map(payload.byExpiry.map((row) => [row.expiry, { callWall: row.callWall ?? null, putWall: row.putWall ?? null }]));
68
+ }
69
+
49
70
  const dateSeconds = (date: string) => Date.parse(`${date}T00:00:00Z`) / 1000;
50
71
  /** Oct 16 '26, as OMON names its expiries. */
51
72
  export const expiryLabel = (date: string) => formatExpDate(dateSeconds(date));
52
73
 
53
- export function formatStrike(value: number): string {
54
- return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(3)));
74
+ /** `08:00 UTC`: the time an expiry settles, when the venue states one apart from its day (Deribit); null otherwise. */
75
+ export function settlementTime(expiresAt: string | null | undefined): string | null {
76
+ const at = expiresAt ? Date.parse(expiresAt) : Number.NaN;
77
+ if (!Number.isFinite(at) || at % 86_400_000 === 0) return null;
78
+ return `${new Date(at).toISOString().slice(11, 16)} UTC`;
79
+ }
80
+
81
+ /** `Oct 30 '26 08:00 UTC` for an expiry with a settlement time, `Oct 30 '26` for one without. */
82
+ export function expiryWithTimeLabel(row: { date: string; expiresAt?: string }): string {
83
+ const time = settlementTime(row.expiresAt);
84
+ return time ? `${expiryLabel(row.date)} ${time}` : expiryLabel(row.date);
85
+ }
86
+
87
+ /** Whether open interest counts contracts on a coin (1 BTC each), whose counts run to tenths. */
88
+ export const isCoinContract = (contract: { unit: string } | null | undefined) => !!contract && contract.unit !== "shares";
89
+
90
+ /** A count of contracts: whole for a US listing's, to tenths for a coin's (Deribit's 0.1 BTC step). */
91
+ export function formatContracts(value: number | null | undefined, coin: boolean): string {
92
+ if (!coin) return formatCount(value);
93
+ return value == null || !Number.isFinite(value) ? "--" : value.toLocaleString("en-US", { maximumFractionDigits: 1 });
55
94
  }
95
+
56
96
  export function formatCount(value: number | null | undefined): string {
57
97
  return value == null || !Number.isFinite(value) ? "--" : Math.round(value).toLocaleString("en-US");
58
98
  }
@@ -64,30 +104,95 @@ export function formatCountChange(value: number | null | undefined): string {
64
104
  export function formatRatio(value: number | null | undefined): string {
65
105
  return value == null || !Number.isFinite(value) ? "--" : value.toFixed(2);
66
106
  }
107
+ /** A price level (spot, the gamma flip) written as OMON and OVDV write spot. */
67
108
  export function formatLevel(value: number | null | undefined): string {
68
- return value == null || !Number.isFinite(value) ? "--" : value.toFixed(2);
109
+ return value == null || !Number.isFinite(value) ? "--" : formatModelSpotPrice(value);
110
+ }
111
+ /**
112
+ * The spot of a positioning answer as the options panes stamp theirs: the
113
+ * regular session's close when the server says so (a cash index outside its
114
+ * session, which has no extended hours), otherwise the session its time
115
+ * falls in.
116
+ */
117
+ function positioningModelSpot(spot: number, at: number, basis?: "close"): OptionModelSpot {
118
+ return basis === "close"
119
+ ? { price: spot, observedAt: at, valuationTime: at, basis: "close", session: null }
120
+ : observedModelSpot(spot, at);
69
121
  }
122
+
70
123
  /**
71
124
  * The spot Gloom Cloud read the distances and dealer gamma at, stamped as
72
125
  * every options pane stamps its spot (`modelSpotStamp`), as a stat cell
73
- * carries it: `pre-market Wed 21 Oct 09:35 UTC`, its shorter forms, then
74
- * none, so the band keeps the columns it has in regular hours. Nothing for
75
- * the regular session's price.
126
+ * carries it: `pre-market Wed 21 Oct 09:35 UTC`, `close Tue 20 Oct` for an
127
+ * index outside its session, their shorter forms, then none, so the band
128
+ * keeps the columns it has in regular hours. Nothing for the regular
129
+ * session's price.
76
130
  */
77
- export function positioningSpotDetail(spot: number | null | undefined, spotAsOf: string | null | undefined):
131
+ export function positioningSpotDetail(spot: number | null | undefined, spotAsOf: string | null | undefined, venue?: string, basis?: "close"):
78
132
  { detail?: string; detailVariants?: string[] } {
79
133
  const at = spotAsOf ? Date.parse(spotAsOf) : Number.NaN;
80
134
  if (spot == null || !Number.isFinite(at)) return {};
81
- const observed = observedModelSpot(spot, at);
135
+ // A coin trades around the clock: its spot is the venue's index at a time, with no session.
136
+ if (venue) {
137
+ const time = `${new Date(at).toISOString().slice(11, 16)} UTC`;
138
+ return { detail: `index ${time}`, detailVariants: [`index ${time}`, time, ""] };
139
+ }
140
+ const observed = positioningModelSpot(spot, at, basis);
82
141
  const stamp = modelSpotStamp(observed);
83
142
  return stamp ? { detail: stamp, detailVariants: [...modelSpotStampVariants(observed), ""] } : {};
84
143
  }
85
144
 
86
- /** The spot as a report says it: `770.88 pre-market Wed 21 Oct 09:35 UTC`, `770.10 last Wed 21 Oct 14:05 UTC`. */
87
- export function formatPositioningSpot(spot: number | null | undefined, spotAsOf: string | null | undefined): string {
145
+ /** The spot as a report says it: `770.88 pre-market Wed 21 Oct 09:35 UTC`, `770.10 last Wed 21 Oct 14:05 UTC`, `7,722.60 close Tue 27 Oct`. */
146
+ export function formatPositioningSpot(spot: number | null | undefined, spotAsOf: string | null | undefined, venue?: string, basis?: "close"): string {
88
147
  const at = spotAsOf ? Date.parse(spotAsOf) : Number.NaN;
89
148
  if (spot == null || !Number.isFinite(spot)) return "--";
90
- return Number.isFinite(at) ? `${formatLevel(spot)} ${modelSpotLabel(observedModelSpot(spot, at))}` : formatLevel(spot);
149
+ if (venue) return Number.isFinite(at) ? `${formatLevel(spot)} ${venue} index ${formatUtcTime(new Date(at).toISOString())}` : formatLevel(spot);
150
+ return Number.isFinite(at) ? `${formatLevel(spot)} ${modelSpotLabel(positioningModelSpot(spot, at, basis))}` : formatLevel(spot);
151
+ }
152
+
153
+ const instant = (value: string | null | undefined) => {
154
+ const at = value ? Date.parse(value) : Number.NaN;
155
+ return Number.isFinite(at) ? at : null;
156
+ };
157
+ /** `Wed 08:34 UTC`. */
158
+ const dayAndTime = (at: number) => formatSpotTime(at).replace(/^(\w{3}) \d{1,2} \w{3} /, "$1 ");
159
+ /** `08:34 UTC`. */
160
+ const timeOnly = (at: number) => `${new Date(at).toISOString().slice(11, 16)} UTC`;
161
+
162
+ /**
163
+ * When dealer gamma is evaluated and when the quotes behind its volatilities
164
+ * were taken, as a report line: `Wed 28 Oct 08:34 UTC, vols from Tue 27 Oct
165
+ * 20:14 UTC`. Before the open that is the pre-market spot's time with the last
166
+ * session's volatilities. Null without a gamma time (an older server, which
167
+ * dates its quotes alone).
168
+ */
169
+ export function formatGammaTimes(gammaAsOf: string | null | undefined, quotesAsOf: string | null | undefined): string | null {
170
+ const gamma = instant(gammaAsOf);
171
+ if (gamma == null) return null;
172
+ const quotes = instant(quotesAsOf);
173
+ return quotes == null ? formatSpotTime(gamma) : `${formatSpotTime(gamma)}, vols from ${formatSpotTime(quotes)}`;
174
+ }
175
+
176
+ /**
177
+ * The same as a GEX figure: `Gamma at Wed 08:34 UTC`, detail `vols from Tue
178
+ * 20:14 UTC` (the day left out when it is the gamma's), with shorter forms
179
+ * that keep the quote time. An older server's answer, with no gamma time,
180
+ * dates its quotes alone. Null with neither.
181
+ */
182
+ export function gammaTimesFigure(gammaAsOf: string | null | undefined, quotesAsOf: string | null | undefined):
183
+ { label: string; value: string; detail?: string; detailVariants?: string[] } | null {
184
+ const gamma = instant(gammaAsOf);
185
+ const quotes = instant(quotesAsOf);
186
+ if (gamma == null) return quotes == null ? null : { label: "Quotes as of", value: dayAndTime(quotes) };
187
+ if (quotes == null) return { label: "Gamma at", value: dayAndTime(gamma) };
188
+ const sameDay = new Date(gamma).toISOString().slice(0, 10) === new Date(quotes).toISOString().slice(0, 10);
189
+ const quoted = sameDay ? timeOnly(quotes) : dayAndTime(quotes);
190
+ return {
191
+ label: "Gamma at",
192
+ value: dayAndTime(gamma),
193
+ detail: `vols from ${quoted}`,
194
+ detailVariants: [`vols from ${quoted}`, `vols ${quoted}`, `vols ${quoted.replace(/ UTC$/, "")}`],
195
+ };
91
196
  }
92
197
 
93
198
  /** Where a level sits against spot: +0.6%. */
@@ -169,6 +274,9 @@ export function chartWindow<T extends { strike: number }>(
169
274
  /** One full-width numeric domain the chart reads as time; strikes are never labelled as dates. */
170
275
  const COORDINATE_SPAN = 1_000_000_000_000;
171
276
 
277
+ /** Where a chart date made by `toDate` sits across the plot, 0 to 1. */
278
+ export const axisRatioOfDate = (date: Date) => date.getTime() / COORDINATE_SPAN;
279
+
172
280
  export interface NumericAxis {
173
281
  /** Where x sits across the plot, 0 at the left edge and 1 at the right. */
174
282
  ratio: (x: number) => number;
@@ -200,7 +308,7 @@ export function strikeAxis(strikes: readonly number[]): NumericAxis {
200
308
  const step = niceStep(span, Math.floor(plotWidth / 8));
201
309
  const ticks: Array<{ label: string; ratio: number }> = [];
202
310
  for (let value = Math.ceil(min / step) * step; value <= max + 1e-9; value += step) {
203
- ticks.push({ label: formatStrike(Number(value.toFixed(6))), ratio: ratio(value) });
311
+ ticks.push({ label: formatStrikeLabel(Number(value.toFixed(6))), ratio: ratio(value) });
204
312
  }
205
313
  return ticks;
206
314
  },