gloomberb 0.16.1 → 0.16.3

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 (643) hide show
  1. package/README.md +2 -1
  2. package/package.json +2 -1
  3. package/src/api-client/beneficial-owners.ts +92 -0
  4. package/src/api-client/data.ts +26 -8
  5. package/src/api-client/errors.ts +12 -0
  6. package/src/api-client/geo.ts +363 -0
  7. package/src/api-client/index.ts +2 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/paths.ts +30 -1
  10. package/src/api-client/perps.ts +37 -0
  11. package/src/api-client/request.ts +5 -2
  12. package/src/api-client/types.ts +2 -0
  13. package/src/brokers/account-cache.ts +69 -0
  14. package/src/cli/command-options.ts +74 -0
  15. package/src/cli/commands/command-utils.ts +37 -0
  16. package/src/cli/commands/crypto-hints.ts +75 -0
  17. package/src/cli/commands/market.ts +560 -136
  18. package/src/cli/commands/overview.ts +136 -48
  19. package/src/cli/commands/ticker.ts +220 -67
  20. package/src/cli/desktop-pane-shot.ts +37 -4
  21. package/src/cli/freshness.ts +61 -0
  22. package/src/cli/help.ts +27 -6
  23. package/src/cli/helpers.ts +4 -8
  24. package/src/cli/history-rows.ts +187 -15
  25. package/src/cli/index.ts +23 -8
  26. package/src/cli/listing-arg.ts +321 -0
  27. package/src/cli/options.ts +5 -1
  28. package/src/cli/pane-functions/access-gate.ts +42 -0
  29. package/src/cli/pane-functions/capabilities.ts +5 -0
  30. package/src/cli/pane-functions/catalog.ts +28 -1
  31. package/src/cli/pane-functions/data.ts +3 -1
  32. package/src/cli/pane-functions/dom.ts +87 -16
  33. package/src/cli/pane-functions/freshness.ts +400 -0
  34. package/src/cli/pane-functions/function-help.ts +31 -22
  35. package/src/cli/pane-functions/headless.ts +201 -41
  36. package/src/cli/pane-functions/index.ts +24 -6
  37. package/src/cli/pane-functions/options.ts +3 -0
  38. package/src/cli/pane-functions/report.ts +12 -1
  39. package/src/cli/pane-functions/resolver.ts +63 -9
  40. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  41. package/src/cli/pane-functions/screenshot.ts +11 -3
  42. package/src/cli/registry.ts +6 -3
  43. package/src/cli/report-tables.ts +460 -0
  44. package/src/cli/result.ts +53 -29
  45. package/src/cli/ticker-resolution.ts +7 -5
  46. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  47. package/src/components/chart/composite/drawing-store.ts +59 -0
  48. package/src/components/chart/composite/legend.tsx +319 -0
  49. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  50. package/src/components/chart/composite/panel-gestures.ts +59 -0
  51. package/src/components/chart/composite/panel-labels.ts +107 -0
  52. package/src/components/chart/composite/panel-surface.tsx +876 -0
  53. package/src/components/chart/composite/tool-catalog.ts +98 -0
  54. package/src/components/chart/composite/toolbar.tsx +186 -0
  55. package/src/components/chart/composite/tools.ts +8 -0
  56. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  57. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  58. package/src/components/command-bar/list/model.ts +5 -0
  59. package/src/components/command-bar/list/view.tsx +16 -3
  60. package/src/components/command-bar/pane-templates/workflow.ts +1 -0
  61. package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
  62. package/src/components/command-bar/workflow/ops.ts +1 -1
  63. package/src/components/command-bar/workflow/tickers.ts +6 -0
  64. package/src/components/data-table/export.ts +6 -51
  65. package/src/components/data-table/view.tsx +32 -11
  66. package/src/components/feedback-dialog.tsx +2 -1
  67. package/src/components/form-modal/field-row.tsx +2 -2
  68. package/src/components/layout/detached-pane-shell.tsx +6 -3
  69. package/src/components/layout/pane/content.tsx +23 -10
  70. package/src/components/layout/pane/error-boundary.tsx +103 -0
  71. package/src/components/layout/pane/footer/registration.tsx +68 -23
  72. package/src/components/layout/pane/header.tsx +11 -11
  73. package/src/components/layout/shell/active-drag.ts +67 -35
  74. package/src/components/layout/shell/cursor-occlusion.ts +6 -5
  75. package/src/components/layout/shell/drag/index.ts +12 -7
  76. package/src/components/layout/shell/drag/live.ts +122 -0
  77. package/src/components/layout/shell/drag/overlays.tsx +179 -35
  78. package/src/components/layout/shell/drag/runtime.ts +62 -50
  79. package/src/components/layout/shell/drag/slide.ts +10 -0
  80. package/src/components/layout/shell/index.tsx +37 -51
  81. package/src/components/layout/shell/menu.ts +2 -1
  82. package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
  83. package/src/components/layout/shell/native/surfaces.ts +30 -14
  84. package/src/components/layout/shell/pane/actions.ts +2 -1
  85. package/src/components/layout/shell/pane/layers.tsx +419 -168
  86. package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
  87. package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
  88. package/src/components/metric-treemap/heat-surface.tsx +43 -16
  89. package/src/components/metric-treemap/heat-tiles.ts +18 -0
  90. package/src/components/metric-treemap/layout.ts +2 -0
  91. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  92. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  93. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  94. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  95. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  96. package/src/components/ticker/list-table-view.tsx +13 -1
  97. package/src/components/ui/fields.tsx +8 -0
  98. package/src/components/ui/range-track.tsx +10 -3
  99. package/src/components/ui/status.tsx +8 -2
  100. package/src/components/ui/tabs.tsx +7 -4
  101. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  102. package/src/data/config/store/normalize.ts +17 -1
  103. package/src/data/json-persistence.ts +17 -3
  104. package/src/data/json-storage.ts +2 -0
  105. package/src/data/memory-resource-store.ts +46 -0
  106. package/src/i18n/es.ts +19 -1
  107. package/src/i18n/ja.ts +19 -1
  108. package/src/i18n/ko.ts +19 -1
  109. package/src/i18n/zh-cn.ts +19 -1
  110. package/src/i18n/zh-tw.ts +19 -1
  111. package/src/market-data/coordinator/chart.ts +1 -1
  112. package/src/market-data/coordinator/quotes.ts +23 -4
  113. package/src/market-data/fx-closes.ts +72 -0
  114. package/src/market-data/market/freshness.ts +123 -6
  115. package/src/market-data/market/session-close-note.ts +57 -0
  116. package/src/market-data/market/status.ts +151 -0
  117. package/src/market-data/published-apac-sessions.ts +66 -0
  118. package/src/market-data/quotes/contributions.ts +2 -0
  119. package/src/market-data/quotes/freshness.ts +5 -0
  120. package/src/market-data/quotes/resolution.ts +2 -0
  121. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  122. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  123. package/src/plugins/builtin/alerts/cli.ts +10 -5
  124. package/src/plugins/builtin/alerts/index.tsx +1 -0
  125. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  126. package/src/plugins/builtin/analytics/pane-model.ts +10 -6
  127. package/src/plugins/builtin/analytics/risk-client.ts +191 -66
  128. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  129. package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
  130. package/src/plugins/builtin/analytics/risk-model.ts +45 -17
  131. package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
  132. package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
  133. package/src/plugins/builtin/attention/headless.ts +6 -4
  134. package/src/plugins/builtin/attention/index.tsx +1 -1
  135. package/src/plugins/builtin/attention/pane.tsx +2 -2
  136. package/src/plugins/builtin/awards/headless.ts +1 -0
  137. package/src/plugins/builtin/awards/pane.tsx +1 -1
  138. package/src/plugins/builtin/backtest/headless.ts +1 -0
  139. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  140. package/src/plugins/builtin/buildout/index.tsx +1 -0
  141. package/src/plugins/builtin/catalysts/detail.tsx +1 -1
  142. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  143. package/src/plugins/builtin/cds/headless.ts +2 -0
  144. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  145. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  146. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  147. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  148. package/src/plugins/builtin/chat/channels.ts +19 -3
  149. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  150. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  151. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  152. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  153. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  154. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  155. package/src/plugins/builtin/chat/index.tsx +1 -0
  156. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  157. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  158. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  159. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  160. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  161. package/src/plugins/builtin/chat/message/types.ts +14 -2
  162. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  163. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  164. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  165. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  166. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  167. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  168. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  169. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  170. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  171. package/src/plugins/builtin/company-attention/pane.tsx +2 -2
  172. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  173. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  174. package/src/plugins/builtin/correlation/compute.ts +59 -16
  175. package/src/plugins/builtin/correlation/geo.ts +34 -0
  176. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  177. package/src/plugins/builtin/correlation/headless.ts +42 -8
  178. package/src/plugins/builtin/correlation/history.ts +2 -0
  179. package/src/plugins/builtin/correlation/index.tsx +68 -14
  180. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  181. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  182. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  183. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  184. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  185. package/src/plugins/builtin/correlation/settings.ts +1 -1
  186. package/src/plugins/builtin/cot/headless.ts +6 -3
  187. package/src/plugins/builtin/cot/index.tsx +3 -3
  188. package/src/plugins/builtin/cot/model.ts +36 -3
  189. package/src/plugins/builtin/cpi/headless.ts +4 -0
  190. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  191. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  192. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  193. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  194. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  195. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  196. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  197. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  198. package/src/plugins/builtin/doe/headless.ts +7 -0
  199. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  200. package/src/plugins/builtin/earnings/headless.ts +5 -0
  201. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  202. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  203. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  204. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  205. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  206. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  207. package/src/plugins/builtin/econ/index.tsx +1 -0
  208. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  209. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  210. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  211. package/src/plugins/builtin/executives/index.tsx +1 -0
  212. package/src/plugins/builtin/exposure/headless.ts +3 -1
  213. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  214. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  215. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  216. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  217. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  218. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  219. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  220. package/src/plugins/builtin/gpu/headless.ts +7 -3
  221. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  222. package/src/plugins/builtin/gpu/model.ts +27 -1
  223. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  224. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  225. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  226. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  227. package/src/plugins/builtin/holders/client.ts +3 -6
  228. package/src/plugins/builtin/holders/format.ts +31 -1
  229. package/src/plugins/builtin/holders/headless.ts +161 -6
  230. package/src/plugins/builtin/holders/index.tsx +10 -3
  231. package/src/plugins/builtin/holders/pane.tsx +42 -16
  232. package/src/plugins/builtin/holders/report-header.ts +136 -0
  233. package/src/plugins/builtin/holders/table-model.ts +20 -5
  234. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  235. package/src/plugins/builtin/holders/types.ts +2 -1
  236. package/src/plugins/builtin/insider/headless.ts +2 -0
  237. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  238. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  239. package/src/plugins/builtin/jobs/headless.ts +1 -0
  240. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  241. package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
  242. package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
  243. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  244. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  245. package/src/plugins/builtin/market-heatmap/data.ts +2 -0
  246. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  247. package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
  248. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  249. package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
  250. package/src/plugins/builtin/market-movers/headless.ts +2 -0
  251. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  252. package/src/plugins/builtin/members/client.ts +20 -3
  253. package/src/plugins/builtin/members/headless.ts +5 -3
  254. package/src/plugins/builtin/members/model.ts +10 -2
  255. package/src/plugins/builtin/members/pane.tsx +23 -6
  256. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  257. package/src/plugins/builtin/mna/headless.ts +1 -0
  258. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  259. package/src/plugins/builtin/news/headless.ts +2 -0
  260. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  261. package/src/plugins/builtin/notes/cli.ts +14 -6
  262. package/src/plugins/builtin/notes/index.tsx +1 -0
  263. package/src/plugins/builtin/openfda/index.tsx +1 -0
  264. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  265. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  266. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  267. package/src/plugins/builtin/pe-band/client.ts +48 -3
  268. package/src/plugins/builtin/pe-band/headless.ts +25 -7
  269. package/src/plugins/builtin/pe-band/model.ts +92 -16
  270. package/src/plugins/builtin/pe-band/pane.tsx +33 -16
  271. package/src/plugins/builtin/perps/client.ts +50 -3
  272. package/src/plugins/builtin/perps/headless.ts +144 -16
  273. package/src/plugins/builtin/perps/index.tsx +6 -6
  274. package/src/plugins/builtin/perps/model.ts +189 -12
  275. package/src/plugins/builtin/perps/pane.tsx +249 -48
  276. package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
  277. package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
  278. package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -0
  279. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  280. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  281. package/src/plugins/builtin/portfolio-list/cli/render.ts +232 -39
  282. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  283. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  284. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  285. package/src/plugins/builtin/portfolio-list/headless.ts +100 -16
  286. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  287. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  288. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  289. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  290. package/src/plugins/builtin/portfolio-list/pane/index.tsx +53 -16
  291. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  292. package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
  293. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
  294. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  295. package/src/plugins/builtin/power/headless.ts +3 -1
  296. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  297. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  298. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  299. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  300. package/src/plugins/builtin/research/events-headless.ts +2 -0
  301. package/src/plugins/builtin/research/headless.ts +2 -0
  302. package/src/plugins/builtin/research/index.tsx +1 -0
  303. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  304. package/src/plugins/builtin/research/relative-valuation-model.ts +18 -6
  305. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  306. package/src/plugins/builtin/research-search/index.tsx +1 -0
  307. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  308. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  309. package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
  310. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  311. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  312. package/src/plugins/builtin/scanner/headless.ts +14 -0
  313. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  314. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  315. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  316. package/src/plugins/builtin/sec/forms.ts +12 -0
  317. package/src/plugins/builtin/sec/headless.ts +2 -0
  318. package/src/plugins/builtin/sectors/client.ts +1 -0
  319. package/src/plugins/builtin/sectors/headless.ts +9 -1
  320. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  321. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  322. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  323. package/src/plugins/builtin/shared/members-menu.tsx +260 -0
  324. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  325. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  326. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  327. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  328. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  329. package/src/plugins/builtin/short-volume/pane.tsx +1 -1
  330. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  331. package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
  332. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  333. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  334. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  335. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  336. package/src/plugins/builtin/themes/headless.ts +3 -0
  337. package/src/plugins/builtin/themes/pane.tsx +3 -0
  338. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  339. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  340. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
  341. package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
  342. package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
  343. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  344. package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
  345. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
  346. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  347. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  348. package/src/plugins/builtin/volatility/headless.ts +6 -1
  349. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  350. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +159 -0
  351. package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
  352. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  353. package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
  354. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  355. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  356. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  357. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  358. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  359. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  360. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +448 -0
  361. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  362. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  363. package/src/plugins/builtin/world-venue-map/index.ts +69 -6
  364. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
  365. package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
  366. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  367. package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
  368. package/src/plugins/builtin/world-venue-map/model.ts +23 -4
  369. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
  370. package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
  371. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  372. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  373. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  374. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  375. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  376. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  377. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  378. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  379. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  380. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  381. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  382. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  383. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  384. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  385. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  386. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  387. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  388. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  389. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  390. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  391. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  392. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  393. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  394. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  395. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  396. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  397. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  398. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  399. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  400. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  401. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  402. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  403. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  404. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  405. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  406. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  407. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  408. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  409. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  410. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  411. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  412. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  413. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  414. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  415. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  416. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  417. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  418. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/pane.tsx +35 -44
  564. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  565. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  566. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  567. package/src/plugins/loader.ts +13 -1
  568. package/src/plugins/registry/pane-settings.ts +1 -0
  569. package/src/renderers/browser/app-services.ts +3 -1
  570. package/src/renderers/dom/build-assets.ts +81 -3
  571. package/src/renderers/dom/data-table/dom.ts +31 -0
  572. package/src/renderers/dom/data-table/index.tsx +5 -0
  573. package/src/renderers/dom/data-table/row.tsx +2 -0
  574. package/src/renderers/dom/desktop/controls.tsx +7 -3
  575. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  576. package/src/renderers/dom/desktop/popover.tsx +73 -14
  577. package/src/renderers/dom/host/box.tsx +113 -17
  578. package/src/renderers/dom/host/drag-shield.ts +24 -0
  579. package/src/renderers/dom/host/input.tsx +14 -3
  580. package/src/renderers/dom/host/live-frame.ts +54 -0
  581. package/src/renderers/dom/host/mouse.ts +8 -1
  582. package/src/renderers/dom/host/scroll-box.tsx +6 -5
  583. package/src/renderers/dom/host/tabs.tsx +3 -2
  584. package/src/renderers/dom/styles.css +16 -9
  585. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
  586. package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
  587. package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
  588. package/src/renderers/electrobun/shared/protocol.ts +10 -1
  589. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  590. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
  591. package/src/renderers/electrobun/view/host/native.ts +0 -10
  592. package/src/renderers/electrobun/view/host/window-move.ts +28 -0
  593. package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
  594. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  595. package/src/renderers/electrobun/view/ui-host.tsx +2 -5
  596. package/src/renderers/opentui/host.tsx +5 -0
  597. package/src/renderers/opentui/ui-host.tsx +7 -1
  598. package/src/sources/gloomberb-cloud/index.ts +25 -4
  599. package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
  600. package/src/sources/provider-router/batches.ts +3 -3
  601. package/src/sources/provider-router/cached-routes.ts +4 -1
  602. package/src/sources/provider-router/financial-routes.ts +2 -2
  603. package/src/sources/provider-router/financials.ts +76 -12
  604. package/src/sources/provider-router/history.ts +15 -10
  605. package/src/sources/provider-router/primary.ts +2 -2
  606. package/src/sources/sec-registrant.ts +75 -0
  607. package/src/state/app/context/index.tsx +24 -8
  608. package/src/state/hooks/quote-streaming.ts +41 -26
  609. package/src/state/pane-scroll-registry.tsx +67 -35
  610. package/src/sync/core-contributors.ts +4 -0
  611. package/src/telemetry/crash-reports.ts +4 -1
  612. package/src/test-support/cli-context.ts +10 -2
  613. package/src/test-support/margin-account.ts +108 -0
  614. package/src/theme/heat-colors.ts +266 -84
  615. package/src/time-series/resolution.ts +15 -0
  616. package/src/time-series/resolve.ts +1 -1
  617. package/src/time-series/use-chart-resolution.ts +1 -1
  618. package/src/types/context-menu.ts +6 -0
  619. package/src/types/data-provider.ts +2 -0
  620. package/src/types/financials.ts +35 -3
  621. package/src/types/headless.ts +79 -2
  622. package/src/types/plugin.ts +20 -1
  623. package/src/types/ticker.ts +15 -0
  624. package/src/ui/host.tsx +26 -0
  625. package/src/ui/index.tsx +8 -3
  626. package/src/ui/scroll-box-axis.ts +26 -0
  627. package/src/updater/index.ts +9 -11
  628. package/src/utils/async-deadline.ts +21 -0
  629. package/src/utils/cli-output.ts +5 -1
  630. package/src/utils/crypto-pair.ts +41 -0
  631. package/src/utils/currency-units.ts +19 -0
  632. package/src/utils/depositary-receipt.ts +70 -0
  633. package/src/utils/display-number.ts +63 -0
  634. package/src/utils/exchanges.ts +72 -0
  635. package/src/utils/fire-and-forget.ts +24 -0
  636. package/src/utils/format.ts +13 -0
  637. package/src/utils/fundamentals.ts +17 -1
  638. package/src/utils/price-earnings.ts +70 -3
  639. package/src/utils/price-history-integrity.ts +19 -6
  640. package/src/utils/price-history.ts +58 -13
  641. package/src/utils/rpc-timeout-error.ts +27 -0
  642. package/src/utils/sec.ts +13 -1
  643. package/src/utils/utc-time.ts +79 -0
