gloomberb 0.16.3 → 0.16.4
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/package.json +4 -1
- 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 +34 -16
- package/src/api-client/index.ts +12 -0
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +88 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +31 -0
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +57 -1
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/app/global-shortcuts.ts +11 -1
- 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 +18 -1
- 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 +70 -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 +23 -9
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +12 -4
- package/src/cli/commands/market.ts +359 -99
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +422 -0
- package/src/cli/commands/overview.ts +164 -26
- package/src/cli/commands/search.ts +29 -8
- package/src/cli/commands/system.ts +99 -19
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +62 -30
- package/src/cli/desktop-pane-shot.ts +97 -16
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +7 -4
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/index-roots.ts +51 -0
- package/src/cli/index.ts +9 -6
- package/src/cli/listing-arg.ts +211 -3
- package/src/cli/not-a-ticker.ts +37 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/capabilities.ts +8 -2
- package/src/cli/pane-functions/catalog.ts +13 -2
- package/src/cli/pane-functions/data.ts +36 -5
- package/src/cli/pane-functions/dom.ts +21 -13
- package/src/cli/pane-functions/freshness.ts +205 -26
- package/src/cli/pane-functions/function-help.ts +67 -22
- package/src/cli/pane-functions/headless.ts +5 -4
- package/src/cli/pane-functions/index.ts +3 -0
- package/src/cli/pane-functions/market-session.ts +133 -0
- package/src/cli/pane-functions/options.ts +15 -4
- package/src/cli/pane-functions/report-notices.ts +63 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +4 -6
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +105 -23
- package/src/cli/registry.ts +2 -1
- package/src/cli/result.ts +50 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/components/chart/composite/composite-chart.tsx +43 -4
- package/src/components/chart/composite/legend.tsx +39 -6
- 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/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/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/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/data-table/view.tsx +28 -9
- package/src/components/layout/floating-pane.tsx +6 -2
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +46 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/header.tsx +2 -1
- 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 +1 -1
- package/src/components/layout/shell/drag/index.ts +4 -0
- package/src/components/layout/shell/drag/live.ts +76 -5
- package/src/components/layout/shell/drag/runtime.ts +8 -8
- package/src/components/layout/shell/index.tsx +47 -6
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +28 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +51 -10
- 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/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +9 -5
- package/src/components/metric-treemap/heat-surface.tsx +27 -8
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-wizard.tsx +49 -40
- 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 +6 -2
- package/src/components/ui/button.tsx +10 -0
- package/src/components/ui/data-table/index.tsx +38 -0
- package/src/components/ui/data-table/types.ts +8 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/icon.tsx +11 -2
- package/src/components/ui/index.ts +1 -1
- 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/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 +37 -3
- package/src/i18n/es.ts +14 -1
- package/src/i18n/ja.ts +14 -1
- package/src/i18n/ko.ts +14 -1
- package/src/i18n/zh-cn.ts +14 -1
- package/src/i18n/zh-tw.ts +14 -1
- package/src/layout/desks.ts +1 -2
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/market-data/market/freshness.ts +118 -18
- package/src/market-data/market/status.ts +40 -0
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/quotes/contributions.ts +19 -2
- package/src/market-data/quotes/metadata.ts +16 -0
- package/src/market-data/quotes/screener-live-quotes.ts +56 -5
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +31 -4
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +3 -1
- package/src/plugins/builtin/analytics/risk-model.ts +37 -8
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -4
- package/src/plugins/builtin/backtest/pane.tsx +1 -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/chart-composer/pane.tsx +1 -1
- 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/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +48 -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 +112 -4
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +1 -0
- package/src/plugins/builtin/cloud/askg/model.ts +129 -70
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +40 -2
- package/src/plugins/builtin/cloud/askg/tool-display.ts +437 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- 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 +360 -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/starter-symbols.ts +8 -0
- 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 +666 -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 +234 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +153 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +168 -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/upgrade-dialog.tsx +26 -2
- package/src/plugins/builtin/cloud/upgrade-personalization.ts +57 -0
- package/src/plugins/builtin/cloud/upgrade-tickers.ts +124 -0
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- 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 +15 -7
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +107 -64
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +21 -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/sovr-pane.tsx +4 -4
- 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/pane.tsx +5 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- 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/index.tsx +68 -22
- package/src/plugins/builtin/econ-statistics/headless.ts +12 -2
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/fx-matrix/freshness.ts +65 -0
- 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/headless.ts +9 -3
- package/src/plugins/builtin/gpu/model.ts +14 -5
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/headless.ts +6 -1
- package/src/plugins/builtin/holders/pane.tsx +3 -0
- package/src/plugins/builtin/insider/index.tsx +4 -4
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +12 -2
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +22 -10
- package/src/plugins/builtin/iv-history/index.tsx +3 -3
- package/src/plugins/builtin/iv-history/model.ts +61 -13
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +42 -18
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- 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 +109 -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 +24 -0
- package/src/plugins/builtin/macro-day/headless.ts +11 -8
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +11 -6
- package/src/plugins/builtin/macro-day/pane.tsx +12 -8
- 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 +94 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +8 -1
- package/src/plugins/builtin/market-movers/model.ts +71 -17
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- 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 +161 -12
- package/src/plugins/builtin/options-positioning/headless.ts +4 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +73 -17
- package/src/plugins/builtin/options-scenario/headless.ts +71 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +284 -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/equity-row.tsx +8 -5
- package/src/plugins/builtin/perps/model.ts +16 -5
- 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 +344 -32
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +87 -4
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +71 -36
- package/src/plugins/builtin/portfolio-list/cli/render.ts +87 -18
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +2 -16
- package/src/plugins/builtin/portfolio-list/headless.ts +38 -7
- package/src/plugins/builtin/realized-vol/headless.ts +3 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -2
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -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/pane.tsx +1 -1
- 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/shared/command-tab.ts +51 -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/report-freshness.ts +50 -2
- 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/index.tsx +19 -4
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-volume/index.tsx +1 -10
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
- 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/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +40 -4
- package/src/plugins/builtin/treasury-auctions/index.tsx +11 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +197 -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 +124 -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/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 +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +1 -1
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +127 -63
- 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 +84 -24
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +5 -0
- package/src/remote/controller.ts +3 -53
- package/src/remote/matching.ts +69 -0
- package/src/remote/schema.ts +1 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +2 -0
- package/src/renderers/dom/desktop/icons.tsx +14 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/host/box.tsx +1 -1
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +10 -2
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +13 -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 +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +101 -5
- package/src/renderers/electrobun/view/main.tsx +4 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +19 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +4 -1
- package/src/sources/listing-symbols.ts +11 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/cached-routes.ts +8 -4
- package/src/sources/provider-router/financial-routes.ts +11 -5
- package/src/sources/provider-router/financials.ts +42 -15
- package/src/sources/provider-router/history.ts +27 -11
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +4 -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/search/index.ts +22 -2
- package/src/tickers/search/ranking.ts +45 -1
- package/src/tickers/search/types.ts +3 -1
- package/src/time-series/resolve.ts +1 -14
- package/src/types/config.ts +61 -1
- package/src/types/headless.ts +11 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +49 -3
- package/src/ui/host.tsx +8 -4
- package/src/ui/index.tsx +2 -0
- package/src/utils/cli-output.ts +14 -1
- package/src/utils/exchanges.ts +13 -0
- package/src/utils/format.ts +2 -1
- package/src/utils/fx-market-hours.ts +34 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +39 -6
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +159 -30
- package/src/utils/sec.ts +38 -34
- package/src/utils/throttled-fetch.ts +51 -22
|
@@ -26,9 +26,10 @@ import {
|
|
|
26
26
|
useUiCapabilities,
|
|
27
27
|
} from "../../../ui";
|
|
28
28
|
import { isPermanentClientError } from "../../../api-client/errors";
|
|
29
|
+
import type { IssuerListingParams } from "../../../api-client/paths";
|
|
29
30
|
import { useFilingYearReader } from "../shared/filing-year-reader";
|
|
30
31
|
import { useProFeatureWall, type ProFeatureWallCopy, type ReadGuard } from "../shared/pro-feature-wall";
|
|
31
|
-
import { useBoundTicker } from "../shared/ticker-request";
|
|
32
|
+
import { useBoundTicker, useIssuerListing } from "../shared/ticker-request";
|
|
32
33
|
import { SplitBar } from "../../../components/ui/split-bar";
|
|
33
34
|
import { loadProxyStatement, loadProxyStatements } from "./data";
|
|
34
35
|
import {
|
|
@@ -249,27 +250,35 @@ export function ExecutivesPane({
|
|
|
249
250
|
nested?: boolean;
|
|
250
251
|
}) {
|
|
251
252
|
const { wall, guard } = useProFeatureWall(EXEC_WALL, { width, height });
|
|
252
|
-
const { symbol } = useBoundTicker();
|
|
253
|
+
const { symbol, ticker: boundTicker } = useBoundTicker();
|
|
253
254
|
const ticker = symbol ? symbol.toUpperCase() : null;
|
|
255
|
+
const listing = useIssuerListing(boundTicker);
|
|
254
256
|
if (wall) return wall;
|
|
255
|
-
if (!ticker) return <EmptyState title="
|
|
256
|
-
return <ExecutiveResearch key={ticker} ticker={ticker} focused={focused} width={width} nested={nested} guard={guard} />;
|
|
257
|
+
if (!ticker) return <EmptyState title="Select a ticker." />;
|
|
258
|
+
return <ExecutiveResearch key={ticker} ticker={ticker} listing={listing} focused={focused} width={width} nested={nested} guard={guard} />;
|
|
257
259
|
}
|
|
258
260
|
|
|
259
261
|
export function ExecutivesResearchTab(props: { focused: boolean; width: number; height: number }) {
|
|
260
262
|
return <ExecutivesPane {...props} nested />;
|
|
261
263
|
}
|
|
262
264
|
|
|
263
|
-
function ExecutiveResearch({ ticker, focused, width, nested, guard }: {
|
|
265
|
+
function ExecutiveResearch({ ticker, listing, focused, width, nested, guard }: {
|
|
266
|
+
ticker: string;
|
|
267
|
+
listing: IssuerListingParams;
|
|
268
|
+
focused: boolean;
|
|
269
|
+
width: number;
|
|
270
|
+
nested: boolean;
|
|
271
|
+
guard: ReadGuard;
|
|
272
|
+
}) {
|
|
264
273
|
const nativePaneChrome = useUiCapabilities().nativePaneChrome === true;
|
|
265
274
|
const rendererHost = useRendererHost();
|
|
266
275
|
const [selectedYear, setYear] = usePaneStateValue<number | null>("proxyYear", null);
|
|
267
|
-
const loadYears = useCallback((force: boolean) => guard(loadProxyStatements(ticker, { force })), [guard, ticker]);
|
|
276
|
+
const loadYears = useCallback((force: boolean) => guard(loadProxyStatements(ticker, { force, listing })), [guard, listing, ticker]);
|
|
268
277
|
const list = useAsyncResource(loadYears, { clearOnError: isPermanentClientError });
|
|
269
278
|
const years = useMemo(() => (list.data?.data?.proxies ?? []).map((entry) => entry.proxyYear), [list.data]);
|
|
270
279
|
const year = selectedYear !== null && years.includes(selectedYear)
|
|
271
280
|
? selectedYear : years[0] ?? null;
|
|
272
|
-
const loadStatement = useCallback((force: boolean) => guard(loadProxyStatement(ticker, year!, { force })), [guard, ticker, year]);
|
|
281
|
+
const loadStatement = useCallback((force: boolean) => guard(loadProxyStatement(ticker, year!, { force, listing })), [guard, listing, ticker, year]);
|
|
273
282
|
const detail = useAsyncResource(year === null ? null : loadStatement, { clearOnError: isPermanentClientError });
|
|
274
283
|
const statement = detail.data?.data ?? null;
|
|
275
284
|
const loading = list.loading || detail.loading;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { apiClient } from "../../../api-client";
|
|
3
|
+
import { ApiRequestError } from "../../../api-client/errors";
|
|
4
|
+
import type { IssuerListingParams } from "../../../api-client/paths";
|
|
3
5
|
import {
|
|
4
6
|
BulletList,
|
|
5
7
|
EmptyState,
|
|
@@ -24,7 +26,7 @@ import {
|
|
|
24
26
|
import { truncateToDisplayWidth } from "../../../utils/format";
|
|
25
27
|
import { isPlainKey } from "../../../utils/keyboard";
|
|
26
28
|
import { useProFeatureWall, type ProFeatureWallCopy, type ReadGuard } from "../shared/pro-feature-wall";
|
|
27
|
-
import { useBoundTicker, useTickerRequest } from "../shared/ticker-request";
|
|
29
|
+
import { useBoundTicker, useIssuerListing, useTickerRequest } from "../shared/ticker-request";
|
|
28
30
|
import {
|
|
29
31
|
buildFilingEventsFeed,
|
|
30
32
|
resolveFeedScrollTop,
|
|
@@ -100,6 +102,20 @@ function FilingEntry({
|
|
|
100
102
|
);
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
/**
|
|
106
|
+
* The latest 8-Ks of a listing. The service answers 404 when it can tie no
|
|
107
|
+
* filer to the ticker, as for a listing abroad whose company files none:
|
|
108
|
+
* that is no 8-Ks, not a failure.
|
|
109
|
+
*/
|
|
110
|
+
async function fetchFilingEvents(ticker: string, listing: IssuerListingParams) {
|
|
111
|
+
try {
|
|
112
|
+
return await apiClient.getFilingEvents(ticker, 100, listing);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (error instanceof ApiRequestError && error.status === 404) return { ticker, events: [] };
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
103
119
|
interface FilingEventsPaneProps {
|
|
104
120
|
focused: boolean;
|
|
105
121
|
width: number;
|
|
@@ -116,14 +132,15 @@ function FilingEventsReader({
|
|
|
116
132
|
width,
|
|
117
133
|
guard,
|
|
118
134
|
}: FilingEventsPaneProps & { guard: ReadGuard }) {
|
|
119
|
-
const { symbol, exchange } = useBoundTicker();
|
|
135
|
+
const { symbol, exchange, ticker: boundTicker } = useBoundTicker();
|
|
120
136
|
const ticker = symbol ? symbol.toUpperCase() : null;
|
|
137
|
+
const { name } = useIssuerListing(boundTicker);
|
|
121
138
|
const nativePaneChrome = useUiCapabilities().nativePaneChrome === true;
|
|
122
139
|
const rendererHost = useRendererHost();
|
|
123
140
|
|
|
124
141
|
const loadFilingEvents = useCallback(
|
|
125
|
-
(
|
|
126
|
-
[guard],
|
|
142
|
+
(key: string, venue: string) => guard(fetchFilingEvents(key, { exchange: venue, name })),
|
|
143
|
+
[guard, name],
|
|
127
144
|
);
|
|
128
145
|
const { data, loading, error, reload } = useTickerRequest(loadFilingEvents, ticker, exchange);
|
|
129
146
|
const events = data?.events ?? [];
|
|
@@ -227,7 +244,7 @@ function FilingEventsReader({
|
|
|
227
244
|
return { info, hints };
|
|
228
245
|
}, [loading, error, ticker, selected, openFiling]);
|
|
229
246
|
|
|
230
|
-
if (!ticker) return <EmptyState title="
|
|
247
|
+
if (!ticker) return <EmptyState title="Select a ticker." />;
|
|
231
248
|
if (loading && !data) {
|
|
232
249
|
return <PaneStatusBody loading align="center" loadingLabel="Loading 8-Ks..." />;
|
|
233
250
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { QueryEntry } from "../../../market-data/result-types";
|
|
2
|
+
import type { Quote } from "../../../types/financials";
|
|
3
|
+
import { isFxMarketOpen } from "../../../utils/fx-market-hours";
|
|
4
|
+
import { quoteFreshnessFields } from "../shared/report-freshness";
|
|
5
|
+
|
|
6
|
+
/** The venue FX pairs trade on, so a report can place the matrix's market. */
|
|
7
|
+
const FX_VENUE = "CCY";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* One rate the matrix draws, in the fields a report reads to date it: when it
|
|
11
|
+
* was observed, whether it is live or delayed (and by how much), whether it is
|
|
12
|
+
* stale, and where its market stands. The pane publishes these for `fn FXC`
|
|
13
|
+
* and `shot FXC`; they are not shown in the pane.
|
|
14
|
+
*/
|
|
15
|
+
type FxRateObservation = {
|
|
16
|
+
currency: string;
|
|
17
|
+
/** ISO time of the observation; absent when the rate carries none. */
|
|
18
|
+
quoteTime?: string;
|
|
19
|
+
dataSource?: "live" | "delayed";
|
|
20
|
+
delayMinutes?: number;
|
|
21
|
+
stale: boolean;
|
|
22
|
+
sessionExchange: string;
|
|
23
|
+
marketState: NonNullable<Quote["marketState"]>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function isoTime(time: number | undefined | null): string | undefined {
|
|
27
|
+
return time != null && Number.isFinite(time) ? new Date(time).toISOString() : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The observation behind each rate the matrix shows, except USD (the base,
|
|
32
|
+
* observed nowhere) and a currency with no usable rate (drawn as a dash).
|
|
33
|
+
*
|
|
34
|
+
* A rate read from a live pair quote (`legQuote`) says what that quote says:
|
|
35
|
+
* live or delayed, by how much, and its market state. Any other rate is the
|
|
36
|
+
* loaded snapshot: a snapshot refreshed on a schedule, so delayed, dated by
|
|
37
|
+
* the snapshot's own observation time and placed on the FX week, which runs
|
|
38
|
+
* Sunday 17:00 to Friday 17:00 New York time. A rate is stale when its entry
|
|
39
|
+
* says so (a failed refresh, or its own schedule), as the pane's footer counts.
|
|
40
|
+
*/
|
|
41
|
+
export function fxRateObservations(
|
|
42
|
+
currencies: readonly string[],
|
|
43
|
+
rates: ReadonlyMap<string, number>,
|
|
44
|
+
read: (currency: string) => { entry?: QueryEntry<number> | null; legQuote?: Quote | null },
|
|
45
|
+
now = Date.now(),
|
|
46
|
+
): FxRateObservation[] {
|
|
47
|
+
return [...new Set(currencies)].flatMap((currency) => {
|
|
48
|
+
if (currency === "USD") return [];
|
|
49
|
+
const rate = rates.get(currency);
|
|
50
|
+
if (rate == null || !Number.isFinite(rate) || rate <= 0) return [];
|
|
51
|
+
const { entry, legQuote } = read(currency);
|
|
52
|
+
const fields = legQuote ? quoteFreshnessFields(legQuote, now) : null;
|
|
53
|
+
const entryStale = entry?.error != null || (entry?.staleAt != null && entry.staleAt <= now);
|
|
54
|
+
const quoteTime = isoTime(entry?.asOf ?? legQuote?.lastUpdated);
|
|
55
|
+
return [{
|
|
56
|
+
currency,
|
|
57
|
+
...(quoteTime ? { quoteTime } : {}),
|
|
58
|
+
dataSource: fields?.dataSource ?? "delayed",
|
|
59
|
+
...(fields?.delayMinutes ? { delayMinutes: fields.delayMinutes } : {}),
|
|
60
|
+
stale: entryStale || fields?.stale === true,
|
|
61
|
+
sessionExchange: fields?.sessionExchange ?? FX_VENUE,
|
|
62
|
+
marketState: fields?.marketState ?? (isFxMarketOpen(now) ? "REGULAR" : "CLOSED"),
|
|
63
|
+
}];
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -12,6 +12,7 @@ import { CountryFlag } from "../../../components/ui/country-flag";
|
|
|
12
12
|
import { getSharedMarketDataCoordinator } from "../../../market-data/coordinator";
|
|
13
13
|
import { useFxRatesMap } from "../../../market-data/hooks";
|
|
14
14
|
import { resolveEntryData } from "../../../market-data/selectors";
|
|
15
|
+
import { useRemoteUiNode } from "../../../remote/semantic-tree";
|
|
15
16
|
import { usePaneSettingValue } from "../../../state/app/context";
|
|
16
17
|
import { colors } from "../../../theme/colors";
|
|
17
18
|
import type { PaneProps } from "../../../types/plugin";
|
|
@@ -25,8 +26,9 @@ import { useLiveStreamingSetting } from "../../../state/hooks/live-streaming";
|
|
|
25
26
|
import { fxLegQuoteKey, fxLegReferenceRate, fxLegTargets, fxLegs, fxLegsBehind, liveFxLegEntry } from "./live-legs";
|
|
26
27
|
import { CURRENCY_FLAG_REGIONS, FX_CURRENCIES, formatRate, resolveCurrencies, type FxCurrency } from "./pairs";
|
|
27
28
|
import { crossMovePercent, directionTint, nextTintLevel } from "./direction";
|
|
28
|
-
import { fxMatrixSettings } from "./settings";
|
|
29
|
+
import { FX_MATRIX_REPORT_OPTIONS, fxMatrixReportNotices, fxMatrixSettings } from "./settings";
|
|
29
30
|
import { createFxExportMetadata } from "./export";
|
|
31
|
+
import { fxRateObservations } from "./freshness";
|
|
30
32
|
|
|
31
33
|
const FX_MATRIX_PANE_ID = "fx-matrix";
|
|
32
34
|
/** Stable identity: a fresh literal here would reload the board every render. */
|
|
@@ -114,6 +116,23 @@ function FxMatrixPane({ focused, width, height }: PaneProps) {
|
|
|
114
116
|
? { ...entry, error: entry.error ? { ...entry.error } : null }
|
|
115
117
|
: undefined] as const;
|
|
116
118
|
}));
|
|
119
|
+
// A report or capture of the board is dated by the rates it draws: when each
|
|
120
|
+
// was observed, whether it is delayed or stale, and where the FX market
|
|
121
|
+
// stands. The pane draws none of this; its footer keeps its own status.
|
|
122
|
+
useRemoteUiNode({
|
|
123
|
+
role: "report-freshness",
|
|
124
|
+
label: "Rate freshness",
|
|
125
|
+
getMetadata: () => {
|
|
126
|
+
const legQuotes = new Map(legs.map((leg) => [leg.currency, resolveEntryData(legEntries.get(fxLegQuoteKey(leg)))] as const));
|
|
127
|
+
return {
|
|
128
|
+
observations: fxRateObservations(currencies, rates, (currency) => ({
|
|
129
|
+
entry: rateEntries.get(currency),
|
|
130
|
+
// Only a rate that is the pair quote's own says what that quote says.
|
|
131
|
+
legQuote: liveEntries.has(currency) ? legQuotes.get(currency) : null,
|
|
132
|
+
})),
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
});
|
|
117
136
|
const status = summarizeFxRates(currencies, rates, (currency) => rateEntries.get(currency));
|
|
118
137
|
const statusText = fxStatusLabel(status);
|
|
119
138
|
const snapshotFetchedAt = summarizeFxRates(currencies, snapshotRates, (currency) => (
|
|
@@ -253,6 +272,8 @@ export const fxMatrixModule: PluginModule = {
|
|
|
253
272
|
defaultFloatingSize: { width: 105, height: 14 },
|
|
254
273
|
tableExport: true,
|
|
255
274
|
settings: fxMatrixSettings,
|
|
275
|
+
reportOptions: FX_MATRIX_REPORT_OPTIONS,
|
|
276
|
+
reportNotices: fxMatrixReportNotices,
|
|
256
277
|
},
|
|
257
278
|
],
|
|
258
279
|
|
|
@@ -60,7 +60,7 @@ export function formatRate(rate: number, referenceRate = rate): string {
|
|
|
60
60
|
return rate.toFixed(decimals);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function isFxCurrency(code: unknown): code is FxCurrency {
|
|
63
|
+
export function isFxCurrency(code: unknown): code is FxCurrency {
|
|
64
64
|
return typeof code === "string" && FX_CURRENCIES.includes(code as FxCurrency);
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { PaneSettingsContext, PaneSettingsDef } from "../../../types/plugin";
|
|
2
|
-
import { CURRENCY_SETS, FX_CURRENCIES, resolveCurrencies } from "./pairs";
|
|
1
|
+
import type { PaneReportOptionDef, PaneSettingsContext, PaneSettingsDef } from "../../../types/plugin";
|
|
2
|
+
import { CURRENCY_SETS, FX_CURRENCIES, MAJOR_CURRENCIES, isFxCurrency, resolveCurrencies } from "./pairs";
|
|
3
3
|
|
|
4
4
|
const CUSTOM_SET = "custom";
|
|
5
5
|
|
|
@@ -60,3 +60,43 @@ export function fxMatrixSettings(context: PaneSettingsContext): PaneSettingsDef
|
|
|
60
60
|
},
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
const SET_NAMES = CURRENCY_SETS.map((set) => set.id).join(", ");
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `--currencies` as typed: codes and set names in any case, separated by
|
|
68
|
+
* commas or spaces, returned as the codes in order without repeats. A token
|
|
69
|
+
* that is neither fails, naming it and the codes the board carries, where the
|
|
70
|
+
* pane setting would drop it and quietly show the majors.
|
|
71
|
+
*/
|
|
72
|
+
function parseCurrenciesOption(value: string): string {
|
|
73
|
+
const tokens = value.split(/[\s,]+/).filter(Boolean);
|
|
74
|
+
const unknown = tokens.filter((token) => (
|
|
75
|
+
!isFxCurrency(token.toUpperCase()) && !CURRENCY_SETS.some((set) => set.id === token.toLowerCase())
|
|
76
|
+
));
|
|
77
|
+
if (unknown.length > 0) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Unknown ${unknown.length > 1 ? "currencies" : "currency"} ${unknown.join(", ")} for --currencies. `
|
|
80
|
+
+ `Use codes from ${FX_CURRENCIES.join(", ")}, or a set: ${SET_NAMES}.`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (tokens.length === 0) throw new Error("--currencies needs at least one code, such as USD,ZAR,NGN.");
|
|
84
|
+
return resolveCurrencies(value).join(",");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** `fn FXC --currencies USD,ZAR,NGN`: the board's currency list, as its settings choose it. */
|
|
88
|
+
export const FX_MATRIX_REPORT_OPTIONS: readonly PaneReportOptionDef[] = [{
|
|
89
|
+
key: "currencies",
|
|
90
|
+
type: "string",
|
|
91
|
+
placeholder: "codes",
|
|
92
|
+
description: `The currencies to cross, in order: codes separated by commas, or a set (${SET_NAMES}). `
|
|
93
|
+
+ `Without it, the ${MAJOR_CURRENCIES.length} majors. Codes: ${FX_CURRENCIES.join(", ")}`,
|
|
94
|
+
example: "--currencies USD,ZAR,NGN,SAR,ILS",
|
|
95
|
+
normalize: parseCurrenciesOption,
|
|
96
|
+
}];
|
|
97
|
+
|
|
98
|
+
/** A report of the default board says it is only the majors, and how to choose others. */
|
|
99
|
+
export function fxMatrixReportNotices(settings: Readonly<Record<string, unknown>>): string[] {
|
|
100
|
+
if (settings.currencies != null) return [];
|
|
101
|
+
return [`Showing the ${MAJOR_CURRENCIES.length} majors. Choose others with --currencies USD,ZAR,NGN; gloomberb catalog FXC lists all ${FX_CURRENCIES.length}.`];
|
|
102
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { HeadlessPaneDefinition } from "../../../types/plugin";
|
|
|
3
3
|
import { fetchGpuBoard, fetchGpuEvents, fetchGpuHistory, loadGpuEquityHistory } from "./client";
|
|
4
4
|
import { GPU_TABS, gpuArgument, gpuBasisLabel, gpuChange, gpuEquityRows, gpuEventDate, gpuProvenanceLabel, gpuLabel, gpuRows, gpuSource, gpuTab } from "./model";
|
|
5
5
|
import { quoteFreshnessFields } from "../shared/report-freshness";
|
|
6
|
+
import { getRegularSessionDisplay } from "../../../market-data/market/status";
|
|
6
7
|
|
|
7
8
|
const observationRow = (row: GpuObservation) => ({ gpu: gpuLabel(row), source: gpuSource(row), basis: gpuBasisLabel(row.basis),
|
|
8
9
|
price: row.pricePerGpuHr, availability: row.availability, observedAt: row.observedAt, effectiveAt: row.effectiveAt, provenance: row.provenance ?? "live", provenanceLabel: gpuProvenanceLabel(row, true),
|
|
@@ -19,14 +20,17 @@ export const gpuHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
19
20
|
shape: "bundle", argument: { kind: "free-text", optional: true, placeholder: "GPU", description: "GPU model, such as H100 or B200." },
|
|
20
21
|
options: [{ key: "tab", type: "enum", values: GPU_TABS.map(({ value }) => ({ value })), defaultValue: "board", description: "Board, sourced history, dated changes or related equities." }],
|
|
21
22
|
discovery: { aliases: ["GPU"], dataRequirements: ["GPU rental price observations"],
|
|
22
|
-
limitations: ["List prices, provider-declared spot and asks are distinct bases",
|
|
23
|
+
limitations: ["List prices, provider-declared spot and asks are distinct bases",
|
|
24
|
+
"Hyperscaler and Neocloud rows are list indexes: the median of the providers' list prices linked over time, so a provider joining or leaving causes no jump; sample.rawMedian is the raw median of today's providers and can differ slightly",
|
|
25
|
+
"1D/7D/30D need sufficient observation history; unavailable changes remain null"] },
|
|
23
26
|
describe: "GPU rental prices in USD per GPU-hour",
|
|
24
27
|
async load(args, ctx) {
|
|
25
28
|
const argument = Array.isArray(args.argument) ? args.argument.join(" ") : args.argument;
|
|
26
29
|
const model = gpuArgument(argument);
|
|
27
30
|
const tab = gpuTab(args.options.tab);
|
|
28
31
|
const board = await fetchGpuBoard(ctx.apiClient);
|
|
29
|
-
const metadata = { asOf: board.asOf, stale: board.stale, complete: board.status === "available" && !board.access?.locked, unit: "USD/GPU-hour", access: board.access
|
|
32
|
+
const metadata = { asOf: board.asOf, stale: board.stale, complete: board.status === "available" && !board.access?.locked, unit: "USD/GPU-hour", access: board.access,
|
|
33
|
+
methodology: "docs/gpu-rental-prices.md#list-indexes" };
|
|
30
34
|
// Prices observed on providers' pages, not a feed; each board row says whether its source has gone quiet.
|
|
31
35
|
const freshness = { source: "GPU cloud providers", status: "not-a-feed" as const, basis: "observed prices" };
|
|
32
36
|
if (tab === "history") {
|
|
@@ -52,7 +56,9 @@ export const gpuHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
52
56
|
const rows = await Promise.all(related.map(async (row) => {
|
|
53
57
|
const quote = await ctx.marketData.getQuote(row.symbol, row.exchange).catch(() => null);
|
|
54
58
|
const history = histories.find((entry) => entry.symbol === row.symbol);
|
|
55
|
-
|
|
59
|
+
// The regular session's last and move, as the pane's board shows them.
|
|
60
|
+
const headline = getRegularSessionDisplay(quote);
|
|
61
|
+
return { symbol: row.symbol, role: row.role, price: headline?.price ?? null, change1d: headline?.changePercent ?? null,
|
|
56
62
|
change5d: history?.value ?? null, fiveDayAsOf: history?.asOf ?? null, quoteAsOf: quote?.lastUpdated ? new Date(quote.lastUpdated).toISOString() : null,
|
|
57
63
|
...quoteFreshnessFields(quote),
|
|
58
64
|
gpu: row.reference ? gpuLabel(row.reference) : row.gpuModel, gpuSource: row.reference ? gpuSource(row.reference) : null, gpuChange7d: row.reference?.change7d ?? null };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GpuBasis, GpuBoardRow, GpuEvent, GpuObservation } from "../../../api-client/gpu";
|
|
2
2
|
import { staticSeries } from "../../../components/chart/static/series";
|
|
3
|
-
import { SERIES_COLORS } from "../../../
|
|
3
|
+
import { SERIES_COLORS } from "../../../theme/series-colors";
|
|
4
4
|
import type { ResolvedSeries } from "../../../time-series/types";
|
|
5
5
|
import type { PricePoint } from "../../../types/financials";
|
|
6
6
|
|
|
@@ -32,16 +32,25 @@ const PROVIDER_NAMES: Record<string, string> = {
|
|
|
32
32
|
scaleway: "Scaleway", horizon: "Horizon", verda: "Verda", latitude: "Latitude", imwt: "IMWT",
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* The provider-class rows are chain-linked list indexes, not raw medians. Servers that predate the
|
|
37
|
+
* rename still send "list median"; both strings read as the index.
|
|
38
|
+
*/
|
|
39
|
+
const LIST_INDEX_PROVIDER = /^(Hyperscaler|Neocloud) list (?:index|median)$/;
|
|
40
|
+
|
|
35
41
|
/** Cloud operators are the product being compared. The data collection intermediary stays invisible. */
|
|
36
42
|
export function gpuSource(row: Pick<GpuObservation, "source" | "provider" | "skuKey">): string {
|
|
43
|
+
const listIndex = LIST_INDEX_PROVIDER.exec(row.provider);
|
|
44
|
+
if (listIndex) return `${listIndex[1]} list index`;
|
|
37
45
|
if (row.source === "vast" || row.source === "vast-ai") return "Marketplace ask median";
|
|
38
46
|
if (row.source === "akash") return "Decentralized ask median";
|
|
39
47
|
if (row.source === "runpod") return /community/i.test(`${row.provider} ${row.skuKey}`) ? "Community cloud asks" : "Secure cloud asks";
|
|
40
48
|
return PROVIDER_NAMES[row.provider.toLowerCase()] ?? row.provider;
|
|
41
49
|
}
|
|
42
50
|
|
|
43
|
-
/** A source inside its basis section: the section already says list or ask, so
|
|
44
|
-
export const gpuShortSource = (row: Pick<GpuObservation, "source" | "provider" | "skuKey">) =>
|
|
51
|
+
/** A source inside its basis section: the section already says list or ask, so an index or median drops the word. */
|
|
52
|
+
export const gpuShortSource = (row: Pick<GpuObservation, "source" | "provider" | "skuKey">) =>
|
|
53
|
+
gpuSource(row).replace(/ list index$/, " index").replace(/ ask median$/, " median");
|
|
45
54
|
|
|
46
55
|
export function gpuTime(value: string | null | undefined, compact = false): string {
|
|
47
56
|
if (!value) return "-";
|
|
@@ -73,7 +82,7 @@ export function gpuBasisColor(basis: GpuBasis): string {
|
|
|
73
82
|
export const gpuVariant = (row: Pick<GpuObservation, "formFactor" | "memoryGb">): string[] =>
|
|
74
83
|
[row.formFactor, row.memoryGb ? `${row.memoryGb}GB` : null].filter((part): part is string => !!part);
|
|
75
84
|
|
|
76
|
-
/**
|
|
85
|
+
/** Indexes and medians lead their section: the provider-class list indexes and the marketplace offer medians. */
|
|
77
86
|
export const gpuHeadline = (row: Pick<GpuObservation, "providerClass" | "source">) =>
|
|
78
87
|
!row.source.startsWith("ref-") && (row.providerClass === "aggregate" || row.source === "vast" || row.source === "vast-ai" || row.source === "akash");
|
|
79
88
|
|
|
@@ -320,7 +329,7 @@ export function gpuEquityRows(rows: readonly GpuBoardRow[], selectedModel: strin
|
|
|
320
329
|
const aggregates = candidates.filter((row) => row.providerClass === "aggregate").sort((a, b) =>
|
|
321
330
|
Number(b.formFactor === "SXM") - Number(a.formFactor === "SXM") || (b.stats?.n ?? 0) - (a.stats?.n ?? 0) || (b.memoryGb ?? 0) - (a.memoryGb ?? 0));
|
|
322
331
|
const reference = "provider" in equity ? candidates.find((row) => gpuSource(row) === equity.provider)
|
|
323
|
-
: aggregates.find((row) => row.provider
|
|
332
|
+
: aggregates.find((row) => row.provider.startsWith("Neocloud")) ?? aggregates[0];
|
|
324
333
|
return { ...equity, gpuModel: model, reference: reference ?? null };
|
|
325
334
|
});
|
|
326
335
|
}
|
|
@@ -153,6 +153,7 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
153
153
|
entry("des", ["DES", "<ticker>"], "Open security details for a specific ticker."),
|
|
154
154
|
entry("help-card", ["HELP", "<function>"], "Open a function's help card: what it shows, its keys, how fresh its data is. HELP HELP reaches support."),
|
|
155
155
|
entry("upgrade", ["UPGRADE"], tf("Go Pro for real-time data at gloom.sh/cloud, free for {days} days.", { days: trialDays })),
|
|
156
|
+
entry("mcp", ["MCP"], "Connect Claude Code, Codex, Cursor or any MCP client to Gloom's research tools."),
|
|
156
157
|
entry("move", ["Up/Down", "Ctrl+P/N"], "Move through command bar results."),
|
|
157
158
|
entry("page", ["PageUp/PageDown", "Ctrl+Home/End"], "Jump a page, or to the first or last result."),
|
|
158
159
|
entry("run", ["Enter", "Shift+Enter"], "Run the selected result or its secondary action."),
|
|
@@ -7,7 +7,9 @@ import type {
|
|
|
7
7
|
BeneficialOwnersPayload,
|
|
8
8
|
} from "../../../api-client/beneficial-owners";
|
|
9
9
|
import { ApiRequestError, isAccessDenied } from "../../../api-client/errors";
|
|
10
|
+
import { listingAbroad, type IssuerListingParams } from "../../../api-client/paths";
|
|
10
11
|
import { createPluginCache } from "../../../data/plugin-cache";
|
|
12
|
+
import { secListingKey } from "../../../utils/sec";
|
|
11
13
|
import { finiteOrNull, recordOrNull } from "../../../utils/guards";
|
|
12
14
|
import { cachedCloudResource, loadCloudResource, type CloudResource } from "../shared/cloud-resource";
|
|
13
15
|
import { CLOUD_SESSION_REQUIRED } from "../shared/research-cloud-session";
|
|
@@ -28,6 +30,8 @@ export interface BeneficialOwnersRequest {
|
|
|
28
30
|
form?: BeneficialOwnersForm;
|
|
29
31
|
/** Every report instead of the latest per filer. */
|
|
30
32
|
history?: boolean;
|
|
33
|
+
/** The listing's venue and company, for a listing outside the US. */
|
|
34
|
+
listing?: IssuerListingParams;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
type BeneficialOwnersClient = Pick<typeof apiClient, "getCloudSecBeneficialOwners">;
|
|
@@ -142,7 +146,7 @@ function describeFailure(error: unknown, ticker: string): unknown {
|
|
|
142
146
|
*/
|
|
143
147
|
export async function fetchBeneficialOwners(
|
|
144
148
|
ticker: string,
|
|
145
|
-
{ form = "all", history = false }: BeneficialOwnersRequest = {},
|
|
149
|
+
{ form = "all", history = false, listing }: BeneficialOwnersRequest = {},
|
|
146
150
|
{ client = apiClient, signal }: { client?: BeneficialOwnersClient; signal?: AbortSignal } = {},
|
|
147
151
|
): Promise<BeneficialOwnersPayload> {
|
|
148
152
|
const symbol = ticker.trim().toUpperCase();
|
|
@@ -154,6 +158,8 @@ export async function fetchBeneficialOwners(
|
|
|
154
158
|
for (;;) {
|
|
155
159
|
const page = normalizeBeneficialOwnersPayload(await client.getCloudSecBeneficialOwners({
|
|
156
160
|
ticker: symbol,
|
|
161
|
+
exchange: listing?.exchange,
|
|
162
|
+
name: listing?.name,
|
|
157
163
|
form,
|
|
158
164
|
history,
|
|
159
165
|
limit: PAGE_SIZE,
|
|
@@ -178,10 +184,20 @@ export async function fetchBeneficialOwners(
|
|
|
178
184
|
offset = nextOffset;
|
|
179
185
|
}
|
|
180
186
|
} catch (error) {
|
|
187
|
+
// A listing abroad whose company the SEC does not know has no reports.
|
|
188
|
+
const abroad = listingAbroad(symbol, listing?.exchange);
|
|
189
|
+
if (abroad && error instanceof ApiRequestError && error.status === 404) return noReports(symbol, history);
|
|
181
190
|
throw describeFailure(error, symbol);
|
|
182
191
|
}
|
|
183
192
|
}
|
|
184
193
|
|
|
194
|
+
function noReports(ticker: string, history: boolean): BeneficialOwnersPayload {
|
|
195
|
+
return {
|
|
196
|
+
ticker, cik: "", companyName: "", asOf: null, owners: [], ...(history ? { filings: [] } : {}),
|
|
197
|
+
hasMore: false, nextOffset: null, coverage: null,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
185
201
|
/** Pages can overlap when a report lands between two requests. */
|
|
186
202
|
function dedupe(rows: BeneficialOwnerFiling[]): BeneficialOwnerFiling[] {
|
|
187
203
|
const seen = new Set<string>();
|
|
@@ -193,17 +209,23 @@ function dedupe(rows: BeneficialOwnerFiling[]): BeneficialOwnerFiling[] {
|
|
|
193
209
|
});
|
|
194
210
|
}
|
|
195
211
|
|
|
196
|
-
|
|
212
|
+
// SAN in Paris is not SAN in New York: a listing abroad is cached under its venue.
|
|
213
|
+
const cacheKey = (ticker: string, listing?: IssuerListingParams) => secListingKey(ticker, listing?.exchange);
|
|
197
214
|
|
|
198
|
-
export function cachedBeneficialOwners(ticker: string): CloudResource<BeneficialOwnersPayload> | null {
|
|
199
|
-
return cachedCloudResource(beneficialOwnersCache, cacheKey(ticker));
|
|
215
|
+
export function cachedBeneficialOwners(ticker: string, listing?: IssuerListingParams): CloudResource<BeneficialOwnersPayload> | null {
|
|
216
|
+
return cachedCloudResource(beneficialOwnersCache, cacheKey(ticker, listing));
|
|
200
217
|
}
|
|
201
218
|
|
|
202
219
|
/** The pane's list: the latest report per filer, both kinds, cached on disk. */
|
|
203
|
-
export async function loadBeneficialOwners(
|
|
220
|
+
export async function loadBeneficialOwners(
|
|
221
|
+
ticker: string,
|
|
222
|
+
force = false,
|
|
223
|
+
listing?: IssuerListingParams,
|
|
224
|
+
): Promise<CloudResource<BeneficialOwnersPayload>> {
|
|
225
|
+
const key = cacheKey(ticker, listing);
|
|
204
226
|
try {
|
|
205
|
-
return await loadCloudResource(beneficialOwnersCache,
|
|
227
|
+
return await loadCloudResource(beneficialOwnersCache, key, () => fetchBeneficialOwners(ticker, { listing }), { force });
|
|
206
228
|
} catch (error) {
|
|
207
|
-
throw describeFailure(error,
|
|
229
|
+
throw describeFailure(error, key);
|
|
208
230
|
}
|
|
209
231
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type DataTableKeyEvent,
|
|
11
11
|
} from "../../../components";
|
|
12
12
|
import { handleRefreshKey, loadingErrorFooterInfo } from "../../../components/data-table/table-pane";
|
|
13
|
+
import type { IssuerListingParams } from "../../../api-client/paths";
|
|
13
14
|
import { useAsyncResource } from "../../../react/async-resource";
|
|
14
15
|
import { useAutoRefresh } from "../../../react/auto-refresh";
|
|
15
16
|
import { colors, priceColor } from "../../../theme/colors";
|
|
@@ -55,10 +56,13 @@ export function BeneficialOwnersView({
|
|
|
55
56
|
fundMatches,
|
|
56
57
|
onCycleView,
|
|
57
58
|
onRefreshHolders,
|
|
59
|
+
listing,
|
|
58
60
|
}: {
|
|
59
61
|
focused: boolean;
|
|
60
62
|
width: number;
|
|
61
63
|
symbol: string | null;
|
|
64
|
+
/** The listing's venue and company, for a listing outside the US. */
|
|
65
|
+
listing?: IssuerListingParams;
|
|
62
66
|
holderRows: readonly HolderRow[];
|
|
63
67
|
fundMatches: ReadonlyMap<string, Holder13FMatch>;
|
|
64
68
|
onCycleView: () => void;
|
|
@@ -75,11 +79,11 @@ export function BeneficialOwnersView({
|
|
|
75
79
|
|
|
76
80
|
// A session change retries a request the sign-in wall was shown for.
|
|
77
81
|
const loader = useMemo(
|
|
78
|
-
() => symbol ? (force: boolean) => loadBeneficialOwners(symbol, force) : null,
|
|
79
|
-
[symbol, session.requestKey],
|
|
82
|
+
() => symbol ? (force: boolean) => loadBeneficialOwners(symbol, force, listing) : null,
|
|
83
|
+
[symbol, listing, session.requestKey],
|
|
80
84
|
);
|
|
81
85
|
const resource = useAsyncResource(loader, {
|
|
82
|
-
initialData: () => symbol ? cachedBeneficialOwners(symbol) : null,
|
|
86
|
+
initialData: () => symbol ? cachedBeneficialOwners(symbol, listing) : null,
|
|
83
87
|
clearOnError: (error) => error instanceof Error && isCloudSessionRequired(error.message),
|
|
84
88
|
});
|
|
85
89
|
useAutoRefresh(resource.updatedAt, resource.load);
|
|
@@ -35,6 +35,7 @@ const CHANGE_COLUMN_KEYS = new Set(["changeShares", "changePercent"]);
|
|
|
35
35
|
const BASIS_COLUMN_KEY = "shareBasis";
|
|
36
36
|
import type { BeneficialOwnersPayload } from "../../../api-client/beneficial-owners";
|
|
37
37
|
import { fetchBeneficialOwners, type BeneficialOwnersRequest } from "./beneficial-client";
|
|
38
|
+
import { resolveHeadlessIssuerListing } from "../shared/headless-market-data";
|
|
38
39
|
import type { BeneficialColumnId } from "./beneficial-model";
|
|
39
40
|
import {
|
|
40
41
|
BENEFICIAL_REPORT_COLUMNS,
|
|
@@ -136,7 +137,11 @@ export interface HoldersHeadlessDependencies {
|
|
|
136
137
|
|
|
137
138
|
const defaultDependencies: HoldersHeadlessDependencies = {
|
|
138
139
|
loadSnapshot: (symbol, _args, ctx) => loadHolderSnapshot(ctx.marketData, symbol),
|
|
139
|
-
|
|
140
|
+
// A listing abroad names its venue and company, so it never reads a US namesake's owners.
|
|
141
|
+
loadBeneficialOwners: async (symbol, request, ctx) => fetchBeneficialOwners(symbol, {
|
|
142
|
+
...request,
|
|
143
|
+
listing: await resolveHeadlessIssuerListing(ctx, symbol),
|
|
144
|
+
}, {
|
|
140
145
|
client: ctx.apiClient,
|
|
141
146
|
signal: ctx.signal,
|
|
142
147
|
}),
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
import { loadHolderData } from "./client";
|
|
44
44
|
import { HoldersTreemap } from "./treemap";
|
|
45
45
|
import { BeneficialOwnersView } from "./beneficial-view";
|
|
46
|
+
import { useIssuerListing } from "../shared/ticker-request";
|
|
46
47
|
import type { HolderColumn, HolderColumnId, HolderRow, SortPreference, ViewMode } from "./types";
|
|
47
48
|
import { loadHolder13FMatches, type Holder13FMatch } from "./thirteenf-match";
|
|
48
49
|
import { useSampledValue, useTickerQuoteStream } from "../../../state/hooks/live-ticker-financials";
|
|
@@ -65,6 +66,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
|
|
|
65
66
|
const fundMatchAbortRef = useRef<AbortController | null>(null);
|
|
66
67
|
|
|
67
68
|
const exchange = ticker?.metadata.exchange ?? "";
|
|
69
|
+
const issuerListing = useIssuerListing(ticker);
|
|
68
70
|
const loadHolders = useMemo(() => symbol ? async (forceRefresh: boolean) => {
|
|
69
71
|
if (!dataProvider) throw new Error("Holder data unavailable");
|
|
70
72
|
return loadHolderData(dataProvider, symbol, exchange, forceRefresh ? { cacheMode: "refresh" } : undefined);
|
|
@@ -337,6 +339,7 @@ export function HoldersView({ focused, width, height }: { focused: boolean; widt
|
|
|
337
339
|
focused={focused}
|
|
338
340
|
width={width}
|
|
339
341
|
symbol={symbol ?? null}
|
|
342
|
+
listing={issuerListing}
|
|
340
343
|
holderRows={rows}
|
|
341
344
|
fundMatches={fundMatches}
|
|
342
345
|
onCycleView={toggleView}
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
type StatItem,
|
|
23
23
|
} from "../../../components";
|
|
24
24
|
import { useDebouncedPluginPaneState, usePluginPaneState } from "../../runtime";
|
|
25
|
-
import {
|
|
25
|
+
import { mayBeUsEquityTicker } from "../../../utils/sec";
|
|
26
26
|
import { formatCompact } from "../../../utils/format";
|
|
27
27
|
import { nextHeaderSort } from "../../../utils/sort-values";
|
|
28
28
|
import { formatShortDate } from "../../../utils/datetime-format";
|
|
@@ -130,7 +130,7 @@ function InsiderView({ width, height, focused }: { width: number; height: number
|
|
|
130
130
|
[setOpenItemIdState],
|
|
131
131
|
);
|
|
132
132
|
const [sort, setSort] = useState<StackSortPreference<InsiderColumnId>>({ columnId: "date", direction: "desc" });
|
|
133
|
-
const eligibleTicker =
|
|
133
|
+
const eligibleTicker = mayBeUsEquityTicker(ticker);
|
|
134
134
|
const instrument = instrumentFromTicker(ticker, ticker?.metadata.ticker ?? null);
|
|
135
135
|
|
|
136
136
|
const filingsEntry = useSecFilingsQuery(
|
|
@@ -458,7 +458,7 @@ export const insiderModule: PluginModule = {
|
|
|
458
458
|
description: "Insider transaction activity for the selected ticker.",
|
|
459
459
|
keywords: ["insider", "form 4", "ownership", "transactions", "ins"],
|
|
460
460
|
shortcut: "INS",
|
|
461
|
-
canCreate: (_context, options) => !options?.ticker ||
|
|
461
|
+
canCreate: (_context, options) => !options?.ticker || mayBeUsEquityTicker(options.ticker),
|
|
462
462
|
}),
|
|
463
463
|
headless: insiderHeadless,
|
|
464
464
|
},
|
|
@@ -471,7 +471,7 @@ export const insiderModule: PluginModule = {
|
|
|
471
471
|
order: 47,
|
|
472
472
|
component: InsiderView,
|
|
473
473
|
instruments: ["equity"],
|
|
474
|
-
isVisible: ({ ticker }) =>
|
|
474
|
+
isVisible: ({ ticker }) => mayBeUsEquityTicker(ticker),
|
|
475
475
|
});
|
|
476
476
|
},
|
|
477
477
|
};
|