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
|
@@ -2,25 +2,45 @@ import { saveConfig } from "../../../../data/config/store";
|
|
|
2
2
|
import { withConfigData, withMarketData } from "../../../../cli/scoped-context";
|
|
3
3
|
import { countCollectionTickers, findWatchlist } from "../../../../cli/helpers";
|
|
4
4
|
import { slugifyName } from "../../../../utils/slugify";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveCliTicker } from "../../../../cli/ticker-resolution";
|
|
6
6
|
import { takeOption } from "../../../../cli/commands/command-utils";
|
|
7
|
-
import { EXCHANGE_OPTION, loadSavedListing, requireListingArg, savedListingName } from "../../../../cli/listing-arg";
|
|
7
|
+
import { EXCHANGE_OPTION, ListingArgError, loadSavedListing, requireListingArg, savedListingName } from "../../../../cli/listing-arg";
|
|
8
8
|
import {
|
|
9
9
|
cliStyles,
|
|
10
10
|
renderSection,
|
|
11
11
|
renderStats,
|
|
12
12
|
renderTable,
|
|
13
13
|
} from "../../../../utils/cli-output";
|
|
14
|
+
import type { AppConfig } from "../../../../types/config";
|
|
14
15
|
import type { CliCommandContext, CliCommandDef } from "../../../../types/plugin";
|
|
16
|
+
import type { Watchlist } from "../../../../types/ticker";
|
|
17
|
+
import type { ConfigContext, MarketContext } from "../../../../cli/types";
|
|
15
18
|
import {
|
|
16
19
|
addTickerToWatchlist,
|
|
17
20
|
deleteWatchlist as deleteWatchlistConfig,
|
|
18
21
|
removeTickerFromWatchlist as removeWatchlistMembership,
|
|
19
22
|
} from "../mutations";
|
|
20
23
|
import { showCollection } from "./render";
|
|
21
|
-
import { listingFields } from "./shared";
|
|
24
|
+
import { listingFields, takeCollectionName } from "./shared";
|
|
25
|
+
import { addSymbols, FILE_OPTION, printSymbolRows, removeSymbols, requireSymbolList, retryNotice, SYMBOL_LIST_HELP } from "./bulk-symbols";
|
|
22
26
|
import { CLI_COMMAND_GROUPS } from "../../../../cli/help";
|
|
23
27
|
|
|
28
|
+
const ADD_USAGE = "Usage: gloomberb watchlist add <watchlist> <symbols...> [--file <path>]";
|
|
29
|
+
const REMOVE_USAGE = "Usage: gloomberb watchlist remove <watchlist> <symbols...> [--file <path>]";
|
|
30
|
+
|
|
31
|
+
/** The watchlist the leading arguments name and the symbols after it; fails naming the watchlists there are. */
|
|
32
|
+
function requireWatchlistArgs(config: AppConfig, args: readonly string[], usage: string, ctx: CliCommandContext): { watchlist: Watchlist; rest: string[] } {
|
|
33
|
+
if (args.length === 0) ctx.fail(usage);
|
|
34
|
+
const match = takeCollectionName(args, config.watchlists);
|
|
35
|
+
if (!match) {
|
|
36
|
+
ctx.fail(
|
|
37
|
+
`Watchlist "${args[0]}" was not found.`,
|
|
38
|
+
config.watchlists.length > 0 ? `Watchlists: ${config.watchlists.map((entry) => entry.name).join(", ")}` : undefined,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return { watchlist: match.collection, rest: match.rest };
|
|
42
|
+
}
|
|
43
|
+
|
|
24
44
|
async function createWatchlist(name: string, ctx: CliCommandContext) {
|
|
25
45
|
await withConfigData(ctx, async ({ config }) => {
|
|
26
46
|
const trimmedName = name.trim();
|
|
@@ -58,47 +78,83 @@ async function deleteWatchlist(name: string, ctx: CliCommandContext) {
|
|
|
58
78
|
});
|
|
59
79
|
}
|
|
60
80
|
|
|
61
|
-
async function addTickerToWatchlistCommand(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
await store.saveTicker(result.ticker);
|
|
78
|
-
ctx.printResult({ data }, { text: () => cliStyles.success(`Added ${saved.label} to "${watchlist.name}".`) });
|
|
79
|
-
} catch (error) {
|
|
80
|
-
ctx.fail(error instanceof Error ? error.message : `Failed to add ${symbol} to "${watchlist.name}".`);
|
|
81
|
+
async function addTickerToWatchlistCommand(watchlist: Watchlist, symbol: string, exchange: string | undefined, ctx: CliCommandContext, { store, dataProvider }: MarketContext) {
|
|
82
|
+
try {
|
|
83
|
+
// A bare symbol is stored on the listing `quote` reads it as, and the notes say which.
|
|
84
|
+
const { ticker, notes } = await resolveCliTicker(symbol, store, dataProvider, exchange, {
|
|
85
|
+
retry: (key) => `gloomberb watchlist add ${watchlist.name} ${key}`,
|
|
86
|
+
});
|
|
87
|
+
const result = addTickerToWatchlist(ticker, watchlist.id);
|
|
88
|
+
// Name the listing that was stored: SAN:EPA is not the SAN that a bare SAN means.
|
|
89
|
+
const saved = savedListingName(ticker);
|
|
90
|
+
const data = { changed: result.changed, ...listingFields(saved), watchlist: watchlist.name };
|
|
91
|
+
const warnings = notes.length > 0 ? notes : undefined;
|
|
92
|
+
if (!result.changed) {
|
|
93
|
+
ctx.printResult({ data, warnings }, { text: () => cliStyles.warning(`${saved.label} is already in "${watchlist.name}".`) });
|
|
94
|
+
return;
|
|
81
95
|
}
|
|
96
|
+
|
|
97
|
+
await store.saveTicker(result.ticker);
|
|
98
|
+
ctx.printResult({ data, warnings }, { text: () => cliStyles.success(`Added ${saved.label} to "${watchlist.name}".`) });
|
|
99
|
+
} catch (error) {
|
|
100
|
+
ctx.fail(
|
|
101
|
+
error instanceof Error ? error.message : `Failed to add ${symbol} to "${watchlist.name}".`,
|
|
102
|
+
error instanceof ListingArgError ? error.details : undefined,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function addToWatchlistCommand(args: string[], file: string | undefined, exchange: string | undefined, ctx: CliCommandContext) {
|
|
108
|
+
await withMarketData(ctx, async (market) => {
|
|
109
|
+
const { watchlist, rest } = requireWatchlistArgs(market.config, args, ADD_USAGE, ctx);
|
|
110
|
+
const list = await requireSymbolList(ctx, rest, file, ADD_USAGE);
|
|
111
|
+
if (list.single) {
|
|
112
|
+
await addTickerToWatchlistCommand(watchlist, list.single, exchange, ctx, market);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const rows = await addSymbols({
|
|
116
|
+
symbols: list.symbols,
|
|
117
|
+
exchange,
|
|
118
|
+
store: market.store,
|
|
119
|
+
dataProvider: market.dataProvider,
|
|
120
|
+
onRetry: retryNotice(ctx),
|
|
121
|
+
retry: (key) => `gloomberb watchlist add ${watchlist.name} ${key}`,
|
|
122
|
+
add: (ticker) => addTickerToWatchlist(ticker, watchlist.id),
|
|
123
|
+
});
|
|
124
|
+
printSymbolRows(ctx, rows, { verb: "add", collection: { kind: "watchlist", name: watchlist.name }, repeated: list.repeated });
|
|
82
125
|
});
|
|
83
126
|
}
|
|
84
127
|
|
|
85
|
-
async function removeTickerFromWatchlist(
|
|
128
|
+
async function removeTickerFromWatchlist(watchlist: Watchlist, symbol: string, exchange: string | undefined, ctx: CliCommandContext, { store }: ConfigContext) {
|
|
86
129
|
// SAN:EPA and SAN --exchange EPA name the stored listing, which a bare SAN may hold under another venue.
|
|
87
130
|
const listing = await requireListingArg(symbol, exchange, ctx);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
131
|
+
const ticker = await loadSavedListing(store, listing);
|
|
132
|
+
if (!ticker) ctx.fail(`Ticker "${listing.key}" was not found in your local data.`);
|
|
133
|
+
const saved = savedListingName(ticker);
|
|
134
|
+
const result = removeWatchlistMembership(ticker, watchlist.id);
|
|
135
|
+
if (!result.changed) ctx.fail(`${saved.key} is not in "${watchlist.name}".`);
|
|
91
136
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
137
|
+
await store.saveTicker(result.ticker);
|
|
138
|
+
ctx.printResult({ data: { changed: true, ...listingFields(saved), watchlist: watchlist.name } }, {
|
|
139
|
+
text: () => cliStyles.success(`Removed ${saved.label} from "${watchlist.name}".`),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
97
142
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
143
|
+
async function removeFromWatchlistCommand(args: string[], file: string | undefined, exchange: string | undefined, ctx: CliCommandContext) {
|
|
144
|
+
await withConfigData(ctx, async (context) => {
|
|
145
|
+
const { watchlist, rest } = requireWatchlistArgs(context.config, args, REMOVE_USAGE, ctx);
|
|
146
|
+
const list = await requireSymbolList(ctx, rest, file, REMOVE_USAGE);
|
|
147
|
+
if (list.single) {
|
|
148
|
+
await removeTickerFromWatchlist(watchlist, list.single, exchange, ctx, context);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const rows = await removeSymbols({
|
|
152
|
+
symbols: list.symbols,
|
|
153
|
+
exchange,
|
|
154
|
+
store: context.store,
|
|
155
|
+
remove: (ticker) => removeWatchlistMembership(ticker, watchlist.id),
|
|
101
156
|
});
|
|
157
|
+
printSymbolRows(ctx, rows, { verb: "remove", collection: { kind: "watchlist", name: watchlist.name }, repeated: list.repeated });
|
|
102
158
|
});
|
|
103
159
|
}
|
|
104
160
|
|
|
@@ -154,16 +210,28 @@ export const watchlistCliCommand: CliCommandDef = {
|
|
|
154
210
|
"watchlist show <name>",
|
|
155
211
|
"watchlist create <name>",
|
|
156
212
|
"watchlist delete <name>",
|
|
157
|
-
"watchlist add <watchlist> <
|
|
158
|
-
"watchlist remove <watchlist> <
|
|
213
|
+
"watchlist add <watchlist> <symbols...> [--file <path>]",
|
|
214
|
+
"watchlist remove <watchlist> <symbols...> [--file <path>]",
|
|
159
215
|
],
|
|
160
|
-
options: [EXCHANGE_OPTION],
|
|
161
|
-
examples: [
|
|
216
|
+
options: [EXCHANGE_OPTION, FILE_OPTION],
|
|
217
|
+
examples: [
|
|
218
|
+
"watchlist show Growth",
|
|
219
|
+
"watchlist create Growth",
|
|
220
|
+
"watchlist add Growth NVDA",
|
|
221
|
+
"watchlist add Growth SAN:EPA",
|
|
222
|
+
"watchlist add Growth NVDA AMD,AVGO",
|
|
223
|
+
"watchlist add Growth --file holdings.csv",
|
|
224
|
+
"watchlist show Growth --csv",
|
|
225
|
+
],
|
|
226
|
+
sections: [SYMBOL_LIST_HELP],
|
|
162
227
|
},
|
|
163
228
|
execute: async (rawArgs, ctx) => {
|
|
164
229
|
const args = [...rawArgs];
|
|
165
230
|
const exchange = takeOption(args, "--exchange");
|
|
231
|
+
const hasFile = args.some((arg) => arg === "--file" || arg.startsWith("--file="));
|
|
232
|
+
const file = hasFile ? takeOption(args, "--file") ?? "" : undefined;
|
|
166
233
|
const action = args[0];
|
|
234
|
+
if (file != null && action !== "add" && action !== "remove") ctx.fail(`--file is an option of watchlist add and remove, not watchlist ${action ?? "list"}.`, ADD_USAGE);
|
|
167
235
|
|
|
168
236
|
if (!action || action === "list") {
|
|
169
237
|
await listWatchlists(ctx);
|
|
@@ -192,21 +260,26 @@ export const watchlistCliCommand: CliCommandDef = {
|
|
|
192
260
|
}
|
|
193
261
|
|
|
194
262
|
if (action === "add") {
|
|
195
|
-
|
|
196
|
-
const name = args.slice(1, -1).join(" ");
|
|
197
|
-
if (!name || !symbol) ctx.fail("Usage: gloomberb watchlist add <watchlist> <ticker>");
|
|
198
|
-
await addTickerToWatchlistCommand(name!, symbol!, exchange, ctx);
|
|
263
|
+
await addToWatchlistCommand(args.slice(1), file, exchange, ctx);
|
|
199
264
|
return;
|
|
200
265
|
}
|
|
201
266
|
|
|
202
267
|
if (action === "remove") {
|
|
203
|
-
|
|
204
|
-
const name = args.slice(1, -1).join(" ");
|
|
205
|
-
if (!name || !symbol) ctx.fail("Usage: gloomberb watchlist remove <watchlist> <ticker>");
|
|
206
|
-
await removeTickerFromWatchlist(name!, symbol!, exchange, ctx);
|
|
268
|
+
await removeFromWatchlistCommand(args.slice(1), file, exchange, ctx);
|
|
207
269
|
return;
|
|
208
270
|
}
|
|
209
271
|
|
|
272
|
+
if (action === "import") {
|
|
273
|
+
// A list of symbols is what add reads; say how, with the user's own list and file.
|
|
274
|
+
const rest = args.slice(1);
|
|
275
|
+
const path = /\.\w+$/.test(rest.at(-1) ?? "") ? rest.at(-1)! : null;
|
|
276
|
+
const name = (path ? rest.slice(0, -1) : rest).join(" ") || "<watchlist>";
|
|
277
|
+
ctx.fail(
|
|
278
|
+
`watchlist has no import. To add the symbols in ${path ?? "a file"}, run: gloomberb watchlist add ${/\s/.test(name) ? `"${name}"` : name} --file ${path ?? "<path>"}`,
|
|
279
|
+
ADD_USAGE,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
210
283
|
await showCollection(args.join(" "), ctx);
|
|
211
284
|
},
|
|
212
285
|
};
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
portfolioPnlPercent,
|
|
50
50
|
signedPositionDirection,
|
|
51
51
|
type PortfolioPositionPnl,
|
|
52
|
-
} from "
|
|
52
|
+
} from "../../../portfolio/position-metrics";
|
|
53
53
|
import { isFiniteNumber } from "../../../utils/guards";
|
|
54
54
|
import {
|
|
55
55
|
allocationFigures,
|
|
@@ -17,7 +17,7 @@ import { createRowValueCache, type RowValueCache } from "../../../components/ui/
|
|
|
17
17
|
import { objectVersion } from "../../../utils/object-version";
|
|
18
18
|
import { columnContextVersion } from "./cell-version";
|
|
19
19
|
import { getColumnValue, getSortValue, type ColumnContext } from "./metrics";
|
|
20
|
-
import { getPortfolioPositionMetrics, getPortfolioQuoteDisplay } from "
|
|
20
|
+
import { getPortfolioPositionMetrics, getPortfolioQuoteDisplay } from "../../../portfolio/position-metrics";
|
|
21
21
|
import { PORTFOLIO_ROW_MENU_KEYS } from "./row-actions";
|
|
22
22
|
import { PORTFOLIO_REORDER_THROTTLE_MS } from "./use-throttled-ticker-order";
|
|
23
23
|
import { useThrottledMemo } from "./use-throttled-memo";
|
|
@@ -9,12 +9,17 @@ import type {
|
|
|
9
9
|
import type { TickerRecord } from "../../../types/ticker";
|
|
10
10
|
import { formatNumber, formatPercentRaw } from "../../../utils/format";
|
|
11
11
|
import {
|
|
12
|
+
collectionQuoteHeadline,
|
|
13
|
+
extendedQuoteFields,
|
|
14
|
+
extendedSessionsOf,
|
|
12
15
|
findCollection,
|
|
16
|
+
listingLabel,
|
|
13
17
|
loadCollectionQuotes,
|
|
14
18
|
valuePortfolioAllocation,
|
|
15
19
|
valuePortfolioPositions,
|
|
16
20
|
type CollectionMatch,
|
|
17
21
|
} from "./cli/render";
|
|
22
|
+
import { EXTENDED_SESSION_LABELS, type ExtendedSession } from "../../../market-data/market/status";
|
|
18
23
|
import {
|
|
19
24
|
BROKER_ACCOUNT_MISSING_NOTE,
|
|
20
25
|
CASH_SYMBOL,
|
|
@@ -23,9 +28,10 @@ import {
|
|
|
23
28
|
formatAllocationWeight,
|
|
24
29
|
formatTradeUnits,
|
|
25
30
|
} from "./allocation";
|
|
26
|
-
import {
|
|
31
|
+
import { currencyPriceMinDigits, formatMarketPrice, formatMarketQuantity } from "../../../market-data/market/format";
|
|
27
32
|
import { resolvePortfolioTotalsCurrency } from "./summary/totals";
|
|
28
33
|
import { quoteFreshnessFields } from "../shared/report-freshness";
|
|
34
|
+
import { importedFromText } from "./imported-from";
|
|
29
35
|
|
|
30
36
|
const DEFAULT_ROW_LIMIT = 50;
|
|
31
37
|
const MAX_ROW_LIMIT = 200;
|
|
@@ -50,7 +56,7 @@ const tradeUnits = (value: unknown, row: HeadlessPaneRow) => (
|
|
|
50
56
|
/** Money per unit at the currency's minor digits: $230.00, not 230. */
|
|
51
57
|
const unitMoney = (currencyKey: string) => (value: unknown, row: HeadlessPaneRow) => (
|
|
52
58
|
typeof value === "number"
|
|
53
|
-
? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits:
|
|
59
|
+
? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits: currencyPriceMinDigits(textOf(row[currencyKey])) })
|
|
54
60
|
: formatNumber(undefined)
|
|
55
61
|
);
|
|
56
62
|
|
|
@@ -61,6 +67,7 @@ function textOf(value: unknown): string | undefined {
|
|
|
61
67
|
const POSITION_COLUMNS: HeadlessPaneColumn[] = [
|
|
62
68
|
{ key: "symbol", header: "Ticker" },
|
|
63
69
|
{ key: "name", header: "Name" },
|
|
70
|
+
{ key: "exchange", header: "Exchange" },
|
|
64
71
|
{ key: "shares", header: "Qty", align: "right", format: quantity },
|
|
65
72
|
{ key: "avgCost", header: "Avg Cost", align: "right", format: unitMoney("positionCurrency"), description: "Per unit, in the position's currency." },
|
|
66
73
|
{ key: "price", header: "Last", align: "right", format: unitMoney("priceCurrency"), description: "In the quote's currency." },
|
|
@@ -79,6 +86,26 @@ const TARGET_COLUMNS: HeadlessPaneColumn[] = [
|
|
|
79
86
|
{ key: "tradeValue", header: "Trade Value", align: "right", format: signedAmount, description: "The trade in the portfolio's currency." },
|
|
80
87
|
];
|
|
81
88
|
|
|
89
|
+
/** The pre-market or after-hours print and its move from the regular close, for the rows that have one. */
|
|
90
|
+
function extendedColumn(session: ExtendedSession): HeadlessPaneColumn {
|
|
91
|
+
return {
|
|
92
|
+
key: "extendedPrice",
|
|
93
|
+
header: EXTENDED_SESSION_LABELS[session],
|
|
94
|
+
align: "right",
|
|
95
|
+
format: (value, row) => row.extendedSession === session && typeof value === "number"
|
|
96
|
+
? `${unitMoney("priceCurrency")(value, row)} ${percent(row.extendedChangePercent)}`
|
|
97
|
+
: formatNumber(undefined),
|
|
98
|
+
description: "Measured from the regular close in Last.",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** `columns` with an extended column after Chg for each session a row has a print for. */
|
|
103
|
+
function withExtendedColumns(columns: HeadlessPaneColumn[], sessions: readonly ExtendedSession[]): HeadlessPaneColumn[] {
|
|
104
|
+
if (sessions.length === 0) return columns;
|
|
105
|
+
const at = columns.findIndex((column) => column.key === "changePercent") + 1;
|
|
106
|
+
return [...columns.slice(0, at), ...sessions.map(extendedColumn), ...columns.slice(at)];
|
|
107
|
+
}
|
|
108
|
+
|
|
82
109
|
const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
|
|
83
110
|
{ key: "symbol", header: "Ticker" },
|
|
84
111
|
{ key: "name", header: "Name" },
|
|
@@ -88,6 +115,25 @@ const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
|
|
|
88
115
|
{ key: "changePercent", header: "Chg", align: "right", format: percent },
|
|
89
116
|
];
|
|
90
117
|
|
|
118
|
+
/**
|
|
119
|
+
* `columns` with the text report's Ticker column naming each listing as
|
|
120
|
+
* `portfolio show` does (SAN:EPA, SAN:NYSE), not by the key it is stored under,
|
|
121
|
+
* which leaves two listings of one symbol looking alike. `textFormat` is text
|
|
122
|
+
* only: JSON and CSV keep the stored key in `symbol`, and the rows stay keyed
|
|
123
|
+
* by it.
|
|
124
|
+
*/
|
|
125
|
+
function withListingLabels(columns: HeadlessPaneColumn[], tickers: readonly TickerRecord[]): HeadlessPaneColumn[] {
|
|
126
|
+
const labels = new Map(tickers.map((ticker) => [ticker.metadata.ticker, listingLabel(ticker)]));
|
|
127
|
+
return columns.map((column) => column.key !== "symbol" ? column : {
|
|
128
|
+
...column,
|
|
129
|
+
textFormat: (value, row) => {
|
|
130
|
+
// The cash line is not a listing, even when a ticker is called CASH; its row carries no exchange.
|
|
131
|
+
if (typeof value !== "string" || !("exchange" in row)) return textOf(value) ?? formatNumber(undefined);
|
|
132
|
+
return labels.get(value) ?? value;
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
91
137
|
function finite(value: unknown): number | null {
|
|
92
138
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
93
139
|
}
|
|
@@ -154,8 +200,9 @@ async function portfolioHoldings(
|
|
|
154
200
|
const gross = held.reduce((sum, entry) => sum + Math.abs(finite(entry.row.marketValue) ?? 0), 0);
|
|
155
201
|
const sum = (key: string) => held.reduce((total, entry) => total + (finite(entry.row[key]) ?? 0), 0);
|
|
156
202
|
const seen = new Set<string>();
|
|
203
|
+
const extendedSessions = extendedSessionsOf(held.map(({ extended }) => extended?.session));
|
|
157
204
|
const rows = held
|
|
158
|
-
.map(({ ticker,
|
|
205
|
+
.map(({ ticker, headline, extended, row }) => {
|
|
159
206
|
const marketValue = finite(row.marketValue);
|
|
160
207
|
// A ticker held in several lots carries its allocation on its first row.
|
|
161
208
|
const figures = seen.has(ticker.metadata.ticker) ? undefined : allocationBySymbol.get(ticker.metadata.ticker);
|
|
@@ -170,9 +217,11 @@ async function portfolioHoldings(
|
|
|
170
217
|
shares: finite(row.shares),
|
|
171
218
|
avgCost: finite(row.avgCost),
|
|
172
219
|
positionCurrency: row.positionCurrency ?? null,
|
|
220
|
+
// Last and Chg are the regular session; market value and P&L are at the live price.
|
|
173
221
|
price: finite(row.quotePrice),
|
|
174
222
|
priceCurrency: row.quoteCurrency ?? null,
|
|
175
|
-
changePercent: finite(
|
|
223
|
+
changePercent: finite(headline?.changePercent),
|
|
224
|
+
...extendedQuoteFields(extended),
|
|
176
225
|
marketValue,
|
|
177
226
|
unrealizedPnl: finite(row.unrealizedPnl),
|
|
178
227
|
weight: figures?.weight ?? null,
|
|
@@ -206,7 +255,9 @@ async function portfolioHoldings(
|
|
|
206
255
|
const broker = !!(target.portfolio.brokerId || target.portfolio.brokerInstanceId);
|
|
207
256
|
const showTargets = allocation.targetSum != null;
|
|
208
257
|
const targetNote = describeTargetSum(allocation.targetSum);
|
|
258
|
+
const imported = importedFromText(target.portfolio);
|
|
209
259
|
const notices = [
|
|
260
|
+
...(imported ? [imported] : []),
|
|
210
261
|
...(rows.length > limit
|
|
211
262
|
? [`${rows.length - limit} more position${rows.length - limit === 1 ? "" : "s"} not shown; totals include every position.`]
|
|
212
263
|
: []),
|
|
@@ -216,7 +267,10 @@ async function portfolioHoldings(
|
|
|
216
267
|
|
|
217
268
|
return {
|
|
218
269
|
freshness: { source: broker ? "Your broker account and Gloom Cloud" : "Local portfolio and Gloom Cloud" },
|
|
219
|
-
columns:
|
|
270
|
+
columns: withListingLabels(
|
|
271
|
+
withExtendedColumns(showTargets ? [...POSITION_COLUMNS, ...TARGET_COLUMNS] : POSITION_COLUMNS, extendedSessions),
|
|
272
|
+
tickers,
|
|
273
|
+
),
|
|
220
274
|
rows: shown,
|
|
221
275
|
complete: unavailable.length === 0,
|
|
222
276
|
...(unavailable.length
|
|
@@ -224,6 +278,7 @@ async function portfolioHoldings(
|
|
|
224
278
|
: {}),
|
|
225
279
|
metadata: {
|
|
226
280
|
collection: { kind: "portfolio", id: target.id, name: target.name, broker },
|
|
281
|
+
...(target.portfolio.importedFrom ? { importedFrom: target.portfolio.importedFrom } : {}),
|
|
227
282
|
currency,
|
|
228
283
|
positions: rows.length,
|
|
229
284
|
totals: {
|
|
@@ -254,21 +309,27 @@ async function watchlistHoldings(
|
|
|
254
309
|
ctx.signal.throwIfAborted();
|
|
255
310
|
const rows = tickers.map((ticker) => {
|
|
256
311
|
const quote = quotes.get(ticker.metadata.ticker);
|
|
312
|
+
// As the watchlist pane shows it: the regular session, then any extended print from its close.
|
|
313
|
+
const { headline, extended } = collectionQuoteHeadline(quote);
|
|
257
314
|
return {
|
|
258
315
|
...quoteFreshnessFields(quote),
|
|
259
316
|
updatedAt: quote?.lastUpdated ?? null,
|
|
260
317
|
symbol: ticker.metadata.ticker,
|
|
261
318
|
name: ticker.metadata.name ?? null,
|
|
262
319
|
exchange: ticker.metadata.exchange || null,
|
|
263
|
-
price: finite(quote?.price),
|
|
320
|
+
price: finite(headline?.price ?? quote?.price),
|
|
264
321
|
priceCurrency: quote?.currency ?? null,
|
|
265
|
-
changePercent: finite(quote?.changePercent),
|
|
322
|
+
changePercent: finite(headline ? headline.changePercent : quote?.changePercent),
|
|
323
|
+
...extendedQuoteFields(extended),
|
|
266
324
|
};
|
|
267
325
|
});
|
|
268
326
|
const shown = rows.slice(0, limit);
|
|
269
327
|
return {
|
|
270
328
|
freshness: { source: "Local watchlist and Gloom Cloud" },
|
|
271
|
-
columns:
|
|
329
|
+
columns: withListingLabels(
|
|
330
|
+
withExtendedColumns(WATCHLIST_COLUMNS, extendedSessionsOf(shown.map((row) => row.extendedSession))),
|
|
331
|
+
tickers,
|
|
332
|
+
),
|
|
272
333
|
rows: shown,
|
|
273
334
|
metadata: {
|
|
274
335
|
collection: { kind: "watchlist", id: target.id, name: target.name },
|
|
@@ -288,7 +349,7 @@ async function watchlistHoldings(
|
|
|
288
349
|
export const collectionHoldingsHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
289
350
|
shape: "rows",
|
|
290
351
|
description:
|
|
291
|
-
"Positions held in a portfolio, broker or manual: symbol,
|
|
352
|
+
"Positions held in a portfolio, broker or manual: symbol, exchange, shares, average cost, last price, market value, unrealized P&L and weight of the total with cash, largest first, then the cash line and totals. With target weights set, each row adds its target, drift and the trade to reach it. For a watchlist, its tickers with quotes. Takes a portfolio or watchlist ID; the first portfolio when omitted.",
|
|
292
353
|
discovery: {
|
|
293
354
|
dataRequirements: ["Local portfolios, watchlists and synced broker positions; current quotes"],
|
|
294
355
|
limitations: ["Unrealized P&L on current positions; excludes realized trades, distributions and cash flows"],
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Portfolio } from "../../../types/ticker";
|
|
2
|
+
|
|
3
|
+
/** One line naming the filing an imported portfolio comes from, as `portfolio show`, `fn PF` and the import print it. */
|
|
4
|
+
export function importedFromText(portfolio: Pick<Portfolio, "importedFrom">): string | null {
|
|
5
|
+
const source = portfolio.importedFrom;
|
|
6
|
+
if (!source) return null;
|
|
7
|
+
return `Weights from ${source.name}'s 13F for ${source.period}, filed ${source.filed}; not your holdings.`;
|
|
8
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AnalystResearchData, Fundamentals, Quote } from "../../../types/financials";
|
|
2
2
|
import { hasLikelyQuoteUnitMismatch } from "../../../utils/currency-units";
|
|
3
|
+
import { priceEarningsEps } from "../../../utils/fundamentals";
|
|
3
4
|
import { selectMarketCapitalization, type MarketCapitalization } from "../../../utils/market-capitalization";
|
|
4
5
|
import { priceEarningsOnEarnings, type PriceEarnings } from "../../../utils/price-earnings";
|
|
5
6
|
|
|
@@ -54,9 +55,12 @@ function repriceMultiple(
|
|
|
54
55
|
return price / perShare;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Trailing P/E over the current price; not meaningful when the trailing EPS is zero or a loss. An EPS in another
|
|
60
|
+
* currency than the price is repriced at the rate the served P/E converted it at.
|
|
61
|
+
*/
|
|
58
62
|
export function liveTrailingPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): PriceEarnings | undefined {
|
|
59
|
-
return priceEarningsOnEarnings(repriceMultiple(fundamentals?.trailingPE, fundamentals
|
|
63
|
+
return priceEarningsOnEarnings(repriceMultiple(fundamentals?.trailingPE, priceEarningsEps(fundamentals), quote, fundamentals), fundamentals?.eps);
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
/** Forward P/E over the current price; not meaningful when the forward EPS behind it is zero or a loss. */
|
|
@@ -88,7 +88,7 @@ import { useThrottledTickerOrder } from "../use-throttled-ticker-order";
|
|
|
88
88
|
import { useThrottledMemo } from "../use-throttled-memo";
|
|
89
89
|
import { useColumnClock } from "../use-column-clock";
|
|
90
90
|
import { liveMarketCapitalization } from "../live-valuation";
|
|
91
|
-
import { hasUnknownOptionMultiplier } from "
|
|
91
|
+
import { hasUnknownOptionMultiplier } from "../../../../portfolio/position-metrics";
|
|
92
92
|
import {
|
|
93
93
|
allocationTotal,
|
|
94
94
|
buildPortfolioAllocation,
|
|
@@ -126,6 +126,8 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
|
|
|
126
126
|
|
|
127
127
|
const [streamWindow, setStreamWindow] = useState({ start: 0, end: 24 });
|
|
128
128
|
const [quickAddFocused, setQuickAddFocused] = useState(false);
|
|
129
|
+
// Bumped by the empty table's "+ ticker" button to open the add row.
|
|
130
|
+
const [quickAddRequest, setQuickAddRequest] = useState(0);
|
|
129
131
|
|
|
130
132
|
const {
|
|
131
133
|
cursorSymbol,
|
|
@@ -612,6 +614,7 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
|
|
|
612
614
|
return null;
|
|
613
615
|
}, [activeCollectionId, config, currentPortfolio]);
|
|
614
616
|
const showQuickAdd = !!(activeCollectionId && activeCollectionEntry && quickAddCollectionKind);
|
|
617
|
+
const requestQuickAdd = useCallback(() => setQuickAddRequest((count) => count + 1), []);
|
|
615
618
|
const quickAddHeight = showQuickAdd ? 1 : 0;
|
|
616
619
|
const selectedFinancials = cursorSymbol ? financialsMap.get(cursorSymbol) : undefined;
|
|
617
620
|
const selectedCap = liveMarketCapitalization(selectedFinancials?.quote, selectedFinancials?.fundamentals);
|
|
@@ -636,6 +639,7 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
|
|
|
636
639
|
width={width}
|
|
637
640
|
onAdded={handleTickerAdded}
|
|
638
641
|
onFocusChange={setQuickAddFocused}
|
|
642
|
+
focusRequest={quickAddRequest}
|
|
639
643
|
/>
|
|
640
644
|
) : null;
|
|
641
645
|
|
|
@@ -674,6 +678,7 @@ export function PortfolioListPane({ focused, width, height }: PaneProps) {
|
|
|
674
678
|
visibleRangeBuffer={3}
|
|
675
679
|
resetScrollKey={activeCollectionId}
|
|
676
680
|
onRowActivate={handleRowActivate}
|
|
681
|
+
onAddTicker={showQuickAdd ? requestQuickAdd : undefined}
|
|
677
682
|
rootHeight={contentHeight}
|
|
678
683
|
/>
|
|
679
684
|
) : (
|
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
} from "./resolution";
|
|
31
31
|
|
|
32
32
|
const QUICK_ADD_DEBOUNCE_MS = 300;
|
|
33
|
+
/** The pane key that opens the add row, as its footer hint shows it. */
|
|
34
|
+
export const QUICK_ADD_KEY = "a";
|
|
33
35
|
|
|
34
36
|
export type { QuickAddCollectionKind } from "./resolution";
|
|
35
37
|
|
|
@@ -101,6 +103,7 @@ export function QuickAddTickerInput({
|
|
|
101
103
|
width,
|
|
102
104
|
onAdded,
|
|
103
105
|
onFocusChange,
|
|
106
|
+
focusRequest = 0,
|
|
104
107
|
}: {
|
|
105
108
|
collectionId: string;
|
|
106
109
|
collectionKind: QuickAddCollectionKind;
|
|
@@ -109,6 +112,12 @@ export function QuickAddTickerInput({
|
|
|
109
112
|
width: number;
|
|
110
113
|
onAdded: (symbol: string) => void;
|
|
111
114
|
onFocusChange?: (focused: boolean) => void;
|
|
115
|
+
/**
|
|
116
|
+
* Bumped by a control outside the row, such as the empty table's
|
|
117
|
+
* "+ ticker" button, to open it. A click there focuses the pane in the same
|
|
118
|
+
* press, so the row opens once the pane is focused.
|
|
119
|
+
*/
|
|
120
|
+
focusRequest?: number;
|
|
112
121
|
}) {
|
|
113
122
|
const dispatch = useAppDispatch();
|
|
114
123
|
const { notify } = usePluginAppActions();
|
|
@@ -132,6 +141,13 @@ export function QuickAddTickerInput({
|
|
|
132
141
|
setInputFocused(false);
|
|
133
142
|
}, []);
|
|
134
143
|
|
|
144
|
+
const handledFocusRequestRef = useRef(focusRequest);
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (focusRequest === handledFocusRequestRef.current || !focused) return;
|
|
147
|
+
handledFocusRequestRef.current = focusRequest;
|
|
148
|
+
focusInput();
|
|
149
|
+
}, [focusInput, focusRequest, focused]);
|
|
150
|
+
|
|
135
151
|
const resetInput = useCallback(() => {
|
|
136
152
|
setInputValue("");
|
|
137
153
|
setValidation(IDLE_VALIDATION);
|
|
@@ -350,7 +366,7 @@ export function QuickAddTickerInput({
|
|
|
350
366
|
|
|
351
367
|
// The row shows only its placeholder, so the footer says which key reaches it.
|
|
352
368
|
usePaneFooter("portfolio-list:quick-add", () => ({
|
|
353
|
-
hints: inputFocused ? [] : [{ id: "add", key:
|
|
369
|
+
hints: inputFocused ? [] : [{ id: "add", key: QUICK_ADD_KEY, label: "dd", onPress: focusInput }],
|
|
354
370
|
}), [focusInput, inputFocused]);
|
|
355
371
|
|
|
356
372
|
return (
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
resolvePortfolioPositionPnl,
|
|
15
15
|
portfolioPnlPercent,
|
|
16
16
|
type PortfolioPositionPnl,
|
|
17
|
-
} from "
|
|
17
|
+
} from "../../../../portfolio/position-metrics";
|
|
18
18
|
|
|
19
19
|
/** A position lot valued from a current quote, in the totals currency. */
|
|
20
20
|
interface PricedPortfolioLot {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef } from "react";
|
|
2
|
+
import { QUICK_ADD_KEY } from "./quick-add";
|
|
2
3
|
import {
|
|
3
4
|
TickerListTableView,
|
|
4
5
|
type DataTableKeyEvent,
|
|
@@ -15,7 +16,7 @@ import type { TickerRecord } from "../../../types/ticker";
|
|
|
15
16
|
import { objectVersion } from "../../../utils/object-version";
|
|
16
17
|
import { columnContextVersion } from "./cell-version";
|
|
17
18
|
import { getColumnValue, type ColumnContext } from "./metrics";
|
|
18
|
-
import { portfolioPnlLabel } from "
|
|
19
|
+
import { portfolioPnlLabel } from "../../../portfolio/position-metrics";
|
|
19
20
|
import { PORTFOLIO_ROW_MENU_KEYS } from "./row-actions";
|
|
20
21
|
|
|
21
22
|
export type { QuoteFlashDirection };
|
|
@@ -98,6 +99,7 @@ export function PortfolioTickerTable({
|
|
|
98
99
|
visibleRangeBuffer,
|
|
99
100
|
resetScrollKey,
|
|
100
101
|
onRowActivate,
|
|
102
|
+
onAddTicker,
|
|
101
103
|
rootHeight,
|
|
102
104
|
}: {
|
|
103
105
|
columns: ColumnConfig[];
|
|
@@ -117,6 +119,8 @@ export function PortfolioTickerTable({
|
|
|
117
119
|
visibleRangeBuffer?: number;
|
|
118
120
|
resetScrollKey?: unknown;
|
|
119
121
|
onRowActivate?: (ticker: TickerRecord) => void;
|
|
122
|
+
/** Opens the add row; the empty table offers it as a button. */
|
|
123
|
+
onAddTicker?: () => void;
|
|
120
124
|
rootHeight?: number;
|
|
121
125
|
}) {
|
|
122
126
|
const cellCacheRef = useRef(createRowValueCache<string, ReturnType<typeof getColumnValue>>(5000));
|
|
@@ -175,6 +179,8 @@ export function PortfolioTickerTable({
|
|
|
175
179
|
resetScrollKey={resetScrollKey}
|
|
176
180
|
onRowActivate={onRowActivate}
|
|
177
181
|
rowMenuAccelerators={PORTFOLIO_ROW_MENU_KEYS}
|
|
182
|
+
onAddTicker={onAddTicker}
|
|
183
|
+
addTickerShortcut={onAddTicker ? QUICK_ADD_KEY : undefined}
|
|
178
184
|
rootHeight={rootHeight}
|
|
179
185
|
/>
|
|
180
186
|
);
|
|
@@ -2,6 +2,8 @@ import { apiClient } from "../../../api-client";
|
|
|
2
2
|
import type { PowerBoard, PowerDetail, PowerFilter, PowerHistory, PowerProject } from "../../../api-client/power";
|
|
3
3
|
import { createPluginCache } from "../../../data/plugin-cache";
|
|
4
4
|
import { loadCloudResource, unavailableOnServer } from "../shared/cloud-resource";
|
|
5
|
+
import { powerTickerScopes, type PowerTab, type PowerTickerScope } from "./model";
|
|
6
|
+
import { powerQuery } from "./query";
|
|
5
7
|
|
|
6
8
|
const cacheOptions = { source: "gloom-cloud", schemaVersion: 1, policy: { staleMs: 60 * 60_000, expireMs: 30 * 86_400_000 } };
|
|
7
9
|
export const powerBoardCache = createPluginCache<PowerBoard>({ ...cacheOptions, kind: "power-board" });
|
|
@@ -88,6 +90,20 @@ export async function fetchAllPowerHistory(filter: PowerFilter, client: Pick<Pow
|
|
|
88
90
|
}
|
|
89
91
|
return { ...first, points, hasMore: false, nextOffset: null };
|
|
90
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* How many records name a ticker on each other tab, for a tab that has none:
|
|
95
|
+
* one single-row page per scope, read for its total, which a free preview
|
|
96
|
+
* reports in full. A scope that fails to answer has no total rather than
|
|
97
|
+
* failing the tab it explains.
|
|
98
|
+
*/
|
|
99
|
+
export async function fetchPowerTickerScopes(symbol: string, tab: PowerTab, context: string,
|
|
100
|
+
client: Pick<PowerApi, "getCloudPowerBoard"> = apiClient, signal?: AbortSignal): Promise<PowerTickerScope[]> {
|
|
101
|
+
return Promise.all(powerTickerScopes(tab, context).map((scope) => {
|
|
102
|
+
const count = () => fetchPowerBoard({ ...powerQuery({ tab: scope.tab, context: scope.context }, symbol), limit: 1 }, client, signal).then((board) => board.total);
|
|
103
|
+
// One retry: a count is cheap, and the first of several at once is the one most often refused.
|
|
104
|
+
return count().catch(() => count()).then((total) => ({ ...scope, total }), () => ({ ...scope, total: null }));
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
91
107
|
const key = (query: unknown, scope: string) => `${scope}:${JSON.stringify(query)}`;
|
|
92
108
|
export const loadPowerBoard = (filter: PowerFilter, scope: string, force = false, signal?: AbortSignal) =>
|
|
93
109
|
loadCloudResource(powerBoardCache, key(filter, scope), () => fetchPowerBoard(filter, apiClient, signal), { force, validate: validatePowerBoard });
|