gloomberb 0.18.3 → 0.18.4
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 +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type { Portfolio } from "../../../types/ticker";
|
|
2
|
+
import type { BrokerAccount } from "../../../types/trading";
|
|
3
|
+
import { resolvePortfolioCash } from "../../../portfolio/allocation";
|
|
4
|
+
import { resolveCurrencyUnit } from "../../../utils/currency-units";
|
|
5
|
+
import { canonicalExchange, normalizeSymbol } from "../../../utils/exchanges";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The whole book beside the equity basket: the cash it holds by currency, and
|
|
9
|
+
* the stress shocks that reprice every line of it (holdings and cash) through
|
|
10
|
+
* its currency or its own price, rather than through a basket regression.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** One currency of the cash a portfolio holds beside its positions. */
|
|
14
|
+
export interface RiskCashLine {
|
|
15
|
+
currency: string;
|
|
16
|
+
/** In `currency`; negative for a balance owed. */
|
|
17
|
+
amount: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const ISO_CURRENCY = /^[A-Z]{3}$/;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The portfolio's cash by currency: the broker account's own balances when it
|
|
24
|
+
* reports them per currency, else its total cash (in the portfolio's currency
|
|
25
|
+
* when the account names none), else the amount entered with `portfolio cash set`.
|
|
26
|
+
*/
|
|
27
|
+
export function riskCashLines(
|
|
28
|
+
portfolio: Pick<Portfolio, "cash" | "currency">,
|
|
29
|
+
account: Pick<BrokerAccount, "cashBalances" | "totalCashValue" | "currency"> | null | undefined,
|
|
30
|
+
): RiskCashLine[] {
|
|
31
|
+
const byCurrency = new Map<string, number>();
|
|
32
|
+
for (const balance of account?.cashBalances ?? []) {
|
|
33
|
+
const currency = balance.currency?.trim().toUpperCase() ?? "";
|
|
34
|
+
// A broker's summary row (IBKR's BASE) is no currency of its own.
|
|
35
|
+
if (!ISO_CURRENCY.test(currency) || !Number.isFinite(balance.quantity) || Math.abs(balance.quantity) < 1e-9) continue;
|
|
36
|
+
byCurrency.set(currency, (byCurrency.get(currency) ?? 0) + balance.quantity);
|
|
37
|
+
}
|
|
38
|
+
if (byCurrency.size) return [...byCurrency].map(([currency, amount]) => ({ currency, amount }));
|
|
39
|
+
const line = resolvePortfolioCash(portfolio, account);
|
|
40
|
+
const currency = (line?.currency.trim() || portfolio.currency || "").toUpperCase();
|
|
41
|
+
return line && ISO_CURRENCY.test(currency) && Number.isFinite(line.amount) && line.amount !== 0
|
|
42
|
+
? [{ currency, amount: line.amount }]
|
|
43
|
+
: [];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** A currency's move against USD, in percent of its USD value: TRY -20 is the lira 20% weaker. */
|
|
47
|
+
export interface RiskFxShift {
|
|
48
|
+
currency: string;
|
|
49
|
+
percent: number;
|
|
50
|
+
}
|
|
51
|
+
/** A holding's own price move, in percent, in its listing currency. */
|
|
52
|
+
export interface RiskAssetShift {
|
|
53
|
+
symbol: string;
|
|
54
|
+
exchange?: string;
|
|
55
|
+
percent: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The moves a shock takes, in percent: a fall to nothing is no scenario, a rise past six times is no stress. */
|
|
59
|
+
export const RISK_SHOCK_LIMITS = { minimum: -99, maximum: 500 } as const;
|
|
60
|
+
|
|
61
|
+
/** `-20%` and `+10%` as a shock names its move. */
|
|
62
|
+
const signedPercent = (percent: number) => `${percent > 0 ? "+" : ""}${percent}%`;
|
|
63
|
+
|
|
64
|
+
/** The commas that separate shocks: not a decimal comma between two digits (`TRY -2,5`). */
|
|
65
|
+
const SHOCK_SEPARATOR = /(?<!\d),|,(?!\d)/;
|
|
66
|
+
|
|
67
|
+
/** `TRY -20, EUR 5`: each item a name and a percent, or why one is not. */
|
|
68
|
+
function shockItems(text: string, flag: string, what: string, example: string): Array<{ name: string; percent: number }> {
|
|
69
|
+
const items = text.split(SHOCK_SEPARATOR).map((item) => item.trim()).filter(Boolean);
|
|
70
|
+
if (!items.length) throw new Error(`${flag} takes ${what} and a percent, such as ${example}.`);
|
|
71
|
+
return items.map((item) => {
|
|
72
|
+
const match = /^(\S+)\s+([-+]?\d+(?:[.,]\d+)?)\s*%?$/.exec(item);
|
|
73
|
+
if (!match) throw new Error(`${flag} takes ${what} and a percent, such as ${example}; got "${item}".`);
|
|
74
|
+
const percent = Number(match[2]!.replace(",", "."));
|
|
75
|
+
if (percent < RISK_SHOCK_LIMITS.minimum || percent > RISK_SHOCK_LIMITS.maximum)
|
|
76
|
+
throw new Error(`${flag} moves by ${RISK_SHOCK_LIMITS.minimum}% to +${RISK_SHOCK_LIMITS.maximum}%; got ${match[2]} for ${match[1]}.`);
|
|
77
|
+
return { name: match[1]!, percent };
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** `--fx-shift TRY -20, EUR 5`, read; throws naming what is wrong. */
|
|
82
|
+
export function parseFxShifts(text: string, flag = "--fx-shift"): RiskFxShift[] {
|
|
83
|
+
const shifts = shockItems(text, flag, "a currency", "TRY -20").map(({ name, percent }) => {
|
|
84
|
+
const currency = name.toUpperCase();
|
|
85
|
+
if (!ISO_CURRENCY.test(currency)) throw new Error(`${flag} takes a three-letter currency code such as TRY or EUR; got "${name}".`);
|
|
86
|
+
if (currency === "USD")
|
|
87
|
+
throw new Error(`${flag} moves a currency against USD, so USD itself does not shift: a stronger dollar is the other currency falling (TRY -20).`);
|
|
88
|
+
return { currency, percent };
|
|
89
|
+
});
|
|
90
|
+
const twice = shifts.find((shift, index) => shifts.findIndex((other) => other.currency === shift.currency) !== index);
|
|
91
|
+
if (twice) throw new Error(`${flag} names ${twice.currency} twice.`);
|
|
92
|
+
return shifts;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** `--asset-shift GLD 10, BTC-USD -30`, read; throws naming what is wrong. */
|
|
96
|
+
export function parseAssetShifts(text: string, flag = "--asset-shift"): RiskAssetShift[] {
|
|
97
|
+
const shifts = shockItems(text, flag, "a holding", "GLD 10").map(({ name, percent }) => {
|
|
98
|
+
if (!/^[A-Za-z0-9^][A-Za-z0-9.=^&/-]{0,23}(?::[A-Za-z0-9.]{1,12})?$/.test(name))
|
|
99
|
+
throw new Error(`${flag} takes a holding's symbol, such as GLD or BTC-USD; got "${name}".`);
|
|
100
|
+
const [symbol, exchange] = name.toUpperCase().split(":");
|
|
101
|
+
return { symbol: symbol!, ...(exchange ? { exchange } : {}), percent };
|
|
102
|
+
});
|
|
103
|
+
const key = (shift: RiskAssetShift) => `${shift.symbol}:${shift.exchange ?? ""}`;
|
|
104
|
+
const twice = shifts.find((shift, index) => shifts.findIndex((other) => key(other) === key(shift)) !== index);
|
|
105
|
+
if (twice) throw new Error(`${flag} names ${twice.symbol} twice.`);
|
|
106
|
+
return shifts;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** The canonical text of shocks, as an option keeps it (`TRY -20, EUR 5`). */
|
|
110
|
+
export function formatShocks(shifts: readonly (RiskFxShift | RiskAssetShift)[]): string {
|
|
111
|
+
return shifts.map((shift) => {
|
|
112
|
+
const name = "currency" in shift ? shift.currency : `${shift.symbol}${shift.exchange ? `:${shift.exchange}` : ""}`;
|
|
113
|
+
return `${name} ${shift.percent}`;
|
|
114
|
+
}).join(", ");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** One line of the book to reprice: a holding or a currency's cash. */
|
|
118
|
+
export interface RiskBookLine {
|
|
119
|
+
id: string;
|
|
120
|
+
label: string;
|
|
121
|
+
/** The currency its value moves with against USD: a listing's own (GBP for pence), or the cash's. */
|
|
122
|
+
currency: string;
|
|
123
|
+
/** Signed value in the account currency; null when nothing values it. */
|
|
124
|
+
value: number | null;
|
|
125
|
+
/** The listing an asset shift names; null for cash. */
|
|
126
|
+
listing: { symbol: string; exchange: string } | null;
|
|
127
|
+
}
|
|
128
|
+
interface RiskRepricedLine {
|
|
129
|
+
id: string;
|
|
130
|
+
label: string;
|
|
131
|
+
/** The shocks that move it, as named: "TRY -20% vs USD", "BTC-USD -30%". */
|
|
132
|
+
shocks: string[];
|
|
133
|
+
before: number | null;
|
|
134
|
+
after: number | null;
|
|
135
|
+
change: number | null;
|
|
136
|
+
/** Change in percent of the line's own gross value. */
|
|
137
|
+
percent: number | null;
|
|
138
|
+
}
|
|
139
|
+
/** Every given shock applied at once, each line of the book repriced at its own currency and price. */
|
|
140
|
+
export interface RiskRepricing {
|
|
141
|
+
/** "TRY -20% vs USD, BTC-USD -30%". */
|
|
142
|
+
scenario: string;
|
|
143
|
+
/** Lines a shock moves, largest change first; lines without a value last. */
|
|
144
|
+
lines: RiskRepricedLine[];
|
|
145
|
+
/** The book's net value before the shocks, cash included, in the account currency. */
|
|
146
|
+
bookValue: number;
|
|
147
|
+
change: number;
|
|
148
|
+
/** Change in percent of `bookValue`; null when the book is worth nothing net. */
|
|
149
|
+
percent: number | null;
|
|
150
|
+
/** Lines a shock moves that have no value, so are not in the change. */
|
|
151
|
+
unvalued: string[];
|
|
152
|
+
/** Shocks nothing in the book moves with: a currency it holds nothing in, a holding it does not hold. */
|
|
153
|
+
unmatched: Array<{ kind: "currency" | "holding"; name: string }>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const fxName = (shift: RiskFxShift) => `${shift.currency} ${signedPercent(shift.percent)} vs USD`;
|
|
157
|
+
const assetName = (shift: RiskAssetShift) => `${shift.symbol}${shift.exchange ? `:${shift.exchange}` : ""} ${signedPercent(shift.percent)}`;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Reprices every line of the book under the shocks at once. A line's value in
|
|
161
|
+
* the account currency is its USD value over the USD price of one account
|
|
162
|
+
* unit, so a currency's move changes it by (1 + its currency's move) and (for
|
|
163
|
+
* a listing a shock names) (1 + its own move), over (1 + the account
|
|
164
|
+
* currency's move): TRY -20 takes a fifth off lira cash in a USD account, and
|
|
165
|
+
* adds a quarter to a USD holding in a lira account. Null without a shock.
|
|
166
|
+
*/
|
|
167
|
+
export function repriceBook(
|
|
168
|
+
lines: readonly RiskBookLine[],
|
|
169
|
+
accountCurrency: string,
|
|
170
|
+
fx: readonly RiskFxShift[] = [],
|
|
171
|
+
assets: readonly RiskAssetShift[] = [],
|
|
172
|
+
): RiskRepricing | null {
|
|
173
|
+
if (!fx.length && !assets.length) return null;
|
|
174
|
+
const currencyOf = (currency: string) => resolveCurrencyUnit(currency).currency || "USD";
|
|
175
|
+
const account = currencyOf(accountCurrency);
|
|
176
|
+
const fxShift = new Map(fx.map((shift) => [shift.currency, shift]));
|
|
177
|
+
const matches = (shift: RiskAssetShift, line: RiskBookLine) =>
|
|
178
|
+
!!line.listing && normalizeSymbol(line.listing.symbol) === normalizeSymbol(shift.symbol)
|
|
179
|
+
&& (!shift.exchange || canonicalExchange(line.listing.exchange) === canonicalExchange(shift.exchange));
|
|
180
|
+
const moved = new Set<string>();
|
|
181
|
+
const repriced = lines.flatMap((line): RiskRepricedLine[] => {
|
|
182
|
+
const own = currencyOf(line.currency);
|
|
183
|
+
const ownShift = own === account ? undefined : fxShift.get(own);
|
|
184
|
+
const accountShift = own === account ? undefined : fxShift.get(account);
|
|
185
|
+
const asset = assets.find((shift) => matches(shift, line));
|
|
186
|
+
const factor = (1 + (ownShift?.percent ?? 0) / 100) * (1 + (asset?.percent ?? 0) / 100) / (1 + (accountShift?.percent ?? 0) / 100);
|
|
187
|
+
if (Math.abs(factor - 1) < 1e-12) return [];
|
|
188
|
+
for (const shift of [ownShift, accountShift]) if (shift) moved.add(shift.currency);
|
|
189
|
+
if (asset) moved.add(assetName(asset));
|
|
190
|
+
const shocks = [...(ownShift ? [fxName(ownShift)] : []), ...(accountShift ? [fxName(accountShift)] : []), ...(asset ? [assetName(asset)] : [])];
|
|
191
|
+
if (line.value == null)
|
|
192
|
+
return [{ id: line.id, label: line.label, shocks, before: null, after: null, change: null, percent: null }];
|
|
193
|
+
const after = line.value * factor;
|
|
194
|
+
return [{
|
|
195
|
+
id: line.id, label: line.label, shocks, before: line.value, after, change: after - line.value,
|
|
196
|
+
percent: line.value === 0 ? 0 : ((after - line.value) / Math.abs(line.value)) * 100,
|
|
197
|
+
}];
|
|
198
|
+
}).sort((left, right) => (left.change == null ? 1 : 0) - (right.change == null ? 1 : 0)
|
|
199
|
+
|| Math.abs(right.change ?? 0) - Math.abs(left.change ?? 0));
|
|
200
|
+
const bookValue = lines.reduce((sum, line) => sum + (line.value ?? 0), 0);
|
|
201
|
+
const change = repriced.reduce((sum, line) => sum + (line.change ?? 0), 0);
|
|
202
|
+
return {
|
|
203
|
+
scenario: [...fx.map(fxName), ...assets.map(assetName)].join(", "),
|
|
204
|
+
lines: repriced,
|
|
205
|
+
bookValue,
|
|
206
|
+
change,
|
|
207
|
+
percent: bookValue > 0 ? (change / bookValue) * 100 : null,
|
|
208
|
+
unvalued: repriced.filter((line) => line.change == null).map((line) => line.label),
|
|
209
|
+
unmatched: [
|
|
210
|
+
...fx.filter((shift) => !moved.has(shift.currency)).map((shift) => ({ kind: "currency" as const, name: shift.currency })),
|
|
211
|
+
...assets.filter((shift) => !moved.has(assetName(shift)))
|
|
212
|
+
.map((shift) => ({ kind: "holding" as const, name: `${shift.symbol}${shift.exchange ? `:${shift.exchange}` : ""}` })),
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
@@ -68,7 +68,7 @@ export interface RiskMarketSnapshot {
|
|
|
68
68
|
fetchedAt: string;
|
|
69
69
|
warnings: string[];
|
|
70
70
|
brokerOptions?: import("./risk-options").PortfolioOptionBook;
|
|
71
|
-
/** USD per unit of the account currency
|
|
71
|
+
/** USD per unit of the account currency, of each listing or position currency of the holdings and of each currency of cash, at load time. */
|
|
72
72
|
fxRates?: Record<string, number>;
|
|
73
73
|
/** For an account not in USD: the daily closes its returns convert at, or why they cannot. */
|
|
74
74
|
accountFx?: AccountFx;
|
|
@@ -321,7 +321,8 @@ const largestFirst = (
|
|
|
321
321
|
* USD. Holdings with no FX pair, positions the caller marks unsupported and
|
|
322
322
|
* holdings past the limit get no history request; their entry says why. An
|
|
323
323
|
* account in another currency than USD also loads that currency's current
|
|
324
|
-
* rate and daily FX history, which the model converts every return with
|
|
324
|
+
* rate and daily FX history, which the model converts every return with, and
|
|
325
|
+
* each currency of the book's cash its current rate, which values it. The
|
|
325
326
|
* signal stops the fetch: no request starts once it
|
|
326
327
|
* aborts, the ones in flight are cancelled, and the call rejects instead of
|
|
327
328
|
* returning a partial snapshot nobody is waiting for.
|
|
@@ -332,6 +333,7 @@ export async function fetchPortfolioRiskMarket(
|
|
|
332
333
|
now = new Date(),
|
|
333
334
|
signal?: AbortSignal,
|
|
334
335
|
accountCurrency = "USD",
|
|
336
|
+
cashCurrencies: readonly string[] = [],
|
|
335
337
|
): Promise<RiskMarketSnapshot> {
|
|
336
338
|
signal?.throwIfAborted();
|
|
337
339
|
const normalized = (row: RiskInstrument): RiskInstrument => ({
|
|
@@ -435,6 +437,9 @@ export async function fetchPortfolioRiskMarket(
|
|
|
435
437
|
listings.get(row.id)?.currency ?? (quotes.has(row.id) ? null : row.request.currency),
|
|
436
438
|
).currency;
|
|
437
439
|
return currency && currency !== "USD" ? [currency] : [];
|
|
440
|
+
}), ...cashCurrencies.flatMap((code) => {
|
|
441
|
+
const currency = resolveCurrencyUnit(code).currency;
|
|
442
|
+
return currency && currency !== "USD" ? [currency] : [];
|
|
438
443
|
})],
|
|
439
444
|
),
|
|
440
445
|
].slice(0, MAX_FX_CURRENCIES);
|
|
@@ -663,23 +668,25 @@ export async function fetchPortfolioRiskMarket(
|
|
|
663
668
|
* What changes the requests: identity, size, whether a holding can enter the
|
|
664
669
|
* basket, and an account currency other than USD (whose daily FX the load adds).
|
|
665
670
|
*/
|
|
666
|
-
const cacheKey = (holdings: readonly RiskHoldingRequest[], accountCurrency: string) =>
|
|
671
|
+
const cacheKey = (holdings: readonly RiskHoldingRequest[], accountCurrency: string, cashCurrencies: readonly string[]) =>
|
|
667
672
|
[
|
|
668
673
|
...new Set(
|
|
669
674
|
holdings.map(
|
|
670
675
|
(row) => `${riskInstrumentId(row)}|${row.quantity ?? ""}|${row.currency ?? ""}|${row.unsupported ? 1 : 0}`,
|
|
671
676
|
),
|
|
672
677
|
),
|
|
673
|
-
].sort().join(",") + (accountCurrency === "USD" ? "" : `@${accountCurrency}`)
|
|
678
|
+
].sort().join(",") + (accountCurrency === "USD" ? "" : `@${accountCurrency}`)
|
|
679
|
+
+ (cashCurrencies.length ? `+${[...new Set(cashCurrencies)].sort().join(",")}` : "");
|
|
674
680
|
export async function loadPortfolioRiskMarket(
|
|
675
681
|
holdings: readonly RiskHoldingRequest[],
|
|
676
682
|
force = false,
|
|
677
683
|
accountCurrency = "USD",
|
|
684
|
+
cashCurrencies: readonly string[] = [],
|
|
678
685
|
) {
|
|
679
686
|
const { payload, stale, refreshError } = await loadCloudResource(
|
|
680
687
|
portfolioRiskCache,
|
|
681
|
-
cacheKey(holdings, accountCurrency),
|
|
682
|
-
() => fetchPortfolioRiskMarket(holdings, undefined, undefined, undefined, accountCurrency),
|
|
688
|
+
cacheKey(holdings, accountCurrency, cashCurrencies),
|
|
689
|
+
() => fetchPortfolioRiskMarket(holdings, undefined, undefined, undefined, accountCurrency, cashCurrencies),
|
|
683
690
|
{ force },
|
|
684
691
|
);
|
|
685
692
|
return {
|
|
@@ -3,15 +3,17 @@ import type { HeadlessPaneDefinition } from "../../../types/plugin";
|
|
|
3
3
|
import { fetchPortfolioRiskMarket, RISK_HISTORY_LIMIT } from "./risk-client";
|
|
4
4
|
import { parsePortfolioRiskEvidence } from "./risk-evidence";
|
|
5
5
|
import { describeCollections } from "../../../portfolio/collection-name";
|
|
6
|
+
import { formatShocks, parseAssetShifts, parseFxShifts, riskCashLines } from "./risk-book";
|
|
6
7
|
import {
|
|
7
8
|
BASKET_VIEWS,
|
|
9
|
+
BOOK_TOTAL_ROW_ID,
|
|
8
10
|
buildPortfolioRisk,
|
|
9
11
|
portfolioRiskRequests,
|
|
10
12
|
portfolioRiskTickers,
|
|
13
|
+
riskCoverageLine,
|
|
11
14
|
riskCoverageNotices,
|
|
12
15
|
riskCoverageShortfall,
|
|
13
|
-
|
|
14
|
-
riskExclusionText,
|
|
16
|
+
riskHoldingsLeftOut,
|
|
15
17
|
RISK_VIEWS,
|
|
16
18
|
riskEvidence,
|
|
17
19
|
riskPercentile,
|
|
@@ -53,16 +55,17 @@ const COMPACT_PAIR_LIMIT = 25;
|
|
|
53
55
|
|
|
54
56
|
/**
|
|
55
57
|
* Formatted like the pane; metadata.model keeps full precision. A tail loss in
|
|
56
|
-
* money is of the covered basket, so its evidence names
|
|
57
|
-
* out, as the pane's footer
|
|
58
|
+
* money is of the covered basket, so its evidence names how it is estimated,
|
|
59
|
+
* the basket's share of the book and what it leaves out, as the pane's footer
|
|
60
|
+
* does beside the same figure.
|
|
58
61
|
*/
|
|
59
|
-
function displayRow(row: RiskDisplayRow
|
|
62
|
+
function displayRow(row: RiskDisplayRow) {
|
|
60
63
|
return {
|
|
61
64
|
label: row.label,
|
|
62
65
|
value: riskValue(row),
|
|
63
66
|
percentile: riskPercentile(row),
|
|
64
67
|
asOf: row.asOf?.slice(0, 10) ?? null,
|
|
65
|
-
detail:
|
|
68
|
+
detail: riskEvidence(row),
|
|
66
69
|
...(row.amount != null ? { amount: row.amount, currency: row.amountCurrency ?? null } : {}),
|
|
67
70
|
};
|
|
68
71
|
}
|
|
@@ -77,19 +80,22 @@ const COMPACT_LEFT_OUT_LIMIT = 40;
|
|
|
77
80
|
/** What the basket views cover, so a report never reads as the whole account when it is not. */
|
|
78
81
|
function coverageSummary(coverage: RiskCoverage, limit = Infinity) {
|
|
79
82
|
return {
|
|
83
|
+
// Of the book, cash included; the minimum is of the holdings' value.
|
|
80
84
|
share: coverage.share,
|
|
81
85
|
shareIsUpperBound: coverage.unvalued > 0,
|
|
86
|
+
holdingsShare: coverage.holdingsShare ?? coverage.share,
|
|
82
87
|
minimumShare: coverage.minimumShare,
|
|
83
88
|
estimated: coverage.sufficient,
|
|
84
89
|
currency: coverage.currency,
|
|
85
90
|
marketValue: coverage.marketValue,
|
|
91
|
+
cashValue: coverage.cashValue ?? 0,
|
|
86
92
|
coveredValue: coverage.coveredValue,
|
|
87
93
|
holdings: coverage.holdings,
|
|
88
94
|
covered: coverage.covered,
|
|
89
95
|
convertedFromLocalCurrency: coverage.converted,
|
|
90
96
|
leftOut: coverage.leftOut
|
|
91
97
|
.slice(0, limit)
|
|
92
|
-
.map((row) => ({ symbol: row.symbol, reason: row.reason, share: row.share })),
|
|
98
|
+
.map((row) => ({ symbol: row.symbol, reason: row.reason, share: row.share, ...(row.cash ? { cash: true } : {}) })),
|
|
93
99
|
...(coverage.leftOut.length > limit ? { moreLeftOut: coverage.leftOut.length - limit } : {}),
|
|
94
100
|
};
|
|
95
101
|
}
|
|
@@ -99,9 +105,8 @@ function coverageLine(coverage: RiskCoverage | undefined): { error?: string; not
|
|
|
99
105
|
const shortfall = riskCoverageShortfall(coverage);
|
|
100
106
|
// No estimate at all is a failure; an estimate that leaves holdings out is a caveat.
|
|
101
107
|
if (shortfall) return { error: `Basket estimates unavailable: ${shortfall.title} ${shortfall.message}`.trim() };
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
: {};
|
|
108
|
+
const line = coverage?.leftOut.length ? riskCoverageLine(coverage) : null;
|
|
109
|
+
return line ? { note: `${line[0]!.toUpperCase()}${line.slice(1)}; metadata.coverage lists each with its reason.` } : {};
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
/** One view, its strongest or first rows, and the portfolio's totals instead of the model. */
|
|
@@ -120,15 +125,18 @@ function compactRiskRows(model: PortfolioRiskModel, view: RiskView): { rows: Ris
|
|
|
120
125
|
};
|
|
121
126
|
}
|
|
122
127
|
if (all.length <= COMPACT_ROW_LIMIT) return { rows: all, notices: [] };
|
|
128
|
+
// The book's total of the shocks is what they come to: the lines go before it does.
|
|
129
|
+
const total = all.filter((row) => row.id === BOOK_TOTAL_ROW_ID);
|
|
130
|
+
const rows = [...all.filter((row) => row.id !== BOOK_TOTAL_ROW_ID).slice(0, COMPACT_ROW_LIMIT - total.length), ...total];
|
|
123
131
|
return {
|
|
124
|
-
rows
|
|
125
|
-
notices: [`${all.length -
|
|
132
|
+
rows,
|
|
133
|
+
notices: [`${all.length - rows.length} more ${view} rows not shown.`],
|
|
126
134
|
};
|
|
127
135
|
}
|
|
128
136
|
|
|
129
137
|
export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
130
138
|
shape: "bundle",
|
|
131
|
-
freshness: { source: "Local portfolio and Gloom Cloud", status: "not-a-feed", basis: "
|
|
139
|
+
freshness: { source: "Local portfolio and Gloom Cloud", status: "not-a-feed", basis: "daily closes" },
|
|
132
140
|
argument: {
|
|
133
141
|
kind: "free-text",
|
|
134
142
|
optional: true,
|
|
@@ -143,8 +151,9 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
143
151
|
"Explicit local evidence for account returns and attribution",
|
|
144
152
|
],
|
|
145
153
|
limitations: [
|
|
146
|
-
`Fixed-current-weight equity basket over the holdings that qualify, largest ${RISK_HISTORY_LIMIT} by value, in the account's currency; foreign listings convert to USD at daily FX closes, and a non-USD account's returns then convert into its currency at its own daily FX closes; metadata.coverage states the covered share of
|
|
154
|
+
`Fixed-current-weight equity basket over the holdings that qualify, largest ${RISK_HISTORY_LIMIT} by value, in the account's currency; foreign listings convert to USD at daily FX closes, and a non-USD account's returns then convert into its currency at its own daily FX closes; metadata.coverage states the covered share of the book (cash included) and each holding and currency's cash left out.`,
|
|
147
155
|
"--since filed buys the 13F's own weights at the filing-date close and holds them (--weights current holds today's weights fixed instead).",
|
|
156
|
+
"--fx-shift and --asset-shift reprice every holding and the cash at once; the index, 10Y and VIX shifts are separate basket regressions.",
|
|
148
157
|
"No account performance inferred.",
|
|
149
158
|
"ETF price-return factor proxies.",
|
|
150
159
|
"Historical percentiles need 20 rolling samples.",
|
|
@@ -204,6 +213,27 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
204
213
|
maximum: 100,
|
|
205
214
|
description: "Independent VIX shock in index points (10 when left out).",
|
|
206
215
|
},
|
|
216
|
+
{
|
|
217
|
+
key: "fx-shift",
|
|
218
|
+
type: "string",
|
|
219
|
+
settingKey: "fxShift",
|
|
220
|
+
valueWords: 2,
|
|
221
|
+
placeholder: "CCY pct",
|
|
222
|
+
example: "--fx-shift TRY -20",
|
|
223
|
+
// "TRY -20" read as the lira's move against USD, not USD's against the lira.
|
|
224
|
+
description: "A currency's move against USD in percent: TRY -20 is the lira 20% weaker. Reprices every holding and the cash in that currency, and in a lira account every other line against it. Several separated by commas: TRY -20, EUR 5.",
|
|
225
|
+
normalize: (value) => formatShocks(parseFxShifts(value)),
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
key: "asset-shift",
|
|
229
|
+
type: "string",
|
|
230
|
+
settingKey: "assetShift",
|
|
231
|
+
valueWords: 2,
|
|
232
|
+
placeholder: "SYMBOL pct",
|
|
233
|
+
example: "--asset-shift BTC-USD -30",
|
|
234
|
+
description: "A holding's own price move in percent, in its listing currency: GLD 10, BTC-USD -30. Applied with --fx-shift as one scenario. Several separated by commas.",
|
|
235
|
+
normalize: (value) => formatShocks(parseAssetShifts(value)),
|
|
236
|
+
},
|
|
207
237
|
],
|
|
208
238
|
// The portfolio as configured, so `Family`, `family` and `FAMILY` head the report alike.
|
|
209
239
|
describe: (args, result) =>
|
|
@@ -217,6 +247,8 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
217
247
|
if (!local) throw new Error(unknownPortfolio(requested, ctx.config.portfolios));
|
|
218
248
|
const id = local.portfolio.id;
|
|
219
249
|
const tickers = portfolioRiskTickers(local.tickers, id);
|
|
250
|
+
// The cash beside the holdings: the broker account's by currency, else the portfolio's own.
|
|
251
|
+
const cash = riskCashLines(local.portfolio, local.account);
|
|
220
252
|
const evidence = parsePortfolioRiskEvidence(
|
|
221
253
|
String(args.options.evidence ?? ctx.settings?.riskEvidence ?? ""),
|
|
222
254
|
);
|
|
@@ -248,6 +280,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
248
280
|
new Date(),
|
|
249
281
|
ctx.signal,
|
|
250
282
|
local.portfolio.currency,
|
|
283
|
+
cash.map((line) => line.currency),
|
|
251
284
|
),
|
|
252
285
|
localOnly
|
|
253
286
|
? Promise.resolve(undefined)
|
|
@@ -264,14 +297,17 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
264
297
|
equity: Number(args.options["equity-shift"] ?? -10),
|
|
265
298
|
rates: Number(args.options["rate-shift"] ?? 100),
|
|
266
299
|
volatility: Number(args.options["vol-shift"] ?? 10),
|
|
300
|
+
fx: args.options["fx-shift"] ? parseFxShifts(String(args.options["fx-shift"])) : [],
|
|
301
|
+
assets: args.options["asset-shift"] ? parseAssetShifts(String(args.options["asset-shift"])) : [],
|
|
267
302
|
},
|
|
268
303
|
args.options.since === "filed"
|
|
269
304
|
? { since: "filed", weights: args.options.weights === "current" ? "current" : "13f" }
|
|
270
305
|
: {},
|
|
306
|
+
cash,
|
|
271
307
|
);
|
|
272
308
|
// Options for views the report does not print are named, not dropped silently; the fallback from --since opens the report.
|
|
273
309
|
const fallback = sinceFallbackNote(local.portfolio);
|
|
274
|
-
const shifted = ["equity-shift", "rate-shift", "vol-shift"].filter((key) => args.options[key] != null);
|
|
310
|
+
const shifted = ["equity-shift", "rate-shift", "vol-shift", "fx-shift", "asset-shift"].filter((key) => args.options[key] != null);
|
|
275
311
|
// A non-USD account's returns were converted, and the basket views say into what.
|
|
276
312
|
const returnsCurrency = riskReturnsCurrency(model);
|
|
277
313
|
const notices = [
|
|
@@ -284,8 +320,8 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
284
320
|
...(requestedView && args.options.since != null && requestedView !== "risk" ? [`--since changes the risk view only, not --view ${requestedView}`] : []),
|
|
285
321
|
...(args.options.weights != null && args.options.since !== "filed" ? ["--weights applies with --since filed only"] : []),
|
|
286
322
|
];
|
|
287
|
-
// A basket view is complete only when the basket covers every holding.
|
|
288
|
-
const covered = model.coverage
|
|
323
|
+
// A basket view is complete only when the basket covers every holding; cash is never in it.
|
|
324
|
+
const covered = !riskHoldingsLeftOut(model.coverage);
|
|
289
325
|
const complete =
|
|
290
326
|
view === "performance"
|
|
291
327
|
? model.performance != null
|
|
@@ -300,7 +336,6 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
300
336
|
: model.complete;
|
|
301
337
|
// A basket view with too little covered shows no estimate, and the report says why rather than leaving dashes.
|
|
302
338
|
const shortfall = BASKET_VIEWS.has(view as RiskView) ? coverageLine(model.coverage).error : undefined;
|
|
303
|
-
const exclusion = riskExclusionText(model.coverage);
|
|
304
339
|
return {
|
|
305
340
|
complete,
|
|
306
341
|
errors: [...(shortfall ? [shortfall] : []), ...model.warnings],
|
|
@@ -308,7 +343,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
308
343
|
sections: (requestedView ? [requestedView] : RISK_VIEWS).map((view) => ({
|
|
309
344
|
title: view,
|
|
310
345
|
columns: RISK_COLUMNS,
|
|
311
|
-
rows: model.rows[view].map(
|
|
346
|
+
rows: model.rows[view].map(displayRow),
|
|
312
347
|
})),
|
|
313
348
|
metadata: { coverage: coverageSummary(model.coverage), model, benchmark: model.benchmark, window: model.window, notices },
|
|
314
349
|
};
|
|
@@ -321,7 +356,6 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
321
356
|
// Each left-out holding is in metadata.coverage; the notes keep one line for all of them.
|
|
322
357
|
const perHolding = new Set(riskCoverageNotices(model.coverage));
|
|
323
358
|
const basketView = BASKET_VIEWS.has(view);
|
|
324
|
-
const exclusion = riskExclusionText(model.coverage);
|
|
325
359
|
const coverage = basketView ? coverageLine(model.coverage) : {};
|
|
326
360
|
const errors = [...new Set([...(coverage.error ? [coverage.error] : []), ...(result.errors ?? [])])];
|
|
327
361
|
const notes = [...(coverage.note ? [coverage.note] : []), ...(result.notes ?? []).filter((note) => !perHolding.has(note))];
|
|
@@ -329,7 +363,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
329
363
|
complete: result.complete,
|
|
330
364
|
...(errors.length ? { errors } : {}),
|
|
331
365
|
...(notes.length ? { notes } : {}),
|
|
332
|
-
sections: [{ title: view, columns: RISK_COLUMNS, rows: rows.map(
|
|
366
|
+
sections: [{ title: view, columns: RISK_COLUMNS, rows: rows.map(displayRow) }],
|
|
333
367
|
metadata: {
|
|
334
368
|
portfolio: {
|
|
335
369
|
id: model.portfolio.id,
|
|
@@ -46,13 +46,16 @@ function sampleVolatility(values: readonly number[]): number | null {
|
|
|
46
46
|
) * Math.sqrt(252)
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
|
+
/** The confidence of the one-day VaR and expected shortfall, and the fewest daily returns they are read from. */
|
|
50
|
+
export const RISK_TAIL_CONFIDENCE = 0.95;
|
|
51
|
+
export const RISK_TAIL_MINIMUM = 60;
|
|
49
52
|
/** Nearest-rank historical loss, without distribution or square-root horizon assumptions. */
|
|
50
53
|
export function historicalTail(
|
|
51
54
|
values: readonly number[],
|
|
52
|
-
confidence =
|
|
55
|
+
confidence = RISK_TAIL_CONFIDENCE,
|
|
53
56
|
): { var: number; expectedShortfall: number } | null {
|
|
54
57
|
if (
|
|
55
|
-
values.length <
|
|
58
|
+
values.length < RISK_TAIL_MINIMUM ||
|
|
56
59
|
confidence <= 0 ||
|
|
57
60
|
confidence >= 1 ||
|
|
58
61
|
values.some((value) => !Number.isFinite(value))
|
|
@@ -225,7 +228,7 @@ function basketRiskDefinitions(benchmark: string) {
|
|
|
225
228
|
},
|
|
226
229
|
{
|
|
227
230
|
id: "var",
|
|
228
|
-
name:
|
|
231
|
+
name: `1D VaR ${Math.round(RISK_TAIL_CONFIDENCE * 100)}%`,
|
|
229
232
|
value: (rows: RiskSamplePoint[]) => {
|
|
230
233
|
const tail = historicalTail(rows.map((row) => row.value));
|
|
231
234
|
return tail == null ? null : 100 * tail.var;
|