gloomberb 0.16.5 → 0.16.6
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/package.json +2 -1
- package/src/api-client/central-bank-rates.ts +6 -1
- package/src/api-client/chat.ts +26 -0
- package/src/api-client/credit-boards.ts +2 -0
- package/src/api-client/data.ts +49 -1
- package/src/api-client/europe-energy.ts +106 -0
- package/src/api-client/index.ts +9 -0
- package/src/api-client/market-discovery.ts +3 -0
- package/src/api-client/normalizers.ts +32 -0
- package/src/api-client/perps.ts +8 -0
- package/src/api-client/request.ts +9 -2
- package/src/api-client/socket.ts +29 -0
- package/src/api-client/themes.ts +22 -1
- package/src/api-client/types.ts +61 -1
- package/src/app/global-shortcuts.ts +35 -1
- package/src/app/keybindings/actions.ts +12 -1
- package/src/app/pane-runtime/plugin-bindings.ts +2 -2
- package/src/app/pane-runtime/ticker-open-runtime.ts +9 -3
- package/src/app/runtime/desktop-deeplink.ts +10 -5
- package/src/app/runtime/startup.ts +1 -1
- package/src/app.tsx +6 -0
- package/src/architecture/core-builtin-allowlist.json +4 -13
- package/src/ask-gloom/pane-context.ts +114 -0
- package/src/ask-gloom/pane-request.ts +70 -0
- package/src/ask-gloom/pane-text.ts +201 -0
- package/src/capabilities/chart-series.ts +8 -1
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/central-bank-events.ts +23 -0
- package/src/cli/command-options.ts +17 -5
- package/src/cli/commands/crypto-hints.ts +28 -2
- package/src/cli/commands/fred-series.ts +89 -4
- package/src/cli/commands/market.ts +101 -18
- package/src/cli/commands/overview.ts +47 -14
- package/src/cli/commands/search.ts +254 -23
- package/src/cli/commands/ticker.ts +73 -13
- package/src/cli/desktop-pane-shot.ts +23 -6
- package/src/cli/errors.ts +7 -5
- package/src/cli/exit-codes.ts +8 -0
- package/src/cli/export-source.ts +58 -0
- package/src/cli/glossary.ts +62 -8
- package/src/cli/help.ts +10 -0
- package/src/cli/helpers.ts +2 -5
- package/src/cli/history-rows.ts +70 -0
- package/src/cli/index.ts +9 -3
- package/src/cli/known-gaps.ts +65 -8
- package/src/cli/listing-arg.ts +182 -89
- package/src/cli/not-a-ticker.ts +12 -4
- package/src/cli/pane-functions/access-gate.ts +8 -2
- package/src/cli/pane-functions/capabilities.ts +1 -1
- package/src/cli/pane-functions/catalog.ts +183 -39
- package/src/cli/pane-functions/data.ts +30 -0
- package/src/cli/pane-functions/dom.ts +17 -2
- package/src/cli/pane-functions/freshness.ts +48 -24
- package/src/cli/pane-functions/function-help.ts +19 -10
- package/src/cli/pane-functions/headless.ts +55 -15
- package/src/cli/pane-functions/index.ts +45 -16
- package/src/cli/pane-functions/options.ts +8 -0
- package/src/cli/pane-functions/resolver.ts +25 -7
- package/src/cli/pane-functions/screenshot.ts +145 -9
- package/src/cli/perpetual-contract.ts +60 -0
- package/src/cli/registry.ts +3 -1
- package/src/cli/report-tables.ts +23 -7
- package/src/cli/result.ts +41 -10
- package/src/cli/series-search.ts +111 -0
- package/src/cli/staged-tickers.ts +1 -1
- package/src/cli/symbol-args.ts +18 -0
- package/src/cli/symbol-list.ts +1 -19
- package/src/cli/symbol-rows.ts +154 -0
- package/src/cli/ticker-resolution.ts +99 -8
- package/src/components/chart/composite/axis-overlays.tsx +8 -1
- package/src/components/chart/composite/composite-chart.tsx +41 -15
- package/src/components/chart/composite/crosshair-readout.tsx +150 -0
- package/src/components/chart/composite/downsample.ts +1 -1
- package/src/components/chart/composite/format.ts +29 -0
- package/src/components/chart/composite/interactions.ts +9 -2
- package/src/components/chart/composite/legend.tsx +52 -32
- package/src/components/chart/composite/panel-bitmap.ts +70 -35
- package/src/components/chart/composite/panel-labels.ts +18 -17
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +6 -8
- package/src/components/chart/composite/rasterizer.ts +50 -8
- package/src/components/chart/composite/scene.ts +2 -1
- package/src/components/chart/composite/time-scale.ts +26 -9
- package/src/components/chart/composite/types.ts +18 -0
- package/src/components/chart/composite/use-composite-viewport.ts +30 -2
- package/src/components/chart/native/raster/crosshair.ts +8 -3
- package/src/components/chart/native/raster/primitives.ts +85 -21
- package/src/components/chart/native/surface/manager.ts +33 -8
- package/src/components/chart/surface3d/chart.tsx +1 -1
- package/src/components/command-bar/action-runtime.ts +1 -1
- package/src/components/command-bar/commands/collection-list.ts +210 -0
- package/src/components/command-bar/commands/collection.ts +40 -1
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -0
- package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
- package/src/components/command-bar/routing/actions.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +35 -29
- package/src/components/layout/detached-pane-shell.tsx +59 -39
- package/src/components/layout/floating-pane.tsx +7 -1
- package/src/components/layout/header.tsx +5 -0
- package/src/components/layout/missing-pane.tsx +3 -3
- package/src/components/layout/pane/capture-stamp.ts +41 -0
- package/src/components/layout/pane/capture-status.ts +12 -0
- package/src/components/layout/pane/footer/keyboard.ts +3 -0
- package/src/components/layout/pane/footer/model.ts +7 -1
- package/src/components/layout/pane/header.tsx +26 -0
- package/src/components/layout/pane/index.tsx +9 -1
- package/src/components/layout/pane/sidebar.tsx +10 -11
- package/src/components/layout/shell/cursor-occlusion.ts +2 -1
- package/src/components/layout/shell/index.tsx +61 -60
- package/src/components/layout/shell/menu.ts +9 -1
- package/src/components/layout/shell/pane/actions.ts +32 -10
- package/src/components/layout/shell/pane/ask.ts +131 -0
- package/src/components/layout/shell/pane/capture.ts +162 -0
- package/src/components/layout/shell/pane/layers.tsx +26 -5
- package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
- package/src/components/layout/shell/shortcuts.ts +21 -4
- package/src/components/metric-treemap/heat-surface.tsx +1 -3
- package/src/components/reader/article-reader.tsx +642 -0
- package/src/components/reader/article-text.ts +527 -0
- package/src/components/ticker/list-table-view.tsx +19 -1
- package/src/components/ui/data-table/index.tsx +1 -0
- package/src/components/ui/icon.tsx +4 -1
- package/src/components/ui/query-bar.tsx +10 -1
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/portfolio-as-of-column.ts +57 -0
- package/src/docs/snapshot.json +162 -23
- package/src/i18n/es.ts +4 -1
- package/src/i18n/ja.ts +4 -1
- package/src/i18n/ko.ts +4 -1
- package/src/i18n/zh-cn.ts +4 -1
- package/src/i18n/zh-tw.ts +4 -1
- package/src/layout-marketplace/gallery.tsx +1 -1
- package/src/market-data/market/freshness.ts +3 -2
- package/src/market-data/market/session-close-note.ts +3 -2
- package/src/market-data/quotes/contributions.ts +2 -0
- package/src/market-data/quotes/metadata.ts +12 -0
- package/src/market-data/quotes/resolution.ts +3 -0
- package/src/notifications/app-notifier.ts +17 -1
- package/src/notifications/notification-log.ts +180 -0
- package/src/plugins/auto-update-node.ts +2 -2
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/alerts/catalysts.ts +1 -1
- package/src/plugins/builtin/alerts/focus.ts +27 -0
- package/src/plugins/builtin/alerts/index.tsx +6 -2
- package/src/plugins/builtin/alerts/pane.tsx +19 -1
- package/src/plugins/builtin/analytics/index.tsx +4 -1
- package/src/plugins/builtin/analytics/risk-headless.ts +30 -15
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/awards/headless.ts +88 -18
- package/src/plugins/builtin/awards/model.ts +41 -1
- package/src/plugins/builtin/awards/pane.tsx +19 -12
- package/src/plugins/builtin/backtest/headless.ts +2 -2
- package/src/plugins/builtin/broker-manager/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +1 -1
- package/src/plugins/builtin/cds/client.ts +11 -31
- package/src/plugins/builtin/cds/headless.ts +5 -2
- package/src/plugins/builtin/cds/model.ts +21 -1
- package/src/plugins/builtin/cds/pane.tsx +6 -4
- package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
- package/src/plugins/builtin/central-bank-rates/index.tsx +1 -1
- package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
- package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
- package/src/plugins/builtin/central-bank-rates/series.ts +19 -25
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
- package/src/plugins/builtin/chart-composer/headless.ts +65 -5
- package/src/plugins/builtin/chart-composer/index.tsx +6 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
- package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
- package/src/plugins/builtin/chat/content/composer.tsx +5 -1
- package/src/plugins/builtin/chat/content/footer.tsx +12 -0
- package/src/plugins/builtin/chat/content/index.tsx +89 -5
- package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
- package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
- package/src/plugins/builtin/chat/content/scroll.ts +127 -27
- package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
- package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
- package/src/plugins/builtin/chat/content/types.ts +1 -0
- package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
- package/src/plugins/builtin/chat/controller/index.ts +121 -1
- package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
- package/src/plugins/builtin/chat/controller/messages.ts +7 -2
- package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
- package/src/plugins/builtin/chat/controller/send.ts +61 -1
- package/src/plugins/builtin/chat/controller/state.ts +8 -0
- package/src/plugins/builtin/chat/ghost-user.ts +20 -0
- package/src/plugins/builtin/chat/index.tsx +23 -5
- package/src/plugins/builtin/chat/layout.ts +78 -5
- package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
- package/src/plugins/builtin/chat/message/header.tsx +16 -4
- package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
- package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
- package/src/plugins/builtin/chat/message/render-state.ts +18 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
- package/src/plugins/builtin/chat/message/types.ts +12 -0
- package/src/plugins/builtin/chat/reactions.ts +197 -0
- package/src/plugins/builtin/chat/share/flow.tsx +87 -0
- package/src/plugins/builtin/chat/share/targets.ts +27 -0
- package/src/plugins/builtin/chat/status-widget.tsx +6 -3
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
- package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
- package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
- package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
- package/src/plugins/builtin/cloud/plugin.tsx +19 -2
- package/src/plugins/builtin/cloud/team/model.ts +5 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/team/store.ts +8 -3
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +2 -2
- package/src/plugins/builtin/company-kpis/headless.ts +97 -10
- package/src/plugins/builtin/company-kpis/model.ts +24 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +13 -14
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- package/src/plugins/builtin/cpi/headless.ts +3 -3
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
- package/src/plugins/builtin/credit-boards/client.ts +6 -2
- package/src/plugins/builtin/credit-boards/headless.ts +108 -31
- package/src/plugins/builtin/credit-boards/model.ts +11 -1
- package/src/plugins/builtin/credit-conditions/client.ts +12 -9
- package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +16 -9
- package/src/plugins/builtin/credit-conditions/model.ts +19 -11
- package/src/plugins/builtin/credit-conditions/series.ts +8 -18
- package/src/plugins/builtin/credit-documents/headless.ts +2 -2
- package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
- package/src/plugins/builtin/dividend-yield/client.ts +3 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +5 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/types.ts +2 -0
- package/src/plugins/builtin/doe/headless.ts +12 -8
- package/src/plugins/builtin/earnings/index.tsx +9 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
- package/src/plugins/builtin/econ/fred-catalog.ts +9 -0
- package/src/plugins/builtin/equity-screener/headless.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
- package/src/plugins/builtin/exposure/drivers.ts +13 -0
- package/src/plugins/builtin/exposure/headless.ts +205 -13
- package/src/plugins/builtin/exposure/index.tsx +1 -0
- package/src/plugins/builtin/exposure/model.ts +23 -3
- package/src/plugins/builtin/exposure/pane.tsx +11 -11
- package/src/plugins/builtin/fear-greed/index.tsx +14 -10
- package/src/plugins/builtin/futures-curve/headless.ts +1 -1
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/fx-matrix/client.ts +63 -0
- package/src/plugins/builtin/fx-matrix/export.ts +2 -1
- package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +3 -3
- package/src/plugins/builtin/gpu/headless.ts +4 -4
- package/src/plugins/builtin/help/function-index.ts +2 -0
- package/src/plugins/builtin/help/index.tsx +14 -1
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
- package/src/plugins/builtin/iv-history/client.ts +6 -2
- package/src/plugins/builtin/iv-history/format.ts +9 -0
- package/src/plugins/builtin/iv-history/headless.ts +50 -18
- package/src/plugins/builtin/iv-history/model.ts +35 -4
- package/src/plugins/builtin/jobs/headless.ts +6 -8
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
- package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
- package/src/plugins/builtin/members/headless.ts +1 -1
- package/src/plugins/builtin/members/pane.tsx +3 -2
- package/src/plugins/builtin/mna/distress/headless.ts +4 -4
- package/src/plugins/builtin/mna/headless.ts +3 -3
- package/src/plugins/builtin/money-markets/headless.ts +5 -4
- package/src/plugins/builtin/news/index.tsx +0 -2
- package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
- package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +3 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -3
- package/src/plugins/builtin/perps/client.ts +50 -10
- package/src/plugins/builtin/perps/equity-row.tsx +29 -16
- package/src/plugins/builtin/perps/headless.ts +2 -2
- package/src/plugins/builtin/perps/index.tsx +5 -3
- package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
- package/src/plugins/builtin/perps/open-market.ts +15 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +6 -6
- package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
- package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +23 -135
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +59 -15
- package/src/plugins/builtin/portfolio-list/cli/render.ts +248 -51
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +5 -12
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +3 -2
- package/src/plugins/builtin/portfolio-list/column-values.ts +103 -25
- package/src/plugins/builtin/portfolio-list/headless.ts +51 -15
- package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
- package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
- package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +46 -8
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +16 -10
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
- package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +8 -3
- package/src/plugins/builtin/portfolio-list/table.tsx +30 -6
- package/src/plugins/builtin/power/evidence.ts +57 -8
- package/src/plugins/builtin/power/headless.ts +6 -2
- package/src/plugins/builtin/power/index.tsx +24 -2
- package/src/plugins/builtin/power/model.ts +2 -2
- package/src/plugins/builtin/power/pane.tsx +5 -0
- package/src/plugins/builtin/power/prices-client.ts +139 -0
- package/src/plugins/builtin/power/prices-headless.ts +137 -0
- package/src/plugins/builtin/power/prices-model.ts +103 -0
- package/src/plugins/builtin/power/prices.tsx +179 -0
- package/src/plugins/builtin/rate-path/headless.ts +38 -18
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/research/index.tsx +2 -0
- package/src/plugins/builtin/research-search/article.ts +65 -0
- package/src/plugins/builtin/research-search/document-view.tsx +33 -215
- package/src/plugins/builtin/research-search/model.ts +0 -9
- package/src/plugins/builtin/research-search/pane.tsx +41 -30
- package/src/plugins/builtin/research-search/snippet.ts +0 -29
- package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
- package/src/plugins/builtin/sec/headless.ts +25 -3
- package/src/plugins/builtin/sec/index.tsx +2 -1
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
- package/src/plugins/builtin/shared/free-preview.ts +47 -0
- package/src/plugins/builtin/shared/report-freshness.ts +3 -1
- package/src/plugins/builtin/shared/volatility/options.ts +4 -1
- package/src/plugins/builtin/short-interest/watch-headless.ts +2 -2
- package/src/plugins/builtin/short-volume/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +43 -11
- package/src/plugins/builtin/supply-chain/model.ts +13 -0
- package/src/plugins/builtin/supply-chain/pane.tsx +5 -5
- package/src/plugins/builtin/themes/headless.ts +74 -10
- package/src/plugins/builtin/themes/model.ts +71 -4
- package/src/plugins/builtin/themes/pane.tsx +22 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +23 -11
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
- package/src/plugins/builtin/time-sales/headless.ts +1 -1
- package/src/plugins/builtin/time-sales/index.tsx +2 -1
- package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
- package/src/plugins/builtin/vol-surface/headless.ts +50 -17
- package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
- package/src/plugins/builtin/vol-surface/model.ts +39 -6
- package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
- package/src/plugins/builtin/vol-surface/stored.ts +63 -3
- package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
- package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +16 -9
- package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
- package/src/plugins/builtin/world-venue-map/model.ts +56 -19
- package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/installer.ts +2 -2
- package/src/plugins/loader.ts +15 -0
- package/src/plugins/manager-node.ts +1 -1
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
- package/src/plugins/registry/host-actions.ts +11 -0
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/valuation-basis.ts +79 -0
- package/src/public/time-series.ts +1 -1
- package/src/react/input.ts +33 -1
- package/src/react/key-repeat.ts +86 -0
- package/src/remote/controller.ts +21 -1
- package/src/remote/schema.ts +3 -2
- package/src/renderers/browser/main.tsx +1 -1
- package/src/renderers/browser/research-entry.ts +4 -2
- package/src/renderers/dom/data-table/row.tsx +3 -0
- package/src/renderers/dom/desktop/icons.tsx +9 -0
- package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
- package/src/renderers/dom/host/box.tsx +7 -2
- package/src/renderers/dom/host/chart-surface.tsx +27 -0
- package/src/renderers/dom/host/scroll-box.tsx +32 -0
- package/src/renderers/dom/host/size-observer.ts +24 -9
- package/src/renderers/dom/host/sticky-scroll.ts +128 -0
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/surface-3d.tsx +13 -6
- package/src/renderers/dom/host/surface-fit.ts +406 -0
- package/src/renderers/dom/input-host.tsx +1 -0
- package/src/renderers/dom/styles.css +48 -12
- package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
- package/src/renderers/electrobun/bun/index.ts +3 -2
- package/src/renderers/electrobun/shared/protocol.ts +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +12 -0
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +59 -24
- package/src/renderers/electrobun/view/main.tsx +3 -3
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
- package/src/renderers/opentui/chart-surface.tsx +1 -0
- package/src/renderers/opentui/frame-capture.ts +33 -0
- package/src/renderers/opentui/host.tsx +10 -13
- package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
- package/src/renderers/opentui/pane-image/glyphs.json +1 -0
- package/src/renderers/opentui/pane-image/index.ts +107 -0
- package/src/renderers/opentui/pane-image/raster.ts +428 -0
- package/src/renderers/opentui/start.tsx +3 -3
- package/src/renderers/opentui/test-utils.tsx +3 -0
- package/src/renderers/opentui/ui-host.tsx +29 -1
- package/src/series/resolve.ts +3 -2
- package/src/series/types.ts +8 -0
- package/src/series/validate.ts +1 -1
- package/src/shares/chat.ts +34 -0
- package/src/shares/dialog.tsx +295 -0
- package/src/shares/flow.tsx +56 -0
- package/src/shares/live.ts +14 -22
- package/src/shares/pane-image.ts +152 -0
- package/src/shares/personal-pane.ts +64 -0
- package/src/shares/portable-layout.ts +4 -2
- package/src/shares/prepare.ts +20 -0
- package/src/sources/gloomberb-cloud/index.ts +102 -3
- package/src/sources/gloomberb-cloud/normalizers.ts +2 -0
- package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
- package/src/sources/history-retention.ts +11 -0
- package/src/sources/listing-target.ts +4 -0
- package/src/sources/provider-router/index.ts +14 -0
- package/src/state/hooks/inline-tickers.ts +49 -11
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/theme-context.tsx +15 -1
- package/src/tickers/instrument-kind.ts +9 -1
- package/src/tickers/listing-name.ts +34 -0
- package/src/tickers/listing-venues.ts +132 -0
- package/src/tickers/open-target.ts +11 -3
- package/src/tickers/perpetual-listing.ts +151 -0
- package/src/tickers/prediction-listing.ts +26 -0
- package/src/tickers/search/index.ts +27 -4
- package/src/tickers/search/ranking.ts +66 -4
- package/src/tickers/ticker-changes.ts +213 -0
- package/src/time-series/economic.ts +2 -6
- package/src/time-series/ice-credit.ts +39 -0
- package/src/time-series/resolve.ts +116 -13
- package/src/time-series/studies.ts +1 -0
- package/src/time-series/types.ts +8 -0
- package/src/types/config.ts +4 -2
- package/src/types/data-provider.ts +6 -0
- package/src/types/financials.ts +10 -0
- package/src/types/headless.ts +52 -0
- package/src/types/instrument.ts +4 -0
- package/src/types/plugin.ts +33 -2
- package/src/types/ticker-changes.ts +26 -0
- package/src/ui/context-menu.tsx +13 -1
- package/src/ui/host.tsx +43 -7
- package/src/ui/live-resize.ts +10 -0
- package/src/ui/live-stretch.ts +51 -19
- package/src/ui/sticky-scroll.ts +7 -0
- package/src/utils/central-banks.ts +76 -0
- package/src/utils/cli-output.ts +126 -16
- package/src/utils/currency-units.ts +11 -0
- package/src/utils/datetime-format.ts +27 -6
- package/src/utils/dom-screenshot.ts +3 -1
- package/src/utils/double-escape-close.ts +15 -1
- package/src/utils/exchanges.ts +36 -0
- package/src/utils/format.ts +19 -2
- package/src/utils/forward-dividend.ts +14 -0
- package/src/utils/fx-status.ts +6 -1
- package/src/utils/inline-content-tokenizer.ts +22 -3
- package/src/utils/market-capitalization.ts +8 -0
- package/src/utils/one-shot.ts +73 -0
- package/src/utils/options.ts +37 -8
- package/src/utils/utc-time.ts +12 -0
- package/src/ui/pane-fill.ts +0 -11
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
|
@@ -69,6 +69,7 @@ import {
|
|
|
69
69
|
type CliReportTables,
|
|
70
70
|
} from "../report-tables";
|
|
71
71
|
import {
|
|
72
|
+
historyBarStatusNote,
|
|
72
73
|
historyFacts,
|
|
73
74
|
historyFlagNote,
|
|
74
75
|
historyGapNote,
|
|
@@ -78,6 +79,8 @@ import {
|
|
|
78
79
|
historyPriceDecimals,
|
|
79
80
|
historyRows,
|
|
80
81
|
historyUnit,
|
|
82
|
+
historyVolume,
|
|
83
|
+
historyVolumeText,
|
|
81
84
|
} from "../history-rows";
|
|
82
85
|
import { CRYPTO_BOARD_HINT, quoteNotes } from "./crypto-hints";
|
|
83
86
|
import { bareFuturesCode } from "../../market-data/futures-board";
|
|
@@ -97,6 +100,7 @@ import {
|
|
|
97
100
|
} from "../../plugins/builtin/shared/report-freshness";
|
|
98
101
|
import {
|
|
99
102
|
bareListingNote,
|
|
103
|
+
tradingBoardNote,
|
|
100
104
|
EXCHANGE_OPTION,
|
|
101
105
|
futuresTryLine,
|
|
102
106
|
isNoProviderError,
|
|
@@ -110,10 +114,13 @@ import {
|
|
|
110
114
|
type ListingVenue,
|
|
111
115
|
loadForListing,
|
|
112
116
|
loadListingQuote,
|
|
117
|
+
listingFateLoader,
|
|
118
|
+
listingFateNotes,
|
|
113
119
|
noLongerTradingNote,
|
|
114
120
|
notTradedMessage,
|
|
115
121
|
quoteBareListing,
|
|
116
122
|
requireCliListing,
|
|
123
|
+
tradingListing,
|
|
117
124
|
type CliListing,
|
|
118
125
|
type ListingDataRequest,
|
|
119
126
|
type ListingIdentity,
|
|
@@ -124,9 +131,12 @@ import { formatBasisPoints, toBasisPoints } from "../../utils/basis-points";
|
|
|
124
131
|
import { providerMissReason } from "../../sources/provider-errors";
|
|
125
132
|
import { isNotATickerMessage } from "../not-a-ticker";
|
|
126
133
|
import { splitSymbolArgs } from "../symbol-args";
|
|
134
|
+
import { cliPerpetualContract, perpetualContractStats, type PerpetualContractPayload } from "../perpetual-contract";
|
|
135
|
+
import { subMinuteDataMessage } from "../known-gaps";
|
|
127
136
|
import { secRegistrantMismatchMessage, SecRegistrantMismatchError, areDifferentCompanies } from "../../sources/sec-registrant";
|
|
128
137
|
import { isCryptoPairSymbol } from "../../utils/crypto-pair";
|
|
129
138
|
import { isUsListingExchange } from "../../utils/exchanges";
|
|
139
|
+
import { describeTickerChange, startTickerChangeLookup, tickerChangeLine, type TickerChange } from "../../tickers/ticker-changes";
|
|
130
140
|
import { noSecReportsNotice, nonUsSecListingVenue } from "../../utils/sec";
|
|
131
141
|
import type { MarketContext } from "../types";
|
|
132
142
|
import { windowRows } from "../row-window";
|
|
@@ -151,6 +161,7 @@ import {
|
|
|
151
161
|
unvaluedHoldersNote,
|
|
152
162
|
} from "../../plugins/builtin/holders/report-rows";
|
|
153
163
|
import { fetchBeneficialOwners } from "../../plugins/builtin/holders/beneficial-client";
|
|
164
|
+
import { centralBankEventsMessage } from "../central-bank-events";
|
|
154
165
|
import { classSharesToday } from "../../plugins/builtin/holders/client";
|
|
155
166
|
import { filingFormMatches, SEC_FILING_FETCH_LIMIT } from "../../plugins/builtin/sec/forms";
|
|
156
167
|
import { loadParsedInsiderFilings } from "../../plugins/builtin/insider/client";
|
|
@@ -178,6 +189,10 @@ type QuoteCliRecord = Omit<QuoteBatchResult, "error"> & {
|
|
|
178
189
|
listing?: { name: string | null };
|
|
179
190
|
/** A futures row's contract, terms and latest confirmed settlement, as `ticker` reads them. */
|
|
180
191
|
futuresContract?: FuturesContractTermsPayload;
|
|
192
|
+
/** A perpetual row's market, funding per eight hours and open interest. */
|
|
193
|
+
perpetualContract?: PerpetualContractPayload;
|
|
194
|
+
/** The symbol changed: its issuer moved to another symbol, or its holder had another before. */
|
|
195
|
+
tickerChange?: TickerChange;
|
|
181
196
|
};
|
|
182
197
|
type FinancialsCliData = TickerFinancials & {
|
|
183
198
|
symbol: string;
|
|
@@ -524,19 +539,36 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
524
539
|
// Each costs a search, so a long list (a portfolio check, not a lookup) names none.
|
|
525
540
|
const venues = new Map(listings.length > MAX_CHOICE_LOOKUPS ? []
|
|
526
541
|
: listings.map((listing) => [listing, loadBareVenues(listing, market)] as const));
|
|
542
|
+
// So is whether a symbol changed (FB is now META), for the same lists.
|
|
543
|
+
const changes = new Map(listings.length > MAX_CHOICE_LOOKUPS ? []
|
|
544
|
+
: listings.map((listing) => [listing, startTickerChangeLookup(market.dataProvider, listing.symbol, listing.exchange)] as const));
|
|
527
545
|
const results = await market.dataProvider.getQuotesBatch(targets, { forceRefresh: ctx.cliOptions.refresh });
|
|
528
546
|
const listingOf = (result: QuoteBatchResult, index: number) => listings[targets.indexOf(result.target)] ?? listings[index]!;
|
|
547
|
+
const asked = results.map(listingOf);
|
|
529
548
|
const request = { command: commandName, noun: "quote" };
|
|
530
549
|
const answers = await Promise.all(results.map((result, index) => {
|
|
531
|
-
const listing =
|
|
550
|
+
const listing = asked[index]!;
|
|
532
551
|
return answerQuote(result, listing, market, request, ctx.cliOptions.refresh, venues.get(listing) ?? null);
|
|
533
552
|
}));
|
|
553
|
+
const now = Date.now();
|
|
554
|
+
const tickerChanges = await Promise.all(answers.map(async ({ result }, index) => {
|
|
555
|
+
const listing = asked[index]!;
|
|
556
|
+
// A bare symbol read on a listing abroad (SXR8 -> XETRA) is not the US symbol the changes are of.
|
|
557
|
+
if (result.quote && bareListingNote(listing, result.quote)) return null;
|
|
558
|
+
return describeTickerChange(listing.symbol, await changes.get(listing)?.settle() ?? null, tradingListing(result.quote, now));
|
|
559
|
+
}));
|
|
534
560
|
const failed = answers[0]?.failure;
|
|
535
|
-
if (listings.length === 1 && failed)
|
|
561
|
+
if (listings.length === 1 && failed) {
|
|
562
|
+
ctx.fail(failed.message, [tickerChangeLine(tickerChanges[0]), failed.details].filter(Boolean).join("\n") || undefined);
|
|
563
|
+
}
|
|
536
564
|
// A futures quote adds its dated settlement and contract terms, as `ticker` prints them; `compare` stays a table.
|
|
537
565
|
const contracts = await Promise.all(answers.map(({ result }) => commandName === "quote" && result.quote
|
|
538
566
|
? cliFuturesContract(result.quote.symbol || result.target.symbol, result.quote.instrumentType)
|
|
539
567
|
: null));
|
|
568
|
+
// A perpetual adds its funding per eight hours and open interest, the figures PERP lists beside its mark.
|
|
569
|
+
const perpetualContracts = await Promise.all(answers.map(({ result }) => commandName === "quote" && result.quote
|
|
570
|
+
? cliPerpetualContract(result.quote)
|
|
571
|
+
: null));
|
|
540
572
|
// Each row names its listing by key (SAN:EPA) and company, so the table needs no line above it.
|
|
541
573
|
const data = answers.map(({ result, listing, failure }, index) => ({
|
|
542
574
|
target: result.target,
|
|
@@ -545,11 +577,15 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
545
577
|
...getQuoteSessionFields(result.quote),
|
|
546
578
|
quote: result.quote,
|
|
547
579
|
...contracts[index] ? { futuresContract: contracts[index] } : {},
|
|
580
|
+
...perpetualContracts[index] ? { perpetualContract: perpetualContracts[index] } : {},
|
|
548
581
|
error: failure?.oneLine ?? errorMessage(result.error),
|
|
549
582
|
...yieldIndexFields(result),
|
|
583
|
+
...tickerChanges[index] ? { tickerChange: tickerChanges[index] } : {},
|
|
550
584
|
}));
|
|
551
|
-
const now = Date.now();
|
|
552
585
|
const notes = [
|
|
586
|
+
// FB now lists another security; the company that was FB trades as META. A symbol a
|
|
587
|
+
// company renamed into (META) is what was typed: its change is in the row, not here.
|
|
588
|
+
...tickerChanges.flatMap((change) => tickerChangeLine(change) ?? []),
|
|
553
589
|
// Which listing a bare symbol was read as, and the index a bare root is not, are in no row.
|
|
554
590
|
...answers.flatMap((answer) => answer.notes),
|
|
555
591
|
// A row that stopped trading long ago reads as a quote that is merely stale.
|
|
@@ -581,6 +617,10 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
581
617
|
*/
|
|
582
618
|
function quoteFuturesContractText(data: QuoteCliRecord[]): string {
|
|
583
619
|
return data.flatMap((row) => {
|
|
620
|
+
if (row.perpetualContract) {
|
|
621
|
+
const stats = perpetualContractStats(row.perpetualContract);
|
|
622
|
+
return [data.length > 1 ? `${renderSection(`${row.target.symbol} Contract`)}\n${renderStats(stats)}` : `${renderSection("Contract")}\n${renderStats(stats)}`];
|
|
623
|
+
}
|
|
584
624
|
const terms = row.futuresContract;
|
|
585
625
|
if (!terms || !row.quote) return [];
|
|
586
626
|
const settle: [string, string] = ["Settle", futuresSettleText(terms, row.quote)];
|
|
@@ -636,7 +676,9 @@ async function answerQuote(
|
|
|
636
676
|
// "CAR = Avis Budget Group, NASDAQ (also XETRA, ASX)" names the venue too, so it replaces "SXR8 -> XETRA".
|
|
637
677
|
const choice = venues ? await listingChoiceNotes(listing, market, result.quote, venues) : listingReadNotes(listing);
|
|
638
678
|
const venue = choice.length > 0 ? null : bareListingNote(listing, result.quote);
|
|
639
|
-
|
|
679
|
+
// A row saved as 247540:KRX is quoted from KOSDAQ, the board it trades on.
|
|
680
|
+
const board = tradingBoardNote(listing, result.quote);
|
|
681
|
+
return { result, listing, notes: [...choice, venue ?? [], board ?? [], also(result.quote)].flat() };
|
|
640
682
|
}
|
|
641
683
|
const notTraded = await notTradedMessage(listing, market);
|
|
642
684
|
if (notTraded) return { result, listing, failure: { message: notTraded, oneLine: notTraded }, notes: [] };
|
|
@@ -675,6 +717,20 @@ const HISTORY_USAGE = "history <symbol> [--range <range>]";
|
|
|
675
717
|
const HISTORY_ALL_RANGE = `ALL gives the full history the source has, up to ${historyAllRangeYears()} years`;
|
|
676
718
|
/** Options people reach for to ask for dates, which history answers with a range. */
|
|
677
719
|
const DATE_WINDOW_OPTIONS = new Set(["--from", "--to", "--start", "--end", "--since", "--until", "--date", "--start-date", "--end-date"]);
|
|
720
|
+
/** Options people reach for to pick a bar size, which history derives from the range. */
|
|
721
|
+
const BAR_SIZE_OPTIONS = new Set(["--interval", "--resolution", "--bar", "--bars", "--bar-size", "--granularity", "--timeframe", "--frequency", "--freq", "--tick", "--ticks"]);
|
|
722
|
+
|
|
723
|
+
/** The symbol `history` was given: the first word that is not an option or the value after one. */
|
|
724
|
+
function historySymbolArg(args: readonly string[]): string | undefined {
|
|
725
|
+
return args.find((arg, index) => !arg.startsWith("-")
|
|
726
|
+
&& !(index > 0 && args[index - 1]!.startsWith("--") && !args[index - 1]!.includes("=")));
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
function historyOptionHint(flag: string, args: readonly string[]): string | null {
|
|
730
|
+
if (DATE_WINDOW_OPTIONS.has(flag)) return `history takes a --range instead of dates: ${TIME_RANGES.join(", ")}. ${HISTORY_ALL_RANGE}.`;
|
|
731
|
+
if (BAR_SIZE_OPTIONS.has(flag)) return `history serves each --range in one bar size. ${subMinuteDataMessage(historySymbolArg(args))}`;
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
678
734
|
|
|
679
735
|
async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
680
736
|
const args = [...rawArgs];
|
|
@@ -689,18 +745,25 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
689
745
|
const load = () => market.dataProvider.getPriceHistoryWithMetadata
|
|
690
746
|
? market.dataProvider.getPriceHistoryWithMetadata(symbol, exchange, range, context)
|
|
691
747
|
: market.dataProvider.getPriceHistory(symbol, exchange, range, context).then((points) => ({ points, resolution: null }));
|
|
748
|
+
const quoted = loadListingQuote(market.dataProvider, listing);
|
|
749
|
+
const fate = listingFateLoader(listing, market, quoted);
|
|
692
750
|
const [{ points, resolution }, quote] = await Promise.all([
|
|
693
751
|
loadForListing(listing, market, ctx, load, (loaded) => loaded.points.length === 0, {
|
|
694
|
-
command: range === "1Y" ? "history" : `history --range ${range}`, noun: "history",
|
|
752
|
+
command: range === "1Y" ? "history" : `history --range ${range}`, noun: "history", fate,
|
|
695
753
|
})
|
|
696
754
|
.catch((error) => failHistory(error, listing.key, ctx)),
|
|
697
|
-
|
|
755
|
+
quoted,
|
|
698
756
|
]);
|
|
699
757
|
const identity = listingIdentity(listing, quote);
|
|
700
758
|
// Without a quote currency, the listing metadata research reads (as `ticker` does) may still state it.
|
|
701
759
|
const listed = quote?.currency ? quote : await market.dataProvider.getQuoteMetadata?.(symbol, exchange).catch(() => null);
|
|
702
760
|
const unit = historyUnit(listing.key, listed ?? quote);
|
|
703
|
-
const
|
|
761
|
+
const traded = {
|
|
762
|
+
listing: listing.key, exchange: quote?.listingExchangeName || exchange || undefined, instrumentType: quote?.instrumentType,
|
|
763
|
+
};
|
|
764
|
+
// A coin's volume is traded value in its quote currency: said in every row and on the status line.
|
|
765
|
+
const volume = historyVolume(unit, traded);
|
|
766
|
+
const data = historyRows(points, resolution, unit.currency, unit.unit, volume);
|
|
704
767
|
const interval = data[0]?.interval ?? null;
|
|
705
768
|
const decimals = historyPriceDecimals(data, listing.saved?.metadata.assetCategory);
|
|
706
769
|
const price = (value: unknown) => typeof value === "number" ? value.toFixed(decimals) : "";
|
|
@@ -713,13 +776,14 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
713
776
|
oldest: null,
|
|
714
777
|
// Bars stop arriving on the listing's own trading days, not New York's.
|
|
715
778
|
cadenceExchange: quote?.listingExchangeName || exchange || undefined,
|
|
779
|
+
...(volume ? { note: historyVolumeText(volume, interval) } : {}),
|
|
716
780
|
});
|
|
717
|
-
const gaps = historyGapNote(data,
|
|
718
|
-
listing: listing.key, exchange: quote?.listingExchangeName || exchange || undefined, instrumentType: quote?.instrumentType,
|
|
719
|
-
});
|
|
781
|
+
const gaps = historyGapNote(data, traded);
|
|
720
782
|
const notes = [
|
|
783
|
+
// FB's bars are the fund listed there now; META's from 2021 are from when it was FB.
|
|
784
|
+
...listingFateNotes(await fate(), { served: data.length > 0, firstDate: data[0]?.date }),
|
|
721
785
|
...await listingChoiceNotes(listing, market, quote, venues),
|
|
722
|
-
...historyNotes(range, interval, data[0]?.date), gaps ?? [], historyFlagNote(data) ?? [],
|
|
786
|
+
...historyNotes(range, interval, data[0]?.date), gaps ?? [], historyFlagNote(data) ?? [], historyBarStatusNote(data) ?? [],
|
|
723
787
|
].flat();
|
|
724
788
|
const priceColumns: CliResultColumn[] = [
|
|
725
789
|
intraday
|
|
@@ -735,6 +799,16 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
735
799
|
const flagColumn: CliResultColumn = {
|
|
736
800
|
key: "flag", header: "Flag", format: (value) => typeof value === "string" ? cliStyles.warning(value) : "",
|
|
737
801
|
};
|
|
802
|
+
// Text also marks a bar still forming or rebuilt from hourly bars there; exports keep them as their own fields.
|
|
803
|
+
const flagTextColumn: CliResultColumn = {
|
|
804
|
+
...flagColumn,
|
|
805
|
+
format: (value, row) => [
|
|
806
|
+
typeof value === "string" ? cliStyles.warning(value) : "",
|
|
807
|
+
row.partial ? cliStyles.muted("partial") : "",
|
|
808
|
+
row.filled ? cliStyles.muted("filled") : "",
|
|
809
|
+
].filter(Boolean).join(" "),
|
|
810
|
+
};
|
|
811
|
+
const marked = data.some((row) => row.partial || row.filled);
|
|
738
812
|
ctx.printResult({
|
|
739
813
|
data,
|
|
740
814
|
metadata: {
|
|
@@ -749,19 +823,23 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
749
823
|
lastDate: data.at(-1)?.date ?? null,
|
|
750
824
|
bars: data.length,
|
|
751
825
|
asOf: freshness?.asOf ?? null,
|
|
826
|
+
...(volume ? { volumeUnit: volume.unit, volumePeriod: interval === "1d" ? "UTC day" : interval } : {}),
|
|
752
827
|
},
|
|
753
828
|
...(notes.length > 0 ? { warnings: notes } : {}),
|
|
754
829
|
freshness,
|
|
755
830
|
}, {
|
|
756
831
|
heading: `${listingHeading(identity)}\n${cliStyles.muted(historyFacts(unit, data).join(" · "))}`,
|
|
757
832
|
dateKey: "date",
|
|
758
|
-
textColumns: [...priceColumns,
|
|
759
|
-
// Every exported row says its currency and bar size, so it survives head and concatenation.
|
|
833
|
+
textColumns: [...priceColumns, flagTextColumn],
|
|
834
|
+
// Every exported row says its currency, what a price is in and its bar size, so it survives head and concatenation.
|
|
760
835
|
columns: [
|
|
761
836
|
...priceColumns,
|
|
762
837
|
{ key: "currency", header: "Currency" },
|
|
838
|
+
{ key: "unit", header: "Unit" },
|
|
763
839
|
{ key: "interval", header: "Interval" },
|
|
764
840
|
flagColumn,
|
|
841
|
+
...marked ? [{ key: "partial", header: "Partial" }, { key: "filled", header: "Filled" }] : [],
|
|
842
|
+
...volume ? [{ key: "volumeUnit", header: "Volume unit" }, { key: "volumeNote", header: "Volume note" }] : [],
|
|
765
843
|
],
|
|
766
844
|
});
|
|
767
845
|
});
|
|
@@ -1295,6 +1373,9 @@ async function runAnalyst(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1295
1373
|
async function runEvents(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
1296
1374
|
const args = [...rawArgs];
|
|
1297
1375
|
const exchangeOption = takeOption(args, "--exchange");
|
|
1376
|
+
// A central bank's name means the bank, not a listing that shares it; a venue still reaches the listing.
|
|
1377
|
+
const bank = exchangeOption ? null : centralBankEventsMessage(args.join(" "));
|
|
1378
|
+
if (bank) ctx.fail(bank);
|
|
1298
1379
|
const raw = requireOneArg(args, "events <symbol>", "symbol", ctx);
|
|
1299
1380
|
await withMarketData(ctx, async (market) => {
|
|
1300
1381
|
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
@@ -1364,6 +1445,7 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1364
1445
|
const refresh = ctx.cliOptions.refresh;
|
|
1365
1446
|
const venues = loadBareVenues(listing, market);
|
|
1366
1447
|
const quotePromise = loadListingQuote(market.dataProvider, listing);
|
|
1448
|
+
const fate = listingFateLoader(listing, market, quotePromise);
|
|
1367
1449
|
const inputsPromise = loadOptionModelInputs(market.dataProvider, listing, quotePromise, refresh);
|
|
1368
1450
|
const { result, chain: loaded } = await loadForListing(listing, market, ctx, async () => {
|
|
1369
1451
|
const cached = await market.dataProvider.getCachedQuery?.("getOptionsChain", [symbol, exchange, expirationDate, undefined])
|
|
@@ -1374,7 +1456,7 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1374
1456
|
cacheMode: refresh ? "refresh" : "default",
|
|
1375
1457
|
}),
|
|
1376
1458
|
};
|
|
1377
|
-
}, undefined, { command: "options", noun: "options chain" }).catch((error: unknown) => {
|
|
1459
|
+
}, undefined, { command: "options", noun: "options chain", fate }).catch((error: unknown) => {
|
|
1378
1460
|
if (!isOptionsUnavailableError(error)) throw error;
|
|
1379
1461
|
// A future or commodity with no chain of its own: name the listed fund whose options stand in.
|
|
1380
1462
|
const alternative = listedOptionsAlternative(listing.key);
|
|
@@ -1403,7 +1485,10 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
1403
1485
|
const modelWarning = inputs.spot == null && (chain.calls.length > 0 || chain.puts.length > 0)
|
|
1404
1486
|
? `IV and delta need a current ${listing.key} quote; those columns are blank`
|
|
1405
1487
|
: null;
|
|
1488
|
+
const listed = chain.expirationDates.length > 0 || chain.calls.length > 0 || chain.puts.length > 0;
|
|
1406
1489
|
const warnings = [
|
|
1490
|
+
// FB's chain is the fund listed there now; a listing that stopped trading has none.
|
|
1491
|
+
...listingFateNotes(await fate(), { served: listed }),
|
|
1407
1492
|
...await listingChoiceNotes(listing, market, quote, venues),
|
|
1408
1493
|
...[refreshWarning ?? sessionWarning, modelWarning].filter((warning): warning is string => warning != null),
|
|
1409
1494
|
];
|
|
@@ -1575,7 +1660,7 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
1575
1660
|
group: CLI_COMMAND_GROUPS.research,
|
|
1576
1661
|
usage: ["quote <symbol...>"],
|
|
1577
1662
|
options: [EXCHANGE_OPTION],
|
|
1578
|
-
examples: ["quote AAPL MSFT NVDA", "quote SAN:EPA BHP:ASX", "quote BTC-USD EURUSD=X", "quote AAPL --json"],
|
|
1663
|
+
examples: ["quote AAPL MSFT NVDA", "quote SAN:EPA BHP:ASX", "quote BTC-USD EURUSD=X", "quote binance:BZUSDT", "quote AAPL --json"],
|
|
1579
1664
|
},
|
|
1580
1665
|
execute: (args, ctx) => runQuote(args, ctx, "quote"),
|
|
1581
1666
|
},
|
|
@@ -1609,9 +1694,7 @@ export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
|
1609
1694
|
}],
|
|
1610
1695
|
examples: ["history AAPL", "history BHP:ASX --range 5Y", "history ZAR=X --range ALL", "history ZAR=X --tail 5", "history AAPL --range 5Y --csv > aapl.csv"],
|
|
1611
1696
|
},
|
|
1612
|
-
unknownOptionHint:
|
|
1613
|
-
? `history takes a --range instead of dates: ${TIME_RANGES.join(", ")}. ${HISTORY_ALL_RANGE}.`
|
|
1614
|
-
: null,
|
|
1697
|
+
unknownOptionHint: historyOptionHint,
|
|
1615
1698
|
execute: runHistory,
|
|
1616
1699
|
},
|
|
1617
1700
|
{
|
|
@@ -38,12 +38,17 @@ import { quotesFreshness, rowsFreshness } from "../freshness";
|
|
|
38
38
|
import { periodicityOf } from "../pane-functions/freshness";
|
|
39
39
|
import { formatBasisPoints, toBasisPoints } from "../../utils/basis-points";
|
|
40
40
|
import {
|
|
41
|
+
basisPointsCell,
|
|
41
42
|
DEFAULT_FRED_START,
|
|
42
43
|
fredEmptyMessage,
|
|
44
|
+
fredExportValue,
|
|
43
45
|
fredHistoryNotes,
|
|
46
|
+
fredProvenance,
|
|
47
|
+
fredPublicationTime,
|
|
48
|
+
fredValueHeader,
|
|
49
|
+
fredValueKey,
|
|
44
50
|
isSpreadSeries,
|
|
45
51
|
laggingSeriesNote,
|
|
46
|
-
spreadBasisPointsCell,
|
|
47
52
|
} from "./fred-series";
|
|
48
53
|
|
|
49
54
|
// Batch quotes often omit names for indices and ETFs; these baskets are fixed, so name them here.
|
|
@@ -351,8 +356,9 @@ async function runFredList(filter: string, ctx: Parameters<CliCommandDef["execut
|
|
|
351
356
|
ctx.printResult({ data: rows, metadata: { filter: filter || null, total: catalog.series.length } }, {
|
|
352
357
|
columns: [
|
|
353
358
|
{ key: "id", header: "ID", shrink: false },
|
|
354
|
-
|
|
355
|
-
{ key: "
|
|
359
|
+
// A title too narrow to tell series apart goes on a line under its ID.
|
|
360
|
+
{ key: "title", header: "Title", minWidth: 30, stackPriority: 1 },
|
|
361
|
+
{ key: "group", header: "Group", shrink: false },
|
|
356
362
|
],
|
|
357
363
|
empty: filter ? `No supported FRED series match "${filter}". Run gloomberb fred --list to see them all.` : "No FRED series are listed.",
|
|
358
364
|
});
|
|
@@ -375,7 +381,15 @@ async function runFred(rawArgs: string[], ctx: Parameters<CliCommandDef["execute
|
|
|
375
381
|
if (isUnsupportedSeries(error)) ctx.fail(`Unsupported FRED series ${seriesId}. List supported series with: gloomberb fred --list`);
|
|
376
382
|
throw error;
|
|
377
383
|
});
|
|
378
|
-
|
|
384
|
+
// Each observation exports under its unit (`value_bp`, `value_pct`), a spread in basis points.
|
|
385
|
+
const valueKey = fredValueKey(seriesId, data.info?.units);
|
|
386
|
+
// A value FRED does not list yet carries its publisher and when it published, in every export.
|
|
387
|
+
const exportRow = (observation: { date: string; value: number | null; publisher?: string; publishedAt?: string }) => ({
|
|
388
|
+
date: observation.date,
|
|
389
|
+
[valueKey]: fredExportValue(seriesId, observation.value),
|
|
390
|
+
...(observation.publisher?.trim() ? { publisher: observation.publisher.trim(), ...(observation.publishedAt ? { publishedAt: observation.publishedAt } : {}) } : {}),
|
|
391
|
+
});
|
|
392
|
+
const rows = data.observations.map(exportRow);
|
|
379
393
|
// The default start hides older history and a start before the series begins is moved up silently: say where it really starts.
|
|
380
394
|
const notes = [
|
|
381
395
|
...fredHistoryNotes({ startDate, startGiven: start != null, seriesStart: data.info?.observationStart }),
|
|
@@ -385,17 +399,25 @@ async function runFred(rawArgs: string[], ctx: Parameters<CliCommandDef["execute
|
|
|
385
399
|
const latest = rows.length > 0 ? null : await apiClient.getCloudFredSeries(seriesId, { limit: 1, sortOrder: "desc" })
|
|
386
400
|
.then((payload) => payload.observations[0] ?? null).catch(() => null);
|
|
387
401
|
const periodicity = periodicityOf(data.info?.frequency);
|
|
402
|
+
const newestDate = rows.reduce<string | null>((newest, row) => (!newest || row.date > newest ? row.date : newest), null);
|
|
403
|
+
// A newest value FRED does not list yet names its publisher, Treasury for a yield; FRED's own stay "FRED".
|
|
404
|
+
const ahead = fredProvenance(data.observations.filter((observation) => observation.date === newestDate));
|
|
405
|
+
// FRED names the series' publisher when Gloom Cloud passes it on, and when it last updated the series.
|
|
406
|
+
const publisher = ahead?.publisher ?? data.info?.source?.trim();
|
|
407
|
+
const publishedAt = ahead ? ahead.publishedAt : fredPublicationTime(data.info, newestDate);
|
|
388
408
|
ctx.printResult({
|
|
389
409
|
data: rows,
|
|
390
410
|
metadata: {
|
|
391
411
|
info: data.info, seriesId, startDate, sortOrder,
|
|
392
412
|
...(notes.length ? { notes } : {}),
|
|
393
|
-
...(latest ? { latestObservation: latest } : {}),
|
|
413
|
+
...(latest ? { latestObservation: exportRow(latest) } : {}),
|
|
394
414
|
},
|
|
395
415
|
freshness: rowsFreshness(rows, {
|
|
396
|
-
source: "FRED", status: "not-a-feed", basis: "published statistics", observedKey: "date", oldest: null,
|
|
416
|
+
source: ahead?.source ?? "FRED", status: "not-a-feed", basis: "published statistics", observedKey: "date", oldest: null,
|
|
397
417
|
// A monthly or quarterly observation is dated the first of its period, not a day it was seen.
|
|
398
418
|
...(periodicity ? { periodicity } : {}),
|
|
419
|
+
...(publisher ? { publisher } : {}),
|
|
420
|
+
...(publishedAt ? { publishedAt } : {}),
|
|
399
421
|
}),
|
|
400
422
|
}, {
|
|
401
423
|
dateKey: "date",
|
|
@@ -404,9 +426,8 @@ async function runFred(rawArgs: string[], ctx: Parameters<CliCommandDef["execute
|
|
|
404
426
|
textColumns: [
|
|
405
427
|
{ key: "date", header: "Date" },
|
|
406
428
|
isSpreadSeries(seriesId)
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
: { key: "value", header: data.info?.units ? `Value (${data.info.units})` : "Value", align: "right" },
|
|
429
|
+
? { key: valueKey, header: "Value (bp)", align: "right", format: basisPointsCell }
|
|
430
|
+
: { key: valueKey, header: fredValueHeader(data.info), align: "right" },
|
|
410
431
|
],
|
|
411
432
|
});
|
|
412
433
|
}
|
|
@@ -424,22 +445,34 @@ async function runYieldCurve(rawArgs: string[], ctx: Parameters<CliCommandDef["e
|
|
|
424
445
|
return {
|
|
425
446
|
seriesId,
|
|
426
447
|
date: latest?.date ?? "",
|
|
427
|
-
|
|
448
|
+
// Yields in percent, named so in every export, as `fred` names a percent series.
|
|
449
|
+
value_pct: latest?.value ?? null,
|
|
428
450
|
title: data.info?.title ?? "",
|
|
429
451
|
// The move since the previous observation FRED has, not calendar yesterday: a Monday reads against Friday.
|
|
430
452
|
previousDate: previous?.date ?? null,
|
|
431
|
-
|
|
453
|
+
previousValue_pct: previous?.value ?? null,
|
|
432
454
|
changeBasisPoints: latest?.value != null && previous?.value != null ? toBasisPoints(latest.value - previous.value, 1) : null,
|
|
455
|
+
latest,
|
|
456
|
+
publishedAt: latest?.publisher ? null : fredPublicationTime(data.info, latest?.date),
|
|
433
457
|
};
|
|
434
458
|
}));
|
|
459
|
+
// Tenors whose latest yield FRED does not list yet name the Treasury and when it published them.
|
|
460
|
+
const ahead = fredProvenance(results.flatMap((row) => row.latest ? [row.latest] : []));
|
|
461
|
+
// The curve shown was published with its last tenor: the newest of their FRED updates, when each has one.
|
|
462
|
+
const published = results.map((row) => row.publishedAt);
|
|
463
|
+
const publishedAt = ahead ? ahead.publishedAt : published.every((time) => time != null) ? published.sort().at(-1) : null;
|
|
435
464
|
ctx.printResult({
|
|
436
|
-
data: results,
|
|
465
|
+
data: results.map(({ publishedAt: _publishedAt, latest: _latest, ...row }) => row),
|
|
437
466
|
metadata: { startDate },
|
|
438
|
-
freshness: rowsFreshness(results, {
|
|
467
|
+
freshness: rowsFreshness(results, {
|
|
468
|
+
source: ahead?.source ?? "FRED", status: "not-a-feed", basis: "daily Treasury yields", observedKey: "date",
|
|
469
|
+
...(ahead?.publisher ? { publisher: ahead.publisher } : {}),
|
|
470
|
+
...(publishedAt ? { publishedAt } : {}),
|
|
471
|
+
}),
|
|
439
472
|
}, {
|
|
440
473
|
textColumns: [
|
|
441
474
|
{ key: "tenor", header: "Tenor", value: (row) => YIELD_TENORS[String(row.seriesId)] ?? row.seriesId },
|
|
442
|
-
{ key: "
|
|
475
|
+
{ key: "value_pct", header: "Yield %", align: "right", format: (value) => typeof value === "number" ? value.toFixed(2) : "-" },
|
|
443
476
|
{
|
|
444
477
|
key: "changeBasisPoints",
|
|
445
478
|
header: "1D bp",
|