@@ -225,6 +225,78 @@ export const EXCHANGE_TIME_ZONES: Record<string, string> = {
225
225
  CCC: "UTC",
226
226
  };
227
227
 
228
+ /**
229
+ * Venue names by canonical code, for output that names the listing a command
230
+ * resolved ("Euronext Paris (EPA)"). Codes whose name is the code itself
231
+ * (NASDAQ, BSE) are left out.
232
+ */
233
+ const EXCHANGE_NAMES: Record<string, string> = {
234
+ NYSE: "New York Stock Exchange",
235
+ AMEX: "NYSE American",
236
+ ARCA: "NYSE Arca",
237
+ BATS: "Cboe BZX",
238
+ OTC: "OTC Markets",
239
+ JPX: "Tokyo Stock Exchange",
240
+ HKEX: "Hong Kong Stock Exchange",
241
+ LSE: "London Stock Exchange",
242
+ TSX: "Toronto Stock Exchange",
243
+ TSXV: "TSX Venture Exchange",
244
+ CSE: "Canadian Securities Exchange",
245
+ NEO: "Cboe Canada",
246
+ ASX: "Australian Securities Exchange",
247
+ CXA: "Cboe Australia",
248
+ NZX: "New Zealand Exchange",
249
+ SWX: "SIX Swiss Exchange",
250
+ XETRA: "Xetra",
251
+ FWB2: "Frankfurt Stock Exchange",
252
+ EPA: "Euronext Paris",
253
+ AMS: "Euronext Amsterdam",
254
+ BRU: "Euronext Brussels",
255
+ LIS: "Euronext Lisbon",
256
+ BIT: "Borsa Italiana",
257
+ MCE: "Bolsa de Madrid",
258
+ SFB: "Nasdaq Stockholm",
259
+ HEL: "Nasdaq Helsinki",
260
+ CPH: "Nasdaq Copenhagen",
261
+ OSL: "Euronext Oslo",
262
+ ICEX: "Nasdaq Iceland",
263
+ WSE: "Warsaw Stock Exchange",
264
+ PSE: "Prague Stock Exchange",
265
+ VIE: "Vienna Stock Exchange",
266
+ TWSE: "Taiwan Stock Exchange",
267
+ TPEX: "Taipei Exchange",
268
+ NSE: "National Stock Exchange of India",
269
+ BSE: "BSE India",
270
+ SSE: "Shanghai Stock Exchange",
271
+ SZSE: "Shenzhen Stock Exchange",
272
+ KRX: "Korea Exchange",
273
+ SGX: "Singapore Exchange",
274
+ BMV: "Mexican Stock Exchange",
275
+ BYMA: "Bolsas y Mercados Argentinos",
276
+ JSE: "Johannesburg Stock Exchange",
277
+ TASE: "Tel Aviv Stock Exchange",
278
+ };
279
+
280
+ const KNOWN_EXCHANGE_CODES: ReadonlySet<string> = new Set([
281
+ ...Object.keys(CANONICAL_EXCHANGE_ALIASES),
282
+ ...Object.values(CANONICAL_EXCHANGE_ALIASES),
283
+ ...Object.keys(EXCHANGE_TIME_ZONES),
284
+ ...Object.keys(EXCHANGE_NAMES),
285
+ ]);
286
+
287
+ /** Whether a code (any spelling the alias table takes) names a venue the app knows. */
288
+ export function isKnownExchangeCode(value?: string): boolean {
289
+ const normalized = normalizeExchange(value);
290
+ return !!normalized && KNOWN_EXCHANGE_CODES.has(normalized);
291
+ }
292
+
293
+ /** "Euronext Paris (EPA)" for a venue with a name, the canonical code otherwise. */
294
+ export function exchangeLabel(value?: string): string {
295
+ const code = canonicalExchange(value);
296
+ const name = EXCHANGE_NAMES[code];
297
+ return name ? `${name} (${code})` : code;
298
+ }
299
+
228
300
  export function normalizeSymbol(value: string): string {
229
301
  return value.trim().toUpperCase();
230
302
  }
