gloomberb 0.18.4 → 0.19.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 +1 -1
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +169 -5
- package/src/account/auth-model.ts +7 -3
- package/src/api-client/auth.ts +9 -4
- package/src/api-client/catalysts.ts +2 -1
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +31 -6
- package/src/api-client/equity-screener.ts +24 -0
- package/src/api-client/fund-facts.ts +45 -4
- package/src/api-client/index.ts +171 -11
- package/src/api-client/live-scan.ts +91 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/market-movers.ts +7 -0
- package/src/api-client/members.ts +13 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/request.ts +222 -41
- package/src/api-client/research-activity.ts +6 -12
- package/src/api-client/types.ts +74 -0
- package/src/app/keybindings/index.ts +3 -0
- package/src/app/keybindings/labels.ts +18 -1
- package/src/app/keybindings/resolve.ts +14 -0
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +42 -27
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/core-builtin-allowlist.json +1 -1
- package/src/architecture/pane-tabs-allowlist.json +3 -0
- package/src/architecture/ttl-caches-allowlist.json +19 -0
- package/src/brokers/sync-broker-instance.ts +2 -8
- package/src/capabilities/chart-series.ts +1 -1
- package/src/cli/commands/crypto-hints.ts +40 -24
- package/src/cli/commands/fred-series.ts +5 -0
- package/src/cli/commands/keybindings.ts +23 -0
- package/src/cli/commands/market.ts +138 -46
- package/src/cli/commands/options-chain.ts +107 -10
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +176 -39
- package/src/cli/commands/search.ts +39 -3
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +57 -35
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +10 -2
- package/src/cli/export-source.ts +29 -1
- package/src/cli/glossary.ts +73 -1
- package/src/cli/history-rows.ts +87 -16
- package/src/cli/index.ts +2 -0
- package/src/cli/known-gaps.ts +5 -2
- package/src/cli/listing-arg.ts +195 -56
- package/src/cli/output-file.ts +68 -0
- package/src/cli/pane-functions/capabilities.ts +3 -0
- package/src/cli/pane-functions/catalog.ts +80 -7
- package/src/cli/pane-functions/dom.ts +13 -3
- package/src/cli/pane-functions/freshness.ts +111 -16
- package/src/cli/pane-functions/function-help.ts +23 -13
- package/src/cli/pane-functions/headless.ts +56 -12
- package/src/cli/pane-functions/index.ts +58 -16
- package/src/cli/pane-functions/market-session.ts +81 -9
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/report.ts +5 -1
- package/src/cli/pane-functions/resolver.ts +35 -8
- package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
- package/src/cli/pane-functions/screenshot-types.ts +5 -0
- package/src/cli/quote-answer.ts +30 -13
- package/src/cli/report-tables.ts +18 -7
- package/src/cli/restore-plugins.ts +13 -1
- package/src/cli/result.ts +57 -5
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +26 -4
- package/src/components/chart/composite/format.ts +27 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/levels.ts +2 -0
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +61 -5
- package/src/components/chart/composite/range-statistics.ts +62 -0
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +46 -7
- package/src/components/chart/composite/series-axis-tags.tsx +16 -9
- package/src/components/chart/composite/series-cues.ts +14 -0
- package/src/components/chart/composite/text-renderer.ts +9 -2
- package/src/components/chart/composite/tool-catalog.ts +36 -0
- package/src/components/chart/composite/tools.ts +203 -44
- package/src/components/chart/composite/types.ts +4 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
- package/src/components/command-bar/assist/inventory.ts +2 -1
- package/src/components/command-bar/commands/direct/index.ts +28 -13
- package/src/components/command-bar/pane-templates/items.ts +3 -2
- package/src/components/command-bar/panel/prompt-binding.ts +0 -8
- package/src/components/command-bar/workflow/alert.ts +1 -1
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/layout/header.tsx +26 -40
- package/src/components/layout/pane/footer/index.tsx +1 -0
- package/src/components/layout/pane/footer/model.ts +27 -0
- package/src/components/onboarding/onboarding-frame.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -9
- package/src/components/onboarding/wizard-broker-sync.ts +0 -1
- package/src/components/onboarding/wizard-positions.ts +3 -3
- package/src/components/ticker/list-table-view.tsx +4 -1
- package/src/components/ui/choice-dialog.tsx +23 -18
- package/src/components/ui/choice-groups.ts +18 -0
- package/src/components/ui/data-table/opentui/index.tsx +9 -7
- package/src/components/ui/data-table/opentui/model.ts +26 -1
- package/src/components/ui/data-table/types.ts +2 -0
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/list-view.tsx +8 -4
- package/src/components/ui/query-bar-keys.tsx +2 -0
- package/src/components/ui/query-bar.tsx +1 -0
- package/src/components/ui/select-button.tsx +5 -1
- package/src/components/ui/select-field.tsx +1 -0
- package/src/components/ui/table-layout.ts +8 -5
- package/src/core/app-runtime.ts +2 -0
- package/src/core/app-services.ts +2 -2
- package/src/core/state/app/layout.ts +2 -0
- package/src/core/state/app/state.ts +9 -0
- package/src/core/state/app/types.ts +3 -0
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/saved-copies.ts +55 -16
- package/src/data/ticker-repository.ts +16 -9
- package/src/data/ticker-writes.ts +81 -0
- package/src/data/ttl-cache.ts +165 -0
- package/src/docs/snapshot.json +427 -216
- package/src/i18n/es.ts +19 -3
- package/src/i18n/ja.ts +19 -3
- package/src/i18n/ko.ts +19 -3
- package/src/i18n/zh-cn.ts +19 -3
- package/src/i18n/zh-tw.ts +19 -3
- package/src/market-data/coordinator/financials.ts +10 -2
- package/src/market-data/coordinator/index.ts +3 -1
- package/src/market-data/coordinator/quotes.ts +4 -2
- package/src/market-data/depositary-pair.ts +2 -2
- package/src/market-data/fund-facts.ts +50 -0
- package/src/market-data/market/change-basis.ts +48 -7
- package/src/market-data/market/dated-previous-close.ts +203 -0
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/market/futures-week.ts +68 -0
- package/src/market-data/market/status.ts +16 -4
- package/src/market-data/options-alternatives.ts +141 -4
- package/src/market-data/quotes/contributions.ts +20 -2
- package/src/market-data/quotes/resolution.ts +3 -0
- package/src/market-data/selectors.ts +3 -0
- package/src/news/aggregator.ts +113 -9
- package/src/news/cloud-session.ts +21 -0
- package/src/news/hooks.ts +1 -0
- package/src/news/news-model.ts +1 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/notification-log.ts +6 -4
- package/src/plugins/builtin/alerts/alert-engine.ts +25 -2
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/calendar-events.ts +57 -6
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +380 -82
- package/src/plugins/builtin/alerts/command.ts +31 -0
- package/src/plugins/builtin/alerts/constants.ts +1 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
- package/src/plugins/builtin/alerts/fired-log.ts +113 -8
- package/src/plugins/builtin/alerts/format.ts +80 -4
- package/src/plugins/builtin/alerts/headless.ts +30 -7
- package/src/plugins/builtin/alerts/history-rows.ts +7 -3
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +135 -22
- package/src/plugins/builtin/alerts/live.ts +3 -3
- package/src/plugins/builtin/alerts/metric-command.ts +134 -0
- package/src/plugins/builtin/alerts/metric-data.ts +111 -0
- package/src/plugins/builtin/alerts/metric-model.ts +324 -0
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
- package/src/plugins/builtin/alerts/pane.tsx +90 -39
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +37 -10
- package/src/plugins/builtin/alerts/types.ts +7 -0
- package/src/plugins/builtin/analytics/index.tsx +2 -1
- package/src/plugins/builtin/analytics/risk-client.ts +16 -5
- package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
- package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
- package/src/plugins/builtin/analytics/risk-model.ts +55 -9
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
- package/src/plugins/builtin/attention/index.tsx +2 -1
- package/src/plugins/builtin/attention/listing.ts +14 -0
- package/src/plugins/builtin/backtest/headless.ts +10 -5
- package/src/plugins/builtin/backtest/pane.tsx +9 -4
- package/src/plugins/builtin/backtest/presets.ts +29 -3
- package/src/plugins/builtin/broker-manager/index.tsx +10 -5
- package/src/plugins/builtin/broker-manager/model.ts +6 -1
- package/src/plugins/builtin/broker-trading/controller.ts +22 -12
- package/src/plugins/builtin/broker-trading/index.tsx +13 -1
- package/src/plugins/builtin/broker-trading/order-feed.ts +9 -4
- package/src/plugins/builtin/broker-trading/pane.tsx +1 -1
- package/src/plugins/builtin/buildout/cells.tsx +12 -4
- package/src/plugins/builtin/buildout/format.ts +38 -0
- package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
- package/src/plugins/builtin/buildout/table-model.ts +23 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +7 -3
- package/src/plugins/builtin/catalysts/model.ts +2 -1
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +6 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +1 -1
- package/src/plugins/builtin/chart-composer/cli-options.ts +9 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +12 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -2
- package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +7 -5
- package/src/plugins/builtin/chart-composer/formula.ts +71 -18
- package/src/plugins/builtin/chart-composer/headless-schema.ts +21 -4
- package/src/plugins/builtin/chart-composer/headless.ts +19 -3
- package/src/plugins/builtin/chart-composer/index.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +53 -9
- package/src/plugins/builtin/chart-composer/presets.ts +50 -15
- package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
- package/src/plugins/builtin/chart-composer/session-history.ts +18 -9
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +40 -26
- package/src/plugins/builtin/chat/content/command-suggestions.ts +93 -0
- package/src/plugins/builtin/chat/content/composer.tsx +13 -6
- package/src/plugins/builtin/chat/content/footer.tsx +6 -3
- package/src/plugins/builtin/chat/content/index.tsx +50 -21
- package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
- package/src/plugins/builtin/chat/index.tsx +23 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
- package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
- package/src/plugins/builtin/chat/pane-links/commands.ts +271 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
- package/src/plugins/builtin/chat/pane-links/open.ts +8 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
- package/src/plugins/builtin/clinical-trials/model.ts +0 -9
- package/src/plugins/builtin/clinical-trials/pane.tsx +15 -22
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +8 -6
- package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
- package/src/plugins/builtin/cloud/plugin.tsx +1 -1
- package/src/plugins/builtin/company-attention/building.tsx +5 -1
- package/src/plugins/builtin/company-attention/client.ts +8 -9
- package/src/plugins/builtin/company-attention/evidence.ts +4 -1
- package/src/plugins/builtin/company-attention/moves.tsx +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +9 -2
- package/src/plugins/builtin/company-attention/signals.tsx +5 -1
- package/src/plugins/builtin/correlation/headless.ts +13 -5
- package/src/plugins/builtin/correlation/history.ts +22 -0
- package/src/plugins/builtin/cot/client.ts +22 -18
- package/src/plugins/builtin/cot/headless.ts +15 -10
- package/src/plugins/builtin/cot/model.ts +14 -1
- package/src/plugins/builtin/cot/pane.tsx +22 -14
- package/src/plugins/builtin/credit-boards/client.ts +6 -10
- package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
- package/src/plugins/builtin/credit-conditions/model.ts +4 -0
- package/src/plugins/builtin/credit-conditions/series.ts +3 -1
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
- package/src/plugins/builtin/credit-documents/export.ts +173 -0
- package/src/plugins/builtin/credit-documents/headless.ts +7 -7
- package/src/plugins/builtin/credit-documents/model.ts +104 -14
- package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
- package/src/plugins/builtin/custom-view/sources.ts +2 -0
- package/src/plugins/builtin/dividend-yield/client.ts +131 -23
- package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
- package/src/plugins/builtin/dividend-yield/model.ts +8 -5
- package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
- package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
- package/src/plugins/builtin/dividend-yield/types.ts +20 -2
- package/src/plugins/builtin/dividend-yield/view.ts +30 -2
- package/src/plugins/builtin/docs/targets.ts +5 -1
- package/src/plugins/builtin/earnings/board-model.ts +16 -15
- package/src/plugins/builtin/earnings/board.tsx +62 -71
- package/src/plugins/builtin/earnings/headless.ts +40 -4
- package/src/plugins/builtin/earnings/scope.ts +31 -43
- package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
- package/src/plugins/builtin/earnings-calls/format.ts +31 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -2
- package/src/plugins/builtin/earnings-calls/model.ts +6 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +5 -4
- package/src/plugins/builtin/econ/calendar-model.ts +14 -9
- package/src/plugins/builtin/econ/figures.ts +72 -0
- package/src/plugins/builtin/econ/index.tsx +33 -3
- package/src/plugins/builtin/econ/types.ts +4 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +85 -35
- package/src/plugins/builtin/econ-statistics/stats.ts +37 -9
- package/src/plugins/builtin/econ-statistics/view.ts +3 -0
- package/src/plugins/builtin/equity-screener/categories.ts +179 -0
- package/src/plugins/builtin/equity-screener/client.ts +4 -2
- package/src/plugins/builtin/equity-screener/headless.ts +144 -13
- package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
- package/src/plugins/builtin/equity-screener/model.ts +99 -10
- package/src/plugins/builtin/equity-screener/pane.tsx +70 -15
- package/src/plugins/builtin/exposure/charts.tsx +2 -2
- package/src/plugins/builtin/exposure/model.ts +13 -1
- package/src/plugins/builtin/exposure/pane.tsx +4 -4
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/index.tsx +1 -0
- package/src/plugins/builtin/futures/model.ts +2 -1
- package/src/plugins/builtin/futures/table.tsx +2 -2
- package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
- package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
- package/src/plugins/builtin/fx-matrix/client.ts +11 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +6 -3
- package/src/plugins/builtin/fx-matrix/index.tsx +16 -4
- package/src/plugins/builtin/fx-matrix/live-legs.ts +54 -3
- package/src/plugins/builtin/gpu/headless.ts +8 -2
- package/src/plugins/builtin/help/function-index.ts +4 -1
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
- package/src/plugins/builtin/help/shortcut-model.ts +1 -1
- package/src/plugins/builtin/holders/fund-holders.ts +51 -0
- package/src/plugins/builtin/holders/headless.ts +18 -1
- package/src/plugins/builtin/iv-history/client.ts +52 -11
- package/src/plugins/builtin/iv-history/format.ts +36 -23
- package/src/plugins/builtin/iv-history/headless.ts +36 -18
- package/src/plugins/builtin/iv-history/index.tsx +2 -2
- package/src/plugins/builtin/iv-history/model.ts +163 -27
- package/src/plugins/builtin/iv-history/pane.tsx +10 -6
- package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
- package/src/plugins/builtin/iv-history/universe.ts +5 -1
- package/src/plugins/builtin/jobs/client.ts +25 -29
- package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
- package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
- package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
- package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
- package/src/plugins/builtin/macro-day/pane.tsx +7 -5
- package/src/plugins/builtin/macro-day/release-table.ts +2 -2
- package/src/plugins/builtin/market-heatmap/data.ts +8 -33
- package/src/plugins/builtin/market-movers/client.ts +25 -7
- package/src/plugins/builtin/market-movers/footer.ts +2 -2
- package/src/plugins/builtin/market-movers/headless.ts +32 -12
- package/src/plugins/builtin/market-movers/index.tsx +26 -14
- package/src/plugins/builtin/market-movers/min-float.ts +74 -0
- package/src/plugins/builtin/market-movers/model.ts +4 -1
- package/src/plugins/builtin/market-movers/screener.ts +14 -0
- package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
- package/src/plugins/builtin/market-movers/session-table.ts +4 -3
- package/src/plugins/builtin/market-movers/table.ts +17 -5
- package/src/plugins/builtin/members/breadth-pane.tsx +82 -0
- package/src/plugins/builtin/members/client.ts +19 -4
- package/src/plugins/builtin/members/headless.ts +20 -7
- package/src/plugins/builtin/members/index.tsx +9 -9
- package/src/plugins/builtin/members/model.ts +23 -4
- package/src/plugins/builtin/members/pane.tsx +25 -15
- package/src/plugins/builtin/news/index.tsx +1 -0
- package/src/plugins/builtin/news/wire/categories.ts +19 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
- package/src/plugins/builtin/openfda/client.ts +14 -2
- package/src/plugins/builtin/openfda/index.tsx +3 -2
- package/src/plugins/builtin/openfda/model.ts +9 -0
- package/src/plugins/builtin/openfda/pane.tsx +42 -6
- package/src/plugins/builtin/options/analytics.ts +54 -6
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/model-spot.ts +5 -2
- package/src/plugins/builtin/options/strike-window.ts +2 -1
- package/src/plugins/builtin/options/table.ts +6 -9
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +42 -12
- package/src/plugins/builtin/options-positioning/client.ts +30 -0
- package/src/plugins/builtin/options-positioning/headless.ts +74 -21
- package/src/plugins/builtin/options-positioning/index.tsx +4 -4
- package/src/plugins/builtin/options-positioning/model.ts +122 -14
- package/src/plugins/builtin/options-positioning/pane.tsx +87 -42
- package/src/plugins/builtin/options-scenario/client.ts +116 -47
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
- package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
- package/src/plugins/builtin/options-scenario/csp.ts +8 -2
- package/src/plugins/builtin/options-scenario/index.tsx +9 -7
- package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
- package/src/plugins/builtin/pe-band/model.ts +12 -49
- package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
- package/src/plugins/builtin/perps/cascade.ts +236 -0
- package/src/plugins/builtin/perps/client.ts +56 -2
- package/src/plugins/builtin/perps/freshness.ts +12 -10
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/live-rows.ts +10 -3
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +32 -31
- package/src/plugins/builtin/perps/status-line.ts +25 -0
- package/src/plugins/builtin/plugin-module.ts +5 -1
- package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
- package/src/plugins/builtin/portfolio-list/cli/render.ts +12 -7
- package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
- package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +4 -1
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +3 -1
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
- package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/rate-path/pane.tsx +2 -2
- package/src/plugins/builtin/realized-vol/index.tsx +2 -2
- package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
- package/src/plugins/builtin/relative-rotation/client.ts +18 -4
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
- package/src/plugins/builtin/relative-rotation/model.ts +16 -40
- package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
- package/src/plugins/builtin/research/event-model.ts +10 -8
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/relative-valuation-headless.ts +5 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +11 -9
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
- package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
- package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
- package/src/plugins/builtin/scanner/feed.ts +2 -2
- package/src/plugins/builtin/scanner/flow-model.ts +50 -4
- package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
- package/src/plugins/builtin/scanner/flow-session.ts +146 -0
- package/src/plugins/builtin/scanner/headless.ts +204 -35
- package/src/plugins/builtin/scanner/index.ts +40 -6
- package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
- package/src/plugins/builtin/scanner/live-feed.ts +168 -0
- package/src/plugins/builtin/scanner/live-headless.ts +138 -0
- package/src/plugins/builtin/scanner/live-model.ts +362 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
- package/src/plugins/builtin/scanner/live-track.ts +186 -0
- package/src/plugins/builtin/scanner/lock-note.ts +3 -2
- package/src/plugins/builtin/seasonality/headless.ts +10 -1
- package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
- package/src/plugins/builtin/sec/fund-facts.ts +116 -34
- package/src/plugins/builtin/sec/headless.ts +2 -1
- package/src/plugins/builtin/series-inventory.ts +3 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +3 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
- package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
- package/src/plugins/builtin/shared/earnings-report.ts +2 -2
- package/src/plugins/builtin/shared/job-posting.ts +1 -0
- package/src/plugins/builtin/shared/macro-releases.ts +65 -0
- package/src/plugins/builtin/shared/members-menu.tsx +3 -2
- package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
- package/src/plugins/builtin/shared/report-freshness.ts +3 -2
- package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
- package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
- package/src/plugins/builtin/shared/ticker-company.ts +77 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +10 -3
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +26 -1
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/headless.ts +6 -4
- package/src/plugins/builtin/themes/model.ts +17 -8
- package/src/plugins/builtin/themes/pane.tsx +7 -7
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
- package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
- package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +6 -1
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -19
- package/src/plugins/builtin/treasury-daily/client.ts +41 -5
- package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
- package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
- package/src/plugins/builtin/treasury-daily/model.ts +50 -3
- package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
- package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
- package/src/plugins/builtin/vol-surface/client.ts +9 -17
- package/src/plugins/builtin/vol-surface/headless.ts +63 -14
- package/src/plugins/builtin/vol-surface/index.tsx +2 -2
- package/src/plugins/builtin/vol-surface/model.ts +22 -7
- package/src/plugins/builtin/vol-surface/pane.tsx +48 -9
- package/src/plugins/builtin/vol-surface/tables.ts +31 -3
- package/src/plugins/builtin/volatility/dvol.ts +46 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +4 -4
- package/src/plugins/builtin/volatility/series.ts +26 -0
- package/src/plugins/builtin/world-indices/footer.ts +1 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/catalog-browser.ts +13 -8
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/column-values.ts +5 -5
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
- package/src/remote/resources.ts +2 -1
- package/src/renderers/browser/app-services.ts +1 -7
- package/src/renderers/browser/config-host.ts +2 -55
- package/src/renderers/browser/main.tsx +7 -57
- package/src/renderers/dom/data-table/row.tsx +26 -0
- package/src/renderers/dom/desktop/list-view.tsx +13 -10
- package/src/renderers/dom/desktop/query-bar.tsx +4 -2
- package/src/renderers/dom/desktop/select-field.tsx +4 -2
- package/src/renderers/dom/host/chart-surface.tsx +21 -0
- package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +29 -7
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +173 -5
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
- package/src/renderers/electrobun/bun/index.ts +25 -1
- package/src/renderers/electrobun/shared/app-name.ts +30 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
- package/src/renderers/electrobun/view/main.tsx +24 -1
- package/src/renderers/electrobun/view/news-source.ts +3 -1
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
- package/src/renderers/electrobun/view/view-ids.ts +85 -0
- package/src/renderers/opentui/start.tsx +5 -0
- package/src/renderers/opentui/toast-host.tsx +71 -43
- package/src/series/registry.ts +1 -0
- package/src/series/types.ts +6 -0
- package/src/series/validate.ts +1 -0
- package/src/sources/gloomberb-cloud/index.ts +1 -0
- package/src/sources/gloomberb-cloud/news.ts +47 -7
- package/src/sources/gloomberb-cloud/normalizers.ts +2 -0
- package/src/sources/provider-router/batches.ts +10 -2
- package/src/sources/provider-router/financial-routes.ts +3 -3
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/history.ts +28 -7
- package/src/sources/provider-router/index.ts +149 -10
- package/src/sources/provider-router/search.ts +13 -2
- package/src/state/app/context/index.tsx +3 -0
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/auth-transition.ts +19 -9
- package/src/sync/baseline.ts +10 -4
- package/src/sync/controller.ts +70 -19
- package/src/sync/core-contributors.ts +90 -31
- package/src/sync/react.ts +4 -1
- package/src/sync/types.ts +3 -0
- package/src/telemetry/stall-reports-dom.ts +38 -0
- package/src/telemetry/stall-reports-node.ts +75 -0
- package/src/telemetry/stall-reports.ts +214 -0
- package/src/telemetry/usage-counts.ts +0 -18
- package/src/test-support/preload.ts +14 -0
- package/src/theme/colors.ts +8 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name.ts +103 -3
- package/src/tickers/listing-venues.ts +38 -3
- package/src/tickers/search/bare-symbol.ts +36 -0
- package/src/tickers/search/index.ts +36 -7
- package/src/tickers/search/ranking.ts +10 -1
- package/src/tickers/search/types.ts +5 -0
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/base-series.ts +13 -5
- package/src/time-series/daily-valuation.ts +62 -0
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +2 -4
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/forward-valuation.ts +32 -0
- package/src/time-series/fundamentals.ts +198 -7
- package/src/time-series/hooks.ts +1 -0
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/price-units.ts +72 -2
- package/src/time-series/resolve-context.ts +7 -1
- package/src/time-series/resolve.ts +116 -15
- package/src/time-series/series-presentation.ts +40 -6
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +5 -3
- package/src/time-series/studies.ts +278 -74
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +3 -3
- package/src/time-series/types.ts +27 -1
- package/src/time-series/valuation-releases.ts +39 -0
- package/src/types/data-provider.ts +9 -1
- package/src/types/desktop-window.ts +2 -0
- package/src/types/financials.ts +73 -2
- package/src/types/headless.ts +61 -5
- package/src/types/instrument.ts +3 -0
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +10 -1
- package/src/ui/host.tsx +3 -0
- package/src/updater/command-names.ts +12 -7
- package/src/updater/failure.ts +4 -1
- package/src/utils/cli-output.ts +42 -1
- package/src/utils/crypto-pair.ts +44 -0
- package/src/utils/financial-statements.ts +6 -1
- package/src/utils/forward-dividend.ts +2 -0
- package/src/utils/fundamentals.ts +24 -3
- package/src/utils/fx-market-hours.ts +26 -3
- package/src/utils/main-thread-stall.ts +35 -2
- package/src/utils/market-capitalization.ts +24 -1
- package/src/utils/network-failure.ts +9 -6
- package/src/utils/option-expiry.ts +48 -1
- package/src/utils/options.ts +10 -0
- package/src/utils/plugin-proxy-hosts.json +1 -0
- package/src/utils/price-history.ts +12 -1
- package/src/utils/shell-word.ts +8 -0
- package/src/utils/trailing-dividend.ts +53 -4
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
- package/src/renderers/browser/first-screen.ts +0 -193
|
@@ -79,6 +79,14 @@ function builtInPanePrefixes(paneId: string): string[] {
|
|
|
79
79
|
return command ? getCommandPrefixes(command) : [];
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* What a user types for a function, as the catalog lists it and every error names it: a template's
|
|
84
|
+
* shortcut or id, a pane opened by a built-in command (LAY) by that command's mnemonic, else the pane's id.
|
|
85
|
+
*/
|
|
86
|
+
export function paneFunctionCode(template: PaneTemplateDef | undefined, pane: PaneDef): string {
|
|
87
|
+
return template?.shortcut?.prefix ?? template?.id ?? builtInPanePrefixes(pane.id)[0] ?? pane.id;
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
function registerResolverToken(
|
|
83
91
|
lookup: Map<string, PaneTemplateDef | PaneDef>,
|
|
84
92
|
token: string | undefined,
|
|
@@ -195,7 +203,8 @@ export function nearFunctionCodes(
|
|
|
195
203
|
const near = new Map<PaneTemplateDef, string>();
|
|
196
204
|
for (const template of registry.paneTemplates.values()) {
|
|
197
205
|
const prefix = template.shortcut?.prefix;
|
|
198
|
-
|
|
206
|
+
// An unlisted function is never offered for a typo.
|
|
207
|
+
if (!prefix || template.listed === false) continue;
|
|
199
208
|
const code = [prefix, ...template.shortcut?.aliases ?? []].find((candidate) => {
|
|
200
209
|
const known = normalizeLookupToken(candidate);
|
|
201
210
|
return (!commandWord || known[0] === wanted[0]) && typoDistance(wanted, known) === 1;
|
|
@@ -215,6 +224,7 @@ export function suggestedFunctionCodes(registry: PaneFunctionCatalog, name: stri
|
|
|
215
224
|
const wanted = normalizeLookupToken(name);
|
|
216
225
|
if (!wanted) return [];
|
|
217
226
|
return [...registry.paneTemplates.values()].flatMap((template) => {
|
|
227
|
+
if (template.listed === false) return [];
|
|
218
228
|
const pane = registry.panes.get(template.paneId);
|
|
219
229
|
const words = pane ? getHeadlessPaneDefinition(template, pane)?.discovery?.suggestFor ?? [] : [];
|
|
220
230
|
const code = template.shortcut?.prefix;
|
|
@@ -277,9 +287,15 @@ async function buildTemplateCatalogEntry(
|
|
|
277
287
|
};
|
|
278
288
|
}
|
|
279
289
|
|
|
290
|
+
/**
|
|
291
|
+
* The functions `gloom catalog` and search list. An unlisted one (`listed:
|
|
292
|
+
* false`) is left out, and its pane is not listed in its place; `unlisted`
|
|
293
|
+
* keeps it, for its own help (`fn ATTN --help`).
|
|
294
|
+
*/
|
|
280
295
|
export async function buildPaneCatalogEntries(
|
|
281
296
|
registry: PaneFunctionCatalog,
|
|
282
297
|
context: MarketContext,
|
|
298
|
+
{ unlisted = false }: { unlisted?: boolean } = {},
|
|
283
299
|
): Promise<PaneCatalogEntry[]> {
|
|
284
300
|
const entries: PaneCatalogEntry[] = [];
|
|
285
301
|
const templatedPaneIds = new Set<string>();
|
|
@@ -288,6 +304,7 @@ export async function buildPaneCatalogEntries(
|
|
|
288
304
|
const pane = registry.panes.get(template.paneId);
|
|
289
305
|
if (!pane) continue;
|
|
290
306
|
templatedPaneIds.add(pane.id);
|
|
307
|
+
if (template.listed === false && !unlisted) continue;
|
|
291
308
|
entries.push(await buildTemplateCatalogEntry(template, pane, context));
|
|
292
309
|
}
|
|
293
310
|
|
|
@@ -296,7 +313,7 @@ export async function buildPaneCatalogEntries(
|
|
|
296
313
|
const [shortcut, ...aliases] = builtInPanePrefixes(pane.id);
|
|
297
314
|
const argument = paneFunctionArgument(undefined, pane);
|
|
298
315
|
entries.push({
|
|
299
|
-
token:
|
|
316
|
+
token: paneFunctionCode(undefined, pane),
|
|
300
317
|
label: pane.name,
|
|
301
318
|
description: `Open the ${pane.name} pane.`,
|
|
302
319
|
paneId: pane.id,
|
|
@@ -333,6 +350,14 @@ const ALL_WORDS_WITH_FLAGS_BAND = 1000;
|
|
|
333
350
|
const PER_MATCHED_WORD = 100;
|
|
334
351
|
/** Loose matches (no function carries every word) listed before the rest are left to a refined query. */
|
|
335
352
|
const LOOSE_MATCH_LIMIT = 5;
|
|
353
|
+
/** Loose matches a word of the query names (in the function's code, name or aliases) are all listed, up to this many. */
|
|
354
|
+
const LOOSE_NAMED_LIMIT = 8;
|
|
355
|
+
/** A query word found in what the function is called (its code, name or aliases) outweighs one found in its keywords or description. */
|
|
356
|
+
const PER_WORD_IN_NAME = 3;
|
|
357
|
+
/** A query word that begins a function's code (`vol` for VOLS, `fx` for FXC) is the start of typing it. */
|
|
358
|
+
const PER_WORD_STARTING_CODE = 3;
|
|
359
|
+
/** A query word that is one of the function's own keywords (`vol` for the volatility functions, which also say volume's) names it. */
|
|
360
|
+
const PER_WORD_IS_KEYWORD = 3;
|
|
336
361
|
|
|
337
362
|
function phraseBand(entry: PaneCatalogEntry, phrase: string): number {
|
|
338
363
|
const lower = (values: Array<string | undefined>) => values
|
|
@@ -375,6 +400,12 @@ function nameAndDescription(entry: PaneCatalogEntry): string {
|
|
|
375
400
|
return nameAndDescriptionFields(entry).join(" ");
|
|
376
401
|
}
|
|
377
402
|
|
|
403
|
+
/** What a function is called: its code, name and aliases, apart from the keywords and description that say what it covers. */
|
|
404
|
+
function identityFields(entry: PaneCatalogEntry): string[] {
|
|
405
|
+
return [entry.token, entry.label, entry.paneName, entry.shortcut, ...entry.aliases]
|
|
406
|
+
.filter((value): value is string => !!value).map((value) => value.toLowerCase().replace(/\s+/g, " "));
|
|
407
|
+
}
|
|
408
|
+
|
|
378
409
|
function flagText(entry: PaneCatalogEntry): string {
|
|
379
410
|
return [
|
|
380
411
|
entry.argKind,
|
|
@@ -394,12 +425,14 @@ interface CatalogMatchScore {
|
|
|
394
425
|
terms: number;
|
|
395
426
|
/** Those found in the function's name, keywords or description. */
|
|
396
427
|
named: number;
|
|
428
|
+
/** Those found in what the function is called: its code, name or aliases. */
|
|
429
|
+
called: number;
|
|
397
430
|
}
|
|
398
431
|
|
|
399
432
|
function scorePaneCatalogEntry(entry: PaneCatalogEntry, query: string): CatalogMatchScore {
|
|
400
433
|
const terms = queryTerms(query);
|
|
401
|
-
if (terms.length === 0) return { score: 1, terms: 0, named: 0 };
|
|
402
|
-
const none = { score: 0, terms: terms.length, named: 0 };
|
|
434
|
+
if (terms.length === 0) return { score: 1, terms: 0, named: 0, called: 0 };
|
|
435
|
+
const none = { score: 0, terms: terms.length, named: 0, called: 0 };
|
|
403
436
|
|
|
404
437
|
const exactTokens = [
|
|
405
438
|
entry.token,
|
|
@@ -414,6 +447,8 @@ function scorePaneCatalogEntry(entry: PaneCatalogEntry, query: string): CatalogM
|
|
|
414
447
|
const named = nameAndDescription(entry);
|
|
415
448
|
const flags = flagText(entry);
|
|
416
449
|
const wholeQuery = query.toLowerCase().trim().replace(/\s+/g, " ");
|
|
450
|
+
const called = identityFields(entry);
|
|
451
|
+
const codes = [entry.token, entry.shortcut, ...entry.aliases].filter((value): value is string => !!value).map((value) => normalizeLookupToken(value));
|
|
417
452
|
|
|
418
453
|
let score = containsPhrase(`${named} ${flags}`, wholeQuery) ? 12 : 0;
|
|
419
454
|
// A query that is one of the function's own keywords ("hedge" for OSA) beats one found inside a
|
|
@@ -423,9 +458,16 @@ function scorePaneCatalogEntry(entry: PaneCatalogEntry, query: string): CatalogM
|
|
|
423
458
|
if (keywords.includes(wholeQuery)) score += 4;
|
|
424
459
|
let matchedTerms = 0;
|
|
425
460
|
let matchedNamed = 0;
|
|
461
|
+
let matchedCalled = 0;
|
|
426
462
|
let matchedFlagKeys = 0;
|
|
427
463
|
for (const term of terms) {
|
|
428
464
|
const normalized = normalizeLookupToken(term);
|
|
465
|
+
if (called.some((field) => containsPhrase(field, term))) {
|
|
466
|
+
score += PER_WORD_IN_NAME;
|
|
467
|
+
matchedCalled += 1;
|
|
468
|
+
}
|
|
469
|
+
if (codes.some((code) => normalized.length >= 2 && code.startsWith(normalized))) score += PER_WORD_STARTING_CODE;
|
|
470
|
+
if (keywords.includes(term)) score += PER_WORD_IS_KEYWORD;
|
|
429
471
|
// A term starts a word: "rate" is found in "rates" but not in "separate", nor "budget" in "budgetBps".
|
|
430
472
|
if (exactTokens.includes(normalized)) {
|
|
431
473
|
score += 8;
|
|
@@ -455,12 +497,13 @@ function scorePaneCatalogEntry(entry: PaneCatalogEntry, query: string): CatalogM
|
|
|
455
497
|
score += Math.round((matchedTerms / terms.length) * 8);
|
|
456
498
|
if (entry.capability.botSafe) score += 2;
|
|
457
499
|
// One word has no phrase to prefer: it keeps the plain term scores.
|
|
458
|
-
if (terms.length === 1) return { score, terms: 1, named: matchedNamed };
|
|
500
|
+
if (terms.length === 1) return { score, terms: 1, named: matchedNamed, called: matchedCalled };
|
|
459
501
|
const allWords = matchedNamed === terms.length ? ALL_WORDS_BAND : matchedTerms === terms.length ? ALL_WORDS_WITH_FLAGS_BAND : 0;
|
|
460
502
|
return {
|
|
461
503
|
score: score + matchedTerms * PER_MATCHED_WORD + (phraseBand(entry, wholeQuery) || allWords),
|
|
462
504
|
terms: terms.length,
|
|
463
505
|
named: matchedNamed,
|
|
506
|
+
called: matchedCalled,
|
|
464
507
|
};
|
|
465
508
|
}
|
|
466
509
|
|
|
@@ -535,8 +578,14 @@ export function selectPaneCatalogMatches(ranked: PaneCatalogEntry[], query: stri
|
|
|
535
578
|
const shown = every(complete).slice(0, limit);
|
|
536
579
|
return { shown, hidden: ranked.length - shown.length, loose: false };
|
|
537
580
|
}
|
|
581
|
+
// No function carries every word: the ones a word names come first, the code or name of a function being what a
|
|
582
|
+
// reader types ("fx vol" is FXC, whose name has fx, and VOLS, whose name has vol), ahead of one that mentions a word
|
|
583
|
+
// in its keywords ("implied fx" in ADR) or its flags, and however many of the words a weaker match has.
|
|
538
584
|
const named = scored.filter(({ named }) => named > 0);
|
|
539
|
-
const
|
|
585
|
+
const pool = named.length > 0 ? named : scored;
|
|
586
|
+
const leading = pool.filter((item) => item.called > 0).slice(0, LOOSE_NAMED_LIMIT);
|
|
587
|
+
const rest = pool.filter((item) => !leading.includes(item)).slice(0, Math.max(0, LOOSE_MATCH_LIMIT - leading.length));
|
|
588
|
+
const shown = every([...leading, ...rest]).slice(0, limit);
|
|
540
589
|
return { shown, hidden: ranked.length - shown.length, loose: true };
|
|
541
590
|
}
|
|
542
591
|
|
|
@@ -576,7 +625,7 @@ function optionDescription(option: PaneFunctionOptionDef): string {
|
|
|
576
625
|
const choices = optionChoices(option);
|
|
577
626
|
const parts = [option.description.replace(/\.$/, "")];
|
|
578
627
|
// An enum that also reads other values (a bar size of any length) lists its values as examples.
|
|
579
|
-
if (choices.join("|").length > MAX_INLINE_CHOICES) parts.push(`${option.normalize ? "Such as" : "One of"} ${choices.join(", ")}`);
|
|
628
|
+
if (choices.join("|").length > MAX_INLINE_CHOICES) parts.push(`${option.list ? "Each one of" : option.normalize ? "Such as" : "One of"} ${choices.join(", ")}`);
|
|
580
629
|
if (option.defaultValue !== undefined && option.defaultValue !== "") parts.push(`Default ${String(option.defaultValue)}`);
|
|
581
630
|
return `${parts.join(". ")}.`;
|
|
582
631
|
}
|
|
@@ -587,6 +636,26 @@ export function limitationSentence(text: string): string {
|
|
|
587
636
|
return !trimmed || /[.!?]["')\]]*$/.test(trimmed) ? trimmed : `${trimmed}.`;
|
|
588
637
|
}
|
|
589
638
|
|
|
639
|
+
/**
|
|
640
|
+
* Names as lines of at most `width`, each name whole and the names apart by
|
|
641
|
+
* semicolons, since a name may hold a comma (Furnishings, Fixtures & Appliances).
|
|
642
|
+
*/
|
|
643
|
+
function packNames(names: readonly string[], width: number): string[] {
|
|
644
|
+
const lines: string[] = [];
|
|
645
|
+
let line = "";
|
|
646
|
+
names.forEach((name, index) => {
|
|
647
|
+
const word = index < names.length - 1 ? `${name};` : name;
|
|
648
|
+
if (line && line.length + 1 + word.length > width) {
|
|
649
|
+
lines.push(line);
|
|
650
|
+
line = word;
|
|
651
|
+
} else {
|
|
652
|
+
line = line ? `${line} ${word}` : word;
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
if (line) lines.push(line);
|
|
656
|
+
return lines;
|
|
657
|
+
}
|
|
658
|
+
|
|
590
659
|
function renderCatalogEntry(entry: PaneCatalogEntry): string {
|
|
591
660
|
const width = Math.min(cliTerminalWidth() ?? CATALOG_TEXT_WIDTH, CATALOG_TEXT_WIDTH);
|
|
592
661
|
const capability = entry.capability;
|
|
@@ -620,6 +689,10 @@ function renderCatalogEntry(entry: PaneCatalogEntry): string {
|
|
|
620
689
|
));
|
|
621
690
|
}
|
|
622
691
|
|
|
692
|
+
for (const { title, items } of capability.reference ?? []) {
|
|
693
|
+
lines.push("", renderSection(title), ...packNames(items, width - 2).map((line) => ` ${line}`));
|
|
694
|
+
}
|
|
695
|
+
|
|
623
696
|
lines.push("", renderSection("Examples"));
|
|
624
697
|
if (capability.reportReadiness !== "unsupported") {
|
|
625
698
|
lines.push(...wrapCommandLine(`gloom fn ${invocation}`, width));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DesktopPaneShotRenderedRow } from "../desktop-pane-shot";
|
|
2
2
|
import { cliStyles, cliTerminalWidth, renderSection, renderTable, wrapText } from "../../utils/cli-output";
|
|
3
|
-
import { formatUtcTime } from "../../utils/utc-time";
|
|
3
|
+
import { formatUtcTime, parseReportTime } from "../../utils/utc-time";
|
|
4
4
|
import type { MarketContext } from "../types";
|
|
5
5
|
import type { PaneFunctionReport } from "./report";
|
|
6
6
|
import type { ResolvedPaneFunction } from "./resolver";
|
|
@@ -83,12 +83,22 @@ function domCellKeys(row: DesktopPaneShotRenderedRow): string[] {
|
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
const DAY_MS = 86_400_000;
|
|
87
|
+
/** A time of day in what a cell draws: `11:27`, `9am`. */
|
|
88
|
+
const DRAWN_CLOCK = /\d{1,2}:\d{2}|\b\d{1,2}\s?[ap]m\b/i;
|
|
89
|
+
|
|
86
90
|
/**
|
|
87
91
|
* A pane may shorten a time to fit ("Wed 11:27", "Oct 2"); the report prints
|
|
88
|
-
* the instant behind it with its date and zone instead.
|
|
92
|
+
* the instant behind it with its date and zone instead. An instant at exactly
|
|
93
|
+
* 00:00 UTC that the cell draws without a time of day (a filing's date, an
|
|
94
|
+
* all-day event) is a day, not a midnight: it prints as the date, as a
|
|
95
|
+
* date-only value does. The CSV and JSON keep the instant.
|
|
89
96
|
*/
|
|
90
97
|
function cellText(cell: DesktopPaneShotRenderedRow["cells"][number]): string {
|
|
91
|
-
|
|
98
|
+
if (!cell.instant) return cell.text;
|
|
99
|
+
const time = parseReportTime(cell.instant);
|
|
100
|
+
if (time && !time.dateOnly && time.time % DAY_MS === 0 && !DRAWN_CLOCK.test(cell.text)) return formatUtcTime({ ...time, dateOnly: true });
|
|
101
|
+
return formatUtcTime(cell.instant) || cell.text;
|
|
92
102
|
}
|
|
93
103
|
|
|
94
104
|
interface DomTable {
|
|
@@ -11,7 +11,15 @@ import type {
|
|
|
11
11
|
import { localTimeSuffix, parseReportTime, type ReportTime } from "../../utils/utc-time";
|
|
12
12
|
import { isRecord } from "../../utils/guards";
|
|
13
13
|
import { latestRegularSessionClose, readIndexSession } from "../../market-data/market/freshness";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
reportMarketSession,
|
|
16
|
+
reportVenueMarkets,
|
|
17
|
+
reportVenueSessionDates,
|
|
18
|
+
type ReportMarket,
|
|
19
|
+
type SessionObservation,
|
|
20
|
+
type VenueMarket,
|
|
21
|
+
type VenueSessionDate,
|
|
22
|
+
} from "./market-session";
|
|
15
23
|
import { savedCopyShownAt } from "../../data/saved-copies";
|
|
16
24
|
import { releasedText } from "../../utils/release-date";
|
|
17
25
|
|
|
@@ -77,6 +85,13 @@ export interface ReportFreshness {
|
|
|
77
85
|
tradingDayMarket?: string;
|
|
78
86
|
/** Where the venues of a quote report stand now, from their session calendars. */
|
|
79
87
|
market?: ReportMarket;
|
|
88
|
+
/**
|
|
89
|
+
* With a declared `datesEachVenue`, when the rows trade on two or three
|
|
90
|
+
* markets that do not all stand alike: where each stands and when it opens,
|
|
91
|
+
* which the status line gives in place of `market` (`LSE opens 08:00 UTC ·
|
|
92
|
+
* US 13:30 UTC`).
|
|
93
|
+
*/
|
|
94
|
+
markets?: VenueMarket[];
|
|
80
95
|
/**
|
|
81
96
|
* With a declared `datesEachVenue`, when the rows trade on more than one
|
|
82
97
|
* market: each market's session date, which the status line gives in place
|
|
@@ -100,8 +115,8 @@ export interface ReportFreshness {
|
|
|
100
115
|
*/
|
|
101
116
|
sources?: ReportSourceAsOf[];
|
|
102
117
|
/**
|
|
103
|
-
* Whole minutes from the oldest of `sources` (or, declared `oldestAge
|
|
104
|
-
* oldest observation) to when this report was built: `oldest 9 min`.
|
|
118
|
+
* Whole minutes from the oldest of `sources` (or, declared `oldestAge` or
|
|
119
|
+
* `ageOnly`, the oldest observation) to when this report was built: `oldest 9 min`.
|
|
105
120
|
*/
|
|
106
121
|
oldestAgeMinutes?: number;
|
|
107
122
|
/** The data states no feed (`status` is `unreported`) and its line says only its time and age (`ageOnly`). */
|
|
@@ -125,16 +140,21 @@ export interface ReportFreshness {
|
|
|
125
140
|
/**
|
|
126
141
|
* Refreshing the data failed and a copy saved earlier answered: when that
|
|
127
142
|
* copy was saved, an ISO instant in UTC. The status line then says
|
|
128
|
-
* `couldn't refresh; saved 21:49 UTC` in place of how current the data is.
|
|
143
|
+
* `couldn't refresh; saved copy from 21:49 UTC` in place of how current the data is.
|
|
129
144
|
*/
|
|
130
145
|
savedAt?: string;
|
|
146
|
+
/**
|
|
147
|
+
* Nothing was served: the data service could not be reached and no saved
|
|
148
|
+
* copy answered. The line then names no time, since nothing was retrieved.
|
|
149
|
+
*/
|
|
150
|
+
unreached?: true;
|
|
131
151
|
}
|
|
132
152
|
|
|
133
153
|
/**
|
|
134
154
|
* The freshness a command prints, saying when what it shows (`shown`: its
|
|
135
155
|
* rows, or the data its line is drawn from) came from a copy saved earlier
|
|
136
156
|
* because refreshing it failed (`collectSavedCopies`): its status line then
|
|
137
|
-
* reads `couldn't refresh; saved 21:49 UTC` instead of live or delayed.
|
|
157
|
+
* reads `couldn't refresh; saved copy from 21:49 UTC` instead of live or delayed.
|
|
138
158
|
*/
|
|
139
159
|
export function withSavedCopy<F extends ReportFreshness | undefined>(freshness: F, shown: unknown): F {
|
|
140
160
|
if (!freshness || freshness.savedAt) return freshness;
|
|
@@ -463,9 +483,11 @@ function resolveFreshness({ declared, signals, observations, now }: FreshnessInp
|
|
|
463
483
|
// A bar still forming covers its period through a later day than the one it is dated by.
|
|
464
484
|
const periodToDate = readPeriodToDate(declared.periodToDate, now);
|
|
465
485
|
const asOf = declaredAsOf ?? periodToDate?.through ?? newest([...observations.units, ...observations.extra]);
|
|
466
|
-
// The oldest source, not the newest, says how far behind the view can be.
|
|
467
|
-
|
|
468
|
-
|
|
486
|
+
// The oldest source, not the newest, says how far behind the view can be. A line that is dated by its age says how
|
|
487
|
+
// old its oldest observation is, even beside each source's newest: a source can stream some rows and not others.
|
|
488
|
+
const oldestSource = oldest(sources.map(({ time }) => time));
|
|
489
|
+
const agedFrom = declared.ageOnly ? oldest(observations.units) ?? oldestSource ?? asOf
|
|
490
|
+
: oldestSource ?? (declared.oldestAge ? oldest(observations.units) ?? asOf : null);
|
|
469
491
|
const oldestAgeMinutes = agedFrom && !agedFrom.dateOnly ? Math.max(0, Math.floor((now - agedFrom.time) / 60_000)) : null;
|
|
470
492
|
// A loader that dates its data itself also says how old the oldest part is, or nothing;
|
|
471
493
|
// `oldest: null` says the rows are a history, whose first entry is not stale data.
|
|
@@ -527,6 +549,9 @@ function resolveFreshness({ declared, signals, observations, now }: FreshnessInp
|
|
|
527
549
|
}
|
|
528
550
|
const { market, closeDate, closeMarket } = reportMarketSession(signals.sessions, now);
|
|
529
551
|
const venueSessions = declared.datesEachVenue && !declaredAsOf ? reportVenueSessionDates(signals.sessions, now) : [];
|
|
552
|
+
// Each market's own state and open, when they are not all one: `LSE opens 08:00 UTC · US 13:30 UTC`.
|
|
553
|
+
const venueMarkets = declared.datesEachVenue ? reportVenueMarkets(signals.sessions, now) : [];
|
|
554
|
+
const markets = venueMarkets.length > 0 && !sameMarketText(venueMarkets, now) ? venueMarkets : [];
|
|
530
555
|
// The close wording dates the newest observation, so only when that is what `asOf` is.
|
|
531
556
|
const asOfClose = closeDate && asOf && !declaredAsOf ? closeDate : null;
|
|
532
557
|
const tradingDayMarket = asOfClose ? closeMarket
|
|
@@ -577,6 +602,7 @@ function resolveFreshness({ declared, signals, observations, now }: FreshnessInp
|
|
|
577
602
|
...(asOfClose ? { asOfClose } : {}),
|
|
578
603
|
...(tradingDayMarket ? { tradingDayMarket } : {}),
|
|
579
604
|
...(market ? { market } : {}),
|
|
605
|
+
...(markets.length > 0 ? { markets } : {}),
|
|
580
606
|
...(venueSessions.length > 0 ? { venueSessions } : {}),
|
|
581
607
|
...(lagDays != null ? { lagDays } : {}),
|
|
582
608
|
...(observation ? { observation } : {}),
|
|
@@ -819,7 +845,7 @@ function onRetrievalDay(iso: string, retrievedAt: string): boolean {
|
|
|
819
845
|
|
|
820
846
|
/**
|
|
821
847
|
* What a report answered from a saved copy says in place of how current its
|
|
822
|
-
* data is: `couldn't refresh; saved 21:49 UTC`, with the day when the copy was
|
|
848
|
+
* data is: `couldn't refresh; saved copy from 21:49 UTC`, with the day when the copy was
|
|
823
849
|
* saved on another day than the report was built.
|
|
824
850
|
*/
|
|
825
851
|
function savedCopyText(savedAt: string, retrievedAt: string, local: boolean): string {
|
|
@@ -827,7 +853,7 @@ function savedCopyText(savedAt: string, retrievedAt: string, local: boolean): st
|
|
|
827
853
|
if (!Number.isFinite(at)) return "couldn't refresh";
|
|
828
854
|
const iso = new Date(at).toISOString();
|
|
829
855
|
const time = onRetrievalDay(iso, retrievedAt) ? `${iso.slice(11, 16)} UTC${local ? localTimeSuffix(at) : ""}` : timeText(iso, local);
|
|
830
|
-
return `couldn't refresh; saved ${time}`;
|
|
856
|
+
return `couldn't refresh; saved copy from ${time}`;
|
|
831
857
|
}
|
|
832
858
|
|
|
833
859
|
/** `US and XETRA`, `US, XETRA and EPA`. */
|
|
@@ -850,6 +876,21 @@ function venueSessionsText(sessions: readonly VenueSessionDate[]): string {
|
|
|
850
876
|
return groups.map(({ markets, date, close }) => `${listText(markets)} ${dayText(date)} ${close ? "close" : "session"}`).join(", ");
|
|
851
877
|
}
|
|
852
878
|
|
|
879
|
+
/**
|
|
880
|
+
* An as-of the feed stamped at exactly 00:00:00.000 UTC reads as the day it
|
|
881
|
+
* names, as a date-only value does: a daily close, a filing's date or a
|
|
882
|
+
* published report's has no time of day, so `Mon 26 Oct 2026 00:00 UTC` would
|
|
883
|
+
* claim one. Quotes keep their time, as does anything a feed or a venue's
|
|
884
|
+
* sessions date, and bars of a size under a day, whose midnight bar opens then.
|
|
885
|
+
*/
|
|
886
|
+
function asOfAsDay(freshness: ReportFreshness, time: ReportTime | null): ReportTime | null {
|
|
887
|
+
if (!time || time.dateOnly || time.time % DAY_MS !== 0) return time;
|
|
888
|
+
const feed = freshness.status === "live" || freshness.status === "delayed" || freshness.feed != null;
|
|
889
|
+
const intradayBars = freshness.basis === "intraday bars";
|
|
890
|
+
return feed || intradayBars || freshness.market || freshness.sources?.length || freshness.oldestAgeMinutes != null
|
|
891
|
+
? time : { ...time, dateOnly: true };
|
|
892
|
+
}
|
|
893
|
+
|
|
853
894
|
/**
|
|
854
895
|
* The dated as-of: a session close, a UTC time, a date, or when the report was
|
|
855
896
|
* retrieved; with the oldest observation unless `short`, or when the line says
|
|
@@ -861,7 +902,7 @@ function asOfText(freshness: ReportFreshness, short: boolean, local: boolean, un
|
|
|
861
902
|
if (freshness.venueSessions?.length) return venueSessionsText(freshness.venueSessions);
|
|
862
903
|
const market = freshness.tradingDayMarket;
|
|
863
904
|
const period = freshness.periodicity;
|
|
864
|
-
const time = parseReportTime(freshness.asOf);
|
|
905
|
+
const time = asOfAsDay(freshness, parseReportTime(freshness.asOf));
|
|
865
906
|
const reference = freshness.referencePeriod;
|
|
866
907
|
// `Sep 2026, released Tue 20 Oct`: the period the figure covers, then when it was released.
|
|
867
908
|
const released = reference ? releasedText(freshness.asOf, reference) : null;
|
|
@@ -913,10 +954,11 @@ function reopenText(market: ReportMarket, now: number, local: boolean): { text:
|
|
|
913
954
|
|
|
914
955
|
/**
|
|
915
956
|
* `markets closed until Mon`; `short` is the compact form a narrow capture
|
|
916
|
-
* falls back to (`reopens Mon`). A time is
|
|
917
|
-
*
|
|
957
|
+
* falls back to (`reopens Mon`). A time is the regular session's open, and
|
|
958
|
+
* says so (`pre-market open · regular session opens 13:30 UTC`), so it is
|
|
918
959
|
* never read as when the pre-market opens, nor a US market as closed until
|
|
919
|
-
* then while its pre-market trades first.
|
|
960
|
+
* then while its pre-market trades first. A futures venue's Sunday open is no
|
|
961
|
+
* regular session's, so it reads `markets closed · reopens 22:00 UTC`.
|
|
920
962
|
*/
|
|
921
963
|
function marketText(market: ReportMarket, now: number, short: boolean, local: boolean): string {
|
|
922
964
|
const reopen = reopenText(market, now, local);
|
|
@@ -930,6 +972,8 @@ function marketText(market: ReportMarket, now: number, short: boolean, local: bo
|
|
|
930
972
|
return short ? `pre-market · regular opens ${reopen.text}` : `pre-market open · regular session opens ${reopen.text}`;
|
|
931
973
|
case "closed":
|
|
932
974
|
if (!reopen) return short ? "closed" : "markets closed";
|
|
975
|
+
// A futures venue's Sunday open is its first trade of the week, which no regular session is.
|
|
976
|
+
if (reopen.time && market.firstTrade) return short ? `reopens ${reopen.text}` : `markets closed · reopens ${reopen.text}`;
|
|
933
977
|
if (reopen.time) return short ? `regular opens ${reopen.text}` : `markets closed · regular session opens ${reopen.text}`;
|
|
934
978
|
return short ? `reopens ${reopen.text}` : `markets closed until ${reopen.text}`;
|
|
935
979
|
default: {
|
|
@@ -939,6 +983,53 @@ function marketText(market: ReportMarket, now: number, short: boolean, local: bo
|
|
|
939
983
|
}
|
|
940
984
|
}
|
|
941
985
|
|
|
986
|
+
/** Whether every market of a mixed report reads the same (`markets closed until Mon`): one line then says it for all. */
|
|
987
|
+
function sameMarketText(markets: readonly VenueMarket[], now: number): boolean {
|
|
988
|
+
return new Set(markets.map((market) => marketText(market, now, false, false))).size === 1;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Where each market of a report that mixes them stands, one after another:
|
|
993
|
+
* the open ones first, then those in an extended session, then the closed ones
|
|
994
|
+
* by when they open. `markets closed · LSE opens 08:00 UTC · US 13:30 UTC`
|
|
995
|
+
* while all are closed, else each its own (`LSE open · US pre-market, opens
|
|
996
|
+
* 13:30 UTC`). A time is the regular session's open, as `marketText` says it;
|
|
997
|
+
* `short` leaves out `markets closed`.
|
|
998
|
+
*/
|
|
999
|
+
function marketsText(markets: readonly VenueMarket[], now: number, short: boolean, local: boolean): string {
|
|
1000
|
+
const opensAt = (market: VenueMarket) => market.reopensAt ? Date.parse(market.reopensAt) : Number.POSITIVE_INFINITY;
|
|
1001
|
+
const rank = (market: VenueMarket) => market.state === "open" ? 0 : market.state === "closed" ? 2 : 1;
|
|
1002
|
+
const ordered = [...markets].sort((left, right) => rank(left) - rank(right) || opensAt(left) - opensAt(right));
|
|
1003
|
+
// `LSE opens 08:00 UTC · US 13:30 UTC`: a verb is said once for the timed opens that follow each other
|
|
1004
|
+
// with it; a week's first trade after a session's open says its own (`reopens 22:00 UTC`).
|
|
1005
|
+
let previousVerb: string | null = null;
|
|
1006
|
+
const parts = ordered.map((market) => {
|
|
1007
|
+
const reopen = reopenText(market, now, local);
|
|
1008
|
+
const verb = market.state === "closed" && reopen?.time ? market.firstTrade ? "reopens" : "opens" : null;
|
|
1009
|
+
const said = (() => {
|
|
1010
|
+
switch (market.state) {
|
|
1011
|
+
case "open":
|
|
1012
|
+
return `${market.market} open`;
|
|
1013
|
+
case "after-hours":
|
|
1014
|
+
return `${market.market} after hours`;
|
|
1015
|
+
case "pre-market":
|
|
1016
|
+
return reopen?.time ? `${market.market} pre-market, opens ${reopen.text}` : `${market.market} pre-market`;
|
|
1017
|
+
case "closed":
|
|
1018
|
+
if (!reopen) return `${market.market} closed`;
|
|
1019
|
+
if (!reopen.time) return `${market.market} closed until ${reopen.text}`;
|
|
1020
|
+
return `${market.market} ${verb === previousVerb ? "" : `${verb} `}${reopen.text}`;
|
|
1021
|
+
default: {
|
|
1022
|
+
const _exhaustive: never = market.state;
|
|
1023
|
+
return _exhaustive;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
})();
|
|
1027
|
+
previousVerb = verb;
|
|
1028
|
+
return said;
|
|
1029
|
+
});
|
|
1030
|
+
return ordered.every((market) => market.state === "closed") && !short ? ["markets closed", ...parts].join(" · ") : parts.join(" · ");
|
|
1031
|
+
}
|
|
1032
|
+
|
|
942
1033
|
interface StatusLineDetail {
|
|
943
1034
|
/** Leave out the oldest observation. */
|
|
944
1035
|
asOf?: "short";
|
|
@@ -970,13 +1061,16 @@ function statusLineParts(freshness: ReportFreshness, detail: StatusLineDetail =
|
|
|
970
1061
|
const undated = detail.date === "none";
|
|
971
1062
|
return [
|
|
972
1063
|
...(freshness.sources?.length ? sourcesAsOfParts(freshness, freshness.sources, undated)
|
|
1064
|
+
: freshness.unreached && !freshness.asOf ? []
|
|
973
1065
|
: [asOfText(freshness, detail.asOf === "short", local, undated)]),
|
|
974
1066
|
...(freshness.schedule && detail.schedule !== "none"
|
|
975
1067
|
? [typeof detail.schedule === "number" ? freshness.scheduleVariants?.[detail.schedule] ?? freshness.schedule : freshness.schedule] : []),
|
|
976
1068
|
...(freshness.oldestAgeMinutes != null ? [`oldest ${ageText(freshness.oldestAgeMinutes)}`] : []),
|
|
977
1069
|
...(freshness.savedAt ? [savedCopyText(freshness.savedAt, freshness.retrievedAt, local)]
|
|
978
1070
|
: [statusText(detail.basis === "none" ? { ...freshness, basis: undefined } : freshness, detail.status === "short")].filter(Boolean)),
|
|
979
|
-
...(
|
|
1071
|
+
...(detail.market === "none" ? []
|
|
1072
|
+
: freshness.markets?.length ? [marketsText(freshness.markets, now, detail.market === "short", local)]
|
|
1073
|
+
: freshness.market ? [marketText(freshness.market, now, detail.market === "short", local)] : []),
|
|
980
1074
|
...(freshness.note && detail.note !== "none" ? [typeof detail.note === "number" ? freshness.noteVariants?.[detail.note] ?? freshness.note : freshness.note] : []),
|
|
981
1075
|
];
|
|
982
1076
|
}
|
|
@@ -1174,7 +1268,8 @@ export function captureStatusLine({ report: loaded, selfDated, quoted, rendered
|
|
|
1174
1268
|
}
|
|
1175
1269
|
if (report && loaded?.declaresData) return sourced(report);
|
|
1176
1270
|
if (quoted) return plain(quoted, "quotes");
|
|
1177
|
-
|
|
1271
|
+
// A report that names no feed but dates its data by a session's close says so too: a board's figures outside the session.
|
|
1272
|
+
if (report && (report.status !== "unreported" || report.ageOnly || report.asOfClose)) return sourced(report);
|
|
1178
1273
|
return plain(rendered(), null);
|
|
1179
1274
|
}
|
|
1180
1275
|
|
|
@@ -234,9 +234,10 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
|
|
|
234
234
|
bloomberg: ["RV"],
|
|
235
235
|
},
|
|
236
236
|
EQS: {
|
|
237
|
-
summary: "Screen covered stocks on valuation, growth, margins, liquidity, volatility, short interest, insider activity and 13F holders, then rank the matches by any metric. "
|
|
238
|
-
+ "ATR% is the 14-session average true range as a percent of the last close. IV rank is a rank, not an IV percentile: 0 is the lowest 30-day implied volatility of the past 52 weeks and 100 the highest."
|
|
239
|
-
|
|
237
|
+
summary: "Screen covered stocks on valuation, growth, margins, liquidity, volatility, technicals, float and ownership, short interest, insider activity and 13F holders, then rank the matches by any metric. "
|
|
238
|
+
+ "ATR% is the 14-session average true range as a percent of the last close. IV rank is a rank, not an IV percentile: 0 is the lowest 30-day implied volatility of the past 52 weeks and 100 the highest. IV percentile, IV30 change in vol points, HV20 and HV rank screen premium to sell. "
|
|
239
|
+
+ "Technical fields read the last completed session: RSI 14, price vs SMA 20, 50 and 200, trading days since a MACD or golden cross and since a new 20-day or 52-week high or low, and Bollinger width percentile (0 is a six-month squeeze). Ideas holds ready technical screens.",
|
|
240
|
+
usage: ["EQS", "gloom fn EQS --preset golden-cross"],
|
|
240
241
|
keys: [key("a", "dd criterion"), key("m", "etric"), key("t", "check ticker"), key("s", "ave screen"), key("o", "pen research")],
|
|
241
242
|
data: same("Daily snapshot, statements as filed"),
|
|
242
243
|
bloomberg: ["EQS"],
|
|
@@ -285,8 +286,10 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
|
|
|
285
286
|
},
|
|
286
287
|
CSP: {
|
|
287
288
|
summary: "Which names pay most to sell a put? For each, the put nearest a delta (0.30) on the expiry nearest a date or a number of days out (30), "
|
|
288
|
-
+ "ranked by annualised yield on cash at the bid, with % out of the money, delta, IV rank, the spread (marked wide, never left out) and an earnings flag."
|
|
289
|
-
|
|
289
|
+
+ "ranked by annualised yield on cash at the bid, with % out of the money, delta, IV rank, the spread (marked wide, never left out) and an earnings flag. "
|
|
290
|
+
+ "--strategy screens covered calls, verticals, iron condors, straddles, strangles and calendars the same way, with the trade, credit or debit, "
|
|
291
|
+
+ "max gain and loss per contract, break-evens, probability of profit, and an income trade's annualised return or a debit trade's reward to risk.",
|
|
292
|
+
usage: ["CSP JPM, GS, KO", "gloom fn CSP JPM GS KO AAPL --delta 0.20 --days 45", "gloom fn CSP JPM GS KO --strategy iron-condor"],
|
|
290
293
|
keys: [key("Enter", " open in OSA")],
|
|
291
294
|
data: OPTIONS,
|
|
292
295
|
bloomberg: [],
|
|
@@ -713,8 +716,8 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
|
|
|
713
716
|
|
|
714
717
|
// Watch markets
|
|
715
718
|
MOST: {
|
|
716
|
-
summary: "Today's top gainers, losers, most active and trending tickers with price, change, volume against average and market cap, and the pre-market and after-hours movers. On Pro, the gaps at the open.",
|
|
717
|
-
usage: ["MOST"],
|
|
719
|
+
summary: "Today's top gainers, losers, most active and trending tickers with price, change, volume against average and market cap, and the pre-market and after-hours movers. On Pro, the gaps at the open. Min float keeps the names with at least that many shares in the float.",
|
|
720
|
+
usage: ["MOST", "gloom fn MOST --list gainers --min-float 10M"],
|
|
718
721
|
keys: [TABS, OPEN],
|
|
719
722
|
data: { free: DELAYED, pro: REAL_TIME },
|
|
720
723
|
bloomberg: ["MOST"],
|
|
@@ -734,10 +737,10 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
|
|
|
734
737
|
bloomberg: ["IMAP"],
|
|
735
738
|
},
|
|
736
739
|
MEMB: {
|
|
737
|
-
summary: "ETF holdings with weights, shares, member returns, daily contributions and index changes. SPX and
|
|
738
|
-
usage: ["MEMB", "MEMB
|
|
740
|
+
summary: "ETF holdings with weights, shares, member returns, daily contributions, breadth and index changes. SPX and ^SPX use IVV holdings.",
|
|
741
|
+
usage: ["MEMB", "MEMB SPX", "MEMB ^RUT", "gloom fn MEMB SPX --tab breadth"],
|
|
739
742
|
keys: [TABS, OPEN, MEMBERS_MENU],
|
|
740
|
-
data: same("Dated
|
|
743
|
+
data: same("Dated holdings and member returns. Breadth history uses current members (survivorship bias). Nasdaq-100 is not covered."),
|
|
741
744
|
bloomberg: ["MEMB", "MRR", "IMOV"],
|
|
742
745
|
},
|
|
743
746
|
THEM: {
|
|
@@ -894,10 +897,17 @@ export const FUNCTION_HELP: Readonly<Record<string, FunctionHelp>> = {
|
|
|
894
897
|
data: US_SCANNER,
|
|
895
898
|
bloomberg: [],
|
|
896
899
|
},
|
|
900
|
+
SCAN: {
|
|
901
|
+
summary: "Your own intraday scan of US stocks over all listings, an index, a sector or a watchlist: moves over the last minutes, volume spikes against the average pace, new session highs and lows, VWAP crosses and gaps, above price, market cap and volume floors. Matches refresh through the session, and new ones can alert.",
|
|
902
|
+
usage: ["SCAN"],
|
|
903
|
+
keys: [TABS, OPEN, key("a", "dd condition"), key("s", "ave scan")],
|
|
904
|
+
data: US_SCANNER,
|
|
905
|
+
bloomberg: [],
|
|
906
|
+
},
|
|
897
907
|
FLOW: {
|
|
898
|
-
summary: "Sweeps, blocks and large premium prints
|
|
899
|
-
usage: ["FLOW"],
|
|
900
|
-
keys: [OPEN],
|
|
908
|
+
summary: "Sweeps, blocks and large premium prints, and the session's net premium tide.",
|
|
909
|
+
usage: ["FLOW", "FLOW NVDA"],
|
|
910
|
+
keys: [TABS, OPEN],
|
|
901
911
|
data: pro(REAL_TIME),
|
|
902
912
|
access: "pro",
|
|
903
913
|
bloomberg: ["FLOW"],
|