gloomberb 0.17.6 → 0.18.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.
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/package.json +6 -1
- package/patches/electrobun@1.18.1.patch +74 -0
- package/src/account/auth-model.ts +3 -2
- package/src/account/device-signin-dialog.tsx +38 -13
- package/src/account/device-signin.ts +2 -1
- package/src/account/upgrade-dialog.tsx +6 -2
- package/src/api-client/askg.ts +5 -3
- package/src/api-client/bank-figures.ts +73 -0
- package/src/api-client/credit-boards.ts +21 -1
- package/src/api-client/crypto-markets.ts +88 -1
- package/src/api-client/data.ts +104 -4
- package/src/api-client/debt-maturities.ts +18 -0
- package/src/api-client/equity-screener.ts +3 -0
- package/src/api-client/errors.ts +13 -0
- package/src/api-client/fund-facts.ts +72 -0
- package/src/api-client/futures-curve.ts +26 -3
- package/src/api-client/geo.ts +11 -1
- package/src/api-client/index.ts +25 -2
- package/src/api-client/insider-signals.ts +95 -11
- package/src/api-client/normalizers.ts +1 -0
- package/src/api-client/paths.ts +20 -1
- package/src/api-client/request.ts +11 -3
- package/src/api-client/research-activity.ts +15 -8
- package/src/api-client/socket.ts +6 -3
- package/src/api-client/supply-chain-graph.ts +2 -2
- package/src/api-client/supply-chain.ts +8 -0
- package/src/api-client/tape.ts +12 -0
- package/src/api-client/types.ts +66 -2
- package/src/api-client/upgrade-experiment.ts +4 -3
- package/src/api-client/wall-experiments.ts +5 -3
- package/src/api-client/wall-summary.ts +3 -1
- package/src/api-client/web-experiments.ts +5 -2
- package/src/api-client/yield-curves.ts +17 -0
- package/src/app/command-bar-intro.ts +38 -0
- package/src/app/keybindings/actions.ts +1 -1
- package/src/app/pane-runtime/pane-template-runtime.ts +35 -7
- package/src/app/pane-runtime/plugin-bindings.ts +4 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +4 -14
- package/src/app/pane-runtime/ticker-open-target.ts +31 -0
- package/src/app/runtime/desktop-deeplink.ts +3 -4
- package/src/app/runtime/plugin-bindings.ts +3 -2
- package/src/app/runtime/startup.ts +3 -4
- package/src/app/runtime/ticker-refresh.ts +13 -12
- package/src/app/runtime/update.ts +3 -2
- package/src/architecture/core-builtin-allowlist.json +0 -3
- package/src/architecture/silent-catch-allowlist.json +3 -0
- package/src/architecture/ui-literals-allowlist.json +186 -0
- package/src/architecture/ui-tokens-allowlist.json +40 -0
- package/src/ask-gloom/pane-context.ts +3 -1
- package/src/brokers/signed-in/catalog.ts +2 -1
- package/src/brokers/signed-in/client.ts +7 -2
- package/src/brokers/signed-in/sign-in-dialog.tsx +120 -26
- package/src/brokers/signed-in/sign-in.ts +22 -20
- package/src/brokers/sync-broker-instance.ts +2 -1
- package/src/capabilities/chart-series.ts +2 -0
- package/src/capabilities/registry.ts +1 -3
- package/src/cli/bank-section.ts +147 -0
- package/src/cli/base-converter.ts +5 -2
- package/src/cli/board-coins.ts +70 -0
- package/src/cli/commands/fred-series.ts +90 -0
- package/src/cli/commands/market.ts +340 -69
- package/src/cli/commands/news-search.ts +35 -2
- package/src/cli/commands/options-chain.ts +7 -5
- package/src/cli/commands/options-leaps.ts +3 -3
- package/src/cli/commands/overview.ts +78 -29
- package/src/cli/commands/plugins.ts +1 -0
- package/src/cli/commands/search.ts +87 -24
- package/src/cli/commands/system.ts +5 -2
- package/src/cli/commands/ticker.ts +337 -60
- package/src/cli/context.ts +2 -1
- package/src/cli/desktop-pane-shot.ts +11 -3
- package/src/cli/earnings-calendar.ts +2 -1
- package/src/cli/errors.ts +10 -0
- package/src/cli/export-source.ts +18 -3
- package/src/cli/glossary.ts +196 -14
- package/src/cli/history-rows.ts +60 -9
- package/src/cli/index-roots.ts +26 -0
- package/src/cli/index.ts +34 -9
- package/src/cli/known-gaps.ts +156 -22
- package/src/cli/listing-arg.ts +156 -12
- package/src/cli/listing-suggestion.ts +4 -2
- package/src/cli/name-entries.ts +76 -0
- package/src/cli/not-a-ticker.ts +15 -6
- package/src/cli/pane-functions/access-gate.ts +22 -0
- package/src/cli/pane-functions/capabilities.ts +62 -4
- package/src/cli/pane-functions/catalog.ts +94 -39
- package/src/cli/pane-functions/data.ts +6 -5
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +3 -3
- package/src/cli/pane-functions/freshness.ts +49 -8
- package/src/cli/pane-functions/function-help.ts +13 -10
- package/src/cli/pane-functions/headless.ts +177 -42
- package/src/cli/pane-functions/index.ts +64 -8
- package/src/cli/pane-functions/options.ts +17 -3
- package/src/cli/pane-functions/report-notices.ts +17 -3
- package/src/cli/pane-functions/resolver.ts +48 -13
- package/src/cli/pane-functions/screenshot.ts +124 -23
- package/src/cli/pane-functions/shot-options.ts +68 -0
- package/src/cli/perpetual-contract.ts +3 -1
- package/src/cli/report-tables.ts +10 -2
- package/src/cli/staged-tickers.ts +5 -0
- package/src/cli/statement-filings.ts +261 -0
- package/src/cli/symbol-args.ts +47 -8
- package/src/cli/symbol-list.ts +9 -2
- package/src/cli/symbol-rows.ts +269 -29
- package/src/cli/ticker-resolution.ts +148 -34
- package/src/cli/treasury-yields.ts +86 -0
- package/src/cli/types.ts +3 -0
- package/src/cli/uncovered-instrument.ts +20 -0
- package/src/components/chart/composite/axis-overlays.tsx +16 -9
- package/src/components/chart/composite/composite-chart.tsx +85 -6
- package/src/components/chart/composite/downsample.ts +19 -3
- package/src/components/chart/composite/format.ts +3 -0
- package/src/components/chart/composite/legend.tsx +155 -76
- package/src/components/chart/composite/panel-bitmap.ts +8 -2
- package/src/components/chart/composite/panel-surface.tsx +3 -3
- package/src/components/chart/composite/toolbar.tsx +12 -7
- package/src/components/chart/composite/types.ts +6 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +28 -1
- package/src/components/chart/curve/curve-surface.tsx +1 -1
- package/src/components/chart/static/series.ts +39 -0
- package/src/components/chart/static/trail-chart-surface.tsx +2 -1
- package/src/components/command-bar/commands/collection-list.ts +45 -15
- package/src/components/command-bar/commands/collection.ts +10 -3
- package/src/components/command-bar/commands/registry.ts +2 -2
- package/src/components/command-bar/list/badge.ts +4 -3
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +1 -1
- package/src/components/command-bar/panel/index.tsx +19 -8
- package/src/components/command-bar/panel/native-surface.ts +6 -4
- package/src/components/command-bar/panel/prompt-example.ts +22 -0
- package/src/components/command-bar/routes/root/provider-search.ts +3 -9
- package/src/components/command-bar/routes/root/results.ts +13 -0
- package/src/components/command-bar/routes/root/start-here.ts +90 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +42 -3
- package/src/components/command-bar/routes/ticker-search/route.ts +3 -10
- package/src/components/command-bar/theme-picker.tsx +3 -1
- package/src/components/command-bar/workflow/builtin.ts +5 -1
- package/src/components/command-bar/workflow/collection-actions.ts +21 -12
- package/src/components/command-bar/workflow/ops.ts +21 -1
- package/src/{plugins/builtin/portfolio-list/command-bar.ts → components/command-bar/workflow/portfolio-position.ts} +42 -9
- package/src/components/command-bar/workflow/tickers.ts +6 -4
- package/src/components/feedback-dialog.tsx +1 -1
- package/src/components/form-modal/broker-step.tsx +7 -63
- package/src/components/form-modal/content.tsx +7 -2
- package/src/components/form-modal/field-row.tsx +6 -8
- package/src/components/form-modal/host.tsx +3 -3
- package/src/components/form-modal/model.ts +3 -0
- package/src/components/form-modal/routes.ts +17 -2
- package/src/components/index.ts +6 -6
- package/src/components/input-search-bar.tsx +43 -6
- package/src/components/layout/detached-pane-shell.tsx +0 -1
- package/src/components/layout/floating-pane.tsx +0 -1
- package/src/components/layout/header.tsx +8 -7
- package/src/components/layout/pane/footer/index.tsx +7 -4
- package/src/components/layout/pane/footer/model.ts +28 -2
- package/src/components/layout/pane/header.tsx +9 -19
- package/src/components/layout/pane/index.tsx +0 -1
- package/src/components/layout/pane/instrument-coverage-gate.tsx +57 -0
- package/src/components/layout/pane/pane-tabs.tsx +4 -3
- package/src/components/layout/pane/sizing.ts +9 -0
- package/src/components/layout/pane/ticker-fate-gate.tsx +8 -2
- package/src/components/layout/shell/pane/capture.ts +44 -20
- package/src/components/layout/status-bar.tsx +3 -6
- package/src/components/markdown-text.tsx +17 -2
- package/src/components/market-board/index.tsx +19 -8
- package/src/components/metric-treemap/heat-surface.tsx +2 -7
- package/src/components/onboarding/account-step/qr-panel.tsx +5 -2
- package/src/components/onboarding/onboarding-frame.tsx +24 -21
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +20 -10
- package/src/components/onboarding/wizard-positions.ts +40 -11
- package/src/components/pane-settings-dialog/desktop.tsx +12 -50
- package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -1
- package/src/components/price-performance.tsx +18 -2
- package/src/components/reader/article-reader.tsx +11 -10
- package/src/components/reader/detail-reader.tsx +9 -5
- package/src/components/reader/reader-text.tsx +51 -24
- package/src/components/sign-in-code-panel.tsx +129 -75
- package/src/components/ticker/badge/index.tsx +2 -1
- package/src/components/ui/action-row.tsx +5 -2
- package/src/components/ui/audio-player.tsx +70 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/data-table/index.tsx +4 -2
- package/src/components/ui/data-table/types.ts +11 -0
- package/src/components/ui/detail-scroll-body.tsx +1 -1
- package/src/components/ui/dialog-actions.tsx +1 -21
- package/src/components/ui/display.tsx +13 -5
- package/src/components/ui/external-link.tsx +4 -2
- package/src/components/ui/fields.tsx +12 -0
- package/src/components/ui/figure.tsx +5 -3
- package/src/components/ui/frame.tsx +40 -6
- package/src/components/ui/icon.tsx +4 -0
- package/src/components/ui/index.ts +4 -1
- package/src/components/ui/list-view.tsx +8 -0
- package/src/components/ui/prose.tsx +97 -25
- package/src/components/ui/query-bar-keys.tsx +3 -1
- package/src/components/ui/query-bar.tsx +6 -0
- package/src/components/ui/quote.ts +42 -0
- package/src/components/ui/range-track.tsx +15 -2
- package/src/components/ui/reveal-in-scroll-box.ts +21 -3
- package/src/components/ui/select-button.tsx +38 -3
- package/src/components/ui/status.tsx +73 -4
- package/src/components/ui/table-layout.ts +20 -0
- package/src/components/use-pinned-moment.ts +19 -0
- package/src/core/app-runtime.ts +2 -2
- package/src/core/state/app/instrument.ts +18 -1
- package/src/core/state/app/layout.ts +6 -0
- package/src/core/state/app/state.ts +14 -2
- package/src/data/cached-query.ts +1 -1
- package/src/data/config/chart-settings.ts +3 -1
- package/src/data/config/home.ts +4 -1
- package/src/data/config/store/node.ts +9 -4
- package/src/data/config/store/normalize.ts +9 -0
- package/src/data/json-storage.ts +6 -3
- package/src/data/json-ticker-repository.ts +3 -1
- package/src/data/plugin-cache.ts +5 -1
- package/src/data/sqlite/json.ts +3 -1
- package/src/data/ticker-repository.ts +5 -2
- package/src/feedback/diagnostics.ts +2 -6
- package/src/i18n/es.ts +86 -6
- package/src/i18n/index.ts +3 -9
- package/src/i18n/ja.ts +86 -6
- package/src/i18n/ko.ts +86 -6
- package/src/i18n/zh-cn.ts +86 -6
- package/src/i18n/zh-tw.ts +86 -6
- package/src/layout-marketplace/gallery-desktop.tsx +8 -4
- package/src/market-data/bars-per-year.ts +43 -0
- package/src/market-data/bond-funds.ts +85 -0
- package/src/market-data/coordinator/auxiliary.ts +5 -2
- package/src/market-data/coordinator/index.ts +6 -5
- package/src/market-data/futures-contract.ts +102 -5
- package/src/market-data/hooks.tsx +20 -11
- package/src/market-data/market/bar-period.ts +36 -0
- package/src/market-data/market/format.ts +5 -13
- package/src/market-data/market/freshness.ts +1 -3
- package/src/market-data/market/index-level.ts +51 -0
- package/src/market-data/model-dividend-yield.ts +57 -16
- package/src/market-data/quotes/live-valuation.ts +48 -2
- package/src/market-data/realized-volatility.ts +16 -7
- package/src/market-data/tax-equivalent.ts +344 -0
- package/src/news/aggregator.ts +4 -2
- package/src/notifications/notification-log.ts +5 -3
- package/src/plugins/auto-update-node.ts +1 -0
- package/src/plugins/builtin/account-management/footer.ts +1 -1
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +71 -19
- package/src/plugins/builtin/account-management/trial-cancel.ts +40 -0
- package/src/plugins/builtin/alerts/cli.ts +7 -18
- package/src/plugins/builtin/alerts/constants.ts +8 -0
- package/src/plugins/builtin/alerts/event-rows.ts +16 -0
- package/src/plugins/builtin/alerts/events-pane.tsx +2 -14
- package/src/plugins/builtin/alerts/headless.ts +182 -0
- package/src/plugins/builtin/alerts/index.tsx +3 -0
- package/src/plugins/builtin/alerts/pane.tsx +1 -7
- package/src/plugins/builtin/alerts/storage.ts +17 -1
- package/src/plugins/builtin/analytics/index.tsx +6 -1
- package/src/plugins/builtin/analytics/metrics.ts +47 -9
- package/src/plugins/builtin/analytics/risk-headless.ts +14 -2
- package/src/plugins/builtin/analytics/risk-math.ts +83 -0
- package/src/plugins/builtin/analytics/risk-model.ts +97 -4
- package/src/plugins/builtin/analytics/risk-pane.tsx +11 -6
- package/src/plugins/builtin/analytics/sector-model.ts +14 -3
- package/src/plugins/builtin/awards/headless.ts +6 -5
- package/src/plugins/builtin/awards/index.tsx +1 -1
- package/src/plugins/builtin/backtest/client.ts +38 -8
- package/src/plugins/builtin/backtest/engine.ts +25 -13
- package/src/plugins/builtin/backtest/export.ts +27 -0
- package/src/plugins/builtin/backtest/format.ts +19 -3
- package/src/plugins/builtin/backtest/headless.ts +42 -28
- package/src/plugins/builtin/backtest/index.tsx +3 -0
- package/src/plugins/builtin/backtest/pane.tsx +39 -10
- package/src/plugins/builtin/backtest/report.ts +160 -0
- package/src/plugins/builtin/backtest/rules.ts +2 -0
- package/src/plugins/builtin/backtest/window.ts +112 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +3 -2
- package/src/plugins/builtin/broker-manager/add-flow.tsx +4 -4
- package/src/plugins/builtin/catalysts/headless.ts +24 -13
- package/src/plugins/builtin/catalysts/index.tsx +4 -2
- package/src/plugins/builtin/catalysts/model.ts +18 -1
- package/src/plugins/builtin/catalysts/pane.tsx +2 -2
- package/src/plugins/builtin/cds/client.ts +28 -5
- package/src/plugins/builtin/cds/headless.ts +183 -31
- package/src/plugins/builtin/cds/index.tsx +1 -1
- package/src/plugins/builtin/cds/model.ts +229 -53
- package/src/plugins/builtin/cds/pane.tsx +82 -26
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -1
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +39 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +77 -0
- package/src/plugins/builtin/chart-composer/chart-spec.ts +15 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +22 -2
- package/src/plugins/builtin/chart-composer/editor/desktop-view.tsx +2 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -2
- package/src/plugins/builtin/chart-composer/headless.ts +99 -21
- package/src/plugins/builtin/chart-composer/index.tsx +70 -13
- package/src/plugins/builtin/chart-composer/pane.tsx +65 -15
- package/src/plugins/builtin/chart-composer/presets.ts +79 -11
- package/src/plugins/builtin/chart-composer/series-catalog.ts +50 -14
- package/src/plugins/builtin/chart-composer/series-expression.ts +9 -7
- package/src/plugins/builtin/chart-composer/series-listings.ts +178 -0
- package/src/plugins/builtin/chart-composer/session-range.ts +87 -0
- package/src/plugins/builtin/chat/attachments/desktop.tsx +4 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +49 -14
- package/src/plugins/builtin/chat/content/composer.tsx +22 -1
- package/src/plugins/builtin/chat/content/index.tsx +35 -5
- package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -0
- package/src/plugins/builtin/chat/content/shortcuts.ts +32 -13
- package/src/plugins/builtin/chat/content/snapshot.ts +29 -6
- package/src/plugins/builtin/chat/ghost-user.ts +11 -3
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +13 -5
- package/src/plugins/builtin/chat/message/header.tsx +26 -4
- package/src/plugins/builtin/chat/message/pane-chip.tsx +131 -35
- package/src/plugins/builtin/chat/message/render-state.ts +28 -1
- package/src/plugins/builtin/chat/message/terminal.tsx +9 -3
- package/src/plugins/builtin/chat/pane-links/composer.ts +87 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +1 -1
- package/src/plugins/builtin/chat/share/flow.tsx +9 -73
- package/src/plugins/builtin/cloud/askg/controller.ts +5 -3
- package/src/plugins/builtin/cloud/askg/executor.ts +3 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +16 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +6 -2
- package/src/plugins/builtin/cloud/auth-actions.tsx +4 -2
- package/src/plugins/builtin/cloud/company-picker.tsx +21 -26
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +5 -3
- package/src/plugins/builtin/cloud/plugin.tsx +2 -0
- package/src/plugins/builtin/cloud/team/module.tsx +5 -1
- package/src/plugins/builtin/cloud/team/pane.tsx +11 -4
- package/src/plugins/builtin/cloud/team/views.ts +11 -4
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +9 -4
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +3 -2
- package/src/plugins/builtin/cloud/thesis/detail.tsx +2 -1
- package/src/plugins/builtin/cloud/thesis/exposure.ts +3 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +3 -2
- package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +2 -1
- package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +2 -1
- package/src/plugins/builtin/cloud/verification-status-widget.tsx +2 -1
- package/src/plugins/builtin/commodities-energy/index.tsx +8 -5
- package/src/plugins/builtin/commodities-energy/view-state.ts +11 -0
- package/src/plugins/builtin/company-attention/headless.ts +15 -7
- package/src/plugins/builtin/company-attention/index.tsx +1 -1
- package/src/plugins/builtin/company-attention/model.ts +49 -4
- package/src/plugins/builtin/company-attention/pane.tsx +11 -9
- package/src/plugins/builtin/company-kpis/headless.ts +4 -3
- package/src/plugins/builtin/company-kpis/index.tsx +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +9 -3
- package/src/plugins/builtin/congress-trades/headless.ts +23 -2
- package/src/plugins/builtin/correlation/relationship/pane.tsx +18 -46
- package/src/plugins/builtin/cot/headless.ts +5 -2
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +41 -13
- package/src/plugins/builtin/credit-boards/client.ts +9 -2
- package/src/plugins/builtin/credit-boards/headless.ts +93 -27
- package/src/plugins/builtin/credit-boards/index.tsx +15 -4
- package/src/plugins/builtin/credit-boards/model.ts +105 -6
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +14 -3
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -1
- package/src/plugins/builtin/credit-documents/index.tsx +3 -0
- package/src/plugins/builtin/credit-documents/model.ts +3 -10
- package/src/plugins/builtin/crypto-board/client.ts +152 -2
- package/src/plugins/builtin/crypto-board/headless.ts +138 -19
- package/src/plugins/builtin/crypto-board/index.tsx +5 -3
- package/src/plugins/builtin/crypto-board/model.ts +210 -12
- package/src/plugins/builtin/crypto-board/pane.tsx +148 -9
- package/src/plugins/builtin/crypto-board/series.ts +52 -1
- package/src/plugins/builtin/crypto-board/supply.ts +123 -0
- package/src/plugins/builtin/debt-maturities/client.ts +54 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +27 -3
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/model.ts +58 -13
- package/src/plugins/builtin/debt-maturities/pane.tsx +47 -7
- package/src/plugins/builtin/dividend-yield/client.ts +42 -36
- package/src/plugins/builtin/dividend-yield/headless.ts +113 -18
- package/src/plugins/builtin/dividend-yield/index.tsx +5 -2
- package/src/plugins/builtin/dividend-yield/pane.tsx +37 -13
- package/src/plugins/builtin/dividend-yield/provider-client.ts +7 -3
- package/src/plugins/builtin/dividend-yield/ranking.ts +187 -0
- package/src/plugins/builtin/dividend-yield/reference-price.ts +28 -5
- package/src/plugins/builtin/dividend-yield/types.ts +6 -1
- package/src/plugins/builtin/dividend-yield/view.ts +1 -1
- package/src/plugins/builtin/docs/blocks.tsx +54 -8
- package/src/plugins/builtin/docs/pane.tsx +8 -13
- package/src/plugins/builtin/earnings/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/data.ts +51 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -0
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
- package/src/plugins/builtin/earnings-calls/model.ts +97 -0
- package/src/plugins/builtin/earnings-calls/pane.tsx +107 -7
- package/src/plugins/builtin/earnings-calls/transcript-view.tsx +140 -22
- package/src/plugins/builtin/earnings-calls/use-call-playback.ts +194 -0
- package/src/plugins/builtin/econ/calendar-model.ts +22 -0
- package/src/plugins/builtin/econ/calendar-source.ts +35 -0
- package/src/plugins/builtin/econ/index.tsx +40 -8
- package/src/plugins/builtin/econ-statistics/defs.ts +7 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +8 -1
- package/src/plugins/builtin/econ-statistics/headless.ts +26 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +4 -2
- package/src/plugins/builtin/econ-statistics/stats.ts +10 -0
- package/src/plugins/builtin/econ-statistics/view.ts +19 -0
- package/src/plugins/builtin/equity-screener/client.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +46 -4
- package/src/plugins/builtin/equity-screener/pane.tsx +3 -0
- package/src/plugins/builtin/estimate-revisions/client.ts +32 -22
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
- package/src/plugins/builtin/estimate-revisions/pane.tsx +5 -3
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/editor.tsx +3 -3
- package/src/plugins/builtin/fear-greed/index.tsx +9 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures/index.tsx +2 -2
- package/src/plugins/builtin/futures/model.ts +34 -21
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-board-terms.ts +2 -2
- package/src/plugins/builtin/futures-curve/headless.ts +4 -2
- package/src/plugins/builtin/futures-curve/model.ts +5 -7
- package/src/plugins/builtin/help/index.tsx +55 -8
- package/src/plugins/builtin/help/shortcut-table.tsx +15 -2
- package/src/plugins/builtin/holders/headless.ts +12 -0
- package/src/plugins/builtin/insider/headless.ts +311 -41
- package/src/plugins/builtin/insider/index.tsx +280 -106
- package/src/plugins/builtin/insider/insiders.tsx +224 -0
- package/src/plugins/builtin/insider/signals-cells.tsx +52 -0
- package/src/plugins/builtin/insider/signals-client.ts +135 -11
- package/src/plugins/builtin/insider/signals-model.ts +628 -56
- package/src/plugins/builtin/insider/signals.tsx +283 -83
- package/src/plugins/builtin/ipo-calendar/headless.ts +17 -7
- package/src/plugins/builtin/ipo-calendar/index.tsx +23 -3
- package/src/plugins/builtin/ipo-calendar/model.ts +84 -36
- package/src/plugins/builtin/ipo-calendar/pane.tsx +20 -8
- package/src/plugins/builtin/iv-history/headless.ts +2 -0
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/jobs/index.tsx +1 -0
- package/src/plugins/builtin/jodi/headless.ts +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +1 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +3 -1
- package/src/plugins/builtin/market-valuation/pane.tsx +1 -1
- package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +31 -57
- package/src/plugins/builtin/mna/distress/headless.ts +2 -1
- package/src/plugins/builtin/mna/headless.ts +14 -2
- package/src/plugins/builtin/mna/index.tsx +1 -0
- package/src/plugins/builtin/news/headless.ts +4 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +5 -3
- package/src/plugins/builtin/news/wire/news/table.tsx +57 -11
- package/src/plugins/builtin/notes/cli.ts +8 -4
- package/src/plugins/builtin/notes/files.ts +66 -20
- package/src/plugins/builtin/notes/migration.ts +18 -6
- package/src/plugins/builtin/notes/owner.tsx +3 -2
- package/src/plugins/builtin/notes/quick-notes-pane.tsx +3 -2
- package/src/plugins/builtin/options-scenario/client.ts +7 -4
- package/src/plugins/builtin/options-scenario/headless.ts +5 -3
- package/src/plugins/builtin/pe-band/index.tsx +1 -1
- package/src/plugins/builtin/pe-band/model.ts +1 -15
- package/src/plugins/builtin/perps/headless.ts +30 -13
- package/src/plugins/builtin/perps/model.ts +45 -3
- package/src/plugins/builtin/perps/pane.tsx +7 -7
- package/src/plugins/builtin/portfolio-list/cell-version.ts +10 -4
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +128 -14
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +108 -46
- package/src/plugins/builtin/portfolio-list/cli/render.ts +368 -45
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +8 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +24 -34
- package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +151 -29
- package/src/plugins/builtin/portfolio-list/income.ts +296 -0
- package/src/plugins/builtin/portfolio-list/metrics.ts +2 -2
- package/src/plugins/builtin/portfolio-list/pane/futures-terms.ts +58 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +27 -10
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +47 -28
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +10 -3
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +26 -4
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +31 -3
- package/src/plugins/builtin/portfolio-list/table.tsx +25 -5
- package/src/plugins/builtin/power/prices-headless.ts +2 -1
- package/src/plugins/builtin/realized-vol/chart-model.ts +29 -5
- package/src/plugins/builtin/realized-vol/charts.tsx +14 -8
- package/src/plugins/builtin/realized-vol/evidence.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +6 -4
- package/src/plugins/builtin/realized-vol/model.ts +5 -1
- package/src/plugins/builtin/realized-vol/pane.tsx +31 -11
- package/src/plugins/builtin/realized-vol/settings.ts +1 -1
- package/src/plugins/builtin/research/analyst-headless.ts +4 -0
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -0
- package/src/plugins/builtin/research/event-model.ts +22 -2
- package/src/plugins/builtin/research/headless-schema.ts +1 -0
- package/src/plugins/builtin/research/headless.ts +3 -0
- package/src/plugins/builtin/research/index.tsx +3 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +27 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +2 -0
- package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +9 -6
- package/src/plugins/builtin/reverse-dcf/index.tsx +2 -2
- package/src/plugins/builtin/reverse-dcf/model.ts +51 -4
- package/src/plugins/builtin/reverse-dcf/pane.tsx +23 -10
- package/src/plugins/builtin/risk-factors/headless.ts +7 -0
- package/src/plugins/builtin/risk-factors/index.tsx +1 -0
- package/src/plugins/builtin/scanner/feed.ts +5 -3
- package/src/plugins/builtin/scanner/headless.ts +9 -57
- package/src/plugins/builtin/scanner/index.ts +1 -2
- package/src/plugins/builtin/sec/forms.ts +2 -6
- package/src/plugins/builtin/sec/fund-facts-view.tsx +53 -0
- package/src/plugins/builtin/sec/fund-facts.ts +328 -0
- package/src/plugins/builtin/sec/headless.ts +140 -44
- package/src/plugins/builtin/sec/index.tsx +95 -30
- package/src/plugins/builtin/sec/model.ts +2 -44
- package/src/plugins/builtin/shared/headless-options.ts +10 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +3 -1
- package/src/plugins/builtin/shared/move-rank.ts +108 -0
- package/src/plugins/builtin/shared/report-freshness.ts +25 -9
- package/src/plugins/builtin/shared/scanner-capture.ts +95 -0
- package/src/plugins/builtin/shared/treasury-cutoffs.ts +15 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +1 -0
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -0
- package/src/plugins/builtin/shared/volatility-indices.ts +32 -0
- package/src/plugins/builtin/short-interest/headless.ts +3 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +2 -2
- package/src/plugins/builtin/social-mentions/client.ts +8 -1
- package/src/plugins/builtin/social-mentions/pane.tsx +8 -6
- package/src/plugins/builtin/supply-chain/client.ts +12 -3
- package/src/plugins/builtin/supply-chain/disclosure-quote.tsx +9 -5
- package/src/plugins/builtin/supply-chain/evidence.ts +3 -1
- package/src/plugins/builtin/supply-chain/flow-layout.ts +2 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +23 -16
- package/src/plugins/builtin/supply-chain/graph-client.ts +8 -5
- package/src/plugins/builtin/supply-chain/graph-evidence.ts +1 -1
- package/src/plugins/builtin/supply-chain/graph-model.ts +10 -2
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +9 -7
- package/src/plugins/builtin/supply-chain/graph.tsx +8 -6
- package/src/plugins/builtin/supply-chain/headless.ts +69 -27
- package/src/plugins/builtin/supply-chain/index.tsx +1 -1
- package/src/plugins/builtin/supply-chain/model.ts +76 -15
- package/src/plugins/builtin/supply-chain/pane.tsx +29 -15
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +5 -4
- package/src/plugins/builtin/themes/model.ts +2 -5
- package/src/plugins/builtin/thirteenf/api.ts +50 -2
- package/src/plugins/builtin/thirteenf/data.ts +250 -11
- package/src/plugins/builtin/thirteenf/headless.ts +311 -28
- package/src/plugins/builtin/thirteenf/index.tsx +4 -1
- package/src/plugins/builtin/thirteenf/model.ts +244 -19
- package/src/plugins/builtin/thirteenf/overlap-pane.tsx +133 -33
- package/src/plugins/builtin/thirteenf/overlap.ts +1 -1
- package/src/plugins/builtin/thirteenf/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/report-notes.ts +78 -0
- package/src/plugins/builtin/thirteenf/types.ts +49 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +22 -8
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +17 -1
- package/src/plugins/builtin/ticker-detail/financials/model.ts +2 -42
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/headless.ts +23 -10
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +27 -3
- package/src/plugins/builtin/ticker-detail/overview/dividend.ts +60 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +46 -9
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +36 -3
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +18 -19
- package/src/plugins/builtin/time-sales/client.ts +7 -4
- package/src/plugins/builtin/time-sales/headless.ts +71 -22
- package/src/plugins/builtin/time-sales/model.ts +12 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -7
- package/src/plugins/builtin/time-sales/window.ts +128 -0
- package/src/plugins/builtin/trace-bonds/client.ts +351 -33
- package/src/plugins/builtin/trace-bonds/headless.ts +60 -22
- package/src/plugins/builtin/trace-bonds/index.tsx +4 -2
- package/src/plugins/builtin/trace-bonds/model.ts +27 -25
- package/src/plugins/builtin/trace-bonds/pane.tsx +63 -45
- package/src/plugins/builtin/treasury-auctions/cache.ts +61 -15
- package/src/plugins/builtin/treasury-auctions/client.ts +45 -10
- package/src/plugins/builtin/treasury-auctions/headless.ts +35 -13
- package/src/plugins/builtin/treasury-auctions/index.tsx +5 -2
- package/src/plugins/builtin/treasury-auctions/model.ts +20 -16
- package/src/plugins/builtin/treasury-auctions/pane.tsx +29 -12
- package/src/plugins/builtin/vol-surface/charts.tsx +2 -1
- package/src/plugins/builtin/vol-surface/headless.ts +3 -2
- package/src/plugins/builtin/vol-surface/pane.tsx +2 -1
- package/src/plugins/builtin/vol-surface/stored.ts +4 -7
- package/src/plugins/builtin/volatility/chart-model.ts +16 -15
- package/src/plugins/builtin/volatility/charts.tsx +5 -5
- package/src/plugins/builtin/volatility/client.ts +73 -2
- package/src/plugins/builtin/volatility/evidence.ts +13 -14
- package/src/plugins/builtin/volatility/headless.ts +13 -7
- package/src/plugins/builtin/volatility/index.tsx +1 -1
- package/src/plugins/builtin/volatility/model.ts +104 -38
- package/src/plugins/builtin/volatility/pane.tsx +42 -24
- package/src/plugins/builtin/volatility/series.ts +22 -13
- package/src/plugins/builtin/world-venue-map/geo-series.ts +9 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +8 -5
- package/src/plugins/builtin/world-venue-map/index.ts +16 -2
- package/src/plugins/builtin/world-venue-map/map.tsx +13 -17
- package/src/plugins/builtin/yield-curve/curves.ts +29 -5
- package/src/plugins/builtin/yield-curve/headless.ts +41 -8
- package/src/plugins/builtin/yield-curve/history.ts +5 -5
- package/src/plugins/builtin/yield-curve/index.tsx +30 -13
- package/src/plugins/compat.ts +3 -1
- package/src/plugins/dependencies.ts +8 -2
- package/src/plugins/host-link.ts +12 -5
- package/src/plugins/installer.ts +16 -7
- package/src/plugins/loader.ts +9 -2
- package/src/plugins/marketplace/activation.ts +10 -4
- package/src/plugins/registry/host-actions.ts +3 -0
- package/src/plugins/registry/index.ts +3 -1
- package/src/{plugins/builtin/portfolio-list → portfolio}/allocation.ts +74 -12
- package/src/{plugins/builtin/portfolio-list → portfolio}/column-values.ts +140 -53
- package/src/portfolio/futures-positions.ts +213 -0
- package/src/portfolio/futures-terms.ts +75 -0
- package/src/portfolio/manual-lots.ts +78 -0
- package/src/portfolio/mutations.ts +54 -10
- package/src/portfolio/position-metrics.ts +44 -10
- package/src/portfolio/valuation-basis.ts +31 -4
- package/src/public/__snapshots__/public-api.test.ts.snap +4 -0
- package/src/public/time-series.ts +2 -1
- package/src/remote/confirm-change.tsx +2 -1
- package/src/remote/server.ts +1 -1
- package/src/remote/watchlist.ts +9 -1
- package/src/renderers/dom/data-table/row.tsx +1 -1
- package/src/renderers/dom/desktop/audio-player.tsx +312 -0
- package/src/renderers/dom/desktop/control-styles.ts +17 -82
- package/src/renderers/dom/desktop/controls.tsx +39 -63
- package/src/renderers/dom/desktop/dialog-actions.tsx +13 -53
- package/src/renderers/dom/desktop/icons.tsx +8 -0
- package/src/renderers/dom/desktop/list-view.tsx +6 -6
- package/src/renderers/dom/desktop/popover.tsx +0 -3
- package/src/renderers/dom/desktop/query-bar.tsx +6 -4
- package/src/renderers/dom/desktop/select-field.tsx +9 -8
- package/src/renderers/dom/desktop/stack-header.ts +3 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -2
- package/src/renderers/dom/host/chart-surface.tsx +3 -3
- package/src/renderers/dom/host/size-observer.ts +33 -4
- package/src/renderers/dom/host/surface-3d.tsx +3 -2
- package/src/renderers/dom/host/surface-fit.ts +4 -1
- package/src/renderers/dom/host/tabs.tsx +22 -132
- package/src/renderers/dom/styles.css +358 -160
- package/src/renderers/electrobun/bun/core-capabilities.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +43 -1
- package/src/renderers/electrobun/bun/desktop/workspace/requests.ts +5 -1
- package/src/renderers/electrobun/shared/rpc-codec.ts +7 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +21 -17
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/desktop/window/bridge.ts +6 -8
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +18 -0
- package/src/series/capability.ts +1 -0
- package/src/series/files.ts +9 -3
- package/src/series/registry.ts +40 -14
- package/src/series/resolve.ts +121 -18
- package/src/series/standalone.ts +3 -2
- package/src/series/types.ts +55 -1
- package/src/series/validate.ts +39 -0
- package/src/shares/api.ts +26 -7
- package/src/shares/bug-report-dialog.tsx +2 -2
- package/src/shares/bug-report-flow.tsx +4 -7
- package/src/shares/capture-flow.ts +5 -4
- package/src/shares/capture-preview.tsx +2 -2
- package/src/shares/chat.ts +7 -27
- package/src/shares/flow.tsx +86 -40
- package/src/shares/location.ts +1 -3
- package/src/shares/pane-image.ts +11 -9
- package/src/shares/pane.ts +5 -2
- package/src/shares/payload.ts +1 -1
- package/src/shares/personal-pane.ts +3 -3
- package/src/shares/portable-layout.ts +9 -2
- package/src/shares/ready.ts +42 -0
- package/src/shares/test-harness.ts +62 -0
- package/src/sources/gloomberb-cloud/batched-lookups.ts +73 -0
- package/src/sources/gloomberb-cloud/index.ts +64 -12
- package/src/sources/gloomberb-cloud/normalizers.ts +31 -2
- package/src/sources/gloomberb-cloud/perpetuals.ts +20 -1
- package/src/sources/history-omitted.ts +34 -0
- package/src/sources/history-result.ts +3 -0
- package/src/sources/history-retention.ts +1 -1
- package/src/sources/provider-errors.ts +43 -1
- package/src/sources/provider-router/batches.ts +3 -2
- package/src/sources/provider-router/cache.ts +2 -1
- package/src/sources/provider-router/cached-routes.ts +9 -3
- package/src/sources/provider-router/history.ts +9 -8
- package/src/sources/provider-router/index.ts +18 -3
- package/src/sources/provider-router/primary.ts +5 -4
- package/src/sources/provider-router/quote-route.ts +3 -1
- package/src/sources/provider-router/routing.ts +2 -1
- package/src/sources/provider-router/search.ts +47 -13
- package/src/sources/provider-router/streaming.ts +7 -4
- package/src/sources/sec-edgar.ts +1 -3
- package/src/state/app/context/index.tsx +9 -13
- package/src/state/app/tab-cursor.ts +149 -12
- package/src/state/hooks/quote-streaming.ts +3 -2
- package/src/state/hooks/session-snapshot.ts +3 -2
- package/src/state/persist-scheduler.ts +12 -4
- package/src/sync/controller.ts +22 -1
- package/src/sync/core-contributors.ts +58 -15
- package/src/team/collections-sync.ts +14 -4
- package/src/team/collections.ts +40 -11
- package/src/team/store.ts +5 -4
- package/src/telemetry/attention-counts.ts +8 -2
- package/src/telemetry/crash-reports-dom.ts +3 -0
- package/src/telemetry/crash-reports-node.ts +7 -4
- package/src/telemetry/crash-reports.ts +11 -11
- package/src/telemetry/usage-counts.ts +16 -12
- package/src/theme/colors.ts +2 -0
- package/src/theme/font-scale.ts +2 -0
- package/src/theme/ui-tokens.ts +71 -0
- package/src/tickers/batched-lookups.ts +186 -0
- package/src/tickers/company-name-listing.ts +97 -0
- package/src/tickers/company-name.ts +13 -0
- package/src/tickers/instrument-coverage.ts +112 -0
- package/src/tickers/listing-fate.ts +49 -9
- package/src/tickers/listing-venues.ts +24 -5
- package/src/tickers/open-target.ts +13 -5
- package/src/tickers/search/index.ts +112 -35
- package/src/tickers/search/ranking.ts +49 -1
- package/src/tickers/terminal-codes.ts +79 -0
- package/src/tickers/ticker-changes.ts +74 -3
- package/src/tickers/us-listing.ts +2 -1
- package/src/time-series/chart-data.ts +79 -8
- package/src/time-series/fundamentals.ts +55 -7
- package/src/time-series/ice-credit.ts +17 -2
- package/src/time-series/live-bars.ts +21 -8
- package/src/time-series/live-quotes.ts +2 -3
- package/src/time-series/price-comparison.ts +6 -1
- package/src/time-series/resolve.ts +65 -10
- package/src/time-series/spec.ts +2 -1
- package/src/time-series/studies.ts +3 -3
- package/src/time-series/types.ts +22 -0
- package/src/time-series/use-chart-resolution.ts +2 -1
- package/src/types/config.ts +7 -0
- package/src/types/data-provider.ts +20 -0
- package/src/types/headless.ts +142 -1
- package/src/types/instrument.ts +6 -0
- package/src/types/plugin.ts +32 -9
- package/src/types/price-history.ts +5 -0
- package/src/types/ticker-changes.ts +19 -0
- package/src/types/ticker.ts +10 -2
- package/src/ui/context-menu.tsx +2 -0
- package/src/ui/host.tsx +40 -4
- package/src/ui/measured-cells.ts +13 -7
- package/src/ui/qr.ts +7 -5
- package/src/updater/index.ts +5 -5
- package/src/utils/calendar-date.ts +86 -27
- package/src/utils/currency-units.ts +17 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/dividend-cash.ts +48 -0
- package/src/utils/dom-screenshot-rasters.ts +3 -1
- package/src/utils/dom-screenshot.ts +14 -10
- package/src/utils/exchange-rate-snapshot.ts +9 -4
- package/src/utils/external-url.ts +1 -0
- package/src/utils/fiscal-period.ts +47 -0
- package/src/utils/format.ts +5 -2
- package/src/utils/forward-dividend.ts +160 -11
- package/src/utils/futures-generic.ts +34 -8
- package/src/utils/http-proxy-response.ts +2 -1
- package/src/utils/local-utc-offset.ts +2 -0
- package/src/utils/log-failure.ts +31 -0
- package/src/utils/option-expiry.ts +12 -12
- package/src/utils/price-history-integrity.ts +56 -0
- package/src/utils/price-history.ts +13 -1
- package/src/utils/sec-filings.ts +245 -0
- package/src/utils/selection-clipboard.ts +5 -2
- package/src/utils/throttled-fetch.ts +1 -0
- package/src/{plugins/builtin/dividend-yield/trailing-cash.ts → utils/trailing-dividend.ts} +55 -8
- package/src/utils/url.ts +1 -0
- package/src/utils/utc-time.ts +11 -0
- package/src/plugins/builtin/chat/share/targets.ts +0 -27
- package/src/renderers/dom/host/top-surface.ts +0 -119
- package/src/shares/dialog.tsx +0 -221
- package/src/shares/live.ts +0 -19
|
@@ -3,9 +3,12 @@ import type {
|
|
|
3
3
|
HeadlessPaneContext,
|
|
4
4
|
HeadlessPaneDefinition,
|
|
5
5
|
HeadlessPaneLoadArgs,
|
|
6
|
+
HeadlessShotState,
|
|
6
7
|
} from "../../../types/plugin";
|
|
7
8
|
import { formatShortDate } from "../../../utils/datetime-format";
|
|
8
|
-
import { normalizeCik } from "./api";
|
|
9
|
+
import { normalizeCik, searchThirteenFFunds, TOP_FUNDS_MAX_LIMIT } from "./api";
|
|
10
|
+
import { ApiRequestError } from "../../../api-client/errors";
|
|
11
|
+
import { REPORT_PAGE, REPORT_ROWS } from "../shared/headless-options";
|
|
9
12
|
import { buildFundOverlap, buildManagerEtfOverlap, overlapPeriod } from "./overlap";
|
|
10
13
|
import type { FundMembersPayload, MemberFundsPayload } from "../../../api-client/members";
|
|
11
14
|
import { fetchFunds, fetchMembers } from "../members/client";
|
|
@@ -18,23 +21,33 @@ import {
|
|
|
18
21
|
cutText,
|
|
19
22
|
filedPeriodText,
|
|
20
23
|
filingDayText,
|
|
24
|
+
filingGapText,
|
|
21
25
|
filingLagDays,
|
|
26
|
+
holdingSplitNotes,
|
|
22
27
|
isOptionType,
|
|
23
28
|
isStaleFiling,
|
|
24
29
|
markedPositionType,
|
|
25
30
|
OPTION_ROWS_NOTE,
|
|
26
31
|
restatedValuesText,
|
|
32
|
+
splitAdjustedText,
|
|
33
|
+
splitUnreadText,
|
|
27
34
|
staleFilingText,
|
|
28
35
|
staleFundsText,
|
|
29
36
|
summarizeTickerHoldings,
|
|
30
37
|
THIRTEENF_LIMITS,
|
|
31
38
|
THIRTEENF_MAX_LIMIT,
|
|
32
39
|
THIRTEENF_OPTIONS_NOTE,
|
|
40
|
+
uncheckedFundsText,
|
|
33
41
|
} from "./report-notes";
|
|
34
42
|
import {
|
|
35
43
|
loadBrowserRows,
|
|
44
|
+
loadFilingGap,
|
|
36
45
|
loadFundDetail,
|
|
46
|
+
corporateSplitFactor,
|
|
47
|
+
loadFundPerformance,
|
|
48
|
+
loadSplitFactors,
|
|
37
49
|
type BrowserLoadResult,
|
|
50
|
+
type FundPerformanceResult,
|
|
38
51
|
} from "./data";
|
|
39
52
|
import {
|
|
40
53
|
DEFAULT_BROWSER_SORT,
|
|
@@ -43,9 +56,13 @@ import {
|
|
|
43
56
|
DEFAULT_TIMELINE_SORT,
|
|
44
57
|
buildFundHoldingRows,
|
|
45
58
|
buildTimelineRows,
|
|
59
|
+
filingGapFor,
|
|
46
60
|
inferBrowserTabFromQuery,
|
|
47
61
|
hasComparable13FQuarter,
|
|
48
62
|
isCikQuery,
|
|
63
|
+
isTickerShapedQuery,
|
|
64
|
+
newestDueQuarter,
|
|
65
|
+
oneFundPerCik,
|
|
49
66
|
positionType,
|
|
50
67
|
quartersBehindLatest,
|
|
51
68
|
sortBrowserRows,
|
|
@@ -65,6 +82,8 @@ import {
|
|
|
65
82
|
import type {
|
|
66
83
|
FundDetailData,
|
|
67
84
|
ThirteenFBrowserTab,
|
|
85
|
+
ThirteenFFilingGap,
|
|
86
|
+
ThirteenFFund,
|
|
68
87
|
} from "./types";
|
|
69
88
|
import { finiteOrNull } from "../../../utils/guards";
|
|
70
89
|
import { SEC_FILINGS } from "../shared/report-freshness";
|
|
@@ -196,6 +215,14 @@ export interface ThirteenFHeadlessDependencies {
|
|
|
196
215
|
args: HeadlessPaneLoadArgs,
|
|
197
216
|
ctx: HeadlessPaneContext,
|
|
198
217
|
): Promise<FundDetailData>;
|
|
218
|
+
/** The split factor of each of a fund's split candidates between its two quarter ends (loadSplitFactors), for its Est P&L. */
|
|
219
|
+
loadSplitFactors?(detail: FundDetailData, ctx: HeadlessPaneContext): Promise<Map<string, number | null>>;
|
|
220
|
+
/** What a fund in a search filed for the newest quarter past its deadline, from EDGAR. */
|
|
221
|
+
loadFilingGap?(cik: string, latestPeriod: string | null | undefined, ctx: HeadlessPaneContext): Promise<ThirteenFFilingGap | null>;
|
|
222
|
+
/** 13F filers whose names contain `query`, without their reports. */
|
|
223
|
+
searchFunds?(query: string, ctx: HeadlessPaneContext): Promise<ThirteenFFund[]>;
|
|
224
|
+
/** One fund's row of the performance list (loadFundPerformance). */
|
|
225
|
+
loadPerformance?(cik: string, name: string, ctx: HeadlessPaneContext): Promise<FundPerformanceResult>;
|
|
199
226
|
/** The ETFs whose holdings files MEMB serves. */
|
|
200
227
|
loadEtfFunds?(ctx: HeadlessPaneContext): Promise<MemberFundsPayload["funds"]>;
|
|
201
228
|
/** One covered ETF's holdings file, as `fn MEMB` reads it. */
|
|
@@ -209,11 +236,26 @@ const defaultDependencies: Required<ThirteenFHeadlessDependencies> = {
|
|
|
209
236
|
ctx.signal,
|
|
210
237
|
{ limit },
|
|
211
238
|
),
|
|
212
|
-
|
|
239
|
+
// An overlap never shows a fund's missed quarter, so it does not ask EDGAR.
|
|
240
|
+
loadDetail: (cik, name, args, ctx) => loadFundDetail(cik, name, ctx.signal, { filingGap: !isOverlapLoad(args) }),
|
|
241
|
+
loadSplitFactors: (detail, ctx) => loadSplitFactors(
|
|
242
|
+
detail,
|
|
243
|
+
(ticker, after, through) => corporateSplitFactor(ctx.marketData, ticker, after, through),
|
|
244
|
+
ctx.signal,
|
|
245
|
+
),
|
|
246
|
+
loadFilingGap: (cik, latestPeriod, ctx) => loadFilingGap(cik, latestPeriod, ctx.signal),
|
|
247
|
+
searchFunds: (query, ctx) => searchThirteenFFunds(query, THIRTEENF_MAX_LIMIT, ctx.signal),
|
|
248
|
+
loadPerformance: (cik, name, ctx) => loadFundPerformance(cik, name, ctx.signal, {
|
|
249
|
+
splitFactor: (ticker, after, through) => corporateSplitFactor(ctx.marketData, ticker, after, through),
|
|
250
|
+
}),
|
|
213
251
|
loadEtfFunds: async (ctx) => (await fetchFunds(ctx.apiClient)).funds,
|
|
214
252
|
loadEtfHoldings: (ticker, ctx) => fetchMembers(ticker, ctx.apiClient),
|
|
215
253
|
};
|
|
216
254
|
|
|
255
|
+
function isOverlapLoad(args: HeadlessPaneLoadArgs): boolean {
|
|
256
|
+
return args.options.view === "overlap" || (typeof args.options.compare === "string" && args.options.compare.trim() !== "");
|
|
257
|
+
}
|
|
258
|
+
|
|
217
259
|
const VIEW_TITLES: Record<string, string> = {
|
|
218
260
|
overlap: "13F Overlap",
|
|
219
261
|
crowding: "13F Crowding",
|
|
@@ -238,12 +280,32 @@ function thirteenFTitle(args: HeadlessPaneLoadArgs, metadata: Record<string, unk
|
|
|
238
280
|
return [VIEW_TITLES[view] ?? "13F Funds", subject].filter(Boolean).join(" | ");
|
|
239
281
|
}
|
|
240
282
|
|
|
283
|
+
/** The browser's columns: the performance list's prior quarters in place of Rows and Filed when it has them, and Est 13F on it alone. */
|
|
284
|
+
function browserColumns(tab: ThirteenFBrowserTab, rows: readonly { priorReturns?: Array<{ quarter: string }> }[]): HeadlessPaneColumn[] {
|
|
285
|
+
const history = rows[0]?.priorReturns ?? [];
|
|
286
|
+
if (history.length) {
|
|
287
|
+
return [...BROWSER_COLUMNS.filter(column => !["filedAsOfDate", "tableEntryTotal"].includes(column.key)), ...history.map((point, index) => ({ key: `return${index + 1}`, header: point.quarter, align: "right" as const, format: (value: unknown) => formatRawPercentMaybe(typeof value === "number" ? value : null) }))];
|
|
288
|
+
}
|
|
289
|
+
return tab === "performance" ? BROWSER_COLUMNS : BROWSER_COLUMNS.filter(column => column.key !== "estQuarterReturn");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** `2026-03-31 and 2026-06-30`: the two quarter ends a fund's own estimate compares. */
|
|
293
|
+
function detailPeriods(period: string | undefined): string | null {
|
|
294
|
+
const end = period ? new Date(`${period}T00:00:00Z`) : null;
|
|
295
|
+
if (!end || !Number.isFinite(end.getTime())) return null;
|
|
296
|
+
const start = new Date(Date.UTC(end.getUTCFullYear(), Math.floor(end.getUTCMonth() / 3) * 3, 0)).toISOString().slice(0, 10);
|
|
297
|
+
return `${start} and ${period}`;
|
|
298
|
+
}
|
|
299
|
+
|
|
241
300
|
function browserTab(view: HeadlessThirteenFView, query: string): ThirteenFBrowserTab {
|
|
242
301
|
if (view === "performance" || view === "funds" || view === "latest") return view;
|
|
243
302
|
if (view === "by-ticker") return "byTicker";
|
|
244
303
|
return inferBrowserTabFromQuery(query);
|
|
245
304
|
}
|
|
246
305
|
|
|
306
|
+
/** What to search by instead, after a search that found no 13F filer. */
|
|
307
|
+
const SEARCH_HINT = 'Search by fund name or CIK, as in fn 13F "Berkshire Hathaway".';
|
|
308
|
+
|
|
247
309
|
/**
|
|
248
310
|
* The manager a fund name or CIK names: a CIK as given, else the one fund
|
|
249
311
|
* whose name matches exactly, else the only match. `search` lists funds by
|
|
@@ -252,7 +314,7 @@ function browserTab(view: HeadlessThirteenFView, query: string): ThirteenFBrowse
|
|
|
252
314
|
async function findThirteenFFund(
|
|
253
315
|
query: string,
|
|
254
316
|
search: (query: string, limit: number) => Promise<BrowserLoadResult>,
|
|
255
|
-
{ exactOnly = false }: { exactOnly?: boolean } = {},
|
|
317
|
+
{ exactOnly = false, notFound }: { exactOnly?: boolean; notFound?: string } = {},
|
|
256
318
|
): Promise<{ cik: string; name: string } | null> {
|
|
257
319
|
if (isCikQuery(query)) return { cik: normalizeCik(query), name: query };
|
|
258
320
|
// A small output limit must not hide other matching managers during lookup.
|
|
@@ -263,7 +325,7 @@ async function findThirteenFFund(
|
|
|
263
325
|
if (exactOnly) return exact.length === 1 ? { cik: exact[0]!.cik, name: exact[0]!.name } : null;
|
|
264
326
|
const fund = exact.length === 1 ? exact[0]
|
|
265
327
|
: candidates.length === 1 && !result.hasMore ? candidates[0] : undefined;
|
|
266
|
-
if (candidates.length === 0) throw new Error(`No 13F fund found for "${query}"
|
|
328
|
+
if (candidates.length === 0) throw new Error(notFound ?? `No 13F fund found for "${query}". ${SEARCH_HINT}`);
|
|
267
329
|
if (!fund) {
|
|
268
330
|
const choices = candidates.slice(0, 5).map((row) => `${row.name} (${row.cik})`).join("; ");
|
|
269
331
|
throw new Error(`Ambiguous 13F fund "${query}". Use an exact fund name or CIK: ${choices}.`);
|
|
@@ -276,9 +338,10 @@ async function resolveFund(
|
|
|
276
338
|
args: HeadlessPaneLoadArgs,
|
|
277
339
|
ctx: HeadlessPaneContext,
|
|
278
340
|
dependencies: ThirteenFHeadlessDependencies,
|
|
341
|
+
{ notFound }: { notFound?: string } = {},
|
|
279
342
|
): Promise<{ cik: string; name: string }> {
|
|
280
343
|
if (!query) throw new Error("13F holdings and filings require a fund name or CIK.");
|
|
281
|
-
return (await findThirteenFFund(query, (text, limit) => dependencies.loadBrowser("funds", text, limit, args, ctx)))!;
|
|
344
|
+
return (await findThirteenFFund(query, (text, limit) => dependencies.loadBrowser("funds", text, limit, args, ctx), { notFound }))!;
|
|
282
345
|
}
|
|
283
346
|
|
|
284
347
|
/** A word that reads as a ticker (SPY, BRK.B), not a manager's name or a CIK. */
|
|
@@ -324,6 +387,110 @@ async function resolveComparison(
|
|
|
324
387
|
|
|
325
388
|
const percentText = (value: number) => `${(value * 100).toFixed(1)}%`;
|
|
326
389
|
|
|
390
|
+
/** Funds in one search whose filings EDGAR is asked about. */
|
|
391
|
+
const FILING_GAP_LOOKUPS = 10;
|
|
392
|
+
|
|
393
|
+
/** "No 13F for Q2 2026, due 14 Aug: A, B, C and 2 more", or one fund's own line. */
|
|
394
|
+
function missingFilingsText(names: readonly string[], gap: ThirteenFFilingGap, shown = 3): string {
|
|
395
|
+
const text = filingGapText(gap);
|
|
396
|
+
if (names.length === 1) return `${names[0]}: ${text.startsWith("No ") ? `n${text.slice(1)}` : text}`;
|
|
397
|
+
return `${text}: ${names.slice(0, shown).join(", ")}${names.length > shown ? ` and ${names.length - shown} more` : ""}`;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/** What a ticker search answers when the word names no security 13F filers report; any other failure is said as one. */
|
|
401
|
+
function isTickerMiss(error: unknown): boolean {
|
|
402
|
+
return error instanceof ApiRequestError && error.status === 404;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/** What a fund's latest report misses: the quarters since it stopped filing, else what EDGAR shows for the quarter it skipped. */
|
|
406
|
+
function filingGapNotes(latestPeriod: string | null, gap: ThirteenFFilingGap | null): string[] {
|
|
407
|
+
const quartersBehind = quartersBehindLatest(latestPeriod);
|
|
408
|
+
// A filing EDGAR shows for a later quarter (a 13F-NT) says more than "nothing filed".
|
|
409
|
+
const stale = isStaleFiling(quartersBehind) && !gap?.filing;
|
|
410
|
+
return [...(stale ? [staleFilingText(quartersBehind)] : []), ...(gap && !stale ? [filingGapText(gap)] : [])];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** The holders listing's own word for a ticker it has no single CUSIP for. */
|
|
414
|
+
const TICKER_MISS_WARNING = /^(?:No CUSIP found|Ambiguous CUSIP) for /;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Filers with `word` as a whole word in their name, those it starts first:
|
|
418
|
+
* "man" in Man Group plc and Prudent Man Advisors, not in Ackerman Asset
|
|
419
|
+
* Management.
|
|
420
|
+
*/
|
|
421
|
+
function fundsNamed(word: string, funds: readonly ThirteenFFund[]): ThirteenFFund[] {
|
|
422
|
+
const escaped = word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
423
|
+
const named = new RegExp(`(?:^|[^a-z0-9])${escaped}(?:$|[^a-z0-9])`, "i");
|
|
424
|
+
const leading = new RegExp(`^${escaped}(?:$|[^a-z0-9])`, "i");
|
|
425
|
+
return oneFundPerCik(funds.filter((fund) => named.test(fund.name)))
|
|
426
|
+
.toSorted((left, right) => Number(leading.test(right.name)) - Number(leading.test(left.name)));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** The funds a lowercase word also names, each with the command that opens it, beside the ticker holders it was read as. */
|
|
430
|
+
function shadowedFundsText(word: string, funds: readonly ThirteenFFund[], shown = 3): string {
|
|
431
|
+
const listed = funds.slice(0, shown).map((fund) => `${fund.name} (fn 13F ${fund.cik})`).join("; ");
|
|
432
|
+
const more = funds.length > shown ? ` and ${funds.length - shown} more` : "";
|
|
433
|
+
return `"${word}" also names ${funds.length === 1 ? "a 13F filer" : "13F filers"}: ${listed}${more}`;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/** Where the 13F pane keeps its tabs and the overlap's second holdings. */
|
|
437
|
+
const PANE_STATE_ID = "ticker-research";
|
|
438
|
+
|
|
439
|
+
/** The crowding pane's ranking for each `--rank`. */
|
|
440
|
+
const CROWDING_RANKING: Record<string, string> = { new: "newCount", exits: "exitCount", increases: "weightChange", decreases: "decreases" };
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* How `shot` opens the 13F pane on what the report loaded: the fund a name or
|
|
444
|
+
* CIK resolved to, on the tab its view names, with the overlap's second fund
|
|
445
|
+
* or ETF. Throws for the views the pane draws only another way.
|
|
446
|
+
*/
|
|
447
|
+
function thirteenFShotState(args: HeadlessPaneLoadArgs, metadata: Record<string, unknown>): HeadlessShotState {
|
|
448
|
+
const query = typeof args.argument === "string" ? args.argument.trim() : "";
|
|
449
|
+
const view = String(metadata.view ?? "");
|
|
450
|
+
const cik = typeof metadata.cik === "string" ? metadata.cik : "";
|
|
451
|
+
// A browser list opens without a fund; a fund's tab opens on that fund, whatever name found it.
|
|
452
|
+
const browser = (paneQuery: string, state: Record<string, unknown> = {}): HeadlessShotState => ({
|
|
453
|
+
settings: { query: paneQuery, initialCik: "" },
|
|
454
|
+
pluginState: { [PANE_STATE_ID]: { browserTab: "funds", query: paneQuery, ...state } },
|
|
455
|
+
});
|
|
456
|
+
const fund = (state: Record<string, unknown>): HeadlessShotState => ({
|
|
457
|
+
settings: { initialCik: cik },
|
|
458
|
+
pluginState: { [PANE_STATE_ID]: { browserTab: "funds", ...state } },
|
|
459
|
+
});
|
|
460
|
+
if (args.options.rank != null && view !== "crowding") throw new Error(`--rank orders the crowding ranking only; the 13F pane opens ${VIEW_TITLES[view] ?? "13F Funds"} here. Drop --rank, or add --view crowding.`);
|
|
461
|
+
switch (view) {
|
|
462
|
+
case "holdings":
|
|
463
|
+
case "filings":
|
|
464
|
+
return fund({ detailTab: view });
|
|
465
|
+
case "overlap": {
|
|
466
|
+
const etf = metadata.etf as { symbol: string; ticker: string; name: string } | undefined;
|
|
467
|
+
return fund({
|
|
468
|
+
detailTab: "overlap",
|
|
469
|
+
"overlap:etf": etf ? { symbol: etf.symbol, ticker: etf.ticker, name: etf.name } : null,
|
|
470
|
+
"overlap:target": etf ? null : { cik: metadata.secondCik, name: metadata.secondFund },
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
case "crowding":
|
|
474
|
+
if (query) throw new Error(`The 13F pane draws the whole crowding ranking, not one ticker's rank. Drop "${query}" from shot, or run the report: gloomberb fn 13F ${query} --view crowding`);
|
|
475
|
+
return { pluginState: { [PANE_STATE_ID]: { browserTab: "crowding", "13f-crowding:ranking": CROWDING_RANKING[String(metadata.rank ?? "new")] ?? "newCount" } } };
|
|
476
|
+
case "performance":
|
|
477
|
+
if (cik) throw new Error(`The 13F pane draws the performance ranking, not one fund's row. Run the report for ${metadata.fund ?? cik}: gloomberb fn 13F ${cik} --view performance, or gloomberb shot 13F --view performance for the ranking.`);
|
|
478
|
+
return browser("");
|
|
479
|
+
case "latest":
|
|
480
|
+
return browser("latest");
|
|
481
|
+
case "funds":
|
|
482
|
+
return browser(query);
|
|
483
|
+
case "ticker-holdings":
|
|
484
|
+
return browser(query);
|
|
485
|
+
case "byTicker":
|
|
486
|
+
// The pane lists a ticker's holders with their positions, and their whole books only when it cannot.
|
|
487
|
+
if (String(args.options.view) !== "auto") throw new Error(`The 13F pane lists a ticker's holders with their positions. Drop --view ${args.options.view} from shot, or run the report: gloomberb fn 13F ${query} --view by-ticker`);
|
|
488
|
+
return browser(query);
|
|
489
|
+
default:
|
|
490
|
+
return {};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
327
494
|
export function createThirteenFHeadless(
|
|
328
495
|
overrides: ThirteenFHeadlessDependencies = defaultDependencies,
|
|
329
496
|
): HeadlessPaneDefinition<"rows"> {
|
|
@@ -342,7 +509,7 @@ export function createThirteenFHeadless(
|
|
|
342
509
|
// No defaults on view-specific options, so a flag the view does not use can be named as ignored.
|
|
343
510
|
{ key: "rank", description: "Crowding order (crowding view; new when left out).", type: "enum", values: [{ value: "new" }, { value: "exits" }, { value: "increases" }, { value: "decreases" }] },
|
|
344
511
|
{ key: "compare", description: "Second fund name or CIK, or an ETF ticker MEMB covers such as SPY; implies the overlap view.", type: "string" },
|
|
345
|
-
{ key: "offset", description: "Fund offset for ticker-holdings (0 when left out).", type: "integer", minimum: 0, maximum: 100000 },
|
|
512
|
+
{ key: "offset", description: "Fund offset for ticker-holdings (0 when left out).", type: "integer", minimum: 0, maximum: 100000, shot: REPORT_PAGE },
|
|
346
513
|
{
|
|
347
514
|
key: "view",
|
|
348
515
|
description: "Fund browser mode or detail tab.",
|
|
@@ -369,9 +536,11 @@ export function createThirteenFHeadless(
|
|
|
369
536
|
defaultValue: 50,
|
|
370
537
|
minimum: 1,
|
|
371
538
|
maximum: THIRTEENF_MAX_LIMIT,
|
|
539
|
+
shot: REPORT_ROWS,
|
|
372
540
|
},
|
|
373
541
|
],
|
|
374
542
|
describe: (args, result) => thirteenFTitle(args, result?.metadata),
|
|
543
|
+
shotState: async (args, load) => thirteenFShotState(args, (await load()).metadata ?? {}),
|
|
375
544
|
async load(args, ctx) {
|
|
376
545
|
const query = typeof args.argument === "string" ? args.argument.trim() : "";
|
|
377
546
|
const requestedView = String(args.options.view) as HeadlessThirteenFView;
|
|
@@ -383,14 +552,15 @@ export function createThirteenFHeadless(
|
|
|
383
552
|
const view = compare ? "overlap"
|
|
384
553
|
: requestedView !== "auto" ? requestedView
|
|
385
554
|
: isCikQuery(query) ? "holdings"
|
|
386
|
-
|
|
555
|
+
// A ticker in any case (aapl, brk.b): its holders, else a fund of that name below.
|
|
556
|
+
: isTickerShapedQuery(query) ? "ticker-holdings"
|
|
387
557
|
: requestedView;
|
|
388
558
|
// A flag the view does not use is named, never dropped without a word.
|
|
389
559
|
const flagNotices = [
|
|
390
560
|
compare && requestedView === "auto" ? "--compare implies --view overlap" : "",
|
|
391
561
|
args.options.rank != null && view !== "crowding" ? "--rank orders --view crowding only; ignored here" : "",
|
|
392
562
|
args.options.offset != null && view !== "ticker-holdings" ? "--offset pages a ticker's holders only; ignored here" : "",
|
|
393
|
-
query && (view === "latest" || view === "performance") ? `--view ${view} lists every manager; "${query}" is not used` : "",
|
|
563
|
+
query && (view === "latest" || (view === "performance" && inferBrowserTabFromQuery(query) !== "funds")) ? `--view ${view} lists every manager; "${query}" is not used` : "",
|
|
394
564
|
].filter(Boolean);
|
|
395
565
|
const limit = Number(args.options.limit);
|
|
396
566
|
if (view === "overlap") {
|
|
@@ -448,7 +618,7 @@ export function createThirteenFHeadless(
|
|
|
448
618
|
const rows = buildFundOverlap(first, second);
|
|
449
619
|
const cut = cutText(rows.length, limit, "positions");
|
|
450
620
|
const read = `${compare} read as the 13F manager ${second.name} (CIK ${second.cik})`;
|
|
451
|
-
return { columns: [{ key: "ticker", header: "Ticker" }, { key: "type", header: "Type" }, { key: "issuer", header: "Issuer" }, { key: "weight", header: "First weight", align: "right", format: weight }, { key: "comparedWeight", header: "Second weight", align: "right", format: weight }], rows: rows.slice(0, limit).map(row => ({ ...row })), errors: [...(first.warnings ?? []), ...(second.warnings ?? []), ...(!comparedPeriod ? ["No reporting quarter is loaded for both funds."] : [])], metadata: { view, comparedWith: "fund", firstFund: first.name, secondFund: second.name, firstPeriod: first.latestForm?.periodOfReport ?? null, secondPeriod: second.latestForm?.periodOfReport ?? null, comparedPeriod, shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [...flagNotices, read, [comparedPeriod ? `Quarter compared: ${comparedPeriod}` : "", cut].filter(Boolean).join(" | ")].filter(Boolean) } };
|
|
621
|
+
return { columns: [{ key: "ticker", header: "Ticker" }, { key: "type", header: "Type" }, { key: "issuer", header: "Issuer" }, { key: "weight", header: "First weight", align: "right", format: weight }, { key: "comparedWeight", header: "Second weight", align: "right", format: weight }], rows: rows.slice(0, limit).map(row => ({ ...row })), errors: [...(first.warnings ?? []), ...(second.warnings ?? []), ...(!comparedPeriod ? ["No reporting quarter is loaded for both funds."] : [])], metadata: { view, comparedWith: "fund", firstFund: first.name, cik: first.cik, secondFund: second.name, secondCik: second.cik, firstPeriod: first.latestForm?.periodOfReport ?? null, secondPeriod: second.latestForm?.periodOfReport ?? null, comparedPeriod, shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [...flagNotices, read, [comparedPeriod ? `Quarter compared: ${comparedPeriod}` : "", cut].filter(Boolean).join(" | ")].filter(Boolean) } };
|
|
452
622
|
}
|
|
453
623
|
if (view === "crowding") {
|
|
454
624
|
const { rows: sourceRows, ...metadata } = await loadCrowding(ctx.signal);
|
|
@@ -466,9 +636,19 @@ export function createThirteenFHeadless(
|
|
|
466
636
|
freshness: { asOf: metadata.period }, errors: metadata.warnings };
|
|
467
637
|
}
|
|
468
638
|
let holdings: TickerHoldings | null = null;
|
|
639
|
+
let shadowed: Promise<ThirteenFFund[]> = Promise.resolve([]);
|
|
469
640
|
if (view === "ticker-holdings") {
|
|
470
641
|
if (!query) throw new Error("13F ticker holdings requires a ticker.");
|
|
471
642
|
const ticker = query.replace(/^\$/, "").toUpperCase();
|
|
643
|
+
// A lowercase word read as a ticker may name a fund too ("ares"); asked alongside, so it costs no wait.
|
|
644
|
+
if (requestedView === "auto" && !query.startsWith("$") && query !== query.toUpperCase()) {
|
|
645
|
+
// The name search matches anywhere ("man" in every Management); the word and a space keeps it to whole words.
|
|
646
|
+
shadowed = dependencies.searchFunds(`${query} `, ctx).then((funds) => fundsNamed(query, funds)).catch((error: unknown) => {
|
|
647
|
+
if (ctx.signal?.aborted) throw error;
|
|
648
|
+
return [];
|
|
649
|
+
});
|
|
650
|
+
shadowed.catch(() => {});
|
|
651
|
+
}
|
|
472
652
|
try {
|
|
473
653
|
holdings = await loadTickerHoldings(ticker, Number(args.options.offset ?? 0), ctx.signal);
|
|
474
654
|
// The endpoint pages 25 funds at a time.
|
|
@@ -476,12 +656,15 @@ export function createThirteenFHeadless(
|
|
|
476
656
|
holdings = appendTickerHoldings(holdings, await loadTickerHoldings(ticker, holdings.nextOffset, ctx.signal));
|
|
477
657
|
}
|
|
478
658
|
} catch (error) {
|
|
479
|
-
//
|
|
659
|
+
// Only a ticker without a mapped CUSIP falls back to the holders listing; an outage is said, not read as no match.
|
|
480
660
|
if (requestedView !== "auto" || ctx.signal?.aborted) throw error;
|
|
661
|
+
if (!isTickerMiss(error))
|
|
662
|
+
throw new Error(`13F holders of ${ticker} could not be loaded: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
481
663
|
}
|
|
482
664
|
}
|
|
483
665
|
if (holdings) {
|
|
484
666
|
const { rows, ...metadata } = holdings;
|
|
667
|
+
const alsoFunds = await shadowed;
|
|
485
668
|
const offset = Number(args.options.offset ?? 0);
|
|
486
669
|
const summary = summarizeTickerHoldings({ ...metadata, offset, limit, loaded: rows });
|
|
487
670
|
const shown = rows.slice(0, limit).map(row => ({ ...row }));
|
|
@@ -503,7 +686,7 @@ export function createThirteenFHeadless(
|
|
|
503
686
|
totalValue: summary.shownValue,
|
|
504
687
|
valueScope: "shown funds",
|
|
505
688
|
valueBasis: "as reported at period end",
|
|
506
|
-
notices: [...flagNotices, ...summary.notices],
|
|
689
|
+
notices: [...flagNotices, ...summary.notices, ...(alsoFunds.length ? [shadowedFundsText(query, alsoFunds)] : [])],
|
|
507
690
|
},
|
|
508
691
|
freshness: { asOf: metadata.period },
|
|
509
692
|
errors: metadata.warnings,
|
|
@@ -514,6 +697,9 @@ export function createThirteenFHeadless(
|
|
|
514
697
|
const fund = await resolveFund(query, args, ctx, dependencies);
|
|
515
698
|
const detail = await dependencies.loadDetail(fund.cik, fund.name, args, ctx);
|
|
516
699
|
const latestPeriod = detail.latestForm?.periodOfReport ?? null;
|
|
700
|
+
const quartersBehind = quartersBehindLatest(latestPeriod);
|
|
701
|
+
const gap = detail.filingGap ?? null;
|
|
702
|
+
const gapNotes = filingGapNotes(latestPeriod, gap);
|
|
517
703
|
if (view === "filings") {
|
|
518
704
|
const all = sortTimelineRows(buildTimelineRows(detail.forms), DEFAULT_TIMELINE_SORT);
|
|
519
705
|
const rows = all
|
|
@@ -534,18 +720,19 @@ export function createThirteenFHeadless(
|
|
|
534
720
|
shown: rows.length,
|
|
535
721
|
total: all.length,
|
|
536
722
|
truncated: all.length > limit,
|
|
537
|
-
|
|
723
|
+
...(gap ? { filingGap: gap } : {}),
|
|
724
|
+
notices: [...flagNotices, [`CIK ${detail.cik}`, cut].filter(Boolean).join(" | "), ...(restated ? [restated] : []), ...gapNotes],
|
|
538
725
|
},
|
|
539
726
|
};
|
|
540
727
|
}
|
|
728
|
+
// A line that moved as across a split gets its Est P&L from its corporate actions: split-adjusted, as a trade, or none.
|
|
541
729
|
const all = sortHoldingRows(
|
|
542
|
-
buildFundHoldingRows(detail),
|
|
730
|
+
buildFundHoldingRows(detail, await dependencies.loadSplitFactors(detail, ctx)),
|
|
543
731
|
DEFAULT_HOLDING_SORT,
|
|
544
732
|
);
|
|
545
733
|
const previousPeriod = detail.previousForm?.periodOfReport ?? null;
|
|
546
734
|
const comparable = hasComparable13FQuarter(detail);
|
|
547
735
|
const filed = detail.latestForm?.filedAsOfDate || null;
|
|
548
|
-
const quartersBehind = quartersBehindLatest(latestPeriod);
|
|
549
736
|
const cut = cutText(all.length, limit, "positions, exits included");
|
|
550
737
|
// Values, weights and Est P&L read both compared quarters' filings.
|
|
551
738
|
const reportForms = (report: typeof detail.latestReport, form: typeof detail.latestForm) =>
|
|
@@ -579,6 +766,7 @@ export function createThirteenFHeadless(
|
|
|
579
766
|
latestFiled: filed,
|
|
580
767
|
filingLagDays: filingLagDays(latestPeriod, filed),
|
|
581
768
|
quartersBehind,
|
|
769
|
+
...(gap ? { filingGap: gap } : {}),
|
|
582
770
|
previousPeriod,
|
|
583
771
|
shown: rows.length,
|
|
584
772
|
total: all.length,
|
|
@@ -588,49 +776,144 @@ export function createThirteenFHeadless(
|
|
|
588
776
|
[`CIK ${detail.cik}`, filedPeriodText(latestPeriod, filed, comparable ? previousPeriod : null)].filter(Boolean).join(" | "),
|
|
589
777
|
AS_FILED_VALUE,
|
|
590
778
|
...(restated ? [restated] : []),
|
|
591
|
-
...(
|
|
779
|
+
...holdingSplitNotes(rows),
|
|
780
|
+
...gapNotes,
|
|
592
781
|
...(cut ? [`${cut[0]!.toUpperCase()}${cut.slice(1)}`] : []),
|
|
593
782
|
],
|
|
594
783
|
comparisonAvailable: comparable,
|
|
595
784
|
currentFilings: detail.latestReport?.filings.map((form) => form.accessionNumber) ?? [],
|
|
596
785
|
previousFilings: detail.previousReport?.filings.map((form) => form.accessionNumber) ?? [],
|
|
597
786
|
currentReportedValue: detail.latestReport?.complete ? detail.latestReport.tableValueTotal : null,
|
|
598
|
-
changeBasis: "Changes compare disclosed quarter-end positions, not trades. Omitted or confidential holdings can affect apparent entries and exits.",
|
|
787
|
+
changeBasis: "Changes compare disclosed quarter-end positions, not trades, with the prior shares of a line split between the filings carried across the split. Omitted or confidential holdings can affect apparent entries and exits.",
|
|
599
788
|
valueBasis: THIRTEENF_OPTIONS_NOTE,
|
|
600
|
-
estimatedPnlBasis: "Quarter-end unit-value change on overlapping reported shares; excludes options, trading costs and dividends; not actual fund P&L.",
|
|
789
|
+
estimatedPnlBasis: "Quarter-end unit-value change on overlapping reported shares, split-adjusted across a split between the filings; excludes options, trading costs and dividends; not actual fund P&L.",
|
|
601
790
|
},
|
|
602
791
|
};
|
|
603
792
|
}
|
|
604
793
|
|
|
605
|
-
|
|
606
|
-
|
|
794
|
+
// A fund's own row of the performance list, with the command that copies its basket.
|
|
795
|
+
if (view === "performance" && query && inferBrowserTabFromQuery(query) === "funds") {
|
|
796
|
+
const fund = await resolveFund(query, args, ctx, dependencies, {
|
|
797
|
+
notFound: `No 13F fund matched "${query}". For the performance ranking, run gloomberb fn 13F --view performance; for one fund, give its CIK, as in gloomberb fn 13F 0001067983 --view performance.`,
|
|
798
|
+
});
|
|
799
|
+
const performance = await dependencies.loadPerformance(fund.cik, fund.name, ctx);
|
|
800
|
+
const row = performance.rows[0]!;
|
|
801
|
+
const estimated = performance.basis === "filings" && detailPeriods(row.periodOfReport);
|
|
802
|
+
const quarter = performance.quarter;
|
|
803
|
+
// True of the ranking whenever the row is not the ranking's own figure.
|
|
804
|
+
const rankingText = performance.basis === "ranking" ? null
|
|
805
|
+
: performance.ranking === "ranked" ? `the ${quarter} ranking lists it without a return`
|
|
806
|
+
: performance.ranking === "unranked" ? `not in the ${quarter} ranking`
|
|
807
|
+
: performance.ranking === "unavailable" ? `the ${quarter} ranking did not load` : null;
|
|
808
|
+
return {
|
|
809
|
+
columns: browserColumns("performance", performance.rows),
|
|
810
|
+
rows: performance.rows.map((entry) => ({ ...entry, ...Object.fromEntries((entry.priorReturns ?? []).map((point, index) => [`return${index + 1}`, point.value])) })),
|
|
811
|
+
...(performance.warning ? { errors: [performance.warning] } : {}),
|
|
812
|
+
metadata: {
|
|
813
|
+
view: "performance",
|
|
814
|
+
query,
|
|
815
|
+
cik: row.cik,
|
|
816
|
+
fund: row.name,
|
|
817
|
+
period: performance.period ?? null,
|
|
818
|
+
quarter: performance.quarter ?? null,
|
|
819
|
+
estimateBasis: performance.basis,
|
|
820
|
+
ranking: performance.ranking,
|
|
821
|
+
...(performance.splits?.length ? { splits: performance.splits } : {}),
|
|
822
|
+
...(performance.skipped?.length ? { skipped: performance.skipped } : {}),
|
|
823
|
+
...(performance.filingGap ? { filingGap: performance.filingGap } : {}),
|
|
824
|
+
shown: 1,
|
|
825
|
+
truncated: false,
|
|
826
|
+
notices: [
|
|
827
|
+
...flagNotices,
|
|
828
|
+
estimated ? `Est 13F: from the ${estimated} filings, the Est P&L of positions held through the quarter over their value at its start${rankingText ? ` (${rankingText})` : ""}` : "",
|
|
829
|
+
performance.splits?.length ? splitAdjustedText(performance.splits) : "",
|
|
830
|
+
performance.skipped?.length ? splitUnreadText(performance.skipped, "Left out of Est 13F") : "",
|
|
831
|
+
performance.unavailable ? `No Est 13F${rankingText ? ` (${rankingText})` : ""}: ${performance.unavailable}` : "",
|
|
832
|
+
...filingGapNotes(performance.period ?? null, performance.filingGap ?? null),
|
|
833
|
+
`Copy this basket: gloomberb portfolio import --13f ${row.cik}`,
|
|
834
|
+
].filter(Boolean),
|
|
835
|
+
},
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
// Reached as "ticker-holdings" only when a ticker-shaped word had no holders: its holders' books, else funds of that name.
|
|
841
|
+
const tickerMiss = view === "ticker-holdings";
|
|
842
|
+
let tab: ThirteenFBrowserTab = tickerMiss ? "byTicker" : browserTab(view, query);
|
|
843
|
+
// The performance ranking pages at most 100 funds; a larger --limit is read as 100, and said so.
|
|
844
|
+
const viewMax = tab === "performance" ? TOP_FUNDS_MAX_LIMIT : THIRTEENF_MAX_LIMIT;
|
|
845
|
+
const rowLimit = Math.min(limit, viewMax);
|
|
846
|
+
let result = await dependencies.loadBrowser(tab, query, rowLimit, args, ctx);
|
|
607
847
|
await result.reportsLoaded;
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
848
|
+
// A holder lookup that failed is said; only a ticker with no CUSIP is a miss that moves on to fund names.
|
|
849
|
+
let tickerFailure: string | undefined;
|
|
850
|
+
if (tickerMiss && result.rows.length === 0) {
|
|
851
|
+
if (result.warning && !TICKER_MISS_WARNING.test(result.warning)) tickerFailure = result.warning;
|
|
852
|
+
tab = "funds";
|
|
853
|
+
result = await dependencies.loadBrowser(tab, query, rowLimit, args, ctx);
|
|
854
|
+
await result.reportsLoaded;
|
|
855
|
+
}
|
|
856
|
+
const more = result.hasMore || result.rows.length > rowLimit;
|
|
857
|
+
const browserRows = sortBrowserRows(result.rows, browserSortFor(DEFAULT_BROWSER_SORT, tab)).slice(0, rowLimit);
|
|
858
|
+
const warning = [tickerFailure, result.warning].filter(Boolean).join(" ") || undefined;
|
|
859
|
+
// A search finds managers behind on their filings. EDGAR says whether one filed a 13F-NT, whose holdings another manager reported.
|
|
860
|
+
const lagging = tab === "funds" ? browserRows.filter((row) => filingGapFor(row.periodOfReport, null)) : [];
|
|
861
|
+
const behind = lagging.slice(0, FILING_GAP_LOOKUPS);
|
|
862
|
+
const gaps = await Promise.all(behind.map(async (row) => {
|
|
863
|
+
const gap = await dependencies.loadFilingGap(row.cik, row.periodOfReport, ctx).catch((error: unknown) => {
|
|
864
|
+
if (ctx.signal.aborted) throw error;
|
|
865
|
+
return filingGapFor(row.periodOfReport, null);
|
|
866
|
+
});
|
|
867
|
+
return gap ? { row, gap } : null;
|
|
868
|
+
}));
|
|
869
|
+
const filed = gaps.filter((entry): entry is NonNullable<typeof entry> => !!entry?.gap.filing);
|
|
870
|
+
const filedCiks = new Set(filed.map((entry) => entry.row.cik));
|
|
871
|
+
// Managers that stopped filing; the Period column alone reads like any other.
|
|
611
872
|
const stale = tab === "funds"
|
|
612
873
|
? browserRows.flatMap((row) => {
|
|
613
874
|
const quarters = quartersBehindLatest(row.periodOfReport);
|
|
614
|
-
return isStaleFiling(quarters) ? [{ name: row.name, quarters }] : [];
|
|
875
|
+
return isStaleFiling(quarters) && !filedCiks.has(row.cik) ? [{ name: row.name, quarters }] : [];
|
|
615
876
|
})
|
|
616
877
|
: [];
|
|
878
|
+
const staleNames = new Set(stale.map((row) => row.name));
|
|
879
|
+
const missing = gaps.filter((entry): entry is NonNullable<typeof entry> => !!entry && !entry.gap.filing && !staleNames.has(entry.row.name));
|
|
880
|
+
// EDGAR's "nothing filed" and an unasked EDGAR read differently, so each is its own line.
|
|
881
|
+
const missingLines = [true, false].flatMap((checked) => {
|
|
882
|
+
const group = missing.filter((entry) => entry.gap.checked === checked);
|
|
883
|
+
return group.length ? [missingFilingsText(group.map((entry) => entry.row.name), group[0]!.gap)] : [];
|
|
884
|
+
});
|
|
885
|
+
const unasked = lagging.length - behind.length;
|
|
886
|
+
// Nothing found: say how to search, not a bare "No data.".
|
|
887
|
+
const empty = browserRows.length === 0 && !warning && query && (tab === "funds" || tab === "byTicker")
|
|
888
|
+
? `No 13F filer${isTickerShapedQuery(query) ? " or ticker" : ""} matches "${query}". ${SEARCH_HINT}`
|
|
889
|
+
: undefined;
|
|
617
890
|
return {
|
|
618
|
-
columns:
|
|
619
|
-
: tab === "performance" ? BROWSER_COLUMNS : BROWSER_COLUMNS.filter(column => column.key !== "estQuarterReturn"),
|
|
891
|
+
columns: browserColumns(tab, result.rows),
|
|
620
892
|
rows: browserRows
|
|
621
893
|
.map((row) => ({ ...row, ...Object.fromEntries((row.priorReturns ?? []).map((point, index) => [`return${index + 1}`, point.value])) })),
|
|
622
|
-
...(
|
|
894
|
+
...(empty ? { empty } : {}),
|
|
895
|
+
...(warning ? { errors: [warning] } : {}),
|
|
623
896
|
metadata: {
|
|
624
897
|
view: tab,
|
|
625
898
|
query: query || null,
|
|
626
899
|
period: result.period ?? null,
|
|
627
900
|
quarter: result.quarter ?? null,
|
|
628
901
|
hasMore: result.hasMore ?? false,
|
|
629
|
-
shown: Math.min(result.rows.length,
|
|
902
|
+
shown: Math.min(result.rows.length, rowLimit),
|
|
630
903
|
truncated: more,
|
|
904
|
+
...(limit > viewMax ? { limit: rowLimit, maxLimit: viewMax } : {}),
|
|
905
|
+
...(gaps.some(Boolean) ? { filingGaps: gaps.flatMap((entry) => entry ? [{ cik: entry.row.cik, fund: entry.row.name, ...entry.gap }] : []) } : {}),
|
|
631
906
|
notices: [
|
|
632
907
|
...flagNotices,
|
|
633
|
-
|
|
908
|
+
// An uppercase word was meant as a ticker; a lowercase one may be a fund name all along.
|
|
909
|
+
...(tickerMiss && tab === "funds" && browserRows.length && query === query.toUpperCase() ? [`No 13F holders found for the ticker ${query.replace(/^\$/, "")}; funds named like it`] : []),
|
|
910
|
+
...(more || limit > viewMax ? [[
|
|
911
|
+
`Showing the first ${Math.min(result.rows.length, rowLimit)}`,
|
|
912
|
+
limit > viewMax ? `the performance ranking stops at ${viewMax} (--limit ${limit} read as ${viewMax})` : more && rowLimit < viewMax ? `more: --limit ${viewMax}` : "",
|
|
913
|
+
].filter(Boolean).join(" | ")] : []),
|
|
914
|
+
...filed.map((entry) => `${entry.row.name}: ${filingGapText(entry.gap)}`),
|
|
915
|
+
...missingLines,
|
|
916
|
+
...(unasked > 0 ? [uncheckedFundsText(behind.length, lagging.length, newestDueQuarter().period)] : []),
|
|
634
917
|
...(stale.length ? [staleFundsText(stale)] : []),
|
|
635
918
|
],
|
|
636
919
|
},
|
|
@@ -61,7 +61,10 @@ export const thirteenFModule: PluginModule = {
|
|
|
61
61
|
paneId: THIRTEENF_PANE_ID,
|
|
62
62
|
label: "13F Funds",
|
|
63
63
|
description: "Browse institutional 13F fund filings and estimated long-book performance.",
|
|
64
|
-
keywords: [
|
|
64
|
+
keywords: [
|
|
65
|
+
"13f", "funds", "hedge funds", "holdings", "filings", "institutional",
|
|
66
|
+
"buffett", "berkshire", "overlap", "copy basket", "active share", "portfolio import",
|
|
67
|
+
],
|
|
65
68
|
shortcut: {
|
|
66
69
|
prefix: "13F",
|
|
67
70
|
argPlaceholder: "fund, ticker, or CIK",
|