gloomberb 0.16.1 → 0.16.2
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 +24 -0
- package/src/cli/commands/command-utils.ts +8 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +414 -106
- package/src/cli/commands/overview.ts +77 -32
- package/src/cli/commands/ticker.ts +101 -43
- package/src/cli/desktop-pane-shot.ts +34 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +1 -0
- package/src/cli/helpers.ts +4 -8
- package/src/cli/index.ts +12 -2
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/pane-functions/access-gate.ts +42 -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 +20 -2
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +27 -20
- package/src/cli/pane-functions/headless.ts +39 -11
- package/src/cli/pane-functions/index.ts +15 -4
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +35 -7
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +7 -3
- package/src/cli/result.ts +41 -27
- 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/view.tsx +29 -10
- 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/menu.ts +2 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +14 -3
- 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/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 +78 -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/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/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 +1 -1
- 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/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 +1 -1
- 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/headless.ts +139 -5
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +20 -3
- package/src/plugins/builtin/holders/report-header.ts +95 -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/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 +13 -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 +248 -47
- package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -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 +230 -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 +98 -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 +47 -13
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -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 +11 -3
- 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/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/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/social-mentions/headless.ts +1 -0
- 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/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -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 +157 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -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 +447 -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 +67 -4
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
- package/src/plugins/builtin/world-venue-map/model.ts +7 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -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 +28 -43
- 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/dom/build-assets.ts +81 -3
- 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/input.tsx +14 -3
- package/src/renderers/dom/styles.css +6 -7
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -0
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +27 -3
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financials.ts +8 -7
- package/src/sources/provider-router/history.ts +15 -10
- 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/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/theme/heat-colors.ts +266 -84
- 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 +3 -0
- 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 +14 -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 +14 -0
- package/src/utils/depositary-receipt.ts +26 -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/price-earnings.ts +70 -3
- 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,20 @@ 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
|
+
CASH_SYMBOL,
|
|
20
|
+
describeTargetSum,
|
|
21
|
+
formatAllocationDrift,
|
|
22
|
+
formatAllocationWeight,
|
|
23
|
+
formatTradeUnits,
|
|
24
|
+
} from "./allocation";
|
|
25
|
+
import { currencyMinorDigits, formatMarketPrice, formatMarketQuantity } from "../../../market-data/market/format";
|
|
16
26
|
import { resolvePortfolioTotalsCurrency } from "./summary/totals";
|
|
27
|
+
import { quoteFreshnessFields } from "../shared/report-freshness";
|
|
17
28
|
|
|
18
29
|
const DEFAULT_ROW_LIMIT = 50;
|
|
19
30
|
const MAX_ROW_LIMIT = 200;
|
|
@@ -21,22 +32,50 @@ const MAX_ROW_LIMIT = 200;
|
|
|
21
32
|
const LISTED_COLLECTION_IDS = 12;
|
|
22
33
|
|
|
23
34
|
const amount = (value: unknown) => formatNumber(typeof value === "number" ? value : undefined, 2);
|
|
35
|
+
/** Market values and trades in whole units, as `portfolio show` prints them. */
|
|
36
|
+
const wholeAmount = (value: unknown) => formatNumber(typeof value === "number" ? value : undefined, 0);
|
|
37
|
+
const signedAmount = (value: unknown) => (
|
|
38
|
+
typeof value === "number" && Number.isFinite(value) ? `${value > 0 && /[1-9]/.test(wholeAmount(value)) ? "+" : ""}${wholeAmount(value)}` : formatNumber(undefined)
|
|
39
|
+
);
|
|
24
40
|
const percent = (value: unknown) => formatPercentRaw(typeof value === "number" ? value : undefined);
|
|
25
|
-
const
|
|
26
|
-
|
|
41
|
+
const weight = (value: unknown) => formatAllocationWeight(typeof value === "number" ? value : null);
|
|
42
|
+
const drift = (value: unknown) => formatAllocationDrift(typeof value === "number" ? value : null);
|
|
43
|
+
const quantity = (value: unknown, row: HeadlessPaneRow) => (
|
|
44
|
+
typeof value === "number" ? formatMarketQuantity(value, { assetCategory: textOf(row.assetCategory) }) : formatNumber(undefined)
|
|
45
|
+
);
|
|
46
|
+
const tradeUnits = (value: unknown, row: HeadlessPaneRow) => (
|
|
47
|
+
typeof value === "number" ? formatTradeUnits(value, { units: finite(row.shares) ?? 0, assetCategory: textOf(row.assetCategory) }) : formatNumber(undefined)
|
|
27
48
|
);
|
|
49
|
+
/** Money per unit at the currency's minor digits: $230.00, not 230. */
|
|
50
|
+
const unitMoney = (currencyKey: string) => (value: unknown, row: HeadlessPaneRow) => (
|
|
51
|
+
typeof value === "number"
|
|
52
|
+
? formatMarketPrice(value, { assetCategory: textOf(row.assetCategory), minimumFractionDigits: Math.min(2, currencyMinorDigits(textOf(row[currencyKey]))) })
|
|
53
|
+
: formatNumber(undefined)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
function textOf(value: unknown): string | undefined {
|
|
57
|
+
return typeof value === "string" && value ? value : undefined;
|
|
58
|
+
}
|
|
28
59
|
|
|
29
60
|
const POSITION_COLUMNS: HeadlessPaneColumn[] = [
|
|
30
61
|
{ key: "symbol", header: "Ticker" },
|
|
31
62
|
{ 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." },
|
|
63
|
+
{ key: "shares", header: "Qty", align: "right", format: quantity },
|
|
64
|
+
{ key: "avgCost", header: "Avg Cost", align: "right", format: unitMoney("positionCurrency"), description: "Per unit, in the position's currency." },
|
|
65
|
+
{ key: "price", header: "Last", align: "right", format: unitMoney("priceCurrency"), description: "In the quote's currency." },
|
|
35
66
|
{ key: "priceCurrency", header: "Ccy" },
|
|
36
67
|
{ key: "changePercent", header: "Chg", align: "right", format: percent },
|
|
37
|
-
{ key: "marketValue", header: "Mkt Val", align: "right", format:
|
|
68
|
+
{ key: "marketValue", header: "Mkt Val", align: "right", format: wholeAmount, description: "In the portfolio's currency; negative for shorts." },
|
|
38
69
|
{ key: "unrealizedPnl", header: "P&L", align: "right", format: amount, description: "Unrealized, in the portfolio's currency." },
|
|
39
|
-
{ key: "weight", header: "Weight", align: "right", format:
|
|
70
|
+
{ key: "weight", header: "Weight", align: "right", format: weight, description: "Percent of the total value, cash included; unpriced holdings are left out." },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
/** Shown once the portfolio has a target weight. */
|
|
74
|
+
const TARGET_COLUMNS: HeadlessPaneColumn[] = [
|
|
75
|
+
{ key: "targetWeight", header: "Target", align: "right", format: weight, description: "Target weight, in percent." },
|
|
76
|
+
{ key: "drift", header: "Drift", align: "right", format: drift, description: "Weight minus target, in percentage points." },
|
|
77
|
+
{ key: "tradeShares", header: "Trade", align: "right", format: tradeUnits, description: "Units to buy (+) or sell (-) to reach the target at the current price." },
|
|
78
|
+
{ key: "tradeValue", header: "Trade Value", align: "right", format: signedAmount, description: "The trade in the portfolio's currency." },
|
|
40
79
|
];
|
|
41
80
|
|
|
42
81
|
const WATCHLIST_COLUMNS: HeadlessPaneColumn[] = [
|
|
@@ -97,26 +136,36 @@ async function portfolioHoldings(
|
|
|
97
136
|
const currency = resolvePortfolioTotalsCurrency(target.portfolio, ctx.config.baseCurrency);
|
|
98
137
|
const quotes = await loadCollectionQuotes(tickers, target, ctx.marketData);
|
|
99
138
|
ctx.signal.throwIfAborted();
|
|
139
|
+
const toBase = createBaseConverter(ctx.marketData, currency);
|
|
100
140
|
const valuation = await valuePortfolioPositions({
|
|
101
141
|
tickers,
|
|
102
142
|
quotes,
|
|
103
143
|
portfolioId: target.id,
|
|
104
144
|
currency,
|
|
105
145
|
baseCurrency: ctx.config.baseCurrency,
|
|
106
|
-
toBase
|
|
146
|
+
toBase,
|
|
107
147
|
});
|
|
148
|
+
const { allocation, cash } = await valuePortfolioAllocation({ valuation, portfolio: resolved.portfolio, account: resolved.account, toBase });
|
|
108
149
|
ctx.signal.throwIfAborted();
|
|
109
150
|
|
|
151
|
+
const allocationBySymbol = new Map(allocation.rows.map((row) => [row.symbol, row]));
|
|
110
152
|
const held = valuation.positions.filter((entry) => entry.position);
|
|
111
153
|
const gross = held.reduce((sum, entry) => sum + Math.abs(finite(entry.row.marketValue) ?? 0), 0);
|
|
112
154
|
const sum = (key: string) => held.reduce((total, entry) => total + (finite(entry.row[key]) ?? 0), 0);
|
|
155
|
+
const seen = new Set<string>();
|
|
113
156
|
const rows = held
|
|
114
157
|
.map(({ ticker, activeQuote, row }) => {
|
|
115
158
|
const marketValue = finite(row.marketValue);
|
|
159
|
+
// A ticker held in several lots carries its allocation on its first row.
|
|
160
|
+
const figures = seen.has(ticker.metadata.ticker) ? undefined : allocationBySymbol.get(ticker.metadata.ticker);
|
|
161
|
+
seen.add(ticker.metadata.ticker);
|
|
116
162
|
return {
|
|
163
|
+
...quoteFreshnessFields(quotes.get(ticker.metadata.ticker)),
|
|
164
|
+
updatedAt: quotes.get(ticker.metadata.ticker)?.lastUpdated ?? null,
|
|
117
165
|
symbol: ticker.metadata.ticker,
|
|
118
166
|
name: ticker.metadata.name ?? null,
|
|
119
167
|
exchange: ticker.metadata.exchange || null,
|
|
168
|
+
assetCategory: ticker.metadata.assetCategory ?? null,
|
|
120
169
|
shares: finite(row.shares),
|
|
121
170
|
avgCost: finite(row.avgCost),
|
|
122
171
|
positionCurrency: row.positionCurrency ?? null,
|
|
@@ -125,7 +174,11 @@ async function portfolioHoldings(
|
|
|
125
174
|
changePercent: finite(activeQuote?.changePercent),
|
|
126
175
|
marketValue,
|
|
127
176
|
unrealizedPnl: finite(row.unrealizedPnl),
|
|
128
|
-
weight:
|
|
177
|
+
weight: figures?.weight ?? null,
|
|
178
|
+
targetWeight: figures?.targetWeight ?? null,
|
|
179
|
+
drift: figures?.drift ?? null,
|
|
180
|
+
tradeShares: figures?.tradeUnits ?? null,
|
|
181
|
+
tradeValue: figures?.tradeValue ?? null,
|
|
129
182
|
};
|
|
130
183
|
})
|
|
131
184
|
// Largest exposure first; a position without a market value sorts last.
|
|
@@ -133,16 +186,39 @@ async function portfolioHoldings(
|
|
|
133
186
|
exposure(right.marketValue) - exposure(left.marketValue)
|
|
134
187
|
|| left.symbol.localeCompare(right.symbol)
|
|
135
188
|
));
|
|
136
|
-
const shown = rows.slice(0, limit);
|
|
189
|
+
const shown: HeadlessPaneRow[] = rows.slice(0, limit);
|
|
190
|
+
// The cash line follows the positions, whatever the limit.
|
|
191
|
+
if (allocation.cash) {
|
|
192
|
+
shown.push({
|
|
193
|
+
symbol: CASH_SYMBOL,
|
|
194
|
+
name: cash?.source === "broker" ? "Cash (broker account)" : "Cash",
|
|
195
|
+
priceCurrency: cash?.currency ?? null,
|
|
196
|
+
marketValue: finite(allocation.cash.value),
|
|
197
|
+
weight: allocation.cash.weight,
|
|
198
|
+
targetWeight: allocation.cash.targetWeight,
|
|
199
|
+
drift: allocation.cash.drift,
|
|
200
|
+
tradeShares: null,
|
|
201
|
+
tradeValue: allocation.cash.tradeValue,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
137
204
|
const unavailable = [...new Set([...valuation.unavailableMarketValue, ...valuation.unavailablePnl])];
|
|
138
205
|
const broker = !!(target.portfolio.brokerId || target.portfolio.brokerInstanceId);
|
|
206
|
+
const showTargets = allocation.targetSum != null;
|
|
207
|
+
const targetNote = describeTargetSum(allocation.targetSum);
|
|
208
|
+
const notices = [
|
|
209
|
+
...(rows.length > limit
|
|
210
|
+
? [`${rows.length - limit} more position${rows.length - limit === 1 ? "" : "s"} not shown; totals include every position.`]
|
|
211
|
+
: []),
|
|
212
|
+
...(targetNote ? [targetNote] : []),
|
|
213
|
+
];
|
|
139
214
|
|
|
140
215
|
return {
|
|
141
|
-
|
|
216
|
+
freshness: { source: broker ? "Your broker account and Gloom Cloud" : "Local portfolio and Gloom Cloud" },
|
|
217
|
+
columns: showTargets ? [...POSITION_COLUMNS, ...TARGET_COLUMNS] : POSITION_COLUMNS,
|
|
142
218
|
rows: shown,
|
|
143
219
|
complete: unavailable.length === 0,
|
|
144
220
|
...(unavailable.length
|
|
145
|
-
? { errors: [`No market value or P&L for ${unavailable.join(", ")}; totals leave them out.`] }
|
|
221
|
+
? { errors: [`No market value or P&L for ${unavailable.join(", ")}; totals and weights leave them out.`] }
|
|
146
222
|
: {}),
|
|
147
223
|
metadata: {
|
|
148
224
|
collection: { kind: "portfolio", id: target.id, name: target.name, broker },
|
|
@@ -153,10 +229,13 @@ async function portfolioHoldings(
|
|
|
153
229
|
grossMarketValue: gross,
|
|
154
230
|
costBasis: sum("costBasis"),
|
|
155
231
|
unrealizedPnl: valuation.totalPnl,
|
|
232
|
+
cash: allocation.cash ? finite(allocation.cash.value) : null,
|
|
233
|
+
total: allocation.total,
|
|
156
234
|
},
|
|
157
|
-
...(
|
|
158
|
-
|
|
159
|
-
|
|
235
|
+
...(cash ? { cash } : {}),
|
|
236
|
+
...(showTargets ? { targetSum: allocation.targetSum } : {}),
|
|
237
|
+
unpricedCount: allocation.unpriced.length,
|
|
238
|
+
...(notices.length > 0 ? { notices } : {}),
|
|
160
239
|
},
|
|
161
240
|
};
|
|
162
241
|
}
|
|
@@ -174,6 +253,8 @@ async function watchlistHoldings(
|
|
|
174
253
|
const rows = tickers.map((ticker) => {
|
|
175
254
|
const quote = quotes.get(ticker.metadata.ticker);
|
|
176
255
|
return {
|
|
256
|
+
...quoteFreshnessFields(quote),
|
|
257
|
+
updatedAt: quote?.lastUpdated ?? null,
|
|
177
258
|
symbol: ticker.metadata.ticker,
|
|
178
259
|
name: ticker.metadata.name ?? null,
|
|
179
260
|
exchange: ticker.metadata.exchange || null,
|
|
@@ -184,6 +265,7 @@ async function watchlistHoldings(
|
|
|
184
265
|
});
|
|
185
266
|
const shown = rows.slice(0, limit);
|
|
186
267
|
return {
|
|
268
|
+
freshness: { source: "Local watchlist and Gloom Cloud" },
|
|
187
269
|
columns: WATCHLIST_COLUMNS,
|
|
188
270
|
rows: shown,
|
|
189
271
|
metadata: {
|
|
@@ -204,7 +286,7 @@ async function watchlistHoldings(
|
|
|
204
286
|
export const collectionHoldingsHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
205
287
|
shape: "rows",
|
|
206
288
|
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,
|
|
289
|
+
"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
290
|
discovery: {
|
|
209
291
|
dataRequirements: ["Local portfolios, watchlists and synced broker positions; current quotes"],
|
|
210
292
|
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. */
|