@gloom-sh/terminal 0.18.5 → 0.19.1
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +163 -8
- package/src/api-client/app-attention.ts +3 -0
- package/src/api-client/beneficial-owners.ts +3 -0
- package/src/api-client/company-kpis.ts +3 -0
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +19 -7
- package/src/api-client/equity-screener.ts +24 -0
- package/src/api-client/fund-facts.ts +45 -4
- package/src/api-client/hiring.ts +3 -0
- package/src/api-client/index.ts +15 -0
- package/src/api-client/ipo.ts +24 -1
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/market-movers.ts +7 -0
- package/src/api-client/members.ts +1 -1
- package/src/api-client/mna.ts +3 -0
- package/src/api-client/paths.ts +9 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/research-activity.ts +3 -2
- package/src/api-client/roadmap.ts +85 -0
- package/src/api-client/types.ts +82 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +0 -2
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/core-builtin-allowlist.json +2 -2
- package/src/architecture/pane-tabs-allowlist.json +3 -0
- package/src/architecture/ttl-caches-allowlist.json +19 -0
- package/src/brokers/sync-broker-instance.ts +2 -8
- package/src/capabilities/chart-series.ts +1 -1
- package/src/cli/commands/crypto-hints.ts +40 -24
- package/src/cli/commands/market.ts +107 -38
- package/src/cli/commands/news-search.ts +22 -0
- package/src/cli/commands/options-chain.ts +48 -7
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +147 -32
- package/src/cli/commands/search.ts +21 -1
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +87 -36
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +25 -2
- package/src/cli/glossary.ts +31 -2
- package/src/cli/history-rows.ts +57 -9
- package/src/cli/index-roots.ts +0 -7
- package/src/cli/index.ts +2 -0
- package/src/cli/listing-arg.ts +235 -60
- package/src/cli/output-file.ts +68 -0
- package/src/cli/pane-functions/capabilities.ts +4 -0
- package/src/cli/pane-functions/catalog.ts +80 -7
- package/src/cli/pane-functions/discovery.ts +21 -1
- package/src/cli/pane-functions/dom.ts +13 -3
- package/src/cli/pane-functions/freshness.ts +93 -4
- package/src/cli/pane-functions/function-help.ts +20 -10
- package/src/cli/pane-functions/headless.ts +17 -7
- package/src/cli/pane-functions/index.ts +54 -16
- package/src/cli/pane-functions/market-session.ts +66 -4
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/resolver.ts +19 -8
- package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
- package/src/cli/pane-functions/screenshot-types.ts +5 -0
- package/src/cli/quote-answer.ts +22 -11
- package/src/cli/saved-copy-persistence.ts +88 -0
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +4 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-surface.tsx +52 -3
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +39 -4
- package/src/components/chart/composite/series-cues.ts +14 -0
- package/src/components/chart/composite/text-renderer.ts +9 -2
- package/src/components/chart/composite/tool-catalog.ts +36 -0
- package/src/components/chart/composite/tools.ts +203 -44
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
- package/src/components/command-bar/assist/inventory.ts +2 -1
- package/src/components/command-bar/commands/direct/index.ts +28 -13
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/pane-templates/items.ts +3 -2
- package/src/components/command-bar/routes/root/runtime.ts +6 -7
- package/src/components/command-bar/selection-runtime.ts +52 -3
- package/src/components/command-bar/surface/index.tsx +2 -0
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/layout/pane/capture-stamp.ts +2 -2
- package/src/components/layout/pane/footer/index.tsx +22 -6
- package/src/components/layout/pane/footer/model.ts +83 -15
- package/src/components/layout/pane/status-footer.ts +35 -2
- package/src/components/layout/status-widget-space.ts +9 -0
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +12 -7
- package/src/components/onboarding/wizard-broker-sync.ts +0 -1
- package/src/components/onboarding/wizard-positions.ts +3 -3
- package/src/components/ticker/list-table-view.tsx +8 -21
- package/src/components/ui/choice-dialog.tsx +23 -18
- package/src/components/ui/choice-groups.ts +18 -0
- package/src/components/ui/data-table/opentui/index.tsx +9 -7
- package/src/components/ui/data-table/opentui/model.ts +26 -1
- package/src/components/ui/data-table/types.ts +2 -0
- package/src/components/ui/display.tsx +18 -3
- package/src/components/ui/icon.tsx +4 -1
- package/src/components/ui/list-view.tsx +8 -4
- package/src/components/ui/query-bar-keys.tsx +2 -0
- package/src/components/ui/query-bar.tsx +1 -0
- package/src/components/ui/select-button.tsx +5 -1
- package/src/components/ui/select-field.tsx +1 -0
- package/src/components/ui/table-layout.ts +8 -5
- package/src/core/app-runtime.ts +2 -0
- package/src/core/app-services.ts +2 -2
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/plugin-cache.ts +5 -3
- package/src/data/saved-copies.ts +8 -0
- package/src/data/ticker-repository.ts +16 -9
- package/src/data/ticker-writes.ts +81 -0
- package/src/data/ttl-cache.ts +165 -0
- package/src/docs/snapshot.json +103 -142
- package/src/i18n/es.ts +20 -6
- package/src/i18n/ja.ts +20 -6
- package/src/i18n/ko.ts +20 -6
- package/src/i18n/zh-cn.ts +20 -6
- package/src/i18n/zh-tw.ts +20 -6
- package/src/market-data/depositary-pair.ts +27 -3
- package/src/market-data/fund-facts.ts +50 -0
- package/src/market-data/market/change-basis.ts +16 -3
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/options-alternatives.ts +81 -4
- package/src/market-data/quotes/metadata.ts +7 -0
- package/src/news/aggregator.ts +119 -9
- package/src/news/cloud-session.ts +21 -0
- package/src/news/hooks.ts +1 -0
- package/src/news/news-model.ts +1 -0
- package/src/news/types.ts +17 -0
- package/src/plugins/builtin/alerts/alert-engine.ts +20 -1
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/calendar-events.ts +10 -4
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +362 -80
- package/src/plugins/builtin/alerts/command.ts +25 -1
- package/src/plugins/builtin/alerts/event-rows.ts +24 -3
- package/src/plugins/builtin/alerts/events-pane.tsx +34 -10
- package/src/plugins/builtin/alerts/fired-log.ts +73 -9
- package/src/plugins/builtin/alerts/format.ts +75 -5
- package/src/plugins/builtin/alerts/headless.ts +34 -12
- package/src/plugins/builtin/alerts/history-rows.ts +3 -2
- package/src/plugins/builtin/alerts/history.ts +1 -1
- package/src/plugins/builtin/alerts/index.tsx +79 -16
- package/src/plugins/builtin/alerts/metric-command.ts +77 -4
- package/src/plugins/builtin/alerts/metric-data.ts +54 -13
- package/src/plugins/builtin/alerts/metric-model.ts +163 -14
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +1 -1
- package/src/plugins/builtin/alerts/pane.tsx +61 -23
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +12 -8
- package/src/plugins/builtin/alerts/types.ts +4 -0
- package/src/plugins/builtin/analytics/index.tsx +2 -1
- package/src/plugins/builtin/analytics/risk-client.ts +16 -5
- package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
- package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
- package/src/plugins/builtin/analytics/risk-model.ts +55 -9
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
- package/src/plugins/builtin/attention/index.tsx +2 -1
- package/src/plugins/builtin/attention/listing.ts +14 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/buildout/cells.tsx +12 -4
- package/src/plugins/builtin/buildout/format.ts +38 -0
- package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
- package/src/plugins/builtin/buildout/table-model.ts +23 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +6 -2
- package/src/plugins/builtin/cds/client.ts +142 -30
- package/src/plugins/builtin/cds/headless.ts +35 -8
- package/src/plugins/builtin/cds/model.ts +145 -18
- package/src/plugins/builtin/cds/pane.tsx +16 -5
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +3 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +4 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -0
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -2
- package/src/plugins/builtin/chart-composer/follow-binding.ts +14 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +7 -1
- package/src/plugins/builtin/chart-composer/headless.ts +6 -1
- package/src/plugins/builtin/chart-composer/index.tsx +5 -6
- package/src/plugins/builtin/chart-composer/pane.tsx +37 -8
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chat/content/command-suggestions.ts +1 -0
- package/src/plugins/builtin/chat/controller/index.ts +5 -1
- package/src/plugins/builtin/chat/controller/notifications.ts +33 -3
- package/src/plugins/builtin/chat/controller/state.ts +25 -2
- package/src/plugins/builtin/chat/controller/unread-people.ts +89 -23
- package/src/plugins/builtin/chat/controller/utils.ts +7 -2
- package/src/plugins/builtin/chat/pane-links/commands.ts +7 -1
- package/src/plugins/builtin/chat/status-preview.ts +79 -0
- package/src/plugins/builtin/chat/status-widget.tsx +147 -10
- package/src/plugins/builtin/chat/unread-badge.ts +51 -10
- package/src/plugins/builtin/clinical-trials/client.ts +49 -4
- package/src/plugins/builtin/clinical-trials/model.ts +86 -31
- package/src/plugins/builtin/clinical-trials/pane.tsx +61 -49
- package/src/plugins/builtin/clinical-trials/sponsor-listing.ts +90 -0
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +95 -15
- package/src/plugins/builtin/clinical-trials/trial-pages.ts +50 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
- package/src/plugins/builtin/company-attention/building.tsx +5 -1
- package/src/plugins/builtin/company-attention/client.ts +8 -9
- package/src/plugins/builtin/company-attention/evidence.ts +4 -1
- package/src/plugins/builtin/company-attention/headless.ts +2 -1
- package/src/plugins/builtin/company-attention/moves.tsx +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +12 -2
- package/src/plugins/builtin/company-attention/signals.tsx +5 -1
- package/src/plugins/builtin/company-kpis/headless.ts +8 -3
- package/src/plugins/builtin/company-kpis/model.ts +73 -5
- package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/correlation/headless.ts +13 -5
- package/src/plugins/builtin/correlation/history.ts +22 -0
- package/src/plugins/builtin/cot/client.ts +22 -18
- package/src/plugins/builtin/cot/headless.ts +15 -10
- package/src/plugins/builtin/cot/model.ts +14 -1
- package/src/plugins/builtin/cot/pane.tsx +22 -14
- package/src/plugins/builtin/credit-boards/client.ts +6 -10
- package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
- package/src/plugins/builtin/credit-conditions/model.ts +4 -0
- package/src/plugins/builtin/credit-conditions/series.ts +3 -1
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
- package/src/plugins/builtin/credit-documents/export.ts +173 -0
- package/src/plugins/builtin/credit-documents/headless.ts +10 -10
- package/src/plugins/builtin/credit-documents/model.ts +104 -14
- package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
- package/src/plugins/builtin/custom-view/sources.ts +2 -0
- package/src/plugins/builtin/dividend-yield/client.ts +131 -23
- package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
- package/src/plugins/builtin/dividend-yield/model.ts +8 -5
- package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
- package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
- package/src/plugins/builtin/dividend-yield/types.ts +20 -2
- package/src/plugins/builtin/dividend-yield/view.ts +30 -2
- package/src/plugins/builtin/docs/targets.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +3 -2
- package/src/plugins/builtin/doe/pane.tsx +13 -3
- package/src/plugins/builtin/earnings/board-model.ts +16 -15
- package/src/plugins/builtin/earnings/board.tsx +62 -71
- package/src/plugins/builtin/earnings/headless.ts +40 -4
- package/src/plugins/builtin/earnings/scope.ts +31 -43
- package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
- package/src/plugins/builtin/earnings-calls/data.ts +18 -6
- package/src/plugins/builtin/earnings-calls/format.ts +31 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +20 -5
- package/src/plugins/builtin/earnings-calls/model.ts +6 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +12 -4
- package/src/plugins/builtin/econ/calendar-model.ts +48 -1
- package/src/plugins/builtin/econ/calendar-source.ts +4 -2
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/figures.ts +48 -0
- package/src/plugins/builtin/econ/index.tsx +14 -5
- package/src/plugins/builtin/econ/print-watch.ts +3 -1
- package/src/plugins/builtin/econ/types.ts +2 -0
- package/src/plugins/builtin/econ-statistics/client.ts +11 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +16 -6
- package/src/plugins/builtin/econ-statistics/pane.tsx +8 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +39 -9
- package/src/plugins/builtin/equity-screener/categories.ts +179 -0
- package/src/plugins/builtin/equity-screener/client.ts +4 -2
- package/src/plugins/builtin/equity-screener/headless.ts +144 -13
- package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
- package/src/plugins/builtin/equity-screener/model.ts +99 -10
- package/src/plugins/builtin/equity-screener/pane.tsx +68 -13
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
- package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
- package/src/plugins/builtin/fx-matrix/client.ts +6 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +1 -1
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -2
- package/src/plugins/builtin/fx-matrix/live-legs.ts +42 -3
- package/src/plugins/builtin/gpu/headless.ts +8 -2
- package/src/plugins/builtin/help/function-index.ts +4 -1
- package/src/plugins/builtin/help/index.tsx +62 -59
- package/src/plugins/builtin/help/shortcut-model.ts +1 -1
- package/src/plugins/builtin/help/shortcut-table.tsx +5 -6
- package/src/plugins/builtin/help/table-cells.tsx +13 -2
- package/src/plugins/builtin/holders/beneficial-client.ts +5 -1
- package/src/plugins/builtin/holders/beneficial-view.tsx +3 -0
- package/src/plugins/builtin/holders/fund-holders.ts +51 -0
- package/src/plugins/builtin/holders/headless.ts +22 -3
- package/src/plugins/builtin/holders/pane.tsx +3 -0
- package/src/plugins/builtin/holders/report-rows.ts +4 -1
- package/src/plugins/builtin/insider/headless.ts +2 -2
- package/src/plugins/builtin/ipo-calendar/client.ts +18 -2
- package/src/plugins/builtin/ipo-calendar/headless.ts +75 -11
- package/src/plugins/builtin/ipo-calendar/listing-ipo.ts +160 -0
- package/src/plugins/builtin/ipo-calendar/model.ts +98 -2
- package/src/plugins/builtin/iv-history/client.ts +52 -11
- package/src/plugins/builtin/iv-history/format.ts +36 -23
- package/src/plugins/builtin/iv-history/headless.ts +33 -18
- package/src/plugins/builtin/iv-history/index.tsx +2 -2
- package/src/plugins/builtin/iv-history/model.ts +163 -27
- package/src/plugins/builtin/iv-history/pane.tsx +10 -6
- package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
- package/src/plugins/builtin/iv-history/universe.ts +5 -1
- package/src/plugins/builtin/jobs/client.ts +25 -29
- package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
- package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
- package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
- package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
- package/src/plugins/builtin/macro-day/headless.ts +12 -5
- package/src/plugins/builtin/macro-day/index.tsx +1 -1
- package/src/plugins/builtin/macro-day/model.ts +39 -5
- package/src/plugins/builtin/macro-day/pane.tsx +27 -19
- package/src/plugins/builtin/macro-day/release-table.ts +2 -2
- package/src/plugins/builtin/market-heatmap/data.ts +8 -33
- package/src/plugins/builtin/market-movers/client.ts +27 -7
- package/src/plugins/builtin/market-movers/headless.ts +34 -12
- package/src/plugins/builtin/market-movers/index.tsx +26 -14
- package/src/plugins/builtin/market-movers/min-float.ts +74 -0
- package/src/plugins/builtin/market-movers/model.ts +4 -1
- package/src/plugins/builtin/market-movers/screener.ts +22 -4
- package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
- package/src/plugins/builtin/market-movers/session-table.ts +4 -3
- package/src/plugins/builtin/market-movers/table.ts +17 -5
- package/src/plugins/builtin/members/breadth-pane.tsx +2 -1
- package/src/plugins/builtin/mna/headless.ts +2 -0
- package/src/plugins/builtin/mna/pane.tsx +3 -1
- package/src/plugins/builtin/news/headless.ts +3 -1
- package/src/plugins/builtin/news/index.tsx +4 -0
- package/src/plugins/builtin/news/wire/categories.ts +19 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
- package/src/plugins/builtin/openfda/client.ts +14 -2
- package/src/plugins/builtin/openfda/index.tsx +3 -2
- package/src/plugins/builtin/openfda/model.ts +9 -0
- package/src/plugins/builtin/openfda/pane.tsx +42 -6
- package/src/plugins/builtin/options/analytics.ts +29 -5
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/table.ts +5 -2
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +17 -4
- package/src/plugins/builtin/options-positioning/client.ts +11 -0
- package/src/plugins/builtin/options-positioning/headless.ts +21 -8
- package/src/plugins/builtin/options-positioning/index.tsx +1 -1
- package/src/plugins/builtin/options-positioning/model.ts +78 -9
- package/src/plugins/builtin/options-positioning/pane.tsx +21 -6
- package/src/plugins/builtin/options-scenario/client.ts +116 -47
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
- package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
- package/src/plugins/builtin/options-scenario/csp.ts +8 -2
- package/src/plugins/builtin/options-scenario/index.tsx +9 -7
- package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
- package/src/plugins/builtin/pe-band/model.ts +12 -49
- package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
- package/src/plugins/builtin/perps/cascade.ts +236 -0
- package/src/plugins/builtin/perps/client.ts +56 -2
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +19 -22
- package/src/plugins/builtin/perps/status-line.ts +25 -0
- package/src/plugins/builtin/plugin-module.ts +5 -1
- package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
- package/src/plugins/builtin/portfolio-list/cli/render.ts +7 -5
- package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -7
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +0 -14
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +5 -2
- package/src/plugins/builtin/portfolio-list/table.tsx +15 -9
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/realized-vol/client.ts +13 -5
- package/src/plugins/builtin/realized-vol/evidence.ts +29 -4
- package/src/plugins/builtin/realized-vol/headless.ts +8 -4
- package/src/plugins/builtin/realized-vol/index.tsx +2 -2
- package/src/plugins/builtin/realized-vol/model.ts +37 -6
- package/src/plugins/builtin/realized-vol/pane.tsx +11 -9
- package/src/plugins/builtin/relative-rotation/client.ts +18 -4
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
- package/src/plugins/builtin/relative-rotation/model.ts +16 -40
- package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
- package/src/plugins/builtin/research/event-model.ts +40 -12
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/index.tsx +7 -3
- package/src/plugins/builtin/research/relative-valuation-headless.ts +13 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +59 -20
- package/src/plugins/builtin/research/relative-valuation-peers.ts +217 -20
- package/src/plugins/builtin/research/relative-valuation-settings.ts +44 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
- package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
- package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
- package/src/plugins/builtin/risk-factors/data.ts +4 -2
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/roadmap/index.tsx +28 -0
- package/src/plugins/builtin/roadmap/model.ts +67 -0
- package/src/plugins/builtin/roadmap/pane.tsx +244 -0
- package/src/plugins/builtin/scanner/flow-model.ts +50 -4
- package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
- package/src/plugins/builtin/scanner/flow-session.ts +146 -0
- package/src/plugins/builtin/scanner/headless.ts +204 -35
- package/src/plugins/builtin/scanner/index.ts +16 -5
- package/src/plugins/builtin/scanner/live-headless.ts +48 -5
- package/src/plugins/builtin/scanner/live-model.ts +11 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +3 -3
- package/src/plugins/builtin/scanner/lock-note.ts +3 -2
- package/src/plugins/builtin/seasonality/headless.ts +10 -1
- package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
- package/src/plugins/builtin/sec/fund-facts.ts +116 -34
- package/src/plugins/builtin/sec/headless.ts +4 -2
- package/src/plugins/builtin/sec/index.tsx +3 -0
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +16 -7
- package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
- package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
- package/src/plugins/builtin/shared/earnings-report.ts +2 -2
- package/src/plugins/builtin/shared/headless-market-data.ts +2 -2
- package/src/plugins/builtin/shared/job-posting.ts +1 -0
- package/src/plugins/builtin/shared/members-menu.tsx +3 -2
- package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
- package/src/plugins/builtin/shared/report-freshness.ts +11 -2
- package/src/plugins/builtin/shared/research-cells.tsx +1 -1
- package/src/plugins/builtin/shared/series-cache.ts +4 -4
- package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
- package/src/plugins/builtin/shared/ticker-company.ts +77 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +2 -1
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +19 -0
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/model.ts +16 -7
- package/src/plugins/builtin/themes/pane.tsx +5 -5
- package/src/plugins/builtin/thirteenf/api.ts +12 -1
- package/src/plugins/builtin/thirteenf/data.ts +7 -7
- package/src/plugins/builtin/thirteenf/headless.ts +31 -4
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
- package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
- package/src/plugins/builtin/ticker-detail/overview/model.ts +11 -3
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +14 -8
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -19
- package/src/plugins/builtin/treasury-auctions/headless.ts +21 -12
- package/src/plugins/builtin/treasury-auctions/pane.tsx +9 -3
- package/src/plugins/builtin/treasury-daily/client.ts +41 -5
- package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
- package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
- package/src/plugins/builtin/treasury-daily/model.ts +50 -3
- package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
- package/src/plugins/builtin/vol-surface/client.ts +3 -13
- package/src/plugins/builtin/vol-surface/headless.ts +3 -3
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/vol-surface/pane.tsx +7 -5
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +7 -4
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/builtin/yield-curve/client.ts +61 -1
- package/src/plugins/builtin/yield-curve/headless.ts +9 -6
- package/src/plugins/builtin/yield-curve/index.tsx +34 -10
- package/src/plugins/builtin/yield-curve/swaps.tsx +9 -5
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/host-link.ts +1 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/column-values.ts +11 -7
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/remote/resources.ts +2 -1
- package/src/renderers/dom/data-table/row.tsx +26 -0
- package/src/renderers/dom/desktop/icons.tsx +7 -0
- package/src/renderers/dom/desktop/list-view.tsx +13 -10
- package/src/renderers/dom/desktop/query-bar.tsx +4 -2
- package/src/renderers/dom/desktop/select-field.tsx +4 -2
- package/src/renderers/dom/host/chart-surface.tsx +21 -0
- package/src/renderers/electrobun/bun/desktop/app-name.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend.ts +21 -10
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +15 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/installer-folder.ts +731 -0
- package/src/renderers/electrobun/bun/desktop/relaunch.ts +102 -10
- package/src/renderers/electrobun/bun/desktop/update.ts +115 -14
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/bun/desktop/windows-script.ts +92 -0
- package/src/renderers/electrobun/bun/index.ts +26 -2
- package/src/renderers/electrobun/bun/window/create.ts +43 -4
- package/src/renderers/electrobun/bun/window/events.ts +20 -0
- package/src/renderers/electrobun/bun/window/windows-custom-chrome.ts +9 -2
- package/src/renderers/electrobun/bun/window/windows-native.ts +78 -0
- package/src/renderers/electrobun/bun/window/windows-quit.ts +57 -0
- package/src/renderers/electrobun/shared/app-name.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +12 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
- package/src/renderers/electrobun/view/main.tsx +24 -1
- package/src/renderers/electrobun/view/news-source.ts +5 -1
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
- package/src/renderers/electrobun/view/ui-host.tsx +8 -0
- package/src/renderers/electrobun/view/view-ids.ts +85 -0
- package/src/renderers/opentui/start.tsx +5 -0
- package/src/series/registry.ts +1 -0
- package/src/series/types.ts +6 -0
- package/src/series/validate.ts +1 -0
- package/src/sources/gloomberb-cloud/fred-series.ts +3 -1
- package/src/sources/gloomberb-cloud/index.ts +43 -8
- package/src/sources/gloomberb-cloud/news.ts +47 -7
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/index.ts +8 -5
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/controller.ts +4 -3
- package/src/sync/core-contributors.ts +90 -31
- package/src/telemetry/stall-reports-dom.ts +38 -0
- package/src/telemetry/stall-reports-node.ts +75 -0
- package/src/telemetry/stall-reports.ts +214 -0
- package/src/test-support/preload.ts +14 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name-listing.ts +53 -13
- package/src/tickers/company-name.ts +50 -4
- package/src/tickers/index-roots.ts +7 -0
- package/src/tickers/listing-fate.ts +2 -2
- package/src/tickers/listing-venues.ts +15 -3
- package/src/tickers/search/index.ts +6 -2
- package/src/tickers/search/ranking.ts +5 -1
- package/src/tickers/search/upsert.ts +13 -0
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/tickers/ticker-changes.ts +8 -4
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +1 -1
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/fundamentals.ts +44 -1
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/resolve-context.ts +3 -1
- package/src/time-series/resolve.ts +56 -4
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +3 -2
- package/src/time-series/studies.ts +8 -2
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +2 -3
- package/src/time-series/types.ts +22 -1
- package/src/types/company-from.ts +40 -0
- package/src/types/data-provider.ts +7 -0
- package/src/types/financials.ts +59 -1
- package/src/types/headless.ts +27 -3
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +9 -0
- package/src/ui/host.tsx +3 -0
- package/src/updater/failure.ts +4 -1
- package/src/utils/cli-output.ts +42 -1
- package/src/utils/crypto-pair.ts +165 -7
- package/src/utils/declared-dividends.ts +1 -1
- package/src/utils/forward-dividend.ts +2 -0
- package/src/utils/fundamentals.ts +60 -8
- package/src/utils/fx-market-hours.ts +26 -3
- package/src/utils/main-thread-stall.ts +35 -2
- package/src/utils/market-capitalization.ts +24 -1
- package/src/utils/price-history.ts +7 -1
- package/src/utils/shell-word.ts +8 -0
- package/src/utils/trailing-dividend.ts +53 -4
- package/src/version.ts +2 -2
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
|
@@ -2,6 +2,7 @@ import { publishedWeekClose } from "../analytics/sharpe-cadence";
|
|
|
2
2
|
import { historyStatistics } from "../../../components/chart/curve/model";
|
|
3
3
|
import type { CloudPricePointPayload } from "../../../api-client/types";
|
|
4
4
|
import { getSectorCollection } from "../sectors/sector-data";
|
|
5
|
+
import { rotationQuadrant, rotationSeries, type RotationQuadrantName } from "../alerts/metric-model";
|
|
5
6
|
import {
|
|
6
7
|
canonicalExchange,
|
|
7
8
|
normalizeSymbol,
|
|
@@ -11,6 +12,8 @@ import {
|
|
|
11
12
|
const DAY = 86_400_000;
|
|
12
13
|
const WEEK = 7 * DAY;
|
|
13
14
|
export const ROTATION_LIMIT = 24;
|
|
15
|
+
/** RRG's benchmark when none is chosen; RRG alerts default to it too. */
|
|
16
|
+
export const DEFAULT_ROTATION_BENCHMARK = "SPY:NYSEARCA";
|
|
14
17
|
export interface RotationInstrument {
|
|
15
18
|
symbol: string;
|
|
16
19
|
exchange: string;
|
|
@@ -46,8 +49,7 @@ export interface RotationRow {
|
|
|
46
49
|
asOf: string | null;
|
|
47
50
|
strength: number | null;
|
|
48
51
|
momentum: number | null;
|
|
49
|
-
quadrant:
|
|
50
|
-
"Leading" | "Weakening" | "Lagging" | "Improving" | "Neutral" | null;
|
|
52
|
+
quadrant: RotationQuadrantName | null;
|
|
51
53
|
strengthRank: RotationRank;
|
|
52
54
|
momentumRank: RotationRank;
|
|
53
55
|
relativeReturn13w: number | null;
|
|
@@ -149,21 +151,8 @@ function rotationRank(
|
|
|
149
151
|
lastDate: stats.endDate,
|
|
150
152
|
};
|
|
151
153
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
momentum: number | null,
|
|
155
|
-
): RotationRow["quadrant"] {
|
|
156
|
-
if (strength == null || momentum == null) return null;
|
|
157
|
-
if (Math.abs(strength - 100) < 1e-9 || Math.abs(momentum - 100) < 1e-9)
|
|
158
|
-
return "Neutral";
|
|
159
|
-
return strength > 100
|
|
160
|
-
? momentum > 100
|
|
161
|
-
? "Leading"
|
|
162
|
-
: "Weakening"
|
|
163
|
-
: momentum > 100
|
|
164
|
-
? "Improving"
|
|
165
|
-
: "Lagging";
|
|
166
|
-
}
|
|
154
|
+
/** The weekly strength, momentum and quadrant math is the RRG alert's, shared with Gloom Cloud's delivery. */
|
|
155
|
+
export { rotationQuadrant };
|
|
167
156
|
export function buildRotation(
|
|
168
157
|
benchmark: RotationHistory,
|
|
169
158
|
instruments: RotationHistory[],
|
|
@@ -219,10 +208,12 @@ export function buildRotation(
|
|
|
219
208
|
const benchmarkUsable = !!benchmark.currency && !!asOf;
|
|
220
209
|
const rows = instruments.map((source): RotationRow => {
|
|
221
210
|
const closes = rotationCloses(source.points, through);
|
|
211
|
+
// A benchmark with no usable weeks says so once in `gaps`; its rows are not to blame for it.
|
|
222
212
|
const gaps = [
|
|
223
213
|
source.error,
|
|
224
214
|
source.stale ? "History is stale." : null,
|
|
225
|
-
|
|
215
|
+
benchmarkUsable &&
|
|
216
|
+
(source.currency !== benchmark.currency || !source.currency)
|
|
226
217
|
? "Price currency does not match the benchmark."
|
|
227
218
|
: null,
|
|
228
219
|
].filter((x): x is string => !!x);
|
|
@@ -240,34 +231,16 @@ export function buildRotation(
|
|
|
240
231
|
? ratio
|
|
241
232
|
: null;
|
|
242
233
|
});
|
|
243
|
-
const
|
|
244
|
-
const window = ratios.slice(Math.max(0, index - 12), index + 1);
|
|
245
|
-
if (
|
|
246
|
-
ratio == null ||
|
|
247
|
-
window.length !== 13 ||
|
|
248
|
-
window.some((value) => value == null)
|
|
249
|
-
)
|
|
250
|
-
return null;
|
|
251
|
-
const mean =
|
|
252
|
-
(window as number[]).reduce((sum, value) => sum + value, 0) / 13;
|
|
253
|
-
return (100 * ratio) / mean;
|
|
254
|
-
});
|
|
234
|
+
const series = rotationSeries(ratios);
|
|
255
235
|
const history = weeks.map((week, index): RotationPoint => {
|
|
256
|
-
const strength =
|
|
257
|
-
previous = index >= 4 ? (strengths[index - 4] ?? null) : null;
|
|
258
|
-
const contiguous =
|
|
259
|
-
index >= 4 &&
|
|
260
|
-
strengths.slice(index - 4, index + 1).every((value) => value != null);
|
|
236
|
+
const { strength, momentum } = series[index]!;
|
|
261
237
|
const priorRatio = index >= 13 ? (ratios[index - 13] ?? null) : null,
|
|
262
238
|
ratio = ratios[index] ?? null;
|
|
263
239
|
return {
|
|
264
240
|
date: weekly.get(week)?.date ?? week,
|
|
265
241
|
week,
|
|
266
242
|
strength,
|
|
267
|
-
momentum
|
|
268
|
-
strength != null && previous != null && contiguous
|
|
269
|
-
? (100 * strength) / previous
|
|
270
|
-
: null,
|
|
243
|
+
momentum,
|
|
271
244
|
relativeReturn13w:
|
|
272
245
|
ratio != null &&
|
|
273
246
|
priorRatio != null &&
|
|
@@ -284,7 +257,10 @@ export function buildRotation(
|
|
|
284
257
|
Number.isFinite(latest.strength) &&
|
|
285
258
|
latest.momentum != null &&
|
|
286
259
|
Number.isFinite(latest.momentum);
|
|
287
|
-
if (
|
|
260
|
+
if (
|
|
261
|
+
benchmarkUsable &&
|
|
262
|
+
(!latest || latest.strength == null || latest.momentum == null)
|
|
263
|
+
)
|
|
288
264
|
gaps.push(
|
|
289
265
|
"At least 17 contiguous matched weekly closes are required; a missing week breaks the trail.",
|
|
290
266
|
);
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
import { useResearchCloudSession } from "../shared/research-cloud-session";
|
|
37
37
|
import { cachedRotation, loadRotation } from "./client";
|
|
38
38
|
import {
|
|
39
|
+
DEFAULT_ROTATION_BENCHMARK,
|
|
39
40
|
ROTATION_LIMIT,
|
|
40
41
|
rotationId,
|
|
41
42
|
rotationTrailWeeks,
|
|
@@ -140,13 +141,13 @@ function RotationDetail({
|
|
|
140
141
|
export function RelativeRotationPane(props: PaneProps) {
|
|
141
142
|
const [scope] = usePaneSettingValue("scope", "sectors");
|
|
142
143
|
const [symbols] = usePaneSettingValue("symbols", "");
|
|
143
|
-
const [benchmarkText] = usePaneSettingValue("benchmark",
|
|
144
|
+
const [benchmarkText] = usePaneSettingValue("benchmark", DEFAULT_ROTATION_BENCHMARK);
|
|
144
145
|
const [trailText] = usePaneSettingValue("trail", "6");
|
|
145
146
|
const { collectionId } = usePaneCollection();
|
|
146
147
|
const tickers = useTickers();
|
|
147
148
|
const context = useMemo(() => {
|
|
148
149
|
try {
|
|
149
|
-
const references = rotationInstruments(benchmarkText ||
|
|
150
|
+
const references = rotationInstruments(benchmarkText || DEFAULT_ROTATION_BENCHMARK);
|
|
150
151
|
if (references.length !== 1)
|
|
151
152
|
throw new Error("Choose one benchmark in pane settings.");
|
|
152
153
|
const instruments =
|
|
@@ -446,6 +446,7 @@ export function CorporateActionsView({
|
|
|
446
446
|
const financialCurrency = tickerFinancials?.financialCurrency;
|
|
447
447
|
const trailingEps = tickerFinancials?.fundamentals?.eps;
|
|
448
448
|
const trailingEpsCurrency = tickerFinancials?.fundamentals?.epsCurrency;
|
|
449
|
+
const trailingEpsSource = tickerFinancials?.fundamentals?.trailingEpsSource;
|
|
449
450
|
const fundamentalsCurrency = tickerFinancials?.fundamentals?.financialCurrency;
|
|
450
451
|
const marketCapCurrency = tickerFinancials?.fundamentals?.marketCapCurrency;
|
|
451
452
|
const quoteCurrency = tickerFinancials?.quote?.currency;
|
|
@@ -453,10 +454,10 @@ export function CorporateActionsView({
|
|
|
453
454
|
() => (quarterlyStatements || financialCurrency || trailingEps != null ? {
|
|
454
455
|
quarterlyStatements: quarterlyStatements ?? [],
|
|
455
456
|
financialCurrency,
|
|
456
|
-
fundamentals: { eps: trailingEps, epsCurrency: trailingEpsCurrency, financialCurrency: fundamentalsCurrency, marketCapCurrency },
|
|
457
|
+
fundamentals: { eps: trailingEps, epsCurrency: trailingEpsCurrency, financialCurrency: fundamentalsCurrency, marketCapCurrency, trailingEpsSource },
|
|
457
458
|
quote: quoteCurrency ? { currency: quoteCurrency } : null,
|
|
458
459
|
} : null),
|
|
459
|
-
[financialCurrency, fundamentalsCurrency, marketCapCurrency, quarterlyStatements, quoteCurrency, trailingEps, trailingEpsCurrency],
|
|
460
|
+
[financialCurrency, fundamentalsCurrency, marketCapCurrency, quarterlyStatements, quoteCurrency, trailingEps, trailingEpsCurrency, trailingEpsSource],
|
|
460
461
|
);
|
|
461
462
|
const actionsLoader = useCallback((nextSymbol: string, nextExchange: string, forceRefresh: boolean) => {
|
|
462
463
|
if (!dataProvider?.getCorporateActions) throw new Error("Corporate actions source unavailable");
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "../../../utils/format";
|
|
16
16
|
import { computeTTM } from "../ticker-detail/financials/aggregation";
|
|
17
17
|
import { declaredDividends } from "../../../utils/declared-dividends";
|
|
18
|
-
import { fundamentalsEpsCurrency } from "../../../utils/fundamentals";
|
|
18
|
+
import { fundamentalsEpsCurrency, SERVED_TRAILING_EPS } from "../../../utils/fundamentals";
|
|
19
19
|
import {
|
|
20
20
|
earningsDateStatus,
|
|
21
21
|
earningsDetail,
|
|
@@ -175,11 +175,11 @@ function estimateValue(pair: EstimatePair): string {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
/**
|
|
178
|
-
* What the TTM row reads: the statements for its four quarters and revenue, and the trailing EPS
|
|
179
|
-
*
|
|
178
|
+
* What the TTM row reads: the statements for its four quarters and revenue, and the trailing EPS of the fundamentals,
|
|
179
|
+
* the figure `ticker` prints as EPS (TTM) (the filed quarters' when they give one, see time-series/filed-trailing-eps).
|
|
180
180
|
*/
|
|
181
181
|
export type EventFinancials = Pick<TickerFinancials, "quarterlyStatements" | "financialCurrency"> & {
|
|
182
|
-
fundamentals?: Pick<NonNullable<TickerFinancials["fundamentals"]>, "eps" | "epsCurrency" | "financialCurrency" | "marketCapCurrency"> | null;
|
|
182
|
+
fundamentals?: Pick<NonNullable<TickerFinancials["fundamentals"]>, "eps" | "epsCurrency" | "financialCurrency" | "marketCapCurrency" | "trailingEpsSource"> | null;
|
|
183
183
|
/** The listing's currency, which says whether an unlabelled EPS can be in the statements' (fundamentalsCurrency). */
|
|
184
184
|
quote?: Pick<NonNullable<TickerFinancials["quote"]>, "currency"> | null;
|
|
185
185
|
};
|
|
@@ -204,9 +204,10 @@ function adjustedQuarterSum(
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
/**
|
|
207
|
-
* The TTM row's EPS is the GAAP diluted trailing figure
|
|
208
|
-
*
|
|
209
|
-
*
|
|
207
|
+
* The TTM row's EPS is the GAAP diluted trailing figure `ticker` prints as EPS (TTM): the last four filed quarters',
|
|
208
|
+
* or Gloom Cloud's trailing figure, named so, when they give none. Without either, the four statement quarters'
|
|
209
|
+
* diluted EPS summed. The reported rows above it are often adjusted, so they are never added to it: only when all
|
|
210
|
+
* four are adjusted does the detail also give their sum.
|
|
210
211
|
*/
|
|
211
212
|
function ttmRow(
|
|
212
213
|
quarterlyStatements: readonly FinancialStatement[],
|
|
@@ -226,7 +227,8 @@ function ttmRow(
|
|
|
226
227
|
date: latest?.date ?? "",
|
|
227
228
|
status: "TTM",
|
|
228
229
|
period: "4 qtrs",
|
|
229
|
-
detail: [eps == null ? "statement sum" : served ? "GAAP diluted
|
|
230
|
+
detail: [eps == null ? "statement sum" : !served ? "GAAP diluted (statements)"
|
|
231
|
+
: financials?.fundamentals?.trailingEpsSource === "served" ? `GAAP diluted (${SERVED_TRAILING_EPS})` : "GAAP diluted",
|
|
230
232
|
adjusted == null ? null : `adj sum ${formatNumber(adjusted, 2)}`].filter(Boolean).join(", "),
|
|
231
233
|
epsCurrency: served ? fundamentalsEpsCurrency(financials) : ttm.currency ?? financials?.financialCurrency,
|
|
232
234
|
revenueCurrency: ttm.currency ?? financials?.financialCurrency,
|
|
@@ -420,7 +422,8 @@ export function buildEventRows(
|
|
|
420
422
|
date: dividend.exDate,
|
|
421
423
|
status: "Dividend",
|
|
422
424
|
period: "-",
|
|
423
|
-
|
|
425
|
+
// A one-off beside the regular payments says so: "Declared special, payable 2026-11-25".
|
|
426
|
+
detail: `Declared${dividend.special ? " special" : ""}${dividend.payDate ? `, payable ${dividend.payDate}` : ""}`,
|
|
424
427
|
value: formatDistributionAmount(dividend.amount, data?.currency ?? currency),
|
|
425
428
|
tone: "positive",
|
|
426
429
|
});
|
|
@@ -478,9 +481,14 @@ export function eventSourceNotice(state: EventSourceState): EventSourceNotice |
|
|
|
478
481
|
const unavailableSections = Object.entries(state.actions?.coverage ?? {})
|
|
479
482
|
.filter(([section, status]) => status === "unavailable" && (state.variant !== "earnings-estimates" || section === "earnings"))
|
|
480
483
|
.map(([section]) => section);
|
|
484
|
+
// Sections and estimates that a source failed to give share one line: "Unavailable: earnings, analyst estimates (the source did not answer)".
|
|
485
|
+
const estimatesCode = !!state.estimatesError && REASON_CODE.test(state.estimatesError.trim());
|
|
486
|
+
const sharedLine = !state.actionsError && unavailableSections.length > 0 && estimatesCode;
|
|
481
487
|
|
|
482
488
|
if (state.actionsError) {
|
|
483
|
-
notices.push(`${actionsLabel} unavailable: ${state.actionsError}`);
|
|
489
|
+
notices.push(`${actionsLabel} unavailable: ${sourceErrorText(state.actionsError)}`);
|
|
490
|
+
} else if (sharedLine) {
|
|
491
|
+
notices.push(`Unavailable: ${unavailableSections.join(", ")}, analyst estimates (${sourceErrorText(state.estimatesError!)})`);
|
|
484
492
|
} else if (unavailableSections.length > 0) {
|
|
485
493
|
notices.push(`Unavailable: ${unavailableSections.join(", ")}`);
|
|
486
494
|
} else if (state.actions && !(state.variant === "earnings-estimates"
|
|
@@ -495,7 +503,7 @@ export function eventSourceNotice(state: EventSourceState): EventSourceNotice |
|
|
|
495
503
|
if (state.estimates?.stale) notices.push(`Analyst estimates stale${state.estimates.fetchedAt ? ` (fetched ${state.estimates.fetchedAt})` : ""}`);
|
|
496
504
|
|
|
497
505
|
if (state.estimatesError) {
|
|
498
|
-
notices.push(`Analyst estimates unavailable: ${state.estimatesError}`);
|
|
506
|
+
if (!sharedLine) notices.push(`Analyst estimates unavailable: ${sourceErrorText(state.estimatesError)}`);
|
|
499
507
|
} else if (state.estimates && !hasAnalystEstimates(state.estimates)) {
|
|
500
508
|
notices.push(`No analyst estimates for ${state.symbol}`);
|
|
501
509
|
}
|
|
@@ -507,8 +515,28 @@ export function eventSourceNotice(state: EventSourceState): EventSourceNotice |
|
|
|
507
515
|
};
|
|
508
516
|
}
|
|
509
517
|
|
|
518
|
+
/** A data service's reason code (UPSTREAM_ERROR) rather than words. */
|
|
519
|
+
const REASON_CODE = /^[A-Z][A-Z0-9_]+$/;
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* A source's failure in words: a reason code reads as what happened
|
|
523
|
+
* ("UPSTREAM_ERROR" is "the source did not answer"); a sentence stands.
|
|
524
|
+
*/
|
|
525
|
+
export function sourceErrorText(error: string): string {
|
|
526
|
+
const text = error.trim();
|
|
527
|
+
if (!REASON_CODE.test(text)) return text;
|
|
528
|
+
switch (text) {
|
|
529
|
+
case "TIMEOUT": return "the source timed out";
|
|
530
|
+
case "NOT_FOUND":
|
|
531
|
+
case "NO_DATA": return "the source has none for this symbol";
|
|
532
|
+
case "RATE_LIMITED": return "the source is busy, try again shortly";
|
|
533
|
+
default: return "the source did not answer";
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
510
537
|
function hasCorporateActionRows(data: CorporateActionsData): boolean {
|
|
511
|
-
|
|
538
|
+
// A declared dividend is a row too: AIOK's $3.50 special with nothing paid yet.
|
|
539
|
+
return data.dividends.length > 0 || data.splits.length > 0 || data.earnings.length > 0 || declaredDividends(data).length > 0;
|
|
512
540
|
}
|
|
513
541
|
|
|
514
542
|
function hasAnalystEstimates(data: AnalystResearchData): boolean {
|
|
@@ -83,7 +83,7 @@ function projectEarningsEstimatesHeadless(
|
|
|
83
83
|
returned: rows.length,
|
|
84
84
|
truncated: rows.length < matching.length,
|
|
85
85
|
coverageNote: notice?.text,
|
|
86
|
-
epsBasis: `${EPS_BASIS_NOTE} The TTM row's EPS is the GAAP diluted trailing figure ticker shows as EPS (TTM), or the four statement quarters' diluted EPS when
|
|
86
|
+
epsBasis: `${EPS_BASIS_NOTE} The TTM row's EPS is the GAAP diluted trailing figure ticker shows as EPS (TTM): the last four filed quarters', or Gloom Cloud's TTM (named so) when they give none, or the four statement quarters' diluted EPS when neither is there; reported quarters of different bases are never summed, and the row adds an adjusted sum only when all four quarters are adjusted.`,
|
|
87
87
|
dateNote: "Fiscal period dates are not announcement dates. Revenue is attached only to an identified statement period.",
|
|
88
88
|
unmatchedReportedPeriods,
|
|
89
89
|
},
|
|
@@ -6,6 +6,8 @@ import { CorporateActionsView } from "./corporate-actions-pane";
|
|
|
6
6
|
import { EquityDiagnosticView } from "./equity-diagnostic-pane";
|
|
7
7
|
import { RelativeValuationPane } from "./relative-valuation-pane";
|
|
8
8
|
import { relativeValuationHeadless } from "./relative-valuation-headless";
|
|
9
|
+
import { AUTO_PEERS_SETTING, relativeValuationTitle } from "./relative-valuation-peers";
|
|
10
|
+
import { buildRelativeValuationSettingsDef, MAX_RELATIVE_VALUATION_TICKERS } from "./relative-valuation-settings";
|
|
9
11
|
import { analystResearchHeadless } from "./analyst-headless";
|
|
10
12
|
import { eventsHeadless } from "./events-headless";
|
|
11
13
|
import { earningsEstimatesHeadless } from "./headless";
|
|
@@ -95,6 +97,7 @@ export const researchModule: PluginModule = {
|
|
|
95
97
|
defaultMode: "floating",
|
|
96
98
|
defaultFloatingSize: { width: 104, height: 24 },
|
|
97
99
|
tableExport: true,
|
|
100
|
+
settings: buildRelativeValuationSettingsDef,
|
|
98
101
|
},
|
|
99
102
|
{
|
|
100
103
|
id: "earnings-estimates",
|
|
@@ -168,14 +171,15 @@ export const researchModule: PluginModule = {
|
|
|
168
171
|
try {
|
|
169
172
|
symbols = options?.symbols?.length
|
|
170
173
|
? options.symbols
|
|
171
|
-
: parseTickerListInput(options?.arg ?? context.activeTicker ?? "",
|
|
174
|
+
: parseTickerListInput(options?.arg ?? context.activeTicker ?? "", MAX_RELATIVE_VALUATION_TICKERS);
|
|
172
175
|
} catch {
|
|
173
176
|
return null;
|
|
174
177
|
}
|
|
175
178
|
return {
|
|
176
|
-
title:
|
|
179
|
+
title: relativeValuationTitle(symbols, null),
|
|
177
180
|
placement: "floating",
|
|
178
|
-
|
|
181
|
+
// One ticker is compared with the peers `--peers` picks, which the pane finds once it opens.
|
|
182
|
+
settings: { symbols, symbolsText: formatTickerListInput(symbols), ...(symbols.length === 1 ? { [AUTO_PEERS_SETTING]: true } : {}) },
|
|
179
183
|
};
|
|
180
184
|
},
|
|
181
185
|
},
|
|
@@ -8,11 +8,10 @@ import {
|
|
|
8
8
|
RELATIVE_VALUATION_STALE_FUNDAMENTALS_NOTICE, RELATIVE_VALUATION_STALE_QUOTE_NOTICE, relativeValuationValues, type RelativeValuationGapKey,
|
|
9
9
|
} from "./relative-valuation-model";
|
|
10
10
|
import { paneSchemas } from "./headless-schema";
|
|
11
|
-
import { isRecord } from "../../../utils/guards";
|
|
12
|
-
import { errorMessage } from "../../../utils/errors";
|
|
13
|
-
import { notATickerSymbol } from "../../../sources/provider-errors";
|
|
14
11
|
import { resolveCurrencyUnit } from "../../../utils/currency-units";
|
|
15
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
AUTO_PEERS_SETTING, findPeers, peerMethodTitle, peerSelectionOf, PEER_SELECTION_SETTING, relativeValuationTitle, type PeerSelection,
|
|
14
|
+
} from "./relative-valuation-peers";
|
|
16
15
|
import { extraColumns, extraColumnsBasis, loadExtraColumns, parseExtraColumns } from "./relative-valuation-columns";
|
|
17
16
|
import { fundamentalsBasisParts } from "./relative-valuation-basis";
|
|
18
17
|
import { conversionNote, convertMarketCaps, loadFxLegs } from "./relative-valuation-currency";
|
|
@@ -96,37 +95,21 @@ const VALUATION_COLUMNS: HeadlessPaneColumn[] = [
|
|
|
96
95
|
...([["fcfYield", "FCF Yield"], ["revenueGrowth", REVENUE_GROWTH_HEADER], ["operatingMargin", "TTM Op Margin"]] as const).map(([key, header]) => ({
|
|
97
96
|
key, header, align: "right" as const,
|
|
98
97
|
format: (value: unknown, row: Record<string, unknown>) => value == null ? gapText(row, key)
|
|
99
|
-
: key === "revenueGrowth" ? formatPercent(Number(value))
|
|
98
|
+
: key === "revenueGrowth" ? formatPercent(Number(value))
|
|
99
|
+
// A margin of the latest fiscal year, where no trailing quarters were served, says which year.
|
|
100
|
+
: key === "operatingMargin" && typeof row.operatingMarginPeriod === "string"
|
|
101
|
+
? `${formatLevelPercent(Number(value))} ${row.operatingMarginPeriod}` : formatLevelPercent(Number(value)),
|
|
100
102
|
})),
|
|
101
103
|
];
|
|
102
104
|
|
|
103
|
-
/** Peers `--peers` chose, as the expansion left them in the settings or the load picked them. */
|
|
104
|
-
function peerSelectionOf(value: unknown, symbols: readonly string[]): PeerSelection | null {
|
|
105
|
-
if (!isRecord(value) || typeof value.subject !== "string" || !Array.isArray(value.peers)) return null;
|
|
106
|
-
const selection = value as unknown as PeerSelection;
|
|
107
|
-
const expected = [selection.subject, ...selection.peers];
|
|
108
|
-
return expected.length === symbols.length && expected.every((symbol, index) => symbol.toUpperCase() === symbols[index]?.toUpperCase())
|
|
109
|
-
? selection : null;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
105
|
/** The peers of the one symbol `--peers` was given; several symbols are already a peer list. */
|
|
113
106
|
async function choosePeers(symbols: readonly string[], ctx: HeadlessPaneContext): Promise<PeerSelection> {
|
|
114
107
|
if (symbols.length !== 1) {
|
|
115
108
|
throw new Error(`--peers picks the peers of one symbol, such as RV ${symbols[0] ?? "DUOL"} --peers; with several symbols, leave it out.`);
|
|
116
109
|
}
|
|
117
|
-
|
|
118
|
-
const financials = await loadHeadlessFinancials(ctx, subject).catch((error: unknown) => {
|
|
119
|
-
ctx.signal.throwIfAborted();
|
|
120
|
-
// A word that is no ticker is said as `fn RV duolingo lrn` says it, which the CLI follows with the search to run.
|
|
121
|
-
if (notATickerSymbol(errorMessage(error))) throw error;
|
|
122
|
-
// Any other failure leaves the peers to what the symbol alone places (a curated core's member).
|
|
123
|
-
return null;
|
|
124
|
-
});
|
|
125
|
-
return pickPeers(subject, financials, ctx);
|
|
110
|
+
return findPeers(symbols[0]!, ctx);
|
|
126
111
|
}
|
|
127
112
|
|
|
128
|
-
const PEER_SELECTION_SETTING = "peerSelection";
|
|
129
|
-
|
|
130
113
|
export const relativeValuationHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
131
114
|
...paneSchemas["relative-valuation-pane"],
|
|
132
115
|
// What Ask Gloom reads. The template's "across peers" never said this is where a list of holdings' P/E is.
|
|
@@ -146,9 +129,12 @@ export const relativeValuationHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
|
146
129
|
return {
|
|
147
130
|
argument: [selection.subject, ...selection.peers].join(", "),
|
|
148
131
|
settings: { [PEER_SELECTION_SETTING]: selection },
|
|
149
|
-
title:
|
|
132
|
+
title: relativeValuationTitle([], selection),
|
|
150
133
|
};
|
|
151
134
|
},
|
|
135
|
+
// The app adds the peers of a pane opened on one ticker; a capture draws the tickers given, as the report does,
|
|
136
|
+
// unless --peers widened them.
|
|
137
|
+
shotState: (args) => args.options.peers === true ? {} : { settings: { [AUTO_PEERS_SETTING]: false } },
|
|
152
138
|
async load(args, ctx) {
|
|
153
139
|
// --peers picked in advance (fn and shot) reads the same peers; any other caller picks them here.
|
|
154
140
|
const preset = args.options.peers === true ? peerSelectionOf(ctx.settings?.[PEER_SELECTION_SETTING], args.symbols) : null;
|
|
@@ -226,6 +212,7 @@ export const relativeValuationHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
|
226
212
|
...rows.flatMap((row) => row.evSalesUnavailable ? [`${row.symbol}: ${row.evSalesUnavailable}`] : []),
|
|
227
213
|
...rows.flatMap((row) => row.evSalesNote ? [`${row.symbol}: ${row.evSalesNote}`] : []),
|
|
228
214
|
...rows.flatMap((row) => row.marketCapNote ? [`${row.symbol}: ${row.marketCapNote}`] : []),
|
|
215
|
+
...rows.flatMap((row) => row.marketCapWithheld ? [`${row.symbol}: ${row.marketCapWithheld}`] : []),
|
|
229
216
|
],
|
|
230
217
|
multipleBasis: "Comparable P/E fields require a positive finite multiple over positive EPS, and evSales an enterprise value above zero; notMeaningful says why one is null, and reportedMultiples preserves the finite provider P/E values.",
|
|
231
218
|
marketCapBasis: "Market caps retain their own currency and source. Fundamentals retrieval time is not a valuation date; quote timestamps do not date fallback caps.",
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { formatCurrency } from "../../../utils/format";
|
|
2
2
|
import { comparablePriceEarnings, notMeaningfulMultiples } from "../../../utils/price-earnings";
|
|
3
|
-
import { marketCapBasisNote, viewMarketCapitalization } from "../../../utils/market-capitalization";
|
|
3
|
+
import { marketCapBasisNote, viewMarketCapitalization, withheldMarketCap } from "../../../utils/market-capitalization";
|
|
4
4
|
import { enterpriseValueNotMeaningful, enterpriseValueReconciliationNote, enterpriseValueWithdrawn, reportedEnterpriseValue } from "../../../utils/fundamentals";
|
|
5
5
|
import { getExtendedSessionDisplay, getQuoteSessionFields } from "../../../market-data/market/status";
|
|
6
6
|
import { atRegularSessionPrice, movePriceDerivedFigures, regularSessionValuationPrice } from "../../../market-data/quotes/regular-session-valuation";
|
|
7
|
+
import { fiscalPeriodLabel, fiscalYearEndMonth } from "../../../utils/fiscal-period";
|
|
7
8
|
import { latestFinancialPeriod, latestReportedPeriod } from "../../../utils/latest-financial-period";
|
|
8
9
|
import type { Quote, TickerFinancials } from "../../../types/financials";
|
|
9
10
|
|
|
@@ -50,6 +51,25 @@ function fcfYieldGap(fundamentals: TickerFinancials["fundamentals"], capCurrency
|
|
|
50
51
|
}
|
|
51
52
|
export const RELATIVE_VALUATION_STALE_FUNDAMENTALS_NOTICE = "Fundamentals stale: retained values may be out of date";
|
|
52
53
|
|
|
54
|
+
/**
|
|
55
|
+
* The operating margin of the latest fiscal year, for a row whose trailing
|
|
56
|
+
* twelve months are not whole (a quarter the source has not carried yet):
|
|
57
|
+
* that year's operating income over its revenue, named for the year ("FY25")
|
|
58
|
+
* so a cell never passes it off as trailing. Null when the latest year lacks
|
|
59
|
+
* either figure; an older year is never stood in for it.
|
|
60
|
+
*/
|
|
61
|
+
function fiscalYearOperatingMargin(annualStatements: TickerFinancials["annualStatements"] | undefined) {
|
|
62
|
+
const latest = latestFinancialPeriod(annualStatements, (row) => row.date);
|
|
63
|
+
if (!latest || !finiteNumber(latest.operatingIncome) || !finiteNumber(latest.totalRevenue) || latest.totalRevenue <= 0) return null;
|
|
64
|
+
const year = /^FY\d{2}(\d{2})$/.exec(fiscalPeriodLabel(latest.date, "annual", fiscalYearEndMonth(annualStatements ?? [])))?.[1];
|
|
65
|
+
return {
|
|
66
|
+
value: latest.operatingIncome / latest.totalRevenue,
|
|
67
|
+
// The fiscal year's own name; the calendar year of its end where the year cannot be named.
|
|
68
|
+
label: `FY${year ?? latest.date.slice(2, 4)}`,
|
|
69
|
+
periodEnd: latest.date.slice(0, 10),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
53
73
|
/**
|
|
54
74
|
* A peer's row. Last, its change and the extended print are the quote's
|
|
55
75
|
* sessions as `quote` reads them (getQuoteSessionFields): after the close,
|
|
@@ -97,14 +117,17 @@ export function relativeValuationValues(snapshot: TickerFinancials | null) {
|
|
|
97
117
|
&& fundamentals.freeCashFlow != null && Number.isFinite(fundamentals.freeCashFlow) && capitalization.value > 0
|
|
98
118
|
? fundamentals.freeCashFlow / capitalization.value : null;
|
|
99
119
|
const revenueGrowth = fundamentals?.revenueGrowth ?? fundamentals?.lastQuarterGrowth ?? null;
|
|
100
|
-
const
|
|
120
|
+
const trailingOperatingMargin = fundamentals?.operatingMargin ?? null;
|
|
121
|
+
const fiscalYearMargin = trailingOperatingMargin == null ? fiscalYearOperatingMargin(financials?.annualStatements) : null;
|
|
122
|
+
const operatingMargin = trailingOperatingMargin ?? fiscalYearMargin?.value ?? null;
|
|
101
123
|
const trailingPE = trailingNotMeaningful ? null : comparablePriceEarnings(reportedMultiples.trailingPE);
|
|
102
124
|
const forwardPE = forwardNotMeaningful ? null : comparablePriceEarnings(reportedMultiples.forwardPE);
|
|
103
125
|
// Every figure a row lacks says why, so an export's blank cell is never silent: N/M multiples say so themselves.
|
|
104
126
|
const gaps: Partial<Record<RelativeValuationGapKey, string>> = {};
|
|
105
127
|
if (session.price == null) gaps.price = quoteStale ? QUOTE_STALE : NOT_REPORTED;
|
|
106
128
|
if (session.changePercent == null) gaps.changePercent = quoteStale ? QUOTE_STALE : NOT_REPORTED;
|
|
107
|
-
|
|
129
|
+
const withheld = withheldMarketCap(fundamentals);
|
|
130
|
+
if (capitalization == null) gaps.marketCap = withheld?.gap ?? (quoteStale && !fundamentals?.marketCap ? QUOTE_STALE : NOT_REPORTED);
|
|
108
131
|
if (trailingPE == null && !trailingNotMeaningful && reportedMultiples.trailingPE == null) gaps.trailingPE = NOT_REPORTED;
|
|
109
132
|
if (forwardPE == null && !forwardNotMeaningful && reportedMultiples.forwardPE == null) gaps.forwardPE = NOT_REPORTED;
|
|
110
133
|
if (evSales == null && !evSalesNotMeaningful) gaps.evSales = evSalesGap(fundamentals, quote?.currency, evSalesWithdrawn, enterpriseValueGap);
|
|
@@ -136,6 +159,8 @@ export function relativeValuationValues(snapshot: TickerFinancials | null) {
|
|
|
136
159
|
marketCapProvenance: capitalization?.provenance ?? null,
|
|
137
160
|
/** valuation's note when the cap is the share count times the price: the provider's figure it replaced. */
|
|
138
161
|
marketCapNote: marketCapBasisNote(capitalization) ?? null,
|
|
162
|
+
/** Why Gloom Cloud withheld the cap (a receipt priced as ordinary shares), as `valuation` and EQS say it; null otherwise. */
|
|
163
|
+
marketCapWithheld: withheld?.note ?? null,
|
|
139
164
|
trailingPE,
|
|
140
165
|
forwardPE,
|
|
141
166
|
reportedMultiples,
|
|
@@ -151,6 +176,9 @@ export function relativeValuationValues(snapshot: TickerFinancials | null) {
|
|
|
151
176
|
fcfYield,
|
|
152
177
|
revenueGrowth,
|
|
153
178
|
operatingMargin,
|
|
179
|
+
/** The fiscal year the operating margin is of ("FY25") when no trailing figure was served; null when it is trailing twelve months. */
|
|
180
|
+
operatingMarginPeriod: fiscalYearMargin?.label ?? null,
|
|
181
|
+
operatingMarginPeriodEnd: fiscalYearMargin?.periodEnd ?? null,
|
|
154
182
|
/** Why each missing figure is missing, in a few words the row draws in its place. */
|
|
155
183
|
gaps,
|
|
156
184
|
};
|