gloomberb 0.11.3 → 0.12.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 (489) hide show
  1. package/README.md +6 -4
  2. package/README.zh-CN.md +4 -2
  3. package/package.json +28 -1
  4. package/src/api-client/auth.ts +10 -0
  5. package/src/api-client/data.ts +103 -1
  6. package/src/api-client/index.test.ts +127 -0
  7. package/src/api-client/index.ts +129 -1
  8. package/src/api-client/normalizers.ts +39 -0
  9. package/src/api-client/paths.ts +85 -1
  10. package/src/api-client/types.ts +196 -0
  11. package/src/app/pane-runtime/index.tsx +15 -12
  12. package/src/app/pane-runtime/layout-placement.test.ts +27 -0
  13. package/src/app/pane-runtime/layout-placement.ts +13 -0
  14. package/src/app/pane-runtime/plugin-bindings.ts +62 -0
  15. package/src/app.tsx +60 -18
  16. package/src/architecture/browser-entry-graph.test.ts +96 -0
  17. package/src/brokers/profile-form.test.ts +25 -27
  18. package/src/brokers/test-broker.ts +68 -0
  19. package/src/cli/commands/plugins.ts +39 -11
  20. package/src/cli/desktop-pane-shot.ts +285 -16
  21. package/src/cli/index.ts +1 -1
  22. package/src/cli/pane-functions/capabilities.ts +58 -28
  23. package/src/cli/pane-functions/catalog.ts +16 -4
  24. package/src/cli/pane-functions/discovery.ts +1 -0
  25. package/src/cli/pane-functions/headless.test.ts +247 -0
  26. package/src/cli/pane-functions/headless.ts +423 -0
  27. package/src/cli/pane-functions/index.test.ts +9 -0
  28. package/src/cli/pane-functions/index.ts +6 -2
  29. package/src/cli/pane-functions/options.ts +27 -2
  30. package/src/cli/pane-functions/report.ts +4 -0
  31. package/src/cli/pane-functions/resolver.ts +26 -8
  32. package/src/cli/pane-functions/screenshot.test.ts +76 -0
  33. package/src/cli/pane-functions/screenshot.ts +236 -20
  34. package/src/cli/restore-plugins.ts +34 -0
  35. package/src/components/chart/{static/chart → composite}/axis-overlays.test.tsx +3 -3
  36. package/src/components/chart/{static/chart → composite}/axis-overlays.tsx +6 -11
  37. package/src/components/chart/{static/chart → composite}/bitmap.ts +17 -3
  38. package/src/components/chart/composite/composite-chart.test.tsx +68 -20
  39. package/src/components/chart/composite/composite-chart.tsx +301 -204
  40. package/src/components/chart/composite/format.ts +8 -2
  41. package/src/components/chart/composite/interactions.test.ts +68 -102
  42. package/src/components/chart/composite/interactions.ts +214 -264
  43. package/src/components/chart/composite/price-axis-labels.test.ts +21 -0
  44. package/src/components/chart/{price-axis-labels.tsx → composite/price-axis-labels.tsx} +9 -4
  45. package/src/components/chart/composite/scene.ts +57 -3
  46. package/src/components/chart/composite/text-renderer.ts +3 -2
  47. package/src/components/chart/composite/time-scale.ts +138 -57
  48. package/src/components/chart/composite/types.ts +25 -1
  49. package/src/components/chart/core/data.ts +9 -13
  50. package/src/components/chart/core/date-window.ts +7 -1
  51. package/src/components/chart/core/pointer.ts +3 -0
  52. package/src/components/chart/core/types.ts +0 -45
  53. package/src/components/chart/native/chart-rasterizer.ts +0 -1
  54. package/src/components/chart/native/kitty/index.test.ts +0 -188
  55. package/src/components/chart/native/raster/crosshair.ts +6 -5
  56. package/src/components/chart/native/raster/primitives.ts +0 -23
  57. package/src/components/chart/native/renderer-selection.ts +81 -31
  58. package/src/components/chart/static/{chart/surface.test.tsx → chart-surface.test.tsx} +28 -80
  59. package/src/components/chart/static/chart-surface.tsx +150 -0
  60. package/src/components/chart/static/index.ts +8 -0
  61. package/src/components/chart/static/multi-line-chart-surface.tsx +51 -166
  62. package/src/components/chart/static/scatter-chart-surface.test.ts +30 -0
  63. package/src/components/chart/static/scatter-chart-surface.tsx +135 -34
  64. package/src/components/chart/static/series.ts +49 -0
  65. package/src/components/command-bar/action-runtime.ts +1 -3
  66. package/src/components/command-bar/assist/model.test.ts +17 -2
  67. package/src/components/command-bar/assist/model.ts +40 -9
  68. package/src/components/command-bar/commands/direct/index.ts +1 -1
  69. package/src/components/command-bar/commands/direct/runtime.ts +1 -1
  70. package/src/components/command-bar/commands/registry.ts +0 -11
  71. package/src/components/command-bar/helpers.test.ts +2 -2
  72. package/src/components/command-bar/helpers.ts +2 -6
  73. package/src/components/command-bar/keyboard-shortcuts.ts +0 -11
  74. package/src/components/command-bar/list/badge.test.ts +54 -0
  75. package/src/components/command-bar/list/badge.ts +62 -0
  76. package/src/components/command-bar/list/model.test.ts +103 -0
  77. package/src/components/command-bar/list/model.ts +61 -4
  78. package/src/components/command-bar/list/view.test.tsx +113 -0
  79. package/src/components/command-bar/list/view.tsx +147 -131
  80. package/src/components/command-bar/pane-templates/workflow.ts +1 -1
  81. package/src/components/command-bar/panel/body.tsx +51 -65
  82. package/src/components/command-bar/panel/index.tsx +48 -13
  83. package/src/components/command-bar/panel/layout.test.ts +139 -0
  84. package/src/components/command-bar/panel/layout.ts +65 -28
  85. package/src/components/command-bar/panel/native-surface.ts +24 -0
  86. package/src/components/command-bar/panel/prompt-binding.ts +54 -0
  87. package/src/components/command-bar/panel/runtime.ts +6 -3
  88. package/src/components/command-bar/panel/state.ts +41 -7
  89. package/src/components/command-bar/panel/types.ts +7 -1
  90. package/src/components/command-bar/routes/root/provider-search.ts +34 -15
  91. package/src/components/command-bar/routes/root/results.test.ts +161 -0
  92. package/src/components/command-bar/routes/root/results.ts +30 -28
  93. package/src/components/command-bar/routes/root/runtime.ts +37 -20
  94. package/src/components/command-bar/routes/root/search-providers.test.tsx +224 -0
  95. package/src/components/command-bar/routes/root/search-providers.ts +205 -0
  96. package/src/components/command-bar/routes/root/selection.ts +1 -12
  97. package/src/components/command-bar/routes/root/shortcuts.test.ts +8 -8
  98. package/src/components/command-bar/routes/ticker-search/actions.ts +10 -9
  99. package/src/components/command-bar/routes/ticker-search/results.test.ts +54 -1
  100. package/src/components/command-bar/routes/ticker-search/results.ts +60 -19
  101. package/src/components/command-bar/routes/ticker-search/route.ts +1 -0
  102. package/src/components/command-bar/routing/actions.ts +1 -81
  103. package/src/components/command-bar/routing/launch-request.ts +1 -1
  104. package/src/components/command-bar/routing/list-state.ts +6 -21
  105. package/src/components/command-bar/selection-runtime.ts +1 -1
  106. package/src/components/command-bar/surface/assist.test.tsx +14 -10
  107. package/src/components/command-bar/surface/environment.ts +8 -1
  108. package/src/components/command-bar/surface/index.test.tsx +84 -68
  109. package/src/components/command-bar/surface/index.tsx +33 -36
  110. package/src/components/command-bar/surface/test-harness.tsx +15 -3
  111. package/src/components/command-bar/theme-picker.tsx +43 -15
  112. package/src/components/command-bar/view-model.test.ts +53 -8
  113. package/src/components/command-bar/view-model.ts +43 -14
  114. package/src/components/command-bar/workflow/tickers.ts +1 -0
  115. package/src/components/command-bar/workflow/types.ts +1 -1
  116. package/src/components/data-table/view.test.tsx +45 -6
  117. package/src/components/data-table/view.tsx +55 -9
  118. package/src/components/index.ts +10 -2
  119. package/src/components/input-search-bar.test.tsx +36 -2
  120. package/src/components/input-search-bar.tsx +18 -1
  121. package/src/components/layout/header.test.tsx +57 -10
  122. package/src/components/layout/header.tsx +292 -149
  123. package/src/components/layout/market-summary.test.ts +81 -0
  124. package/src/components/layout/market-summary.ts +109 -0
  125. package/src/components/layout/shell/chrome.ts +96 -1
  126. package/src/components/layout/shell/index.tsx +11 -3
  127. package/src/components/layout/shell/menu.ts +9 -0
  128. package/src/components/layout/shell/pane/actions.ts +29 -0
  129. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  130. package/src/components/layout/shell/shortcuts.ts +3 -0
  131. package/src/components/layout/status-bar.test.tsx +9 -8
  132. package/src/components/layout/status-bar.tsx +85 -54
  133. package/src/components/onboarding/onboarding-frame.tsx +2 -26
  134. package/src/components/price-sparkline/index.ts +61 -34
  135. package/src/components/price-sparkline/view.tsx +1 -1
  136. package/src/components/sign-in-gate.test.tsx +128 -0
  137. package/src/components/sign-in-gate.tsx +149 -0
  138. package/src/components/speedometer-gauge/desktop.tsx +2 -12
  139. package/src/components/ticker/badge/list.tsx +17 -3
  140. package/src/components/ticker/list-table-view.tsx +6 -3
  141. package/src/components/ui/data-table/index.tsx +3 -2
  142. package/src/components/ui/data-table/opentui/index.tsx +165 -120
  143. package/src/components/ui/frame.tsx +28 -0
  144. package/src/components/ui/index.ts +3 -0
  145. package/src/components/ui/native-select.tsx +20 -10
  146. package/src/components/ui/select-button.tsx +138 -0
  147. package/src/components/ui/status.tsx +2 -2
  148. package/src/components/ui/table-layout.ts +1 -1
  149. package/src/components/use-double-click-activation.ts +7 -3
  150. package/src/core/app-services.ts +3 -3
  151. package/src/data/config/layout.ts +12 -6
  152. package/src/data/config/store/index.test.ts +97 -0
  153. package/src/data/config/store/migrations.ts +41 -0
  154. package/src/data/config/store/normalize.ts +5 -3
  155. package/src/i18n/es.ts +6 -2
  156. package/src/i18n/ja.ts +6 -2
  157. package/src/i18n/ko.ts +6 -2
  158. package/src/i18n/zh-cn.ts +6 -2
  159. package/src/i18n/zh-tw.ts +6 -2
  160. package/src/layout-marketplace/pane-imagery.ts +1 -0
  161. package/src/layout-marketplace/payload.test.ts +17 -0
  162. package/src/layout-marketplace/payload.ts +40 -5
  163. package/src/market-data/coordinator/index.ts +3 -2
  164. package/src/market-data/coordinator/quotes.ts +173 -66
  165. package/src/market-data/coordinator/subscriptions.test.ts +215 -37
  166. package/src/pane-settings.ts +1 -1
  167. package/src/plugins/builtin/analytics/pane-model.ts +1 -1
  168. package/src/plugins/builtin/analytics/view.tsx +1 -1
  169. package/src/plugins/builtin/broker-manager/index.test.tsx +3 -2
  170. package/src/plugins/builtin/broker-manager/model.test.ts +2 -2
  171. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +16 -2
  172. package/src/plugins/builtin/chart-composer/pane.tsx +22 -8
  173. package/src/plugins/builtin/chat/content/composer.tsx +8 -4
  174. package/src/plugins/builtin/cloud/auth-dialog.tsx +14 -228
  175. package/src/plugins/builtin/cloud/auth-form.tsx +277 -0
  176. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  177. package/src/plugins/builtin/composite-plugins.ts +14 -1
  178. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  179. package/src/plugins/builtin/correlation/relationship/pane.tsx +2 -6
  180. package/src/plugins/builtin/correlation/relationship/view-model.ts +2 -2
  181. package/src/plugins/builtin/credit-conditions/index.test.tsx +12 -6
  182. package/src/plugins/builtin/credit-conditions/index.tsx +2 -21
  183. package/src/plugins/builtin/dividend-yield/index.tsx +1 -0
  184. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  185. package/src/plugins/builtin/earnings-calls/data.ts +223 -0
  186. package/src/plugins/builtin/earnings-calls/format.ts +49 -0
  187. package/src/plugins/builtin/earnings-calls/index.tsx +69 -0
  188. package/src/plugins/builtin/earnings-calls/pane.tsx +756 -0
  189. package/src/plugins/builtin/earnings-calls/prose.test.ts +36 -0
  190. package/src/plugins/builtin/earnings-calls/prose.ts +59 -0
  191. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +334 -0
  192. package/src/plugins/builtin/econ/detail-view.tsx +1 -2
  193. package/src/plugins/builtin/econ/fred-series-map.ts +16 -1
  194. package/src/plugins/builtin/econ/index.tsx +2 -1
  195. package/src/plugins/builtin/econ-statistics/cache.ts +4 -0
  196. package/src/plugins/builtin/econ-statistics/client.ts +92 -0
  197. package/src/plugins/builtin/econ-statistics/defs.ts +66 -0
  198. package/src/plugins/builtin/econ-statistics/detail.tsx +154 -0
  199. package/src/plugins/builtin/econ-statistics/headless.test.ts +54 -0
  200. package/src/plugins/builtin/econ-statistics/headless.ts +171 -0
  201. package/src/plugins/builtin/econ-statistics/index.tsx +54 -0
  202. package/src/plugins/builtin/econ-statistics/pane.tsx +356 -0
  203. package/src/plugins/builtin/econ-statistics/stats.ts +522 -0
  204. package/src/plugins/builtin/econ-statistics/transform.test.ts +86 -0
  205. package/src/plugins/builtin/econ-statistics/transform.ts +85 -0
  206. package/src/plugins/builtin/econ-statistics/trend.ts +57 -0
  207. package/src/plugins/builtin/econ-statistics/view.ts +90 -0
  208. package/src/plugins/builtin/fear-greed/charts.tsx +7 -18
  209. package/src/plugins/builtin/fear-greed/data.ts +6 -1
  210. package/src/plugins/builtin/help/index.tsx +4 -0
  211. package/src/plugins/builtin/holders/index.tsx +1 -0
  212. package/src/plugins/builtin/insider/index.tsx +1 -0
  213. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  214. package/src/plugins/builtin/kelly-sizer/sections.tsx +2 -3
  215. package/src/plugins/builtin/market-valuation/align.ts +122 -0
  216. package/src/plugins/builtin/market-valuation/cache.ts +32 -0
  217. package/src/plugins/builtin/market-valuation/chart-projection.ts +217 -0
  218. package/src/plugins/builtin/market-valuation/chart-series.ts +89 -0
  219. package/src/plugins/builtin/market-valuation/client.test.ts +141 -0
  220. package/src/plugins/builtin/market-valuation/client.ts +116 -0
  221. package/src/plugins/builtin/market-valuation/defs.ts +251 -0
  222. package/src/plugins/builtin/market-valuation/detail.tsx +159 -0
  223. package/src/plugins/builtin/market-valuation/headless.test.ts +58 -0
  224. package/src/plugins/builtin/market-valuation/headless.ts +170 -0
  225. package/src/plugins/builtin/market-valuation/index.tsx +64 -0
  226. package/src/plugins/builtin/market-valuation/indicators.ts +422 -0
  227. package/src/plugins/builtin/market-valuation/model.test.ts +350 -0
  228. package/src/plugins/builtin/market-valuation/model.ts +8 -0
  229. package/src/plugins/builtin/market-valuation/pane.test.tsx +247 -0
  230. package/src/plugins/builtin/market-valuation/pane.tsx +344 -0
  231. package/src/plugins/builtin/market-valuation/series.ts +12 -0
  232. package/src/plugins/builtin/market-valuation/settings.ts +38 -0
  233. package/src/plugins/builtin/market-valuation/sources.ts +130 -0
  234. package/src/plugins/builtin/market-valuation/trend.ts +89 -0
  235. package/src/plugins/builtin/market-valuation/view.ts +137 -0
  236. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +123 -0
  237. package/src/plugins/builtin/market-valuation/zone-scale/index.tsx +12 -0
  238. package/src/plugins/builtin/market-valuation/zone-scale/model.ts +60 -0
  239. package/src/plugins/builtin/market-valuation/zone-scale/terminal.tsx +94 -0
  240. package/src/plugins/builtin/news/wire/breaking/filters.test.ts +99 -0
  241. package/src/plugins/builtin/news/wire/breaking/filters.ts +110 -0
  242. package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +157 -53
  243. package/src/plugins/builtin/news/wire/breaking/notifications.ts +91 -25
  244. package/src/plugins/builtin/news/wire/index.tsx +31 -44
  245. package/src/plugins/builtin/options/index.tsx +1 -0
  246. package/src/plugins/builtin/options/view.test.tsx +29 -1
  247. package/src/plugins/builtin/options/view.tsx +1 -22
  248. package/src/plugins/builtin/plugin-marketplace/feed.ts +80 -0
  249. package/src/plugins/builtin/plugin-marketplace/index.tsx +31 -0
  250. package/src/plugins/builtin/plugin-marketplace/model.test.ts +200 -0
  251. package/src/plugins/builtin/plugin-marketplace/model.ts +204 -0
  252. package/src/plugins/builtin/plugin-marketplace/pane.tsx +385 -0
  253. package/src/plugins/builtin/plugin-marketplace/store.ts +46 -0
  254. package/src/plugins/builtin/plugin-module.ts +9 -1
  255. package/src/plugins/builtin/research/index.tsx +4 -0
  256. package/src/plugins/builtin/research-search/command-bar-search.test.ts +81 -0
  257. package/src/plugins/builtin/research-search/command-bar-search.ts +175 -0
  258. package/src/plugins/builtin/research-search/data.ts +109 -0
  259. package/src/plugins/builtin/research-search/document-view.test.tsx +75 -0
  260. package/src/plugins/builtin/research-search/document-view.tsx +254 -0
  261. package/src/plugins/builtin/research-search/filter-bar.tsx +62 -0
  262. package/src/plugins/builtin/research-search/focus-handoff.ts +47 -0
  263. package/src/plugins/builtin/research-search/index.tsx +85 -0
  264. package/src/plugins/builtin/research-search/model.test.ts +40 -0
  265. package/src/plugins/builtin/research-search/model.ts +291 -0
  266. package/src/plugins/builtin/research-search/pane.test.tsx +241 -0
  267. package/src/plugins/builtin/research-search/pane.tsx +678 -0
  268. package/src/plugins/builtin/research-search/saved-view.tsx +171 -0
  269. package/src/plugins/builtin/research-search/snippet-text.tsx +35 -0
  270. package/src/plugins/builtin/research-search/snippet.test.ts +78 -0
  271. package/src/plugins/builtin/research-search/snippet.ts +134 -0
  272. package/src/plugins/builtin/scanner/flow-model.test.ts +11 -1
  273. package/src/plugins/builtin/scanner/flow-model.ts +29 -1
  274. package/src/plugins/builtin/scanner/flow-pane.tsx +78 -22
  275. package/src/plugins/builtin/sec/index.tsx +1 -0
  276. package/src/plugins/builtin/shared/series-cache.ts +93 -0
  277. package/src/plugins/builtin/short-interest/index.tsx +1 -0
  278. package/src/plugins/builtin/short-interest/pane.tsx +1 -1
  279. package/src/plugins/builtin/thirteenf/index.tsx +1 -0
  280. package/src/plugins/builtin/ticker-detail/index.tsx +0 -14
  281. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
  282. package/src/plugins/builtin/volatility/index.tsx +1 -1
  283. package/src/plugins/builtin/world-venue-map/map.desktop.test.tsx +106 -0
  284. package/src/plugins/builtin/world-venue-map/map.tsx +213 -69
  285. package/src/plugins/builtin/world-venue-map/model.test.ts +32 -0
  286. package/src/plugins/builtin/world-venue-map/model.ts +134 -13
  287. package/src/plugins/builtin/yield-curve/index.tsx +1 -1
  288. package/src/plugins/bundle.test.ts +109 -0
  289. package/src/plugins/bundle.ts +139 -0
  290. package/src/plugins/catalog-browser.test.ts +1 -0
  291. package/src/plugins/catalog-browser.ts +10 -0
  292. package/src/plugins/catalog-manifest.test.ts +43 -0
  293. package/src/plugins/catalog-manifest.ts +92 -0
  294. package/src/plugins/catalog-ui.ts +20 -4
  295. package/src/plugins/catalog.ts +9 -2
  296. package/src/plugins/current-target.ts +28 -0
  297. package/src/plugins/host-contract.ts +37 -0
  298. package/src/plugins/host-link.ts +158 -0
  299. package/src/plugins/host-modules.ts +61 -0
  300. package/src/plugins/loader.ts +41 -22
  301. package/src/plugins/ownership.ts +1 -0
  302. package/src/plugins/prediction-markets/index.tsx +1 -0
  303. package/src/plugins/registry/context.ts +3 -0
  304. package/src/plugins/registry/contributions.ts +27 -0
  305. package/src/plugins/registry/index.test.ts +25 -0
  306. package/src/plugins/registry/index.ts +8 -0
  307. package/src/plugins/registry/pane-settings.ts +6 -13
  308. package/src/plugins/seed.test.ts +83 -0
  309. package/src/plugins/seed.ts +80 -0
  310. package/src/public/broker.ts +31 -0
  311. package/src/public/market-data.ts +9 -0
  312. package/src/public/pane-hooks.ts +57 -0
  313. package/src/public/public-api.test.ts +285 -0
  314. package/src/public/react.ts +62 -0
  315. package/src/public/test-support.ts +23 -0
  316. package/src/public/time-series.ts +8 -0
  317. package/src/public/utils.ts +77 -0
  318. package/src/remote/layout-helpers.ts +6 -8
  319. package/src/remote/resources.ts +2 -0
  320. package/src/remote/schema.ts +1 -0
  321. package/src/remote/semantic-tree.test.tsx +105 -0
  322. package/src/remote/semantic-tree.tsx +53 -35
  323. package/src/renderers/browser/main.tsx +6 -0
  324. package/src/renderers/cloudflare/worker.test.ts +19 -0
  325. package/src/renderers/cloudflare/worker.ts +1 -1
  326. package/src/renderers/electrobun/bun/external-plugins.ts +140 -0
  327. package/src/renderers/electrobun/bun/index.ts +5 -2
  328. package/src/renderers/electrobun/shared/protocol.ts +21 -0
  329. package/src/renderers/electrobun/view/build-assets.ts +0 -1
  330. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +51 -1
  331. package/src/renderers/electrobun/view/external-plugins.test.ts +45 -0
  332. package/src/renderers/electrobun/view/external-plugins.ts +63 -0
  333. package/src/renderers/electrobun/view/host/ascii-text.test.ts +48 -0
  334. package/src/renderers/electrobun/view/host/ascii-text.ts +11 -1
  335. package/src/renderers/electrobun/view/host/chart-surface.tsx +38 -32
  336. package/src/renderers/electrobun/view/host/mouse.ts +16 -2
  337. package/src/renderers/electrobun/view/main.tsx +27 -2
  338. package/src/renderers/electrobun/view/styles.css +5 -0
  339. package/src/renderers/electrobun/view/toast-host.tsx +18 -0
  340. package/src/renderers/opentui/chart-surface.tsx +5 -1
  341. package/src/renderers/opentui/host.tsx +16 -2
  342. package/src/renderers/opentui/interaction-performance.test.ts +79 -0
  343. package/src/renderers/opentui/interaction-performance.ts +188 -0
  344. package/src/renderers/opentui/start.tsx +26 -1
  345. package/src/renderers/opentui/test-utils.tsx +13 -0
  346. package/src/renderers/opentui/toast-host.tsx +26 -2
  347. package/src/renderers/opentui/ui-host.tsx +1 -0
  348. package/src/sources/provider-router/search.test.ts +191 -0
  349. package/src/sources/provider-router/search.ts +92 -39
  350. package/src/state/app/context/index.tsx +2 -0
  351. package/src/state/app/context/selector.test.tsx +33 -1
  352. package/src/state/hooks/quote-streaming.test.tsx +93 -0
  353. package/src/state/hooks/quote-streaming.ts +106 -30
  354. package/src/state/pane-table-export-registry.ts +19 -0
  355. package/src/theme/color-utils.ts +1 -1
  356. package/src/theme/colors.ts +50 -0
  357. package/src/theme/themes.test.ts +15 -2
  358. package/src/theme/themes.ts +19 -1
  359. package/src/tickers/search/index.test.ts +26 -0
  360. package/src/tickers/search/index.ts +42 -17
  361. package/src/tickers/search/ranking.ts +14 -0
  362. package/src/time-series/chart-data.test.ts +216 -0
  363. package/src/time-series/resolution.test.ts +25 -26
  364. package/src/time-series/resolution.ts +41 -10
  365. package/src/time-series/resolve.ts +7 -0
  366. package/src/time-series/types.ts +3 -1
  367. package/src/time-series/use-chart-resolution.ts +5 -0
  368. package/src/types/config.ts +123 -3
  369. package/src/types/data-provider.ts +11 -0
  370. package/src/types/headless.ts +161 -0
  371. package/src/types/plugin.ts +102 -0
  372. package/src/ui/host.tsx +12 -1
  373. package/src/ui/index.tsx +1 -0
  374. package/src/ui/toast.tsx +8 -4
  375. package/src/utils/format.ts +35 -0
  376. package/src/utils/fuzzy-search.test.ts +94 -0
  377. package/src/utils/fuzzy-search.ts +81 -22
  378. package/src/utils/shortcut-labels.ts +14 -0
  379. package/src/components/chart/core/axis-format.ts +0 -157
  380. package/src/components/chart/core/index.test.ts +0 -1075
  381. package/src/components/chart/core/projection.ts +0 -357
  382. package/src/components/chart/core/render-utils.ts +0 -4
  383. package/src/components/chart/core/renderer.ts +0 -244
  384. package/src/components/chart/core/scene.ts +0 -180
  385. package/src/components/chart/core/time-axis.ts +0 -330
  386. package/src/components/chart/cursor-motion.ts +0 -47
  387. package/src/components/chart/indicators/types.ts +0 -26
  388. package/src/components/chart/market-session.ts +0 -176
  389. package/src/components/chart/multi-line/renderer.test.ts +0 -83
  390. package/src/components/chart/multi-line/renderer.ts +0 -161
  391. package/src/components/chart/multi-line/scene.ts +0 -188
  392. package/src/components/chart/native/raster/layout.ts +0 -129
  393. package/src/components/chart/native/raster/price-chart.ts +0 -244
  394. package/src/components/chart/rendering/chart-draw.ts +0 -270
  395. package/src/components/chart/rendering/geometry.ts +0 -95
  396. package/src/components/chart/rendering/pixel-buffer.ts +0 -267
  397. package/src/components/chart/scatter-chart-renderer.test.ts +0 -31
  398. package/src/components/chart/scatter-chart-renderer.ts +0 -223
  399. package/src/components/chart/static/chart/surface.tsx +0 -358
  400. package/src/components/command-bar/routes/root/article-results.test.ts +0 -83
  401. package/src/components/command-bar/routes/root/article-results.ts +0 -55
  402. package/src/plugins/builtin/news/wire/article-search.test.ts +0 -72
  403. package/src/plugins/builtin/news/wire/article-search.ts +0 -140
  404. package/src/plugins/builtin/substack/api/auth.ts +0 -185
  405. package/src/plugins/builtin/substack/api/cache.ts +0 -82
  406. package/src/plugins/builtin/substack/api/loaders.ts +0 -170
  407. package/src/plugins/builtin/substack/api/store.ts +0 -186
  408. package/src/plugins/builtin/substack/api/types.ts +0 -42
  409. package/src/plugins/builtin/substack/api.test.ts +0 -298
  410. package/src/plugins/builtin/substack/article-detail.tsx +0 -397
  411. package/src/plugins/builtin/substack/article-stack.tsx +0 -133
  412. package/src/plugins/builtin/substack/content.ts +0 -478
  413. package/src/plugins/builtin/substack/feed-tabs.tsx +0 -44
  414. package/src/plugins/builtin/substack/index.tsx +0 -49
  415. package/src/plugins/builtin/substack/login-view.tsx +0 -126
  416. package/src/plugins/builtin/substack/model.test.ts +0 -155
  417. package/src/plugins/builtin/substack/normalize.ts +0 -343
  418. package/src/plugins/builtin/substack/pane-footer.ts +0 -52
  419. package/src/plugins/builtin/substack/pane-state.ts +0 -170
  420. package/src/plugins/builtin/substack/pane.tsx +0 -547
  421. package/src/plugins/builtin/substack/read-state.ts +0 -30
  422. package/src/plugins/builtin/substack/table.ts +0 -111
  423. package/src/plugins/builtin/substack/types.ts +0 -71
  424. package/src/plugins/builtin/substack/utils.ts +0 -131
  425. package/src/plugins/builtin/ticker-detail/data-panes/provider-search.tsx +0 -229
  426. package/src/plugins/ibkr/account-cache.test.ts +0 -102
  427. package/src/plugins/ibkr/account-cache.ts +0 -24
  428. package/src/plugins/ibkr/broker-adapter.ts +0 -286
  429. package/src/plugins/ibkr/config.test.ts +0 -79
  430. package/src/plugins/ibkr/config.ts +0 -250
  431. package/src/plugins/ibkr/dialogs.tsx +0 -40
  432. package/src/plugins/ibkr/flex/index.test.ts +0 -264
  433. package/src/plugins/ibkr/flex/index.ts +0 -367
  434. package/src/plugins/ibkr/flex/statement-client.ts +0 -235
  435. package/src/plugins/ibkr/fundamental-parser.ts +0 -149
  436. package/src/plugins/ibkr/gateway/account-loaders.ts +0 -266
  437. package/src/plugins/ibkr/gateway/account-summary.ts +0 -164
  438. package/src/plugins/ibkr/gateway/client-lock.ts +0 -154
  439. package/src/plugins/ibkr/gateway/connection-events.ts +0 -114
  440. package/src/plugins/ibkr/gateway/connection.ts +0 -152
  441. package/src/plugins/ibkr/gateway/contracts.ts +0 -132
  442. package/src/plugins/ibkr/gateway/fundamentals.ts +0 -83
  443. package/src/plugins/ibkr/gateway/helpers.ts +0 -33
  444. package/src/plugins/ibkr/gateway/history-requests.ts +0 -158
  445. package/src/plugins/ibkr/gateway/history.ts +0 -120
  446. package/src/plugins/ibkr/gateway/instrument-lookup.ts +0 -117
  447. package/src/plugins/ibkr/gateway/market-data.ts +0 -345
  448. package/src/plugins/ibkr/gateway/order-execution.ts +0 -218
  449. package/src/plugins/ibkr/gateway/orders.ts +0 -63
  450. package/src/plugins/ibkr/gateway/price-normalization.test.ts +0 -44
  451. package/src/plugins/ibkr/gateway/price-normalization.ts +0 -50
  452. package/src/plugins/ibkr/gateway/quote-stream-controller.ts +0 -203
  453. package/src/plugins/ibkr/gateway/quote-stream.ts +0 -171
  454. package/src/plugins/ibkr/gateway/selection.ts +0 -51
  455. package/src/plugins/ibkr/gateway/service/index.test.ts +0 -675
  456. package/src/plugins/ibkr/gateway/service/index.ts +0 -429
  457. package/src/plugins/ibkr/gateway/service/lifecycle.ts +0 -191
  458. package/src/plugins/ibkr/gateway/service/manager.ts +0 -52
  459. package/src/plugins/ibkr/gateway/service/market-data.ts +0 -48
  460. package/src/plugins/ibkr/gateway/service/native-loader.ts +0 -12
  461. package/src/plugins/ibkr/gateway/service/native.ts +0 -543
  462. package/src/plugins/ibkr/gateway/timeouts.ts +0 -13
  463. package/src/plugins/ibkr/gateway/types.ts +0 -27
  464. package/src/plugins/ibkr/index.test.tsx +0 -162
  465. package/src/plugins/ibkr/index.tsx +0 -159
  466. package/src/plugins/ibkr/instance-selection.test.ts +0 -120
  467. package/src/plugins/ibkr/instance-selection.ts +0 -36
  468. package/src/plugins/ibkr/portfolio-performance.test.ts +0 -32
  469. package/src/plugins/ibkr/portfolio-performance.ts +0 -129
  470. package/src/plugins/ibkr/trade/badge.tsx +0 -28
  471. package/src/plugins/ibkr/trade/dialogs.tsx +0 -44
  472. package/src/plugins/ibkr/trade/preview-panel.tsx +0 -130
  473. package/src/plugins/ibkr/trade/tab/actions.tsx +0 -443
  474. package/src/plugins/ibkr/trade/tab/field-editors.tsx +0 -79
  475. package/src/plugins/ibkr/trade/tab/footer.ts +0 -53
  476. package/src/plugins/ibkr/trade/tab/header.tsx +0 -167
  477. package/src/plugins/ibkr/trade/tab/index.test.tsx +0 -178
  478. package/src/plugins/ibkr/trade/tab/index.tsx +0 -298
  479. package/src/plugins/ibkr/trade/tab/model.ts +0 -159
  480. package/src/plugins/ibkr/trade/tab/order-request.ts +0 -64
  481. package/src/plugins/ibkr/trade/tab/shortcuts.ts +0 -89
  482. package/src/plugins/ibkr/trade/tab/state-sync.ts +0 -86
  483. package/src/plugins/ibkr/trade/ticket-panel.tsx +0 -301
  484. package/src/plugins/ibkr/trade/utils.test.ts +0 -175
  485. package/src/plugins/ibkr/trade/utils.ts +0 -144
  486. package/src/plugins/ibkr/trading/pane-view.tsx +0 -237
  487. package/src/plugins/ibkr/trading/pane.tsx +0 -332
  488. package/src/plugins/ibkr/trading/state.test.ts +0 -109
  489. package/src/plugins/ibkr/trading/state.ts +0 -335
@@ -0,0 +1,422 @@
1
+ import { formatNumber } from "../../../utils/format";
2
+ import type { IndicatorDef, SeriesDef, ShillerField } from "./defs";
3
+
4
+ const DAY_MS = 24 * 60 * 60 * 1000;
5
+ const MILLIONS_TO_BILLIONS = 0.001;
6
+
7
+ /** Z.1 lands ~10 weeks after quarter end, then holds until the next quarter's release. */
8
+ const QUARTERLY_STALE_MS = 270 * DAY_MS;
9
+ /** Shiller republishes monthly; two missed months means something is wrong. */
10
+ const MONTHLY_STALE_MS = 75 * DAY_MS;
11
+ const DAILY_STALE_MS = 5 * DAY_MS;
12
+
13
+ function percent(value: number): string {
14
+ return `${Math.round(value)}%`;
15
+ }
16
+
17
+ function percentTenths(value: number): string {
18
+ return `${formatNumber(value, 1)}%`;
19
+ }
20
+
21
+ function ratio(value: number): string {
22
+ return formatNumber(value, 2);
23
+ }
24
+
25
+ /**
26
+ * Total US market value. FRED discontinued the WILL5000* family, so this comes
27
+ * from the cloud's own price history rather than the econ proxy.
28
+ */
29
+ const WILSHIRE_5000: SeriesDef = {
30
+ key: "W5000",
31
+ scaleToBillions: 1,
32
+ source: {
33
+ kind: "market-history",
34
+ symbol: "^W5000",
35
+ exchange: "INDEX",
36
+ startDate: "1970-01-01",
37
+ },
38
+ };
39
+
40
+ const NOMINAL_GDP: SeriesDef = {
41
+ key: "GDP",
42
+ scaleToBillions: 1,
43
+ source: { kind: "fred", seriesId: "GDP", limit: 340 },
44
+ };
45
+
46
+ const M2: SeriesDef = {
47
+ key: "M2SL",
48
+ scaleToBillions: 1,
49
+ source: { kind: "fred", seriesId: "M2SL", limit: 900 },
50
+ };
51
+
52
+ function shillerSeries(key: string, field: ShillerField): SeriesDef {
53
+ return { key, scaleToBillions: 1, source: { kind: "shiller", field } };
54
+ }
55
+
56
+ export const BUFFETT_INDICATOR: IndicatorDef = {
57
+ id: "buffett",
58
+ label: "Buffett Indicator",
59
+ shortLabel: "Buffett",
60
+ description: "US total market cap over nominal GDP.",
61
+ input: {
62
+ kind: "ratio",
63
+ numerator: WILSHIRE_5000,
64
+ denominator: NOMINAL_GDP,
65
+ levels: { numeratorLabel: "Mkt cap", denominatorLabel: "GDP" },
66
+ },
67
+ ratioScale: 100,
68
+ formatValue: percent,
69
+ axisUnit: "%",
70
+ zones: [
71
+ { max: 75, id: "significantly-undervalued", label: "Significantly Undervalued" },
72
+ { max: 90, id: "modestly-undervalued", label: "Modestly Undervalued" },
73
+ { max: 115, id: "fair", label: "Fair Valued" },
74
+ { max: 135, id: "modestly-overvalued", label: "Modestly Overvalued" },
75
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
76
+ ],
77
+ zoneScale: { min: 0, max: 250, edges: [0, 75, 90, 115, 135, 250], ticks: [0, 75, 100, 135, 250] },
78
+ reference: { value: 100, label: "parity" },
79
+ chartGridStep: 150,
80
+ trendModel: "log",
81
+ staleAfterMs: DAILY_STALE_MS,
82
+ notes: [
83
+ "Total US market value against one year of economic output. Warren Buffett called it probably the best single measure of where valuations stand at any given moment, in a December 2001 Fortune essay written with Carol Loomis.",
84
+ "Rates, buybacks, and a larger listed share of the economy have all raised what fair looks like since 2001, so read the trend deviation alongside the absolute zone.",
85
+ ],
86
+ link: {
87
+ url: "https://en.wikipedia.org/wiki/Buffett_indicator",
88
+ label: "Buffett indicator, Wikipedia",
89
+ },
90
+ };
91
+
92
+ export const TOBINS_Q: IndicatorDef = {
93
+ id: "tobins-q",
94
+ label: "Tobin's Q",
95
+ shortLabel: "Tobin Q",
96
+ description: "Corporate equity market value over replacement cost of net assets.",
97
+ input: {
98
+ kind: "ratio",
99
+ numerator: {
100
+ key: "NCBEILQ027S",
101
+ scaleToBillions: MILLIONS_TO_BILLIONS,
102
+ source: { kind: "fred", seriesId: "NCBEILQ027S", limit: 400 },
103
+ },
104
+ denominator: {
105
+ key: "TNWMVBSNNCB",
106
+ scaleToBillions: MILLIONS_TO_BILLIONS,
107
+ source: { kind: "fred", seriesId: "TNWMVBSNNCB", limit: 400 },
108
+ },
109
+ levels: { numeratorLabel: "Equities", denominatorLabel: "Net worth" },
110
+ },
111
+ ratioScale: 1,
112
+ formatValue: ratio,
113
+ axisUnit: "",
114
+ // Bands anchored on the 1945-2026 distribution: p25 0.54, median 0.93, p75 1.34.
115
+ zones: [
116
+ { max: 0.55, id: "significantly-undervalued", label: "Significantly Undervalued" },
117
+ { max: 0.8, id: "modestly-undervalued", label: "Modestly Undervalued" },
118
+ { max: 1.1, id: "fair", label: "Fair Valued" },
119
+ { max: 1.4, id: "modestly-overvalued", label: "Modestly Overvalued" },
120
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
121
+ ],
122
+ zoneScale: { min: 0, max: 2, edges: [0, 0.55, 0.8, 1.1, 1.4, 2], ticks: [0, 0.55, 1, 1.4, 2] },
123
+ reference: { value: 1, label: "replacement cost" },
124
+ chartGridStep: 0.5,
125
+ trendModel: "log",
126
+ staleAfterMs: QUARTERLY_STALE_MS,
127
+ notes: [
128
+ "Equity market value against what it would cost to rebuild the assets behind it. Q above 1 means the market pays more than replacement cost.",
129
+ "Built from the Fed's quarterly Z.1 financial accounts for nonfinancial corporate business, so it moves in quarterly steps and revises with each release.",
130
+ ],
131
+ link: { url: "https://en.wikipedia.org/wiki/Tobin%27s_q", label: "Tobin's q, Wikipedia" },
132
+ };
133
+
134
+ export const SHILLER_CAPE: IndicatorDef = {
135
+ id: "shiller-cape",
136
+ label: "Shiller CAPE",
137
+ shortLabel: "CAPE",
138
+ description: "S&P 500 price over ten years of inflation-adjusted earnings.",
139
+ input: { kind: "direct", series: shillerSeries("SHILLER_CAPE", "cape") },
140
+ ratioScale: 1,
141
+ formatValue: (value) => formatNumber(value, 1),
142
+ axisUnit: "",
143
+ // Bands anchored on the 1881-2026 distribution: p25 12.0, median 16.6, p75 21.5.
144
+ zones: [
145
+ { max: 12, id: "significantly-undervalued", label: "Significantly Undervalued" },
146
+ { max: 15, id: "modestly-undervalued", label: "Modestly Undervalued" },
147
+ { max: 22, id: "fair", label: "Fair Valued" },
148
+ { max: 30, id: "modestly-overvalued", label: "Modestly Overvalued" },
149
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
150
+ ],
151
+ zoneScale: { min: 0, max: 45, edges: [0, 12, 15, 22, 30, 45], ticks: [0, 12, 22, 30, 45] },
152
+ reference: { value: 16.6, label: "median" },
153
+ chartGridStep: 10,
154
+ trendModel: "log",
155
+ staleAfterMs: MONTHLY_STALE_MS,
156
+ notes: [
157
+ "Price divided by the average of ten years of real earnings, which smooths away the profit cycle that makes a one-year P/E swing hardest exactly when it matters most.",
158
+ "Robert Shiller's series runs back to 1881. It has spent decades above its own median without mean-reverting, so treat it as a long-horizon return signal rather than a timing tool.",
159
+ ],
160
+ link: {
161
+ url: "https://en.wikipedia.org/wiki/Cyclically_adjusted_price-to-earnings_ratio",
162
+ label: "CAPE ratio, Wikipedia",
163
+ },
164
+ };
165
+
166
+ export const EXCESS_CAPE_YIELD: IndicatorDef = {
167
+ id: "excess-cape-yield",
168
+ label: "Excess CAPE Yield",
169
+ shortLabel: "ERP (ECY)",
170
+ description: "CAPE earnings yield over the real 10-year Treasury yield.",
171
+ input: { kind: "direct", series: shillerSeries("SHILLER_ECY", "excessCapeYield") },
172
+ // Shiller publishes it as a decimal fraction; show it as a percent.
173
+ ratioScale: 100,
174
+ formatValue: percentTenths,
175
+ axisUnit: "%",
176
+ // A high excess yield means stocks are paid well over bonds, so the bands run the
177
+ // opposite way to a price ratio. Anchored on p25 1.5%, median 3.3%, p75 6.6%.
178
+ zones: [
179
+ { max: 1.5, id: "significantly-overvalued", label: "Significantly Overvalued" },
180
+ { max: 2.5, id: "modestly-overvalued", label: "Modestly Overvalued" },
181
+ { max: 4.5, id: "fair", label: "Fair Valued" },
182
+ { max: 6.5, id: "modestly-undervalued", label: "Modestly Undervalued" },
183
+ { max: null, id: "significantly-undervalued", label: "Significantly Undervalued" },
184
+ ],
185
+ zoneScale: { min: -3, max: 12, edges: [-3, 1.5, 2.5, 4.5, 6.5, 12], ticks: [-3, 1.5, 4.5, 6.5, 12] },
186
+ reference: { value: 0, label: "no premium" },
187
+ chartGridStep: 5,
188
+ // The spread has been negative, so a log fit would silently drop those years.
189
+ trendModel: "linear",
190
+ staleAfterMs: MONTHLY_STALE_MS,
191
+ notes: [
192
+ "What stocks yield over inflation-protected bonds: the CAPE earnings yield minus the real ten-year Treasury yield. It is the equity risk premium in the form Shiller publishes.",
193
+ "Unlike a price ratio, higher is cheaper. It went negative before the 1929 and 2000 peaks, when bonds out-yielded stocks outright.",
194
+ ],
195
+ link: {
196
+ url: "https://en.wikipedia.org/wiki/Equity_premium_puzzle",
197
+ label: "Equity risk premium, Wikipedia",
198
+ },
199
+ };
200
+
201
+ export const SP500_DIVIDEND_YIELD: IndicatorDef = {
202
+ id: "sp500-dividend-yield",
203
+ label: "S&P 500 Dividend Yield",
204
+ shortLabel: "Div yield",
205
+ description: "Index dividend over index price.",
206
+ input: {
207
+ kind: "ratio",
208
+ numerator: shillerSeries("SHILLER_DIVIDEND", "dividend"),
209
+ denominator: shillerSeries("SHILLER_PRICE", "price"),
210
+ },
211
+ ratioScale: 100,
212
+ formatValue: percentTenths,
213
+ axisUnit: "%",
214
+ // Higher yield is cheaper, so the bands invert. Anchored on p25 3.0%, median 4.2%.
215
+ zones: [
216
+ { max: 2, id: "significantly-overvalued", label: "Significantly Overvalued" },
217
+ { max: 3, id: "modestly-overvalued", label: "Modestly Overvalued" },
218
+ { max: 5, id: "fair", label: "Fair Valued" },
219
+ { max: 6.5, id: "modestly-undervalued", label: "Modestly Undervalued" },
220
+ { max: null, id: "significantly-undervalued", label: "Significantly Undervalued" },
221
+ ],
222
+ zoneScale: { min: 0, max: 10, edges: [0, 2, 3, 5, 6.5, 10], ticks: [0, 2, 5, 6.5, 10] },
223
+ reference: { value: 4.2, label: "median" },
224
+ chartGridStep: 4,
225
+ trendModel: "log",
226
+ staleAfterMs: MONTHLY_STALE_MS,
227
+ notes: [
228
+ "What the index pays out against what it costs. Buybacks have moved a large share of shareholder return off this line since the 1980s, so the modern level is structurally lower than the pre-1990 record.",
229
+ "Read it against its own recent decades rather than the full history for that reason.",
230
+ ],
231
+ link: { url: "https://en.wikipedia.org/wiki/Dividend_yield", label: "Dividend yield, Wikipedia" },
232
+ };
233
+
234
+ export const HOUSEHOLD_EQUITY_ALLOCATION: IndicatorDef = {
235
+ id: "household-equity-allocation",
236
+ label: "Investor Equity Allocation",
237
+ shortLabel: "Equity alloc",
238
+ description: "Share of household financial assets held in equities.",
239
+ input: {
240
+ kind: "direct",
241
+ series: {
242
+ key: "BOGZ1FL153064486Q",
243
+ scaleToBillions: 1,
244
+ source: { kind: "fred", seriesId: "BOGZ1FL153064486Q", limit: 400 },
245
+ },
246
+ },
247
+ // FRED publishes it as a percentage already, so it needs no rescaling.
248
+ ratioScale: 1,
249
+ formatValue: percentTenths,
250
+ axisUnit: "%",
251
+ // Bands anchored on the 1945-2026 distribution: p25 17.7%, median 24.3%, p75 30.0%.
252
+ zones: [
253
+ { max: 18, id: "significantly-undervalued", label: "Significantly Undervalued" },
254
+ { max: 22, id: "modestly-undervalued", label: "Modestly Undervalued" },
255
+ { max: 28, id: "fair", label: "Fair Valued" },
256
+ { max: 34, id: "modestly-overvalued", label: "Modestly Overvalued" },
257
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
258
+ ],
259
+ zoneScale: { min: 0, max: 50, edges: [0, 18, 22, 28, 34, 50], ticks: [0, 18, 28, 34, 50] },
260
+ reference: { value: 24.3, label: "median" },
261
+ chartGridStep: 10,
262
+ trendModel: "log",
263
+ staleAfterMs: QUARTERLY_STALE_MS,
264
+ notes: [
265
+ "How much of what households own sits in stocks. When investors are already all-in there is little cash left to bid prices higher, which is why this has tracked ten-year forward returns more closely than any price ratio.",
266
+ "From the Fed's quarterly Z.1 accounts, counting equities held directly and through funds.",
267
+ ],
268
+ link: {
269
+ url: "https://fred.stlouisfed.org/series/BOGZ1FL153064486Q",
270
+ label: "Household equity share, FRED",
271
+ },
272
+ };
273
+
274
+ export const MARKET_CAP_TO_M2: IndicatorDef = {
275
+ id: "market-cap-m2",
276
+ label: "Market Cap to M2",
277
+ shortLabel: "Cap / M2",
278
+ description: "US total market cap against the money supply.",
279
+ input: {
280
+ kind: "ratio",
281
+ numerator: WILSHIRE_5000,
282
+ denominator: M2,
283
+ levels: { numeratorLabel: "Mkt cap", denominatorLabel: "M2" },
284
+ },
285
+ ratioScale: 100,
286
+ formatValue: percent,
287
+ axisUnit: "%",
288
+ // Bands anchored on the 1989-2026 distribution: p25 142%, median 180%, p75 206%.
289
+ zones: [
290
+ { max: 130, id: "significantly-undervalued", label: "Significantly Undervalued" },
291
+ { max: 160, id: "modestly-undervalued", label: "Modestly Undervalued" },
292
+ { max: 210, id: "fair", label: "Fair Valued" },
293
+ { max: 260, id: "modestly-overvalued", label: "Modestly Overvalued" },
294
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
295
+ ],
296
+ zoneScale: { min: 0, max: 350, edges: [0, 130, 160, 210, 260, 350], ticks: [0, 130, 210, 260, 350] },
297
+ reference: { value: 180, label: "median" },
298
+ chartGridStep: 100,
299
+ trendModel: "log",
300
+ staleAfterMs: DAILY_STALE_MS,
301
+ notes: [
302
+ "Market value measured against the money supply rather than output, which is the liquidity-adjusted read on the same question the Buffett indicator asks.",
303
+ "It falls when the Fed expands M2 faster than equities rise, so the 2020 surge shows up here as cheapening even while price ratios were climbing.",
304
+ ],
305
+ link: { url: "https://fred.stlouisfed.org/series/M2SL", label: "M2 money stock, FRED" },
306
+ };
307
+
308
+ export const MARGIN_DEBT_TO_GDP: IndicatorDef = {
309
+ id: "margin-debt-gdp",
310
+ label: "Margin Debt to GDP",
311
+ shortLabel: "Margin debt",
312
+ description: "Borrowing against securities, against the size of the economy.",
313
+ input: {
314
+ kind: "ratio",
315
+ numerator: {
316
+ key: "BOGZ1FL663067003Q",
317
+ scaleToBillions: MILLIONS_TO_BILLIONS,
318
+ source: { kind: "fred", seriesId: "BOGZ1FL663067003Q", limit: 400 },
319
+ },
320
+ denominator: NOMINAL_GDP,
321
+ levels: { numeratorLabel: "Margin debt", denominatorLabel: "GDP" },
322
+ },
323
+ ratioScale: 100,
324
+ formatValue: percentTenths,
325
+ axisUnit: "%",
326
+ // Bands anchored on the 1945-2026 distribution: p25 0.71%, median 0.92%, p75 1.40%.
327
+ zones: [
328
+ { max: 0.7, id: "significantly-undervalued", label: "Significantly Undervalued" },
329
+ { max: 0.9, id: "modestly-undervalued", label: "Modestly Undervalued" },
330
+ { max: 1.4, id: "fair", label: "Fair Valued" },
331
+ { max: 1.8, id: "modestly-overvalued", label: "Modestly Overvalued" },
332
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
333
+ ],
334
+ zoneScale: { min: 0, max: 3, edges: [0, 0.7, 0.9, 1.4, 1.8, 3], ticks: [0, 0.9, 1.4, 1.8, 3] },
335
+ reference: { value: 0.92, label: "median" },
336
+ chartGridStep: 1,
337
+ trendModel: "log",
338
+ staleAfterMs: QUARTERLY_STALE_MS,
339
+ notes: [
340
+ "How much investors have borrowed against their holdings. Leverage is what turns a decline into forced selling, so it is froth rather than value, but it peaks where valuations do.",
341
+ "Its two highest readings are the first quarter of 2000 and the third of 2008. From the Fed's Z.1 accounts, which reach further back than FINRA's own margin table.",
342
+ ],
343
+ link: {
344
+ url: "https://fred.stlouisfed.org/series/BOGZ1FL663067003Q",
345
+ label: "Margin account receivables, FRED",
346
+ },
347
+ };
348
+
349
+ export const MARKET_CAP_TO_PROFITS: IndicatorDef = {
350
+ id: "market-cap-profits",
351
+ label: "Market Cap to Corporate Profits",
352
+ shortLabel: "Cap / profits",
353
+ description: "US total market cap over after-tax corporate profits.",
354
+ input: {
355
+ kind: "ratio",
356
+ numerator: WILSHIRE_5000,
357
+ denominator: {
358
+ key: "CPROFIT",
359
+ scaleToBillions: 1,
360
+ source: { kind: "fred", seriesId: "CPROFIT", limit: 400 },
361
+ },
362
+ levels: { numeratorLabel: "Mkt cap", denominatorLabel: "Profits" },
363
+ },
364
+ ratioScale: 1,
365
+ formatValue: (value) => formatNumber(value, 1),
366
+ axisUnit: "",
367
+ // Bands anchored on the 1989-2026 distribution: p25 7.9, median 9.1, p75 12.3.
368
+ zones: [
369
+ { max: 8, id: "significantly-undervalued", label: "Significantly Undervalued" },
370
+ { max: 9, id: "modestly-undervalued", label: "Modestly Undervalued" },
371
+ { max: 12, id: "fair", label: "Fair Valued" },
372
+ { max: 15, id: "modestly-overvalued", label: "Modestly Overvalued" },
373
+ { max: null, id: "significantly-overvalued", label: "Significantly Overvalued" },
374
+ ],
375
+ zoneScale: { min: 0, max: 20, edges: [0, 8, 9, 12, 15, 20], ticks: [0, 9, 12, 15, 20] },
376
+ reference: { value: 9.1, label: "median" },
377
+ chartGridStep: 5,
378
+ trendModel: "log",
379
+ staleAfterMs: DAILY_STALE_MS,
380
+ notes: [
381
+ "A price-to-earnings ratio for the whole economy rather than the index, using what every US corporation actually earned after tax.",
382
+ "Profits are near a record share of GDP, so this asks whether the market is dear even against unusually good earnings. Its highest reading is March 2000.",
383
+ ],
384
+ link: {
385
+ url: "https://fred.stlouisfed.org/series/CPROFIT",
386
+ label: "Corporate profits after tax, FRED",
387
+ },
388
+ };
389
+
390
+ export const INDICATORS: readonly IndicatorDef[] = [
391
+ BUFFETT_INDICATOR,
392
+ SHILLER_CAPE,
393
+ EXCESS_CAPE_YIELD,
394
+ TOBINS_Q,
395
+ HOUSEHOLD_EQUITY_ALLOCATION,
396
+ SP500_DIVIDEND_YIELD,
397
+ MARGIN_DEBT_TO_GDP,
398
+ MARKET_CAP_TO_PROFITS,
399
+ MARKET_CAP_TO_M2,
400
+ ];
401
+
402
+ export const DEFAULT_INDICATOR_ID = BUFFETT_INDICATOR.id;
403
+
404
+ export function findIndicator(id: string | null | undefined): IndicatorDef {
405
+ const normalized = id?.trim().toLowerCase();
406
+ return INDICATORS.find((entry) => entry.id === normalized) ?? BUFFETT_INDICATOR;
407
+ }
408
+
409
+ /** Resolves shortcut arguments like `VAL cape` or `VAL buffett` onto an indicator. */
410
+ export function resolveIndicatorArg(arg: string | null | undefined): IndicatorDef | null {
411
+ const query = arg?.trim().toLowerCase();
412
+ if (!query) return null;
413
+ const direct = INDICATORS.find((entry) => entry.id === query);
414
+ if (direct) return direct;
415
+ return INDICATORS.find((entry) =>
416
+ entry.shortLabel.toLowerCase() === query
417
+ || entry.label.toLowerCase() === query
418
+ || entry.id.startsWith(query)
419
+ || entry.label.toLowerCase().startsWith(query)
420
+ || entry.shortLabel.toLowerCase().startsWith(query)
421
+ ) ?? null;
422
+ }