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
|
@@ -46,6 +46,8 @@ interface PortfolioRiskHolding {
|
|
|
46
46
|
priceAsOf: string | null;
|
|
47
47
|
/** "close" when no current quote arrived and the latest completed close marks the holding. */
|
|
48
48
|
markSource?: "quote" | "close" | null;
|
|
49
|
+
/** The listing currency its closes were converted from at daily FX closes; null for a USD listing. */
|
|
50
|
+
convertedFrom: string | null;
|
|
49
51
|
historyAsOf: string | null;
|
|
50
52
|
returns: DatedReturn[];
|
|
51
53
|
error: string | null;
|
|
@@ -71,6 +73,8 @@ export interface RiskCoverage {
|
|
|
71
73
|
holdings: number;
|
|
72
74
|
/** Holdings that qualify for the basket. */
|
|
73
75
|
covered: number;
|
|
76
|
+
/** Covered holdings whose returns were converted to USD from their listing currency. */
|
|
77
|
+
converted: number;
|
|
74
78
|
unvalued: number;
|
|
75
79
|
minimumShare: number;
|
|
76
80
|
/** The basket views estimate only when qualifying holdings reach the minimum share. */
|
|
@@ -223,24 +227,28 @@ const coveragePercent = (share: number) => Math.floor(share * 100);
|
|
|
223
227
|
const holdingCount = (count: number) => `${count} holding${count === 1 ? "" : "s"}`;
|
|
224
228
|
const shareText = (share: number) =>
|
|
225
229
|
share < 0.001 ? "under 0.1%" : `${(share * 100).toFixed(1)}%`;
|
|
226
|
-
/**
|
|
230
|
+
/**
|
|
231
|
+
* "covers 78% of market value · 9 holdings left out · 2 converted from local
|
|
232
|
+
* currency", or null when every holding is in the basket in its own USD listing.
|
|
233
|
+
*/
|
|
227
234
|
export function riskCoverageText(coverage: RiskCoverage | undefined): string | null {
|
|
228
|
-
if (!coverage
|
|
235
|
+
if (!coverage) return null;
|
|
236
|
+
const converted = coverage.converted ? `${holdingCount(coverage.converted)} converted from local currency` : null;
|
|
237
|
+
if (!coverage.leftOut.length) return converted;
|
|
229
238
|
const covers = coverage.share == null
|
|
230
239
|
? "covers an unknown share of market value"
|
|
231
240
|
: `covers ${coverage.unvalued ? "at most " : ""}${coveragePercent(coverage.share)}% of market value`;
|
|
232
|
-
return
|
|
241
|
+
return [covers, `${holdingCount(coverage.leftOut.length)} left out`, ...(converted ? [converted] : [])].join(" · ");
|
|
233
242
|
}
|
|
234
|
-
/**
|
|
243
|
+
/** A reason reads as the tail of a sentence, so its first word loses its capital unless it is an acronym ("FX", "USD"). */
|
|
244
|
+
const lowerFirst = (text: string) => (/^[A-Z][a-z]/.test(text) ? text[0]!.toLowerCase() + text.slice(1) : text);
|
|
245
|
+
/** One sentence per left-out holding, largest first, naming the holding and why it is out. */
|
|
235
246
|
export function riskCoverageNotices(coverage: RiskCoverage | undefined): string[] {
|
|
236
247
|
if (!coverage?.leftOut.length) return [];
|
|
237
|
-
return
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
`${row.symbol} (${row.share == null ? "value unknown" : `${shareText(row.share)} of market value`}): ${row.reason}`,
|
|
242
|
-
),
|
|
243
|
-
];
|
|
248
|
+
return coverage.leftOut.map(
|
|
249
|
+
(row) =>
|
|
250
|
+
`${row.symbol} (${row.share == null ? "value unknown" : `${shareText(row.share)} of market value`}) is excluded from the risk estimate: ${lowerFirst(row.reason.replace(/\.$/, ""))}.`,
|
|
251
|
+
);
|
|
244
252
|
}
|
|
245
253
|
/** Why the basket views show no estimate, when too little of the account qualifies. */
|
|
246
254
|
export function riskCoverageShortfall(
|
|
@@ -321,10 +329,13 @@ export function buildPortfolioRisk(
|
|
|
321
329
|
? { price: quote.price, currency: quote.currency, stale: !!quote.stale }
|
|
322
330
|
: null;
|
|
323
331
|
const quantity = signedQuantity(lots);
|
|
332
|
+
// A converted listing is marked and returned in USD; its own currency is what the holding records.
|
|
333
|
+
const convertedFrom = history?.converted?.currency ?? null;
|
|
324
334
|
const listingCurrency =
|
|
325
335
|
quote?.currency ?? close?.currency ?? history?.listing?.currency ?? ticker.metadata.currency;
|
|
336
|
+
const foreign = !convertedFrom && listingCurrency !== "USD";
|
|
326
337
|
const error =
|
|
327
|
-
syntheticPositionUnsupportedReason(ticker,
|
|
338
|
+
syntheticPositionUnsupportedReason(ticker, "USD", portfolio.id) ??
|
|
328
339
|
(lots.some((row) => !Number.isFinite(row.shares))
|
|
329
340
|
? "Invalid position quantity"
|
|
330
341
|
: null) ??
|
|
@@ -332,10 +343,14 @@ export function buildPortfolioRisk(
|
|
|
332
343
|
? "Historical account-currency FX is required"
|
|
333
344
|
: null) ??
|
|
334
345
|
(ticker.metadata.currency &&
|
|
335
|
-
mark?.currency &&
|
|
336
|
-
ticker.metadata.currency !== mark
|
|
346
|
+
(convertedFrom ?? mark?.currency) &&
|
|
347
|
+
ticker.metadata.currency !== (convertedFrom ?? mark?.currency)
|
|
337
348
|
? "Holding and quote currencies differ"
|
|
338
349
|
: null) ??
|
|
350
|
+
// A foreign listing that did not convert says why: no pair, stale or gapped FX.
|
|
351
|
+
(foreign
|
|
352
|
+
? (history?.error ?? syntheticPositionUnsupportedReason(ticker, listingCurrency, portfolio.id))
|
|
353
|
+
: null) ??
|
|
339
354
|
history?.error ??
|
|
340
355
|
(!history ? "Daily history unavailable" : null);
|
|
341
356
|
const priceDate = close ? close.date : quoteDate(quote?.lastUpdated);
|
|
@@ -376,6 +391,7 @@ export function buildPortfolioRisk(
|
|
|
376
391
|
: outsideValue(ticker, portfolio, quote ?? history?.listing ?? null, rates),
|
|
377
392
|
priceAsOf: priceDate,
|
|
378
393
|
markSource: close ? "close" : quote ? "quote" : null,
|
|
394
|
+
convertedFrom,
|
|
379
395
|
historyAsOf: history?.asOf ?? null,
|
|
380
396
|
returns,
|
|
381
397
|
error,
|
|
@@ -395,6 +411,7 @@ export function buildPortfolioRisk(
|
|
|
395
411
|
share,
|
|
396
412
|
holdings: holdings.length,
|
|
397
413
|
covered: qualifying.length,
|
|
414
|
+
converted: qualifying.filter((row) => row.convertedFrom != null).length,
|
|
398
415
|
unvalued: holdings.length - valued.length,
|
|
399
416
|
minimumShare: RISK_MIN_COVERAGE,
|
|
400
417
|
sufficient,
|
|
@@ -416,14 +433,24 @@ export function buildPortfolioRisk(
|
|
|
416
433
|
holding.weight =
|
|
417
434
|
book?.rows.find((row) => row.id === holding.id)?.weight ?? null;
|
|
418
435
|
const closeMarked = members.filter((row) => row.markSource === "close").length;
|
|
436
|
+
const converted = members.filter((row) => row.convertedFrom != null).length;
|
|
419
437
|
const held = new Set(holdings.map((row) => row.id));
|
|
420
|
-
|
|
421
|
-
|
|
438
|
+
// Caveats about an estimate that was made; the warnings are what failed.
|
|
439
|
+
const notes = [
|
|
422
440
|
...(closeMarked
|
|
423
441
|
? [
|
|
424
442
|
`${closeMarked} holding${closeMarked === 1 ? "" : "s"} had no current quote; weighted at the latest completed close.`,
|
|
425
443
|
]
|
|
426
444
|
: []),
|
|
445
|
+
// Daily closes pair by date, so a market that closes before or after the US session is not synchronous with it.
|
|
446
|
+
...(converted
|
|
447
|
+
? [
|
|
448
|
+
"Converted holdings are matched to the US close of the same date; where their market closes at another time, correlations and betas to US holdings read lower than they are.",
|
|
449
|
+
]
|
|
450
|
+
: []),
|
|
451
|
+
];
|
|
452
|
+
const warnings = [
|
|
453
|
+
...market.warnings,
|
|
427
454
|
// A held instrument's failure is its left-out reason; factor proxies report here.
|
|
428
455
|
...market.histories.flatMap((row) =>
|
|
429
456
|
row.error && !held.has(riskInstrumentId(row.instrument))
|
|
@@ -561,7 +588,7 @@ export function buildPortfolioRisk(
|
|
|
561
588
|
asOf: row.priceAsOf,
|
|
562
589
|
detail: row.leftOut
|
|
563
590
|
? row.leftOut
|
|
564
|
-
: `${row.quantity} shares; ${formatNumber(row.value ?? undefined)} ${row.currency}${row.markSource === "close" ? ` at ${row.priceAsOf} close` : ""}; history ${row.historyAsOf}`,
|
|
591
|
+
: `${row.quantity} shares; ${formatNumber(row.value ?? undefined)} ${row.currency}${row.markSource === "close" ? ` at ${row.priceAsOf} close` : ""}${row.convertedFrom ? ` from ${row.convertedFrom} at daily FX` : ""}; history ${row.historyAsOf}`,
|
|
565
592
|
...(row.leftOut ? { leftOut: row.leftOut } : {}),
|
|
566
593
|
})),
|
|
567
594
|
correlation: correlation.map((row) => ({
|
|
@@ -733,6 +760,7 @@ export function buildPortfolioRisk(
|
|
|
733
760
|
coverage.leftOut.length === 0 &&
|
|
734
761
|
metrics.some((row) => row.value != null),
|
|
735
762
|
warnings: [...new Set(warnings)],
|
|
763
|
+
notes,
|
|
736
764
|
fetchedAt: market.fetchedAt,
|
|
737
765
|
};
|
|
738
766
|
}
|
|
@@ -444,6 +444,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
444
444
|
// views say what they need in the body, with the import action.
|
|
445
445
|
const notices = [
|
|
446
446
|
...riskCoverageNotices(model?.coverage),
|
|
447
|
+
...(model?.notes ?? []),
|
|
447
448
|
...(model?.warnings ?? []),
|
|
448
449
|
...(derived.error ? [derived.error] : []),
|
|
449
450
|
...(resource.error ? [resource.error] : []),
|
|
@@ -178,14 +178,35 @@ function fredSeries(id: string, asOf: Date): CloudFredSeriesPayload {
|
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Daily closes of the pair that prices `currency` against the dollar, every
|
|
183
|
+
* weekday as FX trades, wobbling around the rate the endpoint reports.
|
|
184
|
+
*/
|
|
185
|
+
function fxPairHistory(symbol: string, asOf: Date): CloudMarketResponse<CloudPricePointPayload[]> | null {
|
|
186
|
+
const currency = symbol.replace(/(USD)?=X$/, "");
|
|
187
|
+
const rate = BROKER_FX_RATES[currency];
|
|
188
|
+
if (rate == null) return null;
|
|
189
|
+
const usdQuoted = symbol.endsWith("USD=X");
|
|
190
|
+
const data: CloudPricePointPayload[] = [];
|
|
191
|
+
const today = Date.parse(asOf.toISOString().slice(0, 10));
|
|
192
|
+
for (let day = today - 240 * 86_400_000; day < today; day += 86_400_000) {
|
|
193
|
+
if ([0, 6].includes(new Date(day).getUTCDay())) continue;
|
|
194
|
+
const usdPerUnit = rate * (1 + Math.sin(data.length / 5) / 100);
|
|
195
|
+
const close = usdQuoted ? usdPerUnit : 1 / usdPerUnit;
|
|
196
|
+
data.push({ date: new Date(day).toISOString(), open: close, high: close, low: close, close });
|
|
197
|
+
}
|
|
198
|
+
return { status: "success", data, providerMeta: { servedResolution: "1d", normalizedSymbol: symbol } };
|
|
199
|
+
}
|
|
200
|
+
|
|
181
201
|
/**
|
|
182
202
|
* Cloud responses for the broker account: US listings and the factor proxies
|
|
183
203
|
* quote and keep daily history, foreign listings quote in their own currency,
|
|
184
|
-
* the uncovered holdings have neither.
|
|
204
|
+
* the uncovered holdings have neither. Daily FX history exists only with `fx`.
|
|
185
205
|
*/
|
|
186
206
|
export function brokerRiskClient(
|
|
187
207
|
asOf: Date = now,
|
|
188
208
|
holdings: readonly BrokerFixtureHolding[] = brokerFixtureHoldings(),
|
|
209
|
+
{ fx = false }: { fx?: boolean } = {},
|
|
189
210
|
) {
|
|
190
211
|
const bySymbol = new Map(holdings.map((holding) => [normalizeSymbol(holding.symbol), holding]));
|
|
191
212
|
const find = (symbol: string) => bySymbol.get(normalizeSymbol(symbol));
|
|
@@ -217,6 +238,9 @@ export function brokerRiskClient(
|
|
|
217
238
|
},
|
|
218
239
|
getCloudHistory: async (symbol: string, exchange: string) => {
|
|
219
240
|
calls.histories.push(symbol);
|
|
241
|
+
if (symbol.endsWith("=X"))
|
|
242
|
+
return (fx && fxPairHistory(symbol, asOf)) ||
|
|
243
|
+
{ status: "empty" as const, data: null, reasonCode: "Daily history unavailable" };
|
|
220
244
|
const holding = find(symbol);
|
|
221
245
|
if (holding && holding.price == null)
|
|
222
246
|
return { status: "empty" as const, data: null, reasonCode: "Daily history unavailable" };
|
|
@@ -15,16 +15,18 @@ export const attentionHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
15
15
|
const metadata = { asOf: data.asOf, stale: data.stale, complete: data.status === "ready" && !data.truncated,
|
|
16
16
|
status: data.status, periodStart: data.periodStart, periodEnd: data.periodEnd, entitlement: data.entitlement,
|
|
17
17
|
privacy: data.privacy, coverage: data.coverage, methodologyUrl: data.methodologyUrl, selectedListing: data.selectedListing ?? null, historyEvidence: data.historyEvidence ?? null, unit: "rounded researcher-hours" };
|
|
18
|
-
|
|
18
|
+
// Published hour by hour, so not a feed, but the service says when publication has fallen behind.
|
|
19
|
+
const freshness = { status: data.stale ? "stale" as const : "not-a-feed" as const, basis: "hourly publication" };
|
|
20
|
+
if (tab === "sectors" || tab === "countries") return { metadata, freshness, sections: [{ title: tab === "sectors" ? "Sector attention" : "Country attention",
|
|
19
21
|
columns: [{ key: "name", header: "Group" }, { key: "researchUnits", header: "Research hours" }, { key: "sharePct", header: "Share %" }, { key: "tickers", header: "Tickers" }], rows: data[tab].map((row) => ({ ...row })) }] };
|
|
20
|
-
if (tab === "history") return { metadata, sections: [{ title: "Published hourly history", columns: [{ key: "symbol", header: "Ticker" },
|
|
22
|
+
if (tab === "history") return { metadata, freshness, sections: [{ title: "Published hourly history", columns: [{ key: "symbol", header: "Ticker" },
|
|
21
23
|
{ key: "bucketStart", header: "Hour (UTC)" }, { key: "researchUnits", header: "Research hours" }],
|
|
22
24
|
rows: data.history && data.selectedListing ? data.history.map((point) => ({ symbol: data.selectedListing!.symbol, ...point })) : data.rows.flatMap((row) => row.history.map((point) => ({ symbol: row.symbol, ...point }))) }] };
|
|
23
|
-
if (tab === "evidence") return { metadata, sections: [{ title: "Publication evidence", columns: [{ key: "symbol", header: "Ticker" },
|
|
25
|
+
if (tab === "evidence") return { metadata, freshness, sections: [{ title: "Publication evidence", columns: [{ key: "symbol", header: "Ticker" },
|
|
24
26
|
{ key: "periodStart", header: "Period start" }, { key: "periodEnd", header: "Period end" }, { key: "asOf", header: "Published" },
|
|
25
27
|
{ key: "confidence", header: "Quality" }, { key: "marketAsOf", header: "Market as of" }],
|
|
26
28
|
rows: data.rows.map((row) => ({ symbol: row.symbol, ...row.evidence, baselinePeriods: row.baselinePeriods, marketAsOf: row.marketAsOf, news: row.news })) }] };
|
|
27
|
-
return { metadata, sections: [{ title: tab === "abnormal" ? "Abnormal attention" : "Research ranking", columns: [
|
|
29
|
+
return { metadata, freshness, sections: [{ title: tab === "abnormal" ? "Abnormal attention" : "Research ranking", columns: [
|
|
28
30
|
{ key: "rank", header: "Rank" }, { key: "symbol", header: "Ticker" }, { key: "name", header: "Name" }, { key: "researchUnits", header: "Research hours" },
|
|
29
31
|
{ key: "sharePct", header: "Share %" }, { key: "zScore", header: "Latest-hour Z-score" }, { key: "priceChangePct", header: "Price %" },
|
|
30
32
|
{ key: "relativeVolume", header: "Relative volume" }, { key: "sector", header: "Sector" }, { key: "country", header: "Country" },
|
|
@@ -7,7 +7,7 @@ import { AttentionPane } from "./pane";
|
|
|
7
7
|
export const attentionModule: PluginModule = {
|
|
8
8
|
panes: [{ id: "attention", name: "Research Attention", icon: "A", component: AttentionPane, defaultPosition: "right", defaultMode: "floating",
|
|
9
9
|
defaultFloatingSize: { width: 126, height: 32 }, tableExport: true, headless: attentionHeadless },
|
|
10
|
-
{ id: "attention-trending", name: "Gloom Trending", icon: "A", component: TrendingPane, defaultPosition: "right", defaultMode: "floating", defaultFloatingSize: { width: 58, height: 12 } }],
|
|
10
|
+
{ id: "attention-trending", reportFreshness: { status: "not-a-feed", basis: "hourly publication" }, name: "Gloom Trending", icon: "A", component: TrendingPane, defaultPosition: "right", defaultMode: "floating", defaultFloatingSize: { width: 58, height: 12 } }],
|
|
11
11
|
paneTemplates: [{ id: "attention-pane", paneId: "attention", label: "Research Attention",
|
|
12
12
|
description: "Pro research attention: rankings, abnormal activity, sectors, countries and privacy-qualified hourly history.",
|
|
13
13
|
keywords: ["attention", "trending", "research", "activity"], shortcut: { prefix: "ATTN", argKind: "text", argPlaceholder: "TICKER", argOptional: true },
|
|
@@ -159,7 +159,7 @@ export function AttentionPane({ width, height, focused }: PaneProps) {
|
|
|
159
159
|
const cell = (row: AttentionRow | AttentionGroup | Locked, column: DataTableColumn, _index: number, state: { selected: boolean }): DataTableCell => {
|
|
160
160
|
if (isLocked(row)) return desktop ? { text: "", content: <Blurred><Text fg={colors.textDim}>{column.id === "name" ? "Additional research" : "Hidden"}</Text></Blurred> }
|
|
161
161
|
: { text: column.id === columns[0]!.id && row.id === "locked:0" ? "Pro" : "░░░", color: colors.textDim };
|
|
162
|
-
if (column.id === "sharePct") return { ...shareCell(number(row.sharePct, 1), maxShare ? row.sharePct / maxShare : null, column.width, colors, state.selected
|
|
162
|
+
if (column.id === "sharePct") return { ...shareCell(number(row.sharePct, 1), maxShare ? row.sharePct / maxShare : null, column.width, colors, state.selected), value: row.sharePct };
|
|
163
163
|
if ("symbol" in row) {
|
|
164
164
|
const numeric = typeof row[column.id as keyof AttentionRow] === "number" ? row[column.id as keyof AttentionRow] as number : undefined;
|
|
165
165
|
switch (column.id) {
|
|
@@ -15,6 +15,7 @@ const awardRecord = (row: AwardRow) => ({ id: row.id, date: row.awardDate, dateB
|
|
|
15
15
|
|
|
16
16
|
export const awardsHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
17
17
|
shape: "bundle", argument: { kind: "free-text", optional: true, placeholder: "ticker", description: "Optional verified listed-company ticker, including exchange suffix." },
|
|
18
|
+
freshness: { source: "Public procurement records", status: "not-a-feed", basis: "published awards" },
|
|
18
19
|
discovery: { aliases: ["AWARDS"], dataRequirements: ["Verified Gloom Cloud account"],
|
|
19
20
|
limitations: ["Pro dataset; free accounts receive a limited preview", "Published procurement records; source coverage varies by jurisdiction",
|
|
20
21
|
"Currencies and prime awards, subawards and notices are separate", "Award obligations are not revenue or remaining backlog", "Unresolved recipients retain their legal names"] },
|
|
@@ -240,7 +240,7 @@ function AwardsView({ width, height, focused, symbol }: PaneProps & { symbol: st
|
|
|
240
240
|
if (column.id === "contracts") return { text: item.row.count.toLocaleString("en-US"), value: item.row.count, color: colors.textDim };
|
|
241
241
|
if (column.id === "scope") return { text: awardScope(item.row.source), color: colors.textDim };
|
|
242
242
|
return item.row.sharePercent === null ? missingCell(colors)
|
|
243
|
-
: { ...shareCell(`${item.row.sharePercent.toFixed(1)}%`, maxShare ? item.row.sharePercent / maxShare : null, column.width, colors, state.selected
|
|
243
|
+
: { ...shareCell(`${item.row.sharePercent.toFixed(1)}%`, maxShare ? item.row.sharePercent / maxShare : null, column.width, colors, state.selected), value: item.row.sharePercent };
|
|
244
244
|
}
|
|
245
245
|
const award = item.row;
|
|
246
246
|
if (column.id === "date") return { text: award.awardDate, value: award.awardDate };
|
|
@@ -8,6 +8,7 @@ import { parseRule } from "./rules";
|
|
|
8
8
|
|
|
9
9
|
export const backtestHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
10
10
|
shape: "bundle",
|
|
11
|
+
freshness: { status: "not-a-feed", basis: "backtest on daily closes", cadence: "daily", observedKey: "date", oldest: null },
|
|
11
12
|
argument: { kind: "ticker", description: "Instrument to test" },
|
|
12
13
|
describe: (args) => `BT ${args.symbols[0] ?? ""}`,
|
|
13
14
|
discovery: {
|
|
@@ -32,6 +32,7 @@ export const bondCalculatorHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
32
32
|
return {
|
|
33
33
|
complete: errors.length === 0,
|
|
34
34
|
errors,
|
|
35
|
+
freshness: { source: "Your inputs, US Treasury", status: "not-a-feed", basis: "calculator", asOf: result.spread?.asOf ?? null },
|
|
35
36
|
metadata: { settlement: draft.settlement, terms: result.terms, source: "Manual bond inputs; Treasury par yields via Gloom Cloud / FRED",
|
|
36
37
|
treasuryAsOf: result.spread?.asOf ?? null, percentile: null, percentileReason: "Hypothetical bond has no historical sample", units: "Prices and DV01 per 100 face", mode: draft.mode },
|
|
37
38
|
sections: [
|
|
@@ -4,6 +4,7 @@ import type { PluginModule } from "../plugin-module";
|
|
|
4
4
|
export const buildoutModule: PluginModule = {
|
|
5
5
|
panes: [{
|
|
6
6
|
id: "buildout",
|
|
7
|
+
reportFreshness: { status: "not-a-feed", basis: "infrastructure research" },
|
|
7
8
|
name: "TheBuildout",
|
|
8
9
|
icon: "T",
|
|
9
10
|
component: BuildoutPane,
|
|
@@ -5,7 +5,9 @@ import { catalystCell, catalystChangeText, catalystDate, catalystQuery, catalyst
|
|
|
5
5
|
|
|
6
6
|
function definition(litigation: boolean): HeadlessPaneDefinition<"bundle"> {
|
|
7
7
|
return {
|
|
8
|
-
shape: "bundle",
|
|
8
|
+
shape: "bundle",
|
|
9
|
+
freshness: { source: litigation ? "Court and agency dockets" : "Regulator, court and trade records", status: "not-a-feed", basis: "published records" },
|
|
10
|
+
argument: { kind: "ticker", optional: !litigation, description: litigation ? "Company ticker, including exchange-qualified international listings." : "Optional ticker; omit for market-wide events." },
|
|
9
11
|
options: [
|
|
10
12
|
{ key: "tab", type: "enum", values: [{ value: "calendar" }, { value: "changes" }], defaultValue: "calendar", description: "Dated events or observed revisions." },
|
|
11
13
|
{ key: "type", type: "enum", values: CATALYST_TYPES.map((value) => ({ value })), description: "Event type." },
|
|
@@ -89,6 +89,8 @@ export function createCdsHeadless(
|
|
|
89
89
|
): HeadlessPaneDefinition<"rows"> {
|
|
90
90
|
return {
|
|
91
91
|
shape: "rows",
|
|
92
|
+
// Public dissemination of swap trades, held back by rule for some trades.
|
|
93
|
+
freshness: { source: "DTCC", status: "delayed" },
|
|
92
94
|
argument: {
|
|
93
95
|
kind: "free-text",
|
|
94
96
|
placeholder: "ticker or issuer",
|
|
@@ -6,6 +6,7 @@ export const centralBankRatesHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
6
6
|
discovery: { aliases: ["CBR", "CBRT"], dataRequirements: ["Gloom Cloud central-bank-rates endpoint"],
|
|
7
7
|
limitations: ["Published policy observations with individual dates", "Policy instruments differ", "Only US meeting dates are maintained"] },
|
|
8
8
|
shape: "bundle", options: [], argument: { kind: "none" }, describe: "G20 central bank policy rates",
|
|
9
|
+
freshness: { source: "Central banks and BIS", status: "not-a-feed", basis: "published policy rates" },
|
|
9
10
|
async load(_args, ctx) {
|
|
10
11
|
const data = await fetchCentralBankRates(ctx.apiClient);
|
|
11
12
|
const errors = policyNotices(data);
|
|
@@ -2,8 +2,10 @@ import { financialPeriodCoverage } from "../../../time-series/financial-period-c
|
|
|
2
2
|
import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../../../utils/financial-statements";
|
|
3
3
|
import { graphRowsForFinancials, summarizeResolvedSeries } from "../../../time-series/reporting";
|
|
4
4
|
import { priceHistoryIntegrityNotices, chartPriceHistoryIntegrityNotices } from "../../../time-series/market";
|
|
5
|
-
import type { HeadlessPaneContext, HeadlessPaneDefinition, HeadlessSeriesResult } from "../../../types/headless";
|
|
6
|
-
import type { ChartResolutionResult, ChartSeriesSpec, ChartSpec } from "../../../time-series/types";
|
|
5
|
+
import type { HeadlessPaneContext, HeadlessPaneDefinition, HeadlessPaneFreshness, HeadlessSeries, HeadlessSeriesResult } from "../../../types/headless";
|
|
6
|
+
import type { CapabilitySeriesSource, ChartResolutionResult, ChartSeriesSpec, ChartSpec, ChartViewportSpec } from "../../../time-series/types";
|
|
7
|
+
import { resolveGeoChartSeries } from "../world-venue-map/geo-series";
|
|
8
|
+
import { GEO_SERIES_CAPABILITY_ID } from "./series-expression";
|
|
7
9
|
import { mergePriceHistoryWindows, priceHistoryAcquisitionIdentity, priceHistoryTailAcquisition, resolveChartSpecData } from "../../../time-series/resolve";
|
|
8
10
|
import { intersectChartResolutionSupport, isIntradayResolution, normalizeChartResolutionSupport, type ManualChartResolution } from "../../../time-series/resolution";
|
|
9
11
|
import { intradaySessionDates, loadIntradayWindow, resolveIntradayRequest, type IntradayRequest, type IntradayWindow, type LoadedIntradayWindow } from "./session-history";
|
|
@@ -16,6 +18,7 @@ import { createChartSeriesResolver } from "../../../capabilities";
|
|
|
16
18
|
import { parsePublicTickerKey, publicTickerKey, resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
17
19
|
import { parseChartSpec } from "./chart-spec";
|
|
18
20
|
import { paneSchemas } from "./headless-schema";
|
|
21
|
+
import { barHistoryFreshness, REPORTED_DATA } from "../shared/report-freshness";
|
|
19
22
|
|
|
20
23
|
export interface ChartPaneModel extends HeadlessSeriesResult {
|
|
21
24
|
/** The renderer consumes the full model; generic reports project series and metadata. */
|
|
@@ -37,6 +40,23 @@ export interface ChartPaneModel extends HeadlessSeriesResult {
|
|
|
37
40
|
};
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Map series read straight from the Cloud client, so a report or screenshot
|
|
45
|
+
* charts them where plugin capability handlers are not running; every other
|
|
46
|
+
* capability series goes through the registry as before.
|
|
47
|
+
*/
|
|
48
|
+
function headlessCapabilityResolver(context: HeadlessPaneContext) {
|
|
49
|
+
const registry = context.capabilities ? createChartSeriesResolver(context.capabilities) : null;
|
|
50
|
+
return async (source: CapabilitySeriesSource, viewport: ChartViewportSpec, spec: ChartSeriesSpec) => {
|
|
51
|
+
if (source.capabilityId === GEO_SERIES_CAPABILITY_ID) {
|
|
52
|
+
const request = <T,>(path: string, init?: RequestInit) => context.apiClient.geo<T>(path, { ...init, signal: init?.signal ?? context.signal });
|
|
53
|
+
return resolveGeoChartSeries(request, source.seriesId, viewport, context.signal);
|
|
54
|
+
}
|
|
55
|
+
if (!registry) throw new Error(`Chart series capability "${source.capabilityId}" is unavailable. Enable its plugin or provider.`);
|
|
56
|
+
return registry(source, viewport, spec);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
40
60
|
export async function loadChartPaneModel(
|
|
41
61
|
spec: ChartSpec,
|
|
42
62
|
context: HeadlessPaneContext,
|
|
@@ -101,7 +121,7 @@ export async function loadChartPaneModel(
|
|
|
101
121
|
if (!primary || rank < primary.rank) primaryHistories.set(key, { key: variantKey, rank });
|
|
102
122
|
}
|
|
103
123
|
},
|
|
104
|
-
|
|
124
|
+
resolveCapabilitySeries: headlessCapabilityResolver(context),
|
|
105
125
|
loadFredSeries: async (request) => ({
|
|
106
126
|
data: await context.apiClient.getCloudFredSeries(request.seriesId, {
|
|
107
127
|
startDate: request.startDate,
|
|
@@ -189,6 +209,20 @@ export async function loadChartPaneModel(
|
|
|
189
209
|
};
|
|
190
210
|
}
|
|
191
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Price series are bar histories, stale once bars of the coarsest size stop
|
|
214
|
+
* arriving; fundamentals, valuations and economic series are reported data.
|
|
215
|
+
*/
|
|
216
|
+
function chartFreshness(series: readonly HeadlessSeries[]): HeadlessPaneFreshness {
|
|
217
|
+
const order = ["1wk", "1mo"];
|
|
218
|
+
const resolutions = series.map((entry) => (entry as HeadlessSeries & { historyResolution?: string }).historyResolution);
|
|
219
|
+
if (!series.length || resolutions.some((resolution) => !resolution)) return { ...REPORTED_DATA, basis: "reported and published data" };
|
|
220
|
+
const coarsest = resolutions.reduce((worst, resolution) => (
|
|
221
|
+
order.indexOf(resolution!) > order.indexOf(worst!) ? resolution : worst
|
|
222
|
+
), resolutions[0]);
|
|
223
|
+
return barHistoryFreshness(coarsest);
|
|
224
|
+
}
|
|
225
|
+
|
|
192
226
|
export function chartHeadless(template: keyof typeof paneSchemas): HeadlessPaneDefinition<"series"> {
|
|
193
227
|
return {
|
|
194
228
|
...paneSchemas[template],
|
|
@@ -262,6 +296,7 @@ export function chartHeadless(template: keyof typeof paneSchemas): HeadlessPaneD
|
|
|
262
296
|
}
|
|
263
297
|
}
|
|
264
298
|
model.snapshot.intradayHistories = intradayHistories;
|
|
299
|
+
model.freshness = chartFreshness(model.series);
|
|
265
300
|
const priceDomainFailures = intradayHistories.flatMap(({ symbol, exchange, priceDomainFailure }) =>
|
|
266
301
|
priceDomainFailure ? [{ symbol, exchange, ...priceDomainFailure }] : []);
|
|
267
302
|
if (priceDomainFailures.length) {
|
|
@@ -253,7 +253,9 @@ const chartComposerTemplates: PaneTemplateDef[] = [
|
|
|
253
253
|
label: "Chart Series",
|
|
254
254
|
placeholder: "AAPL:price, MSFT:revenue, FRED:CPIAUCSL",
|
|
255
255
|
type: "text",
|
|
256
|
-
|
|
256
|
+
// Empty falls back to the active ticker in createInstance, as `G` with no argument does.
|
|
257
|
+
required: false,
|
|
258
|
+
body: ["Enter comma-separated SYMBOL:field or FRED:series expressions, or leave empty to chart the active ticker."],
|
|
257
259
|
}],
|
|
258
260
|
canCreate: () => true,
|
|
259
261
|
createInstance: (context, options) => {
|
|
@@ -33,6 +33,14 @@ export const CHART_FIELD_IDS = {
|
|
|
33
33
|
evEbitda: "valuation.evEbitda",
|
|
34
34
|
} as const;
|
|
35
35
|
|
|
36
|
+
/** Series of things with a place (chokepoint transits, port calls), served with the map's layers. */
|
|
37
|
+
export const GEO_SERIES_CAPABILITY_ID = "geo-series";
|
|
38
|
+
|
|
39
|
+
/** `GEO:<series id or short alias>`, e.g. `GEO:SUEZ`. */
|
|
40
|
+
export function formatGeoSeriesExpression(seriesId: string): string {
|
|
41
|
+
return `GEO:${seriesId}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
export type ParsedSeriesExpression =
|
|
37
45
|
| { kind: "security"; symbol: string; exchange?: string; fieldId: string; label?: string }
|
|
38
46
|
| { kind: "economic"; provider: "fred"; seriesId: string; label?: string }
|
|
@@ -96,6 +104,12 @@ export function parseSeriesExpression(value: string): ParsedSeriesExpression | n
|
|
|
96
104
|
? { kind: "capability", capabilityId, seriesId }
|
|
97
105
|
: null;
|
|
98
106
|
}
|
|
107
|
+
if (parts[0]?.trim().toUpperCase() === "GEO") {
|
|
108
|
+
const seriesId = trimmed.slice(trimmed.indexOf(":") + 1).trim();
|
|
109
|
+
return parts.length >= 2 && isValidChartSeriesId(seriesId)
|
|
110
|
+
? { kind: "capability", capabilityId: GEO_SERIES_CAPABILITY_ID, seriesId }
|
|
111
|
+
: null;
|
|
112
|
+
}
|
|
99
113
|
if (parts[0]?.trim().toUpperCase() === "FRED") {
|
|
100
114
|
const seriesId = parts.length === 2 ? parts[1]?.trim().toUpperCase() ?? "" : "";
|
|
101
115
|
return /^[A-Z0-9._-]{1,80}$/.test(seriesId)
|
|
@@ -160,7 +174,7 @@ export function parseChartExpression(value: string): ParsedSeriesExpression[] {
|
|
|
160
174
|
if (parsed) return parsed;
|
|
161
175
|
const display = leg.trim() || "empty series";
|
|
162
176
|
throw new Error(
|
|
163
|
-
`Invalid chart series "${display}". Use SYMBOL, SYMBOL:field, FUT:code, UST:maturity, FRED:series, or CAP:capability-id:series-id.`,
|
|
177
|
+
`Invalid chart series "${display}". Use SYMBOL, SYMBOL:field, FUT:code, UST:maturity, FRED:series, GEO:series, or CAP:capability-id:series-id.`,
|
|
164
178
|
);
|
|
165
179
|
});
|
|
166
180
|
}
|
|
@@ -168,7 +182,9 @@ export function parseChartExpression(value: string): ParsedSeriesExpression[] {
|
|
|
168
182
|
export function formatSeriesExpression(series: ChartSeriesSpec): string {
|
|
169
183
|
if (series.source.kind === "economic") return `FRED:${series.source.seriesId}`;
|
|
170
184
|
if (series.source.kind === "capability") {
|
|
171
|
-
return
|
|
185
|
+
return series.source.capabilityId === GEO_SERIES_CAPABILITY_ID
|
|
186
|
+
? formatGeoSeriesExpression(series.source.seriesId)
|
|
187
|
+
: `CAP:${series.source.capabilityId}:${series.source.seriesId}`;
|
|
172
188
|
}
|
|
173
189
|
return `${publicTickerKey(series.source.instrument.symbol, series.source.instrument.exchange)}:${series.source.fieldId}`;
|
|
174
190
|
}
|
|
@@ -4,6 +4,8 @@ import type { AppConfig } from "../../../types/config";
|
|
|
4
4
|
import { t } from "../../../i18n";
|
|
5
5
|
import { chatController } from "./controller";
|
|
6
6
|
import { formatChannelLabel } from "./channel-labels";
|
|
7
|
+
import { describeConversationStartError, knownConversationRefusal } from "./direct-messages";
|
|
8
|
+
import { buildChatUserByUsername } from "./content/user-map";
|
|
7
9
|
|
|
8
10
|
export const DEFAULT_CHAT_CHANNEL_ID = "everyone";
|
|
9
11
|
export const LAST_VISITED_CHAT_CHANNEL_KEY = "lastChatChannelId";
|
|
@@ -87,9 +89,23 @@ export async function openDmTargetFromCommand(ctx: GloomPluginContext, usernames
|
|
|
87
89
|
openDefaultChatPane(ctx);
|
|
88
90
|
return;
|
|
89
91
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
// The command bar shows a thrown message as it is, so it says why.
|
|
93
|
+
const snapshot = chatController.getSnapshot();
|
|
94
|
+
const userByUsername = buildChatUserByUsername(snapshot.channels, snapshot.messages);
|
|
95
|
+
const refusal = knownConversationRefusal(usernames, {
|
|
96
|
+
userByUsername,
|
|
97
|
+
currentUserId: snapshot.user?.id,
|
|
98
|
+
channels: snapshot.channels,
|
|
99
|
+
});
|
|
100
|
+
if (refusal) throw new Error(refusal);
|
|
101
|
+
let channel: ChatChannel;
|
|
102
|
+
try {
|
|
103
|
+
channel = usernames.length === 1
|
|
104
|
+
? await chatController.openDirectChannel({ username: usernames[0] })
|
|
105
|
+
: await chatController.openGroupChannel({ usernames });
|
|
106
|
+
} catch (error) {
|
|
107
|
+
throw new Error(describeConversationStartError(error, usernames, userByUsername));
|
|
108
|
+
}
|
|
93
109
|
openChatChannelFromCommand(ctx, channel.id);
|
|
94
110
|
}
|
|
95
111
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, type Dispatch, type SetStateAction } from "react";
|
|
1
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, type Dispatch, type SetStateAction } from "react";
|
|
2
2
|
import type { TextareaRenderable } from "../../../../ui";
|
|
3
3
|
import type { ChatMessage } from "../../../../api-client";
|
|
4
4
|
import {
|
|
@@ -44,6 +44,7 @@ export function useChatComposerRuntime({
|
|
|
44
44
|
useDefaultControllerChannel,
|
|
45
45
|
draftAttachmentCount = 0,
|
|
46
46
|
onPastedImagePaths,
|
|
47
|
+
onConversationStartError,
|
|
47
48
|
}: {
|
|
48
49
|
applyingExternalDraftRef: MutableRef<boolean>;
|
|
49
50
|
blurInput: () => void;
|
|
@@ -74,6 +75,8 @@ export function useChatComposerRuntime({
|
|
|
74
75
|
draftAttachmentCount?: number;
|
|
75
76
|
/** Set where pasted file paths can attach (the terminal): the paths, and the text that named them. */
|
|
76
77
|
onPastedImagePaths?: (paths: string[], pasted: string) => void;
|
|
78
|
+
/** A `/dm` or `/group` command the server refused, with the names it asked for. */
|
|
79
|
+
onConversationStartError?: (error: unknown, usernames: string[]) => void;
|
|
77
80
|
}) {
|
|
78
81
|
const replyToRef = useRef(replyTo);
|
|
79
82
|
const draftAttachmentCountRef = useRef(draftAttachmentCount);
|
|
@@ -256,7 +259,7 @@ export function useChatComposerRuntime({
|
|
|
256
259
|
if (composerCommand.draft) {
|
|
257
260
|
controller.setChannelDraft(channel.id, composerCommand.draft);
|
|
258
261
|
}
|
|
259
|
-
}).catch(() =>
|
|
262
|
+
}).catch((error: unknown) => onConversationStartError?.(error, [composerCommand.username]));
|
|
260
263
|
return;
|
|
261
264
|
}
|
|
262
265
|
if (composerCommand?.kind === "group") {
|
|
@@ -268,7 +271,7 @@ export function useChatComposerRuntime({
|
|
|
268
271
|
channelIdRef.current = channel.id;
|
|
269
272
|
onChannelChange?.(channel.id);
|
|
270
273
|
clearLocalComposer();
|
|
271
|
-
}).catch(() =>
|
|
274
|
+
}).catch((error: unknown) => onConversationStartError?.(error, composerCommand.usernames));
|
|
272
275
|
return;
|
|
273
276
|
}
|
|
274
277
|
const sendChannelId = useDefaultControllerChannel ? channelId : channelIdRef.current;
|
|
@@ -289,6 +292,7 @@ export function useChatComposerRuntime({
|
|
|
289
292
|
controller,
|
|
290
293
|
inputValueRef,
|
|
291
294
|
onChannelChange,
|
|
295
|
+
onConversationStartError,
|
|
292
296
|
expandDirectSection,
|
|
293
297
|
persistDraft,
|
|
294
298
|
setEditingMessage,
|
|
@@ -345,20 +349,31 @@ export function useChatComposerRuntime({
|
|
|
345
349
|
}
|
|
346
350
|
}, [focused, inputFocused, inputRef]);
|
|
347
351
|
|
|
348
|
-
|
|
352
|
+
// The terminal textarea reports edits only through `onContentChange`. It
|
|
353
|
+
// mounts with the composer, which can come after this hook first runs (the
|
|
354
|
+
// saved session landing after the first render on a cold launch, sign-in or
|
|
355
|
+
// email verification finishing, a narrow pane going back to the thread), and
|
|
356
|
+
// a ref change rerenders nothing. So after every render, bind whichever
|
|
357
|
+
// textarea is there now, and let go of the one it replaced.
|
|
358
|
+
const commitLocalDraftRef = useRef(commitLocalDraft);
|
|
359
|
+
commitLocalDraftRef.current = commitLocalDraft;
|
|
360
|
+
const boundTextareaRef = useRef<TextareaRenderable | null>(null);
|
|
361
|
+
useLayoutEffect(() => {
|
|
349
362
|
const textarea = inputRef.current;
|
|
363
|
+
const bound = boundTextareaRef.current;
|
|
364
|
+
if (textarea === bound) return;
|
|
365
|
+
if (bound) bound.onContentChange = undefined;
|
|
366
|
+
boundTextareaRef.current = textarea;
|
|
350
367
|
if (!textarea) return;
|
|
351
|
-
|
|
352
368
|
textarea.onContentChange = () => {
|
|
353
|
-
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
return () => {
|
|
357
|
-
if (textarea) {
|
|
358
|
-
textarea.onContentChange = undefined;
|
|
359
|
-
}
|
|
369
|
+
commitLocalDraftRef.current(textarea.editBuffer.getText());
|
|
360
370
|
};
|
|
361
|
-
}
|
|
371
|
+
});
|
|
372
|
+
useLayoutEffect(() => () => {
|
|
373
|
+
const bound = boundTextareaRef.current;
|
|
374
|
+
boundTextareaRef.current = null;
|
|
375
|
+
if (bound) bound.onContentChange = undefined;
|
|
376
|
+
}, []);
|
|
362
377
|
|
|
363
378
|
useEffect(() => {
|
|
364
379
|
if (canSend || !replyTo) return;
|