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
@@ -23,6 +23,7 @@ import {
23
23
  } from "../../../components";
24
24
  import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
25
25
  import {
26
+ useAssetData,
26
27
  useDebouncedPluginPaneState,
27
28
  usePaneSettingValue,
28
29
  usePaneTitle,
@@ -34,6 +35,7 @@ import type { PaneProps } from "../../../types/plugin";
34
35
  import { Box, type ScrollBoxRenderable } from "../../../ui";
35
36
  import { isPlainArrowUp, stopSearchFocusNavigation } from "../../../utils/search-focus-navigation";
36
37
  import { toneColor, withoutQuietColumns } from "../shared/research-cells";
38
+ import { looksLikeTicker, useTickerCompanySearch } from "../shared/ticker-company";
37
39
  import { OpenFdaClient, parseOpenFdaDate } from "./client";
38
40
  import {
39
41
  activeFilters,
@@ -41,6 +43,7 @@ import {
41
43
  FILTER_DEFAULT,
42
44
  recordColumns,
43
45
  recordTone,
46
+ termsCellText,
44
47
  type ColumnId,
45
48
  type FilterKey,
46
49
  type FilterState,
@@ -75,6 +78,16 @@ const formatDate = (date: Date | null): string => (date ? date.toISOString().sli
75
78
 
76
79
  const capitalize = (text: string): string => text.charAt(0).toUpperCase() + text.slice(1);
77
80
 
81
+ /** A search written as a ticker is, in capitals (`AZN`, `BRK.B`); `cat` or `azn` is a word to search for. */
82
+ const writtenAsTicker = (term: string): boolean => looksLikeTicker(term) && term === term.toUpperCase();
83
+
84
+ /** What a search that matched nothing points to, by what each dataset is searched on. */
85
+ const EMPTY_SEARCH_HINTS: Record<OpenFdaDataset, string> = {
86
+ drug: "Try the drug's brand or generic name…",
87
+ device: "Try the device or manufacturer name…",
88
+ recall: "Try the firm or product name…",
89
+ };
90
+
78
91
  /** A generic's record lists every labeler; the cell counts them instead of naming one. */
79
92
  function labelerText(record: DrugReport): string | null {
80
93
  if (record.manufacturer) return record.manufacturer;
@@ -95,13 +108,19 @@ function cellFor(record: OpenFdaRecord, column: ColumnId, colors: ThemeColors):
95
108
  return text ? { text, color: record.manufacturer ? colors.text : colors.textMuted } : missing;
96
109
  }
97
110
  if (column === "role") return toned(record.role ? capitalize(record.role) : null);
98
- if (column === "reactions") return record.reactions.length > 0 ? { text: record.reactions.join(", "), color: colors.text } : missing;
111
+ // The row names the first few; its export, like the record, keeps every one.
112
+ if (column === "reactions") {
113
+ return record.reactions.length > 0 ? { text: termsCellText(record.reactions), value: record.reactions.join(", "), color: colors.text } : missing;
114
+ }
99
115
  if (column === "outcome") return toned(record.outcome);
100
116
  break;
101
117
  case "device":
102
118
  if (column === "product") return { text: record.product, color: colors.textBright };
103
119
  if (column === "manufacturer") return record.manufacturer ? { text: record.manufacturer, color: colors.text } : missing;
104
- if (column === "problems") return record.productProblems.length > 0 ? { text: record.productProblems.join(", "), color: colors.text } : missing;
120
+ if (column === "problems") {
121
+ return record.productProblems.length > 0
122
+ ? { text: termsCellText(record.productProblems), value: record.productProblems.join(", "), color: colors.text } : missing;
123
+ }
105
124
  if (column === "event") return toned(record.eventType);
106
125
  break;
107
126
  case "recall":
@@ -201,6 +220,7 @@ const isDataset = (value: unknown): value is OpenFdaDataset => DATASETS.some((en
201
220
 
202
221
  export function OpenFdaPane({ width, height, focused }: PaneProps) {
203
222
  const client = useMemo(() => new OpenFdaClient(), []);
223
+ const dataProvider = useAssetData();
204
224
  const [storedQuery] = usePaneSettingValue("query", "");
205
225
  const initialQuery = String(storedQuery ?? "").trim();
206
226
  const [query, setQuery] = usePluginPaneState("query", initialQuery);
@@ -278,9 +298,25 @@ export function OpenFdaPane({ width, height, focused }: PaneProps) {
278
298
  setOpenItemId(null);
279
299
  }, [setFilterState, setOpenItemId, setSelectedId]);
280
300
 
281
- const loading = records.loading && rows.length === 0;
282
- const error = records.error?.message ?? null;
283
- usePaneRefreshKey(records.reload, { focused, enabled: !searchFocused && !openItemId });
301
+ // `FDA AZN`: FDA records name the firm and its products, never a symbol, so a
302
+ // ticker that finds nothing is searched as its company's name (AstraZeneca),
303
+ // as TRIAL reads one, and the search box then shows it. Only a term written in
304
+ // capitals, as a ticker is (the search box or `fn FDA AZN`): a word such as
305
+ // "cat" stays the search it is. Each term is looked up once.
306
+ const companySearch = useTickerCompanySearch(dataProvider, term, {
307
+ eligible: records.status === "loaded" && rows.length === 0 && !records.error && writtenAsTicker(term),
308
+ key: term,
309
+ onCompany: updateQuery,
310
+ });
311
+ const retryCompanySearch = companySearch.retry;
312
+
313
+ const loading = (records.loading && rows.length === 0) || companySearch.resolving;
314
+ const error = records.error?.message ?? companySearch.error;
315
+ const reload = useCallback(() => {
316
+ retryCompanySearch();
317
+ records.reload();
318
+ }, [records, retryCompanySearch]);
319
+ usePaneRefreshKey(reload, { focused, enabled: !searchFocused && !openItemId });
284
320
 
285
321
  const linkRecord = openRecord ?? selected;
286
322
  const info = useMemo<PaneFooterSegment[]>(() => [
@@ -420,7 +456,7 @@ export function OpenFdaPane({ width, height, focused }: PaneProps) {
420
456
  resetScrollKey={`${dataset}:${term}:${filtersKey}`}
421
457
  selectedTextOverridesCellColor
422
458
  emptyStateTitle={term ? `No ${datasetLabel.toLowerCase()} match ${term}.` : `No ${datasetLabel.toLowerCase()}.`}
423
- emptyStateHint="Press / to search…"
459
+ emptyStateHint={term ? EMPTY_SEARCH_HINTS[dataset] : "Press / to search…"}
424
460
  />
425
461
  );
426
462
  }
@@ -51,8 +51,26 @@ export interface ChainVolatilities {
51
51
  /** Valuation instant the volatilities were solved at, reused for the Greeks. */
52
52
  valuationTime: number;
53
53
  byStrike: ReadonlyMap<number, number>;
54
+ /**
55
+ * Strikes in `byStrike` whose volatility was not solved: with no two-sided
56
+ * out-of-the-money quote to solve from, it is read off the neighbouring solved
57
+ * strikes (flat beyond the last of them). Shown marked, never as a solved figure.
58
+ */
59
+ filled: ReadonlySet<number>;
54
60
  }
55
61
 
62
+ /**
63
+ * How a chain's IV is solved, said under the chain in a report and in the pane's
64
+ * footer while a strike's IV is filled: marked "~", it is read off the
65
+ * neighbouring solved strikes, not solved from a quote.
66
+ */
67
+ export const IV_FILLED_NOTE = "~ IV filled from neighbouring strikes";
68
+ export const IV_FILLED_SHORT = "~ IV filled";
69
+ export const IV_FILLED_DETAIL = "Each strike's IV is solved from the midpoint of its out-of-the-money option. A strike with no two-sided quote there "
70
+ + "has its IV read off the nearest solved strikes, flat beyond the last one, and its cell leads with ~.";
71
+ /** The report's line on how IV was solved, with what "~" marks when a strike is filled. */
72
+ export const ivSolvedNote = (anyFilled: boolean) => `IV solved from quote mids${anyFilled ? ", ~ filled from neighbouring strikes" : ""}`;
73
+
56
74
  function tightestQuotes(contracts: readonly OptionContract[], expiration: number): Map<number, OptionContract> {
57
75
  const quotes = new Map<number, OptionContract>();
58
76
  for (const contract of contracts) {
@@ -78,8 +96,21 @@ export function solveChainVolatilities(
78
96
  ): ChainVolatilities {
79
97
  const valuationTime = optionQuoteValuationTime(chain, now);
80
98
  const byStrike = new Map<number, number>();
81
- if (!positive(spot)) return { valuationTime, byStrike };
82
- const rate = DEFAULT_OPTION_CALC_DRAFT.rate;
99
+ const filled = new Set<number>();
100
+ // A venue that marks every contract (Deribit) states its volatility: the out-of-the-money side's at each strike.
101
+ if ([...chain.calls, ...chain.puts].some((contract) => contract.mark)) {
102
+ for (const [side, contracts] of [["call", chain.calls], ["put", chain.puts]] as const) {
103
+ for (const contract of contracts) {
104
+ const mark = contract.mark;
105
+ if (!mark || !positive(mark.iv)) continue;
106
+ const outOfTheMoney = side === "call" ? contract.strike >= mark.forward : contract.strike < mark.forward;
107
+ if (outOfTheMoney || !byStrike.has(contract.strike)) byStrike.set(contract.strike, mark.iv);
108
+ }
109
+ }
110
+ return { valuationTime, byStrike, filled };
111
+ }
112
+ if (!positive(spot)) return { valuationTime, byStrike, filled };
113
+ const rate = optionChainRate(chain);
83
114
  const carry = Number.isFinite(dividendYield) ? dividendYield! : 0;
84
115
  const expirations = new Set([...chain.calls, ...chain.puts].map((contract) => contract.expiration));
85
116
  for (const expiration of expirations) {
@@ -103,7 +134,8 @@ export function solveChainVolatilities(
103
134
  ? solve("call", calls.get(strike)) : solve("put", puts.get(strike)));
104
135
  // Without a two-sided out-of-the-money quote a strike's time value sits inside
105
136
  // the tick, and the in-the-money quote is intrinsic plus spread noise. Read its
106
- // volatility off the neighbouring solved strikes so delta stays monotonic.
137
+ // volatility off the neighbouring solved strikes so delta stays monotonic, and
138
+ // say it was filled: it is no market's volatility.
107
139
  strikes.forEach((strike, index) => {
108
140
  let volatility = solved[index];
109
141
  if (volatility == null) {
@@ -116,10 +148,14 @@ export function solveChainVolatilities(
116
148
  ? low + (high - low) * (strike - strikes[below]!) / (strikes[above]! - strikes[below]!)
117
149
  : low ?? high;
118
150
  }
119
- if (volatility != null) byStrike.set(strike, volatility);
151
+ if (volatility != null) {
152
+ byStrike.set(strike, volatility);
153
+ if (solved[index] == null) filled.add(strike);
154
+ else filled.delete(strike);
155
+ }
120
156
  });
121
157
  }
122
- return { valuationTime, byStrike };
158
+ return { valuationTime, byStrike, filled };
123
159
  }
124
160
 
125
161
  function atmImpliedVolatility(volatilities: ChainVolatilities, spot: number | undefined): number | null {
@@ -185,7 +221,15 @@ export function calculateOptionsSummary(
185
221
  };
186
222
  }
187
223
 
188
- /** Greeks at the displayed spot, from the strike's solved volatility (0 when the market prices no time value). */
224
+ /** The rate a chain's premiums are valued at: the venue's own when it states one (Deribit's zero), else the model rate. */
225
+ function optionChainRate(chain: Pick<OptionsChain, "rate">): number {
226
+ return Number.isFinite(chain.rate) ? chain.rate! : DEFAULT_OPTION_CALC_DRAFT.rate;
227
+ }
228
+
229
+ /**
230
+ * Greeks at the displayed spot, from the strike's solved volatility (0 when the market prices no time value).
231
+ * A contract its venue marks (Deribit) has the venue's greeks, at the expiry's forward.
232
+ */
189
233
  export function calculateOptionGreeks(
190
234
  contract: OptionContract | undefined,
191
235
  side: OptionSide,
@@ -193,6 +237,10 @@ export function calculateOptionGreeks(
193
237
  dividendYield: number | undefined,
194
238
  volatilities: ChainVolatilities,
195
239
  ): OptionValuation | undefined {
240
+ if (contract?.mark) {
241
+ const { price, delta, gamma, theta, vega } = contract.mark;
242
+ return { price, delta, gamma, thetaPerDay: theta, vegaPerPoint: vega, rhoPerPoint: 0 };
243
+ }
196
244
  const volatility = contract ? volatilities.byStrike.get(contract.strike) : undefined;
197
245
  // A side nobody bids has no market to measure sensitivity against.
198
246
  if (!contract || optionMid(contract) == null || !positive(spot) || !positive(contract.strike) || volatility == null || !(volatility >= 0)) {
@@ -1,4 +1,5 @@
1
1
  import { useEffect, useMemo, useRef, useState } from "react";
2
+ import { createTtlCache, type TtlCache } from "../../../data/ttl-cache";
2
3
  import type { InstrumentRef } from "../../../market-data/request-types";
3
4
  import type { QueryEntry } from "../../../market-data/result-types";
4
5
  import { buildOptionsKey, resolveEntryData } from "../../../market-data/selectors";
@@ -15,6 +16,17 @@ const OPTIONS_LIVE_ANALYTICS_INTERVAL_MS = 1_000;
15
16
  const LIVE_ANALYTICS_MAX_LOAD = 0.05;
16
17
  /** The Treasury curve is daily; a refreshed chain reuses the one it already loaded. */
17
18
  const TREASURY_REUSE_MS = 30 * 60_000;
19
+ const TREASURY_CURVE = "treasury";
20
+
21
+ interface Selection {
22
+ key: string | null;
23
+ cache: OptionsEnrichmentCache;
24
+ curve: TtlCache<YieldPoint[]>;
25
+ }
26
+
27
+ const newSelection = (key: string | null): Selection => ({
28
+ key, cache: {}, curve: createTtlCache<YieldPoint[]>({ ttlMs: TREASURY_REUSE_MS }),
29
+ });
18
30
 
19
31
  interface EnrichmentResult {
20
32
  key: string;
@@ -59,9 +71,9 @@ export function useOptionsEnrichment(input: {
59
71
  const current = useRef(input);
60
72
  current.current = input;
61
73
  // Per selection: the adjacent model and the Treasury curve outlive a chain refresh.
62
- const store = useRef<{ key: string | null; cache: OptionsEnrichmentCache; curve: { value: YieldPoint[]; at: number } | null }>(
63
- { key: null, cache: {}, curve: null });
64
- if (store.current.key !== key) store.current = { key, cache: {}, curve: null };
74
+ const [first] = useState(() => newSelection(key));
75
+ const store = useRef(first);
76
+ if (store.current.key !== key) store.current = newSelection(key);
65
77
  const [result, setResult] = useState<EnrichmentResult | null>(null);
66
78
  const resultRef = useRef(result);
67
79
  resultRef.current = result;
@@ -71,7 +83,7 @@ export function useOptionsEnrichment(input: {
71
83
  const request = current.current;
72
84
  const identity = { key, entryKey, catalogueKey };
73
85
  const selection = store.current;
74
- const curve = selection.curve && Date.now() - selection.curve.at < TREASURY_REUSE_MS ? selection.curve.value : undefined;
86
+ const curve = selection.curve.peek(TREASURY_CURVE);
75
87
  let projection: OptionsEnrichmentProjection | null = null;
76
88
  // A refresh of the same expiry swaps in its analytics complete, never
77
89
  // through a partial projection that would blank the strip for a moment.
@@ -93,7 +105,7 @@ export function useOptionsEnrichment(input: {
93
105
  }).then((snapshot) => {
94
106
  if (controller.signal.aborted) return;
95
107
  if (projection && !projection.curveLoading && !projection.treasuryError && projection.curve?.length && !curve) {
96
- selection.curve = { value: [...projection.curve], at: Date.now() };
108
+ selection.curve.set(TREASURY_CURVE, [...projection.curve]);
97
109
  }
98
110
  setResult({ ...identity, loading: false, carried: false, snapshot, projection, error: null });
99
111
  }).catch((error: unknown) => {
@@ -154,7 +154,10 @@ export function modelSpotExtendedPrint(
154
154
  return `${EXTENDED_SESSION_WORDS[print.session]}${print.mark ? " mid" : ""} ${format(print.price)}`;
155
155
  }
156
156
 
157
- /** A price to the cent, or to the tick it was quoted at below a dollar. */
157
+ /**
158
+ * Spot as every options pane writes it (OMON, OPX, OVDV): grouped, to the
159
+ * cent, or to the tick it was quoted at below a dollar.
160
+ */
158
161
  export function formatModelSpotPrice(price: number): string {
159
- return price.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: price < 1 ? 4 : 2, useGrouping: false });
162
+ return price.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: price < 1 ? 4 : 2 });
160
163
  }
@@ -1,6 +1,7 @@
1
1
  import type { OptionsChain } from "../../../types/financials";
2
2
  import { calculateOptionGreeks, solveChainVolatilities } from "./analytics";
3
- import { findNearestStrikeIndex, formatStrikeLabel } from "./table";
3
+ import { formatStrikeLabel } from "../../../utils/options";
4
+ import { findNearestStrikeIndex } from "./table";
4
5
 
5
6
  /**
6
7
  * Which strikes of an expiry the chain lists. Every strike by default, as
@@ -4,6 +4,7 @@ import type { OptionContract, OptionsChain } from "../../../types/financials";
4
4
  import { blendHex, colors } from "../../../theme/colors";
5
5
  import { blendForContrast, blendForSeparation, contrastRatio } from "../../../theme/color-utils";
6
6
  import { formatCompact } from "../../../utils/format";
7
+ import { formatStrikeLabel } from "../../../utils/options";
7
8
  import { formatOptionPrice, optionQuoteSide, optionSpread } from "./market-reference";
8
9
  import { formatCarryPercent, formatCostOfSpot } from "./carry";
9
10
  import type {
@@ -162,17 +163,13 @@ export function findNearestStrikeIndex(strikes: number[], targetStrike: number):
162
163
  return bestIndex;
163
164
  }
164
165
 
165
- export function formatStrikeLabel(strike: number): string {
166
- // 15 significant digits keep every listed decimal but drop binary noise from
167
- // computed strikes such as spot * 0.9.
168
- return Number.isFinite(strike)
169
- ? strike.toLocaleString("en-US", { maximumSignificantDigits: 15 }) : "—";
170
- }
171
-
172
- export function formatIv(value: number | undefined): string {
166
+ export function formatIv(value: number | undefined, filled = false): string {
173
167
  // Providers send 0 for contracts with no implied volatility; "0.0%" would read
174
168
  // as a real quote of zero vol.
175
169
  if (value == null || !Number.isFinite(value) || value <= 0) return "\u2014";
170
+ // A filled figure leads with "~": it was read off the neighbouring strikes, not solved from a quote.
171
+ // Without the decimal it still fits the column at 100% and over.
172
+ if (filled) return value >= 0.9995 ? `~${Math.round(value * 100)}%` : `~${(value * 100).toFixed(1)}%`;
176
173
  return `${(value * 100).toFixed(1)}%`;
177
174
  }
178
175
 
@@ -311,7 +308,7 @@ function formatOptionContractCell(
311
308
  case "openInterest":
312
309
  return formatCompact(contract.openInterest, { fixedDecimals: true });
313
310
  case "iv":
314
- return formatIv(row.impliedVolatility);
311
+ return formatIv(row.impliedVolatility, row.impliedVolatilityFilled);
315
312
  case "delta":
316
313
  return formatGreek(greeks?.delta);
317
314
  case "gamma":
@@ -32,6 +32,8 @@ export interface OptionTableRow {
32
32
  put?: OptionContract;
33
33
  /** Solved from quote midpoints; the call and put at a strike share it. */
34
34
  impliedVolatility?: number;
35
+ /** `impliedVolatility` was filled from neighbouring strikes, not solved from a quote (see `ChainVolatilities.filled`). */
36
+ impliedVolatilityFilled?: boolean;
35
37
  callGreeks?: OptionValuation;
36
38
  putGreeks?: OptionValuation;
37
39
  /** Time value as a share of spot per year (see `carry.ts`); null when it cannot be read. */
@@ -6,12 +6,15 @@ import { isPlainKey } from "../../../utils/keyboard";
6
6
  import { formatCompact, formatPercentRaw } from "../../../utils/format";
7
7
  import { formatMarketPrice, formatSignedMarketPrice, liveQuoteFormatOptions } from "../../../market-data/market/format";
8
8
  import { getRegularSessionDisplay } from "../../../market-data/market/status";
9
- import { chainOptionContract, formatExpDate, optionContractName, resolveOptionsTarget } from "../../../utils/options";
9
+ import { chainOptionContract, formatExpDate, formatStrikeLabel, optionContractName, resolveOptionsTarget } from "../../../utils/options";
10
10
  import {
11
- expiryIsoDate, findListedExpiry, formatDaysToExpiry, daysToExpiry, isLiveOptionExpiry, missingExpiryMessage, missingExpiryText, readOptionExpiration,
11
+ expiryIsoDate, findListedExpiry, formatDaysToExpiry, daysToExpiry, isLiveOptionExpiry, missingExpiryMessage, missingExpiryText, optionExpiryVenue,
12
+ readOptionExpiration,
12
13
  } from "../../../utils/option-expiry";
13
14
  import { canonicalTickerKey } from "../../../utils/exchanges";
14
- import { isOptionsUnavailableError, listedOptionsAlternative, optionsUnavailableTitle } from "../../../market-data/options-alternatives";
15
+ import {
16
+ COIN_OPTIONS_HINT, isCoinWithoutOptions, isOptionsUnavailableError, listedOptionsAlternative, optionsUnavailableTitle,
17
+ } from "../../../market-data/options-alternatives";
15
18
  import { useChartQueries, useOptionsQuery, useResolvedEntryValue, useTickerFinancials } from "../../../market-data/hooks";
16
19
  import {
17
20
  Button,
@@ -41,14 +44,13 @@ import type { OptionContract } from "../../../types/financials";
41
44
  import { OPTIONS_CALCULATOR_TEMPLATE_ID } from "../options-calculator/model";
42
45
  import { buildChainCalcParams, resolveCalcSide } from "./calc-seed";
43
46
  import { useOptionsCatalogue } from "./expiry-catalogue";
44
- import { calculateOptionGreeks, calculateOptionsSummary, solveChainVolatilities, type OptionsSummary } from "./analytics";
47
+ import { calculateOptionGreeks, calculateOptionsSummary, IV_FILLED_DETAIL, IV_FILLED_NOTE, IV_FILLED_SHORT, solveChainVolatilities, type OptionsSummary } from "./analytics";
45
48
  import {
46
49
  DEFAULT_OPTION_FIELD_IDS,
47
50
  buildStrikeList,
48
51
  createOptionColumns,
49
52
  findNearestStrikeIndex,
50
53
  formatIv,
51
- formatStrikeLabel,
52
54
  optionColumnColor,
53
55
  renderOptionCell,
54
56
  resolveDefaultStrikeTarget,
@@ -272,7 +274,9 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
272
274
  // A listing can still carry a date whose last session has closed. The chain
273
275
  // never opens there, nor on a saved date that has since passed: it takes the nearest live one.
274
276
  const now = Date.now();
275
- const liveExpiration = (expiration: number) => isLiveOptionExpiry(expiration, now, effectiveExchange);
277
+ // Expiries close on the listing's clock: a coin's options (Deribit) settle at 08:00 UTC on any day.
278
+ const expiryVenue = optionExpiryVenue(effectiveTicker, effectiveExchange);
279
+ const liveExpiration = (expiration: number) => isLiveOptionExpiry(expiration, now, expiryVenue);
276
280
  const listedExpirations = initialChain?.expirationDates ?? [];
277
281
  const openingExpirations = listedExpirations.some(liveExpiration) ? listedExpirations.filter(liveExpiration) : listedExpirations;
278
282
  const initialExpiration = openingExpirations.length === 0 ? undefined : openingExpirations.reduce((best, expiration) => (
@@ -322,9 +326,9 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
322
326
  const listed = selectedExpirationMissing
323
327
  ? [...availableExpirations, selectedExpiration!].sort((left, right) => left - right) : availableExpirations;
324
328
  // A date whose last session has closed has no contracts left to show; the strip leaves it out, unless every date has.
325
- const current = (expiration: number) => isLiveOptionExpiry(expiration, Date.now(), effectiveExchange);
329
+ const current = (expiration: number) => isLiveOptionExpiry(expiration, Date.now(), expiryVenue);
326
330
  return listed.some(current) ? listed.filter((expiration) => expiration === selectedExpiration || current(expiration)) : listed;
327
- }, [availableExpirations, effectiveExchange, selectedExpiration, selectedExpirationMissing]);
331
+ }, [availableExpirations, expiryVenue, selectedExpiration, selectedExpirationMissing]);
328
332
  // Keep the date strip stable while a mouse press focuses this pane. A new
329
333
  // tab list asks the web host to reveal the active tab and can move the date
330
334
  // being clicked before mouse-up, cancelling selection of an offscreen expiry.
@@ -444,7 +448,7 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
444
448
  const chainAsOfMs = asOfChain?.asOf ? Date.parse(asOfChain.asOf) : Number.NaN;
445
449
  const expiryAsOfMs = Number.isFinite(chainAsOfMs) ? chainAsOfMs : Date.now();
446
450
  const expiryDate = selectedExpiration == null ? "" : expiryIsoDate(selectedExpiration);
447
- const expiryDays = selectedExpiration == null ? "" : formatDaysToExpiry(selectedExpiration, expiryAsOfMs, effectiveExchange);
451
+ const expiryDays = selectedExpiration == null ? "" : formatDaysToExpiry(selectedExpiration, expiryAsOfMs, expiryVenue);
448
452
  useRemoteUiNode(expiryDate && chain && !expirationUnavailable ? {
449
453
  role: "report-notice",
450
454
  label: "Expiry",
@@ -574,6 +578,7 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
574
578
  call,
575
579
  put,
576
580
  impliedVolatility: volatilities?.byStrike.get(strike),
581
+ impliedVolatilityFilled: volatilities?.filled.has(strike) ?? false,
577
582
  callGreeks: volatilities ? calculateOptionGreeks(call, "call", greeksSpot, dividendYield, volatilities) : undefined,
578
583
  putGreeks: volatilities ? calculateOptionGreeks(put, "put", greeksSpot, dividendYield, volatilities) : undefined,
579
584
  callExtrinsicPerYear: call && volatilities ? optionCarry(call, "call", greeksSpot, volatilities.valuationTime)?.extrinsicPerYear ?? null : null,
@@ -618,9 +623,21 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
618
623
  + `${new Date(footerSpot.observedAt).toISOString().slice(11, 16)} UTC` : null,
619
624
  strikeChain && !listedOpenInterest.loading ? openInterestAsOf?.date ? `OI ${openInterestAsOf.date.slice(5)}` : "OI undated" : null]
620
625
  .filter(Boolean).join(" · ");
621
- usePaneFooter("options-basis", () => ({ info: basisText ? [{ id: "greeks-basis",
622
- parts: [{ text: basisText, tone: "muted" as const }],
623
- variants: [[{ text: shortBasisText, tone: "muted" as const }], []] }] : [] }), [basisText, shortBasisText]);
626
+ // How IV was solved is said while the chain shows a figure that was not: a strike with no two-sided
627
+ // out-of-the-money quote has its IV read off the neighbouring strikes, and its cell leads with "~".
628
+ const ivFilledShown = optionFieldIds.includes("iv") && rows.some((row) => row.impliedVolatilityFilled && row.impliedVolatility != null);
629
+ // A report of the pane (`gloom fn OMON`) says it too.
630
+ useRemoteUiNode(ivFilledShown ? {
631
+ role: "report-notice",
632
+ label: "IV filled",
633
+ getMetadata: () => ({ text: IV_FILLED_NOTE, key: "ivFilled", value: true }),
634
+ } : null);
635
+ usePaneFooter("options-basis", () => ({ info: [
636
+ ...(basisText ? [{ id: "greeks-basis", parts: [{ text: basisText, tone: "muted" as const }],
637
+ variants: [[{ text: shortBasisText, tone: "muted" as const }], []] }] : []),
638
+ ...(ivFilledShown ? [{ id: "iv-filled", parts: [{ text: IV_FILLED_NOTE, tone: "muted" as const }],
639
+ title: IV_FILLED_DETAIL, variants: [[{ text: IV_FILLED_SHORT, tone: "muted" as const }]] }] : []),
640
+ ] }), [basisText, shortBasisText, ivFilledShown]);
624
641
  // Figures that summarise the whole expiry move at most once a second, so a
625
642
  // busy stream reads as a steady strip rather than flicker.
626
643
  // A new expiry, a refreshed snapshot or the underlying price arriving or
@@ -904,6 +921,19 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
904
921
  return <EmptyState title="Select a ticker." />;
905
922
  }
906
923
  if (loading && !chain) return <Spinner label="Loading options chain..." />;
924
+ if (error && !chain && isOptionsUnavailableError(error) && isCoinWithoutOptions(effectiveTicker)) {
925
+ // A coin other than BTC and ETH: the coins that have options, and a bitcoin-linked fund's.
926
+ return (
927
+ <EmptyState
928
+ title={optionsUnavailableTitle(effectiveTicker)}
929
+ hint={COIN_OPTIONS_HINT}
930
+ actions={<>
931
+ <Button label="BTC-USD options" onPress={() => createPaneFromTemplate("options-pane", { symbol: "BTC-USD" })} />
932
+ <Button label="IBIT options" onPress={() => createPaneFromTemplate("options-pane", { symbol: "IBIT" })} />
933
+ </>}
934
+ />
935
+ );
936
+ }
907
937
  if (error && !chain && isOptionsUnavailableError(error)) {
908
938
  // A future or commodity with no chain of its own: the listed fund whose options stand in, and OSA on it.
909
939
  const alternative = listedOptionsAlternative(effectiveTicker);
@@ -12,6 +12,8 @@ export interface ExpiryOpenInterest {
12
12
  /** Change since `previousOiDate`; null without a stored session to compare with. */
13
13
  callChange: number | null;
14
14
  putChange: number | null;
15
+ /** The instant it settles, when the venue states one: 08:00 UTC for Deribit's BTC and ETH options. */
16
+ expiresAt?: string;
15
17
  }
16
18
 
17
19
  export interface StrikeOpenInterest {
@@ -24,6 +26,12 @@ export interface StrikeOpenInterest {
24
26
  payout: number | null;
25
27
  }
26
28
 
29
+ /** What one contract is: 1 BTC for Deribit's options, 100 shares for a US listing's (absent from US payloads). */
30
+ interface PositioningContract {
31
+ size: number;
32
+ unit: string;
33
+ }
34
+
27
35
  export interface OpenInterestPayload {
28
36
  version: 1;
29
37
  symbol: string;
@@ -34,11 +42,19 @@ export interface OpenInterestPayload {
34
42
  tracked: boolean;
35
43
  spot: number | null;
36
44
  spotAsOf: string | null;
45
+ /** `close` when spot is a regular session's close at `spotAsOf`: a cash index outside its session. Absent from older servers. */
46
+ spotBasis?: "close";
37
47
  delayed: boolean;
38
48
  expiries: ExpiryOpenInterest[];
39
49
  expiry: string | null;
40
50
  strikes: StrikeOpenInterest[];
41
51
  warnings: string[];
52
+ /** When the counts were read, for a venue that publishes them live (Deribit); `oiDate` is then that UTC day. */
53
+ oiAsOf?: string | null;
54
+ /** The venue listing the options, when it is not the US exchanges: Deribit. */
55
+ venue?: string;
56
+ /** Open interest counts contracts of this size; absent means 100 shares. */
57
+ contract?: PositioningContract;
42
58
  }
43
59
 
44
60
  export interface GammaStrike {
@@ -56,6 +72,9 @@ interface GammaExpiry {
56
72
  /** Short, as a positive number. */
57
73
  puts: number;
58
74
  net: number;
75
+ /** The expiry's strikes with the most call and put gamma; absent from older servers. */
76
+ callWall?: number | null;
77
+ putWall?: number | null;
59
78
  }
60
79
 
61
80
  export interface GammaPayload {
@@ -65,6 +84,8 @@ export interface GammaPayload {
65
84
  oiDate: string | null;
66
85
  spot: number | null;
67
86
  spotAsOf: string | null;
87
+ /** `close` when spot is a regular session's close at `spotAsOf`: a cash index outside its session. Absent from older servers. */
88
+ spotBasis?: "close";
68
89
  delayed: boolean;
69
90
  /** The one expiry measured, or null for all of them. */
70
91
  expiry: string | null;
@@ -82,8 +103,17 @@ export interface GammaPayload {
82
103
  strikes: GammaStrike[];
83
104
  /** Each priced expiry's totals, from the same legs as `total`; absent from older servers. */
84
105
  byExpiry?: GammaExpiry[];
106
+ /** When the quotes behind the volatilities were taken: the expiry's own, or the newest priced one's for all. */
85
107
  quotesAsOf: string | null;
108
+ /**
109
+ * The instant gamma is evaluated at, which time to expiry runs from: now
110
+ * while the quotes are current, the spot's time with a closed session's
111
+ * quotes (before the open). Absent from older servers.
112
+ */
113
+ gammaAsOf?: string | null;
86
114
  warnings: string[];
115
+ /** The venue listing the options, when it is not the US exchanges: Deribit. */
116
+ venue?: string;
87
117
  }
88
118
 
89
119
  export type OptionsPositioningApi = Pick<typeof apiClient, "optionsPositioning">;