gloomberb 0.16.3 → 0.16.5
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 +7 -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 +42 -17
- package/src/account/upgrade-personalization.ts +57 -0
- package/src/account/upgrade-tickers.ts +124 -0
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +58 -18
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +16 -1
- package/src/api-client/market-discovery.ts +10 -1
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +95 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +46 -10
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +74 -2
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +26 -2
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +61 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/chart-series.ts +11 -1
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +19 -4
- package/src/cli/commands/fred-series.ts +61 -0
- package/src/cli/commands/market.ts +744 -181
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +425 -0
- package/src/cli/commands/overview.ts +251 -40
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +109 -15
- package/src/cli/commands/system.ts +151 -24
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +149 -40
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +150 -17
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +22 -8
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/glossary.ts +429 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/history-rows.ts +48 -7
- package/src/cli/index-roots.ts +58 -0
- package/src/cli/index.ts +29 -12
- package/src/cli/known-gaps.ts +27 -0
- package/src/cli/listing-arg.ts +595 -26
- package/src/cli/not-a-ticker.ts +44 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/access-gate.ts +5 -0
- package/src/cli/pane-functions/capabilities.ts +11 -4
- package/src/cli/pane-functions/catalog.ts +48 -7
- package/src/cli/pane-functions/data.ts +48 -13
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +41 -19
- package/src/cli/pane-functions/freshness.ts +531 -32
- package/src/cli/pane-functions/function-help.ts +77 -25
- package/src/cli/pane-functions/headless.ts +50 -21
- package/src/cli/pane-functions/index.ts +66 -10
- package/src/cli/pane-functions/market-session.ts +147 -0
- package/src/cli/pane-functions/options.ts +77 -25
- package/src/cli/pane-functions/report-notices.ts +81 -0
- package/src/cli/pane-functions/report.ts +19 -8
- package/src/cli/pane-functions/resolver.ts +53 -18
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +199 -30
- package/src/cli/registry.ts +2 -1
- package/src/cli/report-tables.ts +3 -0
- package/src/cli/result.ts +53 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +9 -0
- package/src/cli/symbol-list.ts +172 -0
- package/src/cli/ticker-resolution.ts +223 -30
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +6 -2
- package/src/components/chart/composite/composite-chart.tsx +83 -10
- package/src/components/chart/composite/legend.tsx +88 -8
- package/src/components/chart/composite/panel-surface.tsx +44 -17
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -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/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- 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/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/command-bar/workflow/tickers.ts +23 -4
- package/src/components/data-table/view.tsx +28 -9
- package/src/components/layout/detached-pane-shell.tsx +9 -0
- package/src/components/layout/floating-pane.tsx +9 -2
- package/src/components/layout/header.tsx +20 -5
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +40 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/model.ts +35 -1
- package/src/components/layout/pane/header.tsx +26 -2
- package/src/components/layout/pane/index.tsx +12 -2
- package/src/components/layout/pane/sidebar.tsx +78 -10
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/drag/index.ts +43 -9
- package/src/components/layout/shell/drag/live.ts +87 -6
- package/src/components/layout/shell/drag/runtime.ts +62 -20
- package/src/components/layout/shell/index.tsx +71 -12
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +33 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +216 -28
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +69 -23
- package/src/components/metric-treemap/heat-surface.tsx +37 -9
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- 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-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +50 -41
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
- 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/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +24 -1
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +17 -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 +49 -0
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +20 -1
- package/src/components/ui/data-table/visible-range.ts +2 -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 +13 -2
- package/src/components/ui/index.ts +1 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +44 -5
- 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 +7416 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +75 -5
- package/src/i18n/ja.ts +75 -5
- package/src/i18n/ko.ts +75 -5
- package/src/i18n/zh-cn.ts +75 -5
- package/src/i18n/zh-tw.ts +75 -5
- package/src/layout/desks.ts +2 -3
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/market-data/coordinator/quotes.ts +2 -2
- 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 +193 -30
- package/src/market-data/market/status.ts +59 -23
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +22 -2
- package/src/market-data/quotes/metadata.ts +8 -9
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +61 -9
- package/src/market-data/result-types.ts +2 -0
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +2 -56
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +37 -8
- package/src/plugins/builtin/account-management/password-dialog.tsx +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/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +41 -9
- package/src/plugins/builtin/alerts/pane.tsx +8 -0
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- 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 +4 -2
- package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +71 -12
- package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
- 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/index.tsx +2 -0
- package/src/plugins/builtin/awards/pane.tsx +3 -1
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +70 -13
- package/src/plugins/builtin/cds/headless.ts +116 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +193 -31
- package/src/plugins/builtin/cds/pane.tsx +56 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
- package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -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.ts +8 -3
- package/src/plugins/builtin/chart-composer/index.tsx +9 -2
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- 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/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +50 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
- package/src/plugins/builtin/cloud/askg/model.ts +156 -78
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
- package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -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 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +19 -5
- 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/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +116 -67
- 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/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +23 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
- package/src/plugins/builtin/credit-conditions/series.ts +26 -0
- package/src/plugins/builtin/credit-documents/headless.ts +31 -1
- 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/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -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/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-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +70 -22
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/pane.tsx +3 -1
- package/src/plugins/builtin/fear-greed/index.tsx +4 -0
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- 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 +70 -9
- 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/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- 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 +64 -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 +114 -20
- 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/index.tsx +18 -8
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- 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 +62 -14
- 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 +42 -134
- package/src/plugins/builtin/holders/pane.tsx +14 -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 +27 -10
- 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/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +26 -6
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +27 -12
- package/src/plugins/builtin/iv-history/index.tsx +5 -3
- package/src/plugins/builtin/iv-history/model.ts +172 -20
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +28 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +68 -3
- package/src/plugins/builtin/macro-day/headless.ts +18 -12
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +66 -15
- package/src/plugins/builtin/macro-day/pane.tsx +34 -20
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +102 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +11 -3
- package/src/plugins/builtin/market-movers/model.ts +101 -17
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- 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 +7 -2
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +3 -6
- package/src/plugins/builtin/mna/headless.ts +15 -3
- 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/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +162 -13
- 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 +5 -2
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +75 -18
- package/src/plugins/builtin/options-scenario/headless.ts +72 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/client.ts +40 -6
- package/src/plugins/builtin/perps/equity-row.tsx +33 -8
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +45 -30
- package/src/plugins/builtin/perps/index.tsx +18 -1
- package/src/plugins/builtin/perps/model.ts +32 -6
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +90 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
- package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +6 -2
- package/src/plugins/builtin/power/headless.ts +71 -7
- package/src/plugins/builtin/power/index.tsx +4 -1
- package/src/plugins/builtin/power/model.ts +72 -1
- package/src/plugins/builtin/power/pane.tsx +32 -9
- package/src/plugins/builtin/rate-path/headless.ts +11 -3
- package/src/plugins/builtin/realized-vol/headless.ts +8 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- 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/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- 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/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/series-inventory.ts +91 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +69 -0
- 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/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +4 -4
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +59 -2
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +21 -4
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/index.tsx +3 -10
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- 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/model.ts +1 -1
- package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
- 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/headless.ts +43 -21
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- 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 +48 -4
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +1 -0
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
- package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +125 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -2
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- 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/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +129 -64
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +173 -28
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -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 +48 -1
- package/src/remote/app-host.tsx +25 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +126 -59
- package/src/remote/matching.ts +69 -0
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +63 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +32 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +3 -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 +27 -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 +21 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/box.tsx +4 -1
- package/src/renderers/dom/host/chart-surface.tsx +6 -2
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +14 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/size-observer.ts +26 -0
- package/src/renderers/dom/host/surface-3d.tsx +7 -2
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +74 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +6 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- 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 +107 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +145 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +26 -17
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
- package/src/sources/history-result.ts +1 -0
- package/src/sources/listing-symbols.ts +14 -5
- package/src/sources/provider-errors.ts +88 -3
- 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 +9 -5
- package/src/sources/provider-router/financial-routes.ts +12 -5
- package/src/sources/provider-router/financials.ts +55 -15
- package/src/sources/provider-router/history.ts +68 -34
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/provider-router/search.ts +1 -0
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +5 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +25 -0
- package/src/tickers/open-target.ts +3 -2
- package/src/tickers/search/index.ts +67 -9
- package/src/tickers/search/ranking.ts +78 -18
- package/src/tickers/search/types.ts +10 -2
- package/src/tickers/starter-symbols.ts +8 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/resolve.ts +96 -30
- package/src/time-series/types.ts +4 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +67 -1
- package/src/types/data-provider.ts +5 -0
- package/src/types/financials.ts +52 -1
- package/src/types/headless.ts +72 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +68 -3
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/host.tsx +26 -4
- package/src/ui/index.tsx +2 -0
- package/src/ui/live-resize.ts +81 -0
- package/src/ui/live-stretch.ts +121 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/pane-fill.ts +11 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/cli-output.ts +21 -2
- 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/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 +437 -52
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +120 -1
- package/src/utils/format.ts +17 -3
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +44 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +130 -40
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +178 -36
- package/src/utils/sec.ts +98 -40
- package/src/utils/throttled-fetch.ts +51 -22
- package/src/utils/utc-time.ts +51 -4
|
@@ -20,6 +20,16 @@ export interface HolderReportFacts {
|
|
|
20
20
|
listingCurrency?: string | null;
|
|
21
21
|
/** Left out when the report's closing line already carries it. */
|
|
22
22
|
asOf?: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* What the list is as of, in place of `asOf`: `as of <date>` when every
|
|
25
|
+
* row shares one report date, `latest period per holder` when they differ.
|
|
26
|
+
*/
|
|
27
|
+
period?: string | null;
|
|
28
|
+
/**
|
|
29
|
+
* False when the list is not the source's largest holders but the few
|
|
30
|
+
* filers that report the line at all (a home line abroad): no "top".
|
|
31
|
+
*/
|
|
32
|
+
ranked?: boolean;
|
|
23
33
|
/** Rows printed. */
|
|
24
34
|
shown: number;
|
|
25
35
|
/** Rows the source returned, before any limit. */
|
|
@@ -34,15 +44,39 @@ export function moneyColumnHeader(label: string, currency?: string | null): stri
|
|
|
34
44
|
return unit ? `${label} (${unit})` : label;
|
|
35
45
|
}
|
|
36
46
|
|
|
37
|
-
function holderCountText(shown: number, reported: number, total?: number | null): string {
|
|
47
|
+
function holderCountText(shown: number, reported: number, total?: number | null, ranked = true): string {
|
|
38
48
|
if (total != null && Number.isFinite(total) && total >= reported) {
|
|
39
49
|
return `${shown.toLocaleString("en-US")} of ${total.toLocaleString("en-US")} holders`;
|
|
40
50
|
}
|
|
41
51
|
if (reported === 0) return "none reported";
|
|
52
|
+
// A home line's few filers are all there is, not a top of anything.
|
|
53
|
+
if (!ranked) return shown < reported ? `${shown} of ${reported} reported` : `${reported} ${reported === 1 ? "holder" : "holders"} reported`;
|
|
42
54
|
// Without a total the source's list is its largest holders, cut where it cuts it.
|
|
43
55
|
return shown < reported ? `${shown} of top ${reported} reported` : `top ${reported} reported`;
|
|
44
56
|
}
|
|
45
57
|
|
|
58
|
+
/**
|
|
59
|
+
* What a holder list is as of. Each holder's row is its latest filed
|
|
60
|
+
* period, so one date is claimed only when every row has it; rows of
|
|
61
|
+
* different quarters read `latest period per holder`, and an empty list
|
|
62
|
+
* keeps the source's date.
|
|
63
|
+
*/
|
|
64
|
+
export function holderListPeriod(
|
|
65
|
+
rows: ReadonlyArray<{ reportDate?: unknown }>,
|
|
66
|
+
asOf?: string | null,
|
|
67
|
+
): string | null {
|
|
68
|
+
const dates = new Set(rows.flatMap((row) => typeof row.reportDate === "string" && row.reportDate ? [row.reportDate] : []));
|
|
69
|
+
if (dates.size > 1) return "latest period per holder";
|
|
70
|
+
const [only] = dates;
|
|
71
|
+
const date = only ?? asOf;
|
|
72
|
+
return date ? `as of ${date}` : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Whether a holder list's rows are of more than one report date. */
|
|
76
|
+
export function holderPeriodsDiffer(rows: ReadonlyArray<{ reportDate?: unknown }>): boolean {
|
|
77
|
+
return holderListPeriod(rows) === "latest period per holder";
|
|
78
|
+
}
|
|
79
|
+
|
|
46
80
|
/** A venue the app knows by its short name (NasdaqGS is NASDAQ); any other as the source wrote it. */
|
|
47
81
|
function venueLabel(exchange?: string | null): string {
|
|
48
82
|
const canonical = canonicalExchange(exchange ?? "");
|
|
@@ -51,15 +85,15 @@ function venueLabel(exchange?: string | null): string {
|
|
|
51
85
|
|
|
52
86
|
/** What the list is, after the listing is named: its unit, date and how much of it is shown. */
|
|
53
87
|
export function holderListFacts(
|
|
54
|
-
facts: Pick<HolderReportFacts, "currency" | "listingCurrency" | "asOf" | "shown" | "reported" | "total">,
|
|
88
|
+
facts: Pick<HolderReportFacts, "currency" | "listingCurrency" | "asOf" | "period" | "shown" | "reported" | "total" | "ranked">,
|
|
55
89
|
): string[] {
|
|
56
90
|
const unit = currencyUnitLabel(facts.currency);
|
|
57
91
|
// Dollars on a London line: say they are the values' unit, not the listing's.
|
|
58
92
|
const otherUnit = unit && facts.listingCurrency?.trim() && facts.listingCurrency.trim() !== facts.currency?.trim();
|
|
59
93
|
return [
|
|
60
94
|
otherUnit ? `values in ${unit}` : unit,
|
|
61
|
-
facts.asOf ? `as of ${facts.asOf}` : "",
|
|
62
|
-
holderCountText(facts.shown, facts.reported, facts.total),
|
|
95
|
+
facts.period ?? (facts.asOf ? `as of ${facts.asOf}` : ""),
|
|
96
|
+
holderCountText(facts.shown, facts.reported, facts.total, facts.ranked),
|
|
63
97
|
].filter(Boolean);
|
|
64
98
|
}
|
|
65
99
|
|
|
@@ -132,5 +166,6 @@ export function nonUsHolderCaveat(exchange?: string | null, currency?: string |
|
|
|
132
166
|
if (!isNonUsHolderListing(exchange, currency)) return null;
|
|
133
167
|
const canonical = canonicalExchange(exchange ?? "");
|
|
134
168
|
const venue = resolveExchangeTimeZone(canonical) ? canonical : "local";
|
|
135
|
-
|
|
169
|
+
// Few filers report a line abroad, so a small position can lead the list.
|
|
170
|
+
return `Positions come from institutional filings (mostly US 13F), not the ${venue} share register, so the line's largest holders may be missing.`;
|
|
136
171
|
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { HeadlessPaneColumn } from "../../../types/plugin";
|
|
2
|
+
import type { HolderData, ShareBasis } from "../../../types/financials";
|
|
3
|
+
import { formatCompact, formatPercentRaw } from "../../../utils/format";
|
|
4
|
+
import {
|
|
5
|
+
displayDate,
|
|
6
|
+
formatMoneyCompact,
|
|
7
|
+
formatPercentHeld,
|
|
8
|
+
formatSignedCompact,
|
|
9
|
+
holderPercent,
|
|
10
|
+
holderValueCurrency,
|
|
11
|
+
resolveHolderOwnershipPercent,
|
|
12
|
+
} from "./format";
|
|
13
|
+
import {
|
|
14
|
+
holderListPeriod,
|
|
15
|
+
holderPeriodsDiffer,
|
|
16
|
+
holderShareBasisMarker,
|
|
17
|
+
holderShareBasisNote,
|
|
18
|
+
holderValueBasis,
|
|
19
|
+
holdersHeaderLine,
|
|
20
|
+
moneyColumnHeader,
|
|
21
|
+
nonUsHolderCaveat,
|
|
22
|
+
sharedReportDate,
|
|
23
|
+
} from "./report-header";
|
|
24
|
+
import { buildRows, DEFAULT_SORT, sortRows } from "./table-model";
|
|
25
|
+
import type { HolderColumnId, SortPreference } from "./types";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A holder as `holders` and `fn HDS` report it; the keys are the JSON
|
|
29
|
+
* contract. `value` is in `currency`, the values' own currency; the percents
|
|
30
|
+
* are in percent (0.59 is 0.59% of the shares outstanding, 13.15 a 13.15%
|
|
31
|
+
* change on the quarter). A figure the source did not give is null.
|
|
32
|
+
*/
|
|
33
|
+
export interface HolderReportRow {
|
|
34
|
+
name: string;
|
|
35
|
+
ownerType: string;
|
|
36
|
+
value: number | null;
|
|
37
|
+
shares: number | null;
|
|
38
|
+
changeShares: number | null;
|
|
39
|
+
changePercent: number | null;
|
|
40
|
+
percentHeld: number | null;
|
|
41
|
+
reportDate: string | null;
|
|
42
|
+
currency: string;
|
|
43
|
+
shareBasis: ShareBasis | null;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Columns a source fills only when it reports the quarter's change. */
|
|
48
|
+
const CHANGE_COLUMN_KEYS = new Set(["changeShares", "changePercent"]);
|
|
49
|
+
/** Shown only when some row is held as depositary receipts, as on a home line abroad. */
|
|
50
|
+
const BASIS_COLUMN_KEY = "shareBasis";
|
|
51
|
+
const num = (value: unknown) => (typeof value === "number" && Number.isFinite(value) ? value : null);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The HDS report's columns, which `holders --csv` and `--json` share. CSV
|
|
55
|
+
* reads `format`, so a value drawn as a plain figure exports its full number
|
|
56
|
+
* under a header naming the unit (`Mkt value (USD)`, `Held (%)`); the text
|
|
57
|
+
* report draws `textFormat`, with the currency sign and `<0.01%`.
|
|
58
|
+
*/
|
|
59
|
+
export const HOLDER_REPORT_COLUMNS: HeadlessPaneColumn[] = [
|
|
60
|
+
{ key: "name", header: "Holder" },
|
|
61
|
+
{ key: "ownerType", header: "Type" },
|
|
62
|
+
{
|
|
63
|
+
key: "value",
|
|
64
|
+
header: "Mkt value",
|
|
65
|
+
align: "right",
|
|
66
|
+
format: (value) => num(value) == null ? "-" : formatCompact(num(value)!),
|
|
67
|
+
textFormat: (value, row) => formatMoneyCompact(num(value) ?? undefined, String(row.currency ?? "USD")),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
key: "shares",
|
|
71
|
+
header: "Amount",
|
|
72
|
+
align: "right",
|
|
73
|
+
format: (value) => num(value) == null ? "-" : formatCompact(num(value)!),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: BASIS_COLUMN_KEY,
|
|
77
|
+
header: "Basis",
|
|
78
|
+
format: (_value, row) => holderShareBasisMarker(row),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: "changeShares",
|
|
82
|
+
header: "Chg",
|
|
83
|
+
align: "right",
|
|
84
|
+
format: (value) => formatSignedCompact(num(value) ?? undefined),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
key: "changePercent",
|
|
88
|
+
header: "Chg%",
|
|
89
|
+
align: "right",
|
|
90
|
+
format: (value) => num(value) == null ? "-" : formatPercentRaw(num(value)!),
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
key: "percentHeld",
|
|
94
|
+
header: "Held",
|
|
95
|
+
align: "right",
|
|
96
|
+
format: (value) => num(value) == null ? "-" : `${num(value)!.toFixed(2)}%`,
|
|
97
|
+
textFormat: (value) => formatPercentHeld(num(value)),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
key: "reportDate",
|
|
101
|
+
header: "Period",
|
|
102
|
+
format: (value) => displayDate(typeof value === "string" ? value : undefined),
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
/** `--sort` values, the same for `holders` and `fn HDS`. */
|
|
107
|
+
export const HOLDER_SORT_KEYS: Record<string, HolderColumnId> = {
|
|
108
|
+
holder: "holder",
|
|
109
|
+
value: "value",
|
|
110
|
+
shares: "shares",
|
|
111
|
+
change: "changeShares",
|
|
112
|
+
"change-percent": "changePercent",
|
|
113
|
+
held: "percentHeld",
|
|
114
|
+
date: "reportDate",
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Every holder of the list, largest value first unless another sort is
|
|
119
|
+
* asked for, with the stake and change in percent. A holder without a value
|
|
120
|
+
* sorts after those with one, whichever the direction. `ownerTypes` keeps
|
|
121
|
+
* only those kinds (`insider`, `13f`).
|
|
122
|
+
*/
|
|
123
|
+
export function holderReportRows(
|
|
124
|
+
data: HolderData,
|
|
125
|
+
{
|
|
126
|
+
marketCap,
|
|
127
|
+
sort = DEFAULT_SORT,
|
|
128
|
+
ownerTypes,
|
|
129
|
+
}: { marketCap?: number; sort?: SortPreference; ownerTypes?: ReadonlySet<string> } = {},
|
|
130
|
+
): HolderReportRow[] {
|
|
131
|
+
const holders = ownerTypes ? data.holders.filter((holder) => ownerTypes.has(holder.ownerType)) : data.holders;
|
|
132
|
+
// The values' own currency: dollars from the 13F filings on a London line.
|
|
133
|
+
const currency = holderValueCurrency(data, "USD")!;
|
|
134
|
+
return sortRows(buildRows({ ...data, holders }), sort, marketCap).map((row) => ({
|
|
135
|
+
name: row.name,
|
|
136
|
+
ownerType: row.ownerType,
|
|
137
|
+
value: row.value ?? null,
|
|
138
|
+
shares: row.shares ?? null,
|
|
139
|
+
changeShares: row.changeShares ?? null,
|
|
140
|
+
changePercent: holderPercent(row.changePercent),
|
|
141
|
+
percentHeld: holderPercent(resolveHolderOwnershipPercent(row, marketCap)),
|
|
142
|
+
reportDate: row.reportDate ?? null,
|
|
143
|
+
currency,
|
|
144
|
+
shareBasis: row.shareBasis ?? null,
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** The report dates of the rows, newest first: one when the list is of one quarter. */
|
|
149
|
+
export function holderReportDates(rows: readonly HolderReportRow[]): string[] {
|
|
150
|
+
return [...new Set(rows.flatMap((row) => row.reportDate ? [row.reportDate] : []))].sort().reverse();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** What the JSON rows' numbers are in, for `metadata.units`. */
|
|
154
|
+
export function holderReportUnits(valueCurrency: string): Record<string, string> {
|
|
155
|
+
return { value: valueCurrency, changePercent: "%", percentHeld: "%" };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Whether any holder carries the quarter's change; many sources report none. */
|
|
159
|
+
function holderChangeReported(rows: readonly HolderReportRow[]): boolean {
|
|
160
|
+
return rows.some((row) => row.changeShares != null || row.changePercent != null);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The report's columns for these rows: the change columns only when a row
|
|
165
|
+
* has a change, the basis column only when a row is held as receipts, and
|
|
166
|
+
* the value column named with its currency.
|
|
167
|
+
*/
|
|
168
|
+
export function holderReportColumns(rows: readonly HolderReportRow[], valueCurrency: string | null | undefined): HeadlessPaneColumn[] {
|
|
169
|
+
const changeReported = holderChangeReported(rows);
|
|
170
|
+
const marked = rows.some((row) => holderShareBasisMarker(row));
|
|
171
|
+
return HOLDER_REPORT_COLUMNS
|
|
172
|
+
.filter((column) => changeReported || !CHANGE_COLUMN_KEYS.has(column.key))
|
|
173
|
+
.filter((column) => marked || column.key !== BASIS_COLUMN_KEY)
|
|
174
|
+
.map((column) => column.key === "value" ? { ...column, header: moneyColumnHeader(column.header, valueCurrency) } : column);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The lines above the HDS table, which `holders --csv` also closes with: the
|
|
179
|
+
* listing, unit and count, how a value was reached (and where the change is
|
|
180
|
+
* when the source gives none), and what the positions and shares are.
|
|
181
|
+
*/
|
|
182
|
+
export function holderReportNotices({
|
|
183
|
+
data,
|
|
184
|
+
requested,
|
|
185
|
+
shown,
|
|
186
|
+
reported,
|
|
187
|
+
total,
|
|
188
|
+
sort = DEFAULT_SORT,
|
|
189
|
+
}: {
|
|
190
|
+
data: HolderData;
|
|
191
|
+
/** The symbol as asked for, which `fn 13F` takes. */
|
|
192
|
+
requested: string;
|
|
193
|
+
shown: readonly HolderReportRow[];
|
|
194
|
+
/** Holders on the list before a limit. */
|
|
195
|
+
reported: number;
|
|
196
|
+
total: number | null;
|
|
197
|
+
sort?: SortPreference;
|
|
198
|
+
}): { notices: string[]; valueBasis: string; positionsBasis: string | null; changeReported: boolean } {
|
|
199
|
+
const valueCurrency = holderValueCurrency(data, "USD")!;
|
|
200
|
+
const changeReported = holderChangeReported(shown);
|
|
201
|
+
const valueBasis = holderValueBasis(sharedReportDate(shown), data.valueBasis, valueCurrency);
|
|
202
|
+
const positionsBasis = shown.length > 0 ? nonUsHolderCaveat(data.exchange, data.currency ?? "USD") : null;
|
|
203
|
+
// The title names the ticker and the closing line carries the as-of date,
|
|
204
|
+
// which is one date only when every row has it.
|
|
205
|
+
const header = holdersHeaderLine({
|
|
206
|
+
name: data.name,
|
|
207
|
+
symbol: data.symbol && data.symbol !== requested ? data.symbol : null,
|
|
208
|
+
exchange: data.exchange,
|
|
209
|
+
currency: valueCurrency,
|
|
210
|
+
listingCurrency: data.currency,
|
|
211
|
+
period: holderPeriodsDiffer(shown) ? holderListPeriod(shown) : null,
|
|
212
|
+
shown: shown.length,
|
|
213
|
+
reported,
|
|
214
|
+
total,
|
|
215
|
+
ranked: !positionsBasis,
|
|
216
|
+
});
|
|
217
|
+
const basis = shown.length === 0 ? null : [
|
|
218
|
+
`Mkt value = ${valueBasis}.`,
|
|
219
|
+
changeReported ? "" : `Change vs prior quarter: not reported by this source; see fn 13F ${requested}`,
|
|
220
|
+
].filter(Boolean).join(" ");
|
|
221
|
+
return {
|
|
222
|
+
notices: [header, basis, positionsBasis, holderShareBasisNote(data, shown), unvaluedHoldersNote(shown, sort)]
|
|
223
|
+
.filter((line): line is string => !!line),
|
|
224
|
+
valueBasis,
|
|
225
|
+
positionsBasis,
|
|
226
|
+
changeReported,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Holders the list gives no value for (a home line's position its filing
|
|
232
|
+
* could not tie to a priced security) sort after every valued one, and a
|
|
233
|
+
* value-ordered report says so rather than ranking them silently.
|
|
234
|
+
*/
|
|
235
|
+
export function unvaluedHoldersNote(rows: readonly HolderReportRow[], sort: SortPreference = DEFAULT_SORT): string | null {
|
|
236
|
+
if (sort.columnId !== "value") return null;
|
|
237
|
+
const unvalued = rows.filter((row) => row.value == null).length;
|
|
238
|
+
if (unvalued === 0 || unvalued === rows.length) return null;
|
|
239
|
+
return `${unvalued} ${unvalued === 1 ? "holder has" : "holders have"} no value and ${unvalued === 1 ? "is" : "are"} listed last.`;
|
|
240
|
+
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import type { DataProvider
|
|
1
|
+
import type { DataProvider } from "../../../types/data-provider";
|
|
2
2
|
import { parseInsiderFiling, type ParsedInsiderFiling } from "./model";
|
|
3
3
|
import { isInsiderForm } from "./insider-data";
|
|
4
|
+
import { filesAsForeignPrivateIssuer } from "./issuer";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
// Recent EDGAR dumps cap at 1,000 mixed forms; older archives are read until
|
|
7
|
+
// this many filings or the company's history ends.
|
|
8
|
+
const SEC_FILING_SCAN_LIMIT = 20_000;
|
|
9
|
+
|
|
10
|
+
export interface InsiderFilingsLoad {
|
|
11
|
+
/** The rows of the company's own Form 4 filings, newest first. */
|
|
12
|
+
parsed: ParsedInsiderFiling[];
|
|
13
|
+
/** Every Form 4 listed was read, none is the company's own, and it reports as a foreign private issuer. */
|
|
14
|
+
foreignPrivateIssuer: boolean;
|
|
15
|
+
/** The SEC lists no filing of any form for the company. */
|
|
16
|
+
noFilings: boolean;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
function throwIfAborted(signal: AbortSignal | undefined): void {
|
|
@@ -18,29 +21,41 @@ function throwIfAborted(signal: AbortSignal | undefined): void {
|
|
|
18
21
|
throw signal.reason instanceof Error ? signal.reason : new Error("Insider filing load was aborted.");
|
|
19
22
|
}
|
|
20
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Reads the company's Form 4 filings newest first, one at a time, until
|
|
26
|
+
* `limit` of them are its own. A form it filed as an owner of another
|
|
27
|
+
* company's shares is read and left out, so a list of only those is read to
|
|
28
|
+
* the end before it can say there are none.
|
|
29
|
+
*/
|
|
21
30
|
export async function loadParsedInsiderFilings(
|
|
22
31
|
provider: DataProvider,
|
|
23
32
|
symbol: string,
|
|
24
33
|
options: { limit: number; exchange?: string; signal?: AbortSignal },
|
|
25
|
-
): Promise<
|
|
34
|
+
): Promise<InsiderFilingsLoad> {
|
|
35
|
+
if (!provider.getSecFilings) throw new Error("Insider filing data unavailable");
|
|
26
36
|
if (!provider.getSecFilingContent) throw new Error("Insider filing content unavailable");
|
|
27
|
-
const filings =
|
|
28
|
-
provider,
|
|
29
|
-
symbol,
|
|
30
|
-
20_000,
|
|
31
|
-
options.exchange,
|
|
32
|
-
)).slice(0, options.limit);
|
|
37
|
+
const filings = await provider.getSecFilings(symbol, SEC_FILING_SCAN_LIMIT, options.exchange ?? "");
|
|
33
38
|
|
|
34
39
|
const parsed: ParsedInsiderFiling[] = [];
|
|
40
|
+
let own = 0;
|
|
35
41
|
for (const filing of filings) {
|
|
42
|
+
if (own >= options.limit) break;
|
|
43
|
+
if (!isInsiderForm(filing.form)) continue;
|
|
36
44
|
throwIfAborted(options.signal);
|
|
45
|
+
let content: string | null;
|
|
37
46
|
try {
|
|
38
|
-
|
|
39
|
-
parsed.push(...parseInsiderFiling(filing, content));
|
|
47
|
+
content = await provider.getSecFilingContent(filing);
|
|
40
48
|
} catch {
|
|
41
49
|
throwIfAborted(options.signal);
|
|
50
|
+
// An unread filing may be the company's own; it stays as a row that says so.
|
|
42
51
|
parsed.push({ filing, transaction: null, isLoading: false });
|
|
52
|
+
own += 1;
|
|
53
|
+
continue;
|
|
43
54
|
}
|
|
55
|
+
const entries = parseInsiderFiling(filing, content);
|
|
56
|
+
if (entries.length === 0) continue;
|
|
57
|
+
parsed.push(...entries);
|
|
58
|
+
own += 1;
|
|
44
59
|
}
|
|
45
|
-
return parsed;
|
|
60
|
+
return { parsed, foreignPrivateIssuer: own === 0 && filesAsForeignPrivateIssuer(filings), noFilings: filings.length === 0 };
|
|
46
61
|
}
|
|
@@ -3,9 +3,11 @@ import type {
|
|
|
3
3
|
HeadlessPaneContext,
|
|
4
4
|
HeadlessPaneDefinition,
|
|
5
5
|
HeadlessPaneLoadArgs,
|
|
6
|
+
HeadlessPaneRow,
|
|
6
7
|
} from "../../../types/plugin";
|
|
7
8
|
import { formatCompact, formatCurrency } from "../../../utils/format";
|
|
8
|
-
import { loadParsedInsiderFilings } from "./client";
|
|
9
|
+
import { loadParsedInsiderFilings, type InsiderFilingsLoad } from "./client";
|
|
10
|
+
import { insiderEmptyNotice } from "./issuer";
|
|
9
11
|
import {
|
|
10
12
|
buildInsiderRows,
|
|
11
13
|
buildInsiderSummary,
|
|
@@ -15,9 +17,12 @@ import {
|
|
|
15
17
|
matchesInsiderTypeFilter,
|
|
16
18
|
type ParsedInsiderFiling,
|
|
17
19
|
} from "./model";
|
|
18
|
-
import { relevantInsiderAmendments } from "./amendments";
|
|
20
|
+
import { isAmendedInsiderFiling, relevantInsiderAmendments } from "./amendments";
|
|
19
21
|
import { formatInsiderName } from "./display";
|
|
20
22
|
import { SEC_FILINGS } from "../shared/report-freshness";
|
|
23
|
+
import { resolveHeadlessIssuerListing } from "../shared/headless-market-data";
|
|
24
|
+
import { noSecReportsNotice } from "../../../utils/sec";
|
|
25
|
+
import { parsePublicTickerKey } from "../../../utils/exchanges";
|
|
21
26
|
|
|
22
27
|
const INSIDER_COLUMNS: HeadlessPaneColumn[] = [
|
|
23
28
|
{ key: "form", header: "Form" },
|
|
@@ -62,15 +67,23 @@ const INSIDER_COLUMNS: HeadlessPaneColumn[] = [
|
|
|
62
67
|
align: "right",
|
|
63
68
|
format: (value) => value == null ? "-" : `$${formatCompact(Number(value))}`,
|
|
64
69
|
},
|
|
70
|
+
// An amendment's original date, remarks and footnotes, under the amendment's own row.
|
|
71
|
+
{ key: "note", header: "Note", underRow: true, format: (value) => typeof value === "string" ? value : "" },
|
|
65
72
|
];
|
|
66
73
|
|
|
74
|
+
/** What a Form 4/A says about itself, for its last row in the report. */
|
|
75
|
+
function amendmentNote(entry: ParsedInsiderFiling): string {
|
|
76
|
+
const original = entry.disclosure?.originalFilingDate;
|
|
77
|
+
return [original ? `Original filed ${original}` : "", ...buildInsiderDisclosureText(entry).split("\n")].filter(Boolean).join("\n");
|
|
78
|
+
}
|
|
79
|
+
|
|
67
80
|
export interface InsiderHeadlessDependencies {
|
|
68
81
|
loadParsed(
|
|
69
82
|
symbol: string,
|
|
70
83
|
limit: number,
|
|
71
84
|
args: HeadlessPaneLoadArgs,
|
|
72
85
|
ctx: HeadlessPaneContext,
|
|
73
|
-
): Promise<
|
|
86
|
+
): Promise<InsiderFilingsLoad>;
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
const defaultDependencies: InsiderHeadlessDependencies = {
|
|
@@ -80,6 +93,17 @@ const defaultDependencies: InsiderHeadlessDependencies = {
|
|
|
80
93
|
}),
|
|
81
94
|
};
|
|
82
95
|
|
|
96
|
+
/**
|
|
97
|
+
* "CAR Group (ASX) files no SEC reports." for a listing abroad the SEC lists
|
|
98
|
+
* nothing for, as `filings` says it; null for a US listing or a symbol with no
|
|
99
|
+
* venue, whose empty list is only no Form 4.
|
|
100
|
+
*/
|
|
101
|
+
async function noSecReportsEmpty(ctx: HeadlessPaneContext, key: string): Promise<string | null> {
|
|
102
|
+
const listing = await resolveHeadlessIssuerListing(ctx, key);
|
|
103
|
+
if (!listing.exchange) return null;
|
|
104
|
+
return noSecReportsNotice({ symbol: parsePublicTickerKey(key).symbol, exchange: listing.exchange, name: listing.name ?? null });
|
|
105
|
+
}
|
|
106
|
+
|
|
83
107
|
export function createInsiderHeadless(
|
|
84
108
|
dependencies: InsiderHeadlessDependencies = defaultDependencies,
|
|
85
109
|
): HeadlessPaneDefinition<"rows"> {
|
|
@@ -113,7 +137,7 @@ export function createInsiderHeadless(
|
|
|
113
137
|
{
|
|
114
138
|
key: "limit",
|
|
115
139
|
aliases: ["count", "rows"],
|
|
116
|
-
description: "Maximum Form 4 and Form 4/A filings to parse.",
|
|
140
|
+
description: "Maximum of the company's own Form 4 and Form 4/A filings to parse.",
|
|
117
141
|
type: "integer",
|
|
118
142
|
defaultValue: 20,
|
|
119
143
|
minimum: 1,
|
|
@@ -125,7 +149,9 @@ export function createInsiderHeadless(
|
|
|
125
149
|
async load(args, ctx) {
|
|
126
150
|
const symbol = args.symbols[0]!;
|
|
127
151
|
const limit = Number(args.options.limit);
|
|
128
|
-
const parsed = await dependencies.loadParsed(symbol, limit, args, ctx);
|
|
152
|
+
const { parsed, foreignPrivateIssuer, noFilings } = await dependencies.loadParsed(symbol, limit, args, ctx);
|
|
153
|
+
const empty = parsed.length > 0 ? null
|
|
154
|
+
: (noFilings ? await noSecReportsEmpty(ctx, symbol) : null) ?? insiderEmptyNotice(foreignPrivateIssuer);
|
|
129
155
|
const name = String(args.options.name ?? "").trim().toLocaleLowerCase();
|
|
130
156
|
const type = isInsiderTypeFilter(args.options.type) ? args.options.type : "all";
|
|
131
157
|
const owned = name
|
|
@@ -136,8 +162,16 @@ export function createInsiderHeadless(
|
|
|
136
162
|
const incomplete = [...new Set(buildInsiderRows(parsed)
|
|
137
163
|
.filter((row) => row.status !== "parsed" && row.status !== "disclosure")
|
|
138
164
|
.map((row) => row.accessionNumber))];
|
|
165
|
+
// A filing's lines sit together, so its note goes once, under the last of them.
|
|
166
|
+
const rows: HeadlessPaneRow[] = buildInsiderRows(filtered, parsed).map((row, index) => {
|
|
167
|
+
const entry = filtered[index]!;
|
|
168
|
+
const last = filtered[index + 1]?.filing.accessionNumber !== entry.filing.accessionNumber;
|
|
169
|
+
return isAmendedInsiderFiling(entry) && last ? { ...row, note: amendmentNote(entry) || null } : row;
|
|
170
|
+
});
|
|
139
171
|
return {
|
|
140
|
-
rows
|
|
172
|
+
rows,
|
|
173
|
+
// Nothing at all: the company has no Form 4 of its own, which is the whole answer.
|
|
174
|
+
...(empty ? { empty, unavailableSymbols: [] } : {}),
|
|
141
175
|
errors: [
|
|
142
176
|
...incomplete.map((accessionNumber) => `${accessionNumber}: Form 4 transactions are unavailable or incomplete.`),
|
|
143
177
|
...amendments.map((scope) => `${scope.accessionNumber}: Form 4/A is unreconciled; affected transaction totals are unavailable.`),
|
|
@@ -146,11 +180,7 @@ export function createInsiderHeadless(
|
|
|
146
180
|
symbol,
|
|
147
181
|
summary: buildInsiderSummary(owned, Date.now(), parsed),
|
|
148
182
|
amendments,
|
|
149
|
-
|
|
150
|
-
const entry = parsed.find(({ filing }) => filing.accessionNumber === scope.accessionNumber)!;
|
|
151
|
-
return [`Form 4/A ${scope.accessionNumber}${scope.originalFilingDate ? ` | Original filed ${scope.originalFilingDate}` : ""}`,
|
|
152
|
-
buildInsiderDisclosureText(entry)].filter(Boolean).join("\n");
|
|
153
|
-
}),
|
|
183
|
+
foreignPrivateIssuer,
|
|
154
184
|
parsed: new Set(parsed.filter(({ transaction }) => transaction != null).map(({ filing }) => filing.accessionNumber)).size,
|
|
155
185
|
transactions: filtered.filter(({ transaction }) => transaction != null).length,
|
|
156
186
|
requested: limit,
|
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
type StatItem,
|
|
23
23
|
} from "../../../components";
|
|
24
24
|
import { useDebouncedPluginPaneState, usePluginPaneState } from "../../runtime";
|
|
25
|
-
import {
|
|
25
|
+
import { mayBeSecEquityListing, mayBeUsEquityTicker, noSecReportsNotice, nonUsSecListingVenue } from "../../../utils/sec";
|
|
26
|
+
import { parsePublicTickerKey } from "../../../utils/exchanges";
|
|
26
27
|
import { formatCompact } from "../../../utils/format";
|
|
27
28
|
import { nextHeaderSort } from "../../../utils/sort-values";
|
|
28
29
|
import { formatShortDate } from "../../../utils/datetime-format";
|
|
@@ -48,6 +49,7 @@ import {
|
|
|
48
49
|
import { formatInsiderName } from "./display";
|
|
49
50
|
import { insiderHeadless } from "./headless";
|
|
50
51
|
import { isInsiderForm } from "./insider-data";
|
|
52
|
+
import { filesAsForeignPrivateIssuer, insiderEmptyNotice, isOtherIssuerFiling } from "./issuer";
|
|
51
53
|
import { relevantInsiderAmendments } from "./amendments";
|
|
52
54
|
import { usePaneTickerIdentity } from "../../../state/hooks/pane-ticker";
|
|
53
55
|
import {
|
|
@@ -130,7 +132,9 @@ function InsiderView({ width, height, focused }: { width: number; height: number
|
|
|
130
132
|
[setOpenItemIdState],
|
|
131
133
|
);
|
|
132
134
|
const [sort, setSort] = useState<StackSortPreference<InsiderColumnId>>({ columnId: "date", direction: "desc" });
|
|
133
|
-
const eligibleTicker =
|
|
135
|
+
const eligibleTicker = mayBeSecEquityListing(ticker);
|
|
136
|
+
// A listing abroad is looked up by its company; an empty list means it files nothing with the SEC.
|
|
137
|
+
const abroadVenue = ticker ? nonUsSecListingVenue(ticker.metadata.ticker, ticker.metadata.exchange) : null;
|
|
134
138
|
const instrument = instrumentFromTicker(ticker, ticker?.metadata.ticker ?? null);
|
|
135
139
|
|
|
136
140
|
const filingsEntry = useSecFilingsQuery(
|
|
@@ -185,6 +189,17 @@ function InsiderView({ width, height, focused }: { width: number; height: number
|
|
|
185
189
|
scopeKey: `${ticker?.metadata.ticker ?? "none"}:${ticker?.metadata.exchange ?? ""}`,
|
|
186
190
|
targets: visibleForm4Filings,
|
|
187
191
|
});
|
|
192
|
+
// The list also holds the Form 4s the company filed as an owner of another
|
|
193
|
+
// company's shares, which only their documents tell apart. Until one of its
|
|
194
|
+
// own is read, the pages are read on to the end, so a list of none says so.
|
|
195
|
+
const ownerFilingsShown = useMemo(() => visibleForm4Filings.some((filing) => (
|
|
196
|
+
isOtherIssuerFiling(filing, contentMap.get(filing.accessionNumber))
|
|
197
|
+
)), [contentMap, visibleForm4Filings]);
|
|
198
|
+
const ownFilingShown = useMemo(() => visibleForm4Filings.some((filing) => (
|
|
199
|
+
contentMap.has(filing.accessionNumber) && !isOtherIssuerFiling(filing, contentMap.get(filing.accessionNumber))
|
|
200
|
+
)), [contentMap, visibleForm4Filings]);
|
|
201
|
+
const searchingOwn = !ownFilingShown && pendingCount === 0 && shownCount < form4Filings.length;
|
|
202
|
+
const noOwnFilings = !loading && !ownFilingShown && pendingCount === 0 && shownCount >= form4Filings.length;
|
|
188
203
|
|
|
189
204
|
const allParsed: ParsedFiling[] = useMemo(() => visibleForm4Filings.flatMap((filing) => {
|
|
190
205
|
const hasContent = contentMap.has(filing.accessionNumber);
|
|
@@ -223,13 +238,13 @@ function InsiderView({ width, height, focused }: { width: number; height: number
|
|
|
223
238
|
// load here until it fills a page, back to a year at most.
|
|
224
239
|
const oldestShown = visibleForm4Filings[visibleForm4Filings.length - 1]?.filingDate;
|
|
225
240
|
const oldestShownTime = oldestShown ? new Date(oldestShown).getTime() : Number.NaN;
|
|
226
|
-
const wantsOlderFilings = (typeFilter !== "all" || nameFilter != null)
|
|
241
|
+
const wantsOlderFilings = (typeFilter !== "all" || nameFilter != null || ownerFilingsShown)
|
|
227
242
|
&& shown.length < Math.max(FORM4_PAGE_SIZE, height)
|
|
228
243
|
&& shownCount < Math.min(form4Filings.length, AUTO_FILL_FILING_CAP)
|
|
229
244
|
&& oldestShownTime >= Date.now() - AUTO_FILL_DAYS * DAY_MS;
|
|
230
245
|
useEffect(() => {
|
|
231
|
-
if (wantsOlderFilings && pendingCount === 0) loadNextPage();
|
|
232
|
-
}, [loadNextPage, pendingCount, shownCount, wantsOlderFilings]);
|
|
246
|
+
if (searchingOwn || (wantsOlderFilings && pendingCount === 0)) loadNextPage();
|
|
247
|
+
}, [loadNextPage, pendingCount, searchingOwn, shownCount, wantsOlderFilings]);
|
|
233
248
|
|
|
234
249
|
const summary = useMemo(() => buildInsiderSummaryFigures(parsed, Date.now(), allParsed), [parsed, allParsed]);
|
|
235
250
|
// A page loading in on scroll clears the totals until it is read; the last
|
|
@@ -353,15 +368,17 @@ function InsiderView({ width, height, focused }: { width: number; height: number
|
|
|
353
368
|
if (authWall) return <SignInWall placement="insider-signin" action="view insider transactions" needsVerification={cloudSession.needsVerification} />;
|
|
354
369
|
if (loading && allFilings.length === 0) return <Spinner label="Loading insider filings..." />;
|
|
355
370
|
if (error && allFilings.length === 0) return <EmptyState title="Insider filings unavailable." message={error} />;
|
|
356
|
-
if (
|
|
357
|
-
return renderFilingNotice(
|
|
371
|
+
if (noOwnFilings) {
|
|
372
|
+
return renderFilingNotice(abroadVenue && allFilings.length === 0
|
|
373
|
+
? noSecReportsNotice({ symbol: parsePublicTickerKey(ticker.metadata.ticker).symbol, exchange: abroadVenue, name: ticker.metadata.name ?? null })
|
|
374
|
+
: insiderEmptyNotice(filesAsForeignPrivateIssuer(allFilings)), width);
|
|
358
375
|
}
|
|
359
376
|
|
|
360
377
|
// Until a filing is read there is nothing to say; after that the empty
|
|
361
378
|
// list says how far back the filings it has read go, while older ones load.
|
|
362
379
|
const oldestRead = allParsed.findLast((entry) => !entry.isLoading)?.filing.filingDate;
|
|
363
380
|
const since = oldestRead ? ` since ${formatShortDate(oldestRead, { utc: true })}` : "";
|
|
364
|
-
const emptyTitle = typeCounts.all === 0 && (pendingCount > 0 || wantsOlderFilings)
|
|
381
|
+
const emptyTitle = typeCounts.all === 0 && (pendingCount > 0 || wantsOlderFilings || searchingOwn)
|
|
365
382
|
? "Loading Form 4 transactions..."
|
|
366
383
|
: typeFilter === "trades"
|
|
367
384
|
? `No open-market buys or sells${nameFilter ? " by this insider" : ""}${since}.`
|
|
@@ -458,7 +475,7 @@ export const insiderModule: PluginModule = {
|
|
|
458
475
|
description: "Insider transaction activity for the selected ticker.",
|
|
459
476
|
keywords: ["insider", "form 4", "ownership", "transactions", "ins"],
|
|
460
477
|
shortcut: "INS",
|
|
461
|
-
canCreate: (_context, options) => !options?.ticker ||
|
|
478
|
+
canCreate: (_context, options) => !options?.ticker || mayBeSecEquityListing(options.ticker),
|
|
462
479
|
}),
|
|
463
480
|
headless: insiderHeadless,
|
|
464
481
|
},
|
|
@@ -471,7 +488,7 @@ export const insiderModule: PluginModule = {
|
|
|
471
488
|
order: 47,
|
|
472
489
|
component: InsiderView,
|
|
473
490
|
instruments: ["equity"],
|
|
474
|
-
isVisible: ({ ticker }) =>
|
|
491
|
+
isVisible: ({ ticker }) => mayBeUsEquityTicker(ticker),
|
|
475
492
|
});
|
|
476
493
|
},
|
|
477
494
|
};
|
|
@@ -104,6 +104,16 @@ function disclosureText(xml: string): string {
|
|
|
104
104
|
return decodeHtmlEntities(xml.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, "$1").replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim());
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
/**
|
|
108
|
+
* The CIK of the company whose shares the form reports, without leading
|
|
109
|
+
* zeros, or null when the document is not a Form 4 or names none.
|
|
110
|
+
*/
|
|
111
|
+
export function parseForm4IssuerCik(xml: string): string | null {
|
|
112
|
+
if (!/<(?:[\w.-]+:)?ownershipDocument(?:\s|>)/i.test(xml)) return null;
|
|
113
|
+
const cik = tagText(tagContent(xml, "issuer") ?? "", "issuerCik").replace(/^0+/, "");
|
|
114
|
+
return /^\d+$/.test(cik) ? cik : null;
|
|
115
|
+
}
|
|
116
|
+
|
|
107
117
|
export function parseForm4Disclosure(xml: string): InsiderFilingDisclosure | null {
|
|
108
118
|
if (!/<(?:[\w.-]+:)?ownershipDocument(?:\s|>)/i.test(xml)) return null;
|
|
109
119
|
const original = tagText(xml, "dateOfOriginalSubmission");
|