gloomberb 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { formatPriceEarnings } from "../../../../utils/price-earnings";
|
|
1
|
+
import { formatPriceEarnings, NOT_MEANINGFUL } from "../../../../utils/price-earnings";
|
|
2
2
|
import { convertMarketCapitalization } from "../../../../utils/market-capitalization";
|
|
3
3
|
import { priceColor } from "../../../../theme/colors";
|
|
4
|
-
import type { CompanyProfile, NextEarnings, Quote, TickerFinancials } from "../../../../types/financials";
|
|
4
|
+
import type { CompanyProfile, DepositaryPair, NextEarnings, Quote, TickerFinancials } from "../../../../types/financials";
|
|
5
|
+
import { adrRatioText } from "../../../../utils/depositary-receipt";
|
|
6
|
+
import { ratioCount } from "../../../../market-data/depositary-pair";
|
|
7
|
+
import { ADR_PAIR_TAB_ID, ADR_PAIR_TEMPLATE_ID } from "../adr-pair/model";
|
|
5
8
|
import type { Portfolio, TickerPosition, TickerRecord } from "../../../../types/ticker";
|
|
6
9
|
import type { BrokerInstanceConfig } from "../../../../types/config";
|
|
7
10
|
import type { BrokerAccount } from "../../../../types/trading";
|
|
@@ -28,11 +31,12 @@ import { getPortfolioPositionMetrics, getPortfolioQuoteDisplay, resolvePortfolio
|
|
|
28
31
|
import { listingDividendYield, liveForwardPE, liveMarketCapitalization, liveTrailingPE } from "../../../../market-data/quotes/live-valuation";
|
|
29
32
|
import { atRegularSessionPrice } from "../../../../market-data/quotes/regular-session-valuation";
|
|
30
33
|
import { formatReportedMoney } from "../../../../utils/reported-money";
|
|
31
|
-
import { enterpriseValueCheck, fundamentalsCurrency, fundamentalsEpsCurrency, reportedEnterpriseValue } from "../../../../utils/fundamentals";
|
|
34
|
+
import { enterpriseValueCheck, enterpriseValueNotMeaningful, fundamentalsCurrency, fundamentalsEpsCurrency, reportedEnterpriseValue } from "../../../../utils/fundamentals";
|
|
32
35
|
import { formatShortDate } from "../../../../utils/datetime-format";
|
|
33
36
|
import { safeExternalUrl } from "../../../../utils/external-url";
|
|
34
37
|
import type { FundBondFacts } from "../../../../api-client/fund-facts";
|
|
35
38
|
import { bondFigures } from "../../../../market-data/bond-funds";
|
|
39
|
+
import { formatRunwayMonths, type CashRunway, type RunwayEstimate } from "../../../../utils/cash-runway";
|
|
36
40
|
|
|
37
41
|
type CurrencyConverter = (value: number, fromCurrency: string) => number;
|
|
38
42
|
|
|
@@ -42,6 +46,8 @@ const SHORT_INTEREST: OverviewFunctionLink = { name: "Short Interest", tabId: "s
|
|
|
42
46
|
const EARNINGS: OverviewFunctionLink = { name: "Earnings", templateId: "earnings-calendar-pane" };
|
|
43
47
|
const DIVIDENDS: OverviewFunctionLink = { name: "Dividends", tabId: "dividend-yield", templateId: "dividend-yield-pane" };
|
|
44
48
|
const FUND_FACTS: OverviewFunctionLink = { name: "Fund Facts", templateId: "sec-etf-pane" };
|
|
49
|
+
const FINANCIALS: OverviewFunctionLink = { name: "Financials", tabId: "financials", templateId: "financial-analysis-pane" };
|
|
50
|
+
const ADR_PAIR: OverviewFunctionLink = { name: "ADR vs Home", tabId: ADR_PAIR_TAB_ID, templateId: ADR_PAIR_TEMPLATE_ID };
|
|
45
51
|
|
|
46
52
|
/** A bond fund's sponsor figures in a narrow grid: `SEC Yield 4.04% 2026-10-15`. */
|
|
47
53
|
const BOND_STAT_LABELS = { secYield: "SEC Yield", yieldToWorst: "Yld to Worst" } as const;
|
|
@@ -108,6 +114,33 @@ function positionAccountLabel(position: TickerPosition, names: PositionAccountNa
|
|
|
108
114
|
return `${positionAccountName(position, names)}${suffix}`;
|
|
109
115
|
}
|
|
110
116
|
|
|
117
|
+
/** A runway measure as the grid reads it: `12.0 mo`, or `no burn`. */
|
|
118
|
+
function runwayText(estimate: RunwayEstimate): string {
|
|
119
|
+
return estimate.kind === "no-burn" ? "no burn" : formatRunwayMonths(estimate.months, "mo");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Months of cash for a company that burns it, at the latest quarter's burn
|
|
124
|
+
* with the trailing year's after it and the balance sheet's date where it
|
|
125
|
+
* fits (`12.0 mo qtr to 06-30 · TTM 14.4 mo`). It opens Financials, whose
|
|
126
|
+
* Liquidity rows show the cash and the monthly burn. A company whose
|
|
127
|
+
* trailing operating cash flow is nonnegative or unavailable has no row.
|
|
128
|
+
*/
|
|
129
|
+
function runwayStat(runway: CashRunway | null | undefined): StatField | null {
|
|
130
|
+
if (runway?.trailing?.kind !== "months") return null;
|
|
131
|
+
const { quarter, trailing, periodEnd } = runway;
|
|
132
|
+
const dates = [periodEnd, periodEnd.slice(5)];
|
|
133
|
+
if (!quarter) return { label: "Runway", value: runwayText(trailing), detail: [...dates.map((date) => `TTM to ${date}`), "TTM"], link: FINANCIALS };
|
|
134
|
+
const ttm = ` · TTM ${runwayText(trailing)}`;
|
|
135
|
+
return {
|
|
136
|
+
label: "Runway",
|
|
137
|
+
value: runwayText(quarter),
|
|
138
|
+
// "12.0 mo TTM 14.4 mo" would read as one figure: a narrow column keeps "qtr" alone.
|
|
139
|
+
detail: [...dates.map((date) => `qtr to ${date}${ttm}`), `qtr${ttm}`, "qtr"],
|
|
140
|
+
link: FINANCIALS,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
111
144
|
export function buildOverviewStats({
|
|
112
145
|
quote,
|
|
113
146
|
fundamentals,
|
|
@@ -117,13 +150,15 @@ export function buildOverviewStats({
|
|
|
117
150
|
marketCapExchangeRates = new Map(),
|
|
118
151
|
nextEarnings,
|
|
119
152
|
depositaryReceipt = false,
|
|
153
|
+
depositaryPair = null,
|
|
120
154
|
today,
|
|
121
155
|
dividend,
|
|
122
156
|
bond = null,
|
|
157
|
+
runway = null,
|
|
123
158
|
}: {
|
|
124
159
|
quote: Quote | undefined;
|
|
125
160
|
fundamentals: TickerFinancials["fundamentals"] | undefined;
|
|
126
|
-
/** The currency the statements report in, for fundamentals that declare none. */
|
|
161
|
+
/** The currency the statements report in, for fundamentals that declare none on a listing that trades in it. */
|
|
127
162
|
financialCurrency?: TickerFinancials["financialCurrency"];
|
|
128
163
|
quoteCurrency: string;
|
|
129
164
|
baseCurrency: string;
|
|
@@ -132,6 +167,8 @@ export function buildOverviewStats({
|
|
|
132
167
|
nextEarnings?: NextEarnings;
|
|
133
168
|
/** The share count is in depositary receipts, not ordinary shares. */
|
|
134
169
|
depositaryReceipt?: boolean;
|
|
170
|
+
/** The receipt pair the listing is a side of, as Gloom Cloud serves it; `receiptSide` when the listing is the receipt. */
|
|
171
|
+
depositaryPair?: { pair: DepositaryPair; receiptSide: boolean } | null;
|
|
135
172
|
/** The listing's calendar day, YYYY-MM-DD; dates before it are left out. */
|
|
136
173
|
today?: string;
|
|
137
174
|
/** The history the dividend yield reads (useOverviewDividend): a trailing one is measured from its cash, a forward one stops with it; without it the yield stands. */
|
|
@@ -141,9 +178,11 @@ export function buildOverviewStats({
|
|
|
141
178
|
* distribution yield, not its SEC yield, which follows it with its date.
|
|
142
179
|
*/
|
|
143
180
|
bond?: FundBondFacts | null;
|
|
181
|
+
/** Months of cash at the latest balance sheet (utils/cash-runway); shown when the company burns cash. */
|
|
182
|
+
runway?: CashRunway | null;
|
|
144
183
|
}): StatField[] {
|
|
145
184
|
const stats: StatField[] = [];
|
|
146
|
-
const money = (value: number, perShare = false) => formatReportedMoney(value, fundamentalsCurrency({ fundamentals, financialCurrency }), perShare);
|
|
185
|
+
const money = (value: number, perShare = false) => formatReportedMoney(value, fundamentalsCurrency({ fundamentals, financialCurrency, quote }), perShare);
|
|
147
186
|
|
|
148
187
|
// An index's 0 is volume nobody counts, not a quiet session: no Volume row.
|
|
149
188
|
const volume = reportedQuoteVolume(quote);
|
|
@@ -164,15 +203,25 @@ export function buildOverviewStats({
|
|
|
164
203
|
),
|
|
165
204
|
});
|
|
166
205
|
}
|
|
206
|
+
// A count read off a 10-K or 10-Q cover says when it was counted; the source's own is undated.
|
|
207
|
+
const counted = (asOf: string | undefined) => (asOf ? { detail: [`as of ${asOf}`, `as of ${asOf.slice(5)}`] } : {});
|
|
167
208
|
if (fundamentals?.sharesOutstanding) {
|
|
168
209
|
stats.push({
|
|
169
210
|
label: "Shares Out",
|
|
170
211
|
value: formatCompact(fundamentals.sharesOutstanding),
|
|
171
|
-
...(depositaryReceipt ? { detail: ["ADR equivalent", "in ADRs"] } :
|
|
212
|
+
...(depositaryReceipt ? { detail: ["ADR equivalent", "in ADRs"] } : counted(fundamentals.sharesOutstandingAsOf)),
|
|
172
213
|
});
|
|
173
214
|
}
|
|
174
215
|
if (finite(fundamentals?.floatShares) && fundamentals.floatShares > 0) {
|
|
175
|
-
stats.push({ label: "Float", value: formatCompact(fundamentals.floatShares) });
|
|
216
|
+
stats.push({ label: "Float", value: formatCompact(fundamentals.floatShares), ...counted(fundamentals.floatSharesAsOf) });
|
|
217
|
+
}
|
|
218
|
+
// A receipt says how many shares it holds and a home line which receipt holds it, both opening ADR vs Home.
|
|
219
|
+
if (depositaryPair) {
|
|
220
|
+
const { pair, receiptSide } = depositaryPair;
|
|
221
|
+
const count = ratioCount(pair.ratio);
|
|
222
|
+
stats.push(receiptSide
|
|
223
|
+
? { label: "ADR Ratio", value: `1:${count}`, detail: [adrRatioText(pair.ratio)!, `${count} sh per ADR`], link: ADR_PAIR }
|
|
224
|
+
: { label: "ADR", value: pair.receipt, detail: [`1 ADR = ${count} of these share${pair.ratio === 1 ? "" : "s"}`, `1:${count}`], link: ADR_PAIR });
|
|
176
225
|
}
|
|
177
226
|
const trailingPE = liveTrailingPE(quote, fundamentals);
|
|
178
227
|
if (trailingPE != null) {
|
|
@@ -183,7 +232,7 @@ export function buildOverviewStats({
|
|
|
183
232
|
stats.push({ label: "Fwd P/E", value: formatPriceEarnings(forwardPE) });
|
|
184
233
|
}
|
|
185
234
|
if (fundamentals?.eps != null) {
|
|
186
|
-
stats.push({ label: "EPS", value: formatReportedMoney(fundamentals.eps, fundamentalsEpsCurrency({ fundamentals, financialCurrency }), true) });
|
|
235
|
+
stats.push({ label: "EPS", value: formatReportedMoney(fundamentals.eps, fundamentalsEpsCurrency({ fundamentals, financialCurrency, quote }), true) });
|
|
187
236
|
}
|
|
188
237
|
if (fundamentals?.pegRatio != null) {
|
|
189
238
|
stats.push({ label: "PEG", value: formatPriceEarnings(fundamentals.pegRatio, 2) });
|
|
@@ -239,6 +288,8 @@ export function buildOverviewStats({
|
|
|
239
288
|
if (fundamentals?.freeCashFlow != null) {
|
|
240
289
|
stats.push({ label: "FCF", value: money(fundamentals.freeCashFlow) });
|
|
241
290
|
}
|
|
291
|
+
const runwayField = runwayStat(runway);
|
|
292
|
+
if (runwayField) stats.push(runwayField);
|
|
242
293
|
if (fundamentals?.operatingMargin != null) {
|
|
243
294
|
stats.push({ label: "Op Margin", value: formatLevelPercent(fundamentals.operatingMargin) });
|
|
244
295
|
}
|
|
@@ -255,7 +306,10 @@ export function buildOverviewStats({
|
|
|
255
306
|
// At the regular session price, as the market cap above it is, with the check moved beside it.
|
|
256
307
|
const priced = atRegularSessionPrice({ quote, fundamentals }).fundamentals;
|
|
257
308
|
const enterpriseValue = reportedEnterpriseValue(priced);
|
|
258
|
-
|
|
309
|
+
// At or below zero, N/M as a P/E over a loss reads, with why in the space a stat has; valuation gives the full reason.
|
|
310
|
+
if (enterpriseValueNotMeaningful(priced)) {
|
|
311
|
+
stats.push({ label: "EV", value: formatPriceEarnings(NOT_MEANINGFUL), detail: ["cash > cap + debt", "cash > cap"] });
|
|
312
|
+
} else if (fundamentals?.unavailableFields?.includes("enterpriseValue")) {
|
|
259
313
|
stats.push({ label: "EV", value: "—" });
|
|
260
314
|
} else if (enterpriseValue != null) {
|
|
261
315
|
// More than 5% from market cap + debt - cash: the provider's, with the computed figure where it fits.
|
|
@@ -264,7 +318,8 @@ export function buildOverviewStats({
|
|
|
264
318
|
stats.push({
|
|
265
319
|
label: "EV",
|
|
266
320
|
value: formatCompactCurrency(enterpriseValue, quoteCurrency),
|
|
267
|
-
|
|
321
|
+
// An insurer's: its investment book is not netted as cash.
|
|
322
|
+
detail: computed ? [`provider vs ${computed}`, "provider"] : check?.investmentsKept ? ["investments in", "inv. in"] : undefined,
|
|
268
323
|
});
|
|
269
324
|
}
|
|
270
325
|
if (finite(fundamentals?.beta)) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { PerpEquityRow } from "../../perps/equity-row";
|
|
2
|
+
import { PerpMarketsSection } from "../../perps/markets-section";
|
|
3
|
+
import { perpetualListing } from "../../../../tickers/perpetual-listing";
|
|
2
4
|
import { useCallback } from "react";
|
|
3
5
|
import type { TickerResearchTabProps } from "../../../../types/plugin";
|
|
4
6
|
import {
|
|
@@ -46,7 +48,13 @@ export function OverviewResearchTab({ width, height, focused }: TickerResearchTa
|
|
|
46
48
|
onOpenChart={paneId && !lockedToOneTab ? openChart : undefined}
|
|
47
49
|
onOpenFunction={openFunction}
|
|
48
50
|
dividend={dividend}
|
|
49
|
-
perpetuals={ticker ?
|
|
51
|
+
perpetuals={ticker ? (contentWidth: number) => {
|
|
52
|
+
const instrumentType = financials?.quote?.instrumentType ?? ticker.metadata.assetCategory;
|
|
53
|
+
// A contract's own DES shows its funding and premium; a stock or a coin lists its markets across venues.
|
|
54
|
+
return perpetualListing(ticker.metadata.ticker, ticker.metadata.exchange)
|
|
55
|
+
? <PerpEquityRow symbol={ticker.metadata.ticker} exchange={ticker.metadata.exchange} instrumentType={instrumentType} />
|
|
56
|
+
: <PerpMarketsSection symbol={ticker.metadata.ticker} exchange={ticker.metadata.exchange} instrumentType={instrumentType} quote={financials?.quote} width={contentWidth} />;
|
|
57
|
+
} : undefined}
|
|
50
58
|
/>
|
|
51
59
|
);
|
|
52
60
|
}
|
|
@@ -6,13 +6,13 @@ import { mayBeUsEquityOrFundTicker } from "../../../utils/sec";
|
|
|
6
6
|
import { ResearchTradeActions, researchTradeMatches, useResearchTrading } from "../shared/research-trading";
|
|
7
7
|
import { instrumentFromTicker } from "../../../market-data/request-types";
|
|
8
8
|
import { useMemo, type ReactNode } from "react";
|
|
9
|
-
import { EmptyState, PaneLinkMenu, SectionHeading, usePaneNoticeFooter } from "../../../components";
|
|
9
|
+
import { EmptyState, ExternalLinkText, PaneLinkMenu, SectionHeading, usePaneNoticeFooter } from "../../../components";
|
|
10
10
|
import { CompositeChart, pricePointsToResolvedSeries } from "../../../components/chart/composite";
|
|
11
11
|
import { CompanyLogo, resolveCompanyLogoSrc } from "../../../components/company-logo";
|
|
12
12
|
import { bodyLineInk, FigureText, figureLineInk, useFigureCells } from "../../../components/ui/figure";
|
|
13
13
|
import { PriceReturnStrip } from "../../../components/price-performance";
|
|
14
14
|
import { t } from "../../../i18n";
|
|
15
|
-
import {
|
|
15
|
+
import { useFxRateObservations } from "../../../market-data/hooks";
|
|
16
16
|
import { formatMarketPriceWithCurrency, formatSignedMarketPrice, liveQuoteFormatOptions } from "../../../market-data/market/format";
|
|
17
17
|
import { priceSeriesUnit } from "../../../market-data/market/index-level";
|
|
18
18
|
import {
|
|
@@ -24,9 +24,9 @@ import {
|
|
|
24
24
|
quoteSessionLabel,
|
|
25
25
|
} from "../../../market-data/market/status";
|
|
26
26
|
import { appendQuoteToPriceReturnHistory, buildPriceReturnFields } from "../../../market-data/performance";
|
|
27
|
-
import { changeBasisLabel, changeBasisNote, quoteChangeBasis } from "../../../market-data/market/change-basis";
|
|
27
|
+
import { changeBasisLabel, changeBasisNote, quoteChangeBasis, quoteSettleText } from "../../../market-data/market/change-basis";
|
|
28
28
|
import {
|
|
29
|
-
fitFuturesContractLines, futuresContractLines,
|
|
29
|
+
fitFuturesContractLines, futuresContractLines, isFuturesInstrument, futuresPricePer, usdPerMmbtu, usdPerMmbtuText,
|
|
30
30
|
type FuturesContractLine,
|
|
31
31
|
} from "../../../market-data/futures-contract";
|
|
32
32
|
import { useViewport } from "../../../react/input";
|
|
@@ -38,10 +38,11 @@ import type { TickerRecord } from "../../../types/ticker";
|
|
|
38
38
|
import { Box, ScrollBox, Text, useUiCapabilities } from "../../../ui";
|
|
39
39
|
import { publicTickerKey, resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
40
40
|
import { convertCurrency, displayWidth, formatPercentRaw, truncateToDisplayWidth } from "../../../utils/format";
|
|
41
|
-
import { enterpriseValueReconciliationNote } from "../../../utils/fundamentals";
|
|
41
|
+
import { appTtmRate, enterpriseValueReconciliationNote, ttmAtAppRate, ttmConversionNote } from "../../../utils/fundamentals";
|
|
42
42
|
import { atRegularSessionPrice } from "../../../market-data/quotes/regular-session-valuation";
|
|
43
43
|
import { zonedDateKey } from "../../../utils/zoned-date-time";
|
|
44
44
|
import { sharesOutstandingInReceipts } from "../../../utils/depositary-receipt";
|
|
45
|
+
import { isReceiptSide, listingDepositaryPair } from "../../../market-data/depositary-pair";
|
|
45
46
|
import {
|
|
46
47
|
CompactRangeBar,
|
|
47
48
|
FundamentalsGrid,
|
|
@@ -61,6 +62,9 @@ import { describeFundamentalMarketCap } from "../../../utils/market-capitalizati
|
|
|
61
62
|
import { liveFiftyTwoWeekRange, liveMarketCapitalization } from "../../../market-data/quotes/live-valuation";
|
|
62
63
|
import { instrumentTypeLabel } from "../../../tickers/instrument-kind";
|
|
63
64
|
import { ClippedText } from "../../../components/ui/display";
|
|
65
|
+
import { safeExternalUrl } from "../../../utils/external-url";
|
|
66
|
+
import { cashRunway, SHORT_RUNWAY_HISTORY } from "../../../utils/cash-runway";
|
|
67
|
+
import { useOfferingNote } from "./financials/offerings";
|
|
64
68
|
|
|
65
69
|
/** Cells between the Day and 52W ranges when they share a row. */
|
|
66
70
|
const RANGE_PAIR_GAP = 4;
|
|
@@ -83,7 +87,8 @@ function contractField(line: FuturesContractLine): StatField {
|
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
interface OverviewTabProps {
|
|
86
|
-
|
|
90
|
+
/** The contracts on the security, given the width of the overview's content. */
|
|
91
|
+
perpetuals?: ReactNode | ((contentWidth: number) => ReactNode);
|
|
87
92
|
width?: number;
|
|
88
93
|
/** The tab's height; a short one keeps fewer futures contract terms. */
|
|
89
94
|
height?: number;
|
|
@@ -131,19 +136,34 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
131
136
|
const futuresSymbol = quote?.symbol || ticker.metadata.ticker;
|
|
132
137
|
const contractTerms = useFuturesContractTerms(isFuturesInstrument(futuresSymbol, instrumentType) ? futuresSymbol : null);
|
|
133
138
|
const optionRow = useOptionContractRow(ticker);
|
|
134
|
-
const
|
|
139
|
+
const fxObservations = useFxRateObservations([
|
|
135
140
|
baseCurrency,
|
|
136
141
|
ticker.metadata.currency,
|
|
137
142
|
quote?.currency,
|
|
138
143
|
capitalization?.currency,
|
|
144
|
+
// A converted TTM block is shown at the pane's own rate, the one `fx` reports.
|
|
145
|
+
fundamentals?.ttmConversion?.from,
|
|
146
|
+
fundamentals?.financialCurrency,
|
|
139
147
|
...ticker.metadata.positions.map((position) => position.currency),
|
|
140
148
|
]);
|
|
149
|
+
const exchangeRates = useMemo(
|
|
150
|
+
() => new Map([...fxObservations].map(([currency, observation]) => [currency, observation.rate])),
|
|
151
|
+
[fxObservations],
|
|
152
|
+
);
|
|
153
|
+
const ttmRate = appTtmRate(fundamentals, (currency) => fxObservations.get(currency));
|
|
154
|
+
const shownFundamentals = useMemo(
|
|
155
|
+
() => (fundamentals ? ttmAtAppRate(fundamentals, ttmRate) : fundamentals),
|
|
156
|
+
[fundamentals, ttmRate?.rate, ttmRate?.asOf],
|
|
157
|
+
);
|
|
141
158
|
const quoteCurrency = quote?.currency || ticker.metadata.currency || baseCurrency;
|
|
142
159
|
const toBase = (value: number, fromCurrency: string) =>
|
|
143
160
|
convertCurrency(value, fromCurrency, baseCurrency, exchangeRates);
|
|
144
161
|
const sector = ticker.metadata.sector ?? profile?.sector;
|
|
145
162
|
const industry = ticker.metadata.industry ?? profile?.industry;
|
|
146
163
|
const description = profile?.description?.trim();
|
|
164
|
+
// A description quoted from the fund's issuer or its exchange names where it is from.
|
|
165
|
+
const descriptionSource = description && profile?.descriptionSource?.publisher
|
|
166
|
+
&& safeExternalUrl(profile.descriptionSource.url) ? profile.descriptionSource : null;
|
|
147
167
|
const listingVenue = exchangeShortName(
|
|
148
168
|
quote?.tradingExchangeName ?? quote?.listingExchangeName ?? quote?.exchangeName,
|
|
149
169
|
quote?.listingExchangeFullName ?? quote?.fullExchangeName,
|
|
@@ -185,12 +205,21 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
185
205
|
// A provider EV off market cap + debt - cash, or why a withdrawn one is unavailable, at the
|
|
186
206
|
// regular session price the EV beside it is shown at.
|
|
187
207
|
const enterpriseValueNote = enterpriseValueReconciliationNote(atRegularSessionPrice({ quote, fundamentals }).fundamentals);
|
|
208
|
+
// Months of cash, for a company that burns it, and an offering since its balance sheet that the cash is not in yet.
|
|
209
|
+
const runway = useMemo(() => financials ? cashRunway(financials) : null, [financials]);
|
|
210
|
+
const runwayOfferingNote = useOfferingNote(ticker.metadata.ticker, ticker.metadata.exchange, runway?.periodEnd ?? null, runway?.trailing?.kind === "months");
|
|
211
|
+
// A converted TTM block names what it was converted from, at the pane's rate and its time.
|
|
212
|
+
const ttmNote = [shownFundamentals?.revenue, shownFundamentals?.netIncome, shownFundamentals?.freeCashFlow].some((value) => value != null)
|
|
213
|
+
? ttmConversionNote(shownFundamentals) : undefined;
|
|
188
214
|
usePaneNoticeFooter({
|
|
189
215
|
registrationId: "overview-notices",
|
|
190
216
|
notices: [
|
|
191
217
|
...(!quote && financials ? [t("Current quote unavailable. Other research data is still available.")] : []),
|
|
218
|
+
...(runwayOfferingNote ? [runwayOfferingNote] : []),
|
|
219
|
+
...(runway?.trailingGap === "short-history" ? [`Runway TTM: ${SHORT_RUNWAY_HISTORY}.`] : []),
|
|
192
220
|
...(priceSeries.warning ? [priceSeries.warning] : []),
|
|
193
221
|
...(enterpriseValueNote ? [enterpriseValueNote] : []),
|
|
222
|
+
...(ttmNote ? [ttmNote] : []),
|
|
194
223
|
...(capitalization?.provenance.kind === "fundamentals" && !capitalization.live
|
|
195
224
|
? [`Market cap: ${describeFundamentalMarketCap(capitalization.provenance)}.`] : []),
|
|
196
225
|
],
|
|
@@ -209,7 +238,7 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
209
238
|
const extendedQuote = getExtendedSessionDisplay(quote);
|
|
210
239
|
// A price in cents says what it is per (314.95¢/lb), and the move what it is measured from (vs Fri 16 Oct close).
|
|
211
240
|
const quotePriceText = sessionQuote
|
|
212
|
-
? `${formatMarketPriceWithCurrency(sessionQuote.price, quote?.currency, moneyOptions)}${
|
|
241
|
+
? `${formatMarketPriceWithCurrency(sessionQuote.price, quote?.currency, moneyOptions)}${futuresPricePer(contractTerms, quote?.currency)}` : "";
|
|
213
242
|
// Nor a move: the close it ended on is where it stays.
|
|
214
243
|
const quoteChangeText = sessionQuote && !delisted ? formatSignedMarketPrice(sessionQuote.change, moneyOptions) : "";
|
|
215
244
|
const quotePercentText = sessionQuote && !delisted ? `(${formatPercentRaw(sessionQuote.changePercent)})` : "";
|
|
@@ -240,9 +269,18 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
240
269
|
// The exchange settlement, dated by its session: a futures price is its latest trade.
|
|
241
270
|
const settleLabel = t("Settle");
|
|
242
271
|
const settleText = contractTerms
|
|
243
|
-
? truncateToDisplayWidth(
|
|
272
|
+
? truncateToDisplayWidth(quoteSettleText(quote, contractTerms),
|
|
244
273
|
Math.max(1, quoteTextWidth - displayWidth(settleLabel) - 1))
|
|
245
274
|
: "";
|
|
275
|
+
// European gas beside Henry Hub: "≈ $30.832/MMBtu at EUR/USD 1.1650", at the app's rate, a conversion that says so.
|
|
276
|
+
const inUsdLabel = t("In USD");
|
|
277
|
+
const gasCurrency = quote?.currency?.trim().toUpperCase() ?? "";
|
|
278
|
+
const gasUsdPerUnit = gasCurrency ? convertCurrency(1, gasCurrency, "USD", exchangeRates) : Number.NaN;
|
|
279
|
+
const gasInUsd = sessionQuote && gasCurrency ? usdPerMmbtu(sessionQuote.price, contractTerms, gasCurrency, gasUsdPerUnit) : null;
|
|
280
|
+
const inUsdText = gasInUsd != null
|
|
281
|
+
? truncateToDisplayWidth(usdPerMmbtuText({ value: gasInUsd, currency: gasCurrency, usdPerUnit: gasUsdPerUnit }),
|
|
282
|
+
Math.max(1, quoteTextWidth - displayWidth(inUsdLabel) - 1))
|
|
283
|
+
: "";
|
|
246
284
|
const quoteChangeCells = delisted ? 0 : figureCells(quoteChangeText, "sub") + 1 + figureCells(quotePercentText, "sub");
|
|
247
285
|
const stackQuoteChange = quoteChangeCells > quoteTextWidth;
|
|
248
286
|
const stackQuoteSummary = figureCells(quotePriceText) + 2 + quoteChangeCells > quoteTextWidth;
|
|
@@ -285,9 +323,10 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
285
323
|
const optionFields = optionTarget?.isOptionTicker ? optionContractFields(optionTarget, optionRow, quoteCurrency) : [];
|
|
286
324
|
const contractFields = futuresFields.length > 0 ? futuresFields : optionFields;
|
|
287
325
|
const contractGridColumns = futuresFields.length > 0 ? contractColumns : textGridColumns(optionFields, contentWidth);
|
|
326
|
+
const depositaryPair = listingDepositaryPair(financials);
|
|
288
327
|
const stats = buildOverviewStats({
|
|
289
328
|
quote,
|
|
290
|
-
fundamentals,
|
|
329
|
+
fundamentals: shownFundamentals,
|
|
291
330
|
financialCurrency: financials?.financialCurrency,
|
|
292
331
|
quoteCurrency,
|
|
293
332
|
baseCurrency,
|
|
@@ -295,10 +334,12 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
295
334
|
marketCapExchangeRates: exchangeRates,
|
|
296
335
|
nextEarnings: financials?.nextEarnings,
|
|
297
336
|
depositaryReceipt: sharesOutstandingInReceipts(quote, fundamentals, description),
|
|
337
|
+
depositaryPair: depositaryPair ? { pair: depositaryPair, receiptSide: isReceiptSide(financials) } : null,
|
|
298
338
|
// Report and ex-dividend dates are the listing's calendar days.
|
|
299
339
|
today: zonedDateKey(Date.now(), chartTimeZone ?? "America/New_York"),
|
|
300
340
|
dividend,
|
|
301
341
|
bond: fundFacts?.bond ?? null,
|
|
342
|
+
runway,
|
|
302
343
|
});
|
|
303
344
|
const profileFields = buildProfileFields({
|
|
304
345
|
// The contract section names an option's type.
|
|
@@ -308,8 +349,10 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
308
349
|
profile,
|
|
309
350
|
isin: ticker.metadata.isin,
|
|
310
351
|
});
|
|
352
|
+
// Bars and the quote are dated on the listing's clock.
|
|
311
353
|
const performanceFields = buildPriceReturnFields(
|
|
312
354
|
appendQuoteToPriceReturnHistory(financials?.priceHistory ?? [], historyQuote),
|
|
355
|
+
ticker.metadata.exchange || quote?.listingExchangeName || quote?.exchangeName || undefined,
|
|
313
356
|
);
|
|
314
357
|
const hasPerformance = performanceFields.some((field) => field.value != null || field.unavailableReason);
|
|
315
358
|
const positionRows = buildPositionRows({
|
|
@@ -414,6 +457,12 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
414
457
|
<Text fg={colors.text}>{settleText}</Text>
|
|
415
458
|
</Box>
|
|
416
459
|
)}
|
|
460
|
+
{inUsdText && (
|
|
461
|
+
<Box flexDirection="row" gap={1} minWidth={0} overflow="hidden">
|
|
462
|
+
<Text flexShrink={0} fg={colors.textDim}>{inUsdLabel}</Text>
|
|
463
|
+
<Text fg={colors.textDim}>{inUsdText}</Text>
|
|
464
|
+
</Box>
|
|
465
|
+
)}
|
|
417
466
|
{metadataParts.length > 0 && (
|
|
418
467
|
<Text fg={colors.textDim}>{metadataParts.join(" | ")}</Text>
|
|
419
468
|
)}
|
|
@@ -431,7 +480,7 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
431
480
|
)}
|
|
432
481
|
</Box>
|
|
433
482
|
|
|
434
|
-
{perpetuals && <PaneLinkMenu>{perpetuals}</PaneLinkMenu>}
|
|
483
|
+
{perpetuals && <PaneLinkMenu>{typeof perpetuals === "function" ? perpetuals(contentWidth) : perpetuals}</PaneLinkMenu>}
|
|
435
484
|
|
|
436
485
|
{(hasDayRange || yearRange) && quote && (
|
|
437
486
|
<Box flexDirection={rangeInline ? "row" : "column"} gap={rangeInline ? RANGE_PAIR_GAP : 0} width={nativePaneChrome ? undefined : contentWidth}>
|
|
@@ -553,6 +602,14 @@ function ResolvedOverviewTab({ width, height, focused = false, ticker, financial
|
|
|
553
602
|
<SectionHeading title={t("Description")} />
|
|
554
603
|
{/* The desktop wraps it at the pane's own width, so it follows a resize to the pixel. */}
|
|
555
604
|
<Text fg={colors.text} width={nativePaneChrome ? undefined : contentWidth} wrapMode="word" wrapText>{description}</Text>
|
|
605
|
+
{descriptionSource && (
|
|
606
|
+
<PaneLinkMenu>
|
|
607
|
+
<Box flexDirection="row" width={nativePaneChrome ? undefined : contentWidth}>
|
|
608
|
+
<Text flexShrink={0} fg={colors.textDim}>{`${t("Source")}: `}</Text>
|
|
609
|
+
<ExternalLinkText url={descriptionSource.url} label={descriptionSource.publisher} />
|
|
610
|
+
</Box>
|
|
611
|
+
</PaneLinkMenu>
|
|
612
|
+
)}
|
|
556
613
|
</Box>
|
|
557
614
|
)}
|
|
558
615
|
</Box>
|
|
@@ -227,6 +227,17 @@ export function TickerResearchPane({ focused, width, height }: PaneProps) {
|
|
|
227
227
|
);
|
|
228
228
|
|
|
229
229
|
const visibleTabIdKey = allTabs.map((tab) => tab.id).join("\0");
|
|
230
|
+
// A function that opens DES on one of its tabs (ADR) stamps the tab on the instance (command-tab.ts):
|
|
231
|
+
// it is shown once it is there to show, and once per stamp, so a later choice in the pane stands.
|
|
232
|
+
const requestedTabId = paneInstance?.params?.tab ?? null;
|
|
233
|
+
const requestedTabAt = paneInstance?.params?.tabAt ?? "";
|
|
234
|
+
const [consumedTabAt, setConsumedTabAt] = usePaneStateValue<string>("commandTabAt", "");
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
if (!requestedTabId || !requestedTabAt || requestedTabAt === consumedTabAt) return;
|
|
237
|
+
if (!allTabs.some((tab) => tab.id === requestedTabId)) return;
|
|
238
|
+
setConsumedTabAt(requestedTabAt);
|
|
239
|
+
setActiveTabId(requestedTabId);
|
|
240
|
+
}, [consumedTabAt, requestedTabAt, requestedTabId, setActiveTabId, setConsumedTabAt, visibleTabIdKey]);
|
|
230
241
|
// A quote tick re-renders this pane; the tab strip only has to re-render
|
|
231
242
|
// when a tab appears, disappears, or is renamed.
|
|
232
243
|
const tabItemsKey = allTabs.map((tab) => `${tab.id}:${tab.name}`).join("\0");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PaneFooterSegment } from "../../../components/layout/pane/footer";
|
|
2
2
|
import { t } from "../../../i18n";
|
|
3
|
-
import { isQuoteStaleForCurrentSession } from "../../../market-data/quotes/freshness";
|
|
3
|
+
import { isQuoteStaleForCurrentSession, noPrintsTodaySince } from "../../../market-data/quotes/freshness";
|
|
4
4
|
import { formatQuoteNavAsOf } from "../../../market-data/quotes/time";
|
|
5
5
|
import { delistingLabel } from "../../../market-data/quotes/delisting";
|
|
6
6
|
import type { Quote } from "../../../types/financials";
|
|
@@ -17,12 +17,17 @@ export function tickerQuoteFooterInfo(
|
|
|
17
17
|
// A listing that no longer trades: its quote is its last trade, said once with its date.
|
|
18
18
|
info.push({ id: "ticker-research-stale", parts: [{ text: delistingLabel(quote.delisting), tone: "warning" }] });
|
|
19
19
|
} else if (isQuoteStaleForCurrentSession(quote)) {
|
|
20
|
-
|
|
20
|
+
// In a session the calendar has open with nothing printed in it, the warning says since when.
|
|
21
|
+
const quiet = noPrintsTodaySince(quote) != null;
|
|
22
|
+
const status: PaneFooterSegment = {
|
|
23
|
+
id: "ticker-research-stale",
|
|
24
|
+
parts: [{ text: quiet ? t("No prints today") : t("Stale quote"), tone: "warning" }],
|
|
25
|
+
};
|
|
21
26
|
const timestamp = new Date(quote!.lastUpdated);
|
|
22
27
|
if (navAsOf) {
|
|
23
28
|
status.parts.push({ text: navAsOf, tone: "muted" });
|
|
24
29
|
} else if (width != null && quote!.lastUpdated > 0 && Number.isFinite(timestamp.getTime())) {
|
|
25
|
-
const sourceTime = `${timestamp.toISOString().slice(0, 16).replace("T", " ")}Z`;
|
|
30
|
+
const sourceTime = `${quiet ? "since " : ""}${timestamp.toISOString().slice(0, 16).replace("T", " ")}Z`;
|
|
26
31
|
const accessWidth = access ? displayWidth(access.parts.map((part) => part.text).join(" ")) + 1 : 0;
|
|
27
32
|
// Keep the warning and the existing entitlement action intact in narrow panes.
|
|
28
33
|
if (displayWidth(status.parts[0]!.text) + 1 + sourceTime.length + accessWidth <= width - 2) {
|
|
@@ -2,6 +2,9 @@ import type { TickerFinancials } from "../../../types/financials";
|
|
|
2
2
|
import type { TickerResearchTabDef } from "../../../types/plugin";
|
|
3
3
|
import { FinancialsResearchTab } from "./financials/pane";
|
|
4
4
|
import { OverviewResearchTab } from "./overview/pane";
|
|
5
|
+
import { AdrPairResearchTab } from "./adr-pair/tab";
|
|
6
|
+
import { ADR_PAIR_TAB_ID } from "./adr-pair/model";
|
|
7
|
+
import { listingDepositaryPair } from "../../../market-data/depositary-pair";
|
|
5
8
|
|
|
6
9
|
function hasStatementFinancials(financials: TickerFinancials | null | undefined): boolean {
|
|
7
10
|
return (financials?.annualStatements.length ?? 0) > 0 || (financials?.quarterlyStatements.length ?? 0) > 0;
|
|
@@ -29,4 +32,12 @@ export const TICKER_RESEARCH_BUILTIN_TABS: TickerResearchTabDef[] = [
|
|
|
29
32
|
component: FinancialsResearchTab,
|
|
30
33
|
isVisible: ({ financials }) => hasStatementFinancials(financials),
|
|
31
34
|
},
|
|
35
|
+
{
|
|
36
|
+
// Only a listing Gloom Cloud pairs with a receipt has it, so every other DES is unchanged.
|
|
37
|
+
id: ADR_PAIR_TAB_ID,
|
|
38
|
+
name: "ADR vs Home",
|
|
39
|
+
order: 21,
|
|
40
|
+
component: AdrPairResearchTab,
|
|
41
|
+
isVisible: ({ financials }) => !!listingDepositaryPair(financials),
|
|
42
|
+
},
|
|
32
43
|
];
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./model";
|
|
13
13
|
import { abortable, abortError } from "../../../utils/async-deadline";
|
|
14
14
|
import { errorMessage } from "../../../utils/errors";
|
|
15
|
-
import { findListedExpiry, unlistedExpiryText } from "../../../utils/option-expiry";
|
|
15
|
+
import { expiredExpiryText, findListedExpiry, isLiveOptionExpiry, liveOptionExpiries, unlistedExpiryText } from "../../../utils/option-expiry";
|
|
16
16
|
import { optionModelSpot } from "../options/model-spot";
|
|
17
17
|
|
|
18
18
|
const DEFAULT_SURFACE_EXPIRY_LIMIT = 18;
|
|
@@ -217,8 +217,7 @@ export async function loadVolatilitySurface(
|
|
|
217
217
|
catalogueError = initial.error?.message ?? null;
|
|
218
218
|
catalogueReason = initial.error?.reasonCode;
|
|
219
219
|
if (!chain) catalogueError ??= "Options expiry catalogue unavailable";
|
|
220
|
-
catalogue =
|
|
221
|
-
Number.isFinite(expiration) && expiration > 0 && daysToExpiryFrom(expiration, now) > 0))].sort((a, b) => a - b);
|
|
220
|
+
catalogue = liveOptionExpiries(chain?.expirationDates ?? [], now, request.instrument.exchange);
|
|
222
221
|
// A typed date is that day's UTC midnight; the catalogue's stamp for the
|
|
223
222
|
// same expiry is matched by calendar date, as OMON matches it.
|
|
224
223
|
const required = [...new Set([...(request.requiredExpiries ?? []), ...(request.expiries ?? [])]
|
|
@@ -227,8 +226,10 @@ export async function loadVolatilitySurface(
|
|
|
227
226
|
const listed = new Set(catalogue);
|
|
228
227
|
selected = [...new Set([...request.expiries ? [] : selectSurfaceExpiries(catalogue, limit, now),
|
|
229
228
|
...required.filter((expiration) => listed.has(expiration))])].sort((a, b) => a - b);
|
|
229
|
+
// An expiry whose last session has closed is named as expired, with the nearest live one to pick.
|
|
230
230
|
requiredFailures = required.filter((expiration) => !listed.has(expiration)).map((expiration) => ({
|
|
231
|
-
expiration, message: unlistedExpiryText(expiration, catalogue)
|
|
231
|
+
expiration, message: isLiveOptionExpiry(expiration, now, request.instrument.exchange) ? unlistedExpiryText(expiration, catalogue)
|
|
232
|
+
: expiredExpiryText(expiration, catalogue, now, { exchange: request.instrument.exchange }),
|
|
232
233
|
}));
|
|
233
234
|
if (chain && catalogue.length === 0) catalogueError ??= "No unexpired option expiries available";
|
|
234
235
|
} catch (error) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Quote } from "../../../types/financials";
|
|
2
2
|
import type { HeadlessBundleSection, HeadlessPaneDefinition, HeadlessPaneFreshness, HeadlessPaneLoadArgs, HeadlessPaneRow } from "../../../types/plugin";
|
|
3
3
|
import {
|
|
4
|
-
expirationOptionSeconds,
|
|
4
|
+
expirationOptionSeconds, expiredExpiryText, findListedExpiry, isLiveOptionExpiry, OPTION_EXPIRATION_FORMAT, OPTION_EXPIRATION_PLACEHOLDER,
|
|
5
|
+
readOptionExpiration, unlistedExpiryText,
|
|
5
6
|
} from "../../../utils/option-expiry";
|
|
6
7
|
import { DATE_OPTION_EXAMPLES } from "../../../utils/calendar-date";
|
|
7
8
|
import { IMPLIED_VOL_WORDS, skewHeader } from "../iv-history/format";
|
|
@@ -181,10 +182,18 @@ export const volSurfaceHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
181
182
|
limit: Number(args.options.limit), signal: ctx.signal,
|
|
182
183
|
requiredExpiries: requested == null ? [] : [requested],
|
|
183
184
|
}, createSurfaceDependencies(ctx.marketData, ctx.apiClient)));
|
|
185
|
+
// An expired --expiration names the flag that asks for the nearest live one.
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
if (requested != null && !isLiveOptionExpiry(requested, now, instrument.exchange)) {
|
|
188
|
+
const message = expiredExpiryText(requested, snapshot.catalogue, now, { exchange: instrument.exchange, flag: "expiration" });
|
|
189
|
+
snapshot = { ...snapshot, failures: snapshot.failures.map((failure) => failure.expiration === requested ? { ...failure, message } : failure) };
|
|
190
|
+
}
|
|
184
191
|
}
|
|
185
192
|
const available = snapshot.expiries.some((expiry) => expiry.fit);
|
|
186
|
-
|
|
187
|
-
|
|
193
|
+
// An expiry that failed as the whole surface did (no connection) is not listed again under its own date.
|
|
194
|
+
const surfaceWide = new Set(snapshot.failures.filter((failure) => failure.expiration == null).map((failure) => failure.message));
|
|
195
|
+
const loadErrors = snapshot.failures.filter((failure) => failure.expiration == null || !surfaceWide.has(failure.message))
|
|
196
|
+
.map((failure) => failure.expiration == null ? failure.message : `${expiryLabel(failure.expiration)}: ${failure.message}`);
|
|
188
197
|
// A symbol with no option chain at all says what became of it when something did (FB is a fund now,
|
|
189
198
|
// Meta trades as META) in place of the chain's own error; a chain without clean quotes is the symbol's own.
|
|
190
199
|
const fate = !snapshot.stored && !available && snapshot.catalogue.length === 0
|
|
@@ -613,8 +613,10 @@ export function buildSurfaceGrid(snapshot: SurfaceSnapshot, options: SurfaceGrid
|
|
|
613
613
|
: axis === "strike" ? coordinate : deltaNeutralStrike(targetForward, tenor.years, (k) => at(k)?.volatility ?? null);
|
|
614
614
|
if (strike === null) return unavailable();
|
|
615
615
|
if (axis === "delta" && coordinate !== 0) {
|
|
616
|
-
|
|
617
|
-
|
|
616
|
+
// The quoted strikes against each expiry's forward as it is now, the one its smile is read on: a report's
|
|
617
|
+
// forward is rounded after the points were placed, and the stored log-moneyness would land past the quotes.
|
|
618
|
+
let low = Math.min(...available.map((expiry) => logForwardMoneyness(expiry.points[0]!.strike, expiry.forward!)!));
|
|
619
|
+
let high = Math.max(...available.map((expiry) => logForwardMoneyness(expiry.points.at(-1)!.strike, expiry.forward!)!));
|
|
618
620
|
const delta = (k: number) => {
|
|
619
621
|
const value = at(k);
|
|
620
622
|
return value == null ? null : optionDelta({ spot: snapshot.spot, years: tenor.years,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PERIOD_BASE_MAX_GAP_DAYS, periodBaseDay } from "../../../market-data/market/period-return";
|
|
1
2
|
import type { CloudFredObservationPayload, CloudFredSeriesInfoPayload } from "../../../api-client";
|
|
2
3
|
import type { PricePoint } from "../../../types/financials";
|
|
3
4
|
import { VOLATILITY_CURVE_INDICES, VOLATILITY_INDICES } from "../shared/volatility-indices";
|
|
@@ -354,21 +355,15 @@ export interface VolatilityCurveLookback {
|
|
|
354
355
|
values: Partial<Record<string, number>>;
|
|
355
356
|
}
|
|
356
357
|
|
|
357
|
-
/** A week back is seven calendar days; a month back is the same day of the previous month, or its last day. */
|
|
358
|
+
/** A week back is seven calendar days; a month back is the same day of the previous month, or its last day (periodBaseDay). */
|
|
358
359
|
export function volatilityLookbackDate(date: string, id: VolatilityLookbackId): string {
|
|
359
|
-
|
|
360
|
-
const target = new Date(`${date}T00:00:00.000Z`);
|
|
361
|
-
const day = target.getUTCDate();
|
|
362
|
-
target.setUTCDate(1);
|
|
363
|
-
target.setUTCMonth(target.getUTCMonth() - 1);
|
|
364
|
-
target.setUTCDate(Math.min(day, new Date(Date.UTC(target.getUTCFullYear(), target.getUTCMonth() + 1, 0)).getUTCDate()));
|
|
365
|
-
return target.toISOString().slice(0, 10);
|
|
360
|
+
return periodBaseDay(date, id);
|
|
366
361
|
}
|
|
367
362
|
|
|
368
363
|
/**
|
|
369
364
|
* The curve a week and a month before its date, read from the same daily
|
|
370
365
|
* histories and aligned the same way: the last date on or before the look-back
|
|
371
|
-
* where the 30D and 3M both closed, else where two tenors did, within
|
|
366
|
+
* where the 30D and 3M both closed, else where two tenors did, within a market closure of it (PERIOD_BASE_MAX_GAP_DAYS).
|
|
372
367
|
* A tenor without a close on that date is a gap, never a neighbouring day.
|
|
373
368
|
*/
|
|
374
369
|
export function volatilityCurveLookbacks(data: Pick<VolatilityData, "curve" | "board" | "fred">): VolatilityCurveLookback[] {
|
|
@@ -382,7 +377,7 @@ export function volatilityCurveLookbacks(data: Pick<VolatilityData, "curve" | "b
|
|
|
382
377
|
}));
|
|
383
378
|
return (["1W", "1M"] as const).map((id) => {
|
|
384
379
|
const target = volatilityLookbackDate(curve.date!, id);
|
|
385
|
-
const floor = new Date(Date.parse(target) -
|
|
380
|
+
const floor = new Date(Date.parse(target) - PERIOD_BASE_MAX_GAP_DAYS * DAY_MS).toISOString().slice(0, 10);
|
|
386
381
|
const counts = new Map<string, number>();
|
|
387
382
|
for (const history of histories.values()) for (const day of history.keys()) {
|
|
388
383
|
if (day >= floor && day <= target) counts.set(day, (counts.get(day) ?? 0) + 1);
|