gloomberb 0.17.6 → 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 +6 -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/credit-boards.ts +21 -1
- package/src/api-client/crypto-markets.ts +88 -1
- package/src/api-client/data.ts +104 -4
- package/src/api-client/debt-maturities.ts +18 -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 +25 -2
- package/src/api-client/insider-signals.ts +95 -11
- package/src/api-client/normalizers.ts +1 -0
- package/src/api-client/paths.ts +20 -1
- package/src/api-client/request.ts +11 -3
- package/src/api-client/research-activity.ts +15 -8
- package/src/api-client/socket.ts +6 -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 +66 -2
- 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/desktop-deeplink.ts +3 -4
- package/src/app/runtime/plugin-bindings.ts +3 -2
- package/src/app/runtime/startup.ts +3 -4
- package/src/app/runtime/ticker-refresh.ts +13 -12
- package/src/app/runtime/update.ts +3 -2
- package/src/architecture/core-builtin-allowlist.json +0 -3
- 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/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 +2 -1
- 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 +340 -69
- package/src/cli/commands/news-search.ts +35 -2
- package/src/cli/commands/options-chain.ts +7 -5
- package/src/cli/commands/options-leaps.ts +3 -3
- package/src/cli/commands/overview.ts +78 -29
- 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 +337 -60
- package/src/cli/context.ts +2 -1
- package/src/cli/desktop-pane-shot.ts +11 -3
- package/src/cli/earnings-calendar.ts +2 -1
- package/src/cli/errors.ts +10 -0
- package/src/cli/export-source.ts +18 -3
- package/src/cli/glossary.ts +196 -14
- package/src/cli/history-rows.ts +60 -9
- package/src/cli/index-roots.ts +26 -0
- package/src/cli/index.ts +34 -9
- package/src/cli/known-gaps.ts +156 -22
- package/src/cli/listing-arg.ts +156 -12
- package/src/cli/listing-suggestion.ts +4 -2
- 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 +94 -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 +49 -8
- package/src/cli/pane-functions/function-help.ts +13 -10
- package/src/cli/pane-functions/headless.ts +177 -42
- package/src/cli/pane-functions/index.ts +64 -8
- 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 +48 -13
- package/src/cli/pane-functions/screenshot.ts +124 -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 +10 -2
- 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 -34
- 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/components/chart/composite/axis-overlays.tsx +16 -9
- package/src/components/chart/composite/composite-chart.tsx +85 -6
- package/src/components/chart/composite/downsample.ts +19 -3
- package/src/components/chart/composite/format.ts +3 -0
- package/src/components/chart/composite/legend.tsx +155 -76
- package/src/components/chart/composite/panel-bitmap.ts +8 -2
- package/src/components/chart/composite/panel-surface.tsx +3 -3
- package/src/components/chart/composite/toolbar.tsx +12 -7
- package/src/components/chart/composite/types.ts +6 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +28 -1
- 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 +10 -3
- 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 +5 -0
- package/src/components/command-bar/list/view.tsx +1 -1
- 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/provider-search.ts +3 -9
- package/src/components/command-bar/routes/root/results.ts +13 -0
- package/src/components/command-bar/routes/root/start-here.ts +90 -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/theme-picker.tsx +3 -1
- package/src/components/command-bar/workflow/builtin.ts +5 -1
- package/src/components/command-bar/workflow/collection-actions.ts +21 -12
- package/src/components/command-bar/workflow/ops.ts +21 -1
- 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 +6 -4
- 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/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 +8 -2
- 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-positions.ts +40 -11
- 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/index.tsx +2 -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/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/list-view.tsx +8 -0
- package/src/components/ui/prose.tsx +97 -25
- package/src/components/ui/query-bar-keys.tsx +3 -1
- package/src/components/ui/query-bar.tsx +6 -0
- 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/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/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/gallery-desktop.tsx +8 -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 +6 -5
- package/src/market-data/futures-contract.ts +102 -5
- package/src/market-data/hooks.tsx +20 -11
- package/src/market-data/market/bar-period.ts +36 -0
- package/src/market-data/market/format.ts +5 -13
- package/src/market-data/market/freshness.ts +1 -3
- package/src/market-data/market/index-level.ts +51 -0
- package/src/market-data/model-dividend-yield.ts +57 -16
- package/src/market-data/quotes/live-valuation.ts +48 -2
- 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 +47 -9
- package/src/plugins/builtin/analytics/risk-headless.ts +14 -2
- package/src/plugins/builtin/analytics/risk-math.ts +83 -0
- package/src/plugins/builtin/analytics/risk-model.ts +97 -4
- package/src/plugins/builtin/analytics/risk-pane.tsx +11 -6
- 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/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/desktop-view.tsx +2 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -2
- package/src/plugins/builtin/chart-composer/headless.ts +99 -21
- package/src/plugins/builtin/chart-composer/index.tsx +70 -13
- package/src/plugins/builtin/chart-composer/pane.tsx +65 -15
- package/src/plugins/builtin/chart-composer/presets.ts +79 -11
- package/src/plugins/builtin/chart-composer/series-catalog.ts +50 -14
- package/src/plugins/builtin/chart-composer/series-expression.ts +9 -7
- 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/chat/attachments/desktop.tsx +4 -1
- 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 +35 -5
- package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -0
- package/src/plugins/builtin/chat/content/shortcuts.ts +32 -13
- package/src/plugins/builtin/chat/content/snapshot.ts +29 -6
- package/src/plugins/builtin/chat/ghost-user.ts +11 -3
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +13 -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/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/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/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 +8 -5
- package/src/plugins/builtin/commodities-energy/view-state.ts +11 -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/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/headless.ts +3 -2
- 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 +8 -1
- package/src/plugins/builtin/econ-statistics/headless.ts +26 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +4 -2
- package/src/plugins/builtin/econ-statistics/stats.ts +10 -0
- package/src/plugins/builtin/econ-statistics/view.ts +19 -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 +34 -21
- 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/headless.ts +4 -2
- package/src/plugins/builtin/futures-curve/model.ts +5 -7
- 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 +311 -41
- package/src/plugins/builtin/insider/index.tsx +280 -106
- 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 +135 -11
- package/src/plugins/builtin/insider/signals-model.ts +628 -56
- package/src/plugins/builtin/insider/signals.tsx +283 -83
- 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/headless.ts +2 -0
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/jobs/index.tsx +1 -0
- package/src/plugins/builtin/jodi/headless.ts +2 -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-valuation/pane.tsx +1 -1
- 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-scenario/client.ts +7 -4
- package/src/plugins/builtin/options-scenario/headless.ts +5 -3
- 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 +108 -46
- package/src/plugins/builtin/portfolio-list/cli/render.ts +368 -45
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +8 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +24 -34
- package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +151 -29
- 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 +27 -10
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +47 -28
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +10 -3
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +26 -4
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +31 -3
- package/src/plugins/builtin/portfolio-list/table.tsx +25 -5
- 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 +2 -0
- package/src/plugins/builtin/research/event-model.ts +22 -2
- package/src/plugins/builtin/research/headless-schema.ts +1 -0
- package/src/plugins/builtin/research/headless.ts +3 -0
- 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 +9 -6
- package/src/plugins/builtin/reverse-dcf/index.tsx +2 -2
- package/src/plugins/builtin/reverse-dcf/model.ts +51 -4
- package/src/plugins/builtin/reverse-dcf/pane.tsx +23 -10
- 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/headless-options.ts +10 -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 +25 -9
- package/src/plugins/builtin/shared/scanner-capture.ts +95 -0
- package/src/plugins/builtin/shared/treasury-cutoffs.ts +15 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +1 -0
- 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/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 +22 -8
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +17 -1
- 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.ts +23 -10
- 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 +36 -3
- 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 +8 -5
- 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 +74 -12
- package/src/{plugins/builtin/portfolio-list → portfolio}/column-values.ts +140 -53
- 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/portfolio/mutations.ts +54 -10
- package/src/portfolio/position-metrics.ts +44 -10
- package/src/portfolio/valuation-basis.ts +31 -4
- package/src/public/__snapshots__/public-api.test.ts.snap +4 -0
- package/src/public/time-series.ts +2 -1
- package/src/remote/confirm-change.tsx +2 -1
- package/src/remote/server.ts +1 -1
- package/src/remote/watchlist.ts +9 -1
- 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 +6 -4
- 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 +3 -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/electrobun/bun/core-capabilities.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -1
- 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/workspace/requests.ts +5 -1
- 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/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/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 -13
- package/src/state/app/tab-cursor.ts +149 -12
- 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 +58 -15
- 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/theme/colors.ts +2 -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 +49 -9
- package/src/tickers/listing-venues.ts +24 -5
- package/src/tickers/open-target.ts +13 -5
- package/src/tickers/search/index.ts +112 -35
- package/src/tickers/search/ranking.ts +49 -1
- package/src/tickers/terminal-codes.ts +79 -0
- package/src/tickers/ticker-changes.ts +74 -3
- package/src/tickers/us-listing.ts +2 -1
- package/src/time-series/chart-data.ts +79 -8
- package/src/time-series/fundamentals.ts +55 -7
- package/src/time-series/ice-credit.ts +17 -2
- package/src/time-series/live-bars.ts +21 -8
- package/src/time-series/live-quotes.ts +2 -3
- package/src/time-series/price-comparison.ts +6 -1
- package/src/time-series/resolve.ts +65 -10
- package/src/time-series/spec.ts +2 -1
- package/src/time-series/studies.ts +3 -3
- package/src/time-series/types.ts +22 -0
- package/src/time-series/use-chart-resolution.ts +2 -1
- package/src/types/config.ts +7 -0
- package/src/types/data-provider.ts +20 -0
- package/src/types/headless.ts +142 -1
- package/src/types/instrument.ts +6 -0
- package/src/types/plugin.ts +32 -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 +40 -4
- package/src/ui/measured-cells.ts +13 -7
- package/src/ui/qr.ts +7 -5
- package/src/updater/index.ts +5 -5
- 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/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/futures-generic.ts +34 -8
- package/src/utils/http-proxy-response.ts +2 -1
- 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/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/url.ts +1 -0
- package/src/utils/utc-time.ts +11 -0
- package/src/plugins/builtin/chat/share/targets.ts +0 -27
- package/src/renderers/dom/host/top-surface.ts +0 -119
- package/src/shares/dialog.tsx +0 -221
- package/src/shares/live.ts +0 -19
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logFailure } from "../../utils/log-failure";
|
|
1
2
|
import type { CliCommandDef } from "../../types/plugin";
|
|
2
3
|
import { TIME_RANGES, type TimeRange } from "../../time-series/range";
|
|
3
4
|
import type { EarningsEvent, QuoteBatchResult, QuoteSubscriptionTarget, SecFilingItem } from "../../types/data-provider";
|
|
@@ -10,7 +11,8 @@ import type {
|
|
|
10
11
|
Quote,
|
|
11
12
|
TickerFinancials,
|
|
12
13
|
} from "../../types/financials";
|
|
13
|
-
import { currencyPriceMinDigits, formatMarketPrice, formatMarketPriceWithCurrency, quoteFormatOptions } from "../../market-data/market/format";
|
|
14
|
+
import { currencyPriceMinDigits, formatMarketPrice, formatMarketPriceWithCurrency, quoteFormatOptions, resolveAssetDisplayKind } from "../../market-data/market/format";
|
|
15
|
+
import { INDEX_POINTS_EXPORT_UNIT, isIndexLevel, reportedQuoteVolume } from "../../market-data/market/index-level";
|
|
14
16
|
import {
|
|
15
17
|
EXTENDED_SESSION_LABELS,
|
|
16
18
|
getExtendedSessionDisplay,
|
|
@@ -48,10 +50,14 @@ import { getPublishedUsEquityCalendarYears, getPublishedUsEquitySession } from "
|
|
|
48
50
|
import { isQuoteStaleForCurrentSession } from "../../market-data/quotes/freshness";
|
|
49
51
|
import { isOptionsUnavailableError, listedOptionsAlternative, optionsUnavailableTitle } from "../../market-data/options-alternatives";
|
|
50
52
|
import {
|
|
51
|
-
cliFuturesContract, futuresContractMetrics, fundamentalsReportTables,
|
|
53
|
+
cliFuturesContract, futuresContractMetrics, exportedDividendFundamentals, fundamentalsReportTables, loadDividendDistributions, loadReportBondFacts,
|
|
54
|
+
renderFundamentalsReport,
|
|
52
55
|
} from "./ticker";
|
|
56
|
+
import { loadStatementFilings } from "../statement-filings";
|
|
57
|
+
import { loadBankFigures } from "../bank-section";
|
|
58
|
+
import { latestFinancialPeriod } from "../../utils/latest-financial-period";
|
|
53
59
|
import type { FuturesContractTermsPayload } from "../../api-client/futures-curve";
|
|
54
|
-
import { futuresSettleText, isFuturesInstrument } from "../../market-data/futures-contract";
|
|
60
|
+
import { futuresContractLines, futuresRollLines, futuresSettleText, isFuturesInstrument } from "../../market-data/futures-contract";
|
|
55
61
|
import {
|
|
56
62
|
chainHasExpiry,
|
|
57
63
|
formatExpiryList,
|
|
@@ -70,7 +76,8 @@ import {
|
|
|
70
76
|
valueChainAtModelSpot,
|
|
71
77
|
type OptionsChainBasis,
|
|
72
78
|
} from "./options-chain";
|
|
73
|
-
import { missingExpiryMessage } from "../../utils/option-expiry";
|
|
79
|
+
import { missingExpiryMessage, OPTION_EXPIRATION_FORMAT, OPTION_EXPIRATION_PLACEHOLDER } from "../../utils/option-expiry";
|
|
80
|
+
import { DATE_OPTION_EXAMPLES } from "../../utils/calendar-date";
|
|
74
81
|
import { declaredDividends } from "../../utils/declared-dividends";
|
|
75
82
|
import {
|
|
76
83
|
DEFAULT_LEAPS_CRITERIA, LEAPS_EXTRA_COLUMNS, LEAPS_USAGE, parseLeapsCriteria, runLeapsScreen, takeLeapsOptions,
|
|
@@ -84,6 +91,7 @@ import {
|
|
|
84
91
|
type CliReportTables,
|
|
85
92
|
} from "../report-tables";
|
|
86
93
|
import {
|
|
94
|
+
closedPeriodBarDay,
|
|
87
95
|
formingPeriodBar,
|
|
88
96
|
historyBarStatusNote,
|
|
89
97
|
historyCoverageWarning,
|
|
@@ -94,17 +102,20 @@ import {
|
|
|
94
102
|
historyUnbrokenFrom,
|
|
95
103
|
historyAllRangeYears,
|
|
96
104
|
historyIntervalsByRange,
|
|
105
|
+
historyMissingVolumeNote,
|
|
97
106
|
historyNotes,
|
|
107
|
+
historyReportsVolume,
|
|
98
108
|
historyPriceDecimals,
|
|
99
109
|
historyRows,
|
|
100
110
|
historyUnit,
|
|
101
111
|
historyVolume,
|
|
102
112
|
historyVolumeText,
|
|
103
113
|
} from "../history-rows";
|
|
114
|
+
import { MISSING_VOLUME_TEXT } from "../../utils/price-history-integrity";
|
|
104
115
|
import { CRYPTO_BOARD_HINT, quoteNotes } from "./crypto-hints";
|
|
105
116
|
import { bareFuturesCode } from "../../market-data/futures-board";
|
|
106
117
|
import { newsEmptyMessage } from "./news-hints";
|
|
107
|
-
import { newsFallbackText, newsSearchHeading, newsSearchText, newsSearchTextProblem, searchNewsStories } from "./news-search";
|
|
118
|
+
import { commonWordCandidate, newsFallbackText, newsSearchHeading, newsSearchText, newsSearchTextProblem, quotedSearchCommand, searchNewsStories, wordMeansMore } from "./news-search";
|
|
108
119
|
import { formatUtcTime } from "../../utils/utc-time";
|
|
109
120
|
import { DAY_SO_FAR_TEXT, withSessionBar } from "../../time-series/session-bar";
|
|
110
121
|
import { isFiniteNumber } from "../../utils/guards";
|
|
@@ -155,20 +166,32 @@ import {
|
|
|
155
166
|
} from "../listing-arg";
|
|
156
167
|
import { bareListingNote, listingFateNotes, noLongerTradingNote, tradingListing } from "../../tickers/listing-fate";
|
|
157
168
|
import { indexRootAlsoLine, indexRootFor, indexRootTryLine, isYieldIndexSymbol } from "../index-roots";
|
|
169
|
+
import { treasuryYieldLine, treasuryYieldTenor } from "../treasury-yields";
|
|
170
|
+
import {
|
|
171
|
+
analyzeTaxEquivalent, distributionBasis, loadTreasuryTenors, parseTaxRates, TAX_RATE_HELP_OPTIONS, taxEquivalentJson, type TaxRates,
|
|
172
|
+
} from "../../market-data/tax-equivalent";
|
|
173
|
+
import { CBOE_YIELD_INDEX_CLOSE } from "../../plugins/builtin/shared/treasury-cutoffs";
|
|
158
174
|
import { earningsCalendarFailure, earningsChoiceNote, earningsDateLabel, isListingAbroad, noListingCalendarNote } from "../earnings-calendar";
|
|
159
175
|
import { formatBasisPoints, toBasisPoints } from "../../utils/basis-points";
|
|
160
176
|
import { notATickerSymbol, providerMissReason } from "../../sources/provider-errors";
|
|
161
177
|
import { isNotATickerMessage, withListingSuggestion } from "../not-a-ticker";
|
|
178
|
+
import { primeBoardCoins } from "../board-coins";
|
|
162
179
|
import { describeSuggestion, suggestListing, suggestUsTicker, type ListingSuggestion } from "../listing-suggestion";
|
|
163
|
-
import { splitSymbolArgs, uniqueSecuritySymbols } from "../symbol-args";
|
|
180
|
+
import { quotedPhrase, splitSymbolArgs, uniqueSecuritySymbols } from "../symbol-args";
|
|
181
|
+
import { isCompanyNameInput } from "../../tickers/company-name-listing";
|
|
182
|
+
import { readNameEntries, readPhraseArgument } from "../name-entries";
|
|
183
|
+
import { readSymbolList, SymbolListError } from "../symbol-list";
|
|
164
184
|
import { cliPerpetualContract, perpetualContractStats, type PerpetualContractPayload } from "../perpetual-contract";
|
|
165
|
-
import { subMinuteDataMessage } from "../known-gaps";
|
|
185
|
+
import { knownGapForTicker, knownGapMessage, subMinuteDataMessage } from "../known-gaps";
|
|
186
|
+
import { phraseSearchReport } from "./search";
|
|
166
187
|
import { secRegistrantMismatchMessage, SecRegistrantMismatchError, areDifferentCompanies } from "../../sources/sec-registrant";
|
|
167
188
|
import { isCryptoPairSymbol } from "../../utils/crypto-pair";
|
|
168
189
|
import { looksLikeCurrencyPair } from "../../utils/currency-pair";
|
|
169
190
|
import { canonicalExchange, isUsListingExchange } from "../../utils/exchanges";
|
|
170
|
-
import {
|
|
171
|
-
|
|
191
|
+
import {
|
|
192
|
+
describeFormerIssuer, describeTickerChange, movedAwayChange, startTickerChangeLookup, tickerChangeLine, type FormerIssuer, type TickerChange,
|
|
193
|
+
} from "../../tickers/ticker-changes";
|
|
194
|
+
import { noSecReportsNotice, nonUsSecListingVenue, secFilingItemCodes } from "../../utils/sec";
|
|
172
195
|
import type { MarketContext } from "../types";
|
|
173
196
|
import { windowRows } from "../row-window";
|
|
174
197
|
import { crossRate, describeFxConversion, describeFxRate, FX_USAGE, isUsableRate, parseFxArgs } from "../fx-pair";
|
|
@@ -195,6 +218,7 @@ import { fetchBeneficialOwners } from "../../plugins/builtin/holders/beneficial-
|
|
|
195
218
|
import { centralBankEventsMessage } from "../central-bank-events";
|
|
196
219
|
import { classSharesToday } from "../../plugins/builtin/holders/client";
|
|
197
220
|
import { filingFormMatches, SEC_FILING_FETCH_LIMIT } from "../../plugins/builtin/sec/forms";
|
|
221
|
+
import { currentReportItemsLabel } from "../../utils/sec-filings";
|
|
198
222
|
import { loadParsedInsiderFilings } from "../../plugins/builtin/insider/client";
|
|
199
223
|
import { insiderEmptyNotice } from "../../plugins/builtin/insider/issuer";
|
|
200
224
|
import {
|
|
@@ -220,10 +244,14 @@ type QuoteCliRecord = Omit<QuoteBatchResult, "error"> & {
|
|
|
220
244
|
listing?: { name: string | null };
|
|
221
245
|
/** A futures row's contract, terms and latest confirmed settlement, as `ticker` reads them. */
|
|
222
246
|
futuresContract?: FuturesContractTermsPayload;
|
|
247
|
+
/** The quote of the root's front contract, for a futures row that prices another one (NGF27, NG2). */
|
|
248
|
+
futuresFront?: Quote;
|
|
223
249
|
/** A perpetual row's market, funding per eight hours and open interest. */
|
|
224
250
|
perpetualContract?: PerpetualContractPayload;
|
|
225
251
|
/** The symbol changed: its issuer moved to another symbol, or its holder had another before. */
|
|
226
252
|
tickerChange?: TickerChange;
|
|
253
|
+
/** The company that last held the symbol merged into another, which trades under its own symbol now (GOGL, CMBT). */
|
|
254
|
+
formerIssuer?: FormerIssuer;
|
|
227
255
|
/** A bare symbol read on a listing abroad that is one slip from a US ticker: the US ticker it was most likely typed for. */
|
|
228
256
|
usSuggestion?: ListingSuggestion;
|
|
229
257
|
};
|
|
@@ -244,14 +272,59 @@ function parseNewsFeed(value: string | undefined): NewsQuery["feed"] | undefined
|
|
|
244
272
|
}
|
|
245
273
|
|
|
246
274
|
/**
|
|
247
|
-
* The
|
|
248
|
-
*
|
|
249
|
-
*
|
|
275
|
+
* The entries of a command's arguments (`splitSymbolArgs`), each once however
|
|
276
|
+
* its case or share class was written: `AAPL aapl BRK.B BRK-B` is AAPL and
|
|
277
|
+
* BRK.B. An entry with a space, from a comma list or pasted lines, keeps its
|
|
278
|
+
* case: it may be a company's name, which `readSymbols` says.
|
|
250
279
|
*/
|
|
251
280
|
function normalizeSymbols(args: string[]): string[] {
|
|
252
|
-
return
|
|
281
|
+
return uniqueEntries(splitSymbolArgs(args));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Each entry once, a symbol upper-cased and a company's name in its typed case. */
|
|
285
|
+
function uniqueEntries(entries: readonly string[]): string[] {
|
|
286
|
+
return uniqueSecuritySymbols(entries.map((entry) => isCompanyNameInput(entry) ? entry : entry.toUpperCase()));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* The symbols to resolve: each entry with a space read as a company's name
|
|
291
|
+
* when search finds one, else as its words, each a symbol (`readNameEntries`),
|
|
292
|
+
* with the repeats that leaves dropped. A name found stays whole.
|
|
293
|
+
*/
|
|
294
|
+
async function readSymbols(symbols: readonly string[], dataProvider: Parameters<typeof readNameEntries>[1]): Promise<string[]> {
|
|
295
|
+
return uniqueEntries(await readNameEntries(symbols, dataProvider));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* The symbols of `--file <path>` or standard input (`-`), with any typed
|
|
300
|
+
* beside them, read by the parser `watchlist add` uses. Standard input is read
|
|
301
|
+
* only when asked for, so a script that pipes in nothing never waits on it.
|
|
302
|
+
*/
|
|
303
|
+
async function readListedSymbols(
|
|
304
|
+
args: readonly string[],
|
|
305
|
+
file: string | undefined,
|
|
306
|
+
market: MarketContext,
|
|
307
|
+
ctx: Parameters<CliCommandDef["execute"]>[1],
|
|
308
|
+
usage: string,
|
|
309
|
+
): Promise<string[]> {
|
|
310
|
+
try {
|
|
311
|
+
const list = await readSymbolList({
|
|
312
|
+
args, file, stdinPiped: false, readEntries: (entries) => readNameEntries(entries, market.dataProvider),
|
|
313
|
+
});
|
|
314
|
+
if (list.symbols.length === 0) ctx.fail(`No symbols in ${file && file !== "-" ? file : "standard input"}.`, usage);
|
|
315
|
+
return uniqueEntries(list.symbols);
|
|
316
|
+
} catch (error) {
|
|
317
|
+
if (error instanceof SymbolListError) ctx.fail(error.message, usage);
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
253
320
|
}
|
|
254
321
|
|
|
322
|
+
/** `--file` of quote and compare, as `watchlist add` takes it. */
|
|
323
|
+
const LIST_FILE_OPTION = {
|
|
324
|
+
flags: "--file <path>",
|
|
325
|
+
description: "Read the symbols from a CSV or text file, as watchlist add does (- reads standard input)",
|
|
326
|
+
};
|
|
327
|
+
|
|
255
328
|
/** What JSON metadata says about the listing a command resolved. */
|
|
256
329
|
function listingMetadata(identity: ListingIdentity) {
|
|
257
330
|
return { symbol: identity.symbol, exchange: identity.exchange || null, name: identity.name };
|
|
@@ -366,6 +439,21 @@ function quoteFeedState(quote: QuoteCliRecord["quote"], now: number): "stale" |
|
|
|
366
439
|
return quote.dataSource === "live" || quote.dataSource === "delayed" ? quote.dataSource : "";
|
|
367
440
|
}
|
|
368
441
|
|
|
442
|
+
/** A hundredth of a cent, one basis point of a dollar peg: the decimals CRYP prints a stablecoin to. */
|
|
443
|
+
const STABLECOIN_PRICE_DIGITS = 4;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* A coin trading near a dollar, a dollar stablecoin, prints to four decimals
|
|
447
|
+
* either side of par (0.9987, 1.0003), as CRYP does, whatever digits its
|
|
448
|
+
* source sent (0.99874, 0.99968725); below a dollar a coin otherwise keeps up to eight.
|
|
449
|
+
*/
|
|
450
|
+
function nearParCoin(quote: QuoteCliRecord["quote"]): boolean {
|
|
451
|
+
if (!quote || resolveAssetDisplayKind({ assetCategory: quote.instrumentType }) !== "crypto") return false;
|
|
452
|
+
if ((quote.currency ?? "USD").trim().toUpperCase() !== "USD") return false;
|
|
453
|
+
const reference = [quote.previousClose, quote.price].find((value) => typeof value === "number" && Number.isFinite(value) && value > 0);
|
|
454
|
+
return reference != null && reference >= 0.9 && reference < 1.1;
|
|
455
|
+
}
|
|
456
|
+
|
|
369
457
|
function quoteRows(results: QuoteCliRecord[], now = Date.now()) {
|
|
370
458
|
return results.map((result) => {
|
|
371
459
|
const quote = result.quote;
|
|
@@ -375,12 +463,13 @@ function quoteRows(results: QuoteCliRecord[], now = Date.now()) {
|
|
|
375
463
|
const extended = getExtendedSessionDisplay(quote);
|
|
376
464
|
const yieldIndex = isYieldIndexSymbol(result.target.symbol);
|
|
377
465
|
// An index level is in points, not in the currency its members trade in.
|
|
378
|
-
const indexPoints = quote?.instrumentType
|
|
466
|
+
const indexPoints = isIndexLevel(quote?.instrumentType);
|
|
379
467
|
// Pad to two decimals so a column lines up, but never past the currency's minor unit (JPY has none).
|
|
380
468
|
// Points have no minor unit, so a yen-listed index still pads to two.
|
|
381
469
|
const options = {
|
|
382
470
|
...quoteFormatOptions(quote),
|
|
383
471
|
minimumFractionDigits: indexPoints ? 2 : currencyPriceMinDigits(quote?.currency),
|
|
472
|
+
...nearParCoin(quote) ? { fixedFractionDigits: STABLECOIN_PRICE_DIGITS } : {},
|
|
384
473
|
};
|
|
385
474
|
const price = (value: number | undefined) => (
|
|
386
475
|
quote && value != null
|
|
@@ -413,8 +502,9 @@ function quoteRows(results: QuoteCliRecord[], now = Date.now()) {
|
|
|
413
502
|
dayRange: quote?.low != null && quote.high != null
|
|
414
503
|
? indexPoints ? `${price(quote.low)}-${price(quote.high)}` : formatPriceRange(quote.low, quote.high, quote.currency, options, "-")
|
|
415
504
|
: "",
|
|
416
|
-
|
|
417
|
-
|
|
505
|
+
// An index's 0 is volume nobody counts, and its level has no currency.
|
|
506
|
+
volume: reportedQuoteVolume(quote),
|
|
507
|
+
currency: indexPoints ? "" : quote?.currency ?? "",
|
|
418
508
|
providerId: quote?.providerId ?? "",
|
|
419
509
|
source: quote?.dataSource ?? quote?.providerId ?? "",
|
|
420
510
|
feed: quoteFeedState(quote, now),
|
|
@@ -460,9 +550,20 @@ function filingRows(filings: SecFilingItem[]) {
|
|
|
460
550
|
companyName: filing.companyName ?? "",
|
|
461
551
|
accessionNumber: filing.accessionNumber,
|
|
462
552
|
url: filing.primaryDocumentUrl ?? filing.filingUrl,
|
|
553
|
+
items: secFilingItemCodes(filing.items) ?? "",
|
|
554
|
+
// A current report's items by number and name: the results 8-K reads apart from another filed that day.
|
|
555
|
+
itemsLabel: currentReportItemsLabel(filing.items) ?? "",
|
|
463
556
|
}));
|
|
464
557
|
}
|
|
465
558
|
|
|
559
|
+
/** The filings as JSON gives them, with a current report's items named beside their codes. */
|
|
560
|
+
function filingsWithItemLabels(filings: SecFilingItem[]) {
|
|
561
|
+
return filings.map((filing) => {
|
|
562
|
+
const itemsLabel = currentReportItemsLabel(filing.items);
|
|
563
|
+
return itemsLabel ? { ...filing, itemsLabel } : filing;
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
|
|
466
567
|
function analystSummary(data: AnalystResearchData): string {
|
|
467
568
|
const target = data.priceTarget;
|
|
468
569
|
const currency = analystTargetCurrency(data);
|
|
@@ -596,18 +697,31 @@ const MAX_CHOICE_LOOKUPS = 10;
|
|
|
596
697
|
* names the quote of its new symbol ("HFC became DINO on 2022-03-15:
|
|
597
698
|
* `gloomberb quote DINO`"); its old line's last price stays in the row.
|
|
598
699
|
*/
|
|
599
|
-
function quoteChangeLine(change: TickerChange | null | undefined): string | null {
|
|
700
|
+
function quoteChangeLine(change: TickerChange | null | undefined, formerIssuer?: FormerIssuer | null): string | null {
|
|
600
701
|
const moved = movedAwayChange(change);
|
|
601
|
-
|
|
702
|
+
// One line per symbol: a company that left it, else the company that merged away from it (GOGL).
|
|
703
|
+
return (moved ? movedSymbolLine(moved, `gloomberb quote ${moved.tradesAs}`) : tickerChangeLine(change)) ?? formerIssuer?.note ?? null;
|
|
602
704
|
}
|
|
603
705
|
|
|
604
706
|
async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1], commandName: "quote" | "compare") {
|
|
605
707
|
const args = [...rawArgs];
|
|
708
|
+
const usage = `Usage: gloomberb ${commandName} <symbol...> [--file <path>]`;
|
|
606
709
|
const exchange = takeOption(args, "--exchange") ?? "";
|
|
607
|
-
|
|
608
|
-
|
|
710
|
+
// A list from a file or standard input (`-`), read as `watchlist add` reads one.
|
|
711
|
+
const file = args.some((arg) => arg === "--file" || arg.startsWith("--file=")) ? takeOption(args, "--file") ?? "" : undefined;
|
|
712
|
+
const listed = file != null || args.includes("-");
|
|
713
|
+
const entries = normalizeSymbols(args);
|
|
714
|
+
if (entries.length === 0 && !listed) ctx.fail(usage);
|
|
715
|
+
// One quoted argument with spaces is a company's name, a pasted line of tickers, or a phrase to search for.
|
|
716
|
+
const phrase = exchange || listed ? null : quotedPhrase(args);
|
|
609
717
|
|
|
610
718
|
await withMarketData(ctx, async (market) => {
|
|
719
|
+
const read = phrase ? await readPhraseArgument(phrase, market.dataProvider) : null;
|
|
720
|
+
if (read?.kind === "phrase") return answerPhrase(read.phrase, market, ctx);
|
|
721
|
+
const symbols = read?.kind === "name" ? [read.name]
|
|
722
|
+
: read?.kind === "symbols" ? uniqueEntries(read.symbols)
|
|
723
|
+
: listed ? await readListedSymbols(args, file, market, ctx, usage)
|
|
724
|
+
: await readSymbols(entries, market.dataProvider);
|
|
611
725
|
// With several symbols, --exchange is for the ones that name no exchange of their own.
|
|
612
726
|
const listings = await Promise.all(symbols.map((symbol) => requireCliListing(
|
|
613
727
|
symbol, exchange, market, ctx, { ownExchangeWins: symbols.length > 1 },
|
|
@@ -631,20 +745,26 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
631
745
|
return answerQuote(result, listing, market, request, ctx.cliOptions.refresh, venues.get(listing) ?? null);
|
|
632
746
|
}));
|
|
633
747
|
const now = Date.now();
|
|
634
|
-
const
|
|
748
|
+
const symbolChanges = await Promise.all(answers.map(async ({ result }, index) => {
|
|
635
749
|
const listing = asked[index]!;
|
|
636
750
|
// A bare symbol read on a listing abroad (SXR8 -> XETRA) is not the US symbol the changes are of.
|
|
637
|
-
if (result.quote && bareListingNote(listing, result.quote)) return null;
|
|
638
|
-
|
|
751
|
+
if (result.quote && bareListingNote(listing, result.quote)) return { change: null, formerIssuer: null };
|
|
752
|
+
const payload = await changes.get(listing)?.settle() ?? null;
|
|
753
|
+
const current = tradingListing(result.quote, now);
|
|
754
|
+
return { change: describeTickerChange(listing.symbol, payload, current), formerIssuer: describeFormerIssuer(listing.symbol, payload, current) };
|
|
639
755
|
}));
|
|
756
|
+
const tickerChanges = symbolChanges.map(({ change }) => change);
|
|
757
|
+
const formerIssuers = symbolChanges.map(({ formerIssuer }) => formerIssuer);
|
|
640
758
|
const failed = answers[0]?.failure;
|
|
641
759
|
if (listings.length === 1 && failed) {
|
|
642
|
-
ctx.fail(failed.message, [quoteChangeLine(tickerChanges[0]), failed.details].filter(Boolean).join("\n") || undefined);
|
|
760
|
+
ctx.fail(failed.message, [quoteChangeLine(tickerChanges[0], formerIssuers[0]), failed.details].filter(Boolean).join("\n") || undefined);
|
|
643
761
|
}
|
|
644
762
|
// A futures quote adds its dated settlement and contract terms, as `ticker` prints them; `compare` stays a table.
|
|
645
763
|
const contracts = await Promise.all(answers.map(({ result }) => commandName === "quote" && result.quote
|
|
646
764
|
? cliFuturesContract(result.quote.symbol || result.target.symbol, result.quote.instrumentType)
|
|
647
765
|
: null));
|
|
766
|
+
// A contract that is not its root's front (NGF27, NG2) prints the front's own price beside it, read in one batch.
|
|
767
|
+
const fronts = await loadFuturesFrontQuotes(contracts, market.dataProvider);
|
|
648
768
|
// A perpetual adds its funding per eight hours and open interest, the figures PERP lists beside its mark.
|
|
649
769
|
const perpetualContracts = await Promise.all(answers.map(({ result }) => commandName === "quote" && result.quote
|
|
650
770
|
? cliPerpetualContract(result.quote)
|
|
@@ -662,16 +782,19 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
662
782
|
...getQuoteSessionFields(result.quote),
|
|
663
783
|
quote: result.quote,
|
|
664
784
|
...contracts[index] ? { futuresContract: contracts[index] } : {},
|
|
785
|
+
...fronts[index] ? { futuresFront: fronts[index] } : {},
|
|
665
786
|
...perpetualContracts[index] ? { perpetualContract: perpetualContracts[index] } : {},
|
|
666
787
|
...usSuggestions[index] ? { usSuggestion: usSuggestions[index] } : {},
|
|
667
788
|
error: failure?.oneLine ?? errorMessage(result.error),
|
|
668
789
|
...yieldIndexFields(result),
|
|
669
790
|
...tickerChanges[index] ? { tickerChange: tickerChanges[index] } : {},
|
|
791
|
+
...formerIssuers[index] ? { formerIssuer: formerIssuers[index] } : {},
|
|
670
792
|
}));
|
|
671
793
|
const notes = [
|
|
672
794
|
// FB now lists another security; the company that was FB trades as META. A symbol a
|
|
673
795
|
// company renamed into (META) is what was typed: its change is in the row, not here.
|
|
674
|
-
|
|
796
|
+
// GOGL was Golden Ocean, which merged into CMB.Tech; a fund lists there now.
|
|
797
|
+
...tickerChanges.flatMap((change, index) => quoteChangeLine(change, formerIssuers[index]) ?? []),
|
|
675
798
|
// Which listing a bare symbol was read as, and the index a bare root is not, are in no row.
|
|
676
799
|
...answers.flatMap((answer) => answer.notes),
|
|
677
800
|
// A row that stopped trading long ago reads as a quote that is merely stale.
|
|
@@ -682,14 +805,22 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
682
805
|
...ctx.cliOptions.format === "text" ? quoteNotes(data, { exchange }) : [],
|
|
683
806
|
];
|
|
684
807
|
const columns = commandName === "compare" ? compareColumns() : quoteColumns();
|
|
808
|
+
if (ctx.cliOptions.format !== "json") await primeBoardCoins(notes);
|
|
685
809
|
// Only yield indices: their change is in bp, so the text header drops the percent sign (CSV keeps the percent it holds).
|
|
686
810
|
const yieldsOnly = data.length > 0 && data.every((row) => isYieldIndexSymbol(row.target.symbol));
|
|
687
811
|
ctx.printResult({
|
|
688
812
|
data,
|
|
689
813
|
warnings: notes.length > 0 ? notes : undefined,
|
|
690
|
-
|
|
814
|
+
// A Cboe yield index stops at its 15:00 ET close, before the Treasury's curve is taken: the line says so, so its
|
|
815
|
+
// close does not read as a contradiction of DGS10 or GC for the same day.
|
|
816
|
+
freshness: quotesFreshness(data.map((row) => row.quote), yieldsOnly ? { schedule: `Cboe close ${CBOE_YIELD_INDEX_CLOSE}` } : undefined),
|
|
691
817
|
}, {
|
|
692
818
|
rows: quoteRows,
|
|
819
|
+
// An index row's Cur is blank, its level having no currency; the export names what it is in instead.
|
|
820
|
+
exportIdentity: (row) => ({
|
|
821
|
+
symbolOrSeries: row.symbol,
|
|
822
|
+
currencyOrUnit: row.currency || (row.yieldIndex ? "pct" : isIndexLevel(row.instrumentType) ? INDEX_POINTS_EXPORT_UNIT : null),
|
|
823
|
+
}),
|
|
693
824
|
details: quoteDetailsText,
|
|
694
825
|
columns,
|
|
695
826
|
...(yieldsOnly ? { textColumns: columns.map((column) => column.key === "changePercent" ? { ...column, header: "Chg" } : column) } : {}),
|
|
@@ -699,6 +830,26 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
699
830
|
});
|
|
700
831
|
}
|
|
701
832
|
|
|
833
|
+
/**
|
|
834
|
+
* `quote "10 year yield"`: a phrase that is no ticker and no company's name
|
|
835
|
+
* is answered with what search finds for it and the catalog, never quoted
|
|
836
|
+
* word by word (10, YEAR, YIELD). A script asked for a quote, so structured
|
|
837
|
+
* output fails with where to look instead.
|
|
838
|
+
*/
|
|
839
|
+
async function answerPhrase(phrase: string, market: MarketContext, ctx: Parameters<CliCommandDef["execute"]>[1]): Promise<void> {
|
|
840
|
+
const said = `"${phrase}" is not a ticker or a company's name.`;
|
|
841
|
+
if (ctx.cliOptions.format !== "text") {
|
|
842
|
+
ctx.fail(said, [knownGapMessage(phrase), `Search for it: gloomberb search "${phrase}"`, `Functions and data: gloomberb catalog "${phrase}"`]
|
|
843
|
+
.filter(Boolean).join("\n"));
|
|
844
|
+
}
|
|
845
|
+
process.exitCode = CLI_EXIT_CODES.error;
|
|
846
|
+
if (ctx.cliOptions.quiet) return;
|
|
847
|
+
// Searched first: a busy search fails on its own, without the line saying the phrase names nothing.
|
|
848
|
+
const report = await phraseSearchReport(phrase, market, ctx.plugins);
|
|
849
|
+
console.error(`${cliStyles.warning("warning:")} ${said} What search finds for it:`);
|
|
850
|
+
console.log(report);
|
|
851
|
+
}
|
|
852
|
+
|
|
702
853
|
/**
|
|
703
854
|
* Under the table: each futures row's Settle line and Contract block, then the
|
|
704
855
|
* line for a symbol that is not a US ticker though it is one slip from one.
|
|
@@ -720,9 +871,24 @@ function notUsTickerLine({ target, quote, listing, usSuggestion }: QuoteCliRecor
|
|
|
720
871
|
return cliStyles.warning(`${target.symbol} is not a US ticker: it is ${what}. Did you mean ${describeSuggestion(usSuggestion)}?`);
|
|
721
872
|
}
|
|
722
873
|
|
|
874
|
+
/** Each futures row's front contract quote, when its terms name a front other than its own contract; null otherwise. */
|
|
875
|
+
async function loadFuturesFrontQuotes(
|
|
876
|
+
contracts: ReadonlyArray<FuturesContractTermsPayload | null>,
|
|
877
|
+
provider: Pick<MarketContext["dataProvider"], "getQuotesBatch">,
|
|
878
|
+
): Promise<Array<Quote | null>> {
|
|
879
|
+
const symbols = [...new Set(contracts.flatMap((terms) => terms?.front?.contractSymbol ?? []))];
|
|
880
|
+
if (symbols.length === 0) return contracts.map(() => null);
|
|
881
|
+
const results = await provider.getQuotesBatch(symbols.map((symbol) => ({ symbol, exchange: "" })))
|
|
882
|
+
.catch(logFailure("cli.commands-market", "Read futures front quotes failed", []));
|
|
883
|
+
const quotes = new Map(results.flatMap((result) => result.quote ? [[result.target.symbol, result.quote] as const] : []));
|
|
884
|
+
return contracts.map((terms) => terms?.front ? quotes.get(terms.front.contractSymbol) ?? null : null);
|
|
885
|
+
}
|
|
886
|
+
|
|
723
887
|
/**
|
|
724
|
-
* Each futures row's Settle line and Contract block, worded
|
|
725
|
-
*
|
|
888
|
+
* Each futures row's Settle line and Contract block, worded as `ticker`
|
|
889
|
+
* words them, with how a continuous symbol or a generic rolls, the front it
|
|
890
|
+
* is not and the day's most active contract after the contract it prices.
|
|
891
|
+
* Several symbols name theirs in the block's title.
|
|
726
892
|
*/
|
|
727
893
|
function quoteFuturesContractText(data: QuoteCliRecord[]): string {
|
|
728
894
|
return data.flatMap((row) => {
|
|
@@ -733,7 +899,10 @@ function quoteFuturesContractText(data: QuoteCliRecord[]): string {
|
|
|
733
899
|
const terms = row.futuresContract;
|
|
734
900
|
if (!terms || !row.quote) return [];
|
|
735
901
|
const settle: [string, string] = ["Settle", futuresSettleText(terms, row.quote)];
|
|
736
|
-
const
|
|
902
|
+
const metrics = futuresContractMetrics(terms, row.quote.symbol || row.target.symbol);
|
|
903
|
+
const rolls = futuresRollLines(terms, row.futuresFront).map((line): [string, string] => [line.label, line.value]);
|
|
904
|
+
const at = futuresContractLines(terms, row.quote.symbol || row.target.symbol)[0]?.key === "contract" ? 1 : 0;
|
|
905
|
+
const contract = [...metrics.slice(0, at), ...rolls, ...metrics.slice(at)];
|
|
737
906
|
if (data.length > 1) return [`${renderSection(`${row.target.symbol} Contract`)}\n${renderStats([settle, ...contract])}`];
|
|
738
907
|
return [[renderStats([settle]), ...contract.length ? ["", renderSection("Contract"), renderStats(contract)] : []].join("\n")];
|
|
739
908
|
}).join("\n\n");
|
|
@@ -801,9 +970,13 @@ async function answerQuote(
|
|
|
801
970
|
};
|
|
802
971
|
}
|
|
803
972
|
// Other listings already name a futures board code's future (GC=F); with none, it is named here.
|
|
973
|
+
// A Treasury yield's root (TNX) names its FRED series and the curve beside its index.
|
|
974
|
+
const yieldTenor = root ? treasuryYieldTenor(listing.symbol) : null;
|
|
804
975
|
const tryLines = [
|
|
805
|
-
root ? indexRootTryLine(root, request.command) : null,
|
|
976
|
+
yieldTenor ? treasuryYieldLine(yieldTenor) : root ? indexRootTryLine(root, request.command) : null,
|
|
806
977
|
other || listing.exchange ? null : futuresTryLine(listing.symbol, request),
|
|
978
|
+
// BDI asks which exchange (Black Diamond Group) and says nowhere that the Baltic Dry Index is not here.
|
|
979
|
+
listing.exchange ? null : knownGapForTicker(listing.symbol),
|
|
807
980
|
].filter((line): line is string => !!line);
|
|
808
981
|
if (!other && tryLines.length === 0) return { result: await withCurrencyPairHint(result, market), listing, notes: [] };
|
|
809
982
|
const message = other?.message ?? `${listing.symbol} has no ${request.noun}.`;
|
|
@@ -850,6 +1023,30 @@ function historySymbolArg(args: readonly string[]): string | undefined {
|
|
|
850
1023
|
&& !(index > 0 && args[index - 1]!.startsWith("--") && !args[index - 1]!.includes("=")));
|
|
851
1024
|
}
|
|
852
1025
|
|
|
1026
|
+
/** What people type for quarterly figures, which `financials` (fiscal years) does not take. */
|
|
1027
|
+
const QUARTERLY_OPTIONS = new Set(["--quarterly", "--quarter", "--quarters", "--qtr", "--period", "--periods", "--frequency", "--freq", "--interval"]);
|
|
1028
|
+
|
|
1029
|
+
/** Options before the symbol whose next word is their value: `financials`'s own, and the quarterly ones that take one. */
|
|
1030
|
+
const FINANCIALS_VALUE_OPTIONS = new Set(["--exchange", "--section", "--period", "--periods", "--frequency", "--freq", "--interval"]);
|
|
1031
|
+
|
|
1032
|
+
/** The symbol `financials` was given, wherever it sits: `--quarterly WFC` is WFC, `--period quarterly WFC` too. */
|
|
1033
|
+
function financialsSymbolArg(args: readonly string[]): string | undefined {
|
|
1034
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1035
|
+
const arg = args[index]!;
|
|
1036
|
+
if (!arg.startsWith("-")) return arg;
|
|
1037
|
+
if (!arg.includes("=") && FINANCIALS_VALUE_OPTIONS.has(arg)) index += 1;
|
|
1038
|
+
}
|
|
1039
|
+
return undefined;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/** `financials --quarterly` points at the functions that show quarters: GF a metric over time, FA the statements. */
|
|
1043
|
+
function financialsOptionHint(flag: string, args: readonly string[]): string | null {
|
|
1044
|
+
if (!QUARTERLY_OPTIONS.has(flag)) return null;
|
|
1045
|
+
const symbol = financialsSymbolArg(args) ?? "<symbol>";
|
|
1046
|
+
return `financials lists fiscal years. For quarters: gloomberb fn GF ${symbol} --period quarterly --periods 40 (one metric at a time), `
|
|
1047
|
+
+ `or gloomberb fn FA ${symbol} --period quarterly (the statements).`;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
853
1050
|
function historyOptionHint(flag: string, args: readonly string[]): string | null {
|
|
854
1051
|
if (DATE_WINDOW_OPTIONS.has(flag)) return `history takes a --range instead of dates: ${TIME_RANGES.join(", ")}. ${HISTORY_ALL_RANGE}.`;
|
|
855
1052
|
if (BAR_SIZE_OPTIONS.has(flag)) return `history serves each --range in one bar size. ${subMinuteDataMessage(historySymbolArg(args))}`;
|
|
@@ -884,7 +1081,7 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
884
1081
|
const fromQuote = points !== loaded.points;
|
|
885
1082
|
const identity = listingIdentity(listing, quote);
|
|
886
1083
|
// Without a quote currency, the listing metadata research reads (as `ticker` does) may still state it.
|
|
887
|
-
const listed = quote?.currency ? quote : await market.dataProvider.getQuoteMetadata?.(symbol, exchange).catch((
|
|
1084
|
+
const listed = quote?.currency ? quote : await market.dataProvider.getQuoteMetadata?.(symbol, exchange).catch(logFailure("cli.commands-market", "Read quote metadata for history failed", null));
|
|
888
1085
|
const unit = historyUnit(listing.key, listed ?? quote);
|
|
889
1086
|
const traded = {
|
|
890
1087
|
listing: listing.key, exchange: quote?.listingExchangeName || exchange || undefined, instrumentType: quote?.instrumentType,
|
|
@@ -896,6 +1093,8 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
896
1093
|
const venue = quote?.listingExchangeName || exchange || undefined;
|
|
897
1094
|
// October's monthly bar on 16 Oct runs through the 15th: marked partial, and the status line says how far.
|
|
898
1095
|
const forming = formingPeriodBar(served, venue);
|
|
1096
|
+
// A complete one is dated by the day its last session closed, the day its close is from.
|
|
1097
|
+
const closedDay = forming ? null : closedPeriodBarDay(served, venue);
|
|
899
1098
|
const data = forming?.rows ?? served;
|
|
900
1099
|
const interval = data[0]?.interval ?? null;
|
|
901
1100
|
const decimals = historyPriceDecimals(data, listing.saved?.metadata.assetCategory);
|
|
@@ -910,7 +1109,7 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
910
1109
|
observedKey: "date",
|
|
911
1110
|
oldest: null,
|
|
912
1111
|
cadenceExchange: venue,
|
|
913
|
-
...(forming ? { periodToDate: forming.periodToDate } : {}),
|
|
1112
|
+
...(forming ? { periodToDate: forming.periodToDate } : closedDay ? { asOf: closedDay } : {}),
|
|
914
1113
|
...(dayToDate ? { basis: "daily bars", ...(quote && Number.isFinite(quote.lastUpdated) ? { asOf: new Date(quote.lastUpdated).toISOString() } : {}) } : {}),
|
|
915
1114
|
...(volume || dayToDate ? { note: [volume ? historyVolumeText(volume, interval) : null, dayToDate ? `the newest bar is ${DAY_SO_FAR_TEXT}` : null].filter(Boolean).join("; ") } : {}),
|
|
916
1115
|
});
|
|
@@ -921,7 +1120,8 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
921
1120
|
...await listingChoiceNotes(listing, market, quote, venues),
|
|
922
1121
|
...historyNotes(range, interval, data[0]?.date), historyCoverageWarning(range, loaded) ?? [],
|
|
923
1122
|
// The status line says how far a bar still forming runs; the note is for the bars it does not name.
|
|
924
|
-
gaps ?? [], historyJumpNote(data) ?? [], historyFlagNote(data) ?? [],
|
|
1123
|
+
gaps ?? [], historyJumpNote(data) ?? [], historyFlagNote(data) ?? [], historyMissingVolumeNote(data) ?? [],
|
|
1124
|
+
historyBarStatusNote(forming ? served : data) ?? [],
|
|
925
1125
|
].flat();
|
|
926
1126
|
const priceColumns: CliResultColumn[] = [
|
|
927
1127
|
intraday
|
|
@@ -933,6 +1133,10 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
933
1133
|
{ key: "close", header: "Close", align: "right", format: price },
|
|
934
1134
|
{ key: "volume", header: "Volume", align: "right", format: formatCountCell },
|
|
935
1135
|
];
|
|
1136
|
+
// A bar without volume in a history that reports it prints as missing, never as 0 or blank beside the others.
|
|
1137
|
+
const missingVolume = historyReportsVolume(data) ? MISSING_VOLUME_TEXT : "";
|
|
1138
|
+
const textPriceColumns = priceColumns.map((column) => column.key !== "volume" ? column
|
|
1139
|
+
: { ...column, format: (value: unknown) => formatCountCell(value) || missingVolume });
|
|
936
1140
|
// Text shows a flag only on a bar that has one; the column is dropped when none does.
|
|
937
1141
|
const flagColumn: CliResultColumn = {
|
|
938
1142
|
key: "flag", header: "Flag", format: (value) => typeof value === "string" ? cliStyles.warning(value) : "",
|
|
@@ -972,7 +1176,7 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
972
1176
|
}, {
|
|
973
1177
|
heading: `${listingHeading(identity)}\n${cliStyles.muted(historyFacts(unit, data).join(" · "))}`,
|
|
974
1178
|
dateKey: "date",
|
|
975
|
-
textColumns: [...
|
|
1179
|
+
textColumns: [...textPriceColumns, flagTextColumn],
|
|
976
1180
|
columns: [
|
|
977
1181
|
...priceColumns,
|
|
978
1182
|
flagColumn,
|
|
@@ -1004,6 +1208,21 @@ async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["e
|
|
|
1004
1208
|
const sectionFlag = args.some((arg) => arg === "--section" || arg.startsWith("--section="));
|
|
1005
1209
|
const section = takeOption(args, "--section");
|
|
1006
1210
|
const commandName = view === "statements" ? "financials" : view;
|
|
1211
|
+
// `fundamentals --tax-rate 40.8 [--state-rate 9.3 --state CA]`: a muni fund's tax-equivalent yield and muni/Treasury ratio.
|
|
1212
|
+
let rates: TaxRates | null = null;
|
|
1213
|
+
if (view === "fundamentals") {
|
|
1214
|
+
const taken = (flag: string) => {
|
|
1215
|
+
const given = args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
1216
|
+
const value = takeOption(args, flag);
|
|
1217
|
+
if (given && !value?.trim()) ctx.fail(`${flag} needs a value, such as --tax-rate 40.8 --state-rate 9.3 --state CA.`);
|
|
1218
|
+
return value;
|
|
1219
|
+
};
|
|
1220
|
+
try {
|
|
1221
|
+
rates = parseTaxRates({ taxRate: taken("--tax-rate"), stateRate: taken("--state-rate"), state: taken("--state") });
|
|
1222
|
+
} catch (error) {
|
|
1223
|
+
ctx.fail(error instanceof Error ? error.message : String(error));
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1007
1226
|
const tabular = ctx.cliOptions.format === "csv" || ctx.cliOptions.format === "ndjson";
|
|
1008
1227
|
if (sectionFlag && !tabular) ctx.fail("--section picks one table of --csv or --ndjson output.");
|
|
1009
1228
|
if (sectionFlag && !section?.trim()) ctx.fail("--section needs a section title or number.");
|
|
@@ -1021,6 +1240,15 @@ async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["e
|
|
|
1021
1240
|
const financials = await loadForListing(listing, market, ctx, () => market.dataProvider.getTickerFinancials(
|
|
1022
1241
|
listing.request.symbol, listing.request.exchange, { cacheMode: ctx.cliOptions.refresh ? "refresh" : "default" },
|
|
1023
1242
|
), undefined, { command: commandName, noun: commandName === "valuation" ? "valuation data" : commandName });
|
|
1243
|
+
// A trailing yield is measured from the cash history as DVD measures it, a forward yield dated ahead names the
|
|
1244
|
+
// declared distribution it annualizes (not in JSON), and one whose dividend stopped says so; read beside the listing notes.
|
|
1245
|
+
const distributions = view === "statements" ? null : loadDividendDistributions(
|
|
1246
|
+
market.dataProvider, listing.request, financials, { declared: ctx.cliOptions.format !== "json" });
|
|
1247
|
+
// A bond fund's SEC yield, yield to worst and duration, beside its distribution yield.
|
|
1248
|
+
const bondFund = view === "statements" ? null : loadReportBondFacts(listing.request.symbol,
|
|
1249
|
+
financials.quote?.tradingExchangeName || listing.request.exchange || financials.quote?.listingExchangeName || financials.quote?.exchangeName,
|
|
1250
|
+
financials, listing.saved);
|
|
1251
|
+
const treasury = rates ? loadTreasuryTenors() : null;
|
|
1024
1252
|
const identity = listingIdentity(listing, financials.quote);
|
|
1025
1253
|
const choice = await listingChoiceNotes(listing, market, financials.quote, venues);
|
|
1026
1254
|
const data: FinancialsCliData = {
|
|
@@ -1035,10 +1263,23 @@ async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["e
|
|
|
1035
1263
|
// Market cap, the multiples and the yield at the regular session price, as the text gives them; the quote stays as sent.
|
|
1036
1264
|
const priced = atRegularSessionPrice(financials);
|
|
1037
1265
|
const capitalization = selectMarketCapitalization(priced.quote, priced.fundamentals);
|
|
1038
|
-
//
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1266
|
+
// The filings behind the latest statements, and for a bank its deposits, uninsured share and CRE.
|
|
1267
|
+
const [statementFilings, bank] = view === "fundamentals"
|
|
1268
|
+
? await Promise.all([
|
|
1269
|
+
loadStatementFilings(market.statementSources, listing.request, {
|
|
1270
|
+
quarter: latestFinancialPeriod(financials.quarterlyStatements, (row) => row.date),
|
|
1271
|
+
annual: latestFinancialPeriod(financials.annualStatements, (row) => row.date),
|
|
1272
|
+
}),
|
|
1273
|
+
loadBankFigures(market.statementSources, listing.request, financials),
|
|
1274
|
+
])
|
|
1275
|
+
: [null, { bank: null, note: null }];
|
|
1276
|
+
const bond = await bondFund;
|
|
1277
|
+
// On the SEC yield when the sponsor publishes one, else the distribution yield the line above shows.
|
|
1278
|
+
const taxEquivalent = rates ? analyzeTaxEquivalent({
|
|
1279
|
+
symbol: identity.symbol || listing.key, bond, rates, treasury: await treasury,
|
|
1280
|
+
distribution: distributionBasis(priced.fundamentals?.dividendYield, priced.fundamentals?.dividendYieldBasis === "trailing" ? "trailing" : "forward"),
|
|
1281
|
+
}) : null;
|
|
1282
|
+
const report = { ...data, distributions: await distributions, statementFilings, bank: bank.bank, bankNote: bank.note, bondFund: bond, taxEquivalent };
|
|
1042
1283
|
ctx.printResult({
|
|
1043
1284
|
// JSON reads a multiple over a loss as null with its reason, never as a number.
|
|
1044
1285
|
data: {
|
|
@@ -1048,7 +1289,11 @@ async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["e
|
|
|
1048
1289
|
marketCap: capitalization?.value ?? null,
|
|
1049
1290
|
marketCapCurrency: capitalization?.currency ?? null,
|
|
1050
1291
|
} : {},
|
|
1051
|
-
fundamentals: exportedFundamentals(priced.fundamentals),
|
|
1292
|
+
fundamentals: priced.fundamentals && exportedDividendFundamentals(exportedFundamentals(priced.fundamentals)!, report.distributions),
|
|
1293
|
+
// A bond fund's sponsor figures; fundamentals.dividendYield is then its distribution yield, not its SEC yield.
|
|
1294
|
+
...bond ? { bondFund: bond } : {},
|
|
1295
|
+
...view === "fundamentals" ? { statementFilings, bank: bank.bank, ...bank.note ? { bankNote: bank.note } : {} } : {},
|
|
1296
|
+
...taxEquivalent ? { taxEquivalent: taxEquivalentJson(taxEquivalent) } : {},
|
|
1052
1297
|
},
|
|
1053
1298
|
freshness,
|
|
1054
1299
|
...(choice.length > 0 ? { warnings: choice } : {}),
|
|
@@ -1170,36 +1415,56 @@ async function runNews(rawArgs: string[], ctx: Parameters<CliCommandDef["execute
|
|
|
1170
1415
|
: undefined;
|
|
1171
1416
|
if (word && reason) {
|
|
1172
1417
|
// The lookup that found no ticker already answered; a search that fails leaves that answer.
|
|
1173
|
-
const found = await searchNewsStories(word, limit).catch((
|
|
1418
|
+
const found = await searchNewsStories(word, limit).catch(logFailure("cli.commands-market", "Search news stories failed", []));
|
|
1174
1419
|
await printNewsSearch(word, found, { reason, empty: emptyMessage(true) }, ctx);
|
|
1175
1420
|
return;
|
|
1176
1421
|
}
|
|
1177
1422
|
const empty = emptyMessage(false);
|
|
1178
1423
|
const read = listing ? listingReadNotes(listing) : [];
|
|
1424
|
+
// A word that is also the company's name ("gold" for Gold.com Inc.) says once which ticker it found and how
|
|
1425
|
+
// to search the stories that mention it instead, when those stories are mostly about something else.
|
|
1426
|
+
const typed = args[0]?.trim() ?? "";
|
|
1427
|
+
const wordHint = listing && resolved && !listing.exchange && !feed && !exchangeOption && commonWordCandidate(typed, identity?.name)
|
|
1428
|
+
&& wordMeansMore(await searchNewsStories(typed, 20).catch(logFailure("cli.commands-market", "Search news stories for a ticker word failed", [])), listing.symbol)
|
|
1429
|
+
? `${typed} → ${identity?.name ?? listing.symbol} (ticker ${listing.symbol}). For stories that mention ${typed.toLowerCase()}, try: ${quotedSearchCommand(typed.toLowerCase())}`
|
|
1430
|
+
: null;
|
|
1179
1431
|
ctx.printResult({
|
|
1180
1432
|
data: articles,
|
|
1181
1433
|
...(read.length > 0 ? { warnings: read } : {}),
|
|
1182
|
-
metadata: { ticker: listing?.key ?? null, ...(identity ? listingMetadata(identity) : {}), feed: feed ?? null },
|
|
1434
|
+
metadata: { ticker: listing?.key ?? null, ...(identity ? listingMetadata(identity) : {}), feed: feed ?? null, ...(wordHint ? { textSearch: quotedSearchCommand(typed.toLowerCase()) } : {}) },
|
|
1183
1435
|
freshness: rowsFreshness(newsRows(articles), cloudNewsFreshness(await cloudRealtimeAccess())),
|
|
1184
1436
|
}, {
|
|
1185
1437
|
...(identity ? { heading: listingHeading(identity) } : {}),
|
|
1186
1438
|
rows: newsRows,
|
|
1187
1439
|
columns: NEWS_COLUMNS,
|
|
1188
1440
|
...(empty ? { empty } : {}),
|
|
1441
|
+
...(wordHint ? { footnote: wordHint } : {}),
|
|
1189
1442
|
});
|
|
1190
1443
|
});
|
|
1191
1444
|
}
|
|
1192
1445
|
|
|
1446
|
+
// Exports keep the columns they had and add the items after them: codes, then their names.
|
|
1193
1447
|
const FILING_COLUMNS = [
|
|
1194
1448
|
{ key: "filingDate", header: "Date" },
|
|
1195
1449
|
{ key: "form", header: "Form" },
|
|
1196
1450
|
{ key: "companyName", header: "Company", maxWidth: 24 },
|
|
1197
1451
|
{ key: "url", header: "URL", optional: true },
|
|
1452
|
+
{ key: "items", header: "Items" },
|
|
1453
|
+
{ key: "itemsLabel", header: "Item names" },
|
|
1454
|
+
];
|
|
1455
|
+
|
|
1456
|
+
// The text table names the items before the URL, which a narrow terminal drops first.
|
|
1457
|
+
const FILING_TEXT_COLUMNS = [
|
|
1458
|
+
{ key: "filingDate", header: "Date" },
|
|
1459
|
+
{ key: "form", header: "Form" },
|
|
1460
|
+
{ key: "companyName", header: "Company", maxWidth: 24 },
|
|
1461
|
+
{ key: "itemsLabel", header: "Items" },
|
|
1462
|
+
{ key: "url", header: "URL", optional: true },
|
|
1198
1463
|
];
|
|
1199
1464
|
|
|
1200
1465
|
/** The US listing the SEC files a symbol under, from the symbol's venues: NYSE for SAN's Banco Santander. */
|
|
1201
1466
|
async function registrantUsExchange(market: MarketContext, symbol: string, registrantName: string): Promise<string | null> {
|
|
1202
|
-
const venues = (await listingVenues(symbol, market).catch((
|
|
1467
|
+
const venues = (await listingVenues(symbol, market).catch(logFailure("cli.commands-market", "Read listing venues for filings failed", [])))
|
|
1203
1468
|
.filter((venue) => !nonUsSecListingVenue(symbol, venue.exchange) && !areDifferentCompanies(venue.name, registrantName));
|
|
1204
1469
|
return (venues.find((venue) => isUsListingExchange(venue.exchange)) ?? venues[0])?.exchange ?? null;
|
|
1205
1470
|
}
|
|
@@ -1232,7 +1497,7 @@ async function runFilings(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1232
1497
|
const resolved = identity ?? listingIdentity(listing, quote);
|
|
1233
1498
|
const choice = await listingChoiceNotes(listing, market, quote, venues);
|
|
1234
1499
|
ctx.printResult({
|
|
1235
|
-
data: filings,
|
|
1500
|
+
data: filingsWithItemLabels(filings),
|
|
1236
1501
|
metadata: { ...listingMetadata(resolved), ...(form ? { form } : {}) },
|
|
1237
1502
|
freshness: rowsFreshness(filingRows(filings), { ...SEC_FILINGS, observedKey: "filingDate" }),
|
|
1238
1503
|
...(choice.length > 0 ? { warnings: choice } : {}),
|
|
@@ -1240,6 +1505,7 @@ async function runFilings(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1240
1505
|
heading: listingHeading(resolved),
|
|
1241
1506
|
rows: filingRows,
|
|
1242
1507
|
columns: FILING_COLUMNS,
|
|
1508
|
+
textColumns: FILING_TEXT_COLUMNS,
|
|
1243
1509
|
// A listing abroad is looked up by its company: none found means the company files nothing with the SEC.
|
|
1244
1510
|
empty: form ? `No ${form} filings found for ${listingTitle(resolved)}.`
|
|
1245
1511
|
: identity ? noSecReportsNotice(resolved)
|
|
@@ -1256,7 +1522,7 @@ async function runFilings(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1256
1522
|
data: [] as SecFilingItem[],
|
|
1257
1523
|
metadata: { ...listingMetadata(resolved), secRegistrant: error.registrantName },
|
|
1258
1524
|
warnings: ctx.cliOptions.format === "text" ? undefined : [message],
|
|
1259
|
-
}, { rows: filingRows, columns: FILING_COLUMNS, empty: message });
|
|
1525
|
+
}, { rows: filingRows, columns: FILING_COLUMNS, textColumns: FILING_TEXT_COLUMNS, empty: message });
|
|
1260
1526
|
}
|
|
1261
1527
|
});
|
|
1262
1528
|
}
|
|
@@ -1277,7 +1543,8 @@ async function loadForm4Insiders(market: MarketContext, listing: CliListing): Pr
|
|
|
1277
1543
|
if (parsed.length > 0) return "available";
|
|
1278
1544
|
if (noFilings && nonUsSecListingVenue(listing.request.symbol, listing.request.exchange)) return "no-sec-reports";
|
|
1279
1545
|
return foreignPrivateIssuer ? "foreign-private-issuer" : "none";
|
|
1280
|
-
} catch {
|
|
1546
|
+
} catch (error) {
|
|
1547
|
+
logFailure("cli.commands-market", "Read insider filing availability failed")(error);
|
|
1281
1548
|
return null;
|
|
1282
1549
|
}
|
|
1283
1550
|
}
|
|
@@ -1323,10 +1590,10 @@ async function printBeneficialOwners(
|
|
|
1323
1590
|
const request = { form: beneficialRouteForm(form), history, listing: { exchange, name: abroad?.name ?? undefined } };
|
|
1324
1591
|
const [payload, holders, quote, financials] = await Promise.all([
|
|
1325
1592
|
loadForListing(listing, market, ctx, () => fetchBeneficialOwners(symbol, request)),
|
|
1326
|
-
market.dataProvider.getHolders?.(symbol, exchange).catch((
|
|
1593
|
+
market.dataProvider.getHolders?.(symbol, exchange).catch(logFailure("cli.commands-market", "Read company holders failed", null)) ?? null,
|
|
1327
1594
|
quotePromise,
|
|
1328
1595
|
// Today's share count, which the filed percents are set against.
|
|
1329
|
-
market.dataProvider.getTickerFinancials(symbol, exchange).catch((
|
|
1596
|
+
market.dataProvider.getTickerFinancials(symbol, exchange).catch(logFailure("cli.commands-market", "Read company financials for holders failed", null)),
|
|
1330
1597
|
]);
|
|
1331
1598
|
const identity = listingIdentity(listing, quote);
|
|
1332
1599
|
const sharesOutstanding = classSharesToday(financials);
|
|
@@ -1557,9 +1824,9 @@ async function runEvents(rawArgs: string[], ctx: Parameters<CliCommandDef["execu
|
|
|
1557
1824
|
ctx.printResult({
|
|
1558
1825
|
data,
|
|
1559
1826
|
metadata: listingMetadata(identity),
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
}),
|
|
1827
|
+
// Dated by when it was read, as EE and fn EVT date the same events: a row's
|
|
1828
|
+
// date is when the event happens, and the newest past one is no as-of.
|
|
1829
|
+
freshness: rowsFreshness([], { ...REPORTED_DATA, basis: "corporate actions", oldest: null }),
|
|
1563
1830
|
...(choice.length > 0 ? { warnings: choice } : {}),
|
|
1564
1831
|
}, {
|
|
1565
1832
|
heading: listingHeading(identity),
|
|
@@ -1583,9 +1850,9 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1583
1850
|
const expirationGiven = expiration != null || rawArgs.some((arg) => arg === "--expiration" || arg.startsWith("--expiration="));
|
|
1584
1851
|
const criteria = parseLeapsCriteria({ ...leapsOptions.raw, ...expirationGiven ? { "--expiration": expiration ?? "" } : {} });
|
|
1585
1852
|
if ("error" in criteria) ctx.fail(criteria.error, `Usage: gloomberb ${LEAPS_USAGE}`);
|
|
1586
|
-
const
|
|
1587
|
-
if (
|
|
1588
|
-
await withMarketData(ctx, (market) => runLeapsScreen(
|
|
1853
|
+
const entries = normalizeSymbols(args);
|
|
1854
|
+
if (entries.length === 0) ctx.fail("--leaps needs at least one symbol.", `Usage: gloomberb ${LEAPS_USAGE}`);
|
|
1855
|
+
await withMarketData(ctx, async (market) => runLeapsScreen(await readSymbols(entries, market.dataProvider), exchangeOption, criteria, market, ctx));
|
|
1589
1856
|
return;
|
|
1590
1857
|
}
|
|
1591
1858
|
if (leapsOptions.given.length > 0) {
|
|
@@ -1598,7 +1865,7 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1598
1865
|
if (parsed == null) {
|
|
1599
1866
|
ctx.fail(
|
|
1600
1867
|
expiration == null ? "--expiration needs a date." : `Invalid --expiration "${expiration}".`,
|
|
1601
|
-
`Use
|
|
1868
|
+
`Use ${OPTION_EXPIRATION_FORMAT}.\nUsage: gloomberb ${OPTIONS_USAGE}`,
|
|
1602
1869
|
);
|
|
1603
1870
|
}
|
|
1604
1871
|
expirationDate = parsed;
|
|
@@ -1634,7 +1901,7 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1634
1901
|
// An unlisted date comes back as an empty chain; its own list of expiries, else the default chain's, says what to pick.
|
|
1635
1902
|
const listed = loaded.expirationDates.length > 0 ? loaded.expirationDates : await market.dataProvider
|
|
1636
1903
|
.getOptionsChain(symbol, exchange, undefined, { cacheMode: "default" })
|
|
1637
|
-
.then((fallback) => fallback.expirationDates, (
|
|
1904
|
+
.then((fallback) => fallback.expirationDates, logFailure("cli-market", "Read available option expirations failed", []));
|
|
1638
1905
|
const miss = missingExpiryMessage(listing.key, expirationDate, listed);
|
|
1639
1906
|
ctx.fail(miss.message, miss.details);
|
|
1640
1907
|
}
|
|
@@ -1810,9 +2077,10 @@ async function runFx(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]
|
|
|
1810
2077
|
async function runEarnings(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
1811
2078
|
const args = [...rawArgs];
|
|
1812
2079
|
const exchangeOption = takeOption(args, "--exchange");
|
|
1813
|
-
const
|
|
1814
|
-
if (
|
|
2080
|
+
const entries = normalizeSymbols(args);
|
|
2081
|
+
if (entries.length === 0) ctx.fail("Usage: gloomberb earnings <symbol...>");
|
|
1815
2082
|
await withCliServices(ctx, async (services) => {
|
|
2083
|
+
const symbols = await readSymbols(entries, services.dataProvider);
|
|
1816
2084
|
const listings = await Promise.all(symbols.map((symbol) => requireCliListing(
|
|
1817
2085
|
symbol, exchangeOption, services, ctx, { ownExchangeWins: symbols.length > 1 },
|
|
1818
2086
|
)));
|
|
@@ -1875,9 +2143,9 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
1875
2143
|
description: "Show the latest price for one or more symbols",
|
|
1876
2144
|
help: {
|
|
1877
2145
|
group: CLI_COMMAND_GROUPS.research,
|
|
1878
|
-
usage: ["quote <symbol...>"],
|
|
1879
|
-
options: [EXCHANGE_OPTION],
|
|
1880
|
-
examples: ["quote AAPL MSFT NVDA", "quote SAN:EPA BHP:ASX", "quote BTC-USD EURUSD=X", "quote binance:BZUSDT", "quote AAPL --json"],
|
|
2146
|
+
usage: ["quote <symbol...>", "quote --file <path>"],
|
|
2147
|
+
options: [EXCHANGE_OPTION, LIST_FILE_OPTION],
|
|
2148
|
+
examples: ["quote AAPL MSFT NVDA", "quote SAN:EPA BHP:ASX", "quote BTC-USD EURUSD=X", "quote binance:BZUSDT", "quote AAPL --json", "quote --file holdings.csv"],
|
|
1881
2149
|
},
|
|
1882
2150
|
execute: (args, ctx) => runQuote(args, ctx, "quote"),
|
|
1883
2151
|
},
|
|
@@ -1886,9 +2154,9 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
1886
2154
|
description: "Compare quotes for several symbols side by side",
|
|
1887
2155
|
help: {
|
|
1888
2156
|
group: CLI_COMMAND_GROUPS.research,
|
|
1889
|
-
usage: ["compare <symbol...>"],
|
|
1890
|
-
options: [EXCHANGE_OPTION],
|
|
1891
|
-
examples: ["compare KO PEP", "compare SAN:EPA SAN:NYSE", "compare SPY QQQ IWM --csv"],
|
|
2157
|
+
usage: ["compare <symbol...>", "compare --file <path>"],
|
|
2158
|
+
options: [EXCHANGE_OPTION, LIST_FILE_OPTION],
|
|
2159
|
+
examples: ["compare KO PEP", "compare SAN:EPA SAN:NYSE", "compare SPY QQQ IWM --csv", "compare - < peers.txt"],
|
|
1892
2160
|
},
|
|
1893
2161
|
execute: (args, ctx) => runQuote(args, ctx, "compare"),
|
|
1894
2162
|
},
|
|
@@ -1929,7 +2197,7 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
1929
2197
|
usage: [OPTIONS_USAGE, LEAPS_USAGE],
|
|
1930
2198
|
options: [
|
|
1931
2199
|
{
|
|
1932
|
-
flags:
|
|
2200
|
+
flags: `--expiration <${OPTION_EXPIRATION_PLACEHOLDER}>`,
|
|
1933
2201
|
description: "Expiration as a date (2028-01-21) or Unix seconds; defaults to the nearest one, and lists the others. With --leaps: rank that expiry alone",
|
|
1934
2202
|
},
|
|
1935
2203
|
EXCHANGE_OPTION,
|
|
@@ -1949,8 +2217,8 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
1949
2217
|
description: `With --leaps: fewest calendar days to expiry (default ${DEFAULT_LEAPS_CRITERIA.minDays}); 180 reaches six months out`,
|
|
1950
2218
|
},
|
|
1951
2219
|
{ flags: "--max-days <days>", description: "With --leaps: most calendar days to expiry; --min-days 365 --max-days 730 is 12 to 24 months" },
|
|
1952
|
-
{ flags: "--expiry-from <
|
|
1953
|
-
{ flags: "--expiry-to <
|
|
2220
|
+
{ flags: "--expiry-from <date>", description: `With --leaps: first expiry date kept, as ${DATE_OPTION_EXAMPLES}; replaces the one-year floor` },
|
|
2221
|
+
{ flags: "--expiry-to <date>", description: "With --leaps: last expiry date kept" },
|
|
1954
2222
|
{
|
|
1955
2223
|
flags: "--columns <list>",
|
|
1956
2224
|
description: `With --leaps: add figures, comma-separated: ${LEAPS_EXTRA_COLUMNS.join(", ")}`,
|
|
@@ -2018,6 +2286,7 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
2018
2286
|
options: [EXCHANGE_OPTION, TABLE_SECTION_OPTION],
|
|
2019
2287
|
examples: ["financials MSFT", "financials SAN:EPA", "financials MSFT --json", "financials MSFT --csv > msft.csv"],
|
|
2020
2288
|
},
|
|
2289
|
+
unknownOptionHint: financialsOptionHint,
|
|
2021
2290
|
execute: (args, ctx) => runFinancials(args, ctx, "statements"),
|
|
2022
2291
|
},
|
|
2023
2292
|
{
|
|
@@ -2026,8 +2295,9 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
2026
2295
|
help: {
|
|
2027
2296
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
2028
2297
|
usage: ["fundamentals <symbol>"],
|
|
2029
|
-
options: [EXCHANGE_OPTION, TABLE_SECTION_OPTION],
|
|
2030
|
-
examples: ["fundamentals NVDA", "fundamentals ASML:AMS", "fundamentals NVDA --csv --section fundamentals"
|
|
2298
|
+
options: [EXCHANGE_OPTION, TABLE_SECTION_OPTION, ...TAX_RATE_HELP_OPTIONS],
|
|
2299
|
+
examples: ["fundamentals NVDA", "fundamentals ASML:AMS", "fundamentals NVDA --csv --section fundamentals", "fundamentals MUB --tax-rate 40.8",
|
|
2300
|
+
"fundamentals CMF --tax-rate 40.8 --state-rate 13.3 --state CA"],
|
|
2031
2301
|
},
|
|
2032
2302
|
execute: (args, ctx) => runFinancials(args, ctx, "fundamentals"),
|
|
2033
2303
|
},
|
|
@@ -2151,9 +2421,10 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
2151
2421
|
title: "Text",
|
|
2152
2422
|
lines: [
|
|
2153
2423
|
"Several words, in quotes or not, search the stories that mention them. So does a single word of three letters or more that no listing answers to, and a futures board code such as TTF, a gas benchmark rather than a ticker. A real ticker always gives its own news. The best matches print newest first, 20 unless --limit says otherwise; a search takes neither --feed nor --exchange.",
|
|
2424
|
+
"A shell drops the quotes around one word, so news \"gold\" is the ticker GOLD. Keep them to search the text: news '\"gold\"'. When a word you type is also the name of the company it found, and the stories that mention it are mostly about something else, the listing says so under its stories with that command.",
|
|
2154
2425
|
],
|
|
2155
2426
|
}],
|
|
2156
|
-
examples: ["news", "news TSLA", "news SAN:EPA", "news TTF", "news \"european gas\"", "news --feed top --limit 10"],
|
|
2427
|
+
examples: ["news", "news TSLA", "news SAN:EPA", "news TTF", "news \"european gas\"", "news '\"gold\"'", "news --feed top --limit 10"],
|
|
2157
2428
|
},
|
|
2158
2429
|
execute: runNews,
|
|
2159
2430
|
},
|