gloomberb 0.18.3 → 0.18.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/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -40,15 +40,16 @@ function noMoveNotice(symbols: readonly string[], names: number): string {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* When the board's figures are from, and whose sessions they follow:
|
|
43
|
+
* When the board's figures are from, and whose sessions they follow: when its
|
|
44
|
+
* prices printed, from a server that says (`pricesAsOf`). Otherwise, outside
|
|
44
45
|
* the regular session the tiles are the completed session's, so the board is
|
|
45
46
|
* as of that session's close (its date, from a server that does not send the
|
|
46
|
-
* close)
|
|
47
|
-
* snapshot time.
|
|
47
|
+
* close); while it trades, the snapshot time, which is later than its prices.
|
|
48
48
|
*/
|
|
49
|
-
function boardObservation(board: Pick<MarketHeatmapBoard, "fetchedAt" | "regularSessionDate" | "regularSessionClosedAt">) {
|
|
49
|
+
function boardObservation(board: Pick<MarketHeatmapBoard, "fetchedAt" | "regularSessionDate" | "regularSessionClosedAt" | "pricesAsOf">) {
|
|
50
50
|
const closedAt = board.regularSessionDate ? board.regularSessionClosedAt : null;
|
|
51
|
-
const
|
|
51
|
+
const pricedAt = typeof board.pricesAsOf === "number" && board.pricesAsOf > 0 ? board.pricesAsOf : closedAt;
|
|
52
|
+
const asOf = typeof pricedAt === "number" && pricedAt > 0 ? new Date(pricedAt).toISOString()
|
|
52
53
|
: board.regularSessionDate || new Date(board.fetchedAt).toISOString();
|
|
53
54
|
return { asOf, sessionExchange: "NYSE" };
|
|
54
55
|
}
|
|
@@ -101,7 +102,7 @@ export const marketHeatmapHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
|
101
102
|
aliases: ["HM", "heatmap"],
|
|
102
103
|
dataRequirements: ["Gloom Cloud market heatmap snapshot"],
|
|
103
104
|
limitations: [
|
|
104
|
-
"The snapshot the pane starts from,
|
|
105
|
+
"The snapshot the pane starts from: real-time with Pro, fifteen minutes behind otherwise; the pane's live-streamed colors are not in the report.",
|
|
105
106
|
"Sizes, shares and the weighted move use market cap (net assets for ETFs), not the pane's tile area, which follows its Size by setting (the day's move by default).",
|
|
106
107
|
],
|
|
107
108
|
},
|
|
@@ -129,6 +130,8 @@ export const marketHeatmapHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
|
129
130
|
columns: columns(universe, groupBy, flat),
|
|
130
131
|
rows: groups.map((summary) => projectRow(summary, groupBy, flat)),
|
|
131
132
|
complete: !result.stale && covered,
|
|
133
|
+
// A Pro account's board is priced from a live read.
|
|
134
|
+
freshness: { status: result.access === "realtime" ? "live" : "delayed", tradingDayMarket: "US" },
|
|
132
135
|
unavailableSymbols: covered ? [] : noMove,
|
|
133
136
|
metadata: {
|
|
134
137
|
universe,
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
MARKET_HEATMAP_REQUEST_COUNT,
|
|
49
49
|
MARKET_HEATMAP_UNIVERSES,
|
|
50
50
|
fetchMarketHeatmap,
|
|
51
|
+
heatmapCheckIntervalMs,
|
|
51
52
|
resetMarketHeatmapCache,
|
|
52
53
|
type MarketHeatmapBoard,
|
|
53
54
|
type MarketHeatmapUniverseId,
|
|
@@ -102,7 +103,6 @@ import {
|
|
|
102
103
|
|
|
103
104
|
const NO_ASSETS: HeatmapBoardAsset[] = [];
|
|
104
105
|
const NO_TARGETS: QuoteSubscriptionTarget[] = [];
|
|
105
|
-
const SNAPSHOT_REFRESH_MS = 60_000;
|
|
106
106
|
const LAYOUT_THROTTLE_MS = 5_000;
|
|
107
107
|
/** A size change below this share of a tile's area is not worth moving it. */
|
|
108
108
|
const LAYOUT_TOLERANCE = 0.005;
|
|
@@ -631,8 +631,8 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
631
631
|
// Ages the last check that succeeded, not the snapshot, which the server can
|
|
632
632
|
// hand back unchanged long after it was put together.
|
|
633
633
|
const checked = useUpdatedAgo(shownBoard?.checkedAt ?? null);
|
|
634
|
-
// The snapshot carries sizes and every name the stream does not
|
|
635
|
-
useAutoRefresh(board?.checkedAt ?? null, autoRefresh, { intervalMs:
|
|
634
|
+
// The snapshot carries sizes and every name the stream does not: a minute on the server, a quarter of one real-time.
|
|
635
|
+
useAutoRefresh(board?.checkedAt ?? null, autoRefresh, { intervalMs: heatmapCheckIntervalMs(board) });
|
|
636
636
|
|
|
637
637
|
usePaneStatusFooter({ registrationId: "market-heatmap-retained", stale: hasBoard && stale && !portfolioTab });
|
|
638
638
|
usePaneNoticeFooter({
|
|
@@ -85,16 +85,18 @@ const isTimestamp = (value: number | null | undefined): value is number =>
|
|
|
85
85
|
* the largest names it holds, the completed regular session it shows outside
|
|
86
86
|
* that session, the time its figures are as of, in New York time, dated when
|
|
87
87
|
* that day is not the session's (or, while the session trades, today's), and
|
|
88
|
-
* when this client last checked, which is a separate figure. A board of
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
88
|
+
* when this client last checked, which is a separate figure. A board is as of
|
|
89
|
+
* when its prices printed (`pricesAsOf`), a board of a completed session from
|
|
90
|
+
* a server that gives only its close as of that close
|
|
91
|
+
* (`regularSessionClosedAt`); otherwise the time is when the server put the
|
|
92
|
+
* snapshot together, at least fifteen minutes after its prices, and says so.
|
|
93
|
+
* A footer narrower than `maxWidth` loses the check
|
|
92
94
|
* first, then that time, then the session; after a failed refresh (`failed`)
|
|
93
95
|
* the age of the last good check outlasts the time. Null when not even the
|
|
94
96
|
* count fits.
|
|
95
97
|
*/
|
|
96
98
|
export function heatmapBoardCaption(
|
|
97
|
-
board: { topCount: number; fetchedAt: number; regularSessionDate?: string | null; regularSessionClosedAt?: number | null },
|
|
99
|
+
board: { topCount: number; fetchedAt: number; regularSessionDate?: string | null; regularSessionClosedAt?: number | null; pricesAsOf?: number | null },
|
|
98
100
|
{ now, checked = null, failed = false, maxWidth = Number.POSITIVE_INFINITY }:
|
|
99
101
|
{ now: number; checked?: string | null; failed?: boolean; maxWidth?: number },
|
|
100
102
|
): string | null {
|
|
@@ -103,12 +105,13 @@ export function heatmapBoardCaption(
|
|
|
103
105
|
const parts: Array<{ text: string; rank: number }> = [{ text: `top ${board.topCount}`, rank: 0 }];
|
|
104
106
|
if (sessionDate) parts.push({ text: `${dayLabel(sessionDate)} session`, rank: 1 });
|
|
105
107
|
const closedAt = sessionDate && isTimestamp(board.regularSessionClosedAt) ? board.regularSessionClosedAt : null;
|
|
106
|
-
const
|
|
108
|
+
const pricedAt = isTimestamp(board.pricesAsOf) ? board.pricesAsOf : closedAt;
|
|
109
|
+
const time = pricedAt ?? (isTimestamp(board.fetchedAt) ? board.fetchedAt : null);
|
|
107
110
|
if (time != null) {
|
|
108
111
|
const { hour, minute } = zonedDateTimeParts(time, NEW_YORK);
|
|
109
112
|
const clock = `${twoDigits(hour)}:${twoDigits(minute)} ET`;
|
|
110
113
|
const day = zonedDateKey(time, NEW_YORK);
|
|
111
|
-
const text = `${
|
|
114
|
+
const text = `${pricedAt != null ? "as of" : "snapshot"} ${day === (sessionDate ?? zonedDateKey(now, NEW_YORK)) ? clock : `${dayLabel(day)} ${clock}`}`;
|
|
112
115
|
parts.push({ text, rank: failed ? 3 : 2 });
|
|
113
116
|
}
|
|
114
117
|
if (checked) parts.push({ text: `checked ${checked}`, rank: failed ? 2 : 3 });
|
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
} from "./model";
|
|
19
19
|
import {
|
|
20
20
|
fetchPreferredMarketMovers,
|
|
21
|
-
|
|
21
|
+
fetchTrendingResult,
|
|
22
|
+
type CachedResult,
|
|
22
23
|
type MarketMoversResult,
|
|
23
24
|
type PreferredMoversOptions,
|
|
24
25
|
type TrendingSymbol,
|
|
@@ -30,6 +31,8 @@ export interface MarketMoverTabResult extends MarketMoversResult {
|
|
|
30
31
|
quotes: MoverQuote[];
|
|
31
32
|
/** What the list is ranked by; absent for trending, which keeps its source's order. */
|
|
32
33
|
rankedBy?: MoverRanking;
|
|
34
|
+
/** Requested trending names whose quotes did not load. */
|
|
35
|
+
unavailableSymbols?: string[];
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
/** Rows a list shows. */
|
|
@@ -46,29 +49,31 @@ export interface MarketMoverTabDependencies {
|
|
|
46
49
|
count: number,
|
|
47
50
|
options?: PreferredMoversOptions,
|
|
48
51
|
): Promise<MarketMoversResult>;
|
|
49
|
-
fetchTrending(count: number, options?: { forceRefresh?: boolean }): Promise<TrendingSymbol[]
|
|
52
|
+
fetchTrending(count: number, options?: { forceRefresh?: boolean }): Promise<CachedResult<TrendingSymbol[]>>;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
const defaultDependencies: MarketMoverTabDependencies = {
|
|
53
56
|
fetchPreferred: (category, count, options) => fetchPreferredMarketMovers(category, count, options),
|
|
54
|
-
fetchTrending: (count, options) =>
|
|
57
|
+
fetchTrending: (count, options) => fetchTrendingResult(count, undefined, options),
|
|
55
58
|
};
|
|
56
59
|
|
|
57
60
|
async function hydrateTrending(
|
|
58
61
|
trending: readonly TrendingSymbol[],
|
|
59
62
|
provider: DataProvider | null,
|
|
60
|
-
): Promise<
|
|
61
|
-
const symbols = trending.slice(0,
|
|
63
|
+
): Promise<Pick<MarketMoverTabResult, "quotes" | "unavailableSymbols">> {
|
|
64
|
+
const symbols = trending.slice(0, LIST_ROWS).map(({ symbol }) => symbol);
|
|
62
65
|
const bySymbol = new Map<string, MoverQuote>();
|
|
63
|
-
if (
|
|
64
|
-
if (provider
|
|
65
|
-
|
|
66
|
-
symbols.map((symbol) => ({ symbol, exchange: "" }))
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
if (symbols.length === 0) return { quotes: [] };
|
|
67
|
+
if (provider?.getQuotesBatch) {
|
|
68
|
+
try {
|
|
69
|
+
const results = await provider.getQuotesBatch(symbols.map((symbol) => ({ symbol, exchange: "" })));
|
|
70
|
+
for (const result of results) {
|
|
71
|
+
if (result.quote) bySymbol.set(result.target.symbol, screenerQuoteFromQuote(result.target.symbol, result.quote));
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
logFailure("market-movers", "Trending quote batch failed")(error);
|
|
70
75
|
}
|
|
71
|
-
} else {
|
|
76
|
+
} else if (provider) {
|
|
72
77
|
await Promise.all(symbols.map(async (symbol) => {
|
|
73
78
|
try {
|
|
74
79
|
const quote = await provider.getQuote(symbol, "");
|
|
@@ -78,10 +83,18 @@ async function hydrateTrending(
|
|
|
78
83
|
}
|
|
79
84
|
}));
|
|
80
85
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
const unavailableSymbols = [...new Set(symbols.filter((symbol) => !bySymbol.has(symbol)))];
|
|
87
|
+
return {
|
|
88
|
+
quotes: symbols.flatMap((symbol) => {
|
|
89
|
+
const quote = bySymbol.get(symbol);
|
|
90
|
+
return quote ? [quote] : [];
|
|
91
|
+
}),
|
|
92
|
+
...(unavailableSymbols.length ? { unavailableSymbols } : {}),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function marketMoverQuoteError(result: Pick<MarketMoverTabResult, "unavailableSymbols">): string | null {
|
|
97
|
+
return result.unavailableSymbols?.length ? `Quotes unavailable: ${result.unavailableSymbols.join(", ")}.` : null;
|
|
85
98
|
}
|
|
86
99
|
|
|
87
100
|
export async function loadMarketMoverTab(
|
|
@@ -93,11 +106,12 @@ export async function loadMarketMoverTab(
|
|
|
93
106
|
const { basis, ...fetchOptions } = options ?? {};
|
|
94
107
|
if (tab === "trending") {
|
|
95
108
|
const trending = await dependencies.fetchTrending(LIST_ROWS, fetchOptions);
|
|
109
|
+
const hydrated = await hydrateTrending(trending.data, provider);
|
|
96
110
|
return {
|
|
97
111
|
tab,
|
|
98
|
-
|
|
112
|
+
...hydrated,
|
|
99
113
|
source: "gloom",
|
|
100
|
-
stale:
|
|
114
|
+
stale: trending.stale || !!hydrated.unavailableSymbols?.length,
|
|
101
115
|
};
|
|
102
116
|
}
|
|
103
117
|
const category = CATEGORY_MAP[tab];
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
CloudSessionMoversPayload,
|
|
10
10
|
CloudSessionMoversSide,
|
|
11
11
|
} from "../../../api-client/market-movers";
|
|
12
|
-
import { loadMarketMoverTab, loadSessionMovers, type MarketMoverTabResult } from "./client";
|
|
12
|
+
import { loadMarketMoverTab, loadSessionMovers, marketMoverQuoteError, type MarketMoverTabResult } from "./client";
|
|
13
13
|
import { createRows, fiftyTwoWeekPositionPercent, formatMoverPrice, MOVER_RANKING_LABELS, moverExtendedSessions, moverReferencePrice, type MarketMoverRow, type ScreenerTabId, type TabId } from "./model";
|
|
14
14
|
import { EXTENDED_SESSION_LABELS, type ExtendedSession } from "../../../market-data/market/status";
|
|
15
15
|
import type { HeadlessPaneColumn } from "../../../types/headless";
|
|
@@ -98,7 +98,7 @@ export function createMarketMoversHeadless(
|
|
|
98
98
|
): HeadlessPaneDefinition<"rows"> {
|
|
99
99
|
return {
|
|
100
100
|
shape: "rows",
|
|
101
|
-
//
|
|
101
|
+
// The delayed lists unless the list says it is real-time; rows keep the time of their own last price.
|
|
102
102
|
freshness: { status: "delayed" },
|
|
103
103
|
argument: { kind: "none" },
|
|
104
104
|
options: [{
|
|
@@ -145,6 +145,8 @@ export function createMarketMoversHeadless(
|
|
|
145
145
|
events: item.catalysts.map((catalyst) => CATALYST_LABEL[catalyst] ?? catalyst).join(" "),
|
|
146
146
|
})),
|
|
147
147
|
metadata: { list: tab, side, session: payload.session, phase: payload.phase, asOf: payload.asOf, stale: payload.stale === true },
|
|
148
|
+
// A Pro account's list is the live board; the free one says it is delayed.
|
|
149
|
+
...(payload.access === "delayed" ? {} : { freshness: { status: "live" as const } }),
|
|
148
150
|
};
|
|
149
151
|
}
|
|
150
152
|
const result = await dependencies.load(args, tab, ctx.marketData);
|
|
@@ -165,15 +167,19 @@ export function createMarketMoversHeadless(
|
|
|
165
167
|
}));
|
|
166
168
|
// Beside an extended column, say which move the order follows.
|
|
167
169
|
const rankedBy = result.rankedBy ?? null;
|
|
170
|
+
const quoteError = marketMoverQuoteError(result);
|
|
168
171
|
return {
|
|
169
172
|
...(extendedSessions.length > 0
|
|
170
173
|
? { columns: [...COLUMNS.slice(0, 5), ...extendedSessions.map(extendedColumn), ...COLUMNS.slice(5)] }
|
|
171
174
|
: {}),
|
|
172
175
|
rows,
|
|
176
|
+
...(quoteError ? { complete: false, unavailableSymbols: result.unavailableSymbols, errors: [quoteError] } : {}),
|
|
173
177
|
...(rankedBy && rankedBy !== "volume" && extendedSessions.length > 0
|
|
174
178
|
? { notes: [`Ranked by ${MOVER_RANKING_LABELS[rankedBy]}.`] }
|
|
175
179
|
: {}),
|
|
176
180
|
metadata: { list: tab, source: result.source, stale: result.stale, rankedBy },
|
|
181
|
+
// A Pro account's Gainers, Losers and Most Active are the real-time lists.
|
|
182
|
+
...(result.source === "cloud" ? { freshness: { status: "live" as const } } : {}),
|
|
177
183
|
};
|
|
178
184
|
},
|
|
179
185
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box } from "../../../ui";
|
|
1
|
+
import { Box, useUiCapabilities } from "../../../ui";
|
|
2
2
|
import { nextHeaderSort } from "../../../utils/sort-values";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { DataTableView, EmptyState, usePaneFooter, usePaneTabs, type DataTableKeyEvent } from "../../../components";
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
type ScreenerTabId,
|
|
38
38
|
type TabId,
|
|
39
39
|
} from "./model";
|
|
40
|
-
import { loadMarketMoverTab } from "./client";
|
|
40
|
+
import { loadMarketMoverTab, marketMoverQuoteError } from "./client";
|
|
41
41
|
import { summaryFooterSegments } from "./footer";
|
|
42
42
|
import { isSessionTab, resolveActiveTab, usSessionAt, type UsSession } from "./session";
|
|
43
43
|
import { SessionMoversBody } from "./session-body";
|
|
@@ -161,7 +161,7 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
|
|
|
161
161
|
const [selectedSymbol, setSelectedSymbol] = useState<string | null>(null);
|
|
162
162
|
const [sortPreference, setSortPreference] = useState<MarketMoverSortPreference>(DEFAULT_SORT_PREFERENCE);
|
|
163
163
|
const [moversStale, setMoversStale] = useState(false);
|
|
164
|
-
const [
|
|
164
|
+
const [lastSuccess, setLastSuccess] = useState<{ tab: ScreenerTabId; at: number } | null>(null);
|
|
165
165
|
|
|
166
166
|
const fetchGenRef = useRef(0);
|
|
167
167
|
|
|
@@ -226,12 +226,16 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
|
|
|
226
226
|
});
|
|
227
227
|
if (fetchGenRef.current !== gen) return;
|
|
228
228
|
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
const quoteError = marketMoverQuoteError(result);
|
|
230
|
+
// A partial list shows only its current rows; a total failure keeps this list's prior rows.
|
|
231
|
+
if (!quoteError || result.quotes.length > 0) {
|
|
232
|
+
setQuotes(result.quotes);
|
|
233
|
+
setLoadedTab(tab);
|
|
234
|
+
if (!options?.background) setSelectedSymbol(null);
|
|
235
|
+
}
|
|
231
236
|
setMoversStale(result.stale);
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
setLastLoadedAt(Date.now());
|
|
237
|
+
setLoadError(quoteError);
|
|
238
|
+
if (!quoteError && !result.stale) setLastSuccess({ tab, at: Date.now() });
|
|
235
239
|
} catch {
|
|
236
240
|
if (fetchGenRef.current !== gen) return;
|
|
237
241
|
setMoversStale(true);
|
|
@@ -250,7 +254,7 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
|
|
|
250
254
|
const backgroundRefresh = useCallback(() => {
|
|
251
255
|
void loadTab(activeTab, { background: true });
|
|
252
256
|
}, [activeTab, loadTab]);
|
|
253
|
-
useAutoRefresh(
|
|
257
|
+
useAutoRefresh(lastSuccess?.tab === activeTab ? lastSuccess.at : null, backgroundRefresh);
|
|
254
258
|
|
|
255
259
|
const openSymbol = useCallback((row: MarketMoverRow) => {
|
|
256
260
|
pinTicker(moverKey(row), { floating: true, paneType: TICKER_RESEARCH_PANE_ID, instrument: null });
|
|
@@ -262,6 +266,8 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
|
|
|
262
266
|
}));
|
|
263
267
|
}, []);
|
|
264
268
|
|
|
269
|
+
const logos = useUiCapabilities().nativePaneChrome === true;
|
|
270
|
+
const renderCell = useCallback((row: MarketMoverRow, column: MarketMoverColumn) => renderMarketMoverCell(row, column, logos), [logos]);
|
|
265
271
|
const handleTableKeyDown = useCallback((event: DataTableKeyEvent) => (
|
|
266
272
|
handleRefreshKey(event, () => loadTab(activeTab, { forceRefresh: true }), { stopPropagation: true })
|
|
267
273
|
), [activeTab, loadTab]);
|
|
@@ -301,7 +307,7 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
|
|
|
301
307
|
onHeaderClick={handleHeaderClick}
|
|
302
308
|
getItemKey={moverKey}
|
|
303
309
|
onActivate={openSymbol}
|
|
304
|
-
renderCell={
|
|
310
|
+
renderCell={renderCell}
|
|
305
311
|
selectedTextOverridesCellColor
|
|
306
312
|
emptyStateTitle={loading ? "Loading movers..." : loadError ?? "No movers returned."}
|
|
307
313
|
emptyContent={loadError ? (
|
|
@@ -146,7 +146,7 @@ export interface MarketMoversResult {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
export interface PreferredMarketMoverSources {
|
|
149
|
-
isCloudEligible(): boolean
|
|
149
|
+
isCloudEligible(): boolean | Promise<boolean>;
|
|
150
150
|
fetchCloud(
|
|
151
151
|
category: CloudMarketScreenerCategory,
|
|
152
152
|
count: number,
|
|
@@ -275,9 +275,19 @@ function cloudScreenerCategory(category: ScreenerCategory): CloudMarketScreenerC
|
|
|
275
275
|
return "most-active";
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Whether the signed-in account reads the real-time lists. A session restored
|
|
280
|
+
* without its account, as the CLI starts from the saved one, is asked for it
|
|
281
|
+
* first, so a Pro account is never handed the delayed lists.
|
|
282
|
+
*/
|
|
283
|
+
export function isCloudScreenerEligible(): boolean | Promise<boolean> {
|
|
279
284
|
const user = apiClient.getCurrentUser();
|
|
280
|
-
return apiClient.isVerified() && hasProAccess(user);
|
|
285
|
+
if (user || !apiClient.isSignedIn()) return apiClient.isVerified() && hasProAccess(user);
|
|
286
|
+
return apiClient.ensureVerifiedSession().then((verified) => !!verified && hasProAccess(verified), (error: unknown) => {
|
|
287
|
+
// The delayed lists still load; the failed account check is logged, not shown.
|
|
288
|
+
logFailure("market-movers", "Account check for the real-time lists failed")(error);
|
|
289
|
+
return false;
|
|
290
|
+
});
|
|
281
291
|
}
|
|
282
292
|
|
|
283
293
|
const defaultPreferredMarketMoverSources: PreferredMarketMoverSources = {
|
|
@@ -361,7 +371,9 @@ export async function fetchPreferredMarketMovers(
|
|
|
361
371
|
sources: PreferredMarketMoverSources = defaultPreferredMarketMoverSources,
|
|
362
372
|
): Promise<MarketMoversResult> {
|
|
363
373
|
const { metadataWaitMs = MARKET_METADATA_WAIT_MS, ...options } = preferredOptions ?? {};
|
|
364
|
-
|
|
374
|
+
// Answered at once unless the account has to be asked for, so a loaded account's list starts as soon as before.
|
|
375
|
+
const eligibility = sources.isCloudEligible();
|
|
376
|
+
if (!(typeof eligibility === "boolean" ? eligibility : await eligibility)) {
|
|
365
377
|
const result = await sources.fetchMarket(category, count, options);
|
|
366
378
|
return { quotes: rankScreenerQuotes(category, result.data), source: "gloom", stale: result.stale };
|
|
367
379
|
}
|
|
@@ -410,19 +422,28 @@ export function parseTrendingResponse(data: unknown): TrendingSymbol[] {
|
|
|
410
422
|
return data.flatMap(q => q && typeof q.symbol === "string" && q.symbol.trim() ? [{ symbol: q.symbol.trim() }] : []);
|
|
411
423
|
}
|
|
412
424
|
|
|
413
|
-
export async function
|
|
425
|
+
export async function fetchTrendingResult(
|
|
414
426
|
count = 25,
|
|
415
427
|
api: MarketScreenerApi = screenerApi,
|
|
416
428
|
options?: FetchCacheOptions,
|
|
417
|
-
): Promise<TrendingSymbol[]
|
|
429
|
+
): Promise<CachedResult<TrendingSymbol[]>> {
|
|
418
430
|
const load = async () => {
|
|
419
431
|
const response = await (api.getMarketTrending ?? apiClient.getMarketTrending)(count);
|
|
420
432
|
if (response.status === "empty") return { data: [], stale: response.stale === true };
|
|
421
433
|
if (!response.data) throw new Error("Market trends unavailable");
|
|
422
434
|
return { data: parseTrendingResponse(response.data), stale: response.stale === true };
|
|
423
435
|
};
|
|
424
|
-
if (!shouldUseCache(api, options)) return
|
|
425
|
-
return
|
|
436
|
+
if (!shouldUseCache(api, options)) return load();
|
|
437
|
+
return loadCached(`trending:US:count=${count}`, load, options);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** Array-only reader retained for the overview command. */
|
|
441
|
+
export async function fetchTrending(
|
|
442
|
+
count = 25,
|
|
443
|
+
api: MarketScreenerApi = screenerApi,
|
|
444
|
+
options?: FetchCacheOptions,
|
|
445
|
+
): Promise<TrendingSymbol[]> {
|
|
446
|
+
return (await fetchTrendingResult(count, api, options)).data;
|
|
426
447
|
}
|
|
427
448
|
|
|
428
449
|
export const MARKET_SUMMARY_SYMBOLS = ["^GSPC", "^DJI", "^IXIC", "^RUT"] as const;
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import { useAutoRefresh } from "../../../react/auto-refresh";
|
|
15
15
|
import { useLiveQuoteEntries } from "../../../state/hooks/quote-streaming";
|
|
16
16
|
import { TICKER_RESEARCH_PANE_ID } from "../../../types/config";
|
|
17
|
-
import { Box } from "../../../ui";
|
|
17
|
+
import { Box, useUiCapabilities } from "../../../ui";
|
|
18
18
|
import { publicTickerKey } from "../../../utils/exchanges";
|
|
19
19
|
import { nextHeaderSort } from "../../../utils/sort-values";
|
|
20
20
|
import { usePluginPaneState, usePluginTickerActions } from "../../runtime";
|
|
@@ -208,6 +208,8 @@ function SessionMoversTable({ view, session, focused, width, summaryQuotes, live
|
|
|
208
208
|
const handleHeaderClick = useCallback((columnId: string) => {
|
|
209
209
|
setSortPreference(nextHeaderSort(sort, columnId as SessionMoverColumn["id"], { resetTo: DEFAULT_SORT }));
|
|
210
210
|
}, [sort]);
|
|
211
|
+
const logos = useUiCapabilities().nativePaneChrome === true;
|
|
212
|
+
const renderCell = useCallback((row: SessionMoverRow, column: SessionMoverColumn) => renderSessionMoverCell(row, column, logos), [logos]);
|
|
211
213
|
const handleKeyDown = useCallback((event: DataTableKeyEvent) => (
|
|
212
214
|
handleRefreshKey(event, () => load({ forceRefresh: true }), { stopPropagation: true })
|
|
213
215
|
), [load]);
|
|
@@ -243,7 +245,7 @@ function SessionMoversTable({ view, session, focused, width, summaryQuotes, live
|
|
|
243
245
|
onHeaderClick={handleHeaderClick}
|
|
244
246
|
getItemKey={rowKey}
|
|
245
247
|
onActivate={openRow}
|
|
246
|
-
renderCell={
|
|
248
|
+
renderCell={renderCell}
|
|
247
249
|
selectedTextOverridesCellColor
|
|
248
250
|
emptyStateTitle={emptyTitle}
|
|
249
251
|
emptyContent={loadError && !payload ? (
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CloudSessionMoversCategory } from "../../../api-client/market-movers";
|
|
2
2
|
import type { DataTableCell, DataTableColumn } from "../../../components";
|
|
3
|
+
import { withCompanyLogo } from "../../../components/company-logo";
|
|
3
4
|
import { getTableWidth } from "../../../components/ui/table-layout";
|
|
4
5
|
import { colors, priceColor } from "../../../theme/colors";
|
|
5
6
|
import { TextAttributes } from "../../../ui";
|
|
@@ -60,14 +61,15 @@ function signedPercent(value: number | null): DataTableCell {
|
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
/** `logos`: the desktop and the web lead each name with the company's logo; the terminal draws none. */
|
|
65
|
+
export function renderSessionMoverCell(row: SessionMoverRow, column: SessionMoverColumn, logos = false): DataTableCell {
|
|
64
66
|
switch (column.id) {
|
|
65
67
|
case "rank":
|
|
66
68
|
return { text: String(row.rank), color: colors.textDim };
|
|
67
69
|
case "symbol":
|
|
68
70
|
return { text: row.symbol, color: colors.textBright, attributes: TextAttributes.BOLD };
|
|
69
71
|
case "name":
|
|
70
|
-
return { text: row.name };
|
|
72
|
+
return withCompanyLogo({ text: row.name }, row, logos);
|
|
71
73
|
case "price":
|
|
72
74
|
return { text: formatMoverPrice(row.price, row.currency, moverReferencePrice({ ...row, previousClose: row.referenceClose })), value: row.price };
|
|
73
75
|
case "gapPercent":
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DataTableCell } from "../../../components";
|
|
2
|
+
import { withCompanyLogo } from "../../../components/company-logo";
|
|
2
3
|
import { getTableWidth } from "../../../components/ui/table-layout";
|
|
3
4
|
import { TextAttributes } from "../../../ui";
|
|
4
5
|
import { colors, priceColor } from "../../../theme/colors";
|
|
@@ -65,9 +66,11 @@ export function buildMarketMoverColumns(width: number, extendedSessions: readonl
|
|
|
65
66
|
return [...lead, { id: "name", label: "NAME", width: Math.max(6, nameRoom()), align: "left" }, ...quote, ...trailing];
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
/** `logos`: the desktop and the web lead each name with the company's logo; the terminal draws none. */
|
|
68
70
|
export function renderMarketMoverCell(
|
|
69
71
|
row: MarketMoverRow,
|
|
70
72
|
column: MarketMoverColumn,
|
|
73
|
+
logos = false,
|
|
71
74
|
): DataTableCell {
|
|
72
75
|
switch (column.id) {
|
|
73
76
|
case "rank":
|
|
@@ -79,7 +82,7 @@ export function renderMarketMoverCell(
|
|
|
79
82
|
attributes: TextAttributes.BOLD,
|
|
80
83
|
};
|
|
81
84
|
case "name":
|
|
82
|
-
return { text: row.name };
|
|
85
|
+
return withCompanyLogo({ text: row.name }, row, logos);
|
|
83
86
|
case "price":
|
|
84
87
|
return { text: formatMoverPrice(row.price, row.currency, moverReferencePrice(row)) };
|
|
85
88
|
case "changePercent":
|
|
@@ -74,7 +74,9 @@ function projectValuationHeadlessBundle(
|
|
|
74
74
|
richPercentile: view.richPercentile,
|
|
75
75
|
richSigma: view.richSigma,
|
|
76
76
|
historyStart: view.historyStart,
|
|
77
|
+
// The first day of the period the reading covers; the report names the period, not that day.
|
|
77
78
|
asOf: view.asOf,
|
|
79
|
+
...(view.periodicity ? { periodicity: view.periodicity } : {}),
|
|
78
80
|
stale: view.observationStale,
|
|
79
81
|
}));
|
|
80
82
|
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
type ZoneHit,
|
|
10
10
|
} from "./defs";
|
|
11
11
|
import { historySpan, type HistorySpan } from "../shared/history-span";
|
|
12
|
+
import { periodsPerYear } from "../shared/stat-transform";
|
|
13
|
+
import { periodStartPeriodicity } from "../../../utils/release-date";
|
|
12
14
|
import { fitTrend, sigmaVsTrend, trendAt, type TrendFit } from "../shared/trend";
|
|
13
15
|
|
|
14
16
|
const MS_PER_DAY = 86_400_000;
|
|
@@ -64,6 +66,8 @@ export interface IndicatorViewModel {
|
|
|
64
66
|
*/
|
|
65
67
|
historyStart: string | null;
|
|
66
68
|
asOf: string;
|
|
69
|
+
/** How often the indicator is read when `asOf` is the first day of its period (Shiller's monthly CAPE); null otherwise. */
|
|
70
|
+
periodicity: "monthly" | "quarterly" | "annual" | null;
|
|
67
71
|
observationStale: boolean;
|
|
68
72
|
}
|
|
69
73
|
|
|
@@ -137,6 +141,7 @@ export function projectView(
|
|
|
137
141
|
span: points[0] ? historySpan(points[0].date, visible.filter(isUsableRatio), RANGE_WINDOWS_MS[range]) : null,
|
|
138
142
|
historyStart: points[0]?.date ?? null,
|
|
139
143
|
asOf: current.date,
|
|
144
|
+
periodicity: periodStartPeriodicity(current.date, periodsPerYear(history.slice(-24).map((point) => ({ date: point.date, value: point.ratio })))),
|
|
140
145
|
observationStale: build.sourceStale === true || nowMs - parseDateMs(current.date) > indicator.staleAfterMs,
|
|
141
146
|
};
|
|
142
147
|
}
|
|
@@ -11,7 +11,7 @@ const columns: HeadlessPaneColumn[] = [
|
|
|
11
11
|
export const membersHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
12
12
|
shape: "rows", argument: { kind: "ticker", optional: true, placeholder: "fund", description: "Covered fund or index alias; omit for the fund list." },
|
|
13
13
|
options: [{ key: "tab", type: "enum", values: [{ value: "members" }, { value: "movers" }, { value: "changes" }], defaultValue: "members", description: "Members, movers or changes." }],
|
|
14
|
-
discovery: { aliases: ["MEMB", "MRR", "IMOV"], limitations: ["ETF holdings, with file dates.", "
|
|
14
|
+
discovery: { aliases: ["MEMB", "MRR", "IMOV"], limitations: ["ETF holdings, with file dates.", "Member prices are real-time with Pro and fifteen minutes delayed otherwise; partial 1D coverage.", "Nasdaq-100 is not covered."] },
|
|
15
15
|
describe: (args) => args.rawArgument ? `MEMB ${args.rawArgument}` : "Index and ETF members",
|
|
16
16
|
async load(args, context) {
|
|
17
17
|
const input = args.symbols[0] ?? args.rawArgument ?? "";
|
|
@@ -25,15 +25,16 @@ export const membersHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
|
25
25
|
const data = await fetchMembers(fund, context.apiClient);
|
|
26
26
|
const movers = args.options.tab === "movers";
|
|
27
27
|
const rows = memberRows(data.members, movers ? "movers" : "members", "", DEFAULT_SORT).flatMap((row) => row.kind === "item" ? [{ ...row.item }] : []);
|
|
28
|
-
// Member prices are the pane's
|
|
29
|
-
// whether it is stale; the members' own flags are not what the pane reads.
|
|
30
|
-
|
|
28
|
+
// Member prices are the pane's quotes: real-time for a Pro account, 15 minutes delayed otherwise. As in the
|
|
29
|
+
// pane, the fund's snapshot says whether it is stale; the members' own flags are not what the pane reads.
|
|
30
|
+
const live = data.access === "realtime";
|
|
31
|
+
return { freshness: { status: data.stale ? "stale" : live ? "live" : "delayed", delayMinutes: 15, ignoreStaleFlags: true }, rows, columns: movers ? [...columns.slice(0, 3), { key: "contribution", header: "Contrib. pp", align: "right", format: (value) => percent(value as number | null, "", 3) }] : columns,
|
|
31
32
|
complete: !data.stale && data.aggregate.fresh1D === data.aggregate.total,
|
|
32
33
|
unavailableSymbols: data.members.flatMap((row) => row.symbol && row.changePercent === null ? [row.symbol] : []),
|
|
33
34
|
metadata: { fund: data.fund, asOf: data.asOf, snapshotAsOf: data.snapshotAsOf, aggregate: data.aggregate, stale: data.stale, notices: [
|
|
34
35
|
holdingsSourceText(input, data),
|
|
35
36
|
// The pane's coverage figure, and once what the table's dashes mean instead of leaving them bare.
|
|
36
|
-
[coverageText(data.aggregate), data.aggregate.fresh1D < data.aggregate.total ?
|
|
37
|
+
[coverageText(data.aggregate), data.aggregate.fresh1D < data.aggregate.total ? `1D -- means no fresh ${live ? "" : "delayed "}quote; those holdings are not counted` : ""].filter(Boolean).join(" | "),
|
|
37
38
|
...holdingsCaveats(data, movers),
|
|
38
39
|
] } };
|
|
39
40
|
},
|
|
@@ -17,6 +17,8 @@ import { canonicalFund, changeColumns, changeLabel, changeReason, coverageText,
|
|
|
17
17
|
|
|
18
18
|
type ViewProps = Pick<PaneProps, "width" | "height" | "focused"> & { fund: string; active: boolean };
|
|
19
19
|
const rowKey = (row: SectionedRow<FundMember>) => row.key;
|
|
20
|
+
/** How often live members are worth checking again: the server renews their prices every 15 seconds. */
|
|
21
|
+
const LIVE_MEMBERS_REFRESH_MS = 15_000;
|
|
20
22
|
|
|
21
23
|
function Holdings({ fund, tab, width, height, focused, active }: ViewProps & { tab: MembersTab }) {
|
|
22
24
|
const colors = useThemeColors();
|
|
@@ -39,10 +41,13 @@ function Holdings({ fund, tab, width, height, focused, active }: ViewProps & { t
|
|
|
39
41
|
members: rows.flatMap((row) => isSectionedItemRow(row) && row.item.symbol ? [{ symbol: row.item.symbol, name: row.item.name }] : []) };
|
|
40
42
|
}, [data, fund, query, rows, tab]);
|
|
41
43
|
useMembersMenu("members:members-menu", memberList);
|
|
42
|
-
|
|
44
|
+
// A Pro account's members are priced from the server's live read, renewed every 15 seconds.
|
|
45
|
+
const live = data?.access === "realtime";
|
|
46
|
+
useAutoRefresh(resource.updatedAt, () => { if (active) void resource.load(live); }, { intervalMs: live ? LIVE_MEMBERS_REFRESH_MS : null });
|
|
43
47
|
usePaneRefreshKey(() => void resource.reload(), { focused, enabled: active && !search.active });
|
|
44
48
|
const info = useMemo<PaneFooterSegment[]>(() => {
|
|
45
49
|
if (!data) return [];
|
|
50
|
+
const feed = data.access === "realtime" ? "live" : "15m delayed";
|
|
46
51
|
const dates = [...new Set(data.members.flatMap((row) => row.changePercent !== null && row.dailyAsOf ? [row.dailyAsOf.slice(0, 10)] : []))].sort();
|
|
47
52
|
const date = dates.length === 1 ? dates[0] : dates.length ? `${dates[0]} to ${dates.at(-1)}` : data.fundDailyAsOf?.slice(0, 10);
|
|
48
53
|
const partial = data.aggregate.fresh1D < data.aggregate.total;
|
|
@@ -50,10 +55,12 @@ function Holdings({ fund, tab, width, height, focused, active }: ViewProps & { t
|
|
|
50
55
|
{ id: "coverage", parts: [{ text: coverageText(data.aggregate, width < 60), tone: partial ? "warning" : "muted" }] },
|
|
51
56
|
// A capture's status line says the quotes' date and delay too; it does not say returns are unavailable.
|
|
52
57
|
...(data.quotesUnavailable
|
|
53
|
-
? [{ id: "quote-date", title: `${date ?? "Quote date unavailable"} ·
|
|
58
|
+
? [{ id: "quote-date", title: `${date ?? "Quote date unavailable"} · ${feed} · holdings ${data.asOf}`, parts: [{ text: "returns unavailable", tone: "muted" as const }] }]
|
|
54
59
|
: [
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
data.access === "realtime"
|
|
61
|
+
? { id: "quote-live", quoteStatus: true, parts: [{ text: "live", tone: "positive" as const }] }
|
|
62
|
+
: delayedFooterSegment({ id: "quote-delay", detail: "15m delayed", delay: "15m", quoteStatus: true }),
|
|
63
|
+
...(date ? [{ id: "quote-date", title: `${date} · ${feed} · holdings ${data.asOf}`, quoteStatus: true,
|
|
57
64
|
parts: [{ text: width < 60 && dates.length === 1 ? date.slice(5) : date, tone: "muted" as const }] }] : []),
|
|
58
65
|
]),
|
|
59
66
|
...(width >= 60 ? [{ id: "holdings-date", asOf: true, parts: [{ text: `holdings ${data.asOf}`, tone: "muted" as const }] }] : []),
|
|
@@ -58,6 +58,7 @@ function validDeal(deal: MnaDeal): boolean {
|
|
|
58
58
|
&& !!terms && CONSIDERATIONS.has(terms.consideration)
|
|
59
59
|
&& numberOrNull(terms.cashPerShare) && numberOrNull(terms.exchangeRatio)
|
|
60
60
|
&& textOrNull(terms.ratioSymbol) && textOrNull(terms.currency)
|
|
61
|
+
&& (terms.election === undefined || typeof terms.election === "boolean")
|
|
61
62
|
&& typeof terms.cvr === "boolean" && typeof terms.partial === "boolean"
|
|
62
63
|
&& numberOrNull(deal.value) && textOrNull(deal.valueCurrency) && numberOrNull(deal.valueUsd)
|
|
63
64
|
&& day(deal.announced)
|