gloomberb 0.17.5 → 0.18.0
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 +2 -0
- package/README.zh-CN.md +2 -0
- package/package.json +8 -1
- package/patches/electrobun@1.18.1.patch +74 -0
- package/src/account/auth-model.ts +3 -2
- package/src/account/device-signin-dialog.tsx +38 -13
- package/src/account/device-signin.ts +2 -1
- package/src/account/upgrade-dialog.tsx +6 -2
- package/src/api-client/askg.ts +5 -3
- package/src/api-client/bank-figures.ts +73 -0
- package/src/api-client/chat.ts +9 -0
- package/src/api-client/commodity-balances.ts +77 -0
- package/src/api-client/credit-boards.ts +21 -1
- package/src/api-client/crypto-markets.ts +88 -1
- package/src/api-client/data.ts +135 -6
- package/src/api-client/debt-maturities.ts +18 -0
- package/src/api-client/earnings.ts +10 -0
- package/src/api-client/equity-screener.ts +3 -0
- package/src/api-client/errors.ts +13 -0
- package/src/api-client/fund-facts.ts +72 -0
- package/src/api-client/futures-curve.ts +26 -3
- package/src/api-client/geo.ts +11 -1
- package/src/api-client/index.ts +30 -2
- package/src/api-client/insider-signals.ts +159 -0
- package/src/api-client/market-discovery.ts +1 -1
- package/src/api-client/normalizers.ts +2 -0
- package/src/api-client/paths.ts +28 -0
- package/src/api-client/request.ts +11 -3
- package/src/api-client/research-activity.ts +15 -8
- package/src/api-client/socket.ts +16 -3
- package/src/api-client/supply-chain-graph.ts +2 -2
- package/src/api-client/supply-chain.ts +8 -0
- package/src/api-client/tape.ts +12 -0
- package/src/api-client/types.ts +91 -3
- package/src/api-client/upgrade-experiment.ts +4 -3
- package/src/api-client/wall-experiments.ts +5 -3
- package/src/api-client/wall-summary.ts +3 -1
- package/src/api-client/web-experiments.ts +5 -2
- package/src/api-client/yield-curves.ts +17 -0
- package/src/app/command-bar-intro.ts +38 -0
- package/src/app/keybindings/actions.ts +1 -1
- package/src/app/pane-runtime/pane-template-runtime.ts +35 -7
- package/src/app/pane-runtime/plugin-bindings.ts +4 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +4 -14
- package/src/app/pane-runtime/ticker-open-target.ts +31 -0
- package/src/app/runtime/broker-import.ts +23 -21
- package/src/app/runtime/desktop-deeplink.ts +3 -4
- package/src/app/runtime/plugin-bindings.ts +16 -9
- package/src/app/runtime/startup.ts +3 -4
- package/src/app/runtime/ticker-refresh.ts +13 -12
- package/src/app/runtime/update.ts +17 -3
- package/src/architecture/core-builtin-allowlist.json +2 -13
- package/src/architecture/silent-catch-allowlist.json +3 -0
- package/src/architecture/ui-literals-allowlist.json +186 -0
- package/src/architecture/ui-tokens-allowlist.json +40 -0
- package/src/ask-gloom/pane-context.ts +3 -1
- package/src/brokers/broker-portfolio-sync.ts +66 -0
- package/src/brokers/signed-in/catalog.ts +2 -1
- package/src/brokers/signed-in/client.ts +7 -2
- package/src/brokers/signed-in/sign-in-dialog.tsx +120 -26
- package/src/brokers/signed-in/sign-in.ts +22 -20
- package/src/brokers/sync-broker-instance.ts +77 -42
- package/src/capabilities/chart-series.ts +2 -0
- package/src/capabilities/registry.ts +1 -3
- package/src/cli/bank-section.ts +147 -0
- package/src/cli/base-converter.ts +5 -2
- package/src/cli/board-coins.ts +70 -0
- package/src/cli/commands/fred-series.ts +90 -0
- package/src/cli/commands/market.ts +434 -96
- package/src/cli/commands/news-search.ts +35 -2
- package/src/cli/commands/options-chain.ts +25 -9
- package/src/cli/commands/options-leaps.ts +3 -3
- package/src/cli/commands/overview.ts +130 -40
- package/src/cli/commands/plugins.ts +1 -0
- package/src/cli/commands/search.ts +87 -24
- package/src/cli/commands/system.ts +5 -2
- package/src/cli/commands/ticker.ts +361 -64
- package/src/cli/context.ts +15 -1
- package/src/cli/desktop-pane-shot.ts +11 -3
- package/src/cli/earnings-calendar.ts +2 -1
- package/src/cli/errors.ts +25 -2
- package/src/cli/export-source.ts +18 -3
- package/src/cli/fx-pair.ts +77 -0
- package/src/cli/glossary.ts +196 -14
- package/src/cli/history-rows.ts +84 -19
- package/src/cli/index-roots.ts +26 -0
- package/src/cli/index.ts +57 -20
- package/src/cli/known-gaps.ts +156 -22
- package/src/cli/listing-arg.ts +217 -150
- package/src/cli/listing-suggestion.ts +7 -23
- package/src/cli/name-entries.ts +76 -0
- package/src/cli/not-a-ticker.ts +15 -6
- package/src/cli/pane-functions/access-gate.ts +22 -0
- package/src/cli/pane-functions/capabilities.ts +62 -4
- package/src/cli/pane-functions/catalog.ts +144 -39
- package/src/cli/pane-functions/data.ts +6 -5
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +3 -3
- package/src/cli/pane-functions/freshness.ts +93 -17
- package/src/cli/pane-functions/function-help.ts +20 -17
- package/src/cli/pane-functions/headless.ts +187 -40
- package/src/cli/pane-functions/index.ts +126 -12
- package/src/cli/pane-functions/options.ts +17 -3
- package/src/cli/pane-functions/report-notices.ts +17 -3
- package/src/cli/pane-functions/resolver.ts +74 -18
- package/src/cli/pane-functions/screenshot.ts +126 -23
- package/src/cli/pane-functions/shot-options.ts +68 -0
- package/src/cli/perpetual-contract.ts +3 -1
- package/src/cli/report-tables.ts +21 -6
- package/src/cli/result.ts +2 -0
- package/src/cli/series-search.ts +6 -1
- package/src/cli/staged-tickers.ts +5 -0
- package/src/cli/statement-filings.ts +261 -0
- package/src/cli/symbol-args.ts +47 -8
- package/src/cli/symbol-list.ts +9 -2
- package/src/cli/symbol-rows.ts +269 -29
- package/src/cli/ticker-resolution.ts +148 -35
- package/src/cli/treasury-yields.ts +86 -0
- package/src/cli/types.ts +3 -0
- package/src/cli/uncovered-instrument.ts +20 -0
- package/src/cli/unknown-command.ts +18 -0
- package/src/components/chart/composite/axis-overlays.tsx +16 -9
- package/src/components/chart/composite/composite-chart.tsx +163 -23
- package/src/components/chart/composite/downsample.ts +19 -3
- package/src/components/chart/composite/format.ts +13 -0
- package/src/components/chart/composite/legend.tsx +161 -68
- package/src/components/chart/composite/panel-bitmap.ts +8 -2
- package/src/components/chart/composite/panel-labels.ts +38 -0
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +28 -10
- package/src/components/chart/composite/price-axis-labels.tsx +16 -3
- package/src/components/chart/composite/scene.ts +60 -2
- package/src/components/chart/composite/series-axis-tags.tsx +67 -0
- package/src/components/chart/composite/toolbar.tsx +12 -7
- package/src/components/chart/composite/tools.ts +2 -2
- package/src/components/chart/composite/types.ts +34 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +28 -1
- package/src/components/chart/core/view-reset.ts +46 -0
- package/src/components/chart/curve/curve-surface.tsx +1 -1
- package/src/components/chart/static/series.ts +39 -0
- package/src/components/chart/static/trail-chart-surface.tsx +2 -1
- package/src/components/command-bar/commands/collection-list.ts +45 -15
- package/src/components/command-bar/commands/collection.ts +11 -4
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/registry.ts +2 -2
- package/src/components/command-bar/list/badge.ts +4 -3
- package/src/components/command-bar/list/model.ts +12 -0
- package/src/components/command-bar/list/view.tsx +1 -1
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/panel/index.tsx +19 -8
- package/src/components/command-bar/panel/native-surface.ts +6 -4
- package/src/components/command-bar/panel/prompt-example.ts +22 -0
- package/src/components/command-bar/routes/root/command-items.ts +1 -1
- package/src/components/command-bar/routes/root/pick-prefetch.ts +38 -0
- package/src/components/command-bar/routes/root/provider-search.ts +9 -9
- package/src/components/command-bar/routes/root/results.ts +13 -0
- package/src/components/command-bar/routes/root/runtime.ts +3 -0
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +3 -1
- package/src/components/command-bar/routes/root/shortcut-items.ts +1 -1
- package/src/components/command-bar/routes/root/start-here.ts +90 -0
- package/src/components/command-bar/routes/ticker-search/actions.ts +34 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +42 -3
- package/src/components/command-bar/routes/ticker-search/route.ts +3 -10
- package/src/components/command-bar/surface/index.tsx +5 -0
- package/src/components/command-bar/theme-picker.tsx +3 -1
- package/src/components/command-bar/workflow/builtin.ts +5 -1
- package/src/components/command-bar/workflow/collection-actions.ts +23 -13
- package/src/components/command-bar/workflow/ops.ts +25 -3
- package/src/components/command-bar/workflow/pane-reuse.ts +3 -2
- package/src/{plugins/builtin/portfolio-list/command-bar.ts → components/command-bar/workflow/portfolio-position.ts} +42 -9
- package/src/components/command-bar/workflow/tickers.ts +7 -5
- package/src/components/feedback-dialog.tsx +1 -1
- package/src/components/form-modal/broker-step.tsx +7 -63
- package/src/components/form-modal/content.tsx +7 -2
- package/src/components/form-modal/field-row.tsx +6 -8
- package/src/components/form-modal/host.tsx +3 -3
- package/src/components/form-modal/model.ts +3 -0
- package/src/components/form-modal/routes.ts +17 -2
- package/src/components/index.ts +6 -6
- package/src/components/input-search-bar.tsx +43 -6
- package/src/components/layout/detached-pane-shell.tsx +0 -1
- package/src/components/layout/floating-pane.tsx +0 -1
- package/src/components/layout/header.tsx +8 -7
- package/src/components/layout/pane/content.tsx +11 -8
- package/src/components/layout/pane/footer/index.tsx +7 -4
- package/src/components/layout/pane/footer/model.ts +28 -2
- package/src/components/layout/pane/header.tsx +9 -19
- package/src/components/layout/pane/index.tsx +0 -1
- package/src/components/layout/pane/instrument-coverage-gate.tsx +57 -0
- package/src/components/layout/pane/pane-tabs.tsx +4 -3
- package/src/components/layout/pane/sizing.ts +9 -0
- package/src/components/layout/pane/ticker-fate-gate.tsx +62 -0
- package/src/components/layout/shell/pane/capture.ts +44 -20
- package/src/components/layout/status-bar.tsx +3 -6
- package/src/components/markdown-text.tsx +17 -2
- package/src/components/market-board/index.tsx +19 -8
- package/src/components/metric-treemap/heat-surface.tsx +2 -7
- package/src/components/onboarding/account-step/qr-panel.tsx +5 -2
- package/src/components/onboarding/onboarding-frame.tsx +24 -21
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +20 -10
- package/src/components/onboarding/wizard-model.ts +1 -1
- package/src/components/onboarding/wizard-positions.ts +56 -19
- package/src/components/pane-settings-dialog/desktop.tsx +12 -50
- package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -1
- package/src/components/price-performance.tsx +18 -2
- package/src/components/reader/article-reader.tsx +11 -10
- package/src/components/reader/detail-reader.tsx +9 -5
- package/src/components/reader/reader-text.tsx +51 -24
- package/src/components/sign-in-code-panel.tsx +129 -75
- package/src/components/ticker/badge/format.ts +64 -15
- package/src/components/ticker/badge/index.tsx +33 -11
- package/src/components/ticker/badge/list.tsx +4 -3
- package/src/components/ticker/badge/text.tsx +2 -2
- package/src/components/ticker/list-table-view.tsx +8 -1
- package/src/components/ui/action-row.tsx +5 -2
- package/src/components/ui/audio-player.tsx +70 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/data-table/index.tsx +4 -2
- package/src/components/ui/data-table/opentui/index.tsx +61 -20
- package/src/components/ui/data-table/opentui/model.ts +104 -0
- package/src/components/ui/data-table/types.ts +11 -0
- package/src/components/ui/detail-scroll-body.tsx +1 -1
- package/src/components/ui/dialog-actions.tsx +1 -21
- package/src/components/ui/display.tsx +13 -5
- package/src/components/ui/external-link.tsx +4 -2
- package/src/components/ui/fields.tsx +12 -0
- package/src/components/ui/figure.tsx +5 -3
- package/src/components/ui/frame.tsx +40 -6
- package/src/components/ui/icon.tsx +4 -0
- package/src/components/ui/index.ts +4 -1
- package/src/components/ui/inline-quick-add.tsx +4 -1
- package/src/components/ui/list-view.tsx +8 -0
- package/src/components/ui/prose.tsx +97 -25
- package/src/components/ui/query-bar-keys.tsx +32 -6
- package/src/components/ui/query-bar.tsx +35 -4
- package/src/components/ui/quote.ts +42 -0
- package/src/components/ui/range-track.tsx +15 -2
- package/src/components/ui/reveal-in-scroll-box.ts +21 -3
- package/src/components/ui/select-button.tsx +38 -3
- package/src/components/ui/status.tsx +73 -4
- package/src/components/ui/table-layout.ts +20 -0
- package/src/components/ui/windowed-list.tsx +27 -0
- package/src/components/use-pinned-moment.ts +19 -0
- package/src/core/app-runtime.ts +2 -2
- package/src/core/state/app/instrument.ts +18 -1
- package/src/core/state/app/layout.ts +6 -0
- package/src/core/state/app/state.ts +14 -2
- package/src/data/cached-query.ts +1 -1
- package/src/data/config/chart-settings.ts +3 -1
- package/src/data/config/home.ts +4 -1
- package/src/data/config/store/node.ts +9 -4
- package/src/data/config/store/normalize.ts +9 -0
- package/src/data/json-storage.ts +6 -3
- package/src/data/json-ticker-repository.ts +3 -1
- package/src/data/plugin-cache.ts +5 -1
- package/src/data/sqlite/json.ts +3 -1
- package/src/data/ticker-repository.ts +5 -2
- package/src/docs/snapshot.json +248 -5
- package/src/feedback/diagnostics.ts +2 -6
- package/src/i18n/es.ts +86 -6
- package/src/i18n/index.ts +3 -9
- package/src/i18n/ja.ts +86 -6
- package/src/i18n/ko.ts +86 -6
- package/src/i18n/zh-cn.ts +86 -6
- package/src/i18n/zh-tw.ts +86 -6
- package/src/layout-marketplace/cloud.ts +16 -5
- package/src/layout-marketplace/gallery-desktop.tsx +8 -4
- package/src/layout-marketplace/gallery.tsx +4 -4
- package/src/layout-marketplace/linked-sync.ts +9 -3
- package/src/layout-marketplace/linked.ts +24 -3
- package/src/layout-marketplace/model.ts +39 -4
- package/src/market-data/bars-per-year.ts +43 -0
- package/src/market-data/bond-funds.ts +85 -0
- package/src/market-data/coordinator/auxiliary.ts +5 -2
- package/src/market-data/coordinator/index.ts +39 -5
- package/src/market-data/futures-contract.ts +155 -5
- package/src/market-data/hooks.tsx +77 -12
- package/src/market-data/market/bar-period.ts +107 -0
- package/src/market-data/market/format.ts +18 -14
- package/src/market-data/market/freshness.ts +29 -4
- package/src/market-data/market/index-level.ts +51 -0
- package/src/market-data/market/status.ts +152 -13
- package/src/market-data/model-dividend-yield.ts +117 -0
- package/src/market-data/quotes/freshness.ts +30 -1
- package/src/{plugins/builtin/portfolio-list → market-data/quotes}/live-valuation.ts +52 -6
- package/src/market-data/quotes/regular-session-valuation.ts +32 -1
- package/src/market-data/realized-volatility.ts +16 -7
- package/src/market-data/tax-equivalent.ts +344 -0
- package/src/news/aggregator.ts +4 -2
- package/src/notifications/notification-log.ts +5 -3
- package/src/plugins/auto-update-node.ts +1 -0
- package/src/plugins/builtin/account-management/footer.ts +1 -1
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +71 -19
- package/src/plugins/builtin/account-management/trial-cancel.ts +40 -0
- package/src/plugins/builtin/alerts/cli.ts +7 -18
- package/src/plugins/builtin/alerts/constants.ts +8 -0
- package/src/plugins/builtin/alerts/event-rows.ts +16 -0
- package/src/plugins/builtin/alerts/events-pane.tsx +2 -14
- package/src/plugins/builtin/alerts/headless.ts +182 -0
- package/src/plugins/builtin/alerts/index.tsx +3 -0
- package/src/plugins/builtin/alerts/pane.tsx +1 -7
- package/src/plugins/builtin/alerts/storage.ts +17 -1
- package/src/plugins/builtin/analytics/index.tsx +6 -1
- package/src/plugins/builtin/analytics/metrics.ts +55 -13
- package/src/plugins/builtin/analytics/risk-headless.ts +26 -7
- package/src/plugins/builtin/analytics/risk-math.ts +83 -0
- package/src/plugins/builtin/analytics/risk-model.ts +171 -19
- package/src/plugins/builtin/analytics/risk-pane.tsx +17 -12
- package/src/plugins/builtin/analytics/sector-model.ts +14 -3
- package/src/plugins/builtin/awards/headless.ts +6 -5
- package/src/plugins/builtin/awards/index.tsx +1 -1
- package/src/plugins/builtin/backtest/client.ts +38 -8
- package/src/plugins/builtin/backtest/engine.ts +25 -13
- package/src/plugins/builtin/backtest/export.ts +27 -0
- package/src/plugins/builtin/backtest/format.ts +19 -3
- package/src/plugins/builtin/backtest/headless.ts +42 -28
- package/src/plugins/builtin/backtest/index.tsx +3 -0
- package/src/plugins/builtin/backtest/pane.tsx +39 -10
- package/src/plugins/builtin/backtest/report.ts +160 -0
- package/src/plugins/builtin/backtest/rules.ts +2 -0
- package/src/plugins/builtin/backtest/window.ts +112 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +3 -2
- package/src/plugins/builtin/broker-manager/add-flow.tsx +4 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +0 -1
- package/src/plugins/builtin/catalysts/headless.ts +24 -13
- package/src/plugins/builtin/catalysts/index.tsx +4 -2
- package/src/plugins/builtin/catalysts/model.ts +18 -1
- package/src/plugins/builtin/catalysts/pane.tsx +2 -2
- package/src/plugins/builtin/cds/client.ts +28 -5
- package/src/plugins/builtin/cds/headless.ts +183 -31
- package/src/plugins/builtin/cds/index.tsx +1 -1
- package/src/plugins/builtin/cds/model.ts +229 -53
- package/src/plugins/builtin/cds/pane.tsx +82 -26
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -1
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +39 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +77 -0
- package/src/plugins/builtin/chart-composer/chart-spec.ts +15 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +22 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +14 -10
- package/src/plugins/builtin/chart-composer/editor/desktop-view.tsx +2 -2
- package/src/plugins/builtin/chart-composer/formula.ts +233 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -2
- package/src/plugins/builtin/chart-composer/headless.ts +117 -15
- package/src/plugins/builtin/chart-composer/index.tsx +73 -15
- package/src/plugins/builtin/chart-composer/pane.tsx +86 -23
- package/src/plugins/builtin/chart-composer/presets.ts +165 -8
- package/src/plugins/builtin/chart-composer/quick-add.tsx +9 -2
- package/src/plugins/builtin/chart-composer/series-catalog.ts +85 -16
- package/src/plugins/builtin/chart-composer/series-expression.ts +10 -8
- package/src/plugins/builtin/chart-composer/series-listings.ts +178 -0
- package/src/plugins/builtin/chart-composer/session-range.ts +87 -0
- package/src/plugins/builtin/chart-composer/settings.ts +16 -4
- package/src/plugins/builtin/chart-composer/studies.ts +1 -1
- package/src/plugins/builtin/chat/attachments/desktop.tsx +4 -1
- package/src/plugins/builtin/chat/content/channel-navigation.ts +17 -6
- package/src/plugins/builtin/chat/content/composer-runtime.ts +49 -14
- package/src/plugins/builtin/chat/content/composer.tsx +22 -1
- package/src/plugins/builtin/chat/content/index.tsx +47 -10
- package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -0
- package/src/plugins/builtin/chat/content/mentions.ts +50 -21
- package/src/plugins/builtin/chat/content/scroll.ts +12 -5
- package/src/plugins/builtin/chat/content/shortcuts.ts +32 -13
- package/src/plugins/builtin/chat/content/snapshot.ts +40 -6
- package/src/plugins/builtin/chat/content/transcript.tsx +48 -37
- package/src/plugins/builtin/chat/content/whole-message-copy.ts +44 -2
- package/src/plugins/builtin/chat/controller/index.ts +68 -17
- package/src/plugins/builtin/chat/controller/mention-candidates.ts +104 -0
- package/src/plugins/builtin/chat/controller/realtime.ts +9 -0
- package/src/plugins/builtin/chat/controller/state.ts +10 -0
- package/src/plugins/builtin/chat/controller/view.ts +2 -0
- package/src/plugins/builtin/chat/conversation-recency.ts +73 -0
- package/src/plugins/builtin/chat/conversations.ts +12 -5
- package/src/plugins/builtin/chat/ghost-user.ts +11 -3
- package/src/plugins/builtin/chat/layout.ts +25 -5
- package/src/plugins/builtin/chat/message/desktop.tsx +15 -5
- package/src/plugins/builtin/chat/message/header.tsx +26 -4
- package/src/plugins/builtin/chat/message/pane-chip.tsx +131 -35
- package/src/plugins/builtin/chat/message/render-state.ts +28 -1
- package/src/plugins/builtin/chat/message/terminal.tsx +9 -3
- package/src/plugins/builtin/chat/pane-links/composer.ts +87 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +1 -1
- package/src/plugins/builtin/chat/share/flow.tsx +9 -73
- package/src/plugins/builtin/chat/sidebar-rows.ts +18 -5
- package/src/plugins/builtin/chat/sidebar.tsx +6 -1
- package/src/plugins/builtin/cloud/askg/controller.ts +5 -3
- package/src/plugins/builtin/cloud/askg/executor.ts +3 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +16 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +4 -3
- package/src/plugins/builtin/cloud/askg/pane.tsx +6 -2
- package/src/plugins/builtin/cloud/auth-actions.tsx +4 -2
- package/src/plugins/builtin/cloud/company-picker.tsx +21 -26
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +5 -3
- package/src/plugins/builtin/cloud/plugin.tsx +2 -0
- package/src/plugins/builtin/cloud/team/module.tsx +5 -1
- package/src/plugins/builtin/cloud/team/pane.tsx +11 -4
- package/src/plugins/builtin/cloud/team/views.ts +11 -4
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +9 -4
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +16 -5
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +3 -2
- package/src/plugins/builtin/cloud/thesis/detail.tsx +2 -1
- package/src/plugins/builtin/cloud/thesis/exposure.ts +3 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +3 -2
- package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +2 -1
- package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +2 -1
- package/src/plugins/builtin/cloud/verification-status-widget.tsx +2 -1
- package/src/plugins/builtin/commodities-energy/index.tsx +31 -9
- package/src/plugins/builtin/commodities-energy/view-state.ts +11 -0
- package/src/plugins/builtin/commodity-balances/client.ts +51 -193
- package/src/plugins/builtin/commodity-balances/headless.ts +10 -3
- package/src/plugins/builtin/commodity-balances/model.ts +5 -180
- package/src/plugins/builtin/commodity-balances/pane.tsx +3 -0
- package/src/plugins/builtin/company-attention/headless.ts +15 -7
- package/src/plugins/builtin/company-attention/index.tsx +1 -1
- package/src/plugins/builtin/company-attention/model.ts +49 -4
- package/src/plugins/builtin/company-attention/pane.tsx +11 -9
- package/src/plugins/builtin/company-kpis/headless.ts +4 -3
- package/src/plugins/builtin/company-kpis/index.tsx +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +9 -3
- package/src/plugins/builtin/congress-trades/headless.ts +23 -2
- package/src/plugins/builtin/correlation/relationship/pane.tsx +18 -46
- package/src/plugins/builtin/cot/headless.ts +5 -2
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +41 -13
- package/src/plugins/builtin/credit-boards/client.ts +9 -2
- package/src/plugins/builtin/credit-boards/headless.ts +93 -27
- package/src/plugins/builtin/credit-boards/index.tsx +15 -4
- package/src/plugins/builtin/credit-boards/model.ts +105 -6
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +14 -3
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -1
- package/src/plugins/builtin/credit-documents/index.tsx +3 -0
- package/src/plugins/builtin/credit-documents/model.ts +3 -10
- package/src/plugins/builtin/crypto-board/client.ts +152 -2
- package/src/plugins/builtin/crypto-board/headless.ts +138 -19
- package/src/plugins/builtin/crypto-board/index.tsx +5 -3
- package/src/plugins/builtin/crypto-board/model.ts +210 -12
- package/src/plugins/builtin/crypto-board/pane.tsx +148 -9
- package/src/plugins/builtin/crypto-board/series.ts +52 -1
- package/src/plugins/builtin/crypto-board/supply.ts +123 -0
- package/src/plugins/builtin/custom-view/index.tsx +1 -1
- package/src/plugins/builtin/custom-view/loader.ts +57 -7
- package/src/plugins/builtin/custom-view/sources.ts +146 -0
- package/src/plugins/builtin/custom-view/view-spec.ts +37 -1
- package/src/plugins/builtin/debt-maturities/client.ts +54 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +27 -3
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/model.ts +58 -13
- package/src/plugins/builtin/debt-maturities/pane.tsx +47 -7
- package/src/plugins/builtin/dividend-yield/client.ts +42 -36
- package/src/plugins/builtin/dividend-yield/headless.ts +113 -18
- package/src/plugins/builtin/dividend-yield/index.tsx +5 -2
- package/src/plugins/builtin/dividend-yield/pane.tsx +37 -13
- package/src/plugins/builtin/dividend-yield/provider-client.ts +7 -3
- package/src/plugins/builtin/dividend-yield/ranking.ts +187 -0
- package/src/plugins/builtin/dividend-yield/reference-price.ts +28 -5
- package/src/plugins/builtin/dividend-yield/types.ts +6 -1
- package/src/plugins/builtin/dividend-yield/view.ts +1 -1
- package/src/plugins/builtin/docs/blocks.tsx +54 -8
- package/src/plugins/builtin/docs/pane.tsx +8 -13
- package/src/plugins/builtin/earnings/board-model.ts +33 -3
- package/src/plugins/builtin/earnings/board-table.ts +59 -14
- package/src/plugins/builtin/earnings/board.tsx +36 -3
- package/src/plugins/builtin/earnings/headless.ts +27 -7
- package/src/plugins/builtin/earnings/history-model.ts +9 -1
- package/src/plugins/builtin/earnings/history-table.ts +16 -5
- package/src/plugins/builtin/earnings/history.tsx +40 -10
- package/src/plugins/builtin/earnings/index.tsx +3 -1
- package/src/plugins/builtin/earnings/no-earnings.ts +52 -0
- package/src/plugins/builtin/earnings-calls/data.ts +51 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -0
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
- package/src/plugins/builtin/earnings-calls/model.ts +97 -0
- package/src/plugins/builtin/earnings-calls/pane.tsx +107 -7
- package/src/plugins/builtin/earnings-calls/transcript-view.tsx +140 -22
- package/src/plugins/builtin/earnings-calls/use-call-playback.ts +194 -0
- package/src/plugins/builtin/econ/calendar-model.ts +22 -0
- package/src/plugins/builtin/econ/calendar-source.ts +35 -0
- package/src/plugins/builtin/econ/index.tsx +40 -8
- package/src/plugins/builtin/econ-statistics/defs.ts +7 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +11 -1
- package/src/plugins/builtin/econ-statistics/headless.ts +31 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +5 -3
- package/src/plugins/builtin/econ-statistics/stats.ts +10 -0
- package/src/plugins/builtin/econ-statistics/view.ts +23 -0
- package/src/plugins/builtin/equity-screener/client.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +46 -4
- package/src/plugins/builtin/equity-screener/pane.tsx +3 -0
- package/src/plugins/builtin/estimate-revisions/client.ts +32 -22
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
- package/src/plugins/builtin/estimate-revisions/pane.tsx +5 -3
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/editor.tsx +3 -3
- package/src/plugins/builtin/fear-greed/index.tsx +9 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures/index.tsx +2 -2
- package/src/plugins/builtin/futures/model.ts +39 -25
- package/src/plugins/builtin/futures/series.ts +38 -1
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-board-terms.ts +2 -2
- package/src/plugins/builtin/futures-curve/client.ts +4 -4
- package/src/plugins/builtin/futures-curve/headless.ts +24 -4
- package/src/plugins/builtin/futures-curve/index.tsx +2 -2
- package/src/plugins/builtin/futures-curve/model.ts +50 -9
- package/src/plugins/builtin/futures-curve/pane.tsx +14 -10
- package/src/plugins/builtin/help/index.tsx +55 -8
- package/src/plugins/builtin/help/shortcut-table.tsx +15 -2
- package/src/plugins/builtin/holders/headless.ts +12 -0
- package/src/plugins/builtin/insider/headless.ts +345 -5
- package/src/plugins/builtin/insider/index.tsx +304 -36
- package/src/plugins/builtin/insider/insiders.tsx +224 -0
- package/src/plugins/builtin/insider/signals-cells.tsx +52 -0
- package/src/plugins/builtin/insider/signals-client.ts +193 -0
- package/src/plugins/builtin/insider/signals-model.ts +718 -0
- package/src/plugins/builtin/insider/signals.tsx +376 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +17 -7
- package/src/plugins/builtin/ipo-calendar/index.tsx +23 -3
- package/src/plugins/builtin/ipo-calendar/model.ts +84 -36
- package/src/plugins/builtin/ipo-calendar/pane.tsx +20 -8
- package/src/plugins/builtin/iv-history/client.ts +41 -2
- package/src/plugins/builtin/iv-history/headless.ts +26 -16
- package/src/plugins/builtin/iv-history/screen-pane.tsx +25 -7
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/jobs/index.tsx +1 -0
- package/src/plugins/builtin/jodi/client.ts +42 -205
- package/src/plugins/builtin/jodi/headless.ts +15 -4
- package/src/plugins/builtin/jodi/model.ts +18 -43
- package/src/plugins/builtin/jodi/pane.tsx +5 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +1 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +3 -1
- package/src/plugins/builtin/market-movers/client.ts +32 -6
- package/src/plugins/builtin/market-movers/headless.ts +7 -2
- package/src/plugins/builtin/market-movers/model.ts +64 -3
- package/src/plugins/builtin/market-movers/screener.ts +20 -9
- package/src/plugins/builtin/market-valuation/detail.tsx +7 -2
- package/src/plugins/builtin/market-valuation/headless.ts +17 -4
- package/src/plugins/builtin/market-valuation/pane.tsx +8 -4
- package/src/plugins/builtin/market-valuation/view.ts +10 -0
- package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +31 -57
- package/src/plugins/builtin/mna/distress/headless.ts +2 -1
- package/src/plugins/builtin/mna/headless.ts +14 -2
- package/src/plugins/builtin/mna/index.tsx +1 -0
- package/src/plugins/builtin/news/headless.ts +4 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +5 -3
- package/src/plugins/builtin/news/wire/news/table.tsx +57 -11
- package/src/plugins/builtin/notes/cli.ts +8 -4
- package/src/plugins/builtin/notes/files.ts +66 -20
- package/src/plugins/builtin/notes/migration.ts +18 -6
- package/src/plugins/builtin/notes/owner.tsx +3 -2
- package/src/plugins/builtin/notes/quick-notes-pane.tsx +3 -2
- package/src/plugins/builtin/options-positioning/client.ts +10 -0
- package/src/plugins/builtin/options-positioning/headless.ts +88 -13
- package/src/plugins/builtin/options-positioning/index.tsx +2 -2
- package/src/plugins/builtin/options-positioning/model.ts +33 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +38 -16
- package/src/plugins/builtin/options-scenario/charts.tsx +13 -4
- package/src/plugins/builtin/options-scenario/client.ts +114 -17
- package/src/plugins/builtin/options-scenario/collar.ts +141 -0
- package/src/plugins/builtin/options-scenario/csp.ts +1 -1
- package/src/plugins/builtin/options-scenario/freshness.ts +27 -0
- package/src/plugins/builtin/options-scenario/headless.ts +30 -12
- package/src/plugins/builtin/options-scenario/index.tsx +1 -1
- package/src/plugins/builtin/options-scenario/model.ts +55 -5
- package/src/plugins/builtin/options-scenario/pane.tsx +24 -5
- package/src/plugins/builtin/pe-band/index.tsx +1 -1
- package/src/plugins/builtin/pe-band/model.ts +1 -15
- package/src/plugins/builtin/perps/headless.ts +30 -13
- package/src/plugins/builtin/perps/model.ts +45 -3
- package/src/plugins/builtin/perps/pane.tsx +7 -7
- package/src/plugins/builtin/portfolio-list/cell-version.ts +10 -4
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +128 -14
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +144 -63
- package/src/plugins/builtin/portfolio-list/cli/render.ts +373 -48
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +23 -9
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +25 -35
- package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +161 -32
- package/src/plugins/builtin/portfolio-list/income.ts +296 -0
- package/src/plugins/builtin/portfolio-list/metrics.ts +2 -2
- package/src/plugins/builtin/portfolio-list/pane/futures-terms.ts +58 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +63 -14
- package/src/plugins/builtin/portfolio-list/pane/remove-ticker.ts +1 -1
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +47 -28
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +38 -8
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +12 -4
- package/src/plugins/builtin/portfolio-list/settings.ts +22 -0
- package/src/plugins/builtin/portfolio-list/since-last-seen.ts +197 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +26 -4
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +32 -4
- package/src/plugins/builtin/portfolio-list/table.tsx +39 -7
- package/src/plugins/builtin/power/prices-headless.ts +2 -1
- package/src/plugins/builtin/realized-vol/chart-model.ts +29 -5
- package/src/plugins/builtin/realized-vol/charts.tsx +14 -8
- package/src/plugins/builtin/realized-vol/evidence.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +6 -4
- package/src/plugins/builtin/realized-vol/model.ts +5 -1
- package/src/plugins/builtin/realized-vol/pane.tsx +31 -11
- package/src/plugins/builtin/realized-vol/settings.ts +1 -1
- package/src/plugins/builtin/research/analyst-headless.ts +4 -0
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +16 -5
- package/src/plugins/builtin/research/event-model.ts +63 -51
- package/src/plugins/builtin/research/headless-schema.ts +1 -0
- package/src/plugins/builtin/research/headless.ts +4 -1
- package/src/plugins/builtin/research/index.tsx +3 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +27 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +2 -0
- package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +28 -9
- package/src/plugins/builtin/reverse-dcf/index.tsx +5 -2
- package/src/plugins/builtin/reverse-dcf/model.ts +87 -6
- package/src/plugins/builtin/reverse-dcf/pane.tsx +30 -7
- package/src/plugins/builtin/risk-factors/headless.ts +7 -0
- package/src/plugins/builtin/risk-factors/index.tsx +1 -0
- package/src/plugins/builtin/scanner/feed.ts +5 -3
- package/src/plugins/builtin/scanner/headless.ts +9 -57
- package/src/plugins/builtin/scanner/index.ts +1 -2
- package/src/plugins/builtin/sec/forms.ts +2 -6
- package/src/plugins/builtin/sec/fund-facts-view.tsx +53 -0
- package/src/plugins/builtin/sec/fund-facts.ts +328 -0
- package/src/plugins/builtin/sec/headless.ts +140 -44
- package/src/plugins/builtin/sec/index.tsx +95 -30
- package/src/plugins/builtin/sec/model.ts +2 -44
- package/src/plugins/builtin/shared/earnings-report.ts +48 -1
- package/src/plugins/builtin/shared/headless-options.ts +10 -0
- package/src/plugins/builtin/shared/history-span.ts +55 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +3 -1
- package/src/plugins/builtin/shared/move-rank.ts +108 -0
- package/src/plugins/builtin/shared/report-freshness.ts +45 -20
- package/src/plugins/builtin/shared/scanner-capture.ts +95 -0
- package/src/plugins/builtin/shared/series-detail-chart.tsx +5 -2
- package/src/plugins/builtin/shared/series-list-detail.tsx +7 -3
- package/src/plugins/builtin/shared/ticker-surface.ts +16 -2
- package/src/plugins/builtin/shared/treasury-cutoffs.ts +15 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +13 -5
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -0
- package/src/plugins/builtin/shared/volatility-indices.ts +32 -0
- package/src/plugins/builtin/short-interest/headless.ts +3 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +2 -2
- package/src/plugins/builtin/social-mentions/client.ts +8 -1
- package/src/plugins/builtin/social-mentions/pane.tsx +8 -6
- package/src/plugins/builtin/supply-chain/client.ts +12 -3
- package/src/plugins/builtin/supply-chain/disclosure-quote.tsx +9 -5
- package/src/plugins/builtin/supply-chain/evidence.ts +3 -1
- package/src/plugins/builtin/supply-chain/flow-layout.ts +2 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +23 -16
- package/src/plugins/builtin/supply-chain/graph-client.ts +8 -5
- package/src/plugins/builtin/supply-chain/graph-evidence.ts +1 -1
- package/src/plugins/builtin/supply-chain/graph-model.ts +10 -2
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +9 -7
- package/src/plugins/builtin/supply-chain/graph.tsx +8 -6
- package/src/plugins/builtin/supply-chain/headless.ts +69 -27
- package/src/plugins/builtin/supply-chain/index.tsx +1 -1
- package/src/plugins/builtin/supply-chain/model.ts +76 -15
- package/src/plugins/builtin/supply-chain/pane.tsx +29 -15
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +5 -4
- package/src/plugins/builtin/themes/headless.ts +15 -2
- package/src/plugins/builtin/themes/model.ts +2 -5
- package/src/plugins/builtin/thirteenf/api.ts +50 -2
- package/src/plugins/builtin/thirteenf/data.ts +250 -11
- package/src/plugins/builtin/thirteenf/headless.ts +311 -28
- package/src/plugins/builtin/thirteenf/index.tsx +4 -1
- package/src/plugins/builtin/thirteenf/model.ts +244 -19
- package/src/plugins/builtin/thirteenf/overlap-pane.tsx +133 -33
- package/src/plugins/builtin/thirteenf/overlap.ts +1 -1
- package/src/plugins/builtin/thirteenf/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/report-notes.ts +78 -0
- package/src/plugins/builtin/thirteenf/types.ts +49 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +106 -24
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +108 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +26 -8
- package/src/plugins/builtin/ticker-detail/financials/model.ts +2 -42
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +4 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +109 -23
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +27 -3
- package/src/plugins/builtin/ticker-detail/overview/dividend.ts +60 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +46 -9
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +37 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +18 -19
- package/src/plugins/builtin/time-sales/client.ts +7 -4
- package/src/plugins/builtin/time-sales/headless.ts +71 -22
- package/src/plugins/builtin/time-sales/model.ts +12 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -7
- package/src/plugins/builtin/time-sales/window.ts +128 -0
- package/src/plugins/builtin/trace-bonds/client.ts +351 -33
- package/src/plugins/builtin/trace-bonds/headless.ts +60 -22
- package/src/plugins/builtin/trace-bonds/index.tsx +4 -2
- package/src/plugins/builtin/trace-bonds/model.ts +27 -25
- package/src/plugins/builtin/trace-bonds/pane.tsx +63 -45
- package/src/plugins/builtin/treasury-auctions/cache.ts +61 -15
- package/src/plugins/builtin/treasury-auctions/client.ts +45 -10
- package/src/plugins/builtin/treasury-auctions/headless.ts +35 -13
- package/src/plugins/builtin/treasury-auctions/index.tsx +5 -2
- package/src/plugins/builtin/treasury-auctions/model.ts +20 -16
- package/src/plugins/builtin/treasury-auctions/pane.tsx +29 -12
- package/src/plugins/builtin/vol-surface/charts.tsx +2 -1
- package/src/plugins/builtin/vol-surface/headless.ts +3 -2
- package/src/plugins/builtin/vol-surface/pane.tsx +2 -1
- package/src/plugins/builtin/vol-surface/stored.ts +4 -7
- package/src/plugins/builtin/volatility/chart-model.ts +16 -15
- package/src/plugins/builtin/volatility/charts.tsx +5 -5
- package/src/plugins/builtin/volatility/client.ts +73 -2
- package/src/plugins/builtin/volatility/evidence.ts +13 -14
- package/src/plugins/builtin/volatility/headless.ts +13 -7
- package/src/plugins/builtin/volatility/index.tsx +1 -1
- package/src/plugins/builtin/volatility/model.ts +104 -38
- package/src/plugins/builtin/volatility/pane.tsx +42 -24
- package/src/plugins/builtin/volatility/series.ts +22 -13
- package/src/plugins/builtin/world-venue-map/geo-series.ts +9 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +25 -8
- package/src/plugins/builtin/world-venue-map/index.ts +16 -2
- package/src/plugins/builtin/world-venue-map/map.tsx +13 -17
- package/src/plugins/builtin/yield-curve/curves.ts +29 -5
- package/src/plugins/builtin/yield-curve/headless.ts +41 -8
- package/src/plugins/builtin/yield-curve/history.ts +5 -5
- package/src/plugins/builtin/yield-curve/index.tsx +30 -13
- package/src/plugins/compat.ts +3 -1
- package/src/plugins/dependencies.ts +8 -2
- package/src/plugins/host-link.ts +12 -5
- package/src/plugins/installer.ts +16 -7
- package/src/plugins/loader.ts +9 -2
- package/src/plugins/marketplace/activation.ts +10 -4
- package/src/plugins/registry/host-actions.ts +3 -0
- package/src/plugins/registry/index.ts +3 -1
- package/src/{plugins/builtin/portfolio-list → portfolio}/allocation.ts +82 -15
- package/src/{plugins/builtin/portfolio-list → portfolio}/column-values.ts +143 -55
- package/src/portfolio/futures-positions.ts +213 -0
- package/src/portfolio/futures-terms.ts +75 -0
- package/src/portfolio/manual-lots.ts +78 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/mutations.ts +59 -15
- package/src/portfolio/position-metrics.ts +44 -10
- package/src/portfolio/valuation-basis.ts +34 -24
- package/src/public/__snapshots__/public-api.test.ts.snap +6 -0
- package/src/public/time-series.ts +2 -1
- package/src/remote/confirm-change.tsx +2 -1
- package/src/remote/controller.ts +27 -7
- package/src/remote/schema.ts +25 -9
- package/src/remote/server.ts +1 -1
- package/src/remote/watchlist.ts +9 -1
- package/src/renderers/cloudflare/http-proxy.ts +21 -13
- package/src/renderers/dom/data-table/row.tsx +1 -1
- package/src/renderers/dom/desktop/audio-player.tsx +312 -0
- package/src/renderers/dom/desktop/control-styles.ts +17 -82
- package/src/renderers/dom/desktop/controls.tsx +39 -63
- package/src/renderers/dom/desktop/dialog-actions.tsx +13 -53
- package/src/renderers/dom/desktop/icons.tsx +8 -0
- package/src/renderers/dom/desktop/list-view.tsx +6 -6
- package/src/renderers/dom/desktop/popover.tsx +0 -3
- package/src/renderers/dom/desktop/query-bar.tsx +7 -5
- package/src/renderers/dom/desktop/select-field.tsx +9 -8
- package/src/renderers/dom/desktop/stack-header.ts +3 -0
- package/src/renderers/dom/dom-ui-host.tsx +5 -2
- package/src/renderers/dom/host/chart-surface.tsx +3 -3
- package/src/renderers/dom/host/size-observer.ts +33 -4
- package/src/renderers/dom/host/surface-3d.tsx +3 -2
- package/src/renderers/dom/host/surface-fit.ts +4 -1
- package/src/renderers/dom/host/tabs.tsx +22 -132
- package/src/renderers/dom/styles.css +358 -160
- package/src/renderers/dom/windowed-list.tsx +201 -0
- package/src/renderers/dom/windowed-rows.ts +65 -0
- package/src/renderers/electrobun/bun/core-capabilities.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +2 -9
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/http-stream.ts +21 -6
- package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +43 -1
- package/src/renderers/electrobun/bun/desktop/update.ts +21 -6
- package/src/renderers/electrobun/bun/desktop/workspace/requests.ts +5 -1
- package/src/renderers/electrobun/shared/protocol.ts +4 -2
- package/src/renderers/electrobun/shared/rpc-codec.ts +7 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +21 -17
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/desktop/window/bridge.ts +6 -8
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +18 -0
- package/src/renderers/electrobun/view/http-fetch.ts +12 -1
- package/src/series/capability.ts +1 -0
- package/src/series/files.ts +9 -3
- package/src/series/registry.ts +40 -14
- package/src/series/resolve.ts +121 -18
- package/src/series/standalone.ts +3 -2
- package/src/series/types.ts +55 -1
- package/src/series/validate.ts +39 -0
- package/src/shares/api.ts +26 -7
- package/src/shares/bug-report-dialog.tsx +2 -2
- package/src/shares/bug-report-flow.tsx +4 -7
- package/src/shares/capture-flow.ts +5 -4
- package/src/shares/capture-preview.tsx +2 -2
- package/src/shares/chat.ts +7 -27
- package/src/shares/flow.tsx +86 -40
- package/src/shares/location.ts +1 -3
- package/src/shares/pane-image.ts +11 -9
- package/src/shares/pane.ts +5 -2
- package/src/shares/payload.ts +1 -1
- package/src/shares/personal-pane.ts +3 -3
- package/src/shares/portable-layout.ts +9 -2
- package/src/shares/ready.ts +42 -0
- package/src/shares/test-harness.ts +62 -0
- package/src/sources/gloomberb-cloud/batched-lookups.ts +73 -0
- package/src/sources/gloomberb-cloud/index.ts +64 -12
- package/src/sources/gloomberb-cloud/normalizers.ts +31 -2
- package/src/sources/gloomberb-cloud/perpetuals.ts +20 -1
- package/src/sources/history-omitted.ts +34 -0
- package/src/sources/history-result.ts +3 -0
- package/src/sources/history-retention.ts +1 -1
- package/src/sources/listing-symbols.ts +8 -4
- package/src/sources/provider-errors.ts +43 -1
- package/src/sources/provider-router/batches.ts +3 -2
- package/src/sources/provider-router/cache.ts +2 -1
- package/src/sources/provider-router/cached-routes.ts +9 -3
- package/src/sources/provider-router/history.ts +9 -8
- package/src/sources/provider-router/index.ts +18 -3
- package/src/sources/provider-router/primary.ts +5 -4
- package/src/sources/provider-router/quote-route.ts +3 -1
- package/src/sources/provider-router/routing.ts +2 -1
- package/src/sources/provider-router/search.ts +47 -13
- package/src/sources/provider-router/streaming.ts +7 -4
- package/src/sources/sec-edgar.ts +1 -3
- package/src/state/app/context/index.tsx +9 -0
- package/src/state/app/tab-cursor.ts +222 -0
- package/src/state/hooks/quote-streaming.ts +3 -2
- package/src/state/hooks/session-snapshot.ts +3 -2
- package/src/state/persist-scheduler.ts +12 -4
- package/src/sync/controller.ts +22 -1
- package/src/sync/core-contributors.ts +264 -74
- package/src/team/collections-sync.ts +14 -4
- package/src/team/collections.ts +40 -11
- package/src/team/store.ts +5 -4
- package/src/telemetry/attention-counts.ts +8 -2
- package/src/telemetry/crash-reports-dom.ts +3 -0
- package/src/telemetry/crash-reports-node.ts +7 -4
- package/src/telemetry/crash-reports.ts +11 -11
- package/src/telemetry/usage-counts.ts +16 -12
- package/src/test-support/config-store.ts +31 -0
- package/src/test-support/moved-symbols.ts +64 -0
- package/src/theme/colors.ts +32 -0
- package/src/theme/font-scale.ts +2 -0
- package/src/theme/ui-tokens.ts +71 -0
- package/src/tickers/batched-lookups.ts +186 -0
- package/src/tickers/company-name-listing.ts +97 -0
- package/src/tickers/company-name.ts +13 -0
- package/src/tickers/instrument-coverage.ts +112 -0
- package/src/tickers/listing-fate.ts +282 -0
- package/src/tickers/listing-venues.ts +24 -5
- package/src/tickers/open-target.ts +13 -5
- package/src/tickers/search/index.ts +156 -37
- package/src/tickers/search/ranking.ts +68 -3
- package/src/tickers/search/types.ts +3 -0
- package/src/tickers/search/upsert.ts +22 -7
- package/src/tickers/terminal-codes.ts +79 -0
- package/src/tickers/ticker-changes.ts +100 -12
- package/src/tickers/us-listing.ts +2 -1
- package/src/time-series/bar-spacing.ts +19 -0
- package/src/time-series/chart-data.ts +116 -21
- package/src/time-series/field-catalog.ts +5 -2
- package/src/time-series/forward-valuation.ts +10 -7
- package/src/time-series/fundamentals.ts +103 -17
- package/src/time-series/hooks.ts +2 -0
- package/src/time-series/ice-credit.ts +17 -2
- package/src/time-series/live-bars.ts +24 -9
- package/src/time-series/live-quotes.ts +2 -3
- package/src/time-series/parsed-history-cache.ts +2 -0
- package/src/time-series/price-comparison.ts +6 -1
- package/src/time-series/price-units.ts +69 -0
- package/src/time-series/resolve.ts +114 -14
- package/src/time-series/session-bar.ts +138 -0
- package/src/time-series/spec.ts +14 -4
- package/src/time-series/studies.ts +214 -15
- package/src/time-series/transforms.ts +2 -0
- package/src/time-series/types.ts +33 -1
- package/src/time-series/use-chart-resolution.ts +2 -1
- package/src/time-series/valuation-price.ts +13 -0
- package/src/types/config.ts +17 -1
- package/src/types/data-provider.ts +20 -0
- package/src/types/financials.ts +2 -0
- package/src/types/headless.ts +169 -1
- package/src/types/instrument.ts +6 -0
- package/src/types/plugin.ts +39 -9
- package/src/types/price-history.ts +5 -0
- package/src/types/ticker-changes.ts +19 -0
- package/src/types/ticker.ts +10 -2
- package/src/ui/context-menu.tsx +2 -0
- package/src/ui/host.tsx +45 -4
- package/src/ui/measured-cells.ts +13 -7
- package/src/ui/qr.ts +7 -5
- package/src/updater/index.ts +8 -6
- package/src/utils/asset-category.ts +20 -0
- package/src/utils/calendar-date.ts +86 -27
- package/src/utils/currency-units.ts +17 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +83 -3
- package/src/utils/dividend-cash.ts +48 -0
- package/src/utils/dom-screenshot-rasters.ts +3 -1
- package/src/utils/dom-screenshot.ts +14 -10
- package/src/utils/exchange-rate-snapshot.ts +9 -4
- package/src/utils/external-url.ts +1 -0
- package/src/utils/fiscal-period.ts +47 -0
- package/src/utils/format.ts +5 -2
- package/src/utils/forward-dividend.ts +160 -11
- package/src/utils/fundamentals.ts +7 -2
- package/src/utils/futures-generic.ts +34 -8
- package/src/utils/http-proxy-response.ts +67 -9
- package/src/utils/local-utc-offset.ts +2 -0
- package/src/utils/log-failure.ts +31 -0
- package/src/utils/option-expiry.ts +12 -12
- package/src/utils/plugin-proxy-hosts.json +1 -5
- package/src/utils/price-history-integrity.ts +56 -0
- package/src/utils/price-history.ts +13 -1
- package/src/utils/sec-filings.ts +245 -0
- package/src/utils/selection-clipboard.ts +5 -2
- package/src/utils/throttled-fetch.ts +1 -0
- package/src/{plugins/builtin/dividend-yield/trailing-cash.ts → utils/trailing-dividend.ts} +55 -8
- package/src/utils/typo-distance.ts +22 -0
- package/src/utils/url.ts +1 -0
- package/src/utils/utc-time.ts +11 -0
- package/src/plugins/builtin/chat/share/targets.ts +0 -27
- package/src/plugins/builtin/shared/zip-text.ts +0 -46
- package/src/renderers/dom/host/top-surface.ts +0 -119
- package/src/shares/dialog.tsx +0 -221
- package/src/shares/live.ts +0 -19
|
@@ -358,6 +358,33 @@ export function latestRegularSessionClose(
|
|
|
358
358
|
return null;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
/**
|
|
362
|
+
* When the venue's regular session on `date` (its local `YYYY-MM-DD`) closed,
|
|
363
|
+
* a published early close included. Null when the venue had no session that
|
|
364
|
+
* day or its hours are unknown.
|
|
365
|
+
*/
|
|
366
|
+
export function regularSessionCloseOn(exchange: string | undefined, date: string): number | null {
|
|
367
|
+
const timeZone = sessionCalendarTimeZone(exchange);
|
|
368
|
+
if (!timeZone || isoLocalDateToUtcDay(date) == null) return null;
|
|
369
|
+
const endOfDay = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)), Number(date.slice(8, 10)), 23, 59, 59);
|
|
370
|
+
const close = latestRegularSessionClose(exchange, endOfDay);
|
|
371
|
+
return close?.date === date ? close.close : null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** The US pre-market opens at 04:00 New York. */
|
|
375
|
+
const US_PRE_MARKET_OPEN_MINUTES = 4 * 60;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* When a US listing's pre-market opened on `date` (its New York
|
|
379
|
+
* `YYYY-MM-DD`): 04:00 there. Null for any other venue, whose pre-market
|
|
380
|
+
* hours are not known, and for a date that does not parse.
|
|
381
|
+
*/
|
|
382
|
+
export function preMarketOpenOn(exchange: string | undefined, date: string): number | null {
|
|
383
|
+
if (!isUsListingExchange(canonicalExchange(exchange)) || isoLocalDateToUtcDay(date) == null) return null;
|
|
384
|
+
return zonedWallClockToUtcMs("America/New_York", Number(date.slice(0, 4)), Number(date.slice(5, 7)), Number(date.slice(8, 10)),
|
|
385
|
+
Math.floor(US_PRE_MARKET_OPEN_MINUTES / 60), US_PRE_MARKET_OPEN_MINUTES % 60, 0);
|
|
386
|
+
}
|
|
387
|
+
|
|
361
388
|
/**
|
|
362
389
|
* The UTC minute of the day the venue's regular session closed, for the latest
|
|
363
390
|
* session at or before `time` (20:00 UTC is 1200 while New York is on daylight
|
|
@@ -518,7 +545,7 @@ function formatUsSessionState(timestampMs: number): UsSessionState {
|
|
|
518
545
|
const minute = Number(parts.find((part) => part.type === "minute")?.value ?? "0");
|
|
519
546
|
const totalMinutes = hour * 60 + minute;
|
|
520
547
|
|
|
521
|
-
if (totalMinutes <
|
|
548
|
+
if (totalMinutes < US_PRE_MARKET_OPEN_MINUTES) return "PREPRE";
|
|
522
549
|
if (totalMinutes < 9 * 60 + 30) return "PRE";
|
|
523
550
|
if (totalMinutes < 16 * 60) return "REGULAR";
|
|
524
551
|
if (totalMinutes < 20 * 60) return "POST";
|
|
@@ -633,9 +660,7 @@ export function isTimestampStaleForExchangeSession(
|
|
|
633
660
|
): boolean {
|
|
634
661
|
try {
|
|
635
662
|
return isTimestampStaleForExchangeSessionUnsafe(timestampMs, exchange, now, marketState, weekendDays);
|
|
636
|
-
} catch {
|
|
637
|
-
return true;
|
|
638
|
-
}
|
|
663
|
+
} catch { /* Intentional ignore: Invalid session dates are conservatively stale, never fresh. */ return true; }
|
|
639
664
|
}
|
|
640
665
|
|
|
641
666
|
function isTimestampStaleForExchangeSessionUnsafe(
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { classifyInstrumentType, isCryptoVenuePerpetual } from "../../tickers/instrument-kind";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The unit an index level is in, as a chart's axis and series name it. A
|
|
5
|
+
* generic future on an index reads in the same points.
|
|
6
|
+
*/
|
|
7
|
+
export const INDEX_POINTS_UNIT = "points";
|
|
8
|
+
|
|
9
|
+
/** How a report line names that unit: `history` heads an index's bars with it, `ticker` its quote. */
|
|
10
|
+
export const INDEX_POINTS_LABEL = "Index points";
|
|
11
|
+
|
|
12
|
+
/** How an export names it, in `currency_or_unit` and a `unit` field. */
|
|
13
|
+
export const INDEX_POINTS_EXPORT_UNIT = "index points";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* An index level is points, not money: ^GSPC at 7,805.45 or ^VIX at 19.99 has
|
|
17
|
+
* no currency to name, wherever it is shown, though its quote names the
|
|
18
|
+
* currency its members trade in.
|
|
19
|
+
*/
|
|
20
|
+
export function isIndexLevel(instrumentType: string | null | undefined): boolean {
|
|
21
|
+
return classifyInstrumentType(instrumentType) === "index";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The currency a quote's price is in: none for an index level, nor for a quote that names none. */
|
|
25
|
+
export function quotePriceCurrency(quote: { currency?: string | null; instrumentType?: string | null } | null | undefined): string | null {
|
|
26
|
+
if (!quote || isIndexLevel(quote.instrumentType)) return null;
|
|
27
|
+
return quote.currency?.trim() || null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* What a price chart of the instrument reads in: points for an index level,
|
|
32
|
+
* otherwise its currency, so an axis never puts a dollar sign on ^VIX.
|
|
33
|
+
*/
|
|
34
|
+
export function priceSeriesUnit(currency: string, instrumentType: string | null | undefined): string {
|
|
35
|
+
return isIndexLevel(instrumentType) ? INDEX_POINTS_UNIT : currency;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A quote's volume where it counts one. An index and a crypto venue's
|
|
40
|
+
* perpetual price carry 0 for a volume nobody counts, which is not a session
|
|
41
|
+
* without trades: null for those, as for a quote with no volume. A broad
|
|
42
|
+
* index whose source sums its members' volume (^GSPC) keeps it.
|
|
43
|
+
*/
|
|
44
|
+
export function reportedQuoteVolume(
|
|
45
|
+
quote: { volume?: number | null; instrumentType?: string | null; name?: string | null } | null | undefined,
|
|
46
|
+
): number | null {
|
|
47
|
+
const volume = quote?.volume;
|
|
48
|
+
if (volume == null || !Number.isFinite(volume)) return null;
|
|
49
|
+
if (volume === 0 && (isIndexLevel(quote!.instrumentType) || isCryptoVenuePerpetual(quote!.instrumentType, quote!.name))) return null;
|
|
50
|
+
return volume;
|
|
51
|
+
}
|
|
@@ -3,6 +3,8 @@ import { blendHex, colors, priceColor, type ThemeColors } from "../../theme/colo
|
|
|
3
3
|
import { isFiniteNumber } from "../../utils/guards";
|
|
4
4
|
import { canonicalExchange, isKnownExchangeCode } from "../../utils/exchanges";
|
|
5
5
|
import { quoteTradingDay } from "../quotes/day-range";
|
|
6
|
+
import { isQuoteBeforeLatestSession } from "../quotes/freshness";
|
|
7
|
+
import { preMarketOpenOn, regularSessionCloseOn } from "./freshness";
|
|
6
8
|
|
|
7
9
|
const CLOSED_CHANGE_MUTING_RATIO = 0.55;
|
|
8
10
|
const US_SESSION_TIME = new Intl.DateTimeFormat("en-US", {
|
|
@@ -60,6 +62,28 @@ export function marketStateLabel(state: MarketState): string {
|
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
|
|
65
|
+
/** What a quote's session reads as once its last print is older than its venue's latest completed session. */
|
|
66
|
+
const STALE_SESSION_LABEL = "STALE";
|
|
67
|
+
|
|
68
|
+
const WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] as const;
|
|
69
|
+
|
|
70
|
+
/** `Thu close`: the weekday of the session whose close a quote still stands at. */
|
|
71
|
+
function closeLabel(date: string): string {
|
|
72
|
+
return `${WEEKDAYS[new Date(`${date}T00:00:00Z`).getUTCDay()]} close`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A quote's market state as a status cell names it (marketStateLabel), STALE
|
|
77
|
+
* for a print older than its venue's latest session, and the close it stands
|
|
78
|
+
* at (`Thu close`) in a pre-market nothing has traded in yet.
|
|
79
|
+
*/
|
|
80
|
+
export function quoteMarketStateLabel(quote: Quote | null | undefined, now = Date.now()): string | null {
|
|
81
|
+
if (!quote?.marketState) return null;
|
|
82
|
+
if (isQuoteBeforeLatestSession(quote, now)) return STALE_SESSION_LABEL;
|
|
83
|
+
const awaiting = preMarketCloseAwaitingPrint(quote);
|
|
84
|
+
return awaiting ? closeLabel(awaiting.date) : marketStateLabel(quote.marketState);
|
|
85
|
+
}
|
|
86
|
+
|
|
63
87
|
/** An extended session's column, named as marketStateLabel names its state. */
|
|
64
88
|
export function extendedSessionStateLabel(session: ExtendedSession): string {
|
|
65
89
|
return session === "OVERNIGHT" ? "OVERNIGHT" : marketStateLabel(session);
|
|
@@ -136,19 +160,53 @@ function overnightSessionDisplay(quote: Quote): ExtendedSessionDisplay | null {
|
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
/**
|
|
139
|
-
* A quote's session as a status cell names it:
|
|
140
|
-
*
|
|
141
|
-
*
|
|
163
|
+
* A quote's session as a status cell names it: STALE when its last print is
|
|
164
|
+
* older than its venue's latest completed session (isQuoteBeforeLatestSession),
|
|
165
|
+
* the overnight session while the quote is priced by it, the close it stands
|
|
166
|
+
* at (`Thu close`) in a pre-market nothing has traded in yet, else its market
|
|
167
|
+
* state (marketStateLabel). The exchange stays closed overnight, so the state
|
|
168
|
+
* alone reads CLOSED.
|
|
142
169
|
*/
|
|
143
|
-
export function quoteSessionLabel(quote: Quote | null | undefined): string | null {
|
|
170
|
+
export function quoteSessionLabel(quote: Quote | null | undefined, now = Date.now()): string | null {
|
|
171
|
+
return sessionLabel(quote, now, true);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* quoteSessionLabel as an export keeps it, one of a fixed set: the market
|
|
176
|
+
* state (`PRE-MKT`) in a pre-market nothing has traded in yet, where the
|
|
177
|
+
* status cell names the close (`Thu close`).
|
|
178
|
+
*/
|
|
179
|
+
export function quoteSessionStateLabel(quote: Quote | null | undefined, now = Date.now()): string | null {
|
|
180
|
+
return sessionLabel(quote, now, false);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function sessionLabel(quote: Quote | null | undefined, now: number, standingClose: boolean): string | null {
|
|
144
184
|
if (!quote?.marketState) return null;
|
|
145
|
-
|
|
185
|
+
if (isQuoteBeforeLatestSession(quote, now)) return STALE_SESSION_LABEL;
|
|
186
|
+
if (overnightSessionDisplay(quote)) return "OVERNIGHT";
|
|
187
|
+
const awaiting = standingClose ? preMarketCloseAwaitingPrint(quote) : null;
|
|
188
|
+
return awaiting ? closeLabel(awaiting.date) : marketStateLabel(quote.marketState);
|
|
146
189
|
}
|
|
147
190
|
|
|
148
|
-
/**
|
|
149
|
-
|
|
191
|
+
/**
|
|
192
|
+
* The color of quoteSessionLabel: STALE in the warning color every stale
|
|
193
|
+
* mark uses, an extended session's while the overnight session prices the
|
|
194
|
+
* quote, a closed session's for the close a pre-market still stands at.
|
|
195
|
+
*/
|
|
196
|
+
export function quoteSessionColor(quote: Quote | null | undefined, palette: ThemeColors = colors, now = Date.now()): string {
|
|
150
197
|
if (!quote?.marketState) return palette.textDim;
|
|
151
|
-
|
|
198
|
+
if (isQuoteBeforeLatestSession(quote, now)) return palette.warning;
|
|
199
|
+
if (overnightSessionDisplay(quote)) return marketStateColor("POST", palette);
|
|
200
|
+
return marketStateColor(preMarketCloseAwaitingPrint(quote) ? "CLOSED" : quote.marketState, palette);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* The market state a session dot pictures for a quote: none for one whose
|
|
205
|
+
* last print is older than its venue's latest session, so it draws as a quote
|
|
206
|
+
* with no known session rather than an open market.
|
|
207
|
+
*/
|
|
208
|
+
export function quoteDotMarketState(quote: Quote | null | undefined, now = Date.now()): MarketState | undefined {
|
|
209
|
+
return quote && !isQuoteBeforeLatestSession(quote, now) ? quote.marketState : undefined;
|
|
152
210
|
}
|
|
153
211
|
|
|
154
212
|
/** Closed prices are final snapshots, so they should not look live or directional. */
|
|
@@ -181,7 +239,8 @@ export function exchangeShortName(exchangeName?: string, fullExchangeName?: stri
|
|
|
181
239
|
*/
|
|
182
240
|
export function getActiveQuoteDisplay(quote: Quote | null | undefined): ActiveQuoteDisplay | null {
|
|
183
241
|
if (!quote) return null;
|
|
184
|
-
|
|
242
|
+
// A pre-market price of 0 is no print.
|
|
243
|
+
if ((quote.marketState === "PRE" || quote.marketState === "PREPRE") && isPositive(quote.preMarketPrice)) {
|
|
185
244
|
return { price: quote.preMarketPrice, change: quote.preMarketChange, changePercent: quote.preMarketChangePercent };
|
|
186
245
|
}
|
|
187
246
|
const extendedPrice = (quote.marketState === "POST" || quote.marketState === "POSTPOST") ? quote.postMarketPrice : undefined;
|
|
@@ -205,6 +264,8 @@ interface CompletedRegularSession {
|
|
|
205
264
|
close: number;
|
|
206
265
|
/** The close's move from the session before it, when the quote reports it with the close. */
|
|
207
266
|
reported: { change: number; changePercent: number } | null;
|
|
267
|
+
/** The session's exchange-local date when the quote reports it with the close; otherwise the quote's own day. */
|
|
268
|
+
date?: string;
|
|
208
269
|
}
|
|
209
270
|
|
|
210
271
|
function reportedRegularMove(quote: Quote, close: number): CompletedRegularSession["reported"] {
|
|
@@ -236,9 +297,11 @@ function completedRegularSession(quote: Quote): CompletedRegularSession | null {
|
|
|
236
297
|
if (state === "PRE") {
|
|
237
298
|
// The quote's own day is today; the close must be an earlier one, with its move.
|
|
238
299
|
const today = quoteTradingDay(quote);
|
|
239
|
-
return reported && closeDate && today && closeDate < today ? { close, reported } : null;
|
|
300
|
+
return reported && closeDate && today && closeDate < today ? { close, reported, date: closeDate } : null;
|
|
301
|
+
}
|
|
302
|
+
if (closeDate ? closeDate === quoteTradingDay(quote) : state === "POST") {
|
|
303
|
+
return closeDate ? { close, reported, date: closeDate } : { close, reported };
|
|
240
304
|
}
|
|
241
|
-
if (closeDate ? closeDate === quoteTradingDay(quote) : state === "POST") return { close, reported };
|
|
242
305
|
}
|
|
243
306
|
if (state === "POST" && isFiniteNumber(quote.postMarketPrice) && isFiniteNumber(quote.postMarketChange)) {
|
|
244
307
|
const derived = quote.postMarketPrice - quote.postMarketChange;
|
|
@@ -251,6 +314,58 @@ function completedRegularClose(quote: Quote): number | null {
|
|
|
251
314
|
return completedRegularSession(quote)?.close ?? null;
|
|
252
315
|
}
|
|
253
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Whether a pre-market quote's pre-market price is a trade: not missing or
|
|
319
|
+
* 0, not the regular close carried forward, and, when the source projects
|
|
320
|
+
* its last print into the pre-market fields (`projected`), not the quote's
|
|
321
|
+
* own price.
|
|
322
|
+
*/
|
|
323
|
+
function hasPreMarketPrint(quote: Quote, close: number, projected: boolean): boolean {
|
|
324
|
+
const price = quote.preMarketPrice;
|
|
325
|
+
if (!isPositive(price) || price === close) return false;
|
|
326
|
+
return !(projected && price === quote.price);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* The completed regular session a pre-market quote's headline still shows
|
|
331
|
+
* while nothing has traded in the pre-market, its exchange-local date and
|
|
332
|
+
* when it closed, so the quote reads as that close (`Thu close`, at 20:00
|
|
333
|
+
* UTC), not as the pre-market or the after-hours print before it. Only when
|
|
334
|
+
* the quote cannot hold a pre-market trade: never when the source says it
|
|
335
|
+
* does (extendedSessionPrint true); when it says nothing has traded (false),
|
|
336
|
+
* while its pre-market price is no trade (hasPreMarketPrint), its own price
|
|
337
|
+
* included while that was last updated before the pre-market opened; when it
|
|
338
|
+
* does not say, while there is no pre-market price other than the close and
|
|
339
|
+
* its last update is from before the venue's pre-market opened today. Null in
|
|
340
|
+
* any other session, and while the quote cannot say which close its headline
|
|
341
|
+
* is or its venue's hours are unknown.
|
|
342
|
+
*/
|
|
343
|
+
function preMarketCloseAwaitingPrint(quote: Quote | null | undefined): { date: string; closedAt: number } | null {
|
|
344
|
+
if (quote?.marketState !== "PRE" || quote.extendedSessionPrint === true) return null;
|
|
345
|
+
const session = completedRegularSession(quote);
|
|
346
|
+
const today = quoteTradingDay(quote);
|
|
347
|
+
if (!session?.date || !today) return null;
|
|
348
|
+
const exchange = quote.listingExchangeName || quote.exchangeName;
|
|
349
|
+
const opened = preMarketOpenOn(exchange, today);
|
|
350
|
+
// Last updated before today's pre-market opened: the price is carried from the last session.
|
|
351
|
+
const carried = opened != null && Number.isFinite(quote.lastUpdated) && quote.lastUpdated < opened;
|
|
352
|
+
const saysNoTrade = quote.extendedSessionPrint === false;
|
|
353
|
+
if (!saysNoTrade && !carried) return null;
|
|
354
|
+
if (hasPreMarketPrint(quote, session.close, saysNoTrade && carried)) return null;
|
|
355
|
+
const closedAt = regularSessionCloseOn(exchange, session.date);
|
|
356
|
+
return closedAt == null ? null : { date: session.date, closedAt };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* When the price a quote's headline shows was observed: the regular close a
|
|
361
|
+
* pre-market with no trade yet still stands at (preMarketCloseAwaitingPrint),
|
|
362
|
+
* otherwise the quote's last update. What an Updated cell and a report's
|
|
363
|
+
* as-of date the quote by.
|
|
364
|
+
*/
|
|
365
|
+
export function quoteHeadlineTime(quote: Quote): number {
|
|
366
|
+
return preMarketCloseAwaitingPrint(quote)?.closedAt ?? quote.lastUpdated;
|
|
367
|
+
}
|
|
368
|
+
|
|
254
369
|
/**
|
|
255
370
|
* The day's headline: the regular session, which stops at its close. Once it
|
|
256
371
|
* is over, and in the pre-market while the quote carries the last session's
|
|
@@ -286,6 +401,27 @@ export function getCompletedRegularSessionDisplay(quote: Quote | null | undefine
|
|
|
286
401
|
return quote && completedRegularClose(quote) != null ? getRegularSessionDisplay(quote) : null;
|
|
287
402
|
}
|
|
288
403
|
|
|
404
|
+
/**
|
|
405
|
+
* The price a daily, weekly or monthly bar takes from a quote: the regular
|
|
406
|
+
* session's, never an extended print, so a closed market's last bar is the
|
|
407
|
+
* close `history` and `portfolio show --close` give. While the session
|
|
408
|
+
* trades, or when the quote does not say its session, the quote's price. Once
|
|
409
|
+
* it is over, its close as the headline reads it, with that session's date
|
|
410
|
+
* when the quote reports one (in the pre-market it is an earlier day's).
|
|
411
|
+
* Null in the pre-market while the quote cannot say which close that is: a
|
|
412
|
+
* pre-market print is no regular session's price, and today's bar has not
|
|
413
|
+
* opened.
|
|
414
|
+
*/
|
|
415
|
+
export function getRegularSessionBarClose(quote: Quote | null | undefined): { price: number; sessionDate: string | null } | null {
|
|
416
|
+
if (!quote) return null;
|
|
417
|
+
const state = quote.marketState;
|
|
418
|
+
if (state == null || state === "REGULAR") return { price: quote.price, sessionDate: null };
|
|
419
|
+
const session = completedRegularSession(quote);
|
|
420
|
+
if (session) return { price: session.close, sessionDate: session.date ?? null };
|
|
421
|
+
if (state === "PRE" || (state === "PREPRE" && quote.preMarketPrice != null)) return null;
|
|
422
|
+
return { price: quote.price, sessionDate: null };
|
|
423
|
+
}
|
|
424
|
+
|
|
289
425
|
/**
|
|
290
426
|
* The pre-market or after-hours print, measured from the regular close before
|
|
291
427
|
* it, while the quote has one: the pre-market until the open, the after-hours
|
|
@@ -298,9 +434,12 @@ export function getExtendedSessionDisplay(quote: Quote | null | undefined): Exte
|
|
|
298
434
|
if (overnight) return overnight;
|
|
299
435
|
const state = quote.marketState;
|
|
300
436
|
if (state === "PRE" || state === "PREPRE") {
|
|
301
|
-
|
|
437
|
+
// Nothing has traded in the pre-market: its figures are the close carried forward, no print.
|
|
438
|
+
if (state === "PRE" && preMarketCloseAwaitingPrint(quote)) return null;
|
|
439
|
+
// A pre-market price of 0 is no print.
|
|
440
|
+
if (isPositive(quote.preMarketPrice)) {
|
|
302
441
|
// Against the close the headline shows, so the two cannot disagree about it.
|
|
303
|
-
const close = state === "PRE"
|
|
442
|
+
const close = state === "PRE" ? completedRegularClose(quote) : null;
|
|
304
443
|
if (close != null) {
|
|
305
444
|
const change = quote.preMarketPrice - close;
|
|
306
445
|
return { session: "PRE", price: quote.preMarketPrice, change, changePercent: (change / close) * 100 };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { CorporateActionsData, Fundamentals } from "../types/financials";
|
|
2
|
+
import { abortable, settleWithin } from "../utils/async-deadline";
|
|
3
|
+
import { distributionHistory, forwardYieldMayHaveLapsed, lapsedDividend, lastPaidNote, NO_CURRENT_DIVIDEND } from "../utils/forward-dividend";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How long a distribution history must go without a dividend before it says a
|
|
7
|
+
* security pays none: fifteen months, since an annual payer's next ex-date can
|
|
8
|
+
* slip a few weeks past a year (Gloom Cloud withdraws a lapsed yield the same
|
|
9
|
+
* way). Gloom Cloud's history reaches back ten years (SAP's and Novartis's
|
|
10
|
+
* annual dividends from 2017 on), well past this window.
|
|
11
|
+
*/
|
|
12
|
+
const NO_DIVIDEND_WINDOW_MS = 455 * 86_400_000;
|
|
13
|
+
|
|
14
|
+
/** How long the history may take before the yield is left unknown. */
|
|
15
|
+
const HISTORY_DEADLINE_MS = 5_000;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The continuous dividend yield an option model values an underlying at, read
|
|
19
|
+
* the same way by OSA and the options chain's Greeks
|
|
20
|
+
* (docs/research-data.md#greeks-spot-and-time):
|
|
21
|
+
*
|
|
22
|
+
* - `stated`: the yield the underlying's fundamentals state, which the caller
|
|
23
|
+
* reads (0 for a company whose quote affirms it pays none);
|
|
24
|
+
* - `none-paid`: 0, when no yield is stated but its distribution history,
|
|
25
|
+
* current and covering dividends, has none paid or declared in the last
|
|
26
|
+
* fifteen months (a fund that pays none, such as GLD);
|
|
27
|
+
* - `stopped`: 0, when the dividend has stopped by the issuer's own cadence
|
|
28
|
+
* (lapsedDividend, as every pane reads a lapsed forward yield): WHR, last
|
|
29
|
+
* paid 2026-02-27, whose stated 12.91% annualized a payment that did not
|
|
30
|
+
* recur. `lastPaid` dates it.
|
|
31
|
+
*
|
|
32
|
+
* Null when none says: an unknown yield is never taken as 0.
|
|
33
|
+
*/
|
|
34
|
+
export interface ModelDividendYield {
|
|
35
|
+
/** Decimal annual yield. */
|
|
36
|
+
value: number;
|
|
37
|
+
basis: "stated" | "none-paid" | "stopped";
|
|
38
|
+
/** The last distribution's ex-date (YYYY-MM-DD) of a `stopped` dividend; null when unknown. */
|
|
39
|
+
lastPaid?: string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** What the yield is read from: the fundamentals' yield, its basis, and the ex-date of the distribution it annualizes. */
|
|
43
|
+
type StatedDividend = Pick<Fundamentals, "dividendYield" | "dividendYieldBasis" | "exDividendDate">;
|
|
44
|
+
|
|
45
|
+
const symbolKey = (value: string | null | undefined) => (value ?? "").trim().toUpperCase().replace(/[^A-Z0-9]/g, "");
|
|
46
|
+
|
|
47
|
+
/** Whether a history is `symbol`'s own and current, covering dividends. */
|
|
48
|
+
function currentHistory(actions: CorporateActionsData | null | undefined, symbol: string): actions is CorporateActionsData {
|
|
49
|
+
return !!actions && !actions.stale && actions.coverage?.dividends === "available" && symbolKey(actions.symbol) === symbolKey(symbol);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Whether a current history that covers dividends shows none paid or declared for `symbol` in the last fifteen months. */
|
|
53
|
+
function paysNoDividend(actions: CorporateActionsData, now: number): boolean {
|
|
54
|
+
const since = now - NO_DIVIDEND_WINDOW_MS;
|
|
55
|
+
// A date that cannot be read counts as recent: it cannot show the dividend stopped.
|
|
56
|
+
const recent = (exDate: unknown) => {
|
|
57
|
+
const time = typeof exDate === "string" ? Date.parse(`${exDate.slice(0, 10)}T00:00:00Z`) : Number.NaN;
|
|
58
|
+
return !Number.isFinite(time) || time >= since;
|
|
59
|
+
};
|
|
60
|
+
return !actions.dividends.some((dividend) => recent(dividend.exDate))
|
|
61
|
+
&& !(actions.declaredDividends ?? []).some((dividend) => recent(dividend.exDate));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 0, dated by the last distribution, when the current history shows the dividend dated `asOf` stopped (lapsedDividend). */
|
|
65
|
+
function stoppedDividend(asOf: string | undefined, actions: CorporateActionsData, now: number): ModelDividendYield | null {
|
|
66
|
+
const lapse = lapsedDividend(asOf, distributionHistory(actions, new Date(now)), new Date(now));
|
|
67
|
+
return lapse ? { value: 0, basis: "stopped", lastPaid: lapse.lastPaid } : null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface DividendHistoryOptions {
|
|
71
|
+
now?: number;
|
|
72
|
+
/** Stops waiting for the history; the request itself is shared and keeps running. */
|
|
73
|
+
signal?: AbortSignal;
|
|
74
|
+
timeoutMs?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The yield to value `symbol` at: 0 when its distribution history shows the
|
|
79
|
+
* dividend stopped, else `stated` when it is a yield, else 0 when the history
|
|
80
|
+
* shows none paid, else null. The history is read when no yield is stated,
|
|
81
|
+
* and for a forward yield old enough to have lapsed; one that fails, is stale
|
|
82
|
+
* or takes over five seconds leaves a stated yield as it is and an unstated
|
|
83
|
+
* one unknown.
|
|
84
|
+
*/
|
|
85
|
+
export async function loadModelDividendYield(
|
|
86
|
+
stated: StatedDividend | null | undefined,
|
|
87
|
+
symbol: string,
|
|
88
|
+
loadActions: (() => Promise<CorporateActionsData | null | undefined>) | null | undefined,
|
|
89
|
+
{ now = Date.now(), signal, timeoutMs = HISTORY_DEADLINE_MS }: DividendHistoryOptions = {},
|
|
90
|
+
): Promise<ModelDividendYield | null> {
|
|
91
|
+
const value = stated?.dividendYield;
|
|
92
|
+
const statedYield: ModelDividendYield | null = typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
93
|
+
? { value, basis: "stated" } : null;
|
|
94
|
+
const mayHaveLapsed = !!statedYield && statedYield.value > 0 && forwardYieldMayHaveLapsed(stated, new Date(now));
|
|
95
|
+
if ((statedYield && !mayHaveLapsed) || !loadActions) return statedYield;
|
|
96
|
+
const read = await abortable(settleWithin(Promise.resolve().then(loadActions), timeoutMs), signal, "Dividend history read was cancelled");
|
|
97
|
+
const actions = currentHistory(read, symbol) ? read : null;
|
|
98
|
+
if (!actions) return statedYield;
|
|
99
|
+
if (statedYield) return stoppedDividend(stated?.exDividendDate, actions, now) ?? statedYield;
|
|
100
|
+
if (paysNoDividend(actions, now)) return { value: 0, basis: "none-paid" };
|
|
101
|
+
return stoppedDividend(stated?.exDividendDate, actions, now);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** What a yield the history shows none paid is, beside the 0%: `no dividend in the last 15 months`. */
|
|
105
|
+
const NO_DIVIDEND_PAID = "no dividend in the last 15 months";
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* What a yield read as 0 is, beside the 0%: `no dividend in the last 15
|
|
109
|
+
* months`, or `no current dividend, last paid 2026-02-27` in the words every
|
|
110
|
+
* pane reads a stopped dividend in. Null for a stated yield.
|
|
111
|
+
*/
|
|
112
|
+
export function modelDividendYieldNote(dividend: Pick<ModelDividendYield, "basis" | "lastPaid"> | null | undefined): string | null {
|
|
113
|
+
if (dividend?.basis === "none-paid") return NO_DIVIDEND_PAID;
|
|
114
|
+
if (dividend?.basis !== "stopped") return null;
|
|
115
|
+
const lastPaid = lastPaidNote({ lastPaid: dividend.lastPaid ?? null });
|
|
116
|
+
return lastPaid ? `${NO_CURRENT_DIVIDEND}, ${lastPaid}` : NO_CURRENT_DIVIDEND;
|
|
117
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { Quote } from "../../types/financials";
|
|
2
|
-
import { isUsListingExchange } from "../../utils/exchanges";
|
|
2
|
+
import { canonicalExchange, isUsListingExchange } from "../../utils/exchanges";
|
|
3
3
|
import { zonedDateKey } from "../../utils/zoned-date-time";
|
|
4
4
|
import { getPublishedUsEquitySession } from "../published-us-sessions";
|
|
5
5
|
import { quoteFutureToleranceMs } from "./clock";
|
|
6
6
|
import {
|
|
7
7
|
activeUsExtendedHoursSession,
|
|
8
|
+
isAlwaysOpenExchange,
|
|
8
9
|
isTimestampStaleForExchangeSession,
|
|
9
10
|
isUsPriorSessionPremarketQuote,
|
|
10
11
|
isUsRegularCloseQuoteInPostSession,
|
|
12
|
+
latestRegularSessionClose,
|
|
13
|
+
latestRegularSessionOpen,
|
|
11
14
|
} from "../market/freshness";
|
|
12
15
|
|
|
13
16
|
// Give the next regular session's NAV time to publish after its actual close.
|
|
@@ -90,6 +93,32 @@ export function isQuoteStaleForCurrentSession(quote: Quote | null | undefined, n
|
|
|
90
93
|
);
|
|
91
94
|
}
|
|
92
95
|
|
|
96
|
+
/** Spot FX: its week is in `fx-market-hours`, not a session calendar. */
|
|
97
|
+
const FX_VENUE = "CCY";
|
|
98
|
+
/** Every venue with sessions has had one within this long; Spring Festival can close TWSE for twelve days. */
|
|
99
|
+
const LONGEST_SESSION_GAP_MS = 14 * 24 * 60 * 60_000;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Whether a quote's last print is older than its venue's latest completed
|
|
103
|
+
* regular session: a whole session traded since, so the state its source
|
|
104
|
+
* reports says where the market is, not where this price is (a delisted
|
|
105
|
+
* line read as OPEN). Only a quote already stale for its session can be;
|
|
106
|
+
* the last session's close before the open, an after-hours print after it,
|
|
107
|
+
* and round-the-clock venues and FX keep their state. A venue without a
|
|
108
|
+
* calendar counts a print older than any venue goes between sessions.
|
|
109
|
+
*/
|
|
110
|
+
export function isQuoteBeforeLatestSession(quote: Quote | null | undefined, now = Date.now()): boolean {
|
|
111
|
+
if (!quote || !isQuoteStaleForCurrentSession(quote, now)) return false;
|
|
112
|
+
const venue = canonicalExchange(quote.listingExchangeName || quote.exchangeName);
|
|
113
|
+
if (venue === FX_VENUE || isAlwaysOpenExchange(venue)) return false;
|
|
114
|
+
const printed = quote.lastUpdated;
|
|
115
|
+
if (!Number.isFinite(printed) || printed <= 0 || printed > now) return false;
|
|
116
|
+
const latest = latestRegularSessionClose(venue, now);
|
|
117
|
+
if (!latest) return now - printed > LONGEST_SESSION_GAP_MS;
|
|
118
|
+
const open = latestRegularSessionOpen(venue, latest.close);
|
|
119
|
+
return open != null ? printed < open : zonedDateKey(printed, latest.timeZone) < latest.date;
|
|
120
|
+
}
|
|
121
|
+
|
|
93
122
|
export function hasFreshQuoteForCurrentSession(
|
|
94
123
|
quotes: Iterable<Quote | null | undefined>,
|
|
95
124
|
now = Date.now(),
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { AnalystResearchData, Fundamentals, Quote } from "
|
|
2
|
-
import { atRegularSessionPrice, regularSessionValuationPrice } from "
|
|
3
|
-
import { hasLikelyQuoteUnitMismatch } from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import type { AnalystResearchData, CorporateActionsData, Fundamentals, Quote } from "../../types/financials";
|
|
2
|
+
import { atRegularSessionPrice, regularSessionValuationPrice } from "./regular-session-valuation";
|
|
3
|
+
import { hasLikelyQuoteUnitMismatch, resolveCurrencyUnit } from "../../utils/currency-units";
|
|
4
|
+
import { cashInMajorUnits } from "../../utils/dividend-cash";
|
|
5
|
+
import { cashDistribution, dividendReferencePrice, trailingDividendYield, type CashDistribution } from "../../utils/trailing-dividend";
|
|
6
|
+
import { priceEarningsEps } from "../../utils/fundamentals";
|
|
7
|
+
import { selectMarketCapitalization, type MarketCapitalization } from "../../utils/market-capitalization";
|
|
8
|
+
import { priceEarningsOnEarnings, type PriceEarnings } from "../../utils/price-earnings";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Price-derived statistics repriced at the quote's regular session price
|
|
@@ -89,6 +91,50 @@ export function liveDividendYield(quote: Quote | null | undefined, fundamentals:
|
|
|
89
91
|
return rate / price;
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
/** Whether a listing's yield is a trailing one, which is measured from its cash history (listingDividendYield). */
|
|
95
|
+
export function measuresTrailingYield(fundamentals: Pick<Fundamentals, "dividendYield" | "dividendYieldBasis"> | null | undefined): boolean {
|
|
96
|
+
return fundamentals?.dividendYieldBasis === "trailing" && fundamentals.dividendYield != null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* A trailing dividend yield as DVD measures it (trailingDividendYield): the
|
|
101
|
+
* cash history's trailing twelve months over the quote's regular session
|
|
102
|
+
* price, in the cash's currency. Null when the history cannot be read in full
|
|
103
|
+
* (a row that is no paid distribution, no currency, dividends not covered) or
|
|
104
|
+
* the price is in another currency, where DVD leaves its own blank.
|
|
105
|
+
*/
|
|
106
|
+
export function historyTrailingDividendYield(
|
|
107
|
+
sourceActions: CorporateActionsData,
|
|
108
|
+
quote: Quote | null | undefined,
|
|
109
|
+
now = new Date(),
|
|
110
|
+
): number | null {
|
|
111
|
+
const actions = cashInMajorUnits(sourceActions);
|
|
112
|
+
const currency = resolveCurrencyUnit(actions.currency).currency;
|
|
113
|
+
if (!currency || !Array.isArray(actions.dividends) || actions.coverage?.dividends === "unavailable") return null;
|
|
114
|
+
if (actions.coverage?.dividends !== "available" && actions.dividends.length === 0) return null;
|
|
115
|
+
const payments = actions.dividends.map((row) => cashDistribution(row.exDate, row.amount));
|
|
116
|
+
if (payments.some((payment) => payment == null)) return null;
|
|
117
|
+
const price = dividendReferencePrice(regularSessionValuationPrice(quote), quote?.currency, currency);
|
|
118
|
+
return trailingDividendYield(payments as CashDistribution[], price, now);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The dividend yield a listing shows at its regular session price. A trailing
|
|
123
|
+
* one is DVD's, measured from `actions`, the listing's cash history
|
|
124
|
+
* (historyTrailingDividendYield), so the overview, DIV% and DVD read one
|
|
125
|
+
* figure; until that history is read, or when it cannot be read in full, it
|
|
126
|
+
* is Gloom Cloud's, as a forward one is (liveDividendYield).
|
|
127
|
+
*/
|
|
128
|
+
export function listingDividendYield(
|
|
129
|
+
quote: Quote | null | undefined,
|
|
130
|
+
fundamentals: Fundamentals | undefined,
|
|
131
|
+
actions: CorporateActionsData | null | undefined,
|
|
132
|
+
now = new Date(),
|
|
133
|
+
): number | undefined {
|
|
134
|
+
const measured = actions && measuresTrailingYield(fundamentals) ? historyTrailingDividendYield(actions, quote, now) : null;
|
|
135
|
+
return measured ?? liveDividendYield(quote, fundamentals);
|
|
136
|
+
}
|
|
137
|
+
|
|
92
138
|
/**
|
|
93
139
|
* Whether a capitalization's implied share price is one this listing traded
|
|
94
140
|
* at: the prior close (a source capitalization) or anywhere in the session
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { EnterpriseValueCheck, Fundamentals, Quote, TickerFinancials } from "../../types/financials";
|
|
2
2
|
import { priceEarningsEps } from "../../utils/fundamentals";
|
|
3
|
-
import {
|
|
3
|
+
import type { ReportTime } from "../../utils/utc-time";
|
|
4
|
+
import { latestRegularSessionClose } from "../market/freshness";
|
|
5
|
+
import { getCompletedRegularSessionDisplay, getRegularSessionDisplay } from "../market/status";
|
|
6
|
+
import { quoteTradingDay } from "./day-range";
|
|
4
7
|
|
|
5
8
|
function positive(value: number | null | undefined): value is number {
|
|
6
9
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
@@ -19,6 +22,34 @@ export function regularSessionValuationPrice(quote: Quote | null | undefined): n
|
|
|
19
22
|
return positive(price) ? price : null;
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
/**
|
|
26
|
+
* When the completed regular session the quote reports closed: the venue's
|
|
27
|
+
* close on that day from its calendar, or the day alone when the calendar does
|
|
28
|
+
* not give the hour.
|
|
29
|
+
*/
|
|
30
|
+
function regularCloseTime(quote: Quote): ReportTime | null {
|
|
31
|
+
const date = quote.regularCloseSessionDate ?? quoteTradingDay(quote);
|
|
32
|
+
const exchange = quote.listingExchangeName || quote.exchangeName;
|
|
33
|
+
const close = exchange && Number.isFinite(quote.lastUpdated) ? latestRegularSessionClose(exchange, quote.lastUpdated) : null;
|
|
34
|
+
if (close && (!date || close.date === date)) return { time: close.close, dateOnly: false };
|
|
35
|
+
const day = date ? Date.parse(`${date}T00:00:00Z`) : Number.NaN;
|
|
36
|
+
return Number.isFinite(day) ? { time: day, dateOnly: true } : null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* When the price regularSessionValuationPrice reads is from: once the regular
|
|
41
|
+
* session is over (and in the pre-market while the quote carries the last
|
|
42
|
+
* session's close), that session's close; while it trades, the quote's own
|
|
43
|
+
* time. A figure measured at that price is dated by it, never by an
|
|
44
|
+
* after-hours or pre-market print. Null without a dated quote.
|
|
45
|
+
*/
|
|
46
|
+
export function regularSessionValuationTime(quote: Quote | null | undefined): ReportTime | null {
|
|
47
|
+
if (!quote) return null;
|
|
48
|
+
const close = getCompletedRegularSessionDisplay(quote) ? regularCloseTime(quote) : null;
|
|
49
|
+
if (close) return close;
|
|
50
|
+
return Number.isFinite(quote.lastUpdated) && quote.lastUpdated > 0 ? { time: quote.lastUpdated, dateOnly: false } : null;
|
|
51
|
+
}
|
|
52
|
+
|
|
22
53
|
function scaled(value: number | undefined, ratio: number): number | undefined {
|
|
23
54
|
return value != null && Number.isFinite(value) ? value * ratio : value;
|
|
24
55
|
}
|