gloomberb 0.16.1 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +2 -1
- package/src/api-client/beneficial-owners.ts +92 -0
- package/src/api-client/data.ts +26 -8
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +2 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +37 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +2 -0
- package/src/brokers/account-cache.ts +69 -0
- package/src/cli/command-options.ts +74 -0
- package/src/cli/commands/command-utils.ts +37 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +560 -136
- package/src/cli/commands/overview.ts +136 -48
- package/src/cli/commands/ticker.ts +220 -67
- package/src/cli/desktop-pane-shot.ts +37 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +27 -6
- package/src/cli/helpers.ts +4 -8
- package/src/cli/history-rows.ts +187 -15
- package/src/cli/index.ts +23 -8
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/options.ts +5 -1
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/capabilities.ts +5 -0
- package/src/cli/pane-functions/catalog.ts +28 -1
- package/src/cli/pane-functions/data.ts +3 -1
- package/src/cli/pane-functions/dom.ts +87 -16
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +31 -22
- package/src/cli/pane-functions/headless.ts +201 -41
- package/src/cli/pane-functions/index.ts +24 -6
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +12 -1
- package/src/cli/pane-functions/resolver.ts +63 -9
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +11 -3
- package/src/cli/registry.ts +6 -3
- package/src/cli/report-tables.ts +460 -0
- package/src/cli/result.ts +53 -29
- package/src/cli/ticker-resolution.ts +7 -5
- package/src/components/chart/composite/composite-chart.tsx +88 -2536
- package/src/components/chart/composite/drawing-store.ts +59 -0
- package/src/components/chart/composite/legend.tsx +319 -0
- package/src/components/chart/composite/panel-bitmap.ts +139 -0
- package/src/components/chart/composite/panel-gestures.ts +59 -0
- package/src/components/chart/composite/panel-labels.ts +107 -0
- package/src/components/chart/composite/panel-surface.tsx +876 -0
- package/src/components/chart/composite/tool-catalog.ts +98 -0
- package/src/components/chart/composite/toolbar.tsx +186 -0
- package/src/components/chart/composite/tools.ts +8 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
- package/src/components/chart/composite/use-composite-viewport.ts +143 -0
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +6 -0
- package/src/components/data-table/export.ts +6 -51
- package/src/components/data-table/view.tsx +32 -11
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- package/src/components/layout/pane/content.tsx +23 -10
- package/src/components/layout/pane/error-boundary.tsx +103 -0
- package/src/components/layout/pane/footer/registration.tsx +68 -23
- package/src/components/layout/pane/header.tsx +11 -11
- package/src/components/layout/shell/active-drag.ts +67 -35
- package/src/components/layout/shell/cursor-occlusion.ts +6 -5
- package/src/components/layout/shell/drag/index.ts +12 -7
- package/src/components/layout/shell/drag/live.ts +122 -0
- package/src/components/layout/shell/drag/overlays.tsx +179 -35
- package/src/components/layout/shell/drag/runtime.ts +62 -50
- package/src/components/layout/shell/drag/slide.ts +10 -0
- package/src/components/layout/shell/index.tsx +37 -51
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
- package/src/components/layout/shell/native/surfaces.ts +30 -14
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +419 -168
- package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
- package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
- package/src/components/metric-treemap/heat-surface.tsx +43 -16
- package/src/components/metric-treemap/heat-tiles.ts +18 -0
- package/src/components/metric-treemap/layout.ts +2 -0
- package/src/components/onboarding/onboarding-keyboard.ts +311 -0
- package/src/components/onboarding/onboarding-wizard.tsx +101 -788
- package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
- package/src/components/onboarding/use-onboarding-progress.ts +298 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
- package/src/components/ticker/list-table-view.tsx +13 -1
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/range-track.tsx +10 -3
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +7 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/data/config/store/normalize.ts +17 -1
- package/src/data/json-persistence.ts +17 -3
- package/src/data/json-storage.ts +2 -0
- package/src/data/memory-resource-store.ts +46 -0
- package/src/i18n/es.ts +19 -1
- package/src/i18n/ja.ts +19 -1
- package/src/i18n/ko.ts +19 -1
- package/src/i18n/zh-cn.ts +19 -1
- package/src/i18n/zh-tw.ts +19 -1
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/quotes.ts +23 -4
- package/src/market-data/fx-closes.ts +72 -0
- package/src/market-data/market/freshness.ts +123 -6
- package/src/market-data/market/session-close-note.ts +57 -0
- package/src/market-data/market/status.ts +151 -0
- package/src/market-data/published-apac-sessions.ts +66 -0
- package/src/market-data/quotes/contributions.ts +2 -0
- package/src/market-data/quotes/freshness.ts +5 -0
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- package/src/plugins/builtin/account-management/pane.tsx +4 -0
- package/src/plugins/builtin/alerts/cli.ts +10 -5
- package/src/plugins/builtin/alerts/index.tsx +1 -0
- package/src/plugins/builtin/analytics/metrics.ts +8 -3
- package/src/plugins/builtin/analytics/pane-model.ts +10 -6
- package/src/plugins/builtin/analytics/risk-client.ts +191 -66
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
- package/src/plugins/builtin/analytics/risk-model.ts +45 -17
- package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
- package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
- package/src/plugins/builtin/attention/headless.ts +6 -4
- package/src/plugins/builtin/attention/index.tsx +1 -1
- package/src/plugins/builtin/attention/pane.tsx +2 -2
- package/src/plugins/builtin/awards/headless.ts +1 -0
- package/src/plugins/builtin/awards/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/headless.ts +1 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
- package/src/plugins/builtin/buildout/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/detail.tsx +1 -1
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless.ts +38 -3
- package/src/plugins/builtin/chart-composer/index.tsx +3 -1
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
- package/src/plugins/builtin/chat/channels.ts +19 -3
- package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
- package/src/plugins/builtin/chat/content/footer.tsx +15 -6
- package/src/plugins/builtin/chat/content/index.tsx +120 -21
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
- package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
- package/src/plugins/builtin/chat/direct-messages.ts +200 -0
- package/src/plugins/builtin/chat/index.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
- package/src/plugins/builtin/chat/message/header.tsx +16 -6
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
- package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
- package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
- package/src/plugins/builtin/chat/message/types.ts +14 -2
- package/src/plugins/builtin/chat/profile-popover.ts +18 -13
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/comment-letters/index.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +2 -2
- package/src/plugins/builtin/company-kpis/headless.ts +1 -0
- package/src/plugins/builtin/congress-trades/headless.ts +1 -0
- package/src/plugins/builtin/correlation/compute.ts +59 -16
- package/src/plugins/builtin/correlation/geo.ts +34 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
- package/src/plugins/builtin/correlation/headless.ts +42 -8
- package/src/plugins/builtin/correlation/history.ts +2 -0
- package/src/plugins/builtin/correlation/index.tsx +68 -14
- package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
- package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
- package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
- package/src/plugins/builtin/correlation/settings.ts +1 -1
- package/src/plugins/builtin/cot/headless.ts +6 -3
- package/src/plugins/builtin/cot/index.tsx +3 -3
- package/src/plugins/builtin/cot/model.ts +36 -3
- package/src/plugins/builtin/cpi/headless.ts +4 -0
- package/src/plugins/builtin/credit-boards/headless.ts +2 -0
- package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
- package/src/plugins/builtin/credit-documents/headless.ts +2 -0
- package/src/plugins/builtin/crypto-board/headless.ts +3 -0
- package/src/plugins/builtin/custom-view/loader.ts +1 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
- package/src/plugins/builtin/doe/headless.ts +7 -0
- package/src/plugins/builtin/doe/range-bar.tsx +7 -37
- package/src/plugins/builtin/earnings/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
- package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
- package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
- package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
- package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
- package/src/plugins/builtin/econ/index.tsx +1 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
- package/src/plugins/builtin/equity-screener/headless.ts +2 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/headless.ts +3 -1
- package/src/plugins/builtin/fear-greed/headless.ts +2 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +39 -10
- package/src/plugins/builtin/futures-curve/index.tsx +3 -3
- package/src/plugins/builtin/futures-curve/model.ts +188 -4
- package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
- package/src/plugins/builtin/gpu/headless.ts +7 -3
- package/src/plugins/builtin/gpu/ladder.tsx +26 -30
- package/src/plugins/builtin/gpu/model.ts +27 -1
- package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
- package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
- package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
- package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
- package/src/plugins/builtin/holders/client.ts +3 -6
- package/src/plugins/builtin/holders/format.ts +31 -1
- package/src/plugins/builtin/holders/headless.ts +161 -6
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +42 -16
- package/src/plugins/builtin/holders/report-header.ts +136 -0
- package/src/plugins/builtin/holders/table-model.ts +20 -5
- package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
- package/src/plugins/builtin/holders/types.ts +2 -1
- package/src/plugins/builtin/insider/headless.ts +2 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -1
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
- package/src/plugins/builtin/macro-day/headless.ts +2 -0
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-heatmap/data.ts +2 -0
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
- package/src/plugins/builtin/market-movers/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +20 -3
- package/src/plugins/builtin/members/headless.ts +5 -3
- package/src/plugins/builtin/members/model.ts +10 -2
- package/src/plugins/builtin/members/pane.tsx +23 -6
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- package/src/plugins/builtin/money-markets/headless.ts +1 -0
- package/src/plugins/builtin/news/headless.ts +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +8 -1
- package/src/plugins/builtin/notes/cli.ts +14 -6
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/openfda/index.tsx +1 -0
- package/src/plugins/builtin/options-calculator/headless.ts +2 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +5 -0
- package/src/plugins/builtin/pe-band/client.ts +48 -3
- package/src/plugins/builtin/pe-band/headless.ts +25 -7
- package/src/plugins/builtin/pe-band/model.ts +92 -16
- package/src/plugins/builtin/pe-band/pane.tsx +33 -16
- package/src/plugins/builtin/perps/client.ts +50 -3
- package/src/plugins/builtin/perps/headless.ts +144 -16
- package/src/plugins/builtin/perps/index.tsx +6 -6
- package/src/plugins/builtin/perps/model.ts +189 -12
- package/src/plugins/builtin/perps/pane.tsx +249 -48
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -0
- package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
- package/src/plugins/builtin/portfolio-list/cli/render.ts +232 -39
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
- package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
- package/src/plugins/builtin/portfolio-list/headless.ts +100 -16
- package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
- package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +53 -16
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
- package/src/plugins/builtin/power/headless.ts +3 -1
- package/src/plugins/builtin/rate-path/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
- package/src/plugins/builtin/research/analyst-headless.ts +3 -0
- package/src/plugins/builtin/research/events-headless.ts +2 -0
- package/src/plugins/builtin/research/headless.ts +2 -0
- package/src/plugins/builtin/research/index.tsx +1 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
- package/src/plugins/builtin/research/relative-valuation-model.ts +18 -6
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/research-search/index.tsx +1 -0
- package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
- package/src/plugins/builtin/risk-factors/headless.ts +2 -0
- package/src/plugins/builtin/scanner/flow-history.ts +2 -13
- package/src/plugins/builtin/scanner/headless.ts +14 -0
- package/src/plugins/builtin/seasonality/headless.ts +2 -0
- package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
- package/src/plugins/builtin/sec/filing-content.ts +42 -17
- package/src/plugins/builtin/sec/forms.ts +12 -0
- package/src/plugins/builtin/sec/headless.ts +2 -0
- package/src/plugins/builtin/sectors/client.ts +1 -0
- package/src/plugins/builtin/sectors/headless.ts +9 -1
- package/src/plugins/builtin/sectors/sector-model.ts +2 -0
- package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/members-menu.tsx +260 -0
- package/src/plugins/builtin/shared/report-freshness.ts +57 -0
- package/src/plugins/builtin/shared/research-cells.tsx +4 -9
- package/src/plugins/builtin/short-interest/headless.ts +2 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +7 -1
- package/src/plugins/builtin/supply-chain/index.tsx +10 -1
- package/src/plugins/builtin/supply-chain/model.ts +27 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
- package/src/plugins/builtin/themes/headless.ts +3 -0
- package/src/plugins/builtin/themes/pane.tsx +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
- package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- package/src/plugins/builtin/volatility/headless.ts +6 -1
- package/src/plugins/builtin/world-indices/headless.ts +2 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +159 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
- package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
- package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +448 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
- package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +69 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
- package/src/plugins/builtin/world-venue-map/model.ts +23 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +35 -44
- package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
- package/src/plugins/builtin/yield-curve/headless.ts +16 -0
- package/src/plugins/loader.ts +13 -1
- package/src/plugins/registry/pane-settings.ts +1 -0
- package/src/renderers/browser/app-services.ts +3 -1
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/dom.ts +31 -0
- package/src/renderers/dom/data-table/index.tsx +5 -0
- package/src/renderers/dom/data-table/row.tsx +2 -0
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- package/src/renderers/dom/desktop/list-view.tsx +35 -10
- package/src/renderers/dom/desktop/popover.tsx +73 -14
- package/src/renderers/dom/host/box.tsx +113 -17
- package/src/renderers/dom/host/drag-shield.ts +24 -0
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/live-frame.ts +54 -0
- package/src/renderers/dom/host/mouse.ts +8 -1
- package/src/renderers/dom/host/scroll-box.tsx +6 -5
- package/src/renderers/dom/host/tabs.tsx +3 -2
- package/src/renderers/dom/styles.css +16 -9
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -1
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
- package/src/renderers/electrobun/view/host/native.ts +0 -10
- package/src/renderers/electrobun/view/host/window-move.ts +28 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/ui-host.tsx +2 -5
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/renderers/opentui/ui-host.tsx +7 -1
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
- package/src/sources/provider-router/batches.ts +3 -3
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financial-routes.ts +2 -2
- package/src/sources/provider-router/financials.ts +76 -12
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/provider-router/primary.ts +2 -2
- package/src/sources/sec-registrant.ts +75 -0
- package/src/state/app/context/index.tsx +24 -8
- package/src/state/hooks/quote-streaming.ts +41 -26
- package/src/state/pane-scroll-registry.tsx +67 -35
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/margin-account.ts +108 -0
- package/src/theme/heat-colors.ts +266 -84
- package/src/time-series/resolution.ts +15 -0
- package/src/time-series/resolve.ts +1 -1
- package/src/time-series/use-chart-resolution.ts +1 -1
- package/src/types/context-menu.ts +6 -0
- package/src/types/data-provider.ts +2 -0
- package/src/types/financials.ts +35 -3
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +20 -1
- package/src/types/ticker.ts +15 -0
- package/src/ui/host.tsx +26 -0
- package/src/ui/index.tsx +8 -3
- package/src/ui/scroll-box-axis.ts +26 -0
- package/src/updater/index.ts +9 -11
- package/src/utils/async-deadline.ts +21 -0
- package/src/utils/cli-output.ts +5 -1
- package/src/utils/crypto-pair.ts +41 -0
- package/src/utils/currency-units.ts +19 -0
- package/src/utils/depositary-receipt.ts +70 -0
- package/src/utils/display-number.ts +63 -0
- package/src/utils/exchanges.ts +72 -0
- package/src/utils/fire-and-forget.ts +24 -0
- package/src/utils/format.ts +13 -0
- package/src/utils/fundamentals.ts +17 -1
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history-integrity.ts +19 -6
- package/src/utils/price-history.ts +58 -13
- package/src/utils/rpc-timeout-error.ts +27 -0
- package/src/utils/sec.ts +13 -1
- package/src/utils/utc-time.ts +79 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CliCommandDef } from "../../types/plugin";
|
|
2
2
|
import { TIME_RANGES, type TimeRange } from "../../time-series/range";
|
|
3
|
-
import type { EarningsEvent, QuoteBatchResult, SecFilingItem } from "../../types/data-provider";
|
|
3
|
+
import type { EarningsEvent, QuoteBatchResult, QuoteSubscriptionTarget, SecFilingItem } from "../../types/data-provider";
|
|
4
4
|
import type { NewsArticle, NewsFeed, NewsQuery } from "../../news/types";
|
|
5
5
|
import type {
|
|
6
6
|
AnalystResearchData,
|
|
@@ -13,8 +13,9 @@ import { currencyMinorDigits, formatMarketPrice, formatMarketPriceWithCurrency,
|
|
|
13
13
|
import { getActiveQuoteDisplay, marketStateLabel } from "../../market-data/market/status";
|
|
14
14
|
import { formatCompact, formatDistributionAmount, formatPercent } from "../../utils/format";
|
|
15
15
|
import { withCliServices, withMarketData } from "../context";
|
|
16
|
-
import { isoDate, parsePositiveInt,
|
|
17
|
-
import {
|
|
16
|
+
import { isoDate, parsePositiveInt, rejectExtraArgs, requireOneArg, takeFlag, takeOption } from "./command-utils";
|
|
17
|
+
import type { BuiltinCliCommandDef } from "../command-options";
|
|
18
|
+
import { CLI_COMMAND_GROUPS, TABLE_SECTION_OPTION } from "../help";
|
|
18
19
|
import {
|
|
19
20
|
formatChangePercentCell,
|
|
20
21
|
formatCountCell,
|
|
@@ -33,14 +34,79 @@ import {
|
|
|
33
34
|
} from "../../plugins/builtin/research/analyst-model";
|
|
34
35
|
import { optionQuoteSide } from "../../plugins/builtin/options/market-reference";
|
|
35
36
|
import { getPublishedUsEquityCalendarYears, getPublishedUsEquitySession } from "../../market-data/published-us-sessions";
|
|
36
|
-
import { renderFundamentalsReport } from "./ticker";
|
|
37
|
-
import {
|
|
37
|
+
import { fundamentalsReportTables, renderFundamentalsReport } from "./ticker";
|
|
38
|
+
import type { CliResultColumn } from "../result";
|
|
39
|
+
import {
|
|
40
|
+
exportRowsTable,
|
|
41
|
+
reportFooterLines,
|
|
42
|
+
selectReportTables,
|
|
43
|
+
type CliReportTables,
|
|
44
|
+
} from "../report-tables";
|
|
45
|
+
import {
|
|
46
|
+
historyFacts,
|
|
47
|
+
historyFlagNote,
|
|
48
|
+
historyAllRangeYears,
|
|
49
|
+
historyIntervalsByRange,
|
|
50
|
+
historyNotes,
|
|
51
|
+
historyPriceDecimals,
|
|
52
|
+
historyRows,
|
|
53
|
+
historyUnit,
|
|
54
|
+
} from "../history-rows";
|
|
55
|
+
import { CRYPTO_BOARD_HINT, quoteNotes } from "./crypto-hints";
|
|
56
|
+
import { formatUtcTime } from "../../utils/utc-time";
|
|
57
|
+
import { isFiniteNumber } from "../../utils/guards";
|
|
58
|
+
import { exportedFundamentals } from "../../utils/price-earnings";
|
|
59
|
+
import { fundamentalsFreshness, quotesFreshness, rowsFreshness } from "../freshness";
|
|
60
|
+
import {
|
|
61
|
+
barHistoryFreshness,
|
|
62
|
+
barResolutionFromDates,
|
|
63
|
+
REPORTED_DATA,
|
|
64
|
+
SEC_FILINGS,
|
|
65
|
+
} from "../../plugins/builtin/shared/report-freshness";
|
|
66
|
+
import {
|
|
67
|
+
EXCHANGE_OPTION,
|
|
68
|
+
listingHeading,
|
|
69
|
+
listingIdentity,
|
|
70
|
+
listingTitle,
|
|
71
|
+
listingVenues,
|
|
72
|
+
loadForListing,
|
|
73
|
+
loadListingQuote,
|
|
74
|
+
notTradedMessage,
|
|
75
|
+
requireCliListing,
|
|
76
|
+
type CliListing,
|
|
77
|
+
type ListingIdentity,
|
|
78
|
+
} from "../listing-arg";
|
|
79
|
+
import { secRegistrantMismatchMessage, SecRegistrantMismatchError, areDifferentCompanies } from "../../sources/sec-registrant";
|
|
80
|
+
import { isCryptoPairSymbol } from "../../utils/crypto-pair";
|
|
81
|
+
import { isUsListingExchange } from "../../utils/exchanges";
|
|
82
|
+
import { nonUsSecListingVenue } from "../../utils/sec";
|
|
83
|
+
import type { MarketContext } from "../types";
|
|
84
|
+
import {
|
|
85
|
+
holderListFacts,
|
|
86
|
+
holderShareBasisMarker,
|
|
87
|
+
holderShareBasisNote,
|
|
88
|
+
holderValueBasis,
|
|
89
|
+
moneyColumnHeader,
|
|
90
|
+
nonUsHolderCaveat,
|
|
91
|
+
sharedReportDate,
|
|
92
|
+
} from "../../plugins/builtin/holders/report-header";
|
|
93
|
+
import { formatHolderOwnershipPercent, holderValueCurrency } from "../../plugins/builtin/holders/format";
|
|
94
|
+
import { fetchBeneficialOwners } from "../../plugins/builtin/holders/beneficial-client";
|
|
95
|
+
import { filingFormMatches, SEC_FILING_FETCH_LIMIT } from "../../plugins/builtin/sec/forms";
|
|
96
|
+
import {
|
|
97
|
+
BENEFICIAL_REPORT_COLUMNS,
|
|
98
|
+
beneficialCoverageNotices,
|
|
99
|
+
beneficialListComplete,
|
|
100
|
+
beneficialListFacts,
|
|
101
|
+
beneficialListUnreadable,
|
|
102
|
+
beneficialRouteForm,
|
|
103
|
+
buildBeneficialReportRows,
|
|
104
|
+
HOLDER_FORMS,
|
|
105
|
+
parseHolderForm,
|
|
106
|
+
type HolderForm,
|
|
107
|
+
} from "../../plugins/builtin/holders/beneficial-report";
|
|
38
108
|
|
|
39
109
|
const VALID_RANGES = new Set<TimeRange>(TIME_RANGES);
|
|
40
|
-
const EXCHANGE_OPTION = {
|
|
41
|
-
flags: "--exchange <code>",
|
|
42
|
-
description: "Listing exchange, for a symbol that trades in several places",
|
|
43
|
-
};
|
|
44
110
|
const VALID_NEWS_FEEDS = new Set<NewsFeed>(["latest", "top", "breaking", "ticker", "sector", "topic"]);
|
|
45
111
|
|
|
46
112
|
type QuoteCliRecord = Omit<QuoteBatchResult, "error"> & { error: string | null };
|
|
@@ -67,6 +133,11 @@ function normalizeSymbols(args: string[]): string[] {
|
|
|
67
133
|
.filter(Boolean);
|
|
68
134
|
}
|
|
69
135
|
|
|
136
|
+
/** What JSON metadata says about the listing a command resolved. */
|
|
137
|
+
function listingMetadata(identity: ListingIdentity) {
|
|
138
|
+
return { symbol: identity.symbol, exchange: identity.exchange || null, name: identity.name };
|
|
139
|
+
}
|
|
140
|
+
|
|
70
141
|
const QUOTE_LEAD_COLUMNS = [
|
|
71
142
|
{ key: "symbol", header: "Symbol" },
|
|
72
143
|
{ key: "name", header: "Name" },
|
|
@@ -86,7 +157,8 @@ function quoteColumns() {
|
|
|
86
157
|
return [
|
|
87
158
|
...QUOTE_LEAD_COLUMNS,
|
|
88
159
|
{ key: "currency", header: "Cur" },
|
|
89
|
-
|
|
160
|
+
// Whether the price is real-time or delayed: a feed state, not where it came from.
|
|
161
|
+
{ key: "source", header: "Feed", format: (value: unknown) => value === "live" || value === "delayed" ? value : "" },
|
|
90
162
|
{ key: "updatedAt", header: "Updated" },
|
|
91
163
|
];
|
|
92
164
|
}
|
|
@@ -199,6 +271,7 @@ function holderRows(data: HolderData, ownerTypes?: Set<string>) {
|
|
|
199
271
|
value: holder.value ?? null,
|
|
200
272
|
percentHeld: holder.percentHeld ?? null,
|
|
201
273
|
changeShares: holder.changeShares ?? null,
|
|
274
|
+
shareBasis: holder.shareBasis ?? null,
|
|
202
275
|
}));
|
|
203
276
|
}
|
|
204
277
|
|
|
@@ -332,46 +405,123 @@ async function runQuote(rawArgs: string[], ctx: Parameters<CliCommandDef["execut
|
|
|
332
405
|
if (symbols.length === 0) ctx.fail(`Usage: gloomberb ${commandName} <symbol...>`);
|
|
333
406
|
|
|
334
407
|
await withMarketData(ctx, async (market) => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
{
|
|
338
|
-
);
|
|
339
|
-
const
|
|
408
|
+
// With several symbols, --exchange is for the ones that name no exchange of their own.
|
|
409
|
+
const listings = await Promise.all(symbols.map((symbol) => requireCliListing(
|
|
410
|
+
symbol, exchange, market, ctx, { ownExchangeWins: symbols.length > 1 },
|
|
411
|
+
)));
|
|
412
|
+
const targets: QuoteSubscriptionTarget[] = listings.map((listing) => ({ symbol: listing.request.symbol, exchange: listing.request.exchange }));
|
|
413
|
+
const results = await market.dataProvider.getQuotesBatch(targets, { forceRefresh: ctx.cliOptions.refresh });
|
|
414
|
+
const listingOf = (result: QuoteBatchResult, index: number) => listings[targets.indexOf(result.target)] ?? listings[index]!;
|
|
415
|
+
// A listing with no quote on an exchange its symbol is not listed on says so; venues are only looked up for those.
|
|
416
|
+
const notTraded = await Promise.all(results.map((result, index) => (
|
|
417
|
+
result.quote ? null : notTradedMessage(listingOf(result, index), market)
|
|
418
|
+
)));
|
|
419
|
+
if (listings.length === 1 && notTraded[0]) ctx.fail(notTraded[0]);
|
|
420
|
+
// Each row names its listing by key (SAN:EPA) and company, so the table needs no line above it.
|
|
421
|
+
const data = results.map((result, index) => ({
|
|
340
422
|
target: result.target,
|
|
423
|
+
listing: listingMetadata(listingIdentity(listingOf(result, index), result.quote)),
|
|
341
424
|
quote: result.quote,
|
|
342
|
-
error: errorMessage(result.error),
|
|
425
|
+
error: notTraded[index] ?? errorMessage(result.error),
|
|
343
426
|
}));
|
|
344
|
-
|
|
427
|
+
// Text mode shows only "unavailable" in the cell; the JSON rows already carry each reason.
|
|
428
|
+
const notes = ctx.cliOptions.format === "text" ? quoteNotes(data, { exchange }) : [];
|
|
429
|
+
ctx.printResult({
|
|
430
|
+
data,
|
|
431
|
+
warnings: notes.length > 0 ? notes : undefined,
|
|
432
|
+
freshness: quotesFreshness(data.map((row) => row.quote)),
|
|
433
|
+
}, {
|
|
434
|
+
rows: quoteRows,
|
|
435
|
+
columns: commandName === "compare" ? compareColumns() : quoteColumns(),
|
|
436
|
+
});
|
|
345
437
|
});
|
|
346
438
|
}
|
|
347
439
|
|
|
440
|
+
/** A crypto pair that will not load points at the crypto board. Structured formats keep the error as thrown. */
|
|
441
|
+
function failHistory(error: unknown, symbol: string, ctx: Parameters<CliCommandDef["execute"]>[1]): never {
|
|
442
|
+
if (ctx.cliOptions.format !== "text" || !isCryptoPairSymbol(symbol)) throw error;
|
|
443
|
+
return ctx.fail(errorMessage(error) ?? `No history available for ${symbol}`, CRYPTO_BOARD_HINT);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const HISTORY_USAGE = "history <symbol> [--range <range>]";
|
|
447
|
+
const HISTORY_ALL_RANGE = `ALL gives the full history the source has, up to ${historyAllRangeYears()} years`;
|
|
448
|
+
/** Options people reach for to ask for dates, which history answers with a range. */
|
|
449
|
+
const DATE_WINDOW_OPTIONS = new Set(["--from", "--to", "--start", "--end", "--since", "--until", "--date", "--start-date", "--end-date"]);
|
|
450
|
+
|
|
348
451
|
async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
349
452
|
const args = [...rawArgs];
|
|
350
453
|
const range = parseRange(takeOption(args, "--range"), ctx);
|
|
351
|
-
const requestedExchange = takeOption(args, "--exchange")
|
|
352
|
-
const
|
|
454
|
+
const requestedExchange = takeOption(args, "--exchange");
|
|
455
|
+
const raw = requireOneArg(args, HISTORY_USAGE, "symbol", ctx);
|
|
353
456
|
await withMarketData(ctx, async (market) => {
|
|
354
|
-
const
|
|
355
|
-
const exchange =
|
|
457
|
+
const listing = await requireCliListing(raw, requestedExchange, market, ctx);
|
|
458
|
+
const { symbol, exchange } = listing.request;
|
|
356
459
|
const context = { cacheMode: ctx.cliOptions.refresh ? "refresh" as const : "default" as const };
|
|
357
|
-
const
|
|
358
|
-
?
|
|
359
|
-
:
|
|
360
|
-
const
|
|
361
|
-
|
|
460
|
+
const load = () => market.dataProvider.getPriceHistoryWithMetadata
|
|
461
|
+
? market.dataProvider.getPriceHistoryWithMetadata(symbol, exchange, range, context)
|
|
462
|
+
: market.dataProvider.getPriceHistory(symbol, exchange, range, context).then((points) => ({ points, resolution: null }));
|
|
463
|
+
const [{ points, resolution }, quote] = await Promise.all([
|
|
464
|
+
loadForListing(listing, market, ctx, load, (loaded) => loaded.points.length === 0)
|
|
465
|
+
.catch((error) => failHistory(error, listing.key, ctx)),
|
|
466
|
+
loadListingQuote(market.dataProvider, listing),
|
|
467
|
+
]);
|
|
468
|
+
const identity = listingIdentity(listing, quote);
|
|
469
|
+
// Without a quote currency, the listing metadata research reads (as `ticker` does) may still state it.
|
|
470
|
+
const listed = quote?.currency ? quote : await market.dataProvider.getQuoteMetadata?.(symbol, exchange).catch(() => null);
|
|
471
|
+
const unit = historyUnit(listing.symbol, listed ?? quote);
|
|
472
|
+
const data = historyRows(points, resolution, unit.currency);
|
|
473
|
+
const interval = data[0]?.interval ?? null;
|
|
474
|
+
const decimals = historyPriceDecimals(data, listing.saved?.metadata.assetCategory);
|
|
362
475
|
const price = (value: unknown) => typeof value === "number" ? value.toFixed(decimals) : "";
|
|
363
476
|
// Intraday bars print in UTC, as the charts and time and sales label them, not the host zone.
|
|
364
477
|
const intraday = data.some((row) => row.date.length > 10);
|
|
365
|
-
|
|
478
|
+
// A bar history: dated by its last bar, stale once bars of its size stop arriving.
|
|
479
|
+
const freshness = rowsFreshness(data, {
|
|
480
|
+
...barHistoryFreshness(intraday ? null : barResolutionFromDates(data.map((row) => row.date))),
|
|
481
|
+
observedKey: "date",
|
|
482
|
+
oldest: null,
|
|
483
|
+
});
|
|
484
|
+
const notes = [...historyNotes(range, interval, data[0]?.date), historyFlagNote(data) ?? []].flat();
|
|
485
|
+
const priceColumns: CliResultColumn[] = [
|
|
486
|
+
intraday
|
|
487
|
+
? { key: "date", header: "Time", format: (value) => typeof value === "string" ? formatUtcTime(value) : "" }
|
|
488
|
+
: { key: "date", header: "Date" },
|
|
489
|
+
{ key: "open", header: "Open", align: "right", format: price },
|
|
490
|
+
{ key: "high", header: "High", align: "right", format: price },
|
|
491
|
+
{ key: "low", header: "Low", align: "right", format: price },
|
|
492
|
+
{ key: "close", header: "Close", align: "right", format: price },
|
|
493
|
+
{ key: "volume", header: "Volume", align: "right", format: formatCountCell },
|
|
494
|
+
];
|
|
495
|
+
// Text shows a flag only on a bar that has one; the column is dropped when none does.
|
|
496
|
+
const flagColumn: CliResultColumn = {
|
|
497
|
+
key: "flag", header: "Flag", format: (value) => typeof value === "string" ? cliStyles.warning(value) : "",
|
|
498
|
+
};
|
|
499
|
+
ctx.printResult({
|
|
500
|
+
data,
|
|
501
|
+
metadata: {
|
|
502
|
+
...listingMetadata(identity),
|
|
503
|
+
range,
|
|
504
|
+
resolution,
|
|
505
|
+
requestedRange: range,
|
|
506
|
+
currency: unit.currency,
|
|
507
|
+
unit: unit.unit,
|
|
508
|
+
interval,
|
|
509
|
+
firstDate: data[0]?.date ?? null,
|
|
510
|
+
lastDate: data.at(-1)?.date ?? null,
|
|
511
|
+
bars: data.length,
|
|
512
|
+
asOf: freshness?.asOf ?? null,
|
|
513
|
+
},
|
|
514
|
+
...(notes.length > 0 ? { warnings: notes } : {}),
|
|
515
|
+
freshness,
|
|
516
|
+
}, {
|
|
517
|
+
heading: `${listingHeading(identity)}\n${cliStyles.muted(historyFacts(unit, data).join(" · "))}`,
|
|
518
|
+
textColumns: [...priceColumns, flagColumn],
|
|
519
|
+
// Every exported row says its currency and bar size, so it survives head and concatenation.
|
|
366
520
|
columns: [
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
{ key: "high", header: "High", align: "right", format: price },
|
|
372
|
-
{ key: "low", header: "Low", align: "right", format: price },
|
|
373
|
-
{ key: "close", header: "Close", align: "right", format: price },
|
|
374
|
-
{ key: "volume", header: "Volume", align: "right", format: formatCountCell },
|
|
521
|
+
...priceColumns,
|
|
522
|
+
{ key: "currency", header: "Currency" },
|
|
523
|
+
{ key: "interval", header: "Interval" },
|
|
524
|
+
flagColumn,
|
|
375
525
|
],
|
|
376
526
|
});
|
|
377
527
|
});
|
|
@@ -379,46 +529,84 @@ async function runHistory(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
379
529
|
|
|
380
530
|
type FinancialsView = "statements" | "fundamentals" | "valuation";
|
|
381
531
|
|
|
532
|
+
const STATEMENT_COLUMNS: CliResultColumn<ReturnType<typeof financialStatementRows>[number]>[] = [
|
|
533
|
+
{ key: "date", header: "Date" },
|
|
534
|
+
{ key: "revenue", header: "Revenue", align: "right", format: (value) => value == null ? "" : formatCompact(Number(value)) },
|
|
535
|
+
{ key: "grossProfit", header: "Gross", align: "right", format: (value) => value == null ? "" : formatCompact(Number(value)) },
|
|
536
|
+
{ key: "operatingIncome", header: "Op Inc", align: "right", format: (value) => value == null ? "" : formatCompact(Number(value)) },
|
|
537
|
+
{ key: "netIncome", header: "Net Inc", align: "right", format: (value) => value == null ? "" : formatCompact(Number(value)) },
|
|
538
|
+
{ key: "eps", header: "EPS", align: "right", format: (value) => value == null ? "" : formatPerShareNumber(Number(value)) },
|
|
539
|
+
{ key: "currency", header: "Cur" },
|
|
540
|
+
];
|
|
541
|
+
|
|
382
542
|
async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1], view: FinancialsView) {
|
|
383
543
|
const args = [...rawArgs];
|
|
384
|
-
const
|
|
544
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
545
|
+
const sectionFlag = args.some((arg) => arg === "--section" || arg.startsWith("--section="));
|
|
546
|
+
const section = takeOption(args, "--section");
|
|
385
547
|
const commandName = view === "statements" ? "financials" : view;
|
|
386
|
-
const
|
|
548
|
+
const tabular = ctx.cliOptions.format === "csv" || ctx.cliOptions.format === "ndjson";
|
|
549
|
+
if (sectionFlag && !tabular) ctx.fail("--section picks one table of --csv or --ndjson output.");
|
|
550
|
+
if (sectionFlag && !section?.trim()) ctx.fail("--section needs a section title or number.");
|
|
551
|
+
const raw = requireOneArg(args, `${commandName} <symbol>`, "symbol", ctx);
|
|
552
|
+
const selectTables = (tables: CliReportTables) => {
|
|
553
|
+
try {
|
|
554
|
+
return selectReportTables(tables, section);
|
|
555
|
+
} catch (error) {
|
|
556
|
+
return ctx.fail(error instanceof Error ? error.message : String(error));
|
|
557
|
+
}
|
|
558
|
+
};
|
|
387
559
|
await withMarketData(ctx, async (market) => {
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
560
|
+
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
561
|
+
const financials = await loadForListing(listing, market, ctx, () => market.dataProvider.getTickerFinancials(
|
|
562
|
+
listing.request.symbol, listing.request.exchange, { cacheMode: ctx.cliOptions.refresh ? "refresh" : "default" },
|
|
563
|
+
));
|
|
564
|
+
const identity = listingIdentity(listing, financials.quote);
|
|
391
565
|
const data: FinancialsCliData = {
|
|
392
|
-
symbol,
|
|
393
|
-
exchange,
|
|
566
|
+
symbol: listing.key,
|
|
567
|
+
exchange: identity.exchange,
|
|
394
568
|
providerId: financials.quote?.providerId ?? null,
|
|
395
569
|
...financials,
|
|
396
570
|
};
|
|
397
571
|
if (view !== "statements") {
|
|
398
|
-
|
|
572
|
+
const freshness = fundamentalsFreshness(financials);
|
|
573
|
+
ctx.printResult({
|
|
574
|
+
// JSON reads a multiple over a loss as null with its reason, never as a number.
|
|
575
|
+
data: { ...data, fundamentals: exportedFundamentals(data.fundamentals) },
|
|
576
|
+
freshness,
|
|
577
|
+
}, {
|
|
578
|
+
text: () => renderFundamentalsReport(data, view),
|
|
579
|
+
...(tabular ? { tables: selectTables(fundamentalsReportTables(data, view, freshness)) } : {}),
|
|
580
|
+
});
|
|
399
581
|
return;
|
|
400
582
|
}
|
|
583
|
+
const rows = financialStatementRows(data);
|
|
584
|
+
const freshness = rowsFreshness(rows, {
|
|
585
|
+
...REPORTED_DATA, basis: "financial statements", observedKey: "date", oldest: null,
|
|
586
|
+
});
|
|
587
|
+
// NDJSON keeps the raw statement rows it always wrote; CSV gets the table and its closing lines.
|
|
588
|
+
const tables = tabular
|
|
589
|
+
? selectTables({
|
|
590
|
+
tables: [exportRowsTable("Annual statements", STATEMENT_COLUMNS, rows)],
|
|
591
|
+
footer: reportFooterLines({ freshness }),
|
|
592
|
+
})
|
|
593
|
+
: undefined;
|
|
401
594
|
ctx.printResult({
|
|
402
595
|
data,
|
|
403
596
|
metadata: {
|
|
404
|
-
|
|
597
|
+
...listingMetadata(identity),
|
|
405
598
|
providerId: financials.quote?.providerId,
|
|
406
599
|
annualStatements: financials.annualStatements.length,
|
|
407
600
|
quarterlyStatements: financials.quarterlyStatements.length,
|
|
408
|
-
fundamentals: financials.fundamentals,
|
|
601
|
+
fundamentals: exportedFundamentals(financials.fundamentals),
|
|
409
602
|
profile: financials.profile,
|
|
410
603
|
},
|
|
604
|
+
freshness,
|
|
411
605
|
}, {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
{ key: "grossProfit", header: "Gross", align: "right", value: (row) => row.grossProfit == null ? "" : formatCompact(Number(row.grossProfit)) },
|
|
417
|
-
{ key: "operatingIncome", header: "Op Inc", align: "right", value: (row) => row.operatingIncome == null ? "" : formatCompact(Number(row.operatingIncome)) },
|
|
418
|
-
{ key: "netIncome", header: "Net Inc", align: "right", value: (row) => row.netIncome == null ? "" : formatCompact(Number(row.netIncome)) },
|
|
419
|
-
{ key: "eps", header: "EPS", align: "right", format: (value) => value == null ? "" : formatPerShareNumber(Number(value)) },
|
|
420
|
-
{ key: "currency", header: "Cur" },
|
|
421
|
-
],
|
|
606
|
+
heading: listingHeading(identity),
|
|
607
|
+
rows: () => rows,
|
|
608
|
+
columns: STATEMENT_COLUMNS,
|
|
609
|
+
...(tables && ctx.cliOptions.format === "csv" ? { tables } : {}),
|
|
422
610
|
});
|
|
423
611
|
});
|
|
424
612
|
}
|
|
@@ -426,24 +614,40 @@ async function runFinancials(rawArgs: string[], ctx: Parameters<CliCommandDef["e
|
|
|
426
614
|
async function runNews(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
427
615
|
const args = [...rawArgs];
|
|
428
616
|
const feed = parseNewsFeed(takeOption(args, "--feed"));
|
|
429
|
-
const
|
|
617
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
618
|
+
if (exchangeOption && !args[0]) ctx.fail("--exchange needs a symbol: gloomberb news <symbol> --exchange <code>");
|
|
619
|
+
rejectExtraArgs(args, 1, { usage: "news [symbol] [--feed <feed>]", takes: "one symbol at most", advice: "Run it once per symbol." }, ctx);
|
|
430
620
|
await withMarketData(ctx, async (market) => {
|
|
621
|
+
const listing = args[0] ? await requireCliListing(args[0], exchangeOption, market, ctx) : null;
|
|
431
622
|
const limit = ctx.cliOptions.limit ?? 20;
|
|
432
|
-
const
|
|
433
|
-
feed: feed ?? (
|
|
623
|
+
const loadNews = () => market.dataProvider.getNews({
|
|
624
|
+
feed: feed ?? (listing ? "ticker" : "latest"),
|
|
434
625
|
// Still set for news plugins that read the deprecated scope.
|
|
435
|
-
scope:
|
|
436
|
-
ticker,
|
|
626
|
+
scope: listing ? "ticker" : "global",
|
|
627
|
+
ticker: listing?.request.symbol,
|
|
628
|
+
exchange: listing?.request.exchange || undefined,
|
|
437
629
|
limit,
|
|
438
630
|
});
|
|
439
|
-
|
|
631
|
+
const [articles, quote] = await Promise.all([
|
|
632
|
+
listing ? loadForListing(listing, market, ctx, loadNews, (found) => found.length === 0) : loadNews(),
|
|
633
|
+
listing ? loadListingQuote(market.dataProvider, listing) : null,
|
|
634
|
+
]);
|
|
635
|
+
const identity = listing ? listingIdentity(listing, quote) : null;
|
|
636
|
+
ctx.printResult({
|
|
637
|
+
data: articles,
|
|
638
|
+
metadata: { ticker: listing?.key ?? null, ...(identity ? listingMetadata(identity) : {}), feed: feed ?? null },
|
|
639
|
+
freshness: rowsFreshness(newsRows(articles), {
|
|
640
|
+
status: "not-a-feed", basis: "published stories", observedKey: "publishedAt", oldest: null,
|
|
641
|
+
}),
|
|
642
|
+
}, {
|
|
643
|
+
...(identity ? { heading: listingHeading(identity) } : {}),
|
|
440
644
|
rows: newsRows,
|
|
441
645
|
columns: [
|
|
442
|
-
// UTC, as
|
|
646
|
+
// UTC with the zone named, as every CLI time prints, rather than the host zone unlabeled.
|
|
443
647
|
{
|
|
444
648
|
key: "publishedAt",
|
|
445
|
-
header: "Published
|
|
446
|
-
format: (value) => typeof value === "string" ? value
|
|
649
|
+
header: "Published",
|
|
650
|
+
format: (value) => typeof value === "string" ? formatUtcTime(value) : "",
|
|
447
651
|
},
|
|
448
652
|
{ key: "source", header: "Source", maxWidth: 20 },
|
|
449
653
|
{ key: "title", header: "Title" },
|
|
@@ -454,22 +658,67 @@ async function runNews(rawArgs: string[], ctx: Parameters<CliCommandDef["execute
|
|
|
454
658
|
});
|
|
455
659
|
}
|
|
456
660
|
|
|
661
|
+
const FILING_COLUMNS = [
|
|
662
|
+
{ key: "filingDate", header: "Date" },
|
|
663
|
+
{ key: "form", header: "Form" },
|
|
664
|
+
{ key: "companyName", header: "Company", maxWidth: 24 },
|
|
665
|
+
{ key: "url", header: "URL", optional: true },
|
|
666
|
+
];
|
|
667
|
+
|
|
668
|
+
/** The US listing the SEC files a symbol under, from the symbol's venues: NYSE for SAN's Banco Santander. */
|
|
669
|
+
async function registrantUsExchange(market: MarketContext, symbol: string, registrantName: string): Promise<string | null> {
|
|
670
|
+
const venues = (await listingVenues(symbol, market).catch(() => []))
|
|
671
|
+
.filter((venue) => !nonUsSecListingVenue(symbol, venue.exchange) && !areDifferentCompanies(venue.name, registrantName));
|
|
672
|
+
return (venues.find((venue) => isUsListingExchange(venue.exchange)) ?? venues[0])?.exchange ?? null;
|
|
673
|
+
}
|
|
674
|
+
|
|
457
675
|
async function runFilings(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
458
676
|
const args = [...rawArgs];
|
|
459
677
|
const count = parsePositiveInt(takeOption(args, "--count"), ctx.cliOptions.limit ?? 15, "Count", ctx);
|
|
460
|
-
const
|
|
461
|
-
const
|
|
678
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
679
|
+
const form = takeOption(args, "--form")?.trim() || null;
|
|
680
|
+
const raw = requireOneArg(args, "filings <symbol> [--count <n>] [--form <form>]", "symbol", ctx);
|
|
462
681
|
await withMarketData(ctx, async (market) => {
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
682
|
+
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
683
|
+
const { symbol, exchange } = listing.request;
|
|
684
|
+
// A listing outside the US sends its company to the lookup, which needs its quote first.
|
|
685
|
+
const quotePromise = loadListingQuote(market.dataProvider, listing);
|
|
686
|
+
const identity = nonUsSecListingVenue(symbol, exchange) ? listingIdentity(listing, await quotePromise) : null;
|
|
687
|
+
try {
|
|
688
|
+
const context = identity?.name ? { listingName: identity.name } : undefined;
|
|
689
|
+
const [filings, quote] = await Promise.all([
|
|
690
|
+
loadForListing(listing, market, ctx, () => form
|
|
691
|
+
// A form filter searches every filing the service lists for the issuer, as the SEC pane does.
|
|
692
|
+
? market.dataProvider.getSecFilings(symbol, SEC_FILING_FETCH_LIMIT, exchange, context)
|
|
693
|
+
.then((all) => all.filter((filing) => filingFormMatches(filing.form, form)).slice(0, count))
|
|
694
|
+
: market.dataProvider.getSecFilings(symbol, count, exchange, context),
|
|
695
|
+
(found) => found.length === 0),
|
|
696
|
+
quotePromise,
|
|
697
|
+
]);
|
|
698
|
+
const resolved = identity ?? listingIdentity(listing, quote);
|
|
699
|
+
ctx.printResult({
|
|
700
|
+
data: filings,
|
|
701
|
+
metadata: { ...listingMetadata(resolved), ...(form ? { form } : {}) },
|
|
702
|
+
freshness: rowsFreshness(filingRows(filings), { ...SEC_FILINGS, observedKey: "filingDate" }),
|
|
703
|
+
}, {
|
|
704
|
+
heading: listingHeading(resolved),
|
|
705
|
+
rows: filingRows,
|
|
706
|
+
columns: FILING_COLUMNS,
|
|
707
|
+
empty: form ? `No ${form} filings found for ${listingTitle(resolved)}.` : `No SEC filings found for ${listingTitle(resolved)}.`,
|
|
708
|
+
});
|
|
709
|
+
} catch (error) {
|
|
710
|
+
if (!(error instanceof SecRegistrantMismatchError)) throw error;
|
|
711
|
+
// Another company's filings never show under this listing; say whose they were.
|
|
712
|
+
const message = secRegistrantMismatchMessage(
|
|
713
|
+
error.listing, error.registrantName, await registrantUsExchange(market, error.listing.symbol, error.registrantName),
|
|
714
|
+
);
|
|
715
|
+
const resolved = identity ?? listingIdentity(listing, await quotePromise);
|
|
716
|
+
ctx.printResult({
|
|
717
|
+
data: [] as SecFilingItem[],
|
|
718
|
+
metadata: { ...listingMetadata(resolved), secRegistrant: error.registrantName },
|
|
719
|
+
warnings: ctx.cliOptions.format === "text" ? undefined : [message],
|
|
720
|
+
}, { rows: filingRows, columns: FILING_COLUMNS, empty: message });
|
|
721
|
+
}
|
|
473
722
|
});
|
|
474
723
|
}
|
|
475
724
|
|
|
@@ -487,6 +736,52 @@ function insiderSummary(data: HolderData, ownerTypes: Set<string>): string {
|
|
|
487
736
|
return [share, transactions].filter(Boolean).join("\n");
|
|
488
737
|
}
|
|
489
738
|
|
|
739
|
+
/** `holders --form 13d|13g|all`: the 13D/13G beneficial owners, joined by name to the 13F holders. */
|
|
740
|
+
async function printBeneficialOwners(
|
|
741
|
+
listing: CliListing,
|
|
742
|
+
market: MarketContext,
|
|
743
|
+
form: Exclude<HolderForm, "13f">,
|
|
744
|
+
history: boolean,
|
|
745
|
+
ctx: Parameters<CliCommandDef["execute"]>[1],
|
|
746
|
+
) {
|
|
747
|
+
const { symbol, exchange } = listing.request;
|
|
748
|
+
const [payload, holders, quote] = await Promise.all([
|
|
749
|
+
loadForListing(listing, market, ctx, () => fetchBeneficialOwners(symbol, { form: beneficialRouteForm(form), history })),
|
|
750
|
+
market.dataProvider.getHolders?.(symbol, exchange).catch(() => null) ?? null,
|
|
751
|
+
loadListingQuote(market.dataProvider, listing),
|
|
752
|
+
]);
|
|
753
|
+
const identity = listingIdentity(listing, quote);
|
|
754
|
+
const rows = buildBeneficialReportRows(payload, { history, holders });
|
|
755
|
+
const notices = beneficialCoverageNotices(payload.coverage);
|
|
756
|
+
ctx.printResult({
|
|
757
|
+
data: rows,
|
|
758
|
+
...(notices.length ? { warnings: notices } : {}),
|
|
759
|
+
metadata: {
|
|
760
|
+
...listingMetadata(identity),
|
|
761
|
+
name: identity.name ?? (payload.companyName || null),
|
|
762
|
+
cik: payload.cik || null,
|
|
763
|
+
form,
|
|
764
|
+
history,
|
|
765
|
+
asOf: payload.asOf,
|
|
766
|
+
coverage: payload.coverage,
|
|
767
|
+
complete: beneficialListComplete(payload),
|
|
768
|
+
},
|
|
769
|
+
}, {
|
|
770
|
+
heading: `${listingHeading(identity)}${cliStyles.muted(beneficialListFacts(payload, form, rows.length, history).map((fact) => ` · ${fact}`).join(""))}`,
|
|
771
|
+
textColumns: BENEFICIAL_REPORT_COLUMNS,
|
|
772
|
+
columns: [
|
|
773
|
+
...BENEFICIAL_REPORT_COLUMNS,
|
|
774
|
+
{ key: "status", header: "Status" },
|
|
775
|
+
{ key: "filerCik", header: "Filer CIK" },
|
|
776
|
+
{ key: "accessionNumber", header: "Accession" },
|
|
777
|
+
{ key: "filingUrl", header: "URL" },
|
|
778
|
+
],
|
|
779
|
+
empty: beneficialListUnreadable(payload)
|
|
780
|
+
? `13D/13G filings for ${listingTitle(identity)} are listed but could not be read.`
|
|
781
|
+
: `No 13D/13G filings in the last 4 years for ${listingTitle(identity)}.`,
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
|
|
490
785
|
async function runHolders(
|
|
491
786
|
rawArgs: string[],
|
|
492
787
|
ctx: Parameters<CliCommandDef["execute"]>[1],
|
|
@@ -494,43 +789,112 @@ async function runHolders(
|
|
|
494
789
|
ownerTypes?: Set<string>,
|
|
495
790
|
) {
|
|
496
791
|
const args = [...rawArgs];
|
|
497
|
-
const
|
|
498
|
-
const
|
|
792
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
793
|
+
const formOption = commandName === "holders" ? takeOption(args, "--form") : undefined;
|
|
794
|
+
const history = commandName === "holders" && takeFlag(args, "--history");
|
|
795
|
+
const raw = requireOneArg(args, `${commandName} <symbol>`, "symbol", ctx);
|
|
796
|
+
const form = formOption == null ? "13f" : parseHolderForm(formOption);
|
|
797
|
+
if (!form) ctx.fail(`Unknown form "${formOption}".`, `Use one of ${HOLDER_FORMS.join(", ")}.`);
|
|
798
|
+
if (form === "13f" && history) ctx.fail("--history lists 13D/13G reports.", "Add --form 13d, 13g or all.");
|
|
499
799
|
await withMarketData(ctx, async (market) => {
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
|
|
800
|
+
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
801
|
+
if (form !== "13f") return printBeneficialOwners(listing, market, form, history, ctx);
|
|
802
|
+
const [data, quote] = await Promise.all([
|
|
803
|
+
loadForListing(
|
|
804
|
+
listing, market, ctx,
|
|
805
|
+
() => market.dataProvider.getHolders(listing.request.symbol, listing.request.exchange),
|
|
806
|
+
(found) => found.holders.length === 0,
|
|
807
|
+
),
|
|
808
|
+
loadListingQuote(market.dataProvider, listing),
|
|
809
|
+
]);
|
|
810
|
+
const identity = listingIdentity(listing, quote);
|
|
811
|
+
const rows = holderRows(data, ownerTypes);
|
|
812
|
+
const limit = ctx.cliOptions.limit;
|
|
813
|
+
const shown = limit == null ? rows.length : Math.min(limit, rows.length);
|
|
814
|
+
const institutional = !ownerTypes?.has("insider");
|
|
815
|
+
const total = institutional ? data.summary?.institutionsCount ?? null : null;
|
|
816
|
+
const reportDate = sharedReportDate(rows);
|
|
817
|
+
// A London line's values can be dollars from the 13F filings; the listing's currency is not their unit.
|
|
818
|
+
const valueCurrency = holderValueCurrency(data);
|
|
819
|
+
const valueBasis = rows.length > 0 ? holderValueBasis(reportDate, data.valueBasis, valueCurrency) : null;
|
|
820
|
+
const positionsBasis = rows.length > 0 ? nonUsHolderCaveat(identity.exchange || data.exchange, data.currency) : null;
|
|
821
|
+
const shareBasisNote = holderShareBasisNote(data, rows);
|
|
822
|
+
const markedRows = rows.some((row) => holderShareBasisMarker(row));
|
|
823
|
+
// The heading names the listing; its unit, date and how much of the list follows on the same line.
|
|
824
|
+
const facts = holderListFacts({
|
|
825
|
+
currency: valueCurrency, listingCurrency: data.currency, asOf: data.asOf, shown, reported: rows.length, total,
|
|
826
|
+
});
|
|
827
|
+
ctx.printResult({
|
|
828
|
+
data,
|
|
829
|
+
metadata: {
|
|
830
|
+
...listingMetadata(identity),
|
|
831
|
+
summary: data.summary,
|
|
832
|
+
currency: data.currency ?? null,
|
|
833
|
+
valueCurrency: valueCurrency ?? null,
|
|
834
|
+
asOf: data.asOf ?? null,
|
|
835
|
+
shown,
|
|
836
|
+
reported: rows.length,
|
|
837
|
+
total,
|
|
838
|
+
truncated: shown < (total ?? rows.length),
|
|
839
|
+
valueBasis,
|
|
840
|
+
positionsBasis,
|
|
841
|
+
},
|
|
842
|
+
}, {
|
|
843
|
+
heading: `${listingHeading(identity)}${cliStyles.muted(facts.map((fact) => ` · ${fact}`).join(""))}`,
|
|
844
|
+
rows: () => rows,
|
|
503
845
|
columns: [
|
|
504
846
|
{ key: "type", header: "Type" },
|
|
505
847
|
{ key: "name", header: "Holder" },
|
|
506
848
|
{ key: "reportDate", header: "Date" },
|
|
507
849
|
{ key: "shares", header: "Shares", align: "right", format: formatCountCell },
|
|
508
|
-
|
|
509
|
-
{ key: "
|
|
850
|
+
// Marks the rows of a home line held as receipts; absent when no row is.
|
|
851
|
+
...(markedRows ? [{ key: "shareBasis", header: "Basis", value: (row: Record<string, unknown>) => holderShareBasisMarker(row) }] : []),
|
|
852
|
+
{
|
|
853
|
+
key: "value",
|
|
854
|
+
header: moneyColumnHeader("Value", valueCurrency),
|
|
855
|
+
align: "right",
|
|
856
|
+
value: (row) => row.value == null ? "" : formatCompact(Number(row.value)),
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
key: "percentHeld",
|
|
860
|
+
header: "% Held",
|
|
861
|
+
align: "right",
|
|
862
|
+
format: (value) => isFiniteNumber(value) ? formatHolderOwnershipPercent(value) : "",
|
|
863
|
+
},
|
|
510
864
|
],
|
|
511
|
-
|
|
512
|
-
? {
|
|
513
|
-
:
|
|
514
|
-
|
|
865
|
+
summary: (holderData: HolderData) => [
|
|
866
|
+
[valueBasis ? `Value = ${valueBasis}.` : "", positionsBasis ?? "", shareBasisNote ?? ""].filter(Boolean).join(" "),
|
|
867
|
+
commandName === "insider" && ownerTypes ? insiderSummary(holderData, ownerTypes) : "",
|
|
868
|
+
].filter(Boolean).join("\n"),
|
|
869
|
+
empty: `No holders reported for ${listingTitle(identity)}.`,
|
|
515
870
|
});
|
|
516
871
|
});
|
|
517
872
|
}
|
|
518
873
|
|
|
519
874
|
async function runAnalyst(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
520
875
|
const args = [...rawArgs];
|
|
521
|
-
const
|
|
522
|
-
const
|
|
876
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
877
|
+
const raw = requireOneArg(args, "analyst <symbol>", "symbol", ctx);
|
|
523
878
|
await withMarketData(ctx, async (market) => {
|
|
524
|
-
const
|
|
879
|
+
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
880
|
+
const [data, quote] = await Promise.all([
|
|
881
|
+
loadForListing(listing, market, ctx, () => market.dataProvider.getAnalystResearch(listing.request.symbol, listing.request.exchange)),
|
|
882
|
+
loadListingQuote(market.dataProvider, listing),
|
|
883
|
+
]);
|
|
884
|
+
const identity = listingIdentity(listing, quote);
|
|
525
885
|
ctx.printResult({
|
|
526
886
|
data,
|
|
527
887
|
metadata: {
|
|
528
|
-
|
|
888
|
+
...listingMetadata(identity),
|
|
529
889
|
recommendationRating: data.recommendationRating,
|
|
530
890
|
priceTarget: data.priceTarget,
|
|
531
891
|
recommendations: data.recommendations,
|
|
532
892
|
},
|
|
893
|
+
freshness: rowsFreshness(analystRows(data), {
|
|
894
|
+
...REPORTED_DATA, basis: "analyst ratings", observedKey: "date", oldest: null,
|
|
895
|
+
}, { stale: data.stale === true }),
|
|
533
896
|
}, {
|
|
897
|
+
heading: listingHeading(identity),
|
|
534
898
|
rows: analystRows,
|
|
535
899
|
summary: analystSummary,
|
|
536
900
|
columns: [
|
|
@@ -546,11 +910,23 @@ async function runAnalyst(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
546
910
|
|
|
547
911
|
async function runEvents(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
548
912
|
const args = [...rawArgs];
|
|
549
|
-
const
|
|
550
|
-
const
|
|
913
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
914
|
+
const raw = requireOneArg(args, "events <symbol>", "symbol", ctx);
|
|
551
915
|
await withMarketData(ctx, async (market) => {
|
|
552
|
-
const
|
|
553
|
-
|
|
916
|
+
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
917
|
+
const [data, quote] = await Promise.all([
|
|
918
|
+
loadForListing(listing, market, ctx, () => market.dataProvider.getCorporateActions(listing.request.symbol, listing.request.exchange)),
|
|
919
|
+
loadListingQuote(market.dataProvider, listing),
|
|
920
|
+
]);
|
|
921
|
+
const identity = listingIdentity(listing, quote);
|
|
922
|
+
ctx.printResult({
|
|
923
|
+
data,
|
|
924
|
+
metadata: listingMetadata(identity),
|
|
925
|
+
freshness: rowsFreshness(corporateActionRows(data), {
|
|
926
|
+
...REPORTED_DATA, basis: "corporate actions", observedKey: "date", oldest: null,
|
|
927
|
+
}),
|
|
928
|
+
}, {
|
|
929
|
+
heading: listingHeading(identity),
|
|
554
930
|
rows: corporateActionRows,
|
|
555
931
|
columns: [
|
|
556
932
|
{ key: "date", header: "Date" },
|
|
@@ -564,22 +940,38 @@ async function runEvents(rawArgs: string[], ctx: Parameters<CliCommandDef["execu
|
|
|
564
940
|
async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
565
941
|
const args = [...rawArgs];
|
|
566
942
|
const expiration = takeOption(args, "--expiration");
|
|
567
|
-
const
|
|
568
|
-
const
|
|
943
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
944
|
+
const raw = requireOneArg(args, "options <symbol> [--expiration <unix>]", "symbol", ctx);
|
|
569
945
|
await withMarketData(ctx, async (market) => {
|
|
946
|
+
const listing = await requireCliListing(raw, exchangeOption, market, ctx);
|
|
947
|
+
const { symbol, exchange } = listing.request;
|
|
570
948
|
const expirationDate = expiration == null ? undefined : Number(expiration);
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
949
|
+
const quotePromise = loadListingQuote(market.dataProvider, listing);
|
|
950
|
+
const { result, chain } = await loadForListing(listing, market, ctx, async () => {
|
|
951
|
+
const cached = await market.dataProvider.getCachedQuery?.("getOptionsChain", [symbol, exchange, expirationDate, undefined])
|
|
952
|
+
.load({ force: ctx.cliOptions.refresh });
|
|
953
|
+
return {
|
|
954
|
+
result: cached,
|
|
955
|
+
chain: cached?.value ?? await market.dataProvider.getOptionsChain(symbol, exchange, expirationDate, {
|
|
956
|
+
cacheMode: ctx.cliOptions.refresh ? "refresh" : "default",
|
|
957
|
+
}),
|
|
958
|
+
};
|
|
575
959
|
});
|
|
960
|
+
const identity = listingIdentity(listing, await quotePromise);
|
|
576
961
|
// A failed refresh falls back to the stored chain, which can be days old.
|
|
577
962
|
const refreshWarning = result?.refreshError == null ? null
|
|
578
963
|
: `Options refresh failed; showing the chain stored ${new Date(result.fetchedAt).toISOString()}`
|
|
579
964
|
+ (chain.asOf ? ` (last trade ${chain.asOf})` : "");
|
|
580
|
-
const sessionWarning = refreshWarning ? null : priorSessionChainWarning(chain, exchange, Date.now());
|
|
965
|
+
const sessionWarning = refreshWarning ? null : priorSessionChainWarning(chain, identity.exchange, Date.now());
|
|
581
966
|
const warnings = refreshWarning ? [refreshWarning] : sessionWarning ? [sessionWarning] : undefined;
|
|
582
|
-
|
|
967
|
+
// Dated by the chain's last trade; a chain that failed to refresh is the stored one, stale.
|
|
968
|
+
const freshness = rowsFreshness([], { asOf: chain.asOf ?? null }, {
|
|
969
|
+
...(chain.dataSource ? { dataSource: chain.dataSource } : {}),
|
|
970
|
+
...(chain.delayMinutes != null ? { delayMinutes: chain.delayMinutes } : {}),
|
|
971
|
+
stale: refreshWarning != null,
|
|
972
|
+
});
|
|
973
|
+
ctx.printResult({ data: chain, metadata: { ...listingMetadata(identity), expirations: chain.expirationDates }, warnings, freshness }, {
|
|
974
|
+
heading: listingHeading(identity),
|
|
583
975
|
rows: optionRows,
|
|
584
976
|
columns: [
|
|
585
977
|
{ key: "side", header: "Side" },
|
|
@@ -596,8 +988,10 @@ async function runOptions(rawArgs: string[], ctx: Parameters<CliCommandDef["exec
|
|
|
596
988
|
});
|
|
597
989
|
}
|
|
598
990
|
|
|
991
|
+
const FX_USAGE = "fx <currency>";
|
|
992
|
+
|
|
599
993
|
async function runFx(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
600
|
-
const currency =
|
|
994
|
+
const currency = requireOneArg(rawArgs.map((arg) => arg.trim().toUpperCase()), FX_USAGE, "currency", ctx);
|
|
601
995
|
await withMarketData(ctx, async (market) => {
|
|
602
996
|
const baseCurrency = market.config.baseCurrency.trim().toUpperCase();
|
|
603
997
|
const load = (code: string) => market.dataProvider.getCachedQuery("getExchangeRate", [code])
|
|
@@ -619,9 +1013,10 @@ async function runFx(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]
|
|
|
619
1013
|
...(asOf || stale ? [{
|
|
620
1014
|
key: "asOf",
|
|
621
1015
|
header: "As Of",
|
|
622
|
-
format: (value: unknown, row: { stale: boolean }) =>
|
|
623
|
-
|
|
624
|
-
|
|
1016
|
+
format: (value: unknown, row: { stale: boolean }) => {
|
|
1017
|
+
const time = typeof value === "string" ? formatUtcTime(value) : "";
|
|
1018
|
+
return row.stale ? cliStyles.warning(`${time} stale`.trim()) : time;
|
|
1019
|
+
},
|
|
625
1020
|
}] : []),
|
|
626
1021
|
],
|
|
627
1022
|
});
|
|
@@ -629,11 +1024,23 @@ async function runFx(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]
|
|
|
629
1024
|
}
|
|
630
1025
|
|
|
631
1026
|
async function runEarnings(rawArgs: string[], ctx: Parameters<CliCommandDef["execute"]>[1]) {
|
|
632
|
-
const
|
|
1027
|
+
const args = [...rawArgs];
|
|
1028
|
+
const exchangeOption = takeOption(args, "--exchange");
|
|
1029
|
+
const symbols = normalizeSymbols(args);
|
|
633
1030
|
if (symbols.length === 0) ctx.fail("Usage: gloomberb earnings <symbol...>");
|
|
634
1031
|
await withCliServices(ctx, async (services) => {
|
|
635
|
-
const
|
|
636
|
-
|
|
1032
|
+
const listings = await Promise.all(symbols.map((symbol) => requireCliListing(
|
|
1033
|
+
symbol, exchangeOption, services, ctx, { ownExchangeWins: symbols.length > 1 },
|
|
1034
|
+
)));
|
|
1035
|
+
const events = await loadForListing(
|
|
1036
|
+
listings, services, ctx,
|
|
1037
|
+
() => services.dataProvider.getEarningsCalendar(listings.map((listing) => listing.key)),
|
|
1038
|
+
(found) => found.length === 0,
|
|
1039
|
+
);
|
|
1040
|
+
ctx.printResult({
|
|
1041
|
+
data: events,
|
|
1042
|
+
freshness: rowsFreshness(earningsRows(events), { status: "not-a-feed", basis: "calendar", observedKey: "date", oldest: null }),
|
|
1043
|
+
}, {
|
|
637
1044
|
rows: earningsRows,
|
|
638
1045
|
columns: [
|
|
639
1046
|
{ key: "date", header: "Date" },
|
|
@@ -647,7 +1054,7 @@ async function runEarnings(rawArgs: string[], ctx: Parameters<CliCommandDef["exe
|
|
|
647
1054
|
});
|
|
648
1055
|
}
|
|
649
1056
|
|
|
650
|
-
export const marketDataCliCommands:
|
|
1057
|
+
export const marketDataCliCommands: BuiltinCliCommandDef[] = [
|
|
651
1058
|
{
|
|
652
1059
|
name: "quote",
|
|
653
1060
|
description: "Show the latest price for one or more symbols",
|
|
@@ -655,7 +1062,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
655
1062
|
group: CLI_COMMAND_GROUPS.research,
|
|
656
1063
|
usage: ["quote <symbol...>"],
|
|
657
1064
|
options: [EXCHANGE_OPTION],
|
|
658
|
-
examples: ["quote AAPL MSFT NVDA", "quote BTC-USD EURUSD=X", "quote AAPL --json"],
|
|
1065
|
+
examples: ["quote AAPL MSFT NVDA", "quote SAN:EPA BHP:ASX", "quote BTC-USD EURUSD=X", "quote AAPL --json"],
|
|
659
1066
|
},
|
|
660
1067
|
execute: (args, ctx) => runQuote(args, ctx, "quote"),
|
|
661
1068
|
},
|
|
@@ -666,7 +1073,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
666
1073
|
group: CLI_COMMAND_GROUPS.research,
|
|
667
1074
|
usage: ["compare <symbol...>"],
|
|
668
1075
|
options: [EXCHANGE_OPTION],
|
|
669
|
-
examples: ["compare KO PEP", "compare SPY QQQ IWM --csv"],
|
|
1076
|
+
examples: ["compare KO PEP", "compare SAN:EPA SAN:NYSE", "compare SPY QQQ IWM --csv"],
|
|
670
1077
|
},
|
|
671
1078
|
execute: (args, ctx) => runQuote(args, ctx, "compare"),
|
|
672
1079
|
},
|
|
@@ -675,13 +1082,23 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
675
1082
|
description: "Fetch open, high, low, close, and volume over a range",
|
|
676
1083
|
help: {
|
|
677
1084
|
group: CLI_COMMAND_GROUPS.research,
|
|
678
|
-
usage: [
|
|
1085
|
+
usage: [HISTORY_USAGE],
|
|
679
1086
|
options: [
|
|
680
|
-
{ flags: "--range <range>", description: `${TIME_RANGES.join(", ")} (default 1Y)` },
|
|
1087
|
+
{ flags: "--range <range>", description: `${TIME_RANGES.join(", ")} (default 1Y); ${HISTORY_ALL_RANGE}` },
|
|
681
1088
|
EXCHANGE_OPTION,
|
|
682
1089
|
],
|
|
683
|
-
|
|
1090
|
+
sections: [{
|
|
1091
|
+
title: "Bars",
|
|
1092
|
+
lines: [
|
|
1093
|
+
`Each range comes in one bar size: ${historyIntervalsByRange()}. The line under the heading, and the --json metadata, give the currency, the bar size actually served, the first and last bar and the bar count. A warning says when the bars are coarser, or start later, than the range asked for.`,
|
|
1094
|
+
"A bar whose prices contradict each other (high below the open or close, or low above them) is left blank and flagged, such as high<open, with the count in a warning. Every exported row (--csv, --ndjson, --json) carries currency, interval and flag.",
|
|
1095
|
+
],
|
|
1096
|
+
}],
|
|
1097
|
+
examples: ["history AAPL", "history BHP:ASX --range 5Y", "history ZAR=X --range ALL", "history AAPL --range 5Y --csv > aapl.csv"],
|
|
684
1098
|
},
|
|
1099
|
+
unknownOptionHint: (flag) => DATE_WINDOW_OPTIONS.has(flag)
|
|
1100
|
+
? `history takes a --range instead of dates: ${TIME_RANGES.join(", ")}. ${HISTORY_ALL_RANGE}.`
|
|
1101
|
+
: null,
|
|
685
1102
|
execute: runHistory,
|
|
686
1103
|
},
|
|
687
1104
|
{
|
|
@@ -694,7 +1111,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
694
1111
|
{ flags: "--expiration <unix>", description: "Expiration as Unix seconds; defaults to the nearest one" },
|
|
695
1112
|
EXCHANGE_OPTION,
|
|
696
1113
|
],
|
|
697
|
-
examples: ["options AAPL", "options AAPL --json"],
|
|
1114
|
+
examples: ["options AAPL", "options AAPL:NASDAQ --json"],
|
|
698
1115
|
},
|
|
699
1116
|
execute: runOptions,
|
|
700
1117
|
},
|
|
@@ -731,8 +1148,8 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
731
1148
|
help: {
|
|
732
1149
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
733
1150
|
usage: ["financials <symbol>"],
|
|
734
|
-
options: [EXCHANGE_OPTION],
|
|
735
|
-
examples: ["financials MSFT", "financials MSFT --json"],
|
|
1151
|
+
options: [EXCHANGE_OPTION, TABLE_SECTION_OPTION],
|
|
1152
|
+
examples: ["financials MSFT", "financials SAN:EPA", "financials MSFT --json", "financials MSFT --csv > msft.csv"],
|
|
736
1153
|
},
|
|
737
1154
|
execute: (args, ctx) => runFinancials(args, ctx, "statements"),
|
|
738
1155
|
},
|
|
@@ -742,8 +1159,8 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
742
1159
|
help: {
|
|
743
1160
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
744
1161
|
usage: ["fundamentals <symbol>"],
|
|
745
|
-
options: [EXCHANGE_OPTION],
|
|
746
|
-
examples: ["fundamentals NVDA"],
|
|
1162
|
+
options: [EXCHANGE_OPTION, TABLE_SECTION_OPTION],
|
|
1163
|
+
examples: ["fundamentals NVDA", "fundamentals ASML:AMS", "fundamentals NVDA --csv --section fundamentals"],
|
|
747
1164
|
},
|
|
748
1165
|
execute: (args, ctx) => runFinancials(args, ctx, "fundamentals"),
|
|
749
1166
|
},
|
|
@@ -753,8 +1170,8 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
753
1170
|
help: {
|
|
754
1171
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
755
1172
|
usage: ["valuation <symbol>"],
|
|
756
|
-
options: [EXCHANGE_OPTION],
|
|
757
|
-
examples: ["valuation NVDA"],
|
|
1173
|
+
options: [EXCHANGE_OPTION, TABLE_SECTION_OPTION],
|
|
1174
|
+
examples: ["valuation NVDA", "valuation BP:LSE", "valuation NVDA --csv"],
|
|
758
1175
|
},
|
|
759
1176
|
execute: (args, ctx) => runFinancials(args, ctx, "valuation"),
|
|
760
1177
|
},
|
|
@@ -764,7 +1181,8 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
764
1181
|
help: {
|
|
765
1182
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
766
1183
|
usage: ["earnings <symbol...>"],
|
|
767
|
-
|
|
1184
|
+
options: [EXCHANGE_OPTION],
|
|
1185
|
+
examples: ["earnings AAPL MSFT GOOGL", "earnings SAN:EPA"],
|
|
768
1186
|
},
|
|
769
1187
|
execute: runEarnings,
|
|
770
1188
|
},
|
|
@@ -775,7 +1193,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
775
1193
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
776
1194
|
usage: ["events <symbol>"],
|
|
777
1195
|
options: [EXCHANGE_OPTION],
|
|
778
|
-
examples: ["events KO"],
|
|
1196
|
+
examples: ["events KO", "events BHP:ASX"],
|
|
779
1197
|
},
|
|
780
1198
|
execute: runEvents,
|
|
781
1199
|
},
|
|
@@ -786,18 +1204,22 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
786
1204
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
787
1205
|
usage: ["analyst <symbol>"],
|
|
788
1206
|
options: [EXCHANGE_OPTION],
|
|
789
|
-
examples: ["analyst TSLA"],
|
|
1207
|
+
examples: ["analyst TSLA", "analyst SAN:EPA"],
|
|
790
1208
|
},
|
|
791
1209
|
execute: runAnalyst,
|
|
792
1210
|
},
|
|
793
1211
|
{
|
|
794
1212
|
name: "holders",
|
|
795
|
-
description: "Fetch institutional
|
|
1213
|
+
description: "Fetch institutional holders, or the 13D/13G beneficial owners",
|
|
796
1214
|
help: {
|
|
797
1215
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
798
|
-
usage: ["holders <symbol>"],
|
|
799
|
-
options: [
|
|
800
|
-
|
|
1216
|
+
usage: ["holders <symbol> [--form 13f|13d|13g|all] [--history]"],
|
|
1217
|
+
options: [
|
|
1218
|
+
{ flags: "--form <form>", description: "13f for the holder table (default); 13d, 13g or all for beneficial owners over 5%" },
|
|
1219
|
+
{ flags: "--history", description: "With --form 13d, 13g or all, every report newest first instead of the latest per filer" },
|
|
1220
|
+
EXCHANGE_OPTION,
|
|
1221
|
+
],
|
|
1222
|
+
examples: ["holders AAPL", "holders SAN:EPA", "holders CAR --form all", "holders CAR --form 13g --history --json"],
|
|
801
1223
|
},
|
|
802
1224
|
execute: (args, ctx) => runHolders(args, ctx, "holders"),
|
|
803
1225
|
},
|
|
@@ -808,7 +1230,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
808
1230
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
809
1231
|
usage: ["insider <symbol>"],
|
|
810
1232
|
options: [EXCHANGE_OPTION],
|
|
811
|
-
examples: ["insider NVDA"],
|
|
1233
|
+
examples: ["insider NVDA", "insider BP:LSE"],
|
|
812
1234
|
},
|
|
813
1235
|
execute: (args, ctx) => runHolders(args, ctx, "insider", new Set(["insider", "direct"])),
|
|
814
1236
|
},
|
|
@@ -823,7 +1245,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
823
1245
|
title: "13F filings",
|
|
824
1246
|
lines: ["For each fund's reported position and its change over the quarter, run gloomberb fn 13F <symbol>."],
|
|
825
1247
|
}],
|
|
826
|
-
examples: ["13f AAPL"],
|
|
1248
|
+
examples: ["13f AAPL", "13f BP:NYSE"],
|
|
827
1249
|
},
|
|
828
1250
|
execute: (args, ctx) => runHolders(args, ctx, "13f", new Set(["institution", "fund"])),
|
|
829
1251
|
},
|
|
@@ -832,12 +1254,13 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
832
1254
|
description: "Fetch recent SEC filings",
|
|
833
1255
|
help: {
|
|
834
1256
|
group: CLI_COMMAND_GROUPS.companyData,
|
|
835
|
-
usage: ["filings <symbol> [--count <n>]"],
|
|
1257
|
+
usage: ["filings <symbol> [--count <n>] [--form <form>]"],
|
|
836
1258
|
options: [
|
|
837
1259
|
{ flags: "--count <n>", description: "Number of filings (default 15)" },
|
|
1260
|
+
{ flags: "--form <form>", description: "Only this form and its amendments, such as 10-K or 13D" },
|
|
838
1261
|
EXCHANGE_OPTION,
|
|
839
1262
|
],
|
|
840
|
-
examples: ["filings AAPL", "filings AAPL --count 40 --json"],
|
|
1263
|
+
examples: ["filings AAPL", "filings BHP:ASX", "filings AAPL --count 40 --json", "filings CAR --form 13G"],
|
|
841
1264
|
},
|
|
842
1265
|
execute: runFilings,
|
|
843
1266
|
},
|
|
@@ -849,8 +1272,9 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
849
1272
|
usage: ["news [symbol] [--feed <feed>]"],
|
|
850
1273
|
options: [
|
|
851
1274
|
{ flags: "--feed <feed>", description: "latest, top, or breaking for market news (default latest)" },
|
|
1275
|
+
EXCHANGE_OPTION,
|
|
852
1276
|
],
|
|
853
|
-
examples: ["news", "news TSLA", "news --feed top --limit 10"],
|
|
1277
|
+
examples: ["news", "news TSLA", "news SAN:EPA", "news --feed top --limit 10"],
|
|
854
1278
|
},
|
|
855
1279
|
execute: runNews,
|
|
856
1280
|
},
|
|
@@ -859,7 +1283,7 @@ export const marketDataCliCommands: CliCommandDef[] = [
|
|
|
859
1283
|
description: "Convert a currency into your base currency",
|
|
860
1284
|
help: {
|
|
861
1285
|
group: CLI_COMMAND_GROUPS.markets,
|
|
862
|
-
usage: [
|
|
1286
|
+
usage: [FX_USAGE],
|
|
863
1287
|
examples: ["fx EUR", "fx JPY --json"],
|
|
864
1288
|
},
|
|
865
1289
|
execute: runFx,
|