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
|
@@ -17,11 +17,14 @@ import {
|
|
|
17
17
|
formatMarketPriceWithCurrency,
|
|
18
18
|
formatMarketQuantity,
|
|
19
19
|
formatSignedMarketPrice,
|
|
20
|
+
withCurrencyMinorDigits,
|
|
20
21
|
withStablePriceDigits,
|
|
21
22
|
type MarketFormatOptions,
|
|
22
23
|
} from "../../../market-data/market/format";
|
|
23
24
|
import {
|
|
24
25
|
getActiveQuoteDisplay,
|
|
26
|
+
getCompletedRegularSessionDisplay,
|
|
27
|
+
getExtendedSessionDisplay,
|
|
25
28
|
marketChangeColor,
|
|
26
29
|
marketPriceColor,
|
|
27
30
|
marketStateDot,
|
|
@@ -48,6 +51,14 @@ import {
|
|
|
48
51
|
type PortfolioPositionPnl,
|
|
49
52
|
} from "./position-metrics";
|
|
50
53
|
import { isFiniteNumber } from "../../../utils/guards";
|
|
54
|
+
import {
|
|
55
|
+
allocationFigures,
|
|
56
|
+
formatAllocationDrift,
|
|
57
|
+
formatAllocationWeight,
|
|
58
|
+
formatTradeUnits,
|
|
59
|
+
holdingTarget,
|
|
60
|
+
type AllocationFigures,
|
|
61
|
+
} from "./allocation";
|
|
51
62
|
|
|
52
63
|
export interface ColumnContext {
|
|
53
64
|
activeTab?: string;
|
|
@@ -56,8 +67,14 @@ export interface ColumnContext {
|
|
|
56
67
|
exchangeRates: Map<string, number>;
|
|
57
68
|
/** Clock for quote age (per second while shown) and day-based columns. */
|
|
58
69
|
now: number;
|
|
59
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* The total a portfolio's weights divide by: its priced holdings at net
|
|
72
|
+
* market value plus its cash (see allocation.ts). It may trail the rows by
|
|
73
|
+
* about a second.
|
|
74
|
+
*/
|
|
60
75
|
portfolioTotalMarketValue?: number;
|
|
76
|
+
/** The portfolio's target weights in percent, by symbol. */
|
|
77
|
+
portfolioTargets?: Readonly<Record<string, number>>;
|
|
61
78
|
supplementalVersion?: number;
|
|
62
79
|
analystResearch?: Map<string, AnalystResearchData | null>;
|
|
63
80
|
corporateActions?: Map<string, CorporateActionsData | null>;
|
|
@@ -169,19 +186,61 @@ function tradedQuoteDisplay(
|
|
|
169
186
|
return valuation && metrics.valuesAtMark ? getActiveQuoteDisplay(quote) : valuation;
|
|
170
187
|
}
|
|
171
188
|
|
|
189
|
+
/**
|
|
190
|
+
* LAST, CHG and CHG% once the regular session is over, and in the pre-market
|
|
191
|
+
* while the quote carries the last session's close and move: that close and its
|
|
192
|
+
* move, frozen, because the EXT% column carries the extended print measured
|
|
193
|
+
* from that close. Until the close, and wherever no close is reported (a
|
|
194
|
+
* pre-market quote without it, venues without extended hours), the traded price
|
|
195
|
+
* as above.
|
|
196
|
+
* Valuation columns (DAY P&L, MKT VAL, weight, P&L) keep the live price.
|
|
197
|
+
* A watchlist's Avg Day averages this CHG%.
|
|
198
|
+
*/
|
|
199
|
+
export function headlineQuoteDisplay(
|
|
200
|
+
traded: ActiveQuoteDisplay | null,
|
|
201
|
+
quote: TickerFinancials["quote"],
|
|
202
|
+
): ActiveQuoteDisplay | null {
|
|
203
|
+
return traded ? getCompletedRegularSessionDisplay(quote) ?? traded : null;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** CHG% as shown: the headline's, else the quote's own when no position price is usable. */
|
|
207
|
+
function headlineChangePercent(
|
|
208
|
+
headline: ActiveQuoteDisplay | null,
|
|
209
|
+
quote: TickerFinancials["quote"],
|
|
210
|
+
): number | undefined {
|
|
211
|
+
if (headline) return headline.changePercent;
|
|
212
|
+
return quote ? (getCompletedRegularSessionDisplay(quote) ?? quote).changePercent : undefined;
|
|
213
|
+
}
|
|
214
|
+
|
|
172
215
|
function fiftyTwoWeekPosition(displayQuote: ActiveQuoteDisplay | null, quote: TickerFinancials["quote"]): number | null {
|
|
173
216
|
const range = displayQuote ? liveFiftyTwoWeekRange(quote, displayQuote.price) : null;
|
|
174
217
|
return displayQuote && range ? ((displayQuote.price - range.low) / (range.high - range.low)) * 100 : null;
|
|
175
218
|
}
|
|
176
219
|
|
|
177
|
-
|
|
220
|
+
/** The row's weight, target, drift and trade, from its own live value and the pane's total. */
|
|
221
|
+
function rowAllocation(
|
|
222
|
+
ticker: TickerRecord,
|
|
178
223
|
activeQuote: ActiveQuoteDisplay | null,
|
|
179
|
-
|
|
224
|
+
baseMetrics: ReturnType<typeof getPortfolioPositionMetrics>,
|
|
180
225
|
toBaseQuote: (value: number) => number,
|
|
181
|
-
|
|
182
|
-
|
|
226
|
+
ctx: ColumnContext,
|
|
227
|
+
): AllocationFigures & { unpriced: boolean } {
|
|
228
|
+
const held = baseMetrics.positionCount > 0;
|
|
229
|
+
const unitPrice = activeQuote ? toBaseQuote(activeQuote.price) : null;
|
|
230
|
+
const marketValue = held ? resolvePortfolioMarketValue(baseMetrics, unitPrice)?.net ?? null : 0;
|
|
231
|
+
return {
|
|
232
|
+
...allocationFigures(
|
|
233
|
+
{ held, marketValue, units: baseMetrics.totalShares, unitPrice },
|
|
234
|
+
ctx.portfolioTotalMarketValue,
|
|
235
|
+
holdingTarget(ctx.portfolioTargets, ticker.metadata.ticker),
|
|
236
|
+
),
|
|
237
|
+
unpriced: held && marketValue == null,
|
|
238
|
+
};
|
|
183
239
|
}
|
|
184
240
|
|
|
241
|
+
/** A held position without a price says so where its allocation would be. */
|
|
242
|
+
const UNPRICED = "n/a";
|
|
243
|
+
|
|
185
244
|
export function resolvePortfolioPriceValue(
|
|
186
245
|
activeQuote: ActiveQuoteDisplay | null,
|
|
187
246
|
brokerMarkPrice: number | undefined,
|
|
@@ -215,6 +274,7 @@ export function getColumnValue(
|
|
|
215
274
|
const positionMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, undefined, quote);
|
|
216
275
|
const activeQuote = getPortfolioQuoteDisplay(positionMetrics, quote);
|
|
217
276
|
const displayQuote = tradedQuoteDisplay(positionMetrics, activeQuote, quote);
|
|
277
|
+
const headlineQuote = headlineQuoteDisplay(displayQuote, quote);
|
|
218
278
|
const { positionCurrency, totalShares, totalCost, totalCostUnits, totalPriceUnits, multiplierHint, brokerMarkPrice } = positionMetrics;
|
|
219
279
|
const baseMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, {
|
|
220
280
|
currency: ctx.baseCurrency,
|
|
@@ -270,12 +330,12 @@ export function getColumnValue(
|
|
|
270
330
|
case "tags":
|
|
271
331
|
return { text: ticker.metadata.tags.length > 0 ? ticker.metadata.tags.join(",") : "—" };
|
|
272
332
|
case "price":
|
|
273
|
-
return resolvePortfolioPriceValue(
|
|
333
|
+
return resolvePortfolioPriceValue(headlineQuote, brokerMarkPrice, headlineQuote ? currentQuoteOptions : markOptions, col.width, quote?.marketState);
|
|
274
334
|
case "change":
|
|
275
|
-
if (!
|
|
335
|
+
if (!headlineQuote) return { text: "—" };
|
|
276
336
|
return {
|
|
277
|
-
text: formatSignedMarketPrice(
|
|
278
|
-
color: marketChangeColor(
|
|
337
|
+
text: formatSignedMarketPrice(headlineQuote.change, { ...currentQuoteOptions, maxWidth: col.width }),
|
|
338
|
+
color: marketChangeColor(headlineQuote.change, quote?.marketState),
|
|
279
339
|
};
|
|
280
340
|
case "bid":
|
|
281
341
|
return { text: quote?.bid != null ? formatMarketPrice(quote.bid, { ...currentQuoteOptions, maxWidth: col.width }) : "—" };
|
|
@@ -297,10 +357,12 @@ export function getColumnValue(
|
|
|
297
357
|
if (!isFiniteNumber(quote?.bidSize) && !isFiniteNumber(quote?.askSize)) return { text: "—" };
|
|
298
358
|
return { text: `${formatCompact(quote?.bidSize)}/${formatCompact(quote?.askSize)}` };
|
|
299
359
|
}
|
|
300
|
-
case "change_pct":
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
360
|
+
case "change_pct": {
|
|
361
|
+
const changePercent = headlineChangePercent(headlineQuote, quote);
|
|
362
|
+
return quote
|
|
363
|
+
? { text: formatPercentRaw(changePercent), color: marketChangeColor(changePercent, quote.marketState) }
|
|
364
|
+
: { text: "—" };
|
|
365
|
+
}
|
|
304
366
|
case "volume":
|
|
305
367
|
return { text: isFiniteNumber(quote?.volume) ? formatCompact(quote.volume, { fixedDecimals: true }) : "—" };
|
|
306
368
|
case "dollar_volume": {
|
|
@@ -324,34 +386,50 @@ export function getColumnValue(
|
|
|
324
386
|
const dividendYield = liveDividendYield(quote, fundamentals);
|
|
325
387
|
return { text: dividendYield != null ? `${(dividendYield * 100).toFixed(2)}%` : "—" };
|
|
326
388
|
}
|
|
327
|
-
case "ext_hours":
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
if ((quote?.marketState === "POST" || quote?.marketState === "POSTPOST") && quote.postMarketPrice != null) {
|
|
334
|
-
const changePercent = quote.postMarketChangePercent;
|
|
335
|
-
if (!isFiniteNumber(changePercent)) return { text: "—" };
|
|
336
|
-
return { text: formatPercentRaw(changePercent), color: priceColor(changePercent) };
|
|
337
|
-
}
|
|
338
|
-
return { text: "—" };
|
|
389
|
+
case "ext_hours": {
|
|
390
|
+
const changePercent = getExtendedSessionDisplay(quote)?.changePercent;
|
|
391
|
+
if (!isFiniteNumber(changePercent)) return { text: "—" };
|
|
392
|
+
return { text: formatPercentRaw(changePercent), color: priceColor(changePercent) };
|
|
393
|
+
}
|
|
339
394
|
case "side":
|
|
340
395
|
return { text: positionSideLabel(ticker, ctx.activeTab) ?? "—" };
|
|
341
396
|
case "shares":
|
|
342
397
|
return { text: positionMetrics.positionCount > 0 ? formatMarketQuantity(totalShares, { ...formatOptions, maxWidth: col.width }) : "—" };
|
|
343
398
|
case "avg_cost":
|
|
344
399
|
if (totalCostUnits === 0 || !Number.isFinite(totalCost)) return { text: "—" };
|
|
345
|
-
|
|
400
|
+
// A money cost keeps its currency's minor unit, as `portfolio show` prints it: 45.50, not 45.5.
|
|
401
|
+
return { text: formatMarketCost(totalCost / Math.abs(totalCostUnits), { ...withCurrencyMinorDigits(formatOptions, positionCurrency), maxWidth: col.width }) };
|
|
346
402
|
case "cost_basis":
|
|
347
403
|
if (baseMetrics.positionCount === 0 || !Number.isFinite(baseMetrics.totalCost)) return { text: "—" };
|
|
348
404
|
return { text: formatCompact(baseMetrics.totalCost) };
|
|
349
|
-
case "mkt_value":
|
|
350
|
-
|
|
405
|
+
case "mkt_value": {
|
|
406
|
+
if (baseMetrics.positionCount === 0) return { text: "—" };
|
|
407
|
+
const marketValue = resolvePortfolioMarketValue(baseMetrics, activeQuote ? toBaseQuote(activeQuote.price) : null)?.gross;
|
|
408
|
+
return { text: marketValue == null ? UNPRICED : formatCompactAmount(marketValue) };
|
|
409
|
+
}
|
|
351
410
|
case "weight": {
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
411
|
+
const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
|
|
412
|
+
return { text: allocation.unpriced ? UNPRICED : formatAllocationWeight(allocation.weight) };
|
|
413
|
+
}
|
|
414
|
+
case "target_weight":
|
|
415
|
+
return { text: formatAllocationWeight(holdingTarget(ctx.portfolioTargets, ticker.metadata.ticker)) };
|
|
416
|
+
case "drift": {
|
|
417
|
+
const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
|
|
418
|
+
if (allocation.unpriced && allocation.targetWeight != null) return { text: UNPRICED };
|
|
419
|
+
const text = formatAllocationDrift(allocation.drift);
|
|
420
|
+
return { text, color: /[1-9]/.test(text) ? priceColor(allocation.drift!) : undefined };
|
|
421
|
+
}
|
|
422
|
+
case "trade": {
|
|
423
|
+
const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
|
|
424
|
+
if (allocation.unpriced && allocation.targetWeight != null) return { text: UNPRICED };
|
|
425
|
+
const text = formatTradeUnits(allocation.tradeUnits, { units: totalShares, assetCategory: ticker.metadata.assetCategory });
|
|
426
|
+
return { text, color: /[1-9]/.test(text) ? priceColor(allocation.tradeUnits!) : undefined };
|
|
427
|
+
}
|
|
428
|
+
case "trade_value": {
|
|
429
|
+
const allocation = rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx);
|
|
430
|
+
if (allocation.unpriced && allocation.targetWeight != null) return { text: UNPRICED };
|
|
431
|
+
const text = formatCompactAmount(allocation.tradeValue ?? undefined, { signed: true });
|
|
432
|
+
return { text, color: /[1-9]/.test(text) ? priceColor(allocation.tradeValue!) : undefined };
|
|
355
433
|
}
|
|
356
434
|
case "day_pnl":
|
|
357
435
|
if (activeQuote && isFiniteNumber(activeQuote.change) && Number.isFinite(positionMetrics.grossPriceUnits) && positionMetrics.grossPriceUnits !== 0) {
|
|
@@ -438,6 +516,7 @@ export function getSortValue(
|
|
|
438
516
|
const positionMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, undefined, quote);
|
|
439
517
|
const activeQuote = getPortfolioQuoteDisplay(positionMetrics, quote);
|
|
440
518
|
const displayQuote = tradedQuoteDisplay(positionMetrics, activeQuote, quote);
|
|
519
|
+
const headlineQuote = headlineQuoteDisplay(displayQuote, quote);
|
|
441
520
|
const { positionCurrency, totalShares, totalCost, totalCostUnits, totalPriceUnits, brokerMarkPrice } = positionMetrics;
|
|
442
521
|
const baseMetrics = getPortfolioPositionMetrics(ticker, ctx.activeTab, quoteCurrency, {
|
|
443
522
|
currency: ctx.baseCurrency,
|
|
@@ -471,7 +550,7 @@ export function getSortValue(
|
|
|
471
550
|
case "tags":
|
|
472
551
|
return ticker.metadata.tags.join(",");
|
|
473
552
|
case "price":
|
|
474
|
-
if (
|
|
553
|
+
if (headlineQuote) return headlineQuote.price;
|
|
475
554
|
if (brokerMarkPrice != null) return brokerMarkPrice;
|
|
476
555
|
return null;
|
|
477
556
|
case "bid":
|
|
@@ -490,9 +569,9 @@ export function getSortValue(
|
|
|
490
569
|
? (quote?.bidSize ?? 0) + (quote?.askSize ?? 0)
|
|
491
570
|
: null;
|
|
492
571
|
case "change":
|
|
493
|
-
return
|
|
572
|
+
return headlineQuote?.change ?? null;
|
|
494
573
|
case "change_pct":
|
|
495
|
-
return
|
|
574
|
+
return headlineChangePercent(headlineQuote, quote) ?? null;
|
|
496
575
|
case "volume":
|
|
497
576
|
return quote?.volume ?? null;
|
|
498
577
|
case "dollar_volume":
|
|
@@ -512,13 +591,7 @@ export function getSortValue(
|
|
|
512
591
|
case "dividend_yield":
|
|
513
592
|
return liveDividendYield(quote, fundamentals) ?? null;
|
|
514
593
|
case "ext_hours":
|
|
515
|
-
|
|
516
|
-
return quote.preMarketChangePercent ?? null;
|
|
517
|
-
}
|
|
518
|
-
if ((quote?.marketState === "POST" || quote?.marketState === "POSTPOST") && quote.postMarketPrice != null) {
|
|
519
|
-
return quote.postMarketChangePercent ?? null;
|
|
520
|
-
}
|
|
521
|
-
return null;
|
|
594
|
+
return getExtendedSessionDisplay(quote)?.changePercent ?? null;
|
|
522
595
|
case "side":
|
|
523
596
|
return positionSideLabel(ticker, ctx.activeTab);
|
|
524
597
|
case "shares":
|
|
@@ -529,12 +602,16 @@ export function getSortValue(
|
|
|
529
602
|
return baseMetrics.positionCount > 0 && Number.isFinite(baseMetrics.totalCost) ? baseMetrics.totalCost : null;
|
|
530
603
|
case "mkt_value":
|
|
531
604
|
return resolvePortfolioMarketValue(baseMetrics, activeQuote ? toBaseQuote(activeQuote.price) : null)?.gross ?? null;
|
|
532
|
-
case "weight":
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
605
|
+
case "weight":
|
|
606
|
+
return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).weight;
|
|
607
|
+
case "target_weight":
|
|
608
|
+
return holdingTarget(ctx.portfolioTargets, ticker.metadata.ticker) ?? null;
|
|
609
|
+
case "drift":
|
|
610
|
+
return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).drift;
|
|
611
|
+
case "trade":
|
|
612
|
+
return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).tradeUnits;
|
|
613
|
+
case "trade_value":
|
|
614
|
+
return rowAllocation(ticker, activeQuote, baseMetrics, toBaseQuote, ctx).tradeValue;
|
|
538
615
|
case "day_pnl":
|
|
539
616
|
if (activeQuote && isFiniteNumber(activeQuote.change) && Number.isFinite(positionMetrics.grossPriceUnits) && positionMetrics.grossPriceUnits !== 0) {
|
|
540
617
|
return toBaseQuote(totalPriceUnits * activeQuote.change);
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
HeadlessPaneColumn,
|
|
4
4
|
HeadlessPaneContext,
|
|
5
5
|
HeadlessPaneDefinition,
|
|
6
|
+
HeadlessPaneRow,
|
|
6
7
|
HeadlessRowsResult,
|
|
7
8
|
} from "../../../types/plugin";
|
|
8
9
|
import type { TickerRecord } from "../../../types/ticker";
|
|
@@ -10,10 +11,21 @@ import { formatNumber, formatPercentRaw } from "../../../utils/format";
|
|
|
10
11
|
import {
|
|
11
12
|
findCollection,
|
|
12
13
|
loadCollectionQuotes,
|
|
14
|
+
valuePortfolioAllocation,
|
|
13
15
|
valuePortfolioPositions,
|
|
14
16
|
type CollectionMatch,
|
|
15
17
|
} from "./cli/render";
|
|
18
|
+
import {
|
|
19
|
+
BROKER_ACCOUNT_MISSING_NOTE,
|
|
20
|
+
CASH_SYMBOL,
|
|
21
|
+
describeTargetSum,
|
|
22
|
+
formatAllocationDrift,
|
|
23
|
+
formatAllocationWeight,
|
|
24
|
+
formatTradeUnits,
|
|
25
|
+
} from "./allocation";
|
|
26
|
+
import { currencyMinorDigits, formatMarketPrice, formatMarketQuantity } from "../../../market-data/market/format";
|
|
16
27
|
import { resolvePortfolioTotalsCurrency } from "./summary/totals";
|
|
28
|
+
import { quoteFreshnessFields } from "../shared/report-freshness";
|
|
17
29
|
|
|
18
30
|
const DEFAULT_ROW_LIMIT = 50;
|
|
19
31
|
const MAX_ROW_LIMIT = 200;
|
|
@@ -21,22 +33,50 @@ const MAX_ROW_LIMIT = 200;
|
|
|
21
33
|
const LISTED_COLLECTION_IDS = 12;
|
|
22
34
|
|
|
23
35
|
const amount = (value: unknown) => formatNumber(typeof value === "number" ? value : undefined, 2);
|
|
36
|
+
/** Market values and trades in whole units, as `portfolio show` prints them. */
|
|
37
|
+
const wholeAmount = (value: unknown) => formatNumber(typeof value === "number" ? value : undefined, 0);
|
|
38
|
+
const signedAmount = (value: unknown) => (
|
|
39
|
+
typeof value === "number" && Number.isFinite(value) ? `${value > 0 && /[1-9]/.test(wholeAmount(value)) ? "+" : ""}${wholeAmount(value)}` : formatNumber(undefined)
|
|
40
|
+
);
|
|
24
41
|
const percent = (value: unknown) => formatPercentRaw(typeof value === "number" ? value : undefined);
|
|
25
|
-
const
|
|
26
|
-
|
|
42
|
+
const weight = (value: unknown) => formatAllocationWeight(typeof value === "number" ? value : null);
|
|
43
|
+
const drift = (value: unknown) => formatAllocationDrift(typeof value === "number" ? value : null);
|
|
44
|
+
const quantity = (value: unknown, row: HeadlessPaneRow) => (
|
|
45
|
+
typeof value === "number" ? formatMarketQuantity(value, { assetCategory: textOf(row.assetCategory) }) : formatNumber(undefined)
|
|
46
|
+
);
|
|
47
|
+
const tradeUnits = (value: unknown, row: HeadlessPaneRow) => (
|
|
48
|
+
typeof value === "number" ? formatTradeUnits(value, { units: finite(row.shares) ?? 0, assetCategory: textOf(row.assetCategory) }) : formatNumber(undefined)
|
|
27
49
|
);
|
|
50
|
+
/** Money per unit at the currency's minor digits: $230.00, not 230. */
|
|
51
|
+
const unitMoney = (currencyKey: string) => (value: unknown, row: HeadlessPaneRow) => (
|
|
52
|
+
typeof value === "number"
|
|
53
|
+
? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits: Math.min(2, currencyMinorDigits(textOf(row[currencyKey]))) })
|
|
54
|
+
: formatNumber(undefined)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
function textOf(value: unknown): string | undefined {
|
|
58
|
+
return typeof value === "string" && value ? value : undefined;
|
|
59
|
+
}
|
|
28
60
|
|
|
29
61
|
const POSITION_COLUMNS: HeadlessPaneColumn[] = [
|
|
30
62
|
{ key: "symbol", header: "Ticker" },
|
|
31
63
|
{ key: "name", header: "Name" },
|
|
32
|
-
{ key: "shares", header: "Qty", align: "right" },
|
|
33
|
-
{ key: "avgCost", header: "Avg Cost", align: "right", description: "Per unit, in the position's currency." },
|
|
34
|
-
{ key: "price", header: "Last", align: "right", description: "In the quote's currency." },
|
|
64
|
+
{ key: "shares", header: "Qty", align: "right", format: quantity },
|
|
65
|
+
{ key: "avgCost", header: "Avg Cost", align: "right", format: unitMoney("positionCurrency"), description: "Per unit, in the position's currency." },
|
|
66
|
+
{ key: "price", header: "Last", align: "right", format: unitMoney("priceCurrency"), description: "In the quote's currency." },
|
|
35
67
|
{ key: "priceCurrency", header: "Ccy" },
|
|
36
68
|
{ key: "changePercent", header: "Chg", align: "right", format: percent },
|
|
37
|
-
{ key: "marketValue", header: "Mkt Val", align: "right", format:
|
|
69
|
+
{ key: "marketValue", header: "Mkt Val", align: "right", format: wholeAmount, description: "In the portfolio's currency; negative for shorts." },
|
|
38
70
|
{ key: "unrealizedPnl", header: "P&L", align: "right", format: amount, description: "Unrealized, in the portfolio's currency." },
|
|
39
|
-
{ key: "weight", header: "Weight", align: "right", format:
|
|
71
|
+
{ key: "weight", header: "Weight", align: "right", format: weight, description: "Percent of the total value, cash included; unpriced holdings are left out." },
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
/** Shown once the portfolio has a target weight. */
|
|
75
|
+
const TARGET_COLUMNS: HeadlessPaneColumn[] = [
|
|
76
|
+
{ key: "targetWeight", header: "Target", align: "right", format: weight, description: "Target weight, in percent." },
|
|
77
|
+
{ key: "drift", header: "Drift", align: "right", format: drift, description: "Weight minus target, in percentage points." },
|
|
78
|
+
{ key: "tradeShares", header: "Trade", align: "right", format: tradeUnits, description: "Units to buy (+) or sell (-) to reach the target at the current price." },
|
|
79
|
+
{ key: "tradeValue", header: "Trade Value", align: "right", format: signedAmount, description: "The trade in the portfolio's currency." },
|
|
40
80
|
];
|
|
41
81
|
|
|
42
82
|
const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
|
|
@@ -97,26 +137,36 @@ async function portfolioHoldings(
|
|
|
97
137
|
const currency = resolvePortfolioTotalsCurrency(target.portfolio, ctx.config.baseCurrency);
|
|
98
138
|
const quotes = await loadCollectionQuotes(tickers, target, ctx.marketData);
|
|
99
139
|
ctx.signal.throwIfAborted();
|
|
140
|
+
const toBase = createBaseConverter(ctx.marketData, currency);
|
|
100
141
|
const valuation = await valuePortfolioPositions({
|
|
101
142
|
tickers,
|
|
102
143
|
quotes,
|
|
103
144
|
portfolioId: target.id,
|
|
104
145
|
currency,
|
|
105
146
|
baseCurrency: ctx.config.baseCurrency,
|
|
106
|
-
toBase
|
|
147
|
+
toBase,
|
|
107
148
|
});
|
|
149
|
+
const { allocation, cash } = await valuePortfolioAllocation({ valuation, portfolio: resolved.portfolio, account: resolved.account, toBase });
|
|
108
150
|
ctx.signal.throwIfAborted();
|
|
109
151
|
|
|
152
|
+
const allocationBySymbol = new Map(allocation.rows.map((row) => [row.symbol, row]));
|
|
110
153
|
const held = valuation.positions.filter((entry) => entry.position);
|
|
111
154
|
const gross = held.reduce((sum, entry) => sum + Math.abs(finite(entry.row.marketValue) ?? 0), 0);
|
|
112
155
|
const sum = (key: string) => held.reduce((total, entry) => total + (finite(entry.row[key]) ?? 0), 0);
|
|
156
|
+
const seen = new Set<string>();
|
|
113
157
|
const rows = held
|
|
114
158
|
.map(({ ticker, activeQuote, row }) => {
|
|
115
159
|
const marketValue = finite(row.marketValue);
|
|
160
|
+
// A ticker held in several lots carries its allocation on its first row.
|
|
161
|
+
const figures = seen.has(ticker.metadata.ticker) ? undefined : allocationBySymbol.get(ticker.metadata.ticker);
|
|
162
|
+
seen.add(ticker.metadata.ticker);
|
|
116
163
|
return {
|
|
164
|
+
...quoteFreshnessFields(quotes.get(ticker.metadata.ticker)),
|
|
165
|
+
updatedAt: quotes.get(ticker.metadata.ticker)?.lastUpdated ?? null,
|
|
117
166
|
symbol: ticker.metadata.ticker,
|
|
118
167
|
name: ticker.metadata.name ?? null,
|
|
119
168
|
exchange: ticker.metadata.exchange || null,
|
|
169
|
+
assetCategory: ticker.metadata.assetCategory ?? null,
|
|
120
170
|
shares: finite(row.shares),
|
|
121
171
|
avgCost: finite(row.avgCost),
|
|
122
172
|
positionCurrency: row.positionCurrency ?? null,
|
|
@@ -125,7 +175,11 @@ async function portfolioHoldings(
|
|
|
125
175
|
changePercent: finite(activeQuote?.changePercent),
|
|
126
176
|
marketValue,
|
|
127
177
|
unrealizedPnl: finite(row.unrealizedPnl),
|
|
128
|
-
weight:
|
|
178
|
+
weight: figures?.weight ?? null,
|
|
179
|
+
targetWeight: figures?.targetWeight ?? null,
|
|
180
|
+
drift: figures?.drift ?? null,
|
|
181
|
+
tradeShares: figures?.tradeUnits ?? null,
|
|
182
|
+
tradeValue: figures?.tradeValue ?? null,
|
|
129
183
|
};
|
|
130
184
|
})
|
|
131
185
|
// Largest exposure first; a position without a market value sorts last.
|
|
@@ -133,16 +187,40 @@ async function portfolioHoldings(
|
|
|
133
187
|
exposure(right.marketValue) - exposure(left.marketValue)
|
|
134
188
|
|| left.symbol.localeCompare(right.symbol)
|
|
135
189
|
));
|
|
136
|
-
const shown = rows.slice(0, limit);
|
|
190
|
+
const shown: HeadlessPaneRow[] = rows.slice(0, limit);
|
|
191
|
+
// The cash line follows the positions, whatever the limit.
|
|
192
|
+
if (allocation.cash) {
|
|
193
|
+
shown.push({
|
|
194
|
+
symbol: CASH_SYMBOL,
|
|
195
|
+
name: cash?.source === "broker" ? "Cash (broker account)" : "Cash",
|
|
196
|
+
priceCurrency: cash?.currency ?? null,
|
|
197
|
+
marketValue: finite(allocation.cash.value),
|
|
198
|
+
weight: allocation.cash.weight,
|
|
199
|
+
targetWeight: allocation.cash.targetWeight,
|
|
200
|
+
drift: allocation.cash.drift,
|
|
201
|
+
tradeShares: null,
|
|
202
|
+
tradeValue: allocation.cash.tradeValue,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
137
205
|
const unavailable = [...new Set([...valuation.unavailableMarketValue, ...valuation.unavailablePnl])];
|
|
138
206
|
const broker = !!(target.portfolio.brokerId || target.portfolio.brokerInstanceId);
|
|
207
|
+
const showTargets = allocation.targetSum != null;
|
|
208
|
+
const targetNote = describeTargetSum(allocation.targetSum);
|
|
209
|
+
const notices = [
|
|
210
|
+
...(rows.length > limit
|
|
211
|
+
? [`${rows.length - limit} more position${rows.length - limit === 1 ? "" : "s"} not shown; totals include every position.`]
|
|
212
|
+
: []),
|
|
213
|
+
...(targetNote ? [targetNote] : []),
|
|
214
|
+
...(target.portfolio.brokerInstanceId && !resolved.account ? [BROKER_ACCOUNT_MISSING_NOTE] : []),
|
|
215
|
+
];
|
|
139
216
|
|
|
140
217
|
return {
|
|
141
|
-
|
|
218
|
+
freshness: { source: broker ? "Your broker account and Gloom Cloud" : "Local portfolio and Gloom Cloud" },
|
|
219
|
+
columns: showTargets ? [...POSITION_COLUMNS, ...TARGET_COLUMNS] : POSITION_COLUMNS,
|
|
142
220
|
rows: shown,
|
|
143
221
|
complete: unavailable.length === 0,
|
|
144
222
|
...(unavailable.length
|
|
145
|
-
? { errors: [`No market value or P&L for ${unavailable.join(", ")}; totals leave them out.`] }
|
|
223
|
+
? { errors: [`No market value or P&L for ${unavailable.join(", ")}; totals and weights leave them out.`] }
|
|
146
224
|
: {}),
|
|
147
225
|
metadata: {
|
|
148
226
|
collection: { kind: "portfolio", id: target.id, name: target.name, broker },
|
|
@@ -153,10 +231,13 @@ async function portfolioHoldings(
|
|
|
153
231
|
grossMarketValue: gross,
|
|
154
232
|
costBasis: sum("costBasis"),
|
|
155
233
|
unrealizedPnl: valuation.totalPnl,
|
|
234
|
+
cash: allocation.cash ? finite(allocation.cash.value) : null,
|
|
235
|
+
total: allocation.total,
|
|
156
236
|
},
|
|
157
|
-
...(
|
|
158
|
-
|
|
159
|
-
|
|
237
|
+
...(cash ? { cash } : {}),
|
|
238
|
+
...(showTargets ? { targetSum: allocation.targetSum } : {}),
|
|
239
|
+
unpricedCount: allocation.unpriced.length,
|
|
240
|
+
...(notices.length > 0 ? { notices } : {}),
|
|
160
241
|
},
|
|
161
242
|
};
|
|
162
243
|
}
|
|
@@ -174,6 +255,8 @@ async function watchlistHoldings(
|
|
|
174
255
|
const rows = tickers.map((ticker) => {
|
|
175
256
|
const quote = quotes.get(ticker.metadata.ticker);
|
|
176
257
|
return {
|
|
258
|
+
...quoteFreshnessFields(quote),
|
|
259
|
+
updatedAt: quote?.lastUpdated ?? null,
|
|
177
260
|
symbol: ticker.metadata.ticker,
|
|
178
261
|
name: ticker.metadata.name ?? null,
|
|
179
262
|
exchange: ticker.metadata.exchange || null,
|
|
@@ -184,6 +267,7 @@ async function watchlistHoldings(
|
|
|
184
267
|
});
|
|
185
268
|
const shown = rows.slice(0, limit);
|
|
186
269
|
return {
|
|
270
|
+
freshness: { source: "Local watchlist and Gloom Cloud" },
|
|
187
271
|
columns: WATCHLIST_COLUMNS,
|
|
188
272
|
rows: shown,
|
|
189
273
|
metadata: {
|
|
@@ -204,7 +288,7 @@ async function watchlistHoldings(
|
|
|
204
288
|
export const collectionHoldingsHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
205
289
|
shape: "rows",
|
|
206
290
|
description:
|
|
207
|
-
"Positions held in a portfolio, broker or manual: symbol, quantity, average cost, last price, market value, unrealized P&L and weight, largest first,
|
|
291
|
+
"Positions held in a portfolio, broker or manual: symbol, quantity, average cost, last price, market value, unrealized P&L and weight of the total with cash, largest first, then the cash line and totals. With target weights set, each row adds its target, drift and the trade to reach it. For a watchlist, its tickers with quotes. Takes a portfolio or watchlist ID; the first portfolio when omitted.",
|
|
208
292
|
discovery: {
|
|
209
293
|
dataRequirements: ["Local portfolios, watchlists and synced broker positions; current quotes"],
|
|
210
294
|
limitations: ["Unrealized P&L on current positions; excludes realized trades, distributions and cash flows"],
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { portfolioCliCommand } from "./cli/portfolio-command";
|
|
10
10
|
import { watchlistCliCommand } from "./cli/watchlist-command";
|
|
11
11
|
import { collectionHoldingsHeadless } from "./headless";
|
|
12
|
+
import { findCollection } from "./cli/render";
|
|
12
13
|
import {
|
|
13
14
|
LIVE_STREAMING_QUICK_SETTING,
|
|
14
15
|
withLiveStreamingSetting,
|
|
@@ -30,8 +31,13 @@ function resolveCollectionIdForKind(context: PaneTemplateContext, kind: "portfol
|
|
|
30
31
|
function createCollectionPaneInstance(
|
|
31
32
|
context: PaneTemplateContext,
|
|
32
33
|
kind?: "portfolio" | "watchlist",
|
|
34
|
+
argument?: string,
|
|
33
35
|
): PaneTemplateInstanceConfig | null {
|
|
34
|
-
|
|
36
|
+
// `PF Retirement` (or `shot PF Retirement`) opens the collection it names.
|
|
37
|
+
const named = argument?.trim() ? findCollection(context.config, argument) : null;
|
|
38
|
+
const collectionId = named && (!kind || named.kind === kind)
|
|
39
|
+
? named.id
|
|
40
|
+
: kind ? resolveCollectionIdForKind(context, kind) : resolveCollectionPaneId(context);
|
|
35
41
|
return collectionId ? { params: { collectionId } } : null;
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -39,6 +45,7 @@ export const portfolioListModule: PluginModule = {
|
|
|
39
45
|
panes: [
|
|
40
46
|
{
|
|
41
47
|
id: "portfolio-list",
|
|
48
|
+
reportFreshness: { source: "Local portfolio and Gloom Cloud" },
|
|
42
49
|
name: "Portfolio",
|
|
43
50
|
icon: "P",
|
|
44
51
|
component: PortfolioListPane,
|
|
@@ -75,11 +82,15 @@ export const portfolioListModule: PluginModule = {
|
|
|
75
82
|
paneId: "portfolio-list",
|
|
76
83
|
label: "Collection Pane",
|
|
77
84
|
description: "Open another pane for the current portfolio or watchlist",
|
|
78
|
-
|
|
85
|
+
// Phrases rather than bare words, so `fn rebalance` and `fn target` keep resolving where they did.
|
|
86
|
+
keywords: [
|
|
87
|
+
"portfolio", "watchlist", "collection", "pane", "list",
|
|
88
|
+
"portfolio rebalance", "allocation drift", "target weights", "asset allocation", "cash balance",
|
|
89
|
+
],
|
|
79
90
|
shortcut: { prefix: "PF" },
|
|
80
91
|
headless: collectionHoldingsHeadless,
|
|
81
92
|
canCreate: (context) => resolveCollectionPaneId(context) !== null,
|
|
82
|
-
createInstance: (context) => createCollectionPaneInstance(context),
|
|
93
|
+
createInstance: (context, options) => createCollectionPaneInstance(context, undefined, options?.arg),
|
|
83
94
|
},
|
|
84
95
|
{
|
|
85
96
|
id: "new-portfolio-pane",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AnalystResearchData, Fundamentals, Quote } from "../../../types/financials";
|
|
2
2
|
import { hasLikelyQuoteUnitMismatch } from "../../../utils/currency-units";
|
|
3
3
|
import { selectMarketCapitalization, type MarketCapitalization } from "../../../utils/market-capitalization";
|
|
4
|
+
import { priceEarningsOnEarnings, type PriceEarnings } from "../../../utils/price-earnings";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Price-derived statistics repriced from the current quote with the base
|
|
@@ -53,13 +54,14 @@ function repriceMultiple(
|
|
|
53
54
|
return price / perShare;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
/** Trailing P/E over the current price
|
|
57
|
-
export function liveTrailingPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined):
|
|
58
|
-
return repriceMultiple(fundamentals?.trailingPE, fundamentals?.eps, quote, fundamentals);
|
|
57
|
+
/** Trailing P/E over the current price; not meaningful when the trailing EPS is zero or a loss. */
|
|
58
|
+
export function liveTrailingPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): PriceEarnings | undefined {
|
|
59
|
+
return priceEarningsOnEarnings(repriceMultiple(fundamentals?.trailingPE, fundamentals?.eps, quote, fundamentals), fundamentals?.eps);
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
/** Forward P/E over the current price; not meaningful when the forward EPS behind it is zero or a loss. */
|
|
63
|
+
export function liveForwardPE(quote: Quote | null | undefined, fundamentals: Fundamentals | undefined): PriceEarnings | undefined {
|
|
64
|
+
return priceEarningsOnEarnings(repriceMultiple(fundamentals?.forwardPE, fundamentals?.forwardEps, quote, fundamentals), fundamentals?.forwardEps);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
/** Forward dividend yield over the current price, as a ratio like the stored yield. */
|