gloomberb 0.18.2 → 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/patches/electrobun@1.18.1.patch +106 -5
- 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 +99 -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 +24 -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 +26 -7
- 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/telemetry.ts +17 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/global-shortcuts.ts +1 -16
- 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/runtime/update.ts +28 -8
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/pane-tabs-allowlist.json +65 -0
- 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 +1189 -296
- 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 +272 -70
- 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 +20 -14
- 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 +32 -18
- package/src/cli/issuer-membership.ts +103 -0
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +315 -43
- package/src/cli/name-entries.ts +73 -22
- 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 +77 -20
- package/src/cli/pane-functions/catalog.ts +40 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +12 -8
- 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 +48 -16
- package/src/cli/pane-functions/index.ts +82 -21
- 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 +65 -14
- 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 +190 -27
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +122 -25
- 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 +226 -60
- 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 +387 -21
- package/src/components/chart/composite/drawing-store.ts +26 -6
- package/src/components/chart/composite/interactions.ts +9 -3
- 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 +316 -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 +19 -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/command-items.ts +32 -6
- 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/data-table/view.tsx +23 -3
- 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 +13 -6
- package/src/components/layout/detached-pane-shell.tsx +1 -0
- package/src/components/layout/floating-pane.tsx +1 -0
- package/src/components/layout/header.tsx +234 -60
- 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/pane/header.tsx +10 -3
- package/src/components/layout/pane/index.tsx +1 -0
- package/src/components/layout/pane/pane-tabs.tsx +9 -1
- 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/components/ui/stat-grid.tsx +28 -3
- package/src/components/ui/status.tsx +3 -1
- package/src/core/app-services.ts +4 -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 +51 -12
- package/src/i18n/ja.ts +51 -12
- package/src/i18n/ko.ts +51 -12
- package/src/i18n/zh-cn.ts +51 -12
- package/src/i18n/zh-tw.ts +51 -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 +30 -18
- 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 +108 -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 +77 -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 +107 -43
- package/src/plugins/builtin/attention/pane.tsx +22 -16
- 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 +12 -9
- package/src/plugins/builtin/backtest/export.ts +1 -1
- 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 +24 -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 +115 -26
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
- 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 +34 -18
- 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/client.ts +2 -2
- 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 +9 -11
- 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 +128 -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 +14 -8
- package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
- 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 +89 -31
- 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 +5 -4
- 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 +7 -4
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
- package/src/plugins/builtin/correlation/settings.ts +1 -0
- 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 +7 -5
- 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/credit-documents/pane.tsx +8 -7
- 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/debt-maturities/pane.tsx +4 -3
- 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 +19 -12
- 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 +77 -5
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +34 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
- 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 +16 -10
- 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/board.tsx +4 -1
- package/src/plugins/builtin/gpu/changes.tsx +10 -10
- package/src/plugins/builtin/gpu/equities.tsx +4 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/gpu/history.tsx +4 -2
- package/src/plugins/builtin/gpu/pane.tsx +5 -3
- 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 +15 -2
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +48 -8
- 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/thirteenf-match.ts +3 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/base-values.ts +11 -7
- package/src/plugins/builtin/insider/client.ts +3 -0
- package/src/plugins/builtin/insider/headless.ts +20 -7
- package/src/plugins/builtin/insider/index.tsx +17 -8
- package/src/plugins/builtin/insider/issuer.ts +34 -4
- package/src/plugins/builtin/insider/signals-client.ts +3 -3
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/insider/table-model.ts +35 -13
- package/src/plugins/builtin/insider/table.tsx +5 -2
- 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/events.ts +145 -0
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +91 -7
- 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 +14 -8
- 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 +36 -21
- 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 +33 -11
- 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 +50 -15
- package/src/plugins/builtin/notes/export.ts +17 -6
- package/src/plugins/builtin/notes/files.ts +16 -5
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/enrichment-model.ts +10 -9
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +70 -4
- package/src/plugins/builtin/options/view.tsx +51 -23
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
- package/src/plugins/builtin/options-positioning/headless.ts +11 -3
- package/src/plugins/builtin/options-positioning/model.ts +24 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
- package/src/plugins/builtin/options-scenario/client.ts +142 -29
- 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 +49 -21
- 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 +22 -10
- 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 +145 -60
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
- 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 +6 -3
- 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 +44 -32
- 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/client.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/seasonality/client.ts +2 -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 +6 -4
- 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-resource.ts +15 -2
- 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 +23 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/volatility/options.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/social-mentions/client.ts +2 -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 +28 -7
- package/src/plugins/builtin/vol-surface/headless.ts +43 -15
- package/src/plugins/builtin/vol-surface/model.ts +34 -12
- package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
- package/src/plugins/builtin/vol-surface/stored.ts +34 -3
- package/src/plugins/builtin/vol-surface/tables.ts +14 -0
- 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/desktop/controls.tsx +1 -1
- package/src/renderers/dom/desktop/query-bar.tsx +2 -0
- 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/host/tabs.tsx +16 -5
- package/src/renderers/dom/host/top-surface.ts +127 -0
- package/src/renderers/dom/styles.css +115 -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/core-capabilities.ts +9 -1
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +56 -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/desktop/update.ts +210 -30
- 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 +9 -7
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
- 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 +8 -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 +39 -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/index.ts +16 -0
- 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 +21 -4
- package/src/telemetry/update-failures-node.ts +59 -0
- package/src/telemetry/update-failures.ts +307 -0
- 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 +215 -36
- package/src/tickers/company-name.ts +43 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-fate.ts +30 -0
- 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 +20 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +83 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/issuer-listings.ts +28 -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/failure.ts +163 -0
- package/src/updater/index.ts +97 -28
- 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-pair.ts +26 -0
- 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 +71 -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
|
@@ -2,6 +2,8 @@ import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
|
2
2
|
import { DataTableView, EmptyState, PaneStatusBody, QueryBar, StatGrid, statGridRows, usePaneFooter, usePaneNoticeFooter,
|
|
3
3
|
usePaneTicker, type DataTableCell, type DataTableColumn, type StatItem } from "../../../components";
|
|
4
4
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
5
|
+
import { tableColumnWidth } from "../../../components/ui/table-layout";
|
|
6
|
+
import { displayWidth } from "../../../utils/format";
|
|
5
7
|
import { instrumentFromTicker } from "../../../market-data/request-types";
|
|
6
8
|
import { usePaneSettingValue, usePluginPaneState } from "../../../public/react";
|
|
7
9
|
import { useAsyncResource } from "../../../react/async-resource";
|
|
@@ -10,11 +12,13 @@ import { useThemeColors } from "../../../theme/theme-context";
|
|
|
10
12
|
import type { PaneProps } from "../../../types/plugin";
|
|
11
13
|
import { Box } from "../../../ui";
|
|
12
14
|
import { loadMacroDayEarnings, loadMacroDayHistory, loadMacroReleases, macroDayEarningsNotice } from "./client";
|
|
13
|
-
import { macroDayEventLabel, projectMacroDays, type MacroDayEvent, type MacroDayModel } from "./model";
|
|
14
|
-
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, staleMacroReleasesNotice, type MacroEventKind
|
|
15
|
+
import { macroDayEventLabel, macroDayStats, matchesSurprise, projectMacroDays, type MacroDayEvent, type MacroDayModel } from "./model";
|
|
16
|
+
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, MACRO_SURPRISE_LABELS, MACRO_SURPRISES, staleMacroReleasesNotice, type MacroEventKind,
|
|
17
|
+
type MacroSurprise } from "./releases";
|
|
15
18
|
|
|
16
19
|
export const LOOKBACK_OPTIONS = [{ value: "1", label: "1Y" }, { value: "2", label: "2Y" }, { value: "3", label: "3Y" }, { value: "5", label: "5Y" }];
|
|
17
20
|
const RELEASE_OPTIONS = [{ value: "all", label: "All" }, ...MACRO_EVENT_KINDS.map((kind) => ({ value: kind, label: MACRO_EVENT_LABELS[kind] }))];
|
|
21
|
+
const SURPRISE_OPTIONS = [{ value: "all", label: "All" }, ...MACRO_SURPRISES.map((surprise) => ({ value: surprise, label: MACRO_SURPRISE_LABELS[surprise] }))];
|
|
18
22
|
|
|
19
23
|
function pct(value: number | null | undefined, signed = true): string {
|
|
20
24
|
if (value == null) return "--";
|
|
@@ -29,21 +33,45 @@ const MOVE: DataTableColumn[] = [
|
|
|
29
33
|
{ id: "move", label: "Move", width: 9, align: "right" },
|
|
30
34
|
{ id: "multiple", label: "vs Normal", width: 10, align: "right" },
|
|
31
35
|
];
|
|
36
|
+
/** What each release came out with, under the labels the economic calendar gives them. */
|
|
37
|
+
const FIGURES = [["actual", "Actual"], ["forecast", "Forecast"], ["prior", "Prior"]] as const;
|
|
38
|
+
|
|
39
|
+
/** The figure columns, shown once any listed day has figures, each as wide as its header and its widest value. */
|
|
40
|
+
function figureColumns(rows: readonly MacroDayEvent[]): DataTableColumn[] {
|
|
41
|
+
if (!rows.some((event) => event.figures)) return [];
|
|
42
|
+
return FIGURES.map(([id, label]) => ({ id, label, align: "right", width: tableColumnWidth({ label,
|
|
43
|
+
width: Math.max(6, ...rows.map((event) => displayWidth(event.figures?.[id] ?? ""))) }) }));
|
|
44
|
+
}
|
|
32
45
|
|
|
33
46
|
/**
|
|
34
47
|
* With every release listed, the release's name, widened to take the earnings marker where a row has one. With one
|
|
35
48
|
* selected, a column only for the marker: every row would repeat the name.
|
|
36
49
|
*/
|
|
37
|
-
function columnsFor(release: string, rows: readonly MacroDayEvent[]): DataTableColumn[] {
|
|
50
|
+
export function columnsFor(release: string, rows: readonly MacroDayEvent[]): DataTableColumn[] {
|
|
38
51
|
const marked = rows.some((event) => event.earnings);
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
const values = [...figureColumns(rows), ...MOVE];
|
|
53
|
+
if (release === "all") return [DATE, { id: "release", label: "Release", width: marked ? 15 : 8, align: "left" }, ...values];
|
|
54
|
+
return marked ? [DATE, { id: "release", label: "Note", width: EARNINGS_MARK.length, align: "left" }, ...values] : [DATE, ...values];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const tone = (value: number | null) => value == null ? undefined : value >= 0 ? "positive" as const : "negative" as const;
|
|
58
|
+
|
|
59
|
+
/** The figures over the days a surprise filter keeps: the same four as one release's. */
|
|
60
|
+
function surpriseFigures(model: MacroDayModel, rows: readonly MacroDayEvent[]): StatItem[] {
|
|
61
|
+
const stats = macroDayStats(rows, model.normal.meanAbs);
|
|
62
|
+
return [
|
|
63
|
+
{ id: "abs", label: "Avg |move|", value: pct(stats.meanAbs, false), detail: stats.count ? `${times(stats.multiple)} normal` : undefined },
|
|
64
|
+
{ id: "mean", label: "Avg move", value: pct(stats.mean), tone: tone(stats.mean) },
|
|
65
|
+
{ id: "up", label: "Up", value: stats.hitRate == null ? "--" : `${Math.round(stats.hitRate * 100)}%`,
|
|
66
|
+
detail: stats.count ? `${Math.round(stats.hitRate! * stats.count)} of ${stats.count}` : undefined },
|
|
67
|
+
{ id: "normal", label: "Normal day", value: pct(model.normal.meanAbs, false), detail: "avg |move|" },
|
|
68
|
+
];
|
|
41
69
|
}
|
|
42
70
|
|
|
43
71
|
function figures(model: MacroDayModel, release: string): StatItem[] {
|
|
44
72
|
const normal: StatItem = { id: "normal", label: "Normal day", value: pct(model.normal.meanAbs, false), detail: "avg |move|" };
|
|
45
73
|
if (release === "all") {
|
|
46
|
-
return [...
|
|
74
|
+
return [...model.kinds.map((kind): StatItem => {
|
|
47
75
|
const stats = model.byKind[kind];
|
|
48
76
|
return { id: kind, label: `${MACRO_EVENT_LABELS[kind]} day`, value: pct(stats.meanAbs, false),
|
|
49
77
|
detail: stats.count ? `${times(stats.multiple)} normal` : undefined };
|
|
@@ -51,7 +79,6 @@ function figures(model: MacroDayModel, release: string): StatItem[] {
|
|
|
51
79
|
detail: `${times(model.earnings.multiple)} normal` }] : []), normal];
|
|
52
80
|
}
|
|
53
81
|
const stats = model.byKind[release as MacroEventKind];
|
|
54
|
-
const tone = (value: number | null) => value == null ? undefined : value >= 0 ? "positive" as const : "negative" as const;
|
|
55
82
|
return [
|
|
56
83
|
{ id: "abs", label: "Avg |move|", value: pct(stats.meanAbs, false), detail: stats.count ? `${times(stats.multiple)} normal` : undefined },
|
|
57
84
|
{ id: "mean", label: "Avg move", value: pct(stats.mean), tone: tone(stats.mean) },
|
|
@@ -66,6 +93,7 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
66
93
|
const { symbol, ticker, error: identityError } = usePaneTicker();
|
|
67
94
|
const [lookback, setLookback] = usePaneSettingValue("lookbackYears", "5");
|
|
68
95
|
const [release, setRelease] = usePluginPaneState("release", "all");
|
|
96
|
+
const [surprise, setSurprise] = usePluginPaneState<MacroSurprise | "all">("surprise", "all");
|
|
69
97
|
const [selectedRow, setSelectedRow] = usePluginPaneState<string | null>("selectedRow", null);
|
|
70
98
|
const instrument = instrumentFromTicker(ticker, symbol);
|
|
71
99
|
const instrumentKey = JSON.stringify(instrument);
|
|
@@ -88,8 +116,10 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
88
116
|
[history.data, lookback, symbol]);
|
|
89
117
|
const releasesNotice = history.data ? staleMacroReleasesNotice(history.data.releases) : null;
|
|
90
118
|
const earningsNotice = history.data ? macroDayEarningsNotice(history.data.earnings) : null;
|
|
91
|
-
const rows = useMemo(() => model ? model.events.filter((event) => release === "all" || event.kind === release)
|
|
92
|
-
|
|
119
|
+
const rows = useMemo(() => model ? model.events.filter((event) => (release === "all" || event.kind === release)
|
|
120
|
+
&& matchesSurprise(event, surprise)) : [], [model, release, surprise]);
|
|
121
|
+
const stats = useMemo(() => !model?.events.length ? [] : surprise === "all" ? figures(model, release) : surpriseFigures(model, rows),
|
|
122
|
+
[model, release, surprise, rows]);
|
|
93
123
|
const columns = useMemo(() => columnsFor(release, rows), [release, rows]);
|
|
94
124
|
|
|
95
125
|
usePaneNoticeFooter({ registrationId: "macro-day-notices", focused,
|
|
@@ -103,6 +133,11 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
103
133
|
const renderCell = useCallback((event: MacroDayEvent, column: DataTableColumn): DataTableCell => {
|
|
104
134
|
if (column.id === "date") return { text: event.session === event.date ? event.date : `${event.date} → ${event.session.slice(5)}`, value: event.date };
|
|
105
135
|
if (column.id === "release") return { text: release === "all" ? macroDayEventLabel(event) : event.earnings ? EARNINGS_MARK : "" };
|
|
136
|
+
// The print colored against the consensus, as the economic calendar colors it.
|
|
137
|
+
if (column.id === "actual") return { text: event.figures?.actual ?? "", color: event.figures?.surprise === "hot" ? colors.positive
|
|
138
|
+
: event.figures?.surprise === "cool" ? colors.negative : undefined };
|
|
139
|
+
if (column.id === "forecast") return { text: event.figures?.forecast ?? "" };
|
|
140
|
+
if (column.id === "prior") return { text: event.figures?.prior ?? "" };
|
|
106
141
|
if (column.id === "move") return { text: pct(event.move), value: event.move * 100,
|
|
107
142
|
color: event.move > 0 ? colors.positive : event.move < 0 ? colors.negative : undefined };
|
|
108
143
|
return { text: times(event.multiple), value: event.multiple };
|
|
@@ -114,6 +149,7 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
114
149
|
return <Box width={width} height={height} flexDirection="column" overflow="hidden">
|
|
115
150
|
<QueryBar width={width} filters={[
|
|
116
151
|
{ id: "release", label: "Release", value: release, options: RELEASE_OPTIONS, onChange: setRelease, inline: true },
|
|
152
|
+
{ id: "surprise", label: "Surprise", value: surprise, options: SURPRISE_OPTIONS, onChange: (value) => setSurprise(value as MacroSurprise | "all") },
|
|
117
153
|
{ id: "lookback", label: "Lookback", value: String(lookback), options: LOOKBACK_OPTIONS, onChange: setLookback },
|
|
118
154
|
]} />
|
|
119
155
|
{!symbol ? <EmptyState title="Select a ticker." /> : <PaneStatusBody subject="macro-day moves" loading={history.loading && !model}
|
|
@@ -121,7 +157,7 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
121
157
|
{model ? <>
|
|
122
158
|
<StatGrid items={stats} width={width} />
|
|
123
159
|
<DataTableView<MacroDayEvent> focused={focused} columns={columns} items={rows} rootWidth={width} rootHeight={contentHeight}
|
|
124
|
-
getItemKey={key} emptyStateTitle="No release days." sortColumnId={null} sortDirection="desc" selectedTextOverridesCellColor
|
|
160
|
+
getItemKey={key} emptyStateTitle={surprise === "all" ? "No release days." : `No ${MACRO_SURPRISE_LABELS[surprise].toLowerCase()} prints.`} sortColumnId={null} sortDirection="desc" selectedTextOverridesCellColor
|
|
125
161
|
selection={{ kind: "id", selectedId: selectedRow, getId: key, onChange: (id) => setSelectedRow(id) }}
|
|
126
162
|
getExportMetadata={() => [["symbol", model.symbol], ["from", model.start ?? ""], ["to", model.asOf ?? ""],
|
|
127
163
|
["units", "percent, close to close on the release day"]]}
|
|
@@ -1,27 +1,47 @@
|
|
|
1
|
-
// Published
|
|
1
|
+
// Published release days, not a rule engine: the dates each release came
|
|
2
2
|
// out, read from the publishers' own archives. A release cancelled or moved (the
|
|
3
3
|
// 2025 shutdown) is as published, and a scheduled date is not a release day
|
|
4
|
-
// until it is out. Dates are New York calendar days.
|
|
4
|
+
// until it is out. Dates are New York calendar days. Brazil's IPCA days come
|
|
5
|
+
// from Gloom Cloud only; the list the app ships with has the US releases.
|
|
5
6
|
import { zonedDateKey } from "../../../utils/zoned-date-time";
|
|
6
7
|
import { MACRO_RELEASE_TABLE } from "./release-table";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/** The US releases the bundled list carries, and the ones HIVG reads around. */
|
|
10
|
+
export type UsMacroEventKind = "cpi" | "jobs" | "fomc";
|
|
11
|
+
export type MacroEventKind = UsMacroEventKind | "ipca";
|
|
9
12
|
|
|
10
|
-
export const
|
|
13
|
+
export const US_MACRO_EVENT_KINDS: readonly UsMacroEventKind[] = ["cpi", "jobs", "fomc"];
|
|
14
|
+
export const MACRO_EVENT_KINDS: readonly MacroEventKind[] = [...US_MACRO_EVENT_KINDS, "ipca"];
|
|
11
15
|
|
|
12
|
-
export const MACRO_EVENT_LABELS: Record<MacroEventKind, string> = { cpi: "CPI", jobs: "Jobs", fomc: "FOMC" };
|
|
16
|
+
export const MACRO_EVENT_LABELS: Record<MacroEventKind, string> = { cpi: "CPI", jobs: "Jobs", fomc: "FOMC", ipca: "IPCA" };
|
|
13
17
|
|
|
14
|
-
/** BLS news release archives for CPI and the Employment Situation,
|
|
18
|
+
/** BLS news release archives for CPI and the Employment Situation, the Federal Reserve's meeting calendar, IBGE's calendar. */
|
|
15
19
|
export const MACRO_RELEASE_SOURCES: Record<MacroEventKind, string> = {
|
|
16
20
|
cpi: "https://www.bls.gov/bls/news-release/cpi.htm",
|
|
17
21
|
jobs: "https://www.bls.gov/bls/news-release/empsit.htm",
|
|
18
22
|
fomc: "https://www.federalreserve.gov/monetarypolicy/fomccalendars.htm",
|
|
23
|
+
ipca: "https://www.ibge.gov.br/calendario-indicadores-novoportal.html",
|
|
19
24
|
};
|
|
20
25
|
|
|
21
26
|
/** A list more than this many days behind today says so: a release day may be missing from its end. */
|
|
22
27
|
export const MACRO_RELEASES_STALE_DAYS = 14;
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
/** Above the consensus (hot), below it (cool), at it (in-line). */
|
|
30
|
+
export type MacroSurprise = "hot" | "cool" | "in-line";
|
|
31
|
+
export const MACRO_SURPRISES: readonly MacroSurprise[] = ["hot", "cool", "in-line"];
|
|
32
|
+
export const MACRO_SURPRISE_LABELS: Record<MacroSurprise, string> = { hot: "Hot", cool: "Cool", "in-line": "In line" };
|
|
33
|
+
|
|
34
|
+
/** What a release day came out with: the headline, its print, the consensus before it and the figure before that. */
|
|
35
|
+
export interface MacroReleaseFigures {
|
|
36
|
+
/** The headline the figures are for: "Inflation Rate YoY", "IPCA m/m". */
|
|
37
|
+
event: string;
|
|
38
|
+
actual: string | null;
|
|
39
|
+
forecast: string | null;
|
|
40
|
+
prior: string | null;
|
|
41
|
+
surprise: MacroSurprise | null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MacroRelease { kind: MacroEventKind; date: string; figures?: MacroReleaseFigures }
|
|
25
45
|
|
|
26
46
|
export interface MacroReleaseList {
|
|
27
47
|
/** Oldest first. */
|
|
@@ -37,29 +57,51 @@ const byDate = (left: MacroRelease, right: MacroRelease) => left.date.localeComp
|
|
|
37
57
|
|
|
38
58
|
/** The list the app ships with: the floor whenever the server's list is missing or older. */
|
|
39
59
|
export function bundledMacroReleases(): MacroReleaseList {
|
|
40
|
-
const releases =
|
|
60
|
+
const releases = US_MACRO_EVENT_KINDS.flatMap((kind) => Object.entries(MACRO_RELEASE_TABLE.days[kind]).flatMap(([year, days]) =>
|
|
41
61
|
days.map((day) => ({ kind, date: `${year}-${day}` }))));
|
|
42
62
|
return { releases: releases.sort(byDate), coveredThrough: MACRO_RELEASE_TABLE.coveredThrough };
|
|
43
63
|
}
|
|
44
64
|
|
|
65
|
+
const text = (value: unknown) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
66
|
+
|
|
67
|
+
/** A day's figures as served, or undefined when they break the contract. */
|
|
68
|
+
function servedFigures(value: unknown): MacroReleaseFigures | undefined {
|
|
69
|
+
const figures = value as Partial<Record<keyof MacroReleaseFigures, unknown>> | null;
|
|
70
|
+
const event = text(figures?.event);
|
|
71
|
+
if (!event) return undefined;
|
|
72
|
+
const surprise = MACRO_SURPRISES.find((candidate) => candidate === figures?.surprise) ?? null;
|
|
73
|
+
return { event, actual: text(figures?.actual), forecast: text(figures?.forecast), prior: text(figures?.prior), surprise };
|
|
74
|
+
}
|
|
75
|
+
|
|
45
76
|
/**
|
|
46
77
|
* The served list extends the floor past its end; the floor keeps its own
|
|
47
|
-
* days up to there.
|
|
48
|
-
*
|
|
78
|
+
* days up to there. IPCA, which the floor does not carry, is the served list's
|
|
79
|
+
* through its end, and left out when the server lists none. Every day takes
|
|
80
|
+
* the figures the server has for it. A served list that breaks the contract,
|
|
81
|
+
* or ends no later than the floor, adds nothing.
|
|
49
82
|
*/
|
|
50
83
|
export function mergeMacroReleases(floor: MacroReleaseList, served: unknown): MacroReleaseList {
|
|
51
|
-
const payload = served as { coveredThrough?: unknown; releases?: Partial<Record<MacroEventKind, unknown
|
|
84
|
+
const payload = served as { coveredThrough?: unknown; releases?: Partial<Record<MacroEventKind, unknown>>;
|
|
85
|
+
figures?: Partial<Record<MacroEventKind, Record<string, unknown>>> } | null;
|
|
52
86
|
const coveredThrough = payload?.coveredThrough;
|
|
53
87
|
if (!isDate(coveredThrough) || coveredThrough <= floor.coveredThrough) return floor;
|
|
54
88
|
const later: MacroRelease[] = [];
|
|
55
|
-
for (const kind of
|
|
89
|
+
for (const kind of US_MACRO_EVENT_KINDS) {
|
|
56
90
|
const dates = payload?.releases?.[kind];
|
|
57
91
|
if (!Array.isArray(dates) || !dates.every(isDate)) return floor;
|
|
58
92
|
for (const date of new Set(dates)) {
|
|
59
93
|
if (date > floor.coveredThrough && date <= coveredThrough) later.push({ kind, date });
|
|
60
94
|
}
|
|
61
95
|
}
|
|
62
|
-
|
|
96
|
+
const ipca = payload?.releases?.ipca;
|
|
97
|
+
if (Array.isArray(ipca) && ipca.every(isDate)) {
|
|
98
|
+
for (const date of new Set(ipca)) if (date <= coveredThrough) later.push({ kind: "ipca", date });
|
|
99
|
+
}
|
|
100
|
+
const figuresOf = (release: MacroRelease): MacroRelease => {
|
|
101
|
+
const figures = servedFigures(payload?.figures?.[release.kind]?.[release.date]);
|
|
102
|
+
return figures ? { ...release, figures } : release;
|
|
103
|
+
};
|
|
104
|
+
return { releases: [...floor.releases, ...later].map(figuresOf).sort(byDate), coveredThrough };
|
|
63
105
|
}
|
|
64
106
|
|
|
65
107
|
/** Whole days from the list's last covered day to today in New York. */
|
|
@@ -31,7 +31,14 @@ export interface MarketHeatmapBoard extends MarketHeatmapResult {
|
|
|
31
31
|
const DEFAULT_COUNT = 80;
|
|
32
32
|
/** The most names one board asks for; a server that serves fewer answers with its own maximum. */
|
|
33
33
|
const MAX_MARKET_HEATMAP_COUNT = 500;
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* How often a board is worth checking again: a real-time board's live read
|
|
36
|
+
* is renewed every 15 seconds on the server, a delayed board's snapshot is
|
|
37
|
+
* cached there for a minute.
|
|
38
|
+
*/
|
|
39
|
+
export function heatmapCheckIntervalMs(board: Pick<MarketHeatmapResult, "access"> | null | undefined): number {
|
|
40
|
+
return board?.access === "realtime" ? 15_000 : 60_000;
|
|
41
|
+
}
|
|
35
42
|
const activeFetches = new Map<string, Promise<MarketHeatmapBoard>>();
|
|
36
43
|
const memoryCache = new Map<string, { expiresAt: number; result: MarketHeatmapBoard }>();
|
|
37
44
|
|
|
@@ -90,7 +97,7 @@ export async function fetchMarketHeatmap(
|
|
|
90
97
|
const fetchPromise = loadMarketHeatmap(universe, count, sources)
|
|
91
98
|
.then((result) => {
|
|
92
99
|
if (useCache) {
|
|
93
|
-
memoryCache.set(cacheKey, { result, expiresAt: Date.now() +
|
|
100
|
+
memoryCache.set(cacheKey, { result, expiresAt: Date.now() + heatmapCheckIntervalMs(result) });
|
|
94
101
|
}
|
|
95
102
|
return result;
|
|
96
103
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What `
|
|
2
|
+
* What `gloom shot HM` certifies: the tab the heat map drew, what its tiles
|
|
3
3
|
* are sized by, how many tiles and sectors are plotted, and whether its
|
|
4
4
|
* snapshot had loaded. The heat map has
|
|
5
5
|
* no table rows or labeled values, so this is how a capture counts as data.
|
|
@@ -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 });
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
CloudSessionMoversSide,
|
|
6
6
|
} from "../../../api-client/market-movers";
|
|
7
7
|
import type { DataProvider } from "../../../types/data-provider";
|
|
8
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
8
9
|
import {
|
|
9
10
|
CATEGORY_MAP,
|
|
10
11
|
moverRegularSession,
|
|
@@ -17,7 +18,8 @@ import {
|
|
|
17
18
|
} from "./model";
|
|
18
19
|
import {
|
|
19
20
|
fetchPreferredMarketMovers,
|
|
20
|
-
|
|
21
|
+
fetchTrendingResult,
|
|
22
|
+
type CachedResult,
|
|
21
23
|
type MarketMoversResult,
|
|
22
24
|
type PreferredMoversOptions,
|
|
23
25
|
type TrendingSymbol,
|
|
@@ -29,6 +31,8 @@ export interface MarketMoverTabResult extends MarketMoversResult {
|
|
|
29
31
|
quotes: MoverQuote[];
|
|
30
32
|
/** What the list is ranked by; absent for trending, which keeps its source's order. */
|
|
31
33
|
rankedBy?: MoverRanking;
|
|
34
|
+
/** Requested trending names whose quotes did not load. */
|
|
35
|
+
unavailableSymbols?: string[];
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
/** Rows a list shows. */
|
|
@@ -45,42 +49,52 @@ export interface MarketMoverTabDependencies {
|
|
|
45
49
|
count: number,
|
|
46
50
|
options?: PreferredMoversOptions,
|
|
47
51
|
): Promise<MarketMoversResult>;
|
|
48
|
-
fetchTrending(count: number, options?: { forceRefresh?: boolean }): Promise<TrendingSymbol[]
|
|
52
|
+
fetchTrending(count: number, options?: { forceRefresh?: boolean }): Promise<CachedResult<TrendingSymbol[]>>;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
const defaultDependencies: MarketMoverTabDependencies = {
|
|
52
56
|
fetchPreferred: (category, count, options) => fetchPreferredMarketMovers(category, count, options),
|
|
53
|
-
fetchTrending: (count, options) =>
|
|
57
|
+
fetchTrending: (count, options) => fetchTrendingResult(count, undefined, options),
|
|
54
58
|
};
|
|
55
59
|
|
|
56
60
|
async function hydrateTrending(
|
|
57
61
|
trending: readonly TrendingSymbol[],
|
|
58
62
|
provider: DataProvider | null,
|
|
59
|
-
): Promise<
|
|
60
|
-
const symbols = trending.slice(0,
|
|
63
|
+
): Promise<Pick<MarketMoverTabResult, "quotes" | "unavailableSymbols">> {
|
|
64
|
+
const symbols = trending.slice(0, LIST_ROWS).map(({ symbol }) => symbol);
|
|
61
65
|
const bySymbol = new Map<string, MoverQuote>();
|
|
62
|
-
if (
|
|
63
|
-
if (provider
|
|
64
|
-
|
|
65
|
-
symbols.map((symbol) => ({ symbol, exchange: "" }))
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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);
|
|
69
75
|
}
|
|
70
|
-
} else {
|
|
76
|
+
} else if (provider) {
|
|
71
77
|
await Promise.all(symbols.map(async (symbol) => {
|
|
72
78
|
try {
|
|
73
79
|
const quote = await provider.getQuote(symbol, "");
|
|
74
80
|
bySymbol.set(symbol, screenerQuoteFromQuote(symbol, quote));
|
|
75
|
-
} catch {
|
|
76
|
-
|
|
81
|
+
} catch (error) {
|
|
82
|
+
logFailure("market-movers", "Trending quote failed")(error);
|
|
77
83
|
}
|
|
78
84
|
}));
|
|
79
85
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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;
|
|
84
98
|
}
|
|
85
99
|
|
|
86
100
|
export async function loadMarketMoverTab(
|
|
@@ -92,11 +106,12 @@ export async function loadMarketMoverTab(
|
|
|
92
106
|
const { basis, ...fetchOptions } = options ?? {};
|
|
93
107
|
if (tab === "trending") {
|
|
94
108
|
const trending = await dependencies.fetchTrending(LIST_ROWS, fetchOptions);
|
|
109
|
+
const hydrated = await hydrateTrending(trending.data, provider);
|
|
95
110
|
return {
|
|
96
111
|
tab,
|
|
97
|
-
|
|
112
|
+
...hydrated,
|
|
98
113
|
source: "gloom",
|
|
99
|
-
stale:
|
|
114
|
+
stale: trending.stale || !!hydrated.unavailableSymbols?.length,
|
|
100
115
|
};
|
|
101
116
|
}
|
|
102
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 ? (
|