@@ -0,0 +1,24 @@
1
+ import { reportCrash } from "../telemetry/crash-reports";
2
+ import { debugLog } from "./debug-log";
3
+ import { RpcTimeoutError } from "./rpc-timeout-error";
4
+
5
+ const log = debugLog.createLogger("desktop-rpc");
6
+
7
+ /**
8
+ * Starts a desktop bridge call nobody awaits without leaving its rejection
9
+ * unhandled. A timed-out request is logged and reported once per session
10
+ * (never as a crash when the machine slept, see `reportCrash`) and swallowed:
11
+ * the next state change sends a fresh snapshot anyway. Any other error is
12
+ * rethrown, so a programming error still surfaces as an unhandled rejection.
13
+ *
14
+ * `onFailure` runs for every failure, so a caller that remembers what it
15
+ * already sent can forget it and send again.
16
+ */
17
+ export function fireAndForget(request: Promise<unknown> | undefined, label: string, onFailure?: () => void): void {
18
+ request?.catch((error: unknown) => {
19
+ onFailure?.();
20
+ if (!(error instanceof RpcTimeoutError)) throw error;
21
+ log.warn(`${label} did not complete: ${error.message}`);
22
+ reportCrash(error, { kind: "unhandled-rejection" });
23
+ });
24
+ }
@@ -130,6 +130,19 @@ export function formatNumber(value: number | undefined, decimals = 2): string {
130
130
  return getNumberFormatter(decimals).format(value);
131
131
  }
132
132
 
133
+ /**
134
+ * A value to a count of significant digits, so a small ratio keeps its leading
135
+ * digits (0.0005664, not 0.0006) while a large one reads as a plain number
136
+ * (1,235). Decimals follow the rounded value, so 9.9996 reads 10.00.
137
+ */
138
+ export function formatSignificant(value: number | undefined, digits = 4): string {
139
+ if (value == null || !Number.isFinite(value)) return formatNumber(undefined);
140
+ if (value === 0) return getNumberFormatter(0).format(0);
141
+ const rounded = Number(value.toPrecision(digits));
142
+ const decimals = Math.min(12, Math.max(0, digits - 1 - Math.floor(Math.log10(Math.abs(rounded)))));
143
+ return getNumberFormatter(decimals).format(rounded);
144
+ }
145
+
133
146
  /** A percentile rank with its window: "73 pctl 1Y", "-- pctl 1Y" when unranked, "73 pctl" without a window. */
134
147
  export function formatPercentileRank(value: number | null | undefined, window?: string): string {
135
148
  const rank = value == null || !Number.isFinite(value) ? "--" : value.toFixed(0);
@@ -1,4 +1,4 @@
1
- import type { Fundamentals } from "../types/financials";
1
+ import type { Fundamentals, TickerFinancials } from "../types/financials";
2
2
 
3
3
  export const RETRACTABLE_VALUATION_FIELDS = ["enterpriseValue", "enterpriseToRevenue"] as const;
4
4
 
@@ -13,3 +13,19 @@ export function redactUnavailableFundamentals(value: Fundamentals | undefined):
13
13
  for (const field of unavailableFields) delete result[field];
14
14
  return result;
15
15
  }
16
+
17
+ /** A source's enterprise value, or undefined when it has none: banks and insurers come back as 0, which is a gap, not a value. */
18
+ export function reportedEnterpriseValue(fundamentals: Pick<Fundamentals, "enterpriseValue"> | undefined): number | undefined {
19
+ const value = fundamentals?.enterpriseValue;
20
+ return typeof value === "number" && Number.isFinite(value) && value !== 0 ? value : undefined;
21
+ }
22
+
23
+ /**
24
+ * The currency of the trailing EPS, revenue, income and cash flows: the one the fundamentals declare, else the
25
+ * one the statements report in. Never the quote's, which a depositary receipt can differ from (USD quote, TWD books).
26
+ */
27
+ export function fundamentalsCurrency(
28
+ financials: Pick<TickerFinancials, "fundamentals" | "financialCurrency"> | null | undefined,
29
+ ): string | undefined {
30
+ return financials?.fundamentals?.financialCurrency?.trim() || financials?.financialCurrency?.trim() || undefined;
31
+ }
@@ -1,13 +1,80 @@
1
+ import type { Fundamentals } from "../types/financials";
1
2
  import { formatNumber } from "./format";
2
3
 
3
4
  export const PRICE_EARNINGS_NOTICE = "N/M = not meaningful. Non-positive P/E values are excluded from ranking.";
4
5
 
6
+ /** A multiple over a loss or zero base: there is no number to show, rank or export. */
7
+ export const NOT_MEANINGFUL = "not-meaningful";
8
+ export type PriceEarnings = number | typeof NOT_MEANINGFUL;
9
+
10
+ function nonPositive(value: number | null | undefined): boolean {
11
+ return typeof value === "number" && Number.isFinite(value) && value <= 0;
12
+ }
13
+
14
+ /**
15
+ * A P/E checked against the earnings it divides by. Zero or negative earnings
16
+ * make it not meaningful whatever multiple a source served beside them: a
17
+ * source P/E priced at an older, profitable period stays positive after the
18
+ * trailing EPS turns into a loss (MSTR's 5.47 beside EPS -99.08). Unknown
19
+ * earnings leave the multiple as served.
20
+ */
21
+ export function priceEarningsOnEarnings(
22
+ multiple: number | null | undefined,
23
+ earnings: number | null | undefined,
24
+ ): PriceEarnings | undefined {
25
+ if (nonPositive(earnings)) return NOT_MEANINGFUL;
26
+ return typeof multiple === "number" && Number.isFinite(multiple) ? multiple : undefined;
27
+ }
28
+
5
29
  /** Negative earnings do not make a security cheaper than a profitable peer. */
6
- export function comparablePriceEarnings(value: number | null | undefined): number | null {
7
- return value != null && Number.isFinite(value) && value > 0 ? value : null;
30
+ export function comparablePriceEarnings(value: PriceEarnings | null | undefined): number | null {
31
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
8
32
  }
9
33
 
10
- export function formatPriceEarnings(value: number | null | undefined, precision = 1): string {
34
+ /** P/E, forward P/E or PEG: N/M below zero, as the multiple says nothing there. */
35
+ export function formatPriceEarnings(value: PriceEarnings | null | undefined, precision = 1): string {
36
+ if (value === NOT_MEANINGFUL) return "N/M";
11
37
  if (value == null || !Number.isFinite(value)) return "—";
12
38
  return value <= 0 ? "N/M" : formatNumber(value, precision);
13
39
  }
40
+
41
+ type PriceEarningsField = "trailingPE" | "forwardPE" | "pegRatio";
42
+
43
+ /**
44
+ * Why each earnings multiple of a fundamentals block is not meaningful, if it
45
+ * is not: a trailing or forward EPS at or below zero, or a multiple that is
46
+ * itself at or below zero. Forward P/E is judged on its own estimate only, so
47
+ * a trailing loss leaves a positive forward multiple alone.
48
+ */
49
+ export function notMeaningfulMultiples(
50
+ fundamentals: Pick<Fundamentals, PriceEarningsField | "eps" | "forwardEps"> | undefined,
51
+ ): Partial<Record<PriceEarningsField, string>> {
52
+ const reasons: Partial<Record<PriceEarningsField, string>> = {};
53
+ if (!fundamentals) return reasons;
54
+ if (nonPositive(fundamentals.eps)) reasons.trailingPE = "trailing EPS is not positive";
55
+ else if (nonPositive(fundamentals.trailingPE)) reasons.trailingPE = "trailing earnings are not positive";
56
+ if (nonPositive(fundamentals.forwardEps)) reasons.forwardPE = "forward EPS is not positive";
57
+ else if (nonPositive(fundamentals.forwardPE)) reasons.forwardPE = "forward earnings are not positive";
58
+ if (nonPositive(fundamentals.pegRatio)) reasons.pegRatio = "P/E or expected growth is not positive";
59
+ return reasons;
60
+ }
61
+
62
+ /**
63
+ * The fundamentals block as JSON exports it: a multiple that is not meaningful
64
+ * reads null, with the reason under `notMeaningful`, never as a number.
65
+ */
66
+ export function exportedFundamentals<T extends Fundamentals>(
67
+ fundamentals: T | undefined,
68
+ ): (Omit<T, PriceEarningsField> & Partial<Record<PriceEarningsField, number | null>> & {
69
+ notMeaningful?: Partial<Record<PriceEarningsField, string>>;
70
+ }) | undefined {
71
+ if (!fundamentals) return fundamentals;
72
+ const reasons = notMeaningfulMultiples(fundamentals);
73
+ const fields = Object.keys(reasons) as PriceEarningsField[];
74
+ if (fields.length === 0) return fundamentals;
75
+ return {
76
+ ...fundamentals,
77
+ ...Object.fromEntries(fields.map((field) => [field, null])),
78
+ notMeaningful: reasons,
79
+ };
80
+ }
@@ -27,13 +27,26 @@ function above(left: number, right: number): boolean {
27
27
  return left - right > 8 * Number.EPSILON * Math.max(Math.abs(left), Math.abs(right));
28
28
  }
29
29
 
30
- /** Missing OHLC fields are not contradictory: close-only histories remain usable. */
31
- export function pricePointIntegrity(point: PricePoint): PriceHistoryIntegrity | undefined {
30
+ /**
31
+ * Each way a bar's prices contradict each other, as short codes such as
32
+ * `high<open` or `low>close`; empty when they agree. Missing OHLC fields are
33
+ * not contradictory: close-only histories remain usable.
34
+ */
35
+ export function pricePointIntegrityFlags(point: PricePoint): string[] {
32
36
  const { open, high, low, close } = point;
33
- const invalid = (isFiniteNumber(high) && isFiniteNumber(low) && above(low, high))
34
- || [open, close].some((value) => isFiniteNumber(value)
35
- && ((isFiniteNumber(high) && above(value, high)) || (isFiniteNumber(low) && above(low, value))));
36
- if (!invalid) return undefined;
37
+ const flags: string[] = [];
38
+ for (const [name, value] of [["open", open], ["close", close]] as const) {
39
+ if (isFiniteNumber(value) && isFiniteNumber(high) && above(value, high)) flags.push(`high<${name}`);
40
+ }
41
+ for (const [name, value] of [["open", open], ["close", close]] as const) {
42
+ if (isFiniteNumber(value) && isFiniteNumber(low) && above(low, value)) flags.push(`low>${name}`);
43
+ }
44
+ if (isFiniteNumber(high) && isFiniteNumber(low) && above(low, high)) flags.push("low>high");
45
+ return flags;
46
+ }
47
+
48
+ export function pricePointIntegrity(point: PricePoint): PriceHistoryIntegrity | undefined {
49
+ if (pricePointIntegrityFlags(point).length === 0) return undefined;
37
50
  const date = new Date(point.date);
38
51
  return Object.freeze({
39
52
  reason: "inconsistent-ohlc",
@@ -1,5 +1,6 @@
1
1
  import type { PricePoint, TickerFinancials } from "../types/financials";
2
2
  import { canonicalExchange, resolveExchangeTimeZone } from "./exchanges";
3
+ import { isRoundTheClockCoin } from "./crypto-pair";
3
4
  import { hasPublishedSessionCalendar, isRegularSessionTime, isTimestampStaleForExchangeSession, latestRegularSessionClose, latestRegularSessionOpen, sessionCalendarTimeZone } from "../market-data/market/freshness";
4
5
  import { zonedDateTimeParts } from "./zoned-date-time";
5
6
  import { regularHistorySessionStaleness } from "../market-data/history-session";
@@ -10,9 +11,20 @@ const MAX_CURRENT_INTRADAY_HISTORY_LAG_MS = 18 * 60 * 60 * 1000;
10
11
  const MAX_SAME_SESSION_HISTORY_LAG_MS = 30 * 60 * 1000;
11
12
  const DELAYED_HISTORY_ALLOWANCE_MS = 15 * 60 * 1000;
12
13
  const DAY_MS = 24 * 60 * 60 * 1000;
14
+ // A series that never closes must reach the present without a break: no hole
15
+ // this long (or three bars, if larger) in the stretch before now that a
16
+ // current window is read over.
17
+ const ROUND_THE_CLOCK_RECENT_MS = 6 * 60 * 60 * 1000;
18
+ const ROUND_THE_CLOCK_GAP_MS = 2 * 60 * 60 * 1000;
13
19
 
14
20
  interface PriceHistoryFreshnessOptions {
15
21
  exchange?: string;
22
+ /**
23
+ * The listing's symbol. A coin quoted in dollars (BTC-USD) trades around the
24
+ * clock whether or not the exchange says CCC; without the symbol a bare
25
+ * pair is read as a US listing and judged on the NYSE session.
26
+ */
27
+ symbol?: string;
16
28
  intervalMs?: number | null;
17
29
  session?: HistorySession;
18
30
  }
@@ -140,6 +152,29 @@ function normalizePriceHistoryUncached(points: PricePoint[]): PricePoint[] {
140
152
  return validPoints.length === points.length ? points : validPoints;
141
153
  }
142
154
 
155
+ /**
156
+ * A round-the-clock series is current while its latest bar is within two bars
157
+ * and the publishing allowance of now, with no hole in the last hours. Cloud
158
+ * applies the same rule to the bars it serves.
159
+ */
160
+ function isRoundTheClockHistoryBehind(
161
+ points: PricePoint[], latestTime: number, now: number, intervalMs: number | null,
162
+ ): boolean {
163
+ const allowedLag = intervalMs != null ? 2 * intervalMs + DELAYED_HISTORY_ALLOWANCE_MS : MAX_SAME_SESSION_HISTORY_LAG_MS;
164
+ if (now - latestTime > allowedLag) return true;
165
+ const maxGap = Math.max(3 * (intervalMs ?? 0), ROUND_THE_CLOCK_GAP_MS);
166
+ let later = latestTime;
167
+ for (let index = points.length - 1; index >= 0 && later >= now - ROUND_THE_CLOCK_RECENT_MS; index--) {
168
+ const point = points[index]!;
169
+ if (!hasFiniteClose(point)) continue;
170
+ const time = getPricePointTimestamp(point);
171
+ if (!(time < later)) continue;
172
+ if (later - time > maxGap) return true;
173
+ later = time;
174
+ }
175
+ return false;
176
+ }
177
+
143
178
  export function isPriceHistoryStaleForCurrentWindow(
144
179
  points: PricePoint[],
145
180
  now = Date.now(),
@@ -149,7 +184,9 @@ export function isPriceHistoryStaleForCurrentWindow(
149
184
  const latest = normalized.findLast(hasFiniteClose);
150
185
  if (!latest) return false;
151
186
 
152
- const session = options.session?.exchange === canonicalExchange(options.exchange)
187
+ const coin = isRoundTheClockCoin(options.symbol, options.exchange);
188
+ // A coin has no session to read its bars against.
189
+ const session = !coin && options.session?.exchange === canonicalExchange(options.exchange)
153
190
  ? options.session : undefined;
154
191
  const sessionInterval = session ? priceHistoryIntervalMs(session.interval) : null;
155
192
  const intervalMs = options.intervalMs ?? sessionInterval ?? inferredHistoryIntervalMs(normalized);
@@ -159,6 +196,9 @@ export function isPriceHistoryStaleForCurrentWindow(
159
196
 
160
197
  const latestTime = getPricePointTimestamp(latest);
161
198
  if (!Number.isFinite(latestTime)) return false;
199
+ // Before any exchange logic: a bare BTC-USD is not a US listing, and the
200
+ // always-open venue's own rule lets a bar up to two hours old stand.
201
+ if (coin) return isRoundTheClockHistoryBehind(normalized, latestTime, now, intervalMs);
162
202
  if (session && (options.intervalMs == null || options.intervalMs === sessionInterval)) {
163
203
  const regularStale = regularHistorySessionStaleness(latestTime, now, session);
164
204
  if (regularStale !== null) return regularStale;
@@ -171,15 +211,12 @@ export function isPriceHistoryStaleForCurrentWindow(
171
211
  intervalMs != null ? 2 * intervalMs + DELAYED_HISTORY_ALLOWANCE_MS : 0);
172
212
  if (age <= allowedLag) return false;
173
213
  const exchange = options.exchange || "NASDAQ";
174
- if (
175
- resolveExchangeTimeZone(exchange)
176
- && isTimestampStaleForExchangeSession(latestTime, exchange, now)
177
- ) {
178
- return true;
179
- }
180
214
  // Bars that reach the close of the venue's latest session stay current
181
215
  // once it has closed, so a closed market keeps its last session until the
182
216
  // next one opens. A copy taken earlier in that session is still behind.
217
+ // Asked before the quote rule below, which reads any US bar dated before
218
+ // today as behind from 04:00 ET: right for a last price, wrong for bars
219
+ // waiting for the next session's first one.
183
220
  const regularSession = isRegularSessionTime(exchange, now);
184
221
  if (regularSession !== null) {
185
222
  const open = latestRegularSessionOpen(exchange, now);
@@ -190,6 +227,12 @@ export function isPriceHistoryStaleForCurrentWindow(
190
227
  if (regularSession && close < open && latestTime < open && now - open <= allowedLag) return false;
191
228
  }
192
229
  }
230
+ if (
231
+ resolveExchangeTimeZone(exchange)
232
+ && isTimestampStaleForExchangeSession(latestTime, exchange, now)
233
+ ) {
234
+ return true;
235
+ }
193
236
  const hasExchangeSession = Boolean(resolveExchangeTimeZone(exchange));
194
237
  if (age <= MAX_CURRENT_INTRADAY_HISTORY_LAG_MS) return hasExchangeSession;
195
238
  return !hasExchangeSession;
@@ -209,7 +252,7 @@ const BEHIND_RECHECK_BACKOFF = 4;
209
252
  // re-check fails, answers nothing usable, or is rejected.
210
253
  const UNSETTLED_RETRY_MS = 5 * 60 * 1000;
211
254
 
212
- interface CalendarHistoryFetchOptions extends Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs"> {
255
+ interface CalendarHistoryFetchOptions extends Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs" | "symbol"> {
213
256
  /**
214
257
  * The latest check of this request, including a failed or empty one; the
215
258
  * fetch of the copy itself when absent.
@@ -243,12 +286,13 @@ function barDate(time: number, timeZone: string): string {
243
286
  * The venue date of the latest bar, read as calendarHistoryFetchState reads
244
287
  * it, so copies whose sources label a session differently compare equal.
245
288
  */
246
- export function calendarHistoryLastBarDate(points: PricePoint[], exchange?: string): string | null {
289
+ export function calendarHistoryLastBarDate(points: PricePoint[], exchange?: string, symbol?: string): string | null {
247
290
  const latest = normalizePriceHistory(points).findLast(hasFiniteClose);
248
291
  if (!latest) return null;
249
292
  const time = getPricePointTimestamp(latest);
250
293
  if (!Number.isFinite(time)) return null;
251
- // Bare symbols resolve to their US listing at the sources.
294
+ // Bare symbols resolve to their US listing at the sources, a coin to its UTC date.
295
+ if (isRoundTheClockCoin(symbol, exchange)) return barDate(time, "UTC");
252
296
  return barDate(time, sessionCalendarTimeZone(canonicalExchange(exchange) || "NYSE") ?? "UTC");
253
297
  }
254
298
 
@@ -270,7 +314,7 @@ function isBarBeforeSession(latestTime: number, session: string, intervalMs: num
270
314
  * A daily or coarser series changes at every close. A copy fetched before the
271
315
  * latest settled close is outdated whatever its cache TTL. A copy fetched
272
316
  * after it but without its bar is behind only where the venue's closures are
273
- * published (US venues, JPX): elsewhere, and for a bare symbol whose venue is
317
+ * published (hasPublishedSessionCalendar): elsewhere, and for a bare symbol whose venue is
274
318
  * unknown, a local holiday would read as a missing session. A copy of a 24/7
275
319
  * series goes out of date within the hour.
276
320
  */
@@ -285,7 +329,7 @@ export function calendarHistoryFetchState(
285
329
  const intervalMs = options.intervalMs ?? inferredHistoryIntervalMs(normalized);
286
330
  if (intervalMs == null || intervalMs < DAY_MS) return "current";
287
331
  const exchange = canonicalExchange(options.exchange);
288
- if (exchange === "CCC") {
332
+ if (isRoundTheClockCoin(options.symbol, options.exchange)) {
289
333
  return now - fetchedAt > CRYPTO_BAR_MAX_AGE_MS
290
334
  ? unsettledState(fetchedAt + CRYPTO_BAR_MAX_AGE_MS, options.checkedAt, now) : "current";
291
335
  }
@@ -309,12 +353,13 @@ export function calendarHistoryFetchState(
309
353
  export function reachesLatestSettledSession(
310
354
  points: PricePoint[],
311
355
  now = Date.now(),
312
- options: Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs"> = {},
356
+ options: Pick<PriceHistoryFreshnessOptions, "exchange" | "intervalMs" | "symbol"> = {},
313
357
  ): boolean {
314
358
  const normalized = normalizePriceHistory(points);
315
359
  const latest = normalized.findLast(hasFiniteClose);
316
360
  const latestTime = latest ? getPricePointTimestamp(latest) : Number.NaN;
317
361
  if (!Number.isFinite(latestTime)) return false;
362
+ if (isRoundTheClockCoin(options.symbol, options.exchange)) return false;
318
363
  // Bare symbols resolve to their US listing at the sources.
319
364
  const session = latestRegularSessionClose(canonicalExchange(options.exchange) || "NYSE", now - SESSION_BAR_SETTLE_MS);
320
365
  if (!session) return false;
@@ -0,0 +1,27 @@
1
+ /** A timeout this many times past its limit means the machine slept through it. */
2
+ const SLEEP_TIMEOUT_FACTOR = 5;
3
+
4
+ /**
5
+ * A call to the desktop's Bun process that did not complete in time: the
6
+ * request timer ran out, or the bridge socket never opened. `name` stays
7
+ * "Error", so crash reports and filters see the same type as before.
8
+ */
9
+ export class RpcTimeoutError extends Error {
10
+ readonly elapsedMs: number;
11
+ readonly limitMs: number;
12
+
13
+ constructor(message: string, { elapsedMs, limitMs, cause }: { elapsedMs: number; limitMs: number; cause?: unknown }) {
14
+ super(message, cause === undefined ? undefined : { cause });
15
+ this.elapsedMs = elapsedMs;
16
+ this.limitMs = limitMs;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * A timeout whose timer fired long after its limit. A laptop that sleeps
22
+ * suspends the page, and on wake the timer runs once for a request the Bun
23
+ * process already lost. Nothing the user did failed, so it is not a crash.
24
+ */
25
+ export function isSleepRpcTimeout(error: unknown): boolean {
26
+ return error instanceof RpcTimeoutError && error.elapsedMs > SLEEP_TIMEOUT_FACTOR * error.limitMs;
27
+ }
package/src/utils/sec.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { TickerRecord } from "../types/ticker";
2
- import { canonicalExchange, US_LISTING_EXCHANGES } from "./exchanges";
2
+ import { canonicalExchange, parsePublicTickerKey, US_LISTING_EXCHANGES } from "./exchanges";
3
3
 
4
4
  /** Canonical US equity venues: the listing exchanges plus other lit and OTC venues. */
5
5
  const US_EQUITY_EXCHANGES = new Set([
@@ -102,6 +102,18 @@ export function isKnownNonUsEquityTicker(ticker: TickerRecord | null | undefined
102
102
  .some((exchange) => normalize(exchange).length > 0);
103
103
  }
104
104
 
105
+ /**
106
+ * The venue an SEC issuer lookup has to respect: a listing outside the US,
107
+ * whose bare symbol the SEC may know as another company (SAN is Banco
108
+ * Santander in New York, Sanofi in Paris). Null for a US venue, a routing
109
+ * destination or no venue at all, which look the symbol up as a US ticker.
110
+ */
111
+ export function nonUsSecListingVenue(ticker: string, exchange?: string): string | null {
112
+ const venue = parsePublicTickerKey(ticker).exchange ?? canonicalExchange(exchange);
113
+ if (!venue || ROUTING_EXCHANGES.has(venue) || isUsExchange(venue)) return null;
114
+ return venue;
115
+ }
116
+
105
117
  /**
106
118
  * The item codes in EDGAR's `items` field ("2.02,9.01"). EDGAR fills the same
107
119
  * field with other values for some forms, such as the order dates of a CT
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Times in CLI and report text print in UTC with the zone named, so a value
3
+ * copied out of a report means the same thing on every machine and in every
4
+ * time zone. JSON keeps the raw ISO or epoch values.
5
+ */
6
+
7
+ const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
8
+ /** An ISO date and time with an explicit zone; one without a zone cannot be placed in UTC. */
9
+ const ZONED_ISO_DATE_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})$/i;
10
+ // Epoch milliseconds between 2001 and 2286, so counts and prices are never read as times.
11
+ const EPOCH_MS_MIN = 1e12;
12
+ const EPOCH_MS_MAX = 1e13;
13
+
14
+ export interface ReportTime {
15
+ /** Epoch milliseconds; a date-only value sits at UTC midnight. */
16
+ time: number;
17
+ /** The value named a calendar date, not an instant. */
18
+ dateOnly: boolean;
19
+ }
20
+
21
+ export function isEpochMilliseconds(value: number): boolean {
22
+ return Number.isFinite(value) && value >= EPOCH_MS_MIN && value < EPOCH_MS_MAX;
23
+ }
24
+
25
+ export function isZonedIsoDateTime(value: string): boolean {
26
+ return ZONED_ISO_DATE_TIME.test(value);
27
+ }
28
+
29
+ /**
30
+ * Reads a Date, epoch milliseconds, an ISO date or a zoned ISO date and time.
31
+ * A date and time without a zone, or anything else, is not a report time.
32
+ */
33
+ export function parseReportTime(value: unknown): ReportTime | null {
34
+ if (value instanceof Date) {
35
+ const time = value.getTime();
36
+ return Number.isFinite(time) ? { time, dateOnly: false } : null;
37
+ }
38
+ if (typeof value === "number") return isEpochMilliseconds(value) ? { time: value, dateOnly: false } : null;
39
+ if (typeof value !== "string") return null;
40
+ const text = value.trim();
41
+ if (DATE_ONLY.test(text)) {
42
+ const time = Date.parse(`${text}T00:00:00Z`);
43
+ return Number.isFinite(time) ? { time, dateOnly: true } : null;
44
+ }
45
+ if (!ZONED_ISO_DATE_TIME.test(text)) return null;
46
+ const time = Date.parse(text);
47
+ return Number.isFinite(time) ? { time, dateOnly: false } : null;
48
+ }
49
+
50
+ /**
51
+ * `2026-10-09 00:08 UTC`. Only an explicitly date-only value prints
52
+ * as `2026-10-09`; midnight instants keep their time and zone.
53
+ */
54
+ export function formatUtcTime(value: ReportTime | Date | number | string): string {
55
+ const parsed = typeof value === "object" && !(value instanceof Date) ? value : parseReportTime(value);
56
+ if (!parsed) return typeof value === "string" ? value : "";
57
+ const iso = new Date(parsed.time).toISOString();
58
+ if (parsed.dateOnly) return iso.slice(0, 10);
59
+ return `${iso.slice(0, 16).replace("T", " ")} UTC`;
60
+ }
61
+
62
+ /** The newest of some report times, as given, so a loader can declare its as-of from the rows it means. */
63
+ export function newestReportTime<T>(values: Iterable<T>): T | null {
64
+ let best: { value: T; time: number } | null = null;
65
+ for (const value of values) {
66
+ const parsed = parseReportTime(value);
67
+ if (parsed && (!best || parsed.time > best.time)) best = { value, time: parsed.time };
68
+ }
69
+ return best?.value ?? null;
70
+ }
71
+
72
+ export function oldestReportTime<T>(values: Iterable<T>): T | null {
73
+ let best: { value: T; time: number } | null = null;
74
+ for (const value of values) {
75
+ const parsed = parseReportTime(value);
76
+ if (parsed && (!best || parsed.time < best.time)) best = { value, time: parsed.time };
77
+ }
78
+ return best?.value ?? null;
79
+ }