gloomberb 0.16.4 → 0.16.6
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 +14 -91
- package/package.json +5 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
- package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
- package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/central-bank-rates.ts +6 -1
- package/src/api-client/chat.ts +26 -0
- package/src/api-client/credit-boards.ts +2 -0
- package/src/api-client/data.ts +73 -3
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/europe-energy.ts +106 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +13 -1
- package/src/api-client/market-discovery.ts +13 -1
- package/src/api-client/normalizers.ts +32 -0
- package/src/api-client/paths.ts +7 -0
- package/src/api-client/perps.ts +8 -0
- package/src/api-client/request.ts +9 -2
- package/src/api-client/research-activity.ts +15 -10
- package/src/api-client/socket.ts +29 -0
- package/src/api-client/themes.ts +22 -1
- package/src/api-client/types.ts +78 -2
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +50 -2
- package/src/app/keybindings/actions.ts +12 -1
- package/src/app/pane-runtime/plugin-bindings.ts +2 -2
- package/src/app/pane-runtime/ticker-open-runtime.ts +16 -6
- package/src/app/runtime/desktop-deeplink.ts +10 -5
- package/src/app/runtime/startup.ts +1 -1
- package/src/app.tsx +6 -0
- package/src/architecture/core-builtin-allowlist.json +8 -26
- package/src/ask-gloom/pane-context.ts +114 -0
- package/src/ask-gloom/pane-request.ts +70 -0
- package/src/ask-gloom/pane-text.ts +201 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
- package/src/capabilities/chart-series.ts +19 -2
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/central-bank-events.ts +23 -0
- package/src/cli/command-options.ts +17 -5
- package/src/cli/commands/crypto-hints.ts +35 -2
- package/src/cli/commands/fred-series.ts +146 -0
- package/src/cli/commands/market.ts +501 -115
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-leaps.ts +5 -2
- package/src/cli/commands/overview.ts +132 -26
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +317 -13
- package/src/cli/commands/system.ts +55 -8
- package/src/cli/commands/ticker.ts +155 -18
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +76 -7
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +7 -5
- package/src/cli/exit-codes.ts +8 -0
- package/src/cli/export-source.ts +58 -0
- package/src/cli/freshness.ts +18 -7
- package/src/cli/glossary.ts +483 -0
- package/src/cli/help.ts +10 -0
- package/src/cli/helpers.ts +2 -5
- package/src/cli/history-rows.ts +118 -7
- package/src/cli/index-roots.ts +7 -0
- package/src/cli/index.ts +29 -9
- package/src/cli/known-gaps.ts +84 -0
- package/src/cli/listing-arg.ts +551 -97
- package/src/cli/not-a-ticker.ts +24 -9
- package/src/cli/pane-functions/access-gate.ts +13 -2
- package/src/cli/pane-functions/capabilities.ts +4 -3
- package/src/cli/pane-functions/catalog.ts +214 -40
- package/src/cli/pane-functions/data.ts +42 -8
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +37 -8
- package/src/cli/pane-functions/freshness.ts +393 -49
- package/src/cli/pane-functions/function-help.ts +31 -15
- package/src/cli/pane-functions/headless.ts +98 -30
- package/src/cli/pane-functions/index.ts +101 -19
- package/src/cli/pane-functions/market-session.ts +22 -8
- package/src/cli/pane-functions/options.ts +71 -22
- package/src/cli/pane-functions/report-notices.ts +25 -7
- package/src/cli/pane-functions/report.ts +15 -8
- package/src/cli/pane-functions/resolver.ts +74 -19
- package/src/cli/pane-functions/screenshot.ts +250 -27
- package/src/cli/perpetual-contract.ts +60 -0
- package/src/cli/registry.ts +3 -1
- package/src/cli/report-tables.ts +26 -7
- package/src/cli/result.ts +45 -11
- package/src/cli/series-search.ts +111 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +27 -0
- package/src/cli/symbol-list.ts +154 -0
- package/src/cli/symbol-rows.ts +154 -0
- package/src/cli/ticker-resolution.ts +311 -27
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +14 -3
- package/src/components/chart/composite/composite-chart.tsx +71 -11
- package/src/components/chart/composite/crosshair-readout.tsx +150 -0
- package/src/components/chart/composite/downsample.ts +1 -1
- package/src/components/chart/composite/format.ts +29 -0
- package/src/components/chart/composite/interactions.ts +9 -2
- package/src/components/chart/composite/legend.tsx +100 -33
- package/src/components/chart/composite/panel-bitmap.ts +70 -35
- package/src/components/chart/composite/panel-labels.ts +18 -17
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +46 -21
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +50 -8
- package/src/components/chart/composite/scene.ts +2 -1
- package/src/components/chart/composite/time-scale.ts +26 -9
- package/src/components/chart/composite/types.ts +18 -0
- package/src/components/chart/composite/use-composite-viewport.ts +30 -2
- package/src/components/chart/native/raster/crosshair.ts +8 -3
- package/src/components/chart/native/raster/primitives.ts +85 -21
- package/src/components/chart/native/surface/manager.ts +33 -8
- package/src/components/chart/surface3d/chart.tsx +1 -1
- package/src/components/command-bar/action-runtime.ts +1 -1
- package/src/components/command-bar/commands/collection-list.ts +210 -0
- package/src/components/command-bar/commands/collection.ts +40 -1
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -0
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/routing/actions.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +42 -17
- package/src/components/layout/detached-pane-shell.tsx +68 -39
- package/src/components/layout/floating-pane.tsx +10 -1
- package/src/components/layout/header.tsx +25 -5
- package/src/components/layout/missing-pane.tsx +3 -3
- package/src/components/layout/pane/capture-stamp.ts +41 -0
- package/src/components/layout/pane/capture-status.ts +12 -0
- package/src/components/layout/pane/content.tsx +7 -13
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/keyboard.ts +3 -0
- package/src/components/layout/pane/footer/model.ts +41 -1
- package/src/components/layout/pane/header.tsx +50 -1
- package/src/components/layout/pane/index.tsx +21 -3
- package/src/components/layout/pane/sidebar.tsx +88 -21
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/cursor-occlusion.ts +2 -1
- package/src/components/layout/shell/drag/index.ts +39 -9
- package/src/components/layout/shell/drag/live.ts +61 -51
- package/src/components/layout/shell/drag/runtime.ts +54 -12
- package/src/components/layout/shell/index.tsx +84 -65
- package/src/components/layout/shell/menu.ts +14 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +32 -10
- package/src/components/layout/shell/pane/ask.ts +131 -0
- package/src/components/layout/shell/pane/capture.ts +162 -0
- package/src/components/layout/shell/pane/layers.tsx +218 -50
- package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
- package/src/components/layout/shell/shortcuts.ts +21 -4
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/markdown-text.tsx +62 -20
- package/src/components/metric-treemap/heat-surface.tsx +8 -1
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +2 -2
- package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/reader/article-reader.tsx +642 -0
- package/src/components/reader/article-text.ts +527 -0
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +43 -2
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +7 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +18 -6
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +12 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +6 -1
- package/src/components/ui/query-bar.tsx +10 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/normalize.ts +7 -2
- package/src/data/config/store/portfolio-as-of-column.ts +57 -0
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7555 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +65 -5
- package/src/i18n/ja.ts +65 -5
- package/src/i18n/ko.ts +65 -5
- package/src/i18n/zh-cn.ts +65 -5
- package/src/i18n/zh-tw.ts +65 -5
- package/src/layout/desks.ts +1 -1
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/layout-marketplace/gallery.tsx +1 -1
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +84 -20
- package/src/market-data/market/session-close-note.ts +3 -2
- package/src/market-data/market/status.ts +19 -23
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +5 -0
- package/src/market-data/quotes/metadata.ts +19 -24
- package/src/market-data/quotes/resolution.ts +5 -0
- package/src/market-data/quotes/screener-live-quotes.ts +5 -4
- package/src/market-data/result-types.ts +2 -0
- package/src/notifications/app-notifier.ts +17 -1
- package/src/notifications/notification-log.ts +180 -0
- package/src/plugins/auto-update-node.ts +2 -2
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/model.ts +1 -56
- package/src/plugins/builtin/account-management/pane.tsx +6 -4
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/catalysts.ts +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/focus.ts +27 -0
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +47 -11
- package/src/plugins/builtin/alerts/pane.tsx +27 -1
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +8 -3
- package/src/plugins/builtin/analytics/risk-headless.ts +60 -27
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +35 -5
- package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/headless.ts +88 -18
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/model.ts +41 -1
- package/src/plugins/builtin/awards/pane.tsx +22 -13
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/headless.ts +2 -2
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +1 -1
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +49 -12
- package/src/plugins/builtin/cds/headless.ts +119 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +214 -32
- package/src/plugins/builtin/cds/pane.tsx +58 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
- package/src/plugins/builtin/central-bank-rates/index.tsx +3 -1
- package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
- package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
- package/src/plugins/builtin/central-bank-rates/series.ts +36 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +193 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
- package/src/plugins/builtin/chart-composer/headless.ts +70 -5
- package/src/plugins/builtin/chart-composer/index.tsx +15 -3
- package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
- package/src/plugins/builtin/chat/content/composer.tsx +5 -1
- package/src/plugins/builtin/chat/content/footer.tsx +12 -0
- package/src/plugins/builtin/chat/content/index.tsx +89 -5
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
- package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
- package/src/plugins/builtin/chat/content/scroll.ts +127 -27
- package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
- package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
- package/src/plugins/builtin/chat/content/types.ts +1 -0
- package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
- package/src/plugins/builtin/chat/controller/index.ts +123 -1
- package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
- package/src/plugins/builtin/chat/controller/messages.ts +7 -2
- package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
- package/src/plugins/builtin/chat/controller/send.ts +61 -1
- package/src/plugins/builtin/chat/controller/state.ts +8 -0
- package/src/plugins/builtin/chat/ghost-user.ts +20 -0
- package/src/plugins/builtin/chat/index.tsx +23 -5
- package/src/plugins/builtin/chat/layout.ts +78 -5
- package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
- package/src/plugins/builtin/chat/message/header.tsx +16 -4
- package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
- package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
- package/src/plugins/builtin/chat/message/render-state.ts +18 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
- package/src/plugins/builtin/chat/message/types.ts +12 -0
- package/src/plugins/builtin/chat/reactions.ts +197 -0
- package/src/plugins/builtin/chat/share/flow.tsx +87 -0
- package/src/plugins/builtin/chat/share/targets.ts +27 -0
- package/src/plugins/builtin/chat/status-widget.tsx +6 -3
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
- package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
- package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
- package/src/plugins/builtin/cloud/askg/model.ts +27 -8
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
- package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
- package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
- package/src/plugins/builtin/cloud/plugin.tsx +19 -2
- package/src/plugins/builtin/cloud/team/model.ts +5 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/team/store.ts +8 -3
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +21 -7
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/headless.ts +97 -10
- package/src/plugins/builtin/company-kpis/model.ts +24 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +17 -16
- package/src/plugins/builtin/composite-plugins.ts +19 -13
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/cpi/headless.ts +3 -3
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
- package/src/plugins/builtin/credit-boards/client.ts +6 -2
- package/src/plugins/builtin/credit-boards/headless.ts +108 -31
- package/src/plugins/builtin/credit-boards/index.tsx +2 -0
- package/src/plugins/builtin/credit-boards/model.ts +11 -1
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-conditions/client.ts +12 -9
- package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +18 -9
- package/src/plugins/builtin/credit-conditions/model.ts +19 -11
- package/src/plugins/builtin/credit-conditions/series.ts +16 -0
- package/src/plugins/builtin/credit-documents/headless.ts +33 -3
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/client.ts +3 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +7 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/dividend-yield/types.ts +2 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/headless.ts +12 -8
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/earnings/index.tsx +9 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
- package/src/plugins/builtin/econ/fred-catalog.ts +198 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/equity-screener/headless.ts +3 -3
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
- package/src/plugins/builtin/exposure/drivers.ts +13 -0
- package/src/plugins/builtin/exposure/headless.ts +205 -13
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/index.tsx +1 -0
- package/src/plugins/builtin/exposure/model.ts +23 -3
- package/src/plugins/builtin/exposure/pane.tsx +14 -12
- package/src/plugins/builtin/fear-greed/index.tsx +18 -10
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +71 -10
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/client.ts +63 -0
- package/src/plugins/builtin/fx-matrix/export.ts +2 -1
- package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -4
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +58 -27
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +101 -16
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/function-index.ts +2 -0
- package/src/plugins/builtin/help/index.tsx +31 -9
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +36 -133
- package/src/plugins/builtin/holders/pane.tsx +11 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +26 -9
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
- package/src/plugins/builtin/iv-history/client.ts +20 -6
- package/src/plugins/builtin/iv-history/format.ts +9 -0
- package/src/plugins/builtin/iv-history/headless.ts +56 -21
- package/src/plugins/builtin/iv-history/index.tsx +2 -0
- package/src/plugins/builtin/iv-history/model.ts +143 -8
- package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +26 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/macro-day/client.ts +44 -3
- package/src/plugins/builtin/macro-day/headless.ts +13 -10
- package/src/plugins/builtin/macro-day/model.ts +56 -10
- package/src/plugins/builtin/macro-day/pane.tsx +30 -20
- package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
- package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
- package/src/plugins/builtin/market-heatmap/model.ts +19 -11
- package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/index.tsx +3 -2
- package/src/plugins/builtin/market-movers/model.ts +30 -0
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +8 -3
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +6 -8
- package/src/plugins/builtin/mna/distress/headless.ts +4 -4
- package/src/plugins/builtin/mna/headless.ts +18 -6
- package/src/plugins/builtin/money-markets/headless.ts +5 -4
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/news/index.tsx +0 -2
- package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
- package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +3 -0
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +4 -3
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +2 -1
- package/src/plugins/builtin/options-scenario/headless.ts +1 -0
- package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
- package/src/plugins/builtin/perps/client.ts +90 -16
- package/src/plugins/builtin/perps/equity-row.tsx +52 -17
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +47 -32
- package/src/plugins/builtin/perps/index.tsx +23 -4
- package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
- package/src/plugins/builtin/perps/model.ts +20 -5
- package/src/plugins/builtin/perps/open-market.ts +15 -0
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +73 -67
- package/src/plugins/builtin/plugin-module.ts +3 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
- package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +161 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +384 -74
- package/src/plugins/builtin/portfolio-list/cli/render.ts +437 -71
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +21 -4
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +121 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +104 -26
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +84 -18
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
- package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +52 -9
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +33 -11
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
- package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +9 -4
- package/src/plugins/builtin/portfolio-list/table.tsx +37 -7
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +63 -10
- package/src/plugins/builtin/power/headless.ts +77 -9
- package/src/plugins/builtin/power/index.tsx +28 -3
- package/src/plugins/builtin/power/model.ts +73 -2
- package/src/plugins/builtin/power/pane.tsx +37 -9
- package/src/plugins/builtin/power/prices-client.ts +139 -0
- package/src/plugins/builtin/power/prices-headless.ts +137 -0
- package/src/plugins/builtin/power/prices-model.ts +103 -0
- package/src/plugins/builtin/power/prices.tsx +179 -0
- package/src/plugins/builtin/rate-path/headless.ts +46 -18
- package/src/plugins/builtin/realized-vol/headless.ts +5 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/research/index.tsx +2 -0
- package/src/plugins/builtin/research-search/article.ts +65 -0
- package/src/plugins/builtin/research-search/document-view.tsx +33 -215
- package/src/plugins/builtin/research-search/model.ts +0 -9
- package/src/plugins/builtin/research-search/pane.tsx +41 -30
- package/src/plugins/builtin/research-search/snippet.ts +0 -29
- package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/sec/headless.ts +25 -3
- package/src/plugins/builtin/sec/index.tsx +2 -1
- package/src/plugins/builtin/series-inventory.ts +93 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +30 -12
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/free-preview.ts +47 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +12 -1
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/volatility/options.ts +4 -1
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +2 -0
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +3 -2
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +2 -1
- package/src/plugins/builtin/short-volume/index.tsx +2 -0
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/headless.ts +43 -11
- package/src/plugins/builtin/supply-chain/model.ts +13 -0
- package/src/plugins/builtin/supply-chain/pane.tsx +8 -6
- package/src/plugins/builtin/themes/headless.ts +74 -10
- package/src/plugins/builtin/themes/model.ts +71 -4
- package/src/plugins/builtin/themes/pane.tsx +22 -5
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +26 -11
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +49 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +2 -1
- package/src/plugins/builtin/time-sales/index.tsx +2 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
- package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
- package/src/plugins/builtin/vol-surface/headless.ts +51 -17
- package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
- package/src/plugins/builtin/vol-surface/model.ts +39 -6
- package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
- package/src/plugins/builtin/vol-surface/stored.ts +63 -3
- package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
- package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +2 -1
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +24 -13
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
- package/src/plugins/builtin/world-venue-map/model.ts +56 -19
- package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +4 -2
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/installer.ts +2 -2
- package/src/plugins/loader.ts +15 -0
- package/src/plugins/manager-node.ts +1 -1
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
- package/src/plugins/registry/host-actions.ts +11 -0
- package/src/plugins/registry/index.ts +89 -4
- package/src/portfolio/collection-name.ts +31 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/portfolio/valuation-basis.ts +79 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/react/input.ts +33 -1
- package/src/react/key-repeat.ts +86 -0
- package/src/remote/app-host.tsx +20 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +144 -7
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +65 -2
- package/src/remote/types.ts +30 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +4 -3
- package/src/renderers/browser/research-entry.ts +4 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +30 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +16 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
- package/src/renderers/dom/host/box.tsx +8 -0
- package/src/renderers/dom/host/chart-surface.tsx +33 -2
- package/src/renderers/dom/host/live-frame.ts +6 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/scroll-box.tsx +32 -0
- package/src/renderers/dom/host/size-observer.ts +41 -0
- package/src/renderers/dom/host/sticky-scroll.ts +128 -0
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/surface-3d.tsx +19 -7
- package/src/renderers/dom/host/surface-fit.ts +406 -0
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +1 -0
- package/src/renderers/dom/styles.css +102 -5
- package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
- package/src/renderers/electrobun/bun/index.ts +3 -2
- package/src/renderers/electrobun/shared/protocol.ts +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +29 -2
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +63 -20
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +5 -3
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
- package/src/renderers/opentui/chart-surface.tsx +1 -0
- package/src/renderers/opentui/frame-capture.ts +33 -0
- package/src/renderers/opentui/host.tsx +10 -13
- package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
- package/src/renderers/opentui/pane-image/glyphs.json +1 -0
- package/src/renderers/opentui/pane-image/index.ts +107 -0
- package/src/renderers/opentui/pane-image/raster.ts +428 -0
- package/src/renderers/opentui/start.tsx +3 -3
- package/src/renderers/opentui/test-utils.tsx +3 -0
- package/src/renderers/opentui/ui-host.tsx +29 -1
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +108 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +153 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/chat.ts +34 -0
- package/src/shares/dialog.tsx +295 -0
- package/src/shares/flow.tsx +56 -0
- package/src/shares/live.ts +14 -22
- package/src/shares/pane-image.ts +152 -0
- package/src/shares/personal-pane.ts +64 -0
- package/src/shares/portable-layout.ts +4 -2
- package/src/shares/prepare.ts +20 -0
- package/src/sources/gloomberb-cloud/index.ts +109 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +3 -0
- package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
- package/src/sources/history-result.ts +1 -0
- package/src/sources/history-retention.ts +11 -0
- package/src/sources/listing-symbols.ts +4 -1
- package/src/sources/listing-target.ts +4 -0
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +1 -1
- package/src/sources/provider-router/financial-routes.ts +1 -0
- package/src/sources/provider-router/financials.ts +13 -0
- package/src/sources/provider-router/history.ts +43 -25
- package/src/sources/provider-router/index.ts +14 -0
- package/src/sources/provider-router/search.ts +1 -0
- package/src/state/hooks/inline-tickers.ts +49 -11
- package/src/sync/core-contributors.ts +1 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/theme-context.tsx +15 -1
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +34 -1
- package/src/tickers/listing-name.ts +34 -0
- package/src/tickers/listing-venues.ts +132 -0
- package/src/tickers/open-target.ts +13 -4
- package/src/tickers/perpetual-listing.ts +151 -0
- package/src/tickers/prediction-listing.ts +26 -0
- package/src/tickers/search/index.ts +72 -11
- package/src/tickers/search/ranking.ts +98 -20
- package/src/tickers/search/types.ts +7 -1
- package/src/tickers/ticker-changes.ts +213 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/economic.ts +2 -6
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/ice-credit.ts +39 -0
- package/src/time-series/resolve.ts +211 -29
- package/src/time-series/studies.ts +1 -0
- package/src/time-series/types.ts +12 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +10 -2
- package/src/types/data-provider.ts +11 -0
- package/src/types/financials.ts +62 -1
- package/src/types/headless.ts +113 -0
- package/src/types/instrument.ts +4 -0
- package/src/types/plugin.ts +52 -2
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker-changes.ts +26 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/context-menu.tsx +13 -1
- package/src/ui/host.tsx +57 -3
- package/src/ui/live-resize.ts +91 -0
- package/src/ui/live-stretch.ts +153 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/sticky-scroll.ts +7 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/central-banks.ts +76 -0
- package/src/utils/cli-output.ts +131 -15
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/currency-units.ts +11 -0
- package/src/utils/datetime-format.ts +27 -6
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +439 -52
- package/src/utils/double-escape-close.ts +15 -1
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +143 -1
- package/src/utils/format.ts +35 -5
- package/src/utils/forward-dividend.ts +14 -0
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +15 -5
- package/src/utils/fx-status.ts +6 -1
- package/src/utils/inline-content-tokenizer.ts +22 -3
- package/src/utils/market-capitalization.ts +8 -0
- package/src/utils/one-shot.ts +73 -0
- package/src/utils/options.ts +37 -8
- package/src/utils/price-history.ts +99 -42
- package/src/utils/sec-eps-basis.ts +24 -11
- package/src/utils/sec.ts +61 -7
- package/src/utils/utc-time.ts +63 -4
- package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
- /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
|
@@ -6,16 +6,30 @@ import type {
|
|
|
6
6
|
} from "../../../types/plugin";
|
|
7
7
|
import { formatShortDate } from "../../../utils/datetime-format";
|
|
8
8
|
import { normalizeCik } from "./api";
|
|
9
|
-
import { buildFundOverlap, overlapPeriod } from "./overlap";
|
|
9
|
+
import { buildFundOverlap, buildManagerEtfOverlap, overlapPeriod } from "./overlap";
|
|
10
|
+
import type { FundMembersPayload, MemberFundsPayload } from "../../../api-client/members";
|
|
11
|
+
import { fetchFunds, fetchMembers } from "../members/client";
|
|
12
|
+
import { coveredFund } from "../members/model";
|
|
10
13
|
import { appendTickerHoldings, loadCrowding, loadTickerHoldings, type CrowdingRow, type TickerHoldings } from "./signals";
|
|
11
14
|
import {
|
|
12
15
|
AS_FILED_VALUE,
|
|
13
16
|
compareCrowding,
|
|
14
17
|
crowdingForTicker,
|
|
15
18
|
cutText,
|
|
16
|
-
|
|
19
|
+
filedPeriodText,
|
|
20
|
+
filingDayText,
|
|
21
|
+
filingLagDays,
|
|
22
|
+
isOptionType,
|
|
23
|
+
isStaleFiling,
|
|
24
|
+
markedPositionType,
|
|
25
|
+
OPTION_ROWS_NOTE,
|
|
26
|
+
restatedValuesText,
|
|
27
|
+
staleFilingText,
|
|
28
|
+
staleFundsText,
|
|
17
29
|
summarizeTickerHoldings,
|
|
30
|
+
THIRTEENF_LIMITS,
|
|
18
31
|
THIRTEENF_MAX_LIMIT,
|
|
32
|
+
THIRTEENF_OPTIONS_NOTE,
|
|
19
33
|
} from "./report-notes";
|
|
20
34
|
import {
|
|
21
35
|
loadBrowserRows,
|
|
@@ -31,9 +45,9 @@ import {
|
|
|
31
45
|
buildTimelineRows,
|
|
32
46
|
inferBrowserTabFromQuery,
|
|
33
47
|
hasComparable13FQuarter,
|
|
34
|
-
THIRTEENF_OPTIONS_NOTE,
|
|
35
48
|
isCikQuery,
|
|
36
49
|
positionType,
|
|
50
|
+
quartersBehindLatest,
|
|
37
51
|
sortBrowserRows,
|
|
38
52
|
sortHoldingRows,
|
|
39
53
|
sortTimelineRows,
|
|
@@ -87,9 +101,16 @@ const BROWSER_COLUMNS: HeadlessPaneColumn[] = [
|
|
|
87
101
|
},
|
|
88
102
|
];
|
|
89
103
|
|
|
104
|
+
/** What a 13F position report notes after its table: the filing's limits, and what the option marker means when option rows are shown. */
|
|
105
|
+
function positionNotes(rows: readonly { type?: unknown }[]): string[] {
|
|
106
|
+
return [THIRTEENF_LIMITS, ...(rows.some((row) => isOptionType(row.type)) ? [OPTION_ROWS_NOTE] : [])];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const TYPE_COLUMN: HeadlessPaneColumn = { key: "type", header: "Type", textFormat: markedPositionType };
|
|
110
|
+
|
|
90
111
|
const HOLDING_COLUMNS: HeadlessPaneColumn[] = [
|
|
91
112
|
{ key: "ticker", header: "Ticker" },
|
|
92
|
-
|
|
113
|
+
TYPE_COLUMN,
|
|
93
114
|
{ key: "issuer", header: "Issuer" },
|
|
94
115
|
{
|
|
95
116
|
key: "value",
|
|
@@ -175,9 +196,13 @@ export interface ThirteenFHeadlessDependencies {
|
|
|
175
196
|
args: HeadlessPaneLoadArgs,
|
|
176
197
|
ctx: HeadlessPaneContext,
|
|
177
198
|
): Promise<FundDetailData>;
|
|
199
|
+
/** The ETFs whose holdings files MEMB serves. */
|
|
200
|
+
loadEtfFunds?(ctx: HeadlessPaneContext): Promise<MemberFundsPayload["funds"]>;
|
|
201
|
+
/** One covered ETF's holdings file, as `fn MEMB` reads it. */
|
|
202
|
+
loadEtfHoldings?(ticker: string, ctx: HeadlessPaneContext): Promise<FundMembersPayload>;
|
|
178
203
|
}
|
|
179
204
|
|
|
180
|
-
const defaultDependencies: ThirteenFHeadlessDependencies = {
|
|
205
|
+
const defaultDependencies: Required<ThirteenFHeadlessDependencies> = {
|
|
181
206
|
loadBrowser: (tab, query, limit, _args, ctx) => loadBrowserRows(
|
|
182
207
|
tab,
|
|
183
208
|
query,
|
|
@@ -185,6 +210,8 @@ const defaultDependencies: ThirteenFHeadlessDependencies = {
|
|
|
185
210
|
{ limit },
|
|
186
211
|
),
|
|
187
212
|
loadDetail: (cik, name, _args, ctx) => loadFundDetail(cik, name, ctx.signal),
|
|
213
|
+
loadEtfFunds: async (ctx) => (await fetchFunds(ctx.apiClient)).funds,
|
|
214
|
+
loadEtfHoldings: (ticker, ctx) => fetchMembers(ticker, ctx.apiClient),
|
|
188
215
|
};
|
|
189
216
|
|
|
190
217
|
const VIEW_TITLES: Record<string, string> = {
|
|
@@ -217,18 +244,22 @@ function browserTab(view: HeadlessThirteenFView, query: string): ThirteenFBrowse
|
|
|
217
244
|
return inferBrowserTabFromQuery(query);
|
|
218
245
|
}
|
|
219
246
|
|
|
220
|
-
|
|
247
|
+
/**
|
|
248
|
+
* The manager a fund name or CIK names: a CIK as given, else the one fund
|
|
249
|
+
* whose name matches exactly, else the only match. `search` lists funds by
|
|
250
|
+
* name, as the 13F browser does.
|
|
251
|
+
*/
|
|
252
|
+
async function findThirteenFFund(
|
|
221
253
|
query: string,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
): Promise<{ cik: string; name: string }> {
|
|
226
|
-
if (!query) throw new Error("13F holdings and filings require a fund name or CIK.");
|
|
254
|
+
search: (query: string, limit: number) => Promise<BrowserLoadResult>,
|
|
255
|
+
{ exactOnly = false }: { exactOnly?: boolean } = {},
|
|
256
|
+
): Promise<{ cik: string; name: string } | null> {
|
|
227
257
|
if (isCikQuery(query)) return { cik: normalizeCik(query), name: query };
|
|
228
258
|
// A small output limit must not hide other matching managers during lookup.
|
|
229
|
-
const result = await
|
|
259
|
+
const result = await search(query, 25);
|
|
230
260
|
const candidates = [...new Map(result.rows.map((row) => [row.cik, row])).values()];
|
|
231
261
|
const exact = candidates.filter((row) => row.name.toLocaleLowerCase() === query.toLocaleLowerCase());
|
|
262
|
+
if (exactOnly) return exact.length === 1 ? { cik: exact[0]!.cik, name: exact[0]!.name } : null;
|
|
232
263
|
const fund = exact.length === 1 ? exact[0]
|
|
233
264
|
: candidates.length === 1 && !result.hasMore ? candidates[0] : undefined;
|
|
234
265
|
if (candidates.length === 0) throw new Error(`No 13F fund found for "${query}".`);
|
|
@@ -239,12 +270,67 @@ async function resolveFund(
|
|
|
239
270
|
return { cik: fund.cik, name: fund.name };
|
|
240
271
|
}
|
|
241
272
|
|
|
273
|
+
async function resolveFund(
|
|
274
|
+
query: string,
|
|
275
|
+
args: HeadlessPaneLoadArgs,
|
|
276
|
+
ctx: HeadlessPaneContext,
|
|
277
|
+
dependencies: ThirteenFHeadlessDependencies,
|
|
278
|
+
): Promise<{ cik: string; name: string }> {
|
|
279
|
+
if (!query) throw new Error("13F holdings and filings require a fund name or CIK.");
|
|
280
|
+
return (await findThirteenFFund(query, (text, limit) => dependencies.loadBrowser("funds", text, limit, args, ctx)))!;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** A word that reads as a ticker (SPY, BRK.B), not a manager's name or a CIK. */
|
|
284
|
+
const TICKER_WORD = /^\$?[A-Za-z]{1,5}(?:[.-][A-Za-z])?$/;
|
|
285
|
+
|
|
286
|
+
type OverlapComparison =
|
|
287
|
+
| { kind: "fund"; cik: string; name: string }
|
|
288
|
+
| { kind: "etf"; symbol: string; ticker: string; name: string };
|
|
289
|
+
|
|
290
|
+
/** "IVV (also SPY, SPX), IJH": the covered funds and the aliases each answers to. */
|
|
291
|
+
const coveredEtfs = (funds: MemberFundsPayload["funds"]) => funds
|
|
292
|
+
.map((fund) => fund.aliases.length ? `${fund.ticker} (also ${fund.aliases.join(", ")})` : fund.ticker).join(", ");
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* What `--compare` names. A ticker-like word is an ETF when MEMB has its
|
|
296
|
+
* holdings file, else a 13F manager only by its exact name; it is never
|
|
297
|
+
* matched to a manager by a partial name (SPY is not Spyglass Capital).
|
|
298
|
+
* Anything else, a CIK or a longer name, is a 13F manager as before.
|
|
299
|
+
*/
|
|
300
|
+
async function resolveComparison(
|
|
301
|
+
text: string,
|
|
302
|
+
args: HeadlessPaneLoadArgs,
|
|
303
|
+
ctx: HeadlessPaneContext,
|
|
304
|
+
dependencies: Required<ThirteenFHeadlessDependencies>,
|
|
305
|
+
): Promise<OverlapComparison> {
|
|
306
|
+
if (isCikQuery(text) || !TICKER_WORD.test(text)) return { kind: "fund", ...await resolveFund(text, args, ctx, dependencies) };
|
|
307
|
+
const symbol = text.replace(/^\$/, "").toUpperCase();
|
|
308
|
+
let funds: MemberFundsPayload["funds"] | null = null;
|
|
309
|
+
let failure = "";
|
|
310
|
+
try {
|
|
311
|
+
funds = await dependencies.loadEtfFunds(ctx);
|
|
312
|
+
} catch (error) {
|
|
313
|
+
if (ctx.signal.aborted) throw error;
|
|
314
|
+
failure = error instanceof Error ? error.message : String(error);
|
|
315
|
+
}
|
|
316
|
+
const etf = funds ? coveredFund(funds, symbol) : undefined;
|
|
317
|
+
if (etf) return { kind: "etf", symbol, ticker: etf.ticker, name: etf.name };
|
|
318
|
+
const manager = await findThirteenFFund(text, (query, limit) => dependencies.loadBrowser("funds", query, limit, args, ctx), { exactOnly: true });
|
|
319
|
+
if (manager) return { kind: "fund", ...manager };
|
|
320
|
+
const etfs = funds ? `${symbol} is not an ETF MEMB covers (covered: ${coveredEtfs(funds)})` : `${symbol} could not be checked against MEMB's ETFs (${failure})`;
|
|
321
|
+
throw new Error(`${etfs}, and no 13F manager is named "${text}". For a manager, use its CIK or full name.`);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const percentText = (value: number) => `${(value * 100).toFixed(1)}%`;
|
|
325
|
+
|
|
242
326
|
export function createThirteenFHeadless(
|
|
243
|
-
|
|
327
|
+
overrides: ThirteenFHeadlessDependencies = defaultDependencies,
|
|
244
328
|
): HeadlessPaneDefinition<"rows"> {
|
|
329
|
+
const dependencies: Required<ThirteenFHeadlessDependencies> = { ...defaultDependencies, ...overrides };
|
|
245
330
|
return {
|
|
246
331
|
shape: "rows",
|
|
247
332
|
freshness: { ...SEC_FILINGS, basis: "13F filings", observedKey: "filedAsOfDate" },
|
|
333
|
+
discovery: { limitations: [THIRTEENF_LIMITS] },
|
|
248
334
|
argument: {
|
|
249
335
|
kind: "free-text",
|
|
250
336
|
placeholder: "fund, ticker, or CIK",
|
|
@@ -252,9 +338,10 @@ export function createThirteenFHeadless(
|
|
|
252
338
|
optional: true,
|
|
253
339
|
},
|
|
254
340
|
options: [
|
|
255
|
-
|
|
256
|
-
{ key: "
|
|
257
|
-
{ key: "
|
|
341
|
+
// No defaults on view-specific options, so a flag the view does not use can be named as ignored.
|
|
342
|
+
{ key: "rank", description: "Crowding order (crowding view; new when left out).", type: "enum", values: [{ value: "new" }, { value: "exits" }, { value: "increases" }, { value: "decreases" }] },
|
|
343
|
+
{ key: "compare", description: "Second fund name or CIK, or an ETF ticker MEMB covers such as SPY; implies the overlap view.", type: "string" },
|
|
344
|
+
{ key: "offset", description: "Fund offset for ticker-holdings (0 when left out).", type: "integer", minimum: 0, maximum: 100000 },
|
|
258
345
|
{
|
|
259
346
|
key: "view",
|
|
260
347
|
description: "Fund browser mode or detail tab.",
|
|
@@ -287,20 +374,80 @@ export function createThirteenFHeadless(
|
|
|
287
374
|
async load(args, ctx) {
|
|
288
375
|
const query = typeof args.argument === "string" ? args.argument.trim() : "";
|
|
289
376
|
const requestedView = String(args.options.view) as HeadlessThirteenFView;
|
|
377
|
+
const compare = typeof args.options.compare === "string" ? args.options.compare.trim() : "";
|
|
378
|
+
if (compare && requestedView !== "auto" && requestedView !== "overlap") {
|
|
379
|
+
throw new Error(`--compare is for the overlap view; --view ${requestedView} does not use it. Drop --view, or use --view overlap.`);
|
|
380
|
+
}
|
|
290
381
|
// A ticker's holders with their positions, not the holders' whole books.
|
|
291
|
-
const view =
|
|
292
|
-
:
|
|
293
|
-
:
|
|
294
|
-
:
|
|
382
|
+
const view = compare ? "overlap"
|
|
383
|
+
: requestedView !== "auto" ? requestedView
|
|
384
|
+
: isCikQuery(query) ? "holdings"
|
|
385
|
+
: inferBrowserTabFromQuery(query) === "byTicker" ? "ticker-holdings"
|
|
386
|
+
: requestedView;
|
|
387
|
+
// A flag the view does not use is named, never dropped without a word.
|
|
388
|
+
const flagNotices = [
|
|
389
|
+
compare && requestedView === "auto" ? "--compare implies --view overlap" : "",
|
|
390
|
+
args.options.rank != null && view !== "crowding" ? "--rank orders --view crowding only; ignored here" : "",
|
|
391
|
+
args.options.offset != null && view !== "ticker-holdings" ? "--offset pages a ticker's holders only; ignored here" : "",
|
|
392
|
+
query && (view === "latest" || view === "performance") ? `--view ${view} lists every manager; "${query}" is not used` : "",
|
|
393
|
+
].filter(Boolean);
|
|
295
394
|
const limit = Number(args.options.limit);
|
|
296
395
|
if (view === "overlap") {
|
|
396
|
+
if (!compare) throw new Error(`13F overlap compares two holdings: add --compare <fund name, CIK or ETF ticker>, as in fn 13F ${query || "<fund or CIK>"} --compare SPY.`);
|
|
397
|
+
if (!query) throw new Error("13F overlap needs a fund name or CIK first: fn 13F <fund or CIK> --compare <fund, CIK or ETF ticker>.");
|
|
297
398
|
const fund = await resolveFund(query, args, ctx, dependencies);
|
|
298
|
-
const other = await
|
|
399
|
+
const other = await resolveComparison(compare, args, ctx, dependencies);
|
|
400
|
+
if (other.kind === "etf") {
|
|
401
|
+
const [first, etf] = await Promise.all([dependencies.loadDetail(fund.cik, fund.name, args, ctx), dependencies.loadEtfHoldings(other.ticker, ctx)]);
|
|
402
|
+
const overlap = buildManagerEtfOverlap(first, etf.members);
|
|
403
|
+
const period = first.latestForm?.periodOfReport ?? null;
|
|
404
|
+
const filed = first.latestForm?.filedAsOfDate ?? null;
|
|
405
|
+
const rows = overlap?.rows ?? [];
|
|
406
|
+
const cut = cutText(rows.length, limit, "positions");
|
|
407
|
+
const missing = overlap?.missing ?? [];
|
|
408
|
+
const missingNames = missing.slice(0, 5).map((row) => `${row.ticker || row.issuer} ${weight(row.weight)}`).join(", ");
|
|
409
|
+
const leftOut = overlap ? [overlap.leftOut.options ? `${overlap.leftOut.options} option line${overlap.leftOut.options === 1 ? "" : "s"}` : "", overlap.leftOut.principal ? `${overlap.leftOut.principal} principal-amount line${overlap.leftOut.principal === 1 ? "" : "s"}` : ""].filter(Boolean) : [];
|
|
410
|
+
const etfWeight = (value: unknown, row: Record<string, unknown>) => row.etfWeight == null ? "no ticker" : value === 0 ? "not held" : weight(value);
|
|
411
|
+
return {
|
|
412
|
+
columns: [{ key: "ticker", header: "Ticker" }, { key: "issuer", header: "Issuer" }, { key: "weight", header: "13F weight", align: "right", format: weight }, { key: "etfWeight", header: `${other.symbol} weight`, align: "right", format: etfWeight }, { key: "shared", header: "Shared", align: "right", format: weight }],
|
|
413
|
+
rows: rows.slice(0, limit).map((row) => ({ ...row })),
|
|
414
|
+
errors: [
|
|
415
|
+
...(first.warnings ?? []),
|
|
416
|
+
...(first.latestReport?.complete === false ? [`The 13F for ${period} did not load completely; weights cover the lines that did.`] : []),
|
|
417
|
+
...(etf.stale ? [`The ${other.ticker} holdings file is stale.`] : []),
|
|
418
|
+
...(!overlap ? ["No share positions or ETF weights to compare."] : []),
|
|
419
|
+
],
|
|
420
|
+
freshness: { source: "SEC EDGAR and Gloom Cloud", ...(period ? { asOf: period } : {}) },
|
|
421
|
+
metadata: {
|
|
422
|
+
view, comparedWith: "etf", firstFund: first.name, cik: first.cik, secondFund: other.symbol,
|
|
423
|
+
etf: { symbol: other.symbol, ticker: other.ticker, name: other.name, asOf: etf.asOf },
|
|
424
|
+
comparedPeriod: period, filed,
|
|
425
|
+
overlap: overlap?.overlap ?? null, activeShare: overlap?.activeShare ?? null,
|
|
426
|
+
missing: missing.map((row) => ({ ticker: row.ticker || null, issuer: row.issuer, weight: row.weight, reason: row.etfWeight == null ? "no ticker" : "not held" })),
|
|
427
|
+
missingWeight: overlap?.missingWeight ?? null,
|
|
428
|
+
leftOut: overlap?.leftOut ?? null,
|
|
429
|
+
shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit,
|
|
430
|
+
notices: [
|
|
431
|
+
...flagNotices,
|
|
432
|
+
`${other.symbol} read as an ETF: ${other.name} holdings${other.ticker !== other.symbol ? ` (${other.ticker} file)` : ""}, as fn MEMB ${other.symbol} shows`,
|
|
433
|
+
...(overlap ? [`Overlap ${percentText(overlap.overlap)} (sum of the smaller weight per name) | Active share ${percentText(overlap.activeShare)}`] : []),
|
|
434
|
+
[
|
|
435
|
+
period ? `Quarter compared: ${filingDayText(period)}${filed ? `, filed ${filingDayText(filed)}` : ""}` : "",
|
|
436
|
+
`${other.symbol} holdings as of ${filingDayText(etf.asOf.slice(0, 10))}`,
|
|
437
|
+
leftOut.length ? `13F weights leave out ${leftOut.join(" and ")}` : "",
|
|
438
|
+
].filter(Boolean).join(" | "),
|
|
439
|
+
...(overlap ? [missing.length ? `Not in ${other.symbol}: ${missing.length} of ${rows.length} positions, ${percentText(overlap.missingWeight)} of the 13F | ${missingNames}${missing.length > 5 ? ", ..." : ""}` : `${other.symbol} holds every position in the 13F`] : []),
|
|
440
|
+
...(cut ? [`${cut[0]!.toUpperCase()}${cut.slice(1)}`] : []),
|
|
441
|
+
].filter(Boolean),
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
}
|
|
299
445
|
const [first, second] = await Promise.all([dependencies.loadDetail(fund.cik, fund.name, args, ctx), dependencies.loadDetail(other.cik, other.name, args, ctx)]);
|
|
300
446
|
const comparedPeriod = overlapPeriod(first, second);
|
|
301
447
|
const rows = buildFundOverlap(first, second);
|
|
302
448
|
const cut = cutText(rows.length, limit, "positions");
|
|
303
|
-
|
|
449
|
+
const read = `${compare} read as the 13F manager ${second.name} (CIK ${second.cik})`;
|
|
450
|
+
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) } };
|
|
304
451
|
}
|
|
305
452
|
if (view === "crowding") {
|
|
306
453
|
const { rows: sourceRows, ...metadata } = await loadCrowding(ctx.signal);
|
|
@@ -314,7 +461,7 @@ export function createThirteenFHeadless(
|
|
|
314
461
|
const columns: HeadlessPaneColumn[] = [{ key: "ticker", header: "Ticker" }, { key: "issuer", header: "Issuer" }, { key: "type", header: "Type" }, { key: "holderCount", header: "Funds", align: "right" }, { key: "newCount", header: "New", align: "right" }, { key: "exitCount", header: "Exits", align: "right" }, { key: "weightChange", header: "Weight change", align: "right", format: weightPoints }, { key: "comparedFunds", header: "Compared", align: "right" }, { key: "totalValue", header: "Value (USD)", align: "right", format: money }];
|
|
315
462
|
const cut = cutText(rows.length, limit, "securities");
|
|
316
463
|
return { columns: focus ? [{ key: "rank", header: "Rank", align: "right" }, ...columns] : columns, rows: rows.slice(0, limit).map(row => ({ ...row })),
|
|
317
|
-
metadata: { ...metadata, view, rank, ...(ticker ? { ticker, found: rows.length > 0, rankedSecurities: ranked.length } : {}), shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [[sample, cut].filter(Boolean).join(" | "), ...(focus ? [focus.notice] : [])] },
|
|
464
|
+
metadata: { ...metadata, view, rank, ...(ticker ? { ticker, found: rows.length > 0, rankedSecurities: ranked.length } : {}), shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [...flagNotices, [sample, cut].filter(Boolean).join(" | "), ...(focus ? [focus.notice] : [])] },
|
|
318
465
|
freshness: { asOf: metadata.period }, errors: metadata.warnings };
|
|
319
466
|
}
|
|
320
467
|
let holdings: TickerHoldings | null = null;
|
|
@@ -336,9 +483,11 @@ export function createThirteenFHeadless(
|
|
|
336
483
|
const { rows, ...metadata } = holdings;
|
|
337
484
|
const offset = Number(args.options.offset ?? 0);
|
|
338
485
|
const summary = summarizeTickerHoldings({ ...metadata, offset, limit, loaded: rows });
|
|
486
|
+
const shown = rows.slice(0, limit).map(row => ({ ...row }));
|
|
339
487
|
return {
|
|
340
|
-
columns: [{ key: "fund", header: "Fund" }, { key: "cik", header: "CIK" },
|
|
341
|
-
rows:
|
|
488
|
+
columns: [{ key: "fund", header: "Fund" }, { key: "cik", header: "CIK" }, TYPE_COLUMN, { key: "value", header: "Value (USD)", align: "right", format: money }, { key: "shares", header: "Shares", align: "right", format: shares }, { key: "weight", header: "13F weight", align: "right", format: weight }, { key: "action", header: "Action" }],
|
|
489
|
+
rows: shown,
|
|
490
|
+
notes: positionNotes(shown),
|
|
342
491
|
metadata: {
|
|
343
492
|
...metadata,
|
|
344
493
|
view,
|
|
@@ -353,7 +502,7 @@ export function createThirteenFHeadless(
|
|
|
353
502
|
totalValue: summary.shownValue,
|
|
354
503
|
valueScope: "shown funds",
|
|
355
504
|
valueBasis: "as reported at period end",
|
|
356
|
-
notices: summary.notices,
|
|
505
|
+
notices: [...flagNotices, ...summary.notices],
|
|
357
506
|
},
|
|
358
507
|
freshness: { asOf: metadata.period },
|
|
359
508
|
errors: metadata.warnings,
|
|
@@ -370,6 +519,8 @@ export function createThirteenFHeadless(
|
|
|
370
519
|
.slice(0, limit)
|
|
371
520
|
.map((row) => ({ ...row }));
|
|
372
521
|
const cut = cutText(all.length, limit, "filings");
|
|
522
|
+
const shownFilings = new Set(rows.map((row) => row.accessionNumber));
|
|
523
|
+
const restated = restatedValuesText(detail.forms.filter((form) => shownFilings.has(form.accessionNumber)));
|
|
373
524
|
return {
|
|
374
525
|
columns: FILING_COLUMNS,
|
|
375
526
|
rows,
|
|
@@ -382,7 +533,7 @@ export function createThirteenFHeadless(
|
|
|
382
533
|
shown: rows.length,
|
|
383
534
|
total: all.length,
|
|
384
535
|
truncated: all.length > limit,
|
|
385
|
-
notices: [[`CIK ${detail.cik}`, cut].filter(Boolean).join(" | ")],
|
|
536
|
+
notices: [...flagNotices, [`CIK ${detail.cik}`, cut].filter(Boolean).join(" | "), ...(restated ? [restated] : [])],
|
|
386
537
|
},
|
|
387
538
|
};
|
|
388
539
|
}
|
|
@@ -391,7 +542,17 @@ export function createThirteenFHeadless(
|
|
|
391
542
|
DEFAULT_HOLDING_SORT,
|
|
392
543
|
);
|
|
393
544
|
const previousPeriod = detail.previousForm?.periodOfReport ?? null;
|
|
545
|
+
const comparable = hasComparable13FQuarter(detail);
|
|
546
|
+
const filed = detail.latestForm?.filedAsOfDate || null;
|
|
547
|
+
const quartersBehind = quartersBehindLatest(latestPeriod);
|
|
394
548
|
const cut = cutText(all.length, limit, "positions, exits included");
|
|
549
|
+
// Values, weights and Est P&L read both compared quarters' filings.
|
|
550
|
+
const reportForms = (report: typeof detail.latestReport, form: typeof detail.latestForm) =>
|
|
551
|
+
report?.filings ?? (form ? [form] : []);
|
|
552
|
+
const restated = restatedValuesText([
|
|
553
|
+
...reportForms(detail.latestReport, detail.latestForm),
|
|
554
|
+
...(comparable ? reportForms(detail.previousReport, detail.previousForm) : []),
|
|
555
|
+
]);
|
|
395
556
|
const rows = all
|
|
396
557
|
.slice(0, limit)
|
|
397
558
|
.map((row) => ({
|
|
@@ -403,22 +564,33 @@ export function createThirteenFHeadless(
|
|
|
403
564
|
columns: HOLDING_COLUMNS,
|
|
404
565
|
rows,
|
|
405
566
|
...(detail.warnings?.length ? { errors: detail.warnings } : {}),
|
|
406
|
-
|
|
407
|
-
|
|
567
|
+
notes: positionNotes(rows),
|
|
568
|
+
// Dated by the filing that made the positions public, with the quarter they report beside it.
|
|
569
|
+
...(latestPeriod ? { freshness: {
|
|
570
|
+
asOf: filed ?? latestPeriod,
|
|
571
|
+
basis: `13F filing for the quarter ended ${filingDayText(latestPeriod)}`,
|
|
572
|
+
} } : {}),
|
|
408
573
|
metadata: {
|
|
409
574
|
view,
|
|
410
575
|
cik: detail.cik,
|
|
411
576
|
fund: detail.name,
|
|
412
577
|
latestPeriod,
|
|
578
|
+
latestFiled: filed,
|
|
579
|
+
filingLagDays: filingLagDays(latestPeriod, filed),
|
|
580
|
+
quartersBehind,
|
|
413
581
|
previousPeriod,
|
|
414
582
|
shown: rows.length,
|
|
415
583
|
total: all.length,
|
|
416
584
|
truncated: all.length > limit,
|
|
417
585
|
notices: [
|
|
418
|
-
|
|
586
|
+
...flagNotices,
|
|
587
|
+
[`CIK ${detail.cik}`, filedPeriodText(latestPeriod, filed, comparable ? previousPeriod : null)].filter(Boolean).join(" | "),
|
|
588
|
+
AS_FILED_VALUE,
|
|
589
|
+
...(restated ? [restated] : []),
|
|
590
|
+
...(isStaleFiling(quartersBehind) ? [staleFilingText(quartersBehind)] : []),
|
|
419
591
|
...(cut ? [`${cut[0]!.toUpperCase()}${cut.slice(1)}`] : []),
|
|
420
592
|
],
|
|
421
|
-
comparisonAvailable:
|
|
593
|
+
comparisonAvailable: comparable,
|
|
422
594
|
currentFilings: detail.latestReport?.filings.map((form) => form.accessionNumber) ?? [],
|
|
423
595
|
previousFilings: detail.previousReport?.filings.map((form) => form.accessionNumber) ?? [],
|
|
424
596
|
currentReportedValue: detail.latestReport?.complete ? detail.latestReport.tableValueTotal : null,
|
|
@@ -432,11 +604,18 @@ export function createThirteenFHeadless(
|
|
|
432
604
|
const tab = browserTab(view === "ticker-holdings" ? requestedView : view, query);
|
|
433
605
|
const result = await dependencies.loadBrowser(tab, query, limit, args, ctx);
|
|
434
606
|
const more = result.hasMore || result.rows.length > limit;
|
|
607
|
+
const browserRows = sortBrowserRows(result.rows, browserSortFor(DEFAULT_BROWSER_SORT, tab)).slice(0, limit);
|
|
608
|
+
// A search finds managers that stopped filing; say which, since the Period column alone reads like any other.
|
|
609
|
+
const stale = tab === "funds"
|
|
610
|
+
? browserRows.flatMap((row) => {
|
|
611
|
+
const quarters = quartersBehindLatest(row.periodOfReport);
|
|
612
|
+
return isStaleFiling(quarters) ? [{ name: row.name, quarters }] : [];
|
|
613
|
+
})
|
|
614
|
+
: [];
|
|
435
615
|
return {
|
|
436
616
|
columns: result.rows[0]?.priorReturns?.length ? [...BROWSER_COLUMNS.filter(column => !["filedAsOfDate", "tableEntryTotal"].includes(column.key)), ...result.rows[0].priorReturns.map((point, index) => ({ key: `return${index + 1}`, header: point.quarter, align: "right" as const, format: (value: unknown) => formatRawPercentMaybe(typeof value === "number" ? value : null) }))]
|
|
437
617
|
: tab === "performance" ? BROWSER_COLUMNS : BROWSER_COLUMNS.filter(column => column.key !== "estQuarterReturn"),
|
|
438
|
-
rows:
|
|
439
|
-
.slice(0, limit)
|
|
618
|
+
rows: browserRows
|
|
440
619
|
.map((row) => ({ ...row, ...Object.fromEntries((row.priorReturns ?? []).map((point, index) => [`return${index + 1}`, point.value])) })),
|
|
441
620
|
...(result.warning ? { errors: [result.warning] } : {}),
|
|
442
621
|
metadata: {
|
|
@@ -447,9 +626,11 @@ export function createThirteenFHeadless(
|
|
|
447
626
|
hasMore: result.hasMore ?? false,
|
|
448
627
|
shown: Math.min(result.rows.length, limit),
|
|
449
628
|
truncated: more,
|
|
450
|
-
notices:
|
|
451
|
-
|
|
452
|
-
: [],
|
|
629
|
+
notices: [
|
|
630
|
+
...flagNotices,
|
|
631
|
+
...(more ? [[`Showing the first ${Math.min(result.rows.length, limit)}`, limit < THIRTEENF_MAX_LIMIT ? `more: --limit ${THIRTEENF_MAX_LIMIT}` : ""].filter(Boolean).join(" | ")] : []),
|
|
632
|
+
...(stale.length ? [staleFundsText(stale)] : []),
|
|
633
|
+
],
|
|
453
634
|
},
|
|
454
635
|
};
|
|
455
636
|
},
|
|
@@ -26,7 +26,6 @@ import type {
|
|
|
26
26
|
|
|
27
27
|
export const THIRTEENF_PANE_ID = "thirteenf-funds";
|
|
28
28
|
export const THIRTEENF_TEMPLATE_ID = "thirteenf-funds-pane";
|
|
29
|
-
export const THIRTEENF_OPTIONS_NOTE = "Option values and shares refer to the underlying; 13F % is share of reported value.";
|
|
30
29
|
|
|
31
30
|
export const FUND_DETAIL_TABS: Array<{ label: string; value: ThirteenFDetailTab }> = [
|
|
32
31
|
{ label: "Holdings", value: "holdings" },
|
|
@@ -96,6 +95,45 @@ export function latestLikely13FQuarter(now = new Date()): string {
|
|
|
96
95
|
return "";
|
|
97
96
|
}
|
|
98
97
|
|
|
98
|
+
function quarterIndex(period: string): number | null {
|
|
99
|
+
const match = /^(\d{4})-(\d{2})-\d{2}$/.exec(period) ?? /^(\d{4})Q([1-4])$/.exec(period);
|
|
100
|
+
if (!match) return null;
|
|
101
|
+
const year = Number(match[1]);
|
|
102
|
+
const part = Number(match[2]);
|
|
103
|
+
return year * 4 + (period.includes("Q") ? part - 1 : Math.floor((part - 1) / 3));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* How many quarters a fund's latest report period trails the latest quarter
|
|
108
|
+
* filers have had time to report (`latestLikely13FQuarter`); 0 when it is
|
|
109
|
+
* current or ahead, null without a readable period.
|
|
110
|
+
*/
|
|
111
|
+
export function quartersBehindLatest(period: string | null | undefined, now = new Date()): number | null {
|
|
112
|
+
const latest = quarterIndex(latestLikely13FQuarter(now));
|
|
113
|
+
const own = period ? quarterIndex(period) : null;
|
|
114
|
+
return latest == null || own == null ? null : Math.max(0, latest - own);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The fund search lists a manager once for each name it has filed under
|
|
119
|
+
* ("PERSHING SQUARE HOLDCO, L.P." and "PERSHING SQUARE INC." share a CIK).
|
|
120
|
+
* One row per CIK: a renamed manager takes the name on its latest loaded
|
|
121
|
+
* filing, else the longest of its names.
|
|
122
|
+
*/
|
|
123
|
+
export function oneFundPerCik(
|
|
124
|
+
funds: readonly ThirteenFFund[],
|
|
125
|
+
reports?: ReadonlyMap<string, ThirteenFPeriodReport>,
|
|
126
|
+
): ThirteenFFund[] {
|
|
127
|
+
const byCik = new Map<string, ThirteenFFund[]>();
|
|
128
|
+
for (const fund of funds) byCik.set(fund.cik, [...(byCik.get(fund.cik) ?? []), fund]);
|
|
129
|
+
return [...byCik.values()].map((names) => {
|
|
130
|
+
if (names.length === 1) return names[0]!;
|
|
131
|
+
const filed = reports?.get(names[0]!.cik)?.filings.at(-1)?.companyName;
|
|
132
|
+
const longest = names.reduce((best, fund) => (fund.name.length > best.name.length ? fund : best));
|
|
133
|
+
return { ...longest, name: filed || longest.name };
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
99
137
|
export function buildBrowserRows(options: {
|
|
100
138
|
funds?: ThirteenFFund[];
|
|
101
139
|
topFunds?: ThirteenFTopFund[];
|
|
@@ -34,6 +34,81 @@ function atPeriod(data: FundDetailData, period: string): FundDetailData | null {
|
|
|
34
34
|
return { ...data, latestForm: data.previousForm, latestReport: data.previousReport, latestHoldings: data.previousHoldings, previousForm: null, previousReport: undefined, previousHoldings: [] };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** One line of an ETF's holdings file, as MEMB lists it: weight is a fraction of the fund. */
|
|
38
|
+
export interface EtfHoldingLine {
|
|
39
|
+
symbol: string | null;
|
|
40
|
+
weight: number | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface ManagerEtfRow {
|
|
44
|
+
id: string;
|
|
45
|
+
ticker: string;
|
|
46
|
+
issuer: string;
|
|
47
|
+
/** Share of the manager's 13F share positions. */
|
|
48
|
+
weight: number;
|
|
49
|
+
/** Share of the ETF: 0 when it does not hold the name, null when the 13F line has no ticker to match. */
|
|
50
|
+
etfWeight: number | null;
|
|
51
|
+
/** The smaller of the two weights: how much of this position the ETF already holds. */
|
|
52
|
+
shared: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ManagerEtfOverlap {
|
|
56
|
+
/** The manager's share positions, largest first. */
|
|
57
|
+
rows: ManagerEtfRow[];
|
|
58
|
+
/** Sum of the smaller weight per name. */
|
|
59
|
+
overlap: number;
|
|
60
|
+
/** Half the summed absolute weight differences over every name either holds. */
|
|
61
|
+
activeShare: number;
|
|
62
|
+
/** The manager's positions the ETF does not hold, or that have no ticker to match, largest first. */
|
|
63
|
+
missing: ManagerEtfRow[];
|
|
64
|
+
missingWeight: number;
|
|
65
|
+
/** 13F lines left out of the weights: options, and principal amounts that are not shares. */
|
|
66
|
+
leftOut: { options: number; principal: number };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** BRK.B in a 13F and BRK-B in a holdings file are one share class. */
|
|
70
|
+
const symbolKey = (symbol: string) => symbol.trim().toUpperCase().replace(/[./\s]+/g, "-");
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A manager's latest 13F against an ETF's holdings file. The manager's weights
|
|
74
|
+
* cover its share positions (options and principal amounts left out), the
|
|
75
|
+
* ETF's its whole file (cash and lines without a ticker included), so both sum
|
|
76
|
+
* to one and active share is one minus the overlap.
|
|
77
|
+
*/
|
|
78
|
+
export function buildManagerEtfOverlap(manager: FundDetailData, etf: readonly EtfHoldingLine[]): ManagerEtfOverlap | null {
|
|
79
|
+
const lines = buildFundHoldingRows(manager).filter((row) => row.action !== "exit" && row.value != null && row.value > 0);
|
|
80
|
+
const leftOut = { options: 0, principal: 0 };
|
|
81
|
+
const positions = new Map<string, { id: string; ticker: string; issuer: string; value: number }>();
|
|
82
|
+
for (const row of lines) {
|
|
83
|
+
if (row.putCall) { leftOut.options += 1; continue; }
|
|
84
|
+
if (row.shareType.toUpperCase() === "PRN") { leftOut.principal += 1; continue; }
|
|
85
|
+
const key = row.ticker ? symbolKey(row.ticker) : `cusip:${row.cusip || row.id}`;
|
|
86
|
+
const position = positions.get(key);
|
|
87
|
+
if (position) position.value += row.value!;
|
|
88
|
+
else positions.set(key, { id: row.id, ticker: row.ticker, issuer: row.issuer, value: row.value! });
|
|
89
|
+
}
|
|
90
|
+
const total = [...positions.values()].reduce((sum, row) => sum + row.value, 0);
|
|
91
|
+
const etfWeights = new Map<string, number>();
|
|
92
|
+
let etfTotal = 0;
|
|
93
|
+
for (const line of etf) {
|
|
94
|
+
if (line.weight == null || !Number.isFinite(line.weight) || line.weight <= 0) continue;
|
|
95
|
+
etfTotal += line.weight;
|
|
96
|
+
if (line.symbol) etfWeights.set(symbolKey(line.symbol), (etfWeights.get(symbolKey(line.symbol)) ?? 0) + line.weight);
|
|
97
|
+
}
|
|
98
|
+
if (!(total > 0) || !(etfTotal > 0)) return null;
|
|
99
|
+
const rows = [...positions].map(([key, row]): ManagerEtfRow => {
|
|
100
|
+
const weight = row.value / total;
|
|
101
|
+
const etfWeight = row.ticker ? (etfWeights.get(key) ?? 0) / etfTotal : null;
|
|
102
|
+
return { id: row.id, ticker: row.ticker, issuer: row.issuer, weight, etfWeight, shared: Math.min(weight, etfWeight ?? 0) };
|
|
103
|
+
}).sort((a, b) => b.weight - a.weight);
|
|
104
|
+
const overlap = rows.reduce((sum, row) => sum + row.shared, 0);
|
|
105
|
+
// The ETF's weight in names the manager does not hold, cash and untickered lines included.
|
|
106
|
+
const etfOnly = 1 - rows.reduce((sum, row) => sum + (row.etfWeight ?? 0), 0);
|
|
107
|
+
const activeShare = (rows.reduce((sum, row) => sum + Math.abs(row.weight - (row.etfWeight ?? 0)), 0) + Math.max(0, etfOnly)) / 2;
|
|
108
|
+
const missing = rows.filter((row) => !row.etfWeight);
|
|
109
|
+
return { rows, overlap, activeShare, missing, missingWeight: missing.reduce((sum, row) => sum + row.weight, 0), leftOut };
|
|
110
|
+
}
|
|
111
|
+
|
|
37
112
|
export function buildFundOverlap(first: FundDetailData, second: FundDetailData): FundOverlapRow[] {
|
|
38
113
|
const period = overlapPeriod(first, second);
|
|
39
114
|
const left = period ? atPeriod(first, period) : null;
|
|
@@ -46,12 +46,14 @@ import {
|
|
|
46
46
|
buildTimelineColumns,
|
|
47
47
|
buildTimelineRows,
|
|
48
48
|
inferBrowserTabFromQuery,
|
|
49
|
+
quartersBehindLatest,
|
|
49
50
|
selectedIndexById,
|
|
50
51
|
sortBrowserRows,
|
|
51
52
|
sortFilingPositionRows,
|
|
52
53
|
sortHoldingRows,
|
|
53
54
|
sortTimelineRows,
|
|
54
55
|
} from "./model";
|
|
56
|
+
import { isOptionType, isStaleFiling, quartersOldText } from "./report-notes";
|
|
55
57
|
import {
|
|
56
58
|
renderBrowserCell,
|
|
57
59
|
renderFilingPositionCell,
|
|
@@ -479,15 +481,22 @@ export function FundDetailView({
|
|
|
479
481
|
}
|
|
480
482
|
});
|
|
481
483
|
|
|
484
|
+
const quartersBehind = quartersBehindLatest(data?.latestForm?.periodOfReport);
|
|
485
|
+
const staleFiling = isStaleFiling(quartersBehind);
|
|
482
486
|
const holdingStats: StatItem[] = [
|
|
483
487
|
{ id: "reported", label: "Reported", value: data?.latestForm?.periodOfReport ?? "--",
|
|
484
|
-
detail: `filed ${data?.latestForm?.filedAsOfDate || "--"}${data?.latestForm && amendmentKind(data.latestForm) === "restatement" ? ", restated" : ""}` }
|
|
488
|
+
detail: `filed ${data?.latestForm?.filedAsOfDate || "--"}${data?.latestForm && amendmentKind(data.latestForm) === "restatement" ? ", restated" : ""}${staleFiling ? `, ${quartersOldText(quartersBehind)}` : ""}`,
|
|
489
|
+
...(staleFiling ? { tone: "warning" as const } : {}) },
|
|
485
490
|
data && hasComparable13FQuarter(data)
|
|
486
491
|
? { id: "compared", label: "Compared with", value: data.previousForm!.periodOfReport }
|
|
487
492
|
: { id: "compared", label: "Compared with", value: "No prior quarter", tone: "muted" },
|
|
488
493
|
...(data?.latestReport && data.latestReport.filings.length > 1
|
|
489
494
|
? [{ id: "combined", label: "Combined", value: `${data.latestReport.filings.length} filings` }]
|
|
490
495
|
: []),
|
|
496
|
+
// The value basis of option rows, like a unit: only for a fund that holds them.
|
|
497
|
+
...(holdingRows.some((row) => isOptionType(row.putCall))
|
|
498
|
+
? [{ id: "options", label: "CALL/PUT", value: "underlying value", tone: "muted" as const }]
|
|
499
|
+
: []),
|
|
491
500
|
];
|
|
492
501
|
|
|
493
502
|
usePaneNoticeFooter({
|