gloomberb 0.18.3 → 0.18.5
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 +32 -1
- package/src/account/auth-model.ts +7 -3
- 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 +11 -6
- package/src/api-client/catalysts.ts +2 -1
- 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 +98 -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 +182 -16
- package/src/api-client/live-scan.ts +91 -0
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +18 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +224 -26
- package/src/api-client/research-activity.ts +3 -10
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +96 -2
- package/src/app/keybindings/index.ts +3 -0
- package/src/app/keybindings/labels.ts +18 -1
- package/src/app/keybindings/resolve.ts +14 -0
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/broker-import.ts +43 -26
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +9 -2
- package/src/cli/commands/keybindings.ts +25 -2
- package/src/cli/commands/market.ts +1177 -278
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-chain.ts +59 -3
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +222 -61
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +82 -46
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +194 -48
- 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 +21 -3
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +38 -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 +113 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +226 -50
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +123 -27
- package/src/cli/listing-arg.ts +316 -46
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +193 -30
- package/src/cli/pane-functions/function-help.ts +76 -30
- package/src/cli/pane-functions/headless.ts +59 -12
- package/src/cli/pane-functions/index.ts +28 -19
- package/src/cli/pane-functions/market-session.ts +15 -5
- 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 +10 -6
- package/src/cli/pane-functions/resolver.ts +64 -11
- 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 +45 -4
- package/src/cli/report-tables.ts +75 -19
- package/src/cli/restore-plugins.ts +42 -15
- package/src/cli/result.ts +164 -23
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +395 -20
- package/src/components/chart/composite/format.ts +27 -0
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +7 -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-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +314 -13
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/range-statistics.ts +62 -0
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +20 -4
- package/src/components/chart/composite/series-axis-tags.tsx +16 -9
- 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 +17 -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/panel/prompt-binding.ts +0 -8
- 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/alert.ts +1 -1
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +33 -46
- 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/index.tsx +1 -0
- package/src/components/layout/pane/footer/model.ts +38 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-frame.tsx +1 -1
- 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/portfolio-step/positions-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 +10 -2
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +6 -4
- package/src/core/state/app/state.ts +9 -0
- package/src/core/state/app/types.ts +3 -0
- 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 +123 -0
- package/src/docs/snapshot.json +422 -112
- package/src/i18n/es.ts +30 -13
- package/src/i18n/ja.ts +30 -13
- package/src/i18n/ko.ts +30 -13
- package/src/i18n/zh-cn.ts +30 -13
- package/src/i18n/zh-tw.ts +30 -13
- 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/coordinator/financials.ts +10 -2
- package/src/market-data/coordinator/index.ts +3 -1
- package/src/market-data/coordinator/quotes.ts +4 -2
- 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 +81 -11
- package/src/market-data/market/dated-previous-close.ts +203 -0
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/futures-week.ts +68 -0
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/status.ts +16 -4
- 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/options-alternatives.ts +60 -0
- 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 +25 -3
- 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 +7 -2
- package/src/market-data/selectors.ts +3 -0
- 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/notifications/notification-log.ts +6 -4
- 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 +34 -20
- package/src/plugins/builtin/alerts/calendar-events.ts +429 -0
- package/src/plugins/builtin/alerts/cli.ts +533 -85
- package/src/plugins/builtin/alerts/command.ts +12 -10
- package/src/plugins/builtin/alerts/constants.ts +1 -1
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +119 -0
- package/src/plugins/builtin/alerts/format.ts +10 -3
- package/src/plugins/builtin/alerts/headless.ts +107 -41
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +92 -0
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +107 -30
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/live.ts +3 -3
- package/src/plugins/builtin/alerts/metric-command.ts +61 -0
- package/src/plugins/builtin/alerts/metric-data.ts +70 -0
- package/src/plugins/builtin/alerts/metric-model.ts +175 -0
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
- package/src/plugins/builtin/alerts/pane.tsx +130 -49
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +38 -12
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/alerts/types.ts +3 -0
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +13 -8
- package/src/plugins/builtin/backtest/pane.tsx +9 -4
- package/src/plugins/builtin/backtest/presets.ts +29 -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 +24 -14
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +18 -3
- 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 +66 -24
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +19 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +83 -10
- 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 +111 -24
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +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 +51 -5
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +4 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +3 -2
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +7 -10
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -3
- package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -0
- package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +9 -4
- package/src/plugins/builtin/chart-composer/formula.ts +71 -18
- package/src/plugins/builtin/chart-composer/headless-schema.ts +42 -29
- package/src/plugins/builtin/chart-composer/headless.ts +266 -37
- 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 +144 -30
- package/src/plugins/builtin/chart-composer/presets.ts +50 -15
- package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
- 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 +31 -28
- 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 +44 -31
- 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/command-suggestions.ts +92 -0
- package/src/plugins/builtin/chat/content/composer.tsx +13 -6
- package/src/plugins/builtin/chat/content/footer.tsx +6 -3
- package/src/plugins/builtin/chat/content/index.tsx +51 -22
- package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
- package/src/plugins/builtin/chat/index.tsx +23 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
- package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
- package/src/plugins/builtin/chat/pane-links/commands.ts +265 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
- package/src/plugins/builtin/chat/pane-links/open.ts +9 -2
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -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/plugin.tsx +1 -1
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +144 -27
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/figures.ts +72 -0
- 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 +144 -27
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +34 -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 +87 -28
- 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 +104 -0
- package/src/plugins/builtin/econ-statistics/view.ts +19 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +47 -12
- 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/charts.tsx +2 -2
- 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 +20 -1
- package/src/plugins/builtin/exposure/pane.tsx +10 -5
- 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/index.tsx +1 -0
- package/src/plugins/builtin/futures/model.ts +12 -10
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +3 -3
- 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 +20 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +37 -16
- package/src/plugins/builtin/fx-matrix/index.tsx +25 -13
- package/src/plugins/builtin/fx-matrix/live-legs.ts +34 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +7 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +51 -13
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/footer.ts +2 -2
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/breadth-pane.tsx +81 -0
- package/src/plugins/builtin/members/client.ts +19 -4
- package/src/plugins/builtin/members/headless.ts +24 -10
- package/src/plugins/builtin/members/index.tsx +9 -9
- package/src/plugins/builtin/members/model.ts +23 -4
- package/src/plugins/builtin/members/pane.tsx +31 -14
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/analytics.ts +26 -2
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +5 -2
- package/src/plugins/builtin/options/strike-window.ts +2 -1
- package/src/plugins/builtin/options/table.ts +1 -7
- package/src/plugins/builtin/options/view.tsx +30 -13
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-positioning/client.ts +19 -0
- package/src/plugins/builtin/options-positioning/headless.ts +54 -14
- package/src/plugins/builtin/options-positioning/index.tsx +3 -3
- package/src/plugins/builtin/options-positioning/model.ts +47 -8
- package/src/plugins/builtin/options-positioning/pane.tsx +68 -38
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +14 -9
- 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 +168 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +49 -26
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +54 -22
- 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 +7 -4
- 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/index.tsx +11 -8
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/rate-path/pane.tsx +2 -2
- 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 +80 -13
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/feed.ts +2 -2
- package/src/plugins/builtin/scanner/index.ts +24 -1
- package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
- package/src/plugins/builtin/scanner/live-feed.ts +168 -0
- package/src/plugins/builtin/scanner/live-headless.ts +114 -0
- package/src/plugins/builtin/scanner/live-model.ts +351 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
- package/src/plugins/builtin/scanner/live-track.ts +186 -0
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +3 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/macro-releases.ts +65 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +8 -2
- package/src/plugins/builtin/shared/volatility/pricing.ts +7 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +11 -6
- package/src/plugins/builtin/themes/model.ts +15 -5
- package/src/plugins/builtin/themes/pane.tsx +27 -8
- 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 +14 -4
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
- package/src/plugins/builtin/vol-surface/client.ts +7 -4
- package/src/plugins/builtin/vol-surface/headless.ts +71 -13
- package/src/plugins/builtin/vol-surface/index.tsx +2 -2
- package/src/plugins/builtin/vol-surface/model.ts +26 -9
- package/src/plugins/builtin/vol-surface/pane.tsx +44 -7
- package/src/plugins/builtin/vol-surface/tables.ts +31 -3
- package/src/plugins/builtin/volatility/dvol.ts +46 -0
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/volatility/pane.tsx +2 -2
- package/src/plugins/builtin/volatility/series.ts +26 -0
- package/src/plugins/builtin/world-indices/footer.ts +1 -1
- 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 +15 -9
- 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 +15 -13
- 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 +15 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/app-services.ts +1 -7
- package/src/renderers/browser/config-host.ts +5 -55
- package/src/renderers/browser/main.tsx +30 -60
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
- 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/relaunch.ts +74 -25
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +70 -3
- package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +36 -2
- 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/app-name.ts +17 -0
- 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/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/opentui/toast-host.tsx +71 -43
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +16 -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/batches.ts +10 -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 +58 -15
- package/src/sources/provider-router/index.ts +146 -10
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/sources/provider-router/search.ts +13 -2
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/app/context/index.tsx +3 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/auth-transition.ts +19 -9
- package/src/sync/baseline.ts +10 -4
- package/src/sync/controller.ts +67 -17
- package/src/sync/core-contributors.ts +46 -14
- package/src/sync/react.ts +4 -1
- package/src/sync/types.ts +3 -0
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/telemetry/usage-counts.ts +0 -18
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +11 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/company-name.ts +59 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-venues.ts +23 -0
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/bare-symbol.ts +36 -0
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +111 -33
- package/src/tickers/search/ranking.ts +64 -5
- package/src/tickers/search/types.ts +5 -0
- 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 +315 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/daily-valuation.ts +62 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/field-catalog.ts +1 -3
- package/src/time-series/forward-valuation.ts +32 -0
- package/src/time-series/fundamentals.ts +173 -10
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/hooks.ts +1 -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/price-units.ts +72 -2
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +161 -0
- package/src/time-series/resolve.ts +185 -1587
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +242 -0
- package/src/time-series/spec.ts +13 -7
- package/src/time-series/studies.ts +377 -82
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/transforms.ts +1 -0
- package/src/time-series/types.ts +34 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/time-series/valuation-releases.ts +39 -0
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +23 -1
- package/src/types/desktop-window.ts +2 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +145 -8
- package/src/types/headless.ts +117 -9
- package/src/types/instrument.ts +6 -0
- package/src/types/plugin.ts +66 -9
- 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 +180 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +89 -5
- 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 +86 -0
- package/src/utils/option-expiry.ts +186 -7
- package/src/utils/options.ts +10 -0
- package/src/utils/plugin-proxy-hosts.json +1 -0
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +23 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
- package/src/renderers/browser/first-screen.ts +0 -193
|
@@ -1,14 +1,40 @@
|
|
|
1
|
+
import type { PaneTemplateContext, ShortcutArgError } from "../../../types/plugin";
|
|
2
|
+
import { findNamedCollection, unknownCollectionArgError } from "../../../portfolio/collection-name";
|
|
1
3
|
import type { PluginModule } from "../plugin-module";
|
|
2
4
|
import { exposureHeadless } from "./headless";
|
|
3
5
|
import { ExposurePane } from "./pane";
|
|
4
6
|
|
|
7
|
+
const SOURCE = /^(PORT|WATCH):(.+)$/i;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `EXPO PORT:Book` names a portfolio, and `WATCH:Watchlist` a watchlist, by
|
|
11
|
+
* name or id in any case, as `fn EXPO` reads them. The pane keeps its source
|
|
12
|
+
* by id (`PORT:book`), so the name is rewritten to the id it names.
|
|
13
|
+
*/
|
|
14
|
+
function sourceInput(arg: string, context: PaneTemplateContext): string {
|
|
15
|
+
const source = SOURCE.exec(arg.trim());
|
|
16
|
+
if (!source) return arg;
|
|
17
|
+
const prefix = source[1]!.toUpperCase();
|
|
18
|
+
const match = findNamedCollection(prefix === "PORT" ? context.config.portfolios : context.config.watchlists, source[2]);
|
|
19
|
+
return match ? `${prefix}:${match.id}` : arg;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** `EXPO PORT:Nope` or `EXPO WATCH:Nope` names a portfolio or watchlist nothing has; tickers and weights are read by the pane. */
|
|
23
|
+
function unknownSourceArg(arg: string, context: PaneTemplateContext): ShortcutArgError | null {
|
|
24
|
+
const source = SOURCE.exec(arg.trim());
|
|
25
|
+
if (!source) return null;
|
|
26
|
+
return source[1]!.toUpperCase() === "PORT"
|
|
27
|
+
? unknownCollectionArgError(source[2]!, context.config.portfolios, "portfolio", (name) => `PORT:${name}`)
|
|
28
|
+
: unknownCollectionArgError(source[2]!, context.config.watchlists, "watchlist", (name) => `WATCH:${name}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
5
31
|
export const exposureModule: PluginModule = {
|
|
6
32
|
panes: [{ id: "exposure", name: "Exposure", icon: "E", component: ExposurePane, defaultPosition: "right", defaultMode: "floating", defaultFloatingSize: { width: 138, height: 31 }, tableExport: true, headless: exposureHeadless,
|
|
7
33
|
personalData: "holdings",
|
|
8
34
|
portableShare: { private: { params: true, settings: true, state: true } } }],
|
|
9
35
|
paneTemplates: [{ id: "exposure-pane", paneId: "exposure", label: "Exposure", description: "Pro scenario exposures across holdings, geographic revenue and supply chains, with source evidence and portfolio concentrations.",
|
|
10
36
|
keywords: ["exposure", "scenario", "stress", "portfolio", "supply", "country", "tariff", "pro"],
|
|
11
|
-
shortcut: { prefix: "EXPO", argKind: "text", argOptional: true, argPlaceholder: "AAPL=60% NVDA=40%" }, headless: exposureHeadless,
|
|
12
|
-
createInstance: (
|
|
37
|
+
shortcut: { prefix: "EXPO", argKind: "text", argOptional: true, argPlaceholder: "AAPL=60% NVDA=40%", argError: unknownSourceArg }, headless: exposureHeadless,
|
|
38
|
+
createInstance: (context, options) => ({ params: { input: sourceInput(options?.arg ?? "", context) } }),
|
|
13
39
|
}],
|
|
14
40
|
};
|
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
import type { ExposureBasis, ExposureComponent, ExposureExtensionObservation, ExposureHolding, ExposurePayload, ExposureRange, ExposureScenario } from "../../../api-client/exposure";
|
|
2
|
+
import { quarterLabel } from "../shared/earnings-report";
|
|
2
3
|
import { humanLabel } from "../shared/research-cells";
|
|
3
4
|
|
|
4
5
|
export const TABS = [{ value: "table", label: "Table" }, { value: "drivers", label: "Drivers" }, { value: "paths", label: "Paths" }, { value: "portfolio", label: "Portfolio" }];
|
|
5
6
|
export const DEFAULT_SCENARIO: ExposureScenario = { id: "taiwan-disruption", label: "Taiwan disruption", shocks: [{ id: "taiwan", kind: "country", target: "TW", changePct: -100 }] };
|
|
7
|
+
/**
|
|
8
|
+
* The ids of Gloom Cloud's scenario library, which the catalog lists for
|
|
9
|
+
* `--scenario`. A report reads the library itself, so an id added there runs
|
|
10
|
+
* before it is listed here.
|
|
11
|
+
*/
|
|
12
|
+
export const LIBRARY_SCENARIO_IDS = ["taiwan-disruption", "china-demand", "europe-demand", "china-semiconductor-ban", "china-tariff",
|
|
13
|
+
"oil-up", "rates-up", "usd-up", "tsmc-outage", "microsoft-capex"] as const;
|
|
6
14
|
export const basisLabel = (basis: string | null) => basis?.replaceAll("_", " ") ?? "Unknown basis";
|
|
7
15
|
const pct = (value: number) => `${value.toFixed(1)}%`;
|
|
8
16
|
export const rangeText = (range: ExposureRange | null) => !range ? "Unknown" : range.low === range.high ? pct(range.low) : `${range.low.toFixed(1)} to ${range.high.toFixed(1)}%`;
|
|
9
17
|
export const fraction = (value: number) => pct(value * 100);
|
|
18
|
+
/** "1 hop", "2 hops". */
|
|
19
|
+
export const hopsText = (count: number) => `${count} hop${count === 1 ? "" : "s"}`;
|
|
20
|
+
/**
|
|
21
|
+
* A reporting period as the tables word it. The server keys a quarter by its end date (`quarter:2026-07-31`), which
|
|
22
|
+
* reads as the month it ends in, Jul 2026, as the earnings events label a quarter; a date or a source's own words
|
|
23
|
+
* stay as they are.
|
|
24
|
+
*/
|
|
25
|
+
export function periodText(period: string): string {
|
|
26
|
+
const quarter = /^quarter:(\d{4}-\d{2}(?:-\d{2})?)$/.exec(period);
|
|
27
|
+
return quarter ? quarterLabel(quarter[1]) : period;
|
|
28
|
+
}
|
|
10
29
|
|
|
11
30
|
/** A weighted list is entirely explicit. Never silently fill missing weights or normalize shorts. */
|
|
12
31
|
export function parseHoldings(text: string): ExposureHolding[] {
|
|
@@ -71,7 +90,7 @@ export function exposureCellText(row: ExposureRow, column: "label" | "basis" | "
|
|
|
71
90
|
// What the number rests on, in words: disclosed by the company, estimated by a chain, or not visible.
|
|
72
91
|
case "classification": return `${humanLabel(row.classification)}${row.incomplete && row.classification !== "unknown" ? " · partial" : ""}`;
|
|
73
92
|
case "impact": return row.impact ? rangeText(row.impact) : "--";
|
|
74
|
-
case "period": return row.period
|
|
93
|
+
case "period": return row.period ? periodText(row.period) : "--";
|
|
75
94
|
case "weight": return fraction(row.weight ?? 0);
|
|
76
95
|
}
|
|
77
96
|
}
|
|
@@ -8,6 +8,7 @@ import { useAppSelector, useAsyncResource, useAutoRefresh, useMarketData, usePan
|
|
|
8
8
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
9
9
|
import type { PaneProps } from "../../../types/plugin";
|
|
10
10
|
import { Box, ScrollBox, Text, useRendererHost, useUiCapabilities } from "../../../ui";
|
|
11
|
+
import { withCountryFlag } from "../../../components/ui/country-flag";
|
|
11
12
|
import { logFailure } from "../../../utils/log-failure";
|
|
12
13
|
import { SignInWall } from "../cloud/auth-actions";
|
|
13
14
|
import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
|
|
@@ -19,7 +20,7 @@ import { ExposurePathDiagram, ExposureRanges } from "./charts";
|
|
|
19
20
|
import { fetchExposure, fetchScenarios, validateExposure } from "./client";
|
|
20
21
|
import { ExposureEditor, type ExposureInputs } from "./editor";
|
|
21
22
|
import { portfolioHoldings, watchlistHoldings } from "./holdings";
|
|
22
|
-
import { basisLabel, DEFAULT_SCENARIO, exposureCellText, fraction, parseCustomScenario, parseHoldings, pathRows, portfolioRows, rangeText, tableRows, TABS, type ExposureRow } from "./model";
|
|
23
|
+
import { basisLabel, DEFAULT_SCENARIO, exposureCellText, fraction, hopsText, parseCustomScenario, parseHoldings, pathRows, periodText, portfolioRows, rangeText, tableRows, TABS, type ExposureRow } from "./model";
|
|
23
24
|
import { useExposureEvidence } from "./evidence";
|
|
24
25
|
import { driverRows, driverScope, driverUnits, driverValue } from "./drivers";
|
|
25
26
|
|
|
@@ -28,7 +29,7 @@ function EvidenceItem({ item }: { item: ExposureEvidence }) {
|
|
|
28
29
|
const host = useRendererHost();
|
|
29
30
|
return <Box flexDirection="column" paddingY={1}>
|
|
30
31
|
<KeyValueRow labelWidth={20} label="Evidence" value={`${item.tier} · ${item.asOf ?? "undated"}`} detail={item.confidence === null ? undefined : `${Math.round(item.confidence * 100)}% confidence`} />
|
|
31
|
-
<KeyValueRow labelWidth={20} label="Period / units" value={`${item.period
|
|
32
|
+
<KeyValueRow labelWidth={20} label="Period / units" value={`${item.period ? periodText(item.period) : "unknown"} · ${item.units}${item.currency ? ` ${item.currency}` : ""}`} />
|
|
32
33
|
{item.revision ? <KeyValueRow labelWidth={20} label="Revision" value={item.revision} /> : null}
|
|
33
34
|
{item.quote ? <Text fg={colors.textBright}>{item.quote}</Text> : <Text fg={colors.textDim}>{item.tier === "user" ? "User-supplied assumption" : "Structured observation; no verbatim quote"}</Text>}
|
|
34
35
|
{item.url ? <ActionRow label="Open primary evidence" onPress={() => void host.openExternal(item.url!)} /> : null}
|
|
@@ -48,7 +49,7 @@ function ExposureDetail({ row, data, width }: { row: ExposureRow | null; data: E
|
|
|
48
49
|
{Object.entries(row.driver.dimensions ?? {}).map(([key, value]) => <KeyValueRow key={key} labelWidth={20} label={humanLabel(key)} value={value} />)}
|
|
49
50
|
{row.driver.evidence.map(item => <EvidenceItem key={item.id} item={item} />)}
|
|
50
51
|
</> : row ? <>
|
|
51
|
-
<KeyValueRow labelWidth={20} label="Basis / period" value={`${basisLabel(row.basis)} · ${row.period
|
|
52
|
+
<KeyValueRow labelWidth={20} label="Basis / period" value={`${basisLabel(row.basis)} · ${row.period ? periodText(row.period) : "unknown"}`} />
|
|
52
53
|
<KeyValueRow labelWidth={20} label={row.concentration ? "Gross exposure" : "Exposure"} value={rangeText(row.exposure)} detail={`${row.classification}${row.incomplete ? " · incomplete bound" : ""}`} />
|
|
53
54
|
<KeyValueRow labelWidth={20} label={row.concentration ? "Signed exposure" : "Operating stress"} value={rangeText(row.impact)} detail={row.concentration ? "NAV-weighted operating exposure; not a scenario change" : "Estimated change in the stated denominator"} />
|
|
54
55
|
{row.components.map(component => <Box key={component.id} flexDirection="column" paddingY={1}>
|
|
@@ -212,7 +213,11 @@ export function ExposurePane({ width, height, focused }: PaneProps) {
|
|
|
212
213
|
case "value": return { text: row.driver ? driverValue(row.driver) : "--", value: row.driver?.value ?? null, color: colors.textBright };
|
|
213
214
|
case "units": return { text: row.driver ? driverUnits(row.driver) : "", color: colors.textDim };
|
|
214
215
|
case "scope": return { text: row.driver ? driverScope(row.driver) : "", color: colors.textDim };
|
|
215
|
-
case "label":
|
|
216
|
+
case "label": {
|
|
217
|
+
const cell = { text: exposureCellText(row, "label"), color: unknown ? colors.textDim : colors.text };
|
|
218
|
+
// Grouped by country, each target leads with its flag on the desktop and the web.
|
|
219
|
+
return concentration && view === "country" ? withCountryFlag(cell, row.label, desktop) : cell;
|
|
220
|
+
}
|
|
216
221
|
case "basis": return row.basis ? { text: exposureCellText(row, "basis"), color: colors.textDim } : missingCell(colors);
|
|
217
222
|
case "exposure": return row.exposure ? { text: exposureCellText(row, "exposure"), value: row.exposure.high, color: colors.textBright } : { text: exposureCellText(row, "exposure"), value: null, color: colors.textMuted };
|
|
218
223
|
// Disclosed figures stand out; estimates read plainly, and the word says which is which.
|
|
@@ -244,7 +249,7 @@ export function ExposurePane({ width, height, focused }: PaneProps) {
|
|
|
244
249
|
const query = <QueryBar width={width} filters={[
|
|
245
250
|
{ id: "scenario", label: "Scenario", value: scenarioId, options: [...(library.data ?? [DEFAULT_SCENARIO]).map(s => ({ value: s.id ?? (snapshot ? "captured" : "custom"), label: s.label })), { value: "custom", label: "Custom" }].filter((s, i, all) => all.findIndex(v => v.value === s.value) === i), onChange: (value: string) => { if (value === "custom") setEditing(true); else setScenarioId(value); } },
|
|
246
251
|
...(tab === "portfolio" ? [{ id: "group", label: "View", value: view, options: [{ value: "stress", label: "Stress" }, { value: "country", label: "Country" }, { value: "supplier", label: "Supplier" }, { value: "customer", label: "Customer" }], onChange: setView }] : []),
|
|
247
|
-
]} meta={tab === "drivers" ? "Company disclosures" : tab === "portfolio" ? "NAV-weighted operating exposure" :
|
|
252
|
+
]} meta={tab === "drivers" ? "Company disclosures" : tab === "portfolio" ? "NAV-weighted operating exposure" : hopsText(data?.depth ?? inputs.depth)} />;
|
|
248
253
|
if (!data && isCloudSessionRequired(resource.error) && !editing) return <SignInWall placement="exposure-signin" action="analyze exposures" needsVerification={session.needsVerification} />;
|
|
249
254
|
return <Box width={width} height={height} flexDirection="column">
|
|
250
255
|
{strip}
|
|
@@ -63,7 +63,7 @@ export const fearGreedPlugin: GloomPlugin = {
|
|
|
63
63
|
},
|
|
64
64
|
],
|
|
65
65
|
|
|
66
|
-
// `
|
|
66
|
+
// `gloom fear-greed`, as before the plugin moved out of the host. Runs
|
|
67
67
|
// without the pane cache attached when invoked from the CLI, so it always
|
|
68
68
|
// fetches, which is what a CLI call wants anyway.
|
|
69
69
|
cliCommands: [
|
|
@@ -22,7 +22,7 @@ function filingEventsLockNote(lock: PaneLock): Promise<string> {
|
|
|
22
22
|
does: "it reads each 8-K and sums up what it said and who it names",
|
|
23
23
|
shows: "them",
|
|
24
24
|
free: [{
|
|
25
|
-
text: (ticker, company) => `
|
|
25
|
+
text: (ticker, company) => `gloom fn SEC ${ticker} lists ${company}'s recent filings, 8-Ks among them, each with its filing date and its items by number and name.`,
|
|
26
26
|
answers: (symbol, context) => filesForm(symbol, "8-K", context),
|
|
27
27
|
}],
|
|
28
28
|
});
|
|
@@ -4,6 +4,8 @@ import { compareSortValues, type SortDirection } from "../../../utils/sort-value
|
|
|
4
4
|
import type { BoardQuoteMap } from "../shared/use-quote-board";
|
|
5
5
|
import { FUTURES_SECTOR_ORDER, type FuturesContract, type FuturesSector } from "../../../market-data/futures-board";
|
|
6
6
|
import { futuresPriceUnit } from "../../../market-data/futures-contract";
|
|
7
|
+
import { contractMonthLabel } from "../../../utils/contract-month";
|
|
8
|
+
import { quoteDotMarketState } from "../../../market-data/market/status";
|
|
7
9
|
import type { FuturesReturnHorizon } from "./returns";
|
|
8
10
|
import type { FuturesTermsMap } from "./use-board-terms";
|
|
9
11
|
import type { FrontReturnsMap } from "./use-front-returns";
|
|
@@ -41,20 +43,20 @@ export function futuresRowId(row: FuturesTableRow): string {
|
|
|
41
43
|
return row.type === "header" ? `header-${row.sector}` : row.contract.symbol;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
/** "Nov 26" or "Futures,Nov-2026"; a hyphen takes only a whole year, since "Futures,Nov-20" is 2026 cut short. */
|
|
46
|
+
/** "Nov 2026", "Nov 26" or "Futures,Nov-2026"; a hyphen takes only a whole year, since "Futures,Nov-20" is 2026 cut short. */
|
|
45
47
|
const CONTRACT_MONTH = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)(?: (\d{4}|\d{2})|-(\d{4}))$/i;
|
|
46
48
|
|
|
47
49
|
/**
|
|
48
50
|
* The alias stays the row identity while its quoted contract rolls, so the
|
|
49
51
|
* label is the catalog name plus the quoted contract's month ("30-Year T-Bond
|
|
50
|
-
* Dec
|
|
51
|
-
* or cut off mid-month ("Futures,Dec-"); a month
|
|
52
|
-
* rather than guessed.
|
|
52
|
+
* Dec 2026"). Quote names arrive as "Crude Oil Nov 2026", "Crude Oil Nov 26",
|
|
53
|
+
* "Corn Futures,Dec-2026" or cut off mid-month ("Futures,Dec-"); a month
|
|
54
|
+
* without a year is dropped rather than guessed.
|
|
53
55
|
*/
|
|
54
56
|
export function futuresContractName(contract: FuturesContract, quote?: Quote | null): string {
|
|
55
57
|
const month = quotedContractMonth(contract, quote);
|
|
56
58
|
if (!month) return contract.name;
|
|
57
|
-
return `${contract.name} ${
|
|
59
|
+
return `${contract.name} ${contractMonthLabel(month.year, month.month)}`;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
const MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
@@ -82,9 +84,9 @@ function dayMonth(date: string): string {
|
|
|
82
84
|
* The row's headline: the contract its quote prices, as futuresContractName
|
|
83
85
|
* words it: the root's front month until its roll date. Two notes follow,
|
|
84
86
|
* each from the day's facts. Once the continuous symbol has rolled while the
|
|
85
|
-
* nearer month still trades, that month's last trade: "WTI Crude Oil Dec
|
|
87
|
+
* nearer month still trades, that month's last trade: "WTI Crude Oil Dec 2026,
|
|
86
88
|
* rolled (Nov expires 20 Oct)". When the day's volume put another month first,
|
|
87
|
-
* that month: "WTI Crude Oil Nov
|
|
89
|
+
* that month: "WTI Crude Oil Nov 2026, Dec most active". The terms only add a
|
|
88
90
|
* note when they name the month the quote prices, so a roll between the two
|
|
89
91
|
* loads never mixes months, and place the month when the quote's name carries
|
|
90
92
|
* none. A name column too narrow for a note drops it, the last one first.
|
|
@@ -104,7 +106,7 @@ export function futuresContractHeadline(
|
|
|
104
106
|
const month = agree ? quoted ?? termsMonth : quoted;
|
|
105
107
|
if (!month) return contract.name;
|
|
106
108
|
const priced = `${month.year}-${String(month.month + 1).padStart(2, "0")}`;
|
|
107
|
-
const plain = `${contract.name} ${
|
|
109
|
+
const plain = `${contract.name} ${contractMonthLabel(month.year, month.month)}`;
|
|
108
110
|
if (!agree) return plain;
|
|
109
111
|
const notes: Array<{ text: string; min: string }> = [];
|
|
110
112
|
const nearest = terms?.nearest;
|
|
@@ -117,7 +119,7 @@ export function futuresContractHeadline(
|
|
|
117
119
|
if (active && /^\d{4}-\d{2}$/.test(active.deliveryMonth) && active.deliveryMonth !== priced) {
|
|
118
120
|
// Another year's month says which year it is.
|
|
119
121
|
const name = MONTH_NAMES[Number(active.deliveryMonth.slice(5, 7)) - 1];
|
|
120
|
-
const label = active.deliveryMonth.slice(0, 4) === String(month.year) ? name : `${name} ${active.deliveryMonth.slice(
|
|
122
|
+
const label = active.deliveryMonth.slice(0, 4) === String(month.year) ? name : `${name} ${active.deliveryMonth.slice(0, 4)}`;
|
|
121
123
|
notes.push({ text: `, ${label} most active`, min: `, ${label} most active` });
|
|
122
124
|
}
|
|
123
125
|
// The month the quote prices leads, so a column that clips the tail still shows it; a note keeps its place
|
|
@@ -168,7 +170,7 @@ function getSortValue(
|
|
|
168
170
|
case "unit":
|
|
169
171
|
return futuresUnitLabel(contract, terms?.get(contract.symbol)?.terms);
|
|
170
172
|
case "status":
|
|
171
|
-
return quote
|
|
173
|
+
return quoteDotMarketState(quote) === "REGULAR" ? 0 : 1;
|
|
172
174
|
case "code":
|
|
173
175
|
return contract.code;
|
|
174
176
|
case "name":
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PricePoint, Quote } from "../../../types/financials";
|
|
2
|
-
import {
|
|
2
|
+
import { periodReturn } from "../../../market-data/market/period-return";
|
|
3
3
|
import type { FuturesContract } from "../../../market-data/futures-board";
|
|
4
4
|
import { quotedContractMonth } from "./model";
|
|
5
5
|
|
|
@@ -9,7 +9,6 @@ export type FuturesReturnValues = Readonly<Record<FuturesReturnHorizon, number |
|
|
|
9
9
|
export const NO_FUTURES_RETURNS: FuturesReturnValues = { "1W": null, "1M": null, YTD: null };
|
|
10
10
|
|
|
11
11
|
const MONTH_CODES = "FGHJKMNQUVXZ";
|
|
12
|
-
const DAY_MS = 86_400_000;
|
|
13
12
|
|
|
14
13
|
/** Gloom symbol of one listed contract: LEZ26.CME. */
|
|
15
14
|
function listedContractSymbol(contract: FuturesContract, year: number, month: number): string {
|
|
@@ -51,10 +50,6 @@ function utcDay(value: Date | string | number): string | null {
|
|
|
51
50
|
return Number.isFinite(date.getTime()) ? date.toISOString().slice(0, 10) : null;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
function shiftDay(day: string, days: number): string {
|
|
55
|
-
return new Date(Date.parse(`${day}T00:00:00Z`) + days * DAY_MS).toISOString().slice(0, 10);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
53
|
/** Dated closes, one per day, oldest first. History that crossed a JSON bridge carries string dates. */
|
|
59
54
|
function dailyCloses(history: readonly PricePoint[]): DailyClose[] {
|
|
60
55
|
const byDay = new Map<string, number>();
|
|
@@ -86,25 +81,10 @@ export function pickFrontContract(
|
|
|
86
81
|
return best?.symbol ?? null;
|
|
87
82
|
}
|
|
88
83
|
|
|
89
|
-
/**
|
|
90
|
-
* A baseline further than this before its target date is a hole in the
|
|
91
|
-
* contract's trading (or a contract listed after the target), not its close.
|
|
92
|
-
*/
|
|
93
|
-
const MAX_BASELINE_GAP_DAYS = 10;
|
|
94
|
-
|
|
95
|
-
function closeOnOrBefore(closes: readonly DailyClose[], target: string): number | null {
|
|
96
|
-
const earliest = shiftDay(target, -MAX_BASELINE_GAP_DAYS);
|
|
97
|
-
for (let index = closes.length - 1; index >= 0; index -= 1) {
|
|
98
|
-
const bar = closes[index]!;
|
|
99
|
-
if (bar.day > target) continue;
|
|
100
|
-
return bar.day >= earliest && bar.close > 0 ? bar.close : null;
|
|
101
|
-
}
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
84
|
/**
|
|
106
85
|
* One contract's returns: the latest price against that same contract's close
|
|
107
|
-
* a week
|
|
86
|
+
* on or before the same date a week and a calendar month earlier, and its
|
|
87
|
+
* last close of the year before (periodReturn). The continuous alias's own
|
|
108
88
|
* series jumps at every roll (LE=F fell 6.3% on a July roll day), so its
|
|
109
89
|
* history is never the baseline. `price` is the live quote, dated `asOf`;
|
|
110
90
|
* without one the contract's last close stands in.
|
|
@@ -116,17 +96,9 @@ export function frontContractReturns(
|
|
|
116
96
|
): FuturesReturnValues {
|
|
117
97
|
const closes = dailyCloses(history);
|
|
118
98
|
const live = price != null && Number.isFinite(price) && asOf != null && Number.isFinite(asOf);
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
if (latest
|
|
122
|
-
const change = (
|
|
123
|
-
|
|
124
|
-
return base == null ? null : (latest / base - 1) * 100;
|
|
125
|
-
};
|
|
126
|
-
const monthBack = calendarMonthsBefore(new Date(`${latestDay}T00:00:00Z`), 1).toISOString().slice(0, 10);
|
|
127
|
-
return {
|
|
128
|
-
"1W": change(shiftDay(latestDay, -7)),
|
|
129
|
-
"1M": change(monthBack),
|
|
130
|
-
YTD: change(`${Number(latestDay.slice(0, 4)) - 1}-12-31`),
|
|
131
|
-
};
|
|
99
|
+
const liveDay = live ? utcDay(asOf) : null;
|
|
100
|
+
const latest = live && liveDay ? { day: liveDay, close: price } : closes.at(-1);
|
|
101
|
+
if (!latest) return NO_FUTURES_RETURNS;
|
|
102
|
+
const change = (period: FuturesReturnHorizon) => periodReturn(closes, period, latest)?.percent ?? null;
|
|
103
|
+
return { "1W": change("1W"), "1M": change("1M"), YTD: change("YTD") };
|
|
132
104
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DataTableCell, DataTableColumn } from "../../../components";
|
|
2
|
-
import { colors,
|
|
2
|
+
import { colors, shownPriceColor } from "../../../theme/colors";
|
|
3
3
|
import type { Quote } from "../../../types/financials";
|
|
4
4
|
import { TextAttributes } from "../../../ui";
|
|
5
5
|
import { formatCompact, formatNumber, formatPercentRaw } from "../../../utils/format";
|
|
@@ -43,7 +43,7 @@ const DEFAULT_FUTURES_COLUMN_IDS = FUTURES_COLUMN_DEFS.map((column) => column.id
|
|
|
43
43
|
* which the change in percent still gives. The previous close (the last price
|
|
44
44
|
* less the change) goes first, then each row's quote time (the status line
|
|
45
45
|
* dates the newest), which leaves a 1280-pixel shot room for "WTI Crude Oil
|
|
46
|
-
* Dec
|
|
46
|
+
* Dec 2026, rolled (Nov expires 20 Oct)".
|
|
47
47
|
*/
|
|
48
48
|
const COLUMN_MIN_PANE_WIDTH: Partial<Record<FuturesColumnId, number>> = {
|
|
49
49
|
change: 100,
|
|
@@ -253,7 +253,7 @@ export function renderFuturesCell(
|
|
|
253
253
|
if (isBoardRowLoading(state) || returns?.loading) return { text: "…", color: colors.textDim };
|
|
254
254
|
const value = returns?.values[FUTURES_RETURN_COLUMNS[column.id]!];
|
|
255
255
|
if (value == null || !Number.isFinite(value)) return { text: "—", color: colors.textDim };
|
|
256
|
-
return { text: formatPercentRaw(value), color:
|
|
256
|
+
return { text: formatPercentRaw(value), color: shownPriceColor(value, 2) };
|
|
257
257
|
}
|
|
258
258
|
case "prevClose":
|
|
259
259
|
if (isBoardRowLoading(state)) return { text: "…", color: colors.textDim };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
1
2
|
import { apiClient } from "../../../api-client";
|
|
2
3
|
import type { FuturesCurvePayload } from "../../../api-client/futures-curve";
|
|
3
4
|
import { createPluginCache } from "../../../data/plugin-cache";
|
|
4
5
|
import { isFuturesContractSpec } from "../../../market-data/futures-contract";
|
|
5
6
|
import { loadCloudResource, unavailableOnServer } from "../shared/cloud-resource";
|
|
6
|
-
import type { DataProvider } from "../../../types/data-provider";
|
|
7
|
-
import {
|
|
7
|
+
import type { AssetDataProvider, DataProvider } from "../../../types/data-provider";
|
|
8
|
+
import type { TimeRange } from "../../../time-series/range";
|
|
9
|
+
import { archivedFuturesCurve, curveLookbackDate, curveSpot, normalizeCurveRoot, spotBarsFromHistory, unsupportedCurveRootMessage, withSettleChanges, withTradedExpirations, type CurveSpot, type SpotBar } from "./model";
|
|
8
10
|
|
|
9
11
|
export const futuresCurveCache = createPluginCache<FuturesCurvePayload>({
|
|
10
12
|
kind: "futures-curve", source: "gloom-cloud", schemaVersion: 1,
|
|
@@ -53,26 +55,31 @@ export function validateFuturesCurve(data: FuturesCurvePayload, root: string): F
|
|
|
53
55
|
const slope = data.slope;
|
|
54
56
|
if (![slope.value, slope.annualizedRollYield].every(finiteOrNull)
|
|
55
57
|
|| ![slope.percentile, slope.rollPercentile].every(rank) || !Number.isInteger(slope.samples) || slope.samples < 0
|
|
56
|
-
|| slope.asOf !== null && !timestamp(slope.asOf)
|
|
58
|
+
|| slope.asOf !== null && !timestamp(slope.asOf)
|
|
59
|
+
|| slope.basis != null && slope.basis !== "last" && slope.basis !== "settle"
|
|
60
|
+
|| slope.thinSymbol != null && typeof slope.thinSymbol !== "string") throw new Error("The server returned an invalid futures spread");
|
|
57
61
|
return data;
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
/** A live curve as every reader takes it: expiring on last trading days, its changes against the settlement shown. */
|
|
65
|
+
const liveCurve = (data: FuturesCurvePayload) => withSettleChanges(withTradedExpirations(data));
|
|
66
|
+
|
|
60
67
|
export async function fetchFuturesCurve(root: string, client: Pick<typeof apiClient, "getCloudFuturesCurve"> = apiClient): Promise<FuturesCurvePayload> {
|
|
61
68
|
const normalized = normalizeCurveRoot(root);
|
|
62
69
|
if (!normalized) throw new Error(unsupportedCurveRootMessage(root));
|
|
63
|
-
try { return
|
|
70
|
+
try { return liveCurve(validateFuturesCurve(await client.getCloudFuturesCurve(normalized), normalized)); }
|
|
64
71
|
catch (error) { throw unavailableOnServer(error, "Futures curves are not available yet."); }
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
export function getCachedFuturesCurve(root: string): FuturesCurvePayload | null {
|
|
68
75
|
const cached = futuresCurveCache.get(root, { allowExpired: true });
|
|
69
76
|
// The pane revalidates this copy on mount; only the source or a failed refresh makes it stale.
|
|
70
|
-
return cached?.data ?
|
|
77
|
+
return cached?.data ? liveCurve(cached.data) : null;
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
export async function loadFuturesCurve(root: string, force = false): Promise<FuturesCurvePayload> {
|
|
74
81
|
const { payload, stale, refreshError } = await loadCloudResource(futuresCurveCache, root, () => fetchFuturesCurve(root), { force });
|
|
75
|
-
return { ...
|
|
82
|
+
return { ...liveCurve(payload), stale: stale || payload.stale, gaps: [...payload.gaps, ...(refreshError ? [refreshError] : [])] };
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
/** The archived curve on a past date with the curves a week and a month before it. */
|
|
@@ -83,8 +90,8 @@ export async function loadFuturesCurveAsOf(root: string, date: string,
|
|
|
83
90
|
try {
|
|
84
91
|
const [curve, week, month] = await Promise.all([
|
|
85
92
|
client.getCloudFuturesCurveAsOf(normalized, date),
|
|
86
|
-
client.getCloudFuturesCurveAsOf(normalized, curveLookbackDate(date, 7)).catch((
|
|
87
|
-
client.getCloudFuturesCurveAsOf(normalized, curveLookbackDate(date, 30)).catch((
|
|
93
|
+
client.getCloudFuturesCurveAsOf(normalized, curveLookbackDate(date, 7)).catch(logFailure("futures-curve.client", "Load week comparison curve failed", null)),
|
|
94
|
+
client.getCloudFuturesCurveAsOf(normalized, curveLookbackDate(date, 30)).catch(logFailure("futures-curve.client", "Load month comparison curve failed", null)),
|
|
88
95
|
]);
|
|
89
96
|
if (!curve || curve.root !== normalized || !Array.isArray(curve.contracts) || !Array.isArray(curve.gaps)
|
|
90
97
|
|| curve.contracts.some((row) => !row || typeof row.symbol !== "string" || !Number.isFinite(row.price)
|
|
@@ -101,5 +108,29 @@ export async function loadFuturesCurveAsOf(root: string, date: string,
|
|
|
101
108
|
* A failed read is a missing spot, never a failed report: the curve stands without its basis.
|
|
102
109
|
*/
|
|
103
110
|
export async function loadCurveSpot(symbol: string, provider: Pick<DataProvider, "getQuote">, now = Date.now()): Promise<CurveSpot> {
|
|
104
|
-
return curveSpot(symbol, await provider.getQuote(symbol, "").catch((
|
|
111
|
+
return curveSpot(symbol, await provider.getQuote(symbol, "").catch(logFailure("futures-curve.client", "Load curve spot quote failed", null)), now);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** The last day of one-minute bars: the reach of a curve's trades a basis is read for, the far months' older ones aside. */
|
|
115
|
+
const SPOT_BAR_RANGE: TimeRange = "1D";
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The spot pair's one-minute bars over the last day, read through the same
|
|
119
|
+
* history path the charts use, which the basis pairs each trade with by
|
|
120
|
+
* minute. Bars of any other size pair nothing, and a failed read has none:
|
|
121
|
+
* the curve stands without its basis, each blank saying why.
|
|
122
|
+
*/
|
|
123
|
+
export async function loadCurveSpotBars(symbol: string,
|
|
124
|
+
provider: Pick<AssetDataProvider, "getPriceHistoryForResolutionWithMetadata" | "getPriceHistoryForResolution">, force = false): Promise<SpotBar[]> {
|
|
125
|
+
const context = force ? { cacheMode: "refresh" as const } : undefined;
|
|
126
|
+
try {
|
|
127
|
+
if (provider.getPriceHistoryForResolutionWithMetadata) {
|
|
128
|
+
const history = await provider.getPriceHistoryForResolutionWithMetadata(symbol, "", SPOT_BAR_RANGE, "1m", context);
|
|
129
|
+
return history.resolution && history.resolution !== "1m" ? [] : spotBarsFromHistory(history.points);
|
|
130
|
+
}
|
|
131
|
+
return provider.getPriceHistoryForResolution
|
|
132
|
+
? spotBarsFromHistory(await provider.getPriceHistoryForResolution(symbol, "", SPOT_BAR_RANGE, "1m", context)) : [];
|
|
133
|
+
} catch (error) {
|
|
134
|
+
return logFailure("futures-curve.client", "Load curve spot bars failed", [] as SpotBar[])(error);
|
|
135
|
+
}
|
|
105
136
|
}
|
|
@@ -4,8 +4,8 @@ import type { HeadlessPaneColumn, HeadlessPaneDefinition, HeadlessPaneEntry, Hea
|
|
|
4
4
|
import { formatPercentRaw } from "../../../utils/format";
|
|
5
5
|
import { DATE_OPTION_EXAMPLES } from "../../../utils/calendar-date";
|
|
6
6
|
import { newestReportTime, oldestReportTime } from "../../../utils/utc-time";
|
|
7
|
-
import { fetchFuturesCurve, loadCurveSpot, loadFuturesCurveAsOf } from "./client";
|
|
8
|
-
import { basisSpotSymbol, BASIS_CONVENTION, blankBasisNote, catalogueCurveUnit, curveAsOfDate, curveBasisPercent, curveBasisRows, curveChangeText, curveContractCode, curvePrice, curveRoundedPrice,
|
|
7
|
+
import { fetchFuturesCurve, loadCurveSpot, loadCurveSpotBars, loadFuturesCurveAsOf } from "./client";
|
|
8
|
+
import { basisSpotSymbol, BASIS_CONVENTION, blankBasisNote, catalogueCurveUnit, curveAsOfDate, curveBasisPercent, curveBasisRows, curveChangeText, curveContractCode, curvePrice, curveRoundedPrice, curveSpotSource, curveSpreadLabel, curveTimestamp, curveNoTradeSince, curveUnitLabel, noTradeChangeNote, normalizeCurveRoot, shortDatedBasisNote, thinSpreadNotice, unpairedContractCount, unsupportedCurveRootMessage, type ContractBasis } from "./model";
|
|
9
9
|
import { COMMODITIES_VIEW_STATE } from "../commodities-energy/view-state";
|
|
10
10
|
|
|
11
11
|
/** The root a report shows when none is given. */
|
|
@@ -22,6 +22,11 @@ const basisValue = (value: number | null) => value == null ? null : Number(value
|
|
|
22
22
|
* every root. Prices and changes are at the root's tick precision. `price` is
|
|
23
23
|
* the latest trade and `settlement` the exchange settlement for the curve's
|
|
24
24
|
* settlement session (a past curve's settled rows have no separate trade).
|
|
25
|
+
* `change` is `price` less `settlement`; `noTradeSince` dates the settlement
|
|
26
|
+
* a contract has not traded since, whose change is therefore blank. A crypto
|
|
27
|
+
* root adds the basis: the spot in the minute of `price`'s trade and that
|
|
28
|
+
* minute (`spot`, `spotTime`), the fractional days from the trade to final
|
|
29
|
+
* settlement, and the premium and its yearly rate.
|
|
25
30
|
*/
|
|
26
31
|
function contractRow(row: FuturesContract, data: FuturesCurvePayload, root: string, past: boolean, basis?: ContractBasis) {
|
|
27
32
|
const price = (value: number | null | undefined) => curveRoundedPrice(value, root);
|
|
@@ -30,15 +35,21 @@ function contractRow(row: FuturesContract, data: FuturesCurvePayload, root: stri
|
|
|
30
35
|
firstNotice: row.firstNotice ?? null, inDelivery: row.inDelivery ?? false,
|
|
31
36
|
settlement: price(row.settlement), settlementDate: row.settlement != null ? data.settlementDate ?? null : null,
|
|
32
37
|
price: past && row.settlement != null ? null : price(row.price), change: price(row.change),
|
|
38
|
+
noTradeSince: past ? null : curveNoTradeSince(row, data),
|
|
33
39
|
asOf: row.asOf, stale: row.stale, volume: row.volume, openInterest: row.openInterest, percentile: rank(row.percentile),
|
|
34
40
|
samples: row.samples, historyStart: row.historyStart, historyEnd: row.historyEnd,
|
|
35
41
|
currency: row.currency, quoteUnit: curveUnitLabel(data) ?? row.quoteUnit, delayMinutes: row.delayMinutes,
|
|
36
|
-
...(basis ? {
|
|
42
|
+
...(basis ? { spot: price(basis.spot), spotTime: basis.spotTime, daysToExpiry: basisValue(basis.daysToExpiry),
|
|
43
|
+
vsSpotPct: basisValue(basis.vsSpotPct), annualisedBasisPct: basisValue(basis.annualisedBasisPct) } : {}),
|
|
37
44
|
};
|
|
38
45
|
}
|
|
39
46
|
|
|
40
|
-
/**
|
|
41
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The table: what a hedge reads, in one order for every root; JSON keeps every
|
|
49
|
+
* field. A crypto root's spot is the one each trade is read against; the
|
|
50
|
+
* export dates it, where the text leaves its minute to As Of UTC, the trade's.
|
|
51
|
+
*/
|
|
52
|
+
function contractColumns(root: string, settlementDate: string | null, options: { basis: boolean; last: boolean; notice: boolean; text?: boolean }): HeadlessPaneColumn[] {
|
|
42
53
|
const price = (value: unknown) => typeof value === "number" ? curvePrice(value, root) : "--";
|
|
43
54
|
const date = (value: unknown) => typeof value === "string" ? value : "--";
|
|
44
55
|
return [
|
|
@@ -51,7 +62,10 @@ function contractColumns(root: string, settlementDate: string | null, options: {
|
|
|
51
62
|
// A Cboe price is the settlement itself, with no separate last trade.
|
|
52
63
|
...options.last ? [{ key: "price", header: "Last", align: "right" as const, format: price }] : [],
|
|
53
64
|
{ key: "change", header: "Change", align: "right", format: (value) => typeof value === "number" ? curveChangeText(value, root) : "--" },
|
|
54
|
-
...options.basis ? [{ key: "
|
|
65
|
+
...options.basis ? [{ key: "spot", header: "Spot", align: "right" as const, format: price },
|
|
66
|
+
...options.text ? [] : [{ key: "spotTime", header: "Spot Time UTC", shrink: false, format: (value: unknown) => typeof value === "string" ? curveTimestamp(value) : "--" }],
|
|
67
|
+
{ key: "vsSpotPct", header: "Vs Spot", align: "right" as const, format: (value: unknown) => curveBasisPercent(typeof value === "number" ? value : null, 2) },
|
|
68
|
+
{ key: "daysToExpiry", header: "Days to Expiry", textHeader: "Days", align: "right" as const, format: (value: unknown) => typeof value === "number" ? value.toFixed(1) : "--" },
|
|
55
69
|
{ key: "annualisedBasisPct", header: "Ann Basis", align: "right" as const, format: (value: unknown) => curveBasisPercent(typeof value === "number" ? value : null, 1) }] : [],
|
|
56
70
|
{ key: "asOf", header: "As Of UTC", shrink: false, format: (value) => typeof value === "string" ? curveTimestamp(value) : "--" },
|
|
57
71
|
{ key: "openInterest", header: "Open Int", align: "right", format: (value) => typeof value === "number" ? value.toLocaleString("en-US") : "--" },
|
|
@@ -70,8 +84,9 @@ function fieldColumns(order: readonly string[], fields: object, formats: Record<
|
|
|
70
84
|
.map((key) => ({ key, header: key, ...formats[key] ? { textFormat: formats[key] } : {} }));
|
|
71
85
|
}
|
|
72
86
|
|
|
87
|
+
// `basis` says which prices the value subtracts: two last trades made together, or the settlements of the session in `asOf`.
|
|
73
88
|
const FRONT_SPREAD_FIELDS = ["label", "frontSymbol", "nextSymbol", "value", "annualizedRollYield", "percentile", "rollPercentile",
|
|
74
|
-
"samples", "historyStart", "historyEnd", "asOf", "state"];
|
|
89
|
+
"samples", "historyStart", "historyEnd", "asOf", "basis", "state", "thinSymbol"];
|
|
75
90
|
const GHOST_FIELDS = ["symbol", "expiration", "price", "asOf"];
|
|
76
91
|
/** The annualized roll yield reads as the percent it is (+32.36%); an export keeps the number. */
|
|
77
92
|
const ROLL_YIELD_FORMAT = { annualizedRollYield: (value: unknown) => typeof value === "number" ? formatPercentRaw(value) : "--" };
|
|
@@ -93,7 +108,7 @@ function specEntries(data: FuturesCurvePayload): HeadlessPaneEntry[] {
|
|
|
93
108
|
export const futuresCurveHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
94
109
|
discovery: { aliases: ["CTM"], dataRequirements: ["Gloom Cloud futures curve endpoint"],
|
|
95
110
|
limitations: ["Listed-contract catalogues can be incomplete.", "Ghosts and percentiles use the same listed contracts.", "Cboe VIX is daily settlement.",
|
|
96
|
-
"Ann Basis is simple actual/365
|
|
111
|
+
"Ann Basis is simple actual/365, each last trade against spot in the same minute, and noisy under 7 days to expiry."],
|
|
97
112
|
intents: ["futures basis trade", "cash and carry", "basis against spot"] },
|
|
98
113
|
shape: "bundle", argument: { kind: "free-text", optional: true, placeholder: "root", description: "FUT root such as CL, ES, ZN or VX, or a CME crypto root (BTC, ETH, SOL, XRP). Defaults to ES." },
|
|
99
114
|
// Only the pane reads the tab; the report always carries both.
|
|
@@ -106,23 +121,30 @@ export const futuresCurveHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
106
121
|
const input = args.argument || DEFAULT_ROOT;
|
|
107
122
|
const root = normalizeCurveRoot(input);
|
|
108
123
|
if (!root) throw new Error(unsupportedCurveRootMessage(input));
|
|
109
|
-
const date = curveAsOfDate(args.options.date);
|
|
124
|
+
const date = curveAsOfDate(args.options.date, new Date(), "--date");
|
|
110
125
|
// The archive keeps no spot history, so a past curve has no basis.
|
|
111
126
|
const spotSymbol = date ? null : basisSpotSymbol(root);
|
|
112
127
|
const now = Date.now();
|
|
113
|
-
|
|
128
|
+
// The quote names the spot and its feed; the one-minute bars price each trade's own minute.
|
|
129
|
+
const [data, spot, bars] = await Promise.all([
|
|
114
130
|
date ? loadFuturesCurveAsOf(root, date, ctx.apiClient) : fetchFuturesCurve(root, ctx.apiClient),
|
|
115
131
|
spotSymbol ? loadCurveSpot(spotSymbol, ctx.marketData, now) : null,
|
|
132
|
+
spotSymbol ? loadCurveSpotBars(spotSymbol, ctx.marketData, ctx.refresh === true) : null,
|
|
116
133
|
]);
|
|
117
|
-
const bases = spot ? curveBasisRows(data.contracts,
|
|
134
|
+
const bases = spot && bars ? curveBasisRows(data.contracts, bars) : null;
|
|
118
135
|
const unit = curveUnitLabel(data);
|
|
119
136
|
const terms = specEntries(data);
|
|
120
137
|
const source = spot ? curveSpotSource(spot) : null;
|
|
121
138
|
const notices = [...args.argument ? [] : [`Showing ${DEFAULT_ROOT}. Try fn CTM ${EXAMPLE_ROOT}.`],
|
|
122
|
-
...spot ? [
|
|
139
|
+
...spot ? [`Basis against ${spot.symbol} spot in each last trade's own minute${source ? ` (${source})` : ""}; not the CME reference rate.`] : []];
|
|
123
140
|
// The footnotes under the table: the convention, why a cell is blank, and where a short-dated rate is not to be trusted.
|
|
124
|
-
|
|
125
|
-
|
|
141
|
+
const basisNotes = bases ? [BASIS_CONVENTION, blankBasisNote(data.contracts, bases), shortDatedBasisNote(data.contracts, bases)]
|
|
142
|
+
.filter((note): note is string => !!note) : [];
|
|
143
|
+
// A blank Change says why, as a blank basis does; a past curve has no session change to blank.
|
|
144
|
+
const changeNote = date ? null : noTradeChangeNote(data.contracts, data);
|
|
145
|
+
const thinSpread = thinSpreadNotice(data);
|
|
146
|
+
const notes = [...thinSpread ? [`${thinSpread}.`] : [], ...changeNote ? [changeNote] : [], ...basisNotes];
|
|
147
|
+
const columnOptions = { basis: !!bases, last: data.source !== "cboe", notice: data.contracts.some((row) => row.firstNotice) };
|
|
126
148
|
// Dated by the contracts' own quotes; the same-contract history rows are a year of context, not observations.
|
|
127
149
|
const quoted = data.contracts.map((row) => row.asOf);
|
|
128
150
|
const freshness: HeadlessPaneFreshness = date
|
|
@@ -132,8 +154,8 @@ export const futuresCurveHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
132
154
|
return {
|
|
133
155
|
freshness,
|
|
134
156
|
sections: [
|
|
135
|
-
{ title: "Contracts", columns: contractColumns(root, data.settlementDate ?? null,
|
|
136
|
-
{
|
|
157
|
+
{ title: "Contracts", columns: contractColumns(root, data.settlementDate ?? null, columnOptions),
|
|
158
|
+
...bases ? { textColumns: contractColumns(root, data.settlementDate ?? null, { ...columnOptions, text: true }) } : {},
|
|
137
159
|
rows: data.contracts.map((row) => contractRow(row, data, root, !!date, bases?.get(row.symbol))) },
|
|
138
160
|
{ title: "Front spread", columns: fieldColumns(FRONT_SPREAD_FIELDS, data.slope, ROLL_YIELD_FORMAT), rows: [{ label: curveSpreadLabel(data.slope), ...data.slope, value: curveRoundedPrice(data.slope.value, root),
|
|
139
161
|
annualizedRollYield: data.slope.annualizedRollYield == null ? null : Number(data.slope.annualizedRollYield.toFixed(2)),
|
|
@@ -144,7 +166,7 @@ export const futuresCurveHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
144
166
|
],
|
|
145
167
|
errors: data.gaps,
|
|
146
168
|
...(notes.length ? { notes } : {}),
|
|
147
|
-
metadata: { ...data, quoteUnit: unit, ...(spot && bases ? { spot,
|
|
169
|
+
metadata: { ...data, quoteUnit: unit, ...(spot && bases ? { spot, basisBlankedUnpaired: unpairedContractCount(bases.values()) } : {}), ...(args.argument ? {} : { defaultArgument: DEFAULT_ROOT }),
|
|
148
170
|
...(notices.length ? { notices } : {}),
|
|
149
171
|
complete: data.status === "available", percentileBasis: "Same-contract observations within one year; actual sample start/end retained" },
|
|
150
172
|
};
|