gloomberb 0.18.2 → 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/patches/electrobun@1.18.1.patch +106 -5
- 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 +99 -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 +24 -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 +26 -7
- 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/telemetry.ts +17 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/global-shortcuts.ts +1 -16
- 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/runtime/update.ts +28 -8
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/pane-tabs-allowlist.json +65 -0
- 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 +1189 -296
- 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 +272 -70
- 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 +20 -14
- 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 +32 -18
- package/src/cli/issuer-membership.ts +103 -0
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +315 -43
- package/src/cli/name-entries.ts +73 -22
- 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 +77 -20
- package/src/cli/pane-functions/catalog.ts +40 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +12 -8
- 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 +48 -16
- package/src/cli/pane-functions/index.ts +82 -21
- 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 +65 -14
- 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 +190 -27
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +122 -25
- 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 +226 -60
- 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 +387 -21
- package/src/components/chart/composite/drawing-store.ts +26 -6
- package/src/components/chart/composite/interactions.ts +9 -3
- 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 +316 -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 +19 -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/command-items.ts +32 -6
- 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/data-table/view.tsx +23 -3
- 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 +13 -6
- package/src/components/layout/detached-pane-shell.tsx +1 -0
- package/src/components/layout/floating-pane.tsx +1 -0
- package/src/components/layout/header.tsx +234 -60
- 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/pane/header.tsx +10 -3
- package/src/components/layout/pane/index.tsx +1 -0
- package/src/components/layout/pane/pane-tabs.tsx +9 -1
- 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/components/ui/stat-grid.tsx +28 -3
- package/src/components/ui/status.tsx +3 -1
- package/src/core/app-services.ts +4 -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 +51 -12
- package/src/i18n/ja.ts +51 -12
- package/src/i18n/ko.ts +51 -12
- package/src/i18n/zh-cn.ts +51 -12
- package/src/i18n/zh-tw.ts +51 -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 +30 -18
- 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 +108 -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 +77 -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 +107 -43
- package/src/plugins/builtin/attention/pane.tsx +22 -16
- 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 +12 -9
- package/src/plugins/builtin/backtest/export.ts +1 -1
- 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 +24 -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 +115 -26
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
- 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 +34 -18
- 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/client.ts +2 -2
- 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 +9 -11
- 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 +128 -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 +14 -8
- package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
- 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 +89 -31
- 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 +5 -4
- 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 +7 -4
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
- package/src/plugins/builtin/correlation/settings.ts +1 -0
- 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 +7 -5
- 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/credit-documents/pane.tsx +8 -7
- 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/debt-maturities/pane.tsx +4 -3
- 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 +19 -12
- 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 +77 -5
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +34 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
- 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 +16 -10
- 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/board.tsx +4 -1
- package/src/plugins/builtin/gpu/changes.tsx +10 -10
- package/src/plugins/builtin/gpu/equities.tsx +4 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/gpu/history.tsx +4 -2
- package/src/plugins/builtin/gpu/pane.tsx +5 -3
- 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 +15 -2
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +48 -8
- 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/thirteenf-match.ts +3 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/base-values.ts +11 -7
- package/src/plugins/builtin/insider/client.ts +3 -0
- package/src/plugins/builtin/insider/headless.ts +20 -7
- package/src/plugins/builtin/insider/index.tsx +17 -8
- package/src/plugins/builtin/insider/issuer.ts +34 -4
- package/src/plugins/builtin/insider/signals-client.ts +3 -3
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/insider/table-model.ts +35 -13
- package/src/plugins/builtin/insider/table.tsx +5 -2
- 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/events.ts +145 -0
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +91 -7
- 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 +14 -8
- 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 +36 -21
- 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 +33 -11
- 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 +50 -15
- package/src/plugins/builtin/notes/export.ts +17 -6
- package/src/plugins/builtin/notes/files.ts +16 -5
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/enrichment-model.ts +10 -9
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +70 -4
- package/src/plugins/builtin/options/view.tsx +51 -23
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
- package/src/plugins/builtin/options-positioning/headless.ts +11 -3
- package/src/plugins/builtin/options-positioning/model.ts +24 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
- package/src/plugins/builtin/options-scenario/client.ts +142 -29
- 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 +49 -21
- 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 +22 -10
- 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 +145 -60
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
- 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 +6 -3
- 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 +44 -32
- 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/client.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/seasonality/client.ts +2 -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 +6 -4
- 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-resource.ts +15 -2
- 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 +23 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/volatility/options.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/social-mentions/client.ts +2 -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 +28 -7
- package/src/plugins/builtin/vol-surface/headless.ts +43 -15
- package/src/plugins/builtin/vol-surface/model.ts +34 -12
- package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
- package/src/plugins/builtin/vol-surface/stored.ts +34 -3
- package/src/plugins/builtin/vol-surface/tables.ts +14 -0
- 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/desktop/controls.tsx +1 -1
- package/src/renderers/dom/desktop/query-bar.tsx +2 -0
- 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/host/tabs.tsx +16 -5
- package/src/renderers/dom/host/top-surface.ts +127 -0
- package/src/renderers/dom/styles.css +115 -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/core-capabilities.ts +9 -1
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +56 -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/desktop/update.ts +210 -30
- 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 +9 -7
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
- 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 +8 -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 +39 -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/index.ts +16 -0
- 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 +21 -4
- package/src/telemetry/update-failures-node.ts +59 -0
- package/src/telemetry/update-failures.ts +307 -0
- 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 +215 -36
- package/src/tickers/company-name.ts +43 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-fate.ts +30 -0
- 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 +20 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +83 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/issuer-listings.ts +28 -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/failure.ts +163 -0
- package/src/updater/index.ts +97 -28
- 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-pair.ts +26 -0
- 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 +71 -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
|
@@ -46,17 +46,20 @@ import { useResearchCloudSession } from "../shared/research-cloud-session";
|
|
|
46
46
|
import { loadPortfolioRiskMarket } from "./risk-client";
|
|
47
47
|
import { brokerPerformanceEvidence, parsePortfolioRiskEvidence } from "./risk-evidence";
|
|
48
48
|
import { useBrokerPortfolioPerformance } from "./broker-performance";
|
|
49
|
+
import { parseAssetShifts, parseFxShifts, riskCashLines } from "./risk-book";
|
|
50
|
+
import { resolvePortfolioAccountState } from "../portfolio-list/summary";
|
|
49
51
|
import {
|
|
50
52
|
BASKET_VIEWS,
|
|
51
53
|
buildPortfolioRisk,
|
|
54
|
+
HOLDINGS_SHARE_UNIT,
|
|
52
55
|
HOLDINGS_SUMMARY_ROW_IDS,
|
|
56
|
+
isShockRow,
|
|
53
57
|
portfolioRiskRequests,
|
|
54
58
|
portfolioRiskTickers,
|
|
55
|
-
|
|
59
|
+
riskCoverageLine,
|
|
56
60
|
riskCoverageNotices,
|
|
57
61
|
riskCoverageShortfall,
|
|
58
62
|
riskPercentile,
|
|
59
|
-
riskAmountBase,
|
|
60
63
|
riskEvidence,
|
|
61
64
|
riskReturnsCurrency,
|
|
62
65
|
riskValue,
|
|
@@ -98,6 +101,10 @@ const LABEL_HEADERS: Record<RiskView, string> = {
|
|
|
98
101
|
greeks: "Metric",
|
|
99
102
|
};
|
|
100
103
|
const EVIDENCE_VIEWS: ReadonlySet<RiskView> = new Set(["performance", "attribution", "greeks"]);
|
|
104
|
+
/** The risk view's tail rows, whose method the footer names. */
|
|
105
|
+
const TAIL_ROW_IDS: ReadonlySet<string> = new Set(["var", "es"]);
|
|
106
|
+
/** The views that read the basket's daily closes, and say to when; Holdings reads current marks. */
|
|
107
|
+
const DAILY_CLOSE_VIEWS: ReadonlySet<RiskView> = new Set(["risk", "factors", "correlation", "stress"]);
|
|
101
108
|
const ATTRIBUTION_PARTS = [
|
|
102
109
|
{ id: "allocation", label: "Allocation" },
|
|
103
110
|
{ id: "selection", label: "Selection" },
|
|
@@ -113,13 +120,17 @@ const bareValue = (row: RiskDisplayRow) => row.value == null ? "--" : row.value.
|
|
|
113
120
|
const HOLDINGS_SUMMARY_LABELS: Record<string, string> = { top: "Largest", "top-five": "Top five" };
|
|
114
121
|
/** The book concentration figures that lead the holdings view, as a summary band. */
|
|
115
122
|
function holdingsSummaryItems(rows: RiskDisplayRow[]): StatItem[] {
|
|
116
|
-
return rows.map((row) =>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
return rows.map((row) => {
|
|
124
|
+
// A snapshot saved before the shares named their base reads "% value".
|
|
125
|
+
const share = row.unit === HOLDINGS_SHARE_UNIT || row.unit === "% value";
|
|
126
|
+
return {
|
|
127
|
+
id: row.id,
|
|
128
|
+
label: HOLDINGS_SUMMARY_LABELS[row.id] ?? row.label,
|
|
129
|
+
value: row.value == null ? "--" : share ? `${row.value.toFixed(2)}%` : row.value.toFixed(2),
|
|
130
|
+
// The same note sits on both shares: what they divide.
|
|
131
|
+
detail: share ? (row.unit === HOLDINGS_SHARE_UNIT ? "of holdings, cash aside" : "of market value") : row.detail,
|
|
132
|
+
};
|
|
133
|
+
});
|
|
123
134
|
}
|
|
124
135
|
/**
|
|
125
136
|
* Cumulative return of the basket and of its benchmark across the window of
|
|
@@ -224,7 +235,8 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
224
235
|
const instance = usePaneInstance(),
|
|
225
236
|
renderer = useRendererHost();
|
|
226
237
|
const portfolios = useAppSelector((state) => state.config.portfolios),
|
|
227
|
-
tickers = useAppSelector((state) => state.tickers)
|
|
238
|
+
tickers = useAppSelector((state) => state.tickers),
|
|
239
|
+
brokerAccounts = useAppSelector((state) => state.brokerAccounts);
|
|
228
240
|
const focusedCollection = useAppSelector((state) =>
|
|
229
241
|
getFocusedCollectionId(state),
|
|
230
242
|
);
|
|
@@ -271,8 +283,33 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
271
283
|
const [equity] = usePaneSettingValue("equityShift", -10),
|
|
272
284
|
[rates] = usePaneSettingValue("rateShift", 100),
|
|
273
285
|
[volatility] = usePaneSettingValue("volShift", 10),
|
|
286
|
+
[fxShift] = usePaneSettingValue("fxShift", ""),
|
|
287
|
+
[assetShift] = usePaneSettingValue("assetShift", ""),
|
|
274
288
|
[since] = usePaneSettingValue("riskSince", "trailing"),
|
|
275
289
|
[weights] = usePaneSettingValue("riskWeights", "13f");
|
|
290
|
+
// Currency and price shocks as the settings give them; one that does not read is named in the footer, not applied.
|
|
291
|
+
const shocks = useMemo(() => {
|
|
292
|
+
const errors: string[] = [];
|
|
293
|
+
function read<T>(text: unknown, parse: (text: string, flag: string) => T[], label: string): T[] {
|
|
294
|
+
if (!String(text ?? "").trim()) return [];
|
|
295
|
+
try {
|
|
296
|
+
return parse(String(text), label);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
errors.push(error instanceof Error ? error.message : `${label} unreadable`);
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return { fx: read(fxShift, parseFxShifts, "FX shift"), assets: read(assetShift, parseAssetShifts, "Asset shift"), errors };
|
|
303
|
+
}, [fxShift, assetShift]);
|
|
304
|
+
// The cash beside the holdings: the broker account's last saved balances by currency, else the portfolio's own.
|
|
305
|
+
const cash = useMemo(() => {
|
|
306
|
+
if (!portfolio) return [];
|
|
307
|
+
const account = resolvePortfolioAccountState(portfolio, { config, brokerAccounts }, { status: null, accounts: [] })?.account;
|
|
308
|
+
return riskCashLines(portfolio, account);
|
|
309
|
+
}, [brokerAccounts, config, portfolio]);
|
|
310
|
+
// The currencies the load prices, kept by value so a resynced account with the same ones reloads nothing.
|
|
311
|
+
const cashKey = cash.map((line) => line.currency).join(",");
|
|
312
|
+
const cashCurrencies = useMemo(() => (cashKey ? cashKey.split(",") : []), [cashKey]);
|
|
276
313
|
const riskWindow = useMemo(
|
|
277
314
|
() => (since === "filed" ? { since: "filed" as const, weights: weights === "current" ? "current" as const : "13f" as const } : {}),
|
|
278
315
|
[since, weights],
|
|
@@ -302,12 +339,12 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
302
339
|
const loader = useCallback(
|
|
303
340
|
async (force: boolean) => {
|
|
304
341
|
const [market, brokerOptions] = await Promise.all([
|
|
305
|
-
loadPortfolioRiskMarket(requests, force, portfolio!.currency),
|
|
342
|
+
loadPortfolioRiskMarket(requests, force, portfolio!.currency, cashCurrencies),
|
|
306
343
|
loadPortfolioOptionBook(localTickers, portfolio!),
|
|
307
344
|
]);
|
|
308
345
|
return { ...market, brokerOptions };
|
|
309
346
|
},
|
|
310
|
-
[requests, localTickers, portfolio, session.requestKey],
|
|
347
|
+
[requests, localTickers, portfolio, cashCurrencies, session.requestKey],
|
|
311
348
|
);
|
|
312
349
|
const resource = useAsyncResource(!frozen && portfolio ? loader : null, {
|
|
313
350
|
clearOnError: isAccessDenied,
|
|
@@ -335,14 +372,17 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
335
372
|
equity: Number(equity),
|
|
336
373
|
rates: Number(rates),
|
|
337
374
|
volatility: Number(volatility),
|
|
375
|
+
fx: shocks.fx,
|
|
376
|
+
assets: shocks.assets,
|
|
338
377
|
},
|
|
339
378
|
riskWindow,
|
|
379
|
+
cash,
|
|
340
380
|
),
|
|
341
381
|
error: null,
|
|
342
382
|
};
|
|
343
383
|
} catch (error) {
|
|
344
384
|
return {
|
|
345
|
-
model: buildPortfolioRisk(portfolio, localTickers, market, null, undefined, riskWindow),
|
|
385
|
+
model: buildPortfolioRisk(portfolio, localTickers, market, null, undefined, riskWindow, cash),
|
|
346
386
|
error: error instanceof Error ? error.message : "Evidence invalid",
|
|
347
387
|
};
|
|
348
388
|
}
|
|
@@ -356,7 +396,9 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
356
396
|
equity,
|
|
357
397
|
rates,
|
|
358
398
|
volatility,
|
|
399
|
+
shocks,
|
|
359
400
|
riskWindow,
|
|
401
|
+
cash,
|
|
360
402
|
]);
|
|
361
403
|
const model = derived.model;
|
|
362
404
|
const marketLoading = resource.loading && !resource.data;
|
|
@@ -365,8 +407,16 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
365
407
|
if (!model || !BASKET_VIEWS.has(view)) return null;
|
|
366
408
|
if (!frozen && !resource.data)
|
|
367
409
|
return marketLoading ? { loading: true } : resource.error ? { error: resource.error } : null;
|
|
368
|
-
|
|
410
|
+
if (view === "holdings") return null;
|
|
411
|
+
const shortfall = riskCoverageShortfall(model.coverage);
|
|
412
|
+
// The currency and price shocks reprice the book without the basket, so they stay; the footer says why the basket scenarios do not.
|
|
413
|
+
return shortfall && view === "stress" && model.rows.stress.some(isShockRow) ? null : shortfall;
|
|
369
414
|
}, [frozen, marketLoading, model, resource.data, resource.error, view]);
|
|
415
|
+
// Stress with too little covered for the basket scenarios, its shocks shown alone.
|
|
416
|
+
const stressShortfall = useMemo(
|
|
417
|
+
() => (!basketBody && model && view === "stress" ? riskCoverageShortfall(model.coverage) : null),
|
|
418
|
+
[basketBody, model, view],
|
|
419
|
+
);
|
|
370
420
|
const holdingsSummary = useMemo(
|
|
371
421
|
() => view === "holdings" ? holdingsSummaryItems((model?.rows.holdings ?? []).filter((row) => HOLDINGS_SUMMARY_ROW_IDS.has(row.id))) : [],
|
|
372
422
|
[model, view],
|
|
@@ -375,6 +425,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
375
425
|
() =>
|
|
376
426
|
(basketBody ? [] : model?.rows[view] ?? [])
|
|
377
427
|
.filter((row) => view !== "holdings" || !HOLDINGS_SUMMARY_ROW_IDS.has(row.id))
|
|
428
|
+
.filter((row) => !stressShortfall || isShockRow(row))
|
|
378
429
|
.sort((a, b) => {
|
|
379
430
|
if (!sort.column) return 0;
|
|
380
431
|
const left = a[sort.column as keyof RiskDisplayRow],
|
|
@@ -388,7 +439,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
388
439
|
(sort.direction === "asc" ? 1 : -1)
|
|
389
440
|
);
|
|
390
441
|
}),
|
|
391
|
-
[basketBody, model, view, sort],
|
|
442
|
+
[basketBody, stressShortfall, model, view, sort],
|
|
392
443
|
);
|
|
393
444
|
const openRow = rows.find((row) => row.id === open);
|
|
394
445
|
const detailScrollRef = useRef<ScrollBoxRenderable | null>(null);
|
|
@@ -401,6 +452,8 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
401
452
|
rows.length > 1 && rows.every((row) => row.detail === rows[0]!.detail)
|
|
402
453
|
? rows[0]!.detail
|
|
403
454
|
: null;
|
|
455
|
+
// The risk rows read their window in their labels, so the footer names how the tail rows are estimated instead of a column.
|
|
456
|
+
const footerEvidence = (view === "risk" ? rows.find((row) => TAIL_ROW_IDS.has(row.id))?.detail : null) ?? sharedEvidence;
|
|
404
457
|
const importEvidence = useCallback(async () => {
|
|
405
458
|
try {
|
|
406
459
|
const text = await renderer.readText(),
|
|
@@ -461,30 +514,37 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
461
514
|
...riskCoverageNotices(model?.coverage),
|
|
462
515
|
...(model?.notes ?? []),
|
|
463
516
|
...(model?.warnings ?? []),
|
|
517
|
+
...shocks.errors,
|
|
464
518
|
...(derived.error ? [derived.error] : []),
|
|
465
519
|
...(resource.error ? [resource.error] : []),
|
|
466
520
|
];
|
|
467
|
-
// What the basket views leave out, unless the body already says why they show nothing.
|
|
468
|
-
|
|
469
|
-
const
|
|
521
|
+
// What the basket views cover of the book and leave out, unless the body already says why they show nothing.
|
|
522
|
+
// Stress showing its shocks alone says instead why the basket scenarios are not there.
|
|
523
|
+
const coverageText = !model || !BASKET_VIEWS.has(view) || basketBody
|
|
524
|
+
? null
|
|
525
|
+
: stressShortfall
|
|
526
|
+
? `Index, 10Y and VIX scenarios: ${stressShortfall.title.replace(/\.$/, "").replace(/^[A-Z](?=[a-z])/, (letter) => letter.toLowerCase())}`
|
|
527
|
+
: riskCoverageLine(model.coverage);
|
|
528
|
+
const asOfDate = (stressShortfall ? rows : model?.rows[view])?.find((row) => row.asOf)?.asOf?.slice(0, 10) ?? null;
|
|
470
529
|
// The views estimated from returns name the currency a non-USD account's returns were converted into.
|
|
471
|
-
const returnsCurrency = BASKET_VIEWS.has(view) && view !== "holdings" ? riskReturnsCurrency(model) : null;
|
|
472
|
-
const amountBase = rows.map(riskAmountBase).find(Boolean);
|
|
530
|
+
const returnsCurrency = BASKET_VIEWS.has(view) && view !== "holdings" && !stressShortfall ? riskReturnsCurrency(model) : null;
|
|
473
531
|
// Dated evidence only when a row has a date; a missing date is not a claim about history.
|
|
474
532
|
const asOfText = !model
|
|
475
533
|
? null
|
|
476
534
|
: [
|
|
477
535
|
...(basketBody ? [] : [
|
|
478
|
-
...(
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
: [returnsCurrency ?? model.portfolio.currency]),
|
|
483
|
-
...(asOfDate ? [asOfDate] : []),
|
|
536
|
+
...(coverageText ? [coverageText] : []),
|
|
537
|
+
...(asOfDate && footerEvidence ? [footerEvidence] : []),
|
|
538
|
+
// The coverage names the currency of its basket value; a non-USD account's returns say what they converted into.
|
|
539
|
+
...(returnsCurrency ? [returnsCurrency] : coverageText ? [] : [model.portfolio.currency]),
|
|
484
540
|
...(EVIDENCE_VIEWS.has(view) && model.evidence ? [model.evidence.source] : []),
|
|
485
541
|
]),
|
|
486
|
-
...(frozen ? ["snapshot"] : []),
|
|
487
542
|
].join(" · ") || null;
|
|
543
|
+
// What the figures are read from and to when: the basket's daily closes, or the marks and evidence of that day.
|
|
544
|
+
// The shocks alone are repriced at the current marks.
|
|
545
|
+
const sourceText = basketBody || !asOfDate
|
|
546
|
+
? null
|
|
547
|
+
: DAILY_CLOSE_VIEWS.has(view) && !stressShortfall ? `daily closes to ${asOfDate}` : `as of ${asOfDate}`;
|
|
488
548
|
usePaneNoticeFooter({
|
|
489
549
|
registrationId: "portfolio-risk-notices",
|
|
490
550
|
notices,
|
|
@@ -505,12 +565,13 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
505
565
|
},
|
|
506
566
|
]
|
|
507
567
|
: []),
|
|
508
|
-
//
|
|
509
|
-
...(
|
|
510
|
-
? [{
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
568
|
+
// Coverage first: a narrow footer cuts the method and the date before what the numbers cover.
|
|
569
|
+
...(asOfText
|
|
570
|
+
? [{ id: "asof", parts: [{ text: asOfText, tone: "muted" as const }] }]
|
|
571
|
+
: []),
|
|
572
|
+
// The source and its date, which a capture's own dated status line stands in for.
|
|
573
|
+
...(sourceText
|
|
574
|
+
? [{ id: "source", asOf: true, parts: [{ text: sourceText, tone: "muted" as const }] }]
|
|
514
575
|
: []),
|
|
515
576
|
...(actionStatus
|
|
516
577
|
? [
|
|
@@ -523,7 +584,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
523
584
|
],
|
|
524
585
|
hints,
|
|
525
586
|
}),
|
|
526
|
-
[resource.loading,
|
|
587
|
+
[resource.loading, asOfText, sourceText, actionStatus, hints],
|
|
527
588
|
);
|
|
528
589
|
useShortcut(
|
|
529
590
|
(event) => {
|
|
@@ -611,7 +672,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
611
672
|
? []
|
|
612
673
|
: [{ id: "asOf", label: "As of", width: 11, align: "left" as const }]),
|
|
613
674
|
// Attribution's evidence is the three effects, now columns of their own.
|
|
614
|
-
...(width >= 95 && !
|
|
675
|
+
...(width >= 95 && !footerEvidence && !attributionParts
|
|
615
676
|
? [
|
|
616
677
|
{
|
|
617
678
|
id: "detail",
|
|
@@ -623,7 +684,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
623
684
|
]
|
|
624
685
|
: []),
|
|
625
686
|
],
|
|
626
|
-
[width, view, valueHeader, sharedUnit, attributionParts,
|
|
687
|
+
[width, view, valueHeader, sharedUnit, attributionParts, footerEvidence, showPercentile, sharedDate, rows],
|
|
627
688
|
);
|
|
628
689
|
const selectView = (value: string) => {
|
|
629
690
|
setView(value);
|
|
@@ -632,7 +693,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
632
693
|
};
|
|
633
694
|
// The view strip takes a row when it is not in the title bar; the portfolio
|
|
634
695
|
// bar, the holdings summary and the chart sit on the root view only.
|
|
635
|
-
const { strip: tabStrip, rows: tabRows } = usePaneTabs(portfolio
|
|
696
|
+
const { strip: tabStrip, rows: tabRows } = usePaneTabs(portfolio ? {
|
|
636
697
|
tabs,
|
|
637
698
|
activeValue: view,
|
|
638
699
|
onSelect: selectView,
|
|
@@ -650,12 +711,15 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
650
711
|
);
|
|
651
712
|
if (!model)
|
|
652
713
|
return (
|
|
653
|
-
<
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
714
|
+
<Box width={width} height={height} flexDirection="column">
|
|
715
|
+
{tabStrip}
|
|
716
|
+
<PaneStatusBody
|
|
717
|
+
loading={resource.loading}
|
|
718
|
+
error={resource.error}
|
|
719
|
+
loadingLabel="Loading portfolio risk"
|
|
720
|
+
emptyTitle="Risk data unavailable"
|
|
721
|
+
/>
|
|
722
|
+
</Box>
|
|
659
723
|
);
|
|
660
724
|
return (
|
|
661
725
|
<Box width={width} height={height} flexDirection="column">
|
|
@@ -10,6 +10,7 @@ import { useAsyncResource, useAutoRefresh, usePaneSettingValue, usePluginAppActi
|
|
|
10
10
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
11
11
|
import type { PaneProps } from "../../../types/plugin";
|
|
12
12
|
import { Box, ScrollBox, Text, TextAttributes, useRendererHost, useUiCapabilities } from "../../../ui";
|
|
13
|
+
import { withCountryFlag } from "../../../components/ui/country-flag";
|
|
13
14
|
import { SignInWall } from "../cloud/auth-actions";
|
|
14
15
|
import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
|
|
15
16
|
import { useOpenDescription } from "../shared/open-description";
|
|
@@ -123,7 +124,8 @@ export function AttentionPane({ width, height, focused }: PaneProps) {
|
|
|
123
124
|
priceChangePct: null, relativeVolume: null, marketAsOf: null, relativeVolumeAsOf: null, news: [],
|
|
124
125
|
} : undefined);
|
|
125
126
|
useAttentionEvidence((detailMode ? detailData : data) ?? null, tab, selectedSymbol, tab === "history" ? selected?.history.length ?? 0 : rows.length);
|
|
126
|
-
const
|
|
127
|
+
const signInWall = !data && isCloudSessionRequired(resource.error);
|
|
128
|
+
const { strip, rows: tabRows } = usePaneTabs(!signInWall ? { tabs: [...ATTENTION_TABS], activeValue: tab, onSelect: setTab, focused, dense: true } : null);
|
|
127
129
|
useAutoRefresh(resource.updatedAt, resource.load);
|
|
128
130
|
usePaneRefreshKey(() => { void resource.reload(); if (detailMode) void detail.reload(); }, { focused });
|
|
129
131
|
const hints: PaneHint[] = [
|
|
@@ -142,7 +144,7 @@ export function AttentionPane({ width, height, focused }: PaneProps) {
|
|
|
142
144
|
usePaneNoticeFooter({ registrationId: "attention:notices", focused, notices: [resource.data?.refreshError, detailMode ? detail.data?.refreshError : null,
|
|
143
145
|
data?.status === "ready" && selected?.zScore === null ? "The selected ticker has insufficient qualified history for an abnormal-attention score." : null,
|
|
144
146
|
].filter((value): value is string => !!value) });
|
|
145
|
-
if (
|
|
147
|
+
if (signInWall) return <SignInWall placement="attention-signin" action="view research attention" needsVerification={session.needsVerification} />;
|
|
146
148
|
const bodyHeight = Math.max(3, height - tabRows);
|
|
147
149
|
const queryBar = <QueryBar width={width} filters={[{ id: "window", label: "Period", inline: true, value: window, options: WINDOWS,
|
|
148
150
|
onChange: (value: string) => setWindow(value) }, ...(detailMode && data?.rows.length ? [{ id: "ticker", label: "Ticker", value: selectedSymbol,
|
|
@@ -172,13 +174,16 @@ export function AttentionPane({ width, height, focused }: PaneProps) {
|
|
|
172
174
|
color: row.zScore >= 2 ? colors.warning : row.zScore < 0 ? colors.textDim : colors.text, attributes: row.zScore >= 2 ? TextAttributes.BOLD : 0, keepColorWhenSelected: row.zScore >= 2 };
|
|
173
175
|
case "priceChangePct": return row.priceChangePct == null ? missingCell(colors) : { text: rowCell(row, column.id), value: row.priceChangePct, color: signedColor(row.priceChangePct, colors) };
|
|
174
176
|
case "relativeVolume": return row.relativeVolume == null ? missingCell(colors) : { text: rowCell(row, column.id), value: row.relativeVolume, color: row.relativeVolume >= 2 ? colors.textBright : colors.text };
|
|
175
|
-
case "sector":
|
|
177
|
+
case "sector": return { text: rowCell(row, column.id), color: colors.textDim };
|
|
178
|
+
// The column has room for the flag beside a code.
|
|
179
|
+
case "country": return withCountryFlag({ text: rowCell(row, column.id), color: colors.textDim }, row.country, desktop);
|
|
176
180
|
default: return { text: rowCell(row, column.id), value: numeric, color: colors.text };
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
183
|
const value = row[column.id as keyof AttentionGroup];
|
|
180
|
-
|
|
184
|
+
const groupCell: DataTableCell = { text: typeof value === "number" ? number(value) : value, value: typeof value === "number" ? value : undefined,
|
|
181
185
|
color: column.id === "name" ? colors.textBright : column.id === "tickers" ? colors.textDim : colors.text };
|
|
186
|
+
return tab === "countries" && column.id === "name" ? withCountryFlag(groupCell, row.name, desktop) : groupCell;
|
|
182
187
|
};
|
|
183
188
|
// The whole board in four figures; a preview would only summarise its own three rows.
|
|
184
189
|
const top = (groups: readonly AttentionGroup[]) => groups[0] ? { value: groups[0].name, detail: `${number(groups[0].sharePct, 1)}%` } : null;
|
|
@@ -190,24 +195,25 @@ export function AttentionPane({ width, height, focused }: PaneProps) {
|
|
|
190
195
|
...(topSector ? [{ id: "sector", label: "Top sector", ...topSector }] : []),
|
|
191
196
|
...(topCountry ? [{ id: "country", label: "Top country", ...topCountry }] : []),
|
|
192
197
|
] : [];
|
|
198
|
+
// The strip and the period filter stay while a new period loads; only the body waits.
|
|
193
199
|
return <Box width={width} height={height} flexDirection="column">{strip}
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
{detailMode ? <Box flexGrow={1} flexBasis={0} flexDirection="column">{queryBar}
|
|
201
|
+
<PaneStatusBody loading={!data ? resource.loading : !detailData && detail.loading} error={!data ? resource.error : !detailData ? detail.error : null}
|
|
202
|
+
empty={!!data && !!detailData && !selected} subject={!data ? "research attention" : "ticker attention"}
|
|
203
|
+
emptyTitle={data?.entitlement === "preview" ? "This ticker is outside the current preview." : "No privacy-qualified hours for this ticker."}>
|
|
204
|
+
{data && selected ? tab === "history" ? <History row={selected} width={width} height={bodyHeight - 1} focused={focused} preview={data.entitlement === "preview"} />
|
|
205
|
+
: <Evidence row={selected} data={detailData ?? data} width={width} height={bodyHeight - 1} /> : null}
|
|
206
|
+
</PaneStatusBody>
|
|
207
|
+
</Box> : <DataTableView columns={columns} items={data ? items : []} rootWidth={width} rootHeight={bodyHeight} focused={focused && !search.active}
|
|
208
|
+
status={!data ? { loading: resource.loading, error: resource.error, subject: "research attention" }
|
|
209
|
+
: data.status !== "ready" && !data.rows.length ? { empty: true, emptyTitle: emptyAttention(data), subject: "research attention" } : undefined}
|
|
210
|
+
rootBefore={<ChartTableHeader width={width} height={bodyHeight} tableRows={items.length} tableColumns={columns} query={queryBar} figures={figures} />}
|
|
204
211
|
getItemKey={rowId} selection={{ kind: "id", selectedId: groupMode ? groupSelectedId : selected?.symbol ?? null, getId: rowId, onChange: (id) => { if (groupMode) setGroupSelected(id); else if (!id.startsWith("locked:")) setSelected(id); } }}
|
|
205
212
|
onActivate={(row) => { if (isLocked(row)) openUpgrade(); else if ("symbol" in row) { setSelected(row.symbol); setTab("history"); } else { setGroupFilter({ field: tab === "countries" ? "country" : "sector", value: row.name }); setQuery(""); setSelected(null); setTab("ranking"); } }}
|
|
206
213
|
renderCell={cell} selectedTextOverridesCellColor showHorizontalScrollbar
|
|
207
214
|
sortColumnId={!groupMode ? tab === "abnormal" ? "zScore" : sort.column : null} sortDirection={tab === "abnormal" ? "desc" : sort.direction}
|
|
208
215
|
onHeaderClick={!groupMode && tab !== "abnormal" ? (column) => setSort((current) => ({ column, direction: current.column === column && current.direction === "desc" ? "asc" : "desc" })) : undefined}
|
|
209
216
|
emptyStateTitle={tab === "abnormal" ? "Collecting enough qualified history for abnormal attention." : "No published research matches."}
|
|
210
|
-
bodyAfter={hidden && desktop ? <LockedOverlay rows={Math.min(3, hidden)} text="Pro unlocks the full attention graph" onPress={openUpgrade} /> : undefined} />
|
|
211
|
-
</PaneStatusBody>
|
|
217
|
+
bodyAfter={hidden && desktop ? <LockedOverlay rows={Math.min(3, hidden)} text="Pro unlocks the full attention graph" onPress={openUpgrade} /> : undefined} />}
|
|
212
218
|
</Box>;
|
|
213
219
|
}
|
|
@@ -4,7 +4,7 @@ import type { HeadlessBundleSection, HeadlessPaneColumn, HeadlessPaneContext, He
|
|
|
4
4
|
import { DATE_OPTION_EXAMPLES, isoDateOption } from "../../../utils/calendar-date";
|
|
5
5
|
import { resolveHeadlessInstrument } from "../shared/headless-market-data";
|
|
6
6
|
import { fetchAward, fetchAwards } from "./client";
|
|
7
|
-
import { AWARD_TABS, awardScope, awardsPreviewNote, awardTypeLabel, futureAwardDatesNote, money } from "./model";
|
|
7
|
+
import { AWARD_TABS, awardScope, awardsCoverageNotes, awardsEmptyReason, awardsPreviewNote, awardTypeLabel, futureAwardDatesNote, money } from "./model";
|
|
8
8
|
import { REPORT_PAGE, REPORT_ROWS } from "../shared/headless-options";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -113,6 +113,8 @@ export const awardsHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
113
113
|
const missing = filter.ticker && (data.locked || !data.rows.length) ? await notATicker(filter.ticker, ctx) : null;
|
|
114
114
|
const lock = awardsPreviewNote(data, filter);
|
|
115
115
|
const futureDates = futureAwardDatesNote(data.rows, data.generatedAt);
|
|
116
|
+
const notes = [...awardsCoverageNotes(data), ...(futureDates ? [futureDates] : [])];
|
|
117
|
+
const empty = awardsEmptyReason(data);
|
|
116
118
|
const sections: HeadlessBundleSection[] = [];
|
|
117
119
|
const tab = String(args.options.tab ?? "feed");
|
|
118
120
|
if (tab === "feed" || tab === "company" || tab === "all") sections.push({ title: "Awards", columns: FEED_COLUMNS, rows: data.rows.map(awardRecord) });
|
|
@@ -122,8 +124,10 @@ export const awardsHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
122
124
|
{ title: "Sector totals", columns: aggregateColumns("Sector"), rows: data.sectors.map((row) => ({ ...row })) });
|
|
123
125
|
if (tab === "events" || tab === "all") sections.push({ title: "Awards relative to annual revenue", columns: EVENT_COLUMNS, rows: data.alerts.map(awardRecord) });
|
|
124
126
|
return { complete: !data.locked && !data.nextCursor && data.status === "available" && !Object.values(data.truncated ?? {}).some(Boolean), sections,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
// Collection health is what the awards may be missing, a coverage note; only a failure is an error.
|
|
128
|
+
...(notes.length ? { notes } : {}),
|
|
129
|
+
...(empty ? { empty } : {}),
|
|
130
|
+
errors: [...(missing ? [missing] : []), ...(lock ? [lock] : [])],
|
|
127
131
|
// A preview is the same latest awards whatever was asked, so the filters were requested, not applied.
|
|
128
132
|
metadata: { generatedAt: data.generatedAt, asOf: data.asOf, access: data.access, nextCursor: data.nextCursor, truncated: data.truncated, coverage: data.coverage, sources: data.sources,
|
|
129
133
|
filters: filter, filtersApplied: !data.locked } };
|
|
@@ -67,6 +67,24 @@ export function awardsPreviewNote(data: AwardsPayload, filter: AwardFilter): str
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/** The server's word for a selection with no awards: the report's empty line, not a gap in coverage. */
|
|
71
|
+
const NO_AWARDS = "No awards are available for this selection.";
|
|
72
|
+
|
|
73
|
+
/** Why the awards asked for are empty, as the server says it; null while there are some. */
|
|
74
|
+
export function awardsEmptyReason(data: Pick<AwardsPayload, "gaps">): string | null {
|
|
75
|
+
return data.gaps.includes(NO_AWARDS) ? NO_AWARDS : null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Collection health (jurisdictions awaiting a first collection, unfinished
|
|
80
|
+
* windows, quarantined records, a paused or capped store): what the awards
|
|
81
|
+
* shown may be missing, so coverage notes in the pane, `fn AWARDS` and its
|
|
82
|
+
* JSON, never errors.
|
|
83
|
+
*/
|
|
84
|
+
export function awardsCoverageNotes(data: Pick<AwardsPayload, "gaps">): string[] {
|
|
85
|
+
return data.gaps.filter((gap) => gap !== NO_AWARDS);
|
|
86
|
+
}
|
|
87
|
+
|
|
70
88
|
/** Award dates after the response's own date are the source's, not a mapping slip; they say so instead of passing as past awards. */
|
|
71
89
|
export function futureAwardDatesNote(rows: readonly AwardRow[], generatedAt: string): string | null {
|
|
72
90
|
const today = generatedAt.slice(0, 10);
|
|
@@ -12,6 +12,7 @@ import { usePaneTickerIdentity } from "../../../state/hooks/pane-ticker";
|
|
|
12
12
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
13
13
|
import type { PaneProps } from "../../../types/plugin";
|
|
14
14
|
import { Box, Text, TextAttributes, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
|
|
15
|
+
import { withCountryFlag } from "../../../components/ui/country-flag";
|
|
15
16
|
import { publicTickerKey } from "../../../utils/exchanges";
|
|
16
17
|
import { truncateToDisplayWidth } from "../../../utils/format";
|
|
17
18
|
import { SignInWall } from "../cloud/auth-actions";
|
|
@@ -23,7 +24,7 @@ import { AwardDetail } from "./detail";
|
|
|
23
24
|
import { useAwardAlerts } from "./alerts";
|
|
24
25
|
import { AWARDS_UNAVAILABLE, fetchAwards, loadAward, loadAwards, validateAwards } from "./client";
|
|
25
26
|
import { useAwardsEvidence } from "./evidence";
|
|
26
|
-
import { AWARD_TABS, aggregateId, awardHistorySeries, awardPercent, awardPeriod, awardScope, awardsPreviewNote, awardTab, awardTypeLabel, futureAwardDatesNote, money,
|
|
27
|
+
import { AWARD_TABS, aggregateId, awardHistorySeries, awardPercent, awardPeriod, awardScope, awardsCoverageNotes, awardsPreviewNote, awardTab, awardTypeLabel, futureAwardDatesNote, money,
|
|
27
28
|
rankedAggregates } from "./model";
|
|
28
29
|
|
|
29
30
|
type Item = { kind: "award"; row: AwardRow } | { kind: "aggregate"; row: AwardAggregate } | { kind: "leader"; row: AwardCompanyLeader } | { kind: "locked"; id: string }
|
|
@@ -186,7 +187,8 @@ function AwardsView({ width, height, focused, symbol }: PaneProps & { symbol: st
|
|
|
186
187
|
error: data && !denied ? failed?.message ?? null : null, stale: loaded?.stale,
|
|
187
188
|
info: data?.asOf ? [{ id: "asof", parts: [{ text: `as of ${data.asOf.slice(0, 10)}`, tone: "muted" }] }] : [], hints });
|
|
188
189
|
usePaneNoticeFooter({ registrationId: "awards:notices", focused, notices: [
|
|
189
|
-
|
|
190
|
+
// The same coverage notes `fn AWARDS` prints: what the awards shown may be missing.
|
|
191
|
+
...(data ? awardsCoverageNotes(data) : []),
|
|
190
192
|
...(loaded?.refreshError ? [loaded.refreshError] : []),
|
|
191
193
|
...(data?.truncated && Object.values(data.truncated).some(Boolean) ? ["Some aggregate history exceeds this response's limit. Narrow the date range or scope."] : []),
|
|
192
194
|
...(tab === "company" && currencies.length > 1 && !currency ? [`Chart in ${chartCurrency}; select a currency to inspect other obligations.`] : []),
|
|
@@ -221,15 +223,16 @@ function AwardsView({ width, height, focused, symbol }: PaneProps & { symbol: st
|
|
|
221
223
|
if (denied || !data && isCloudSessionRequired(failed?.message)) return <SignInWall placement="awards-signin" action="view government awards" needsVerification={session.needsVerification} />;
|
|
222
224
|
return <Box width={width} height={height} flexDirection="column">
|
|
223
225
|
{strip}
|
|
224
|
-
<
|
|
225
|
-
empty={!data && failed?.message === AWARDS_UNAVAILABLE} emptyTitle={AWARDS_UNAVAILABLE} subject="government awards">
|
|
226
|
-
{data ? <PageStackView focused={focused} detailOpen={!!openId} onBack={() => setOpen(null)} detailTitle={openRow ? truncateToDisplayWidth(openRow.title, Math.max(20, width - 16)) : "Award evidence"}
|
|
226
|
+
<PageStackView focused={focused} detailOpen={!!openId} onBack={() => setOpen(null)} detailTitle={openRow ? truncateToDisplayWidth(openRow.title, Math.max(20, width - 16)) : "Award evidence"}
|
|
227
227
|
detailContent={openRow ? <AwardDetail key={openRow.id} row={openRow} accessKey={accessKey} width={width} height={bodyHeight - 1} focused={focused} openAward={setOpen} openUpgrade={openUpgrade}
|
|
228
228
|
openChildren={(type) => { setParentId(openRow.id); setTicker(""); setSource(""); setQuery(""); setAgency(""); setSector(""); setCurrency(""); setJurisdiction(""); setRange("all"); setType(type); setOpen(null); setTab("feed"); }} />
|
|
229
229
|
: <PaneStatusBody loading={detail.loading} error={detail.error} empty={!detail.loading && !detail.error} emptyTitle="Award no longer available." subject="award evidence" />}
|
|
230
230
|
rootContent={<DataTableView<Item> columns={columns} items={tab === "company" && !ticker ? [] : items} rootWidth={width} rootHeight={bodyHeight}
|
|
231
|
+
// A filter change loads under the query bar, which stays.
|
|
232
|
+
status={data ? undefined : { loading: paged.loading, error: failed?.message !== AWARDS_UNAVAILABLE ? failed?.message : null,
|
|
233
|
+
empty: failed?.message === AWARDS_UNAVAILABLE, emptyTitle: AWARDS_UNAVAILABLE, subject: "government awards" }}
|
|
231
234
|
focused={focused && !openId && !search.active && !tickerSearch.active} scrollRef={tableScrollRef} onBodyScrollActivity={loadMore}
|
|
232
|
-
rootBefore={<ChartTableHeader width={width} height={bodyHeight} tableRows={items.length} tableColumns={columns} query={queryBar} chart={chart}
|
|
235
|
+
rootBefore={<ChartTableHeader width={width} height={bodyHeight} tableRows={items.length} tableColumns={columns} query={queryBar} chart={data ? chart : null}
|
|
233
236
|
figures={tab === "company" && ticker && latest ? [{ id: "total", label: `Obligated ${chartCurrency}`, value: money(latest.cumulativeObligatedAmount) },
|
|
234
237
|
{ id: "period", label: "Latest cohort", value: latest.month.slice(0, 7), detail: awardScope(chartSource) }] : undefined} />}
|
|
235
238
|
selection={{ kind: "id", selectedId: selected ? itemId(selected) : null, getId: itemId, onChange: setSelected }} getItemKey={itemId}
|
|
@@ -268,7 +271,8 @@ function AwardsView({ width, height, focused, symbol }: PaneProps & { symbol: st
|
|
|
268
271
|
if (column.id === "recipient") return { text: award.recipient.name, color: colors.textBright };
|
|
269
272
|
if (column.id === "ticker") return award.entity ? { text: award.entity.ticker, content: <Badge label={award.entity.ticker} /> } : missingCell(colors);
|
|
270
273
|
if (column.id === "agency") return { text: award.agency.name, color: colors.text };
|
|
271
|
-
|
|
274
|
+
// The column has room for the flag beside a code.
|
|
275
|
+
if (column.id === "country") return withCountryFlag({ text: award.jurisdiction, color: colors.textDim }, award.jurisdiction, desktop);
|
|
272
276
|
if (column.id === "period") return { text: awardPeriod(award), color: colors.textDim };
|
|
273
277
|
if (column.id === "title") return { text: award.title, color: colors.text };
|
|
274
278
|
if (column.id === "ratio") return { text: awardPercent(award), value: award.revenueComparison?.percent ?? null, color: colors.warning, attributes: TextAttributes.BOLD, keepColorWhenSelected: true };
|
|
@@ -277,7 +281,6 @@ function AwardsView({ width, height, focused, symbol }: PaneProps & { symbol: st
|
|
|
277
281
|
return { text: award.revenueComparison?.periodEnd ?? "--", color: colors.textDim };
|
|
278
282
|
}}
|
|
279
283
|
emptyStateTitle={tab === "company" && !ticker ? "Enter a company ticker." : tab === "events" ? "No revenue-comparable awards in this scope." : "No awards match these filters."}
|
|
280
|
-
bodyAfter={data
|
|
281
|
-
</PaneStatusBody>
|
|
284
|
+
bodyAfter={data?.locked && desktop ? <LockedOverlay rows={3} text="Upgrade for complete awards and history" onPress={openUpgrade} /> : undefined} />} />
|
|
282
285
|
</Box>;
|
|
283
286
|
}
|
|
@@ -15,7 +15,7 @@ export function backtestEquityCsv(report: HeadlessBundleResult, symbol: string,
|
|
|
15
15
|
const tables = report.sections.flatMap((section): CliReportTable[] => {
|
|
16
16
|
if (!section.rows) return [];
|
|
17
17
|
// The curve's one section, identified as `headlessReportTables` identifies it (no per-row units).
|
|
18
|
-
const table = exportRowsTable(section.title, section.columns ?? [], section.rows);
|
|
18
|
+
const table = exportRowsTable(section.title, section.columns ?? [], section.rows, { status: true });
|
|
19
19
|
return [{
|
|
20
20
|
...table,
|
|
21
21
|
identity: { ...(section.unit ? { currencyOrUnit: section.unit } : {}), ...(section.interval ? { interval: section.interval } : {}) },
|
|
@@ -5,7 +5,7 @@ import { resolveHeadlessInstrument } from "../shared/headless-market-data";
|
|
|
5
5
|
import { createBacktestDependencies, loadBacktestHistory } from "./client";
|
|
6
6
|
import { BACKTEST_PRESETS, DEFAULT_PRESET, lookbackYears, resolveRules } from "./presets";
|
|
7
7
|
import { BACKTEST_FRESHNESS, backtestPriceUnit, backtestReport } from "./report";
|
|
8
|
-
import { parseRule } from "./rules";
|
|
8
|
+
import { parseRule, RULE_SYNTAX } from "./rules";
|
|
9
9
|
import { runHistoryBacktest } from "./window";
|
|
10
10
|
|
|
11
11
|
/** The listing's price unit, as `history` reads it from the quote; null when no quote says. */
|
|
@@ -39,8 +39,8 @@ export const backtestHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
39
39
|
options: [
|
|
40
40
|
{ key: "preset", type: "enum", defaultValue: DEFAULT_PRESET.id, description: "Strategy preset, or custom to use --entry and --exit",
|
|
41
41
|
values: [...BACKTEST_PRESETS.map(({ id }) => ({ value: id })), { value: "custom" }] },
|
|
42
|
-
{ key: "entry", type: "string", defaultValue: "", description:
|
|
43
|
-
{ key: "exit", type: "string", defaultValue: "", description: "Custom exit rule, for example 'close < sma(200)'" },
|
|
42
|
+
{ key: "entry", type: "string", defaultValue: "", description: `Custom entry rule, for example 'close > sma(200)' or 'weekday == 3'. ${RULE_SYNTAX}` },
|
|
43
|
+
{ key: "exit", type: "string", defaultValue: "", description: "Custom exit rule, for example 'close < sma(200)' or 'weekday == 4'. Same operands and comparisons as --entry" },
|
|
44
44
|
{ key: "lookback", type: "enum", defaultValue: "10", values: [{ value: "5" }, { value: "10" }, { value: "max" }], description: "Evaluation years after indicator warmup" },
|
|
45
45
|
{ key: "cost", type: "integer", defaultValue: 5, minimum: 0, maximum: 100, description: "Cost per side in basis points" },
|
|
46
46
|
{ key: "end", type: "string", defaultValue: "", placeholder: "date", example: "--end 2026-10-16 --json",
|