gloomberb 0.18.2 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/patches/electrobun@1.18.1.patch +106 -5
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +99 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +24 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +26 -7
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/telemetry.ts +17 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/global-shortcuts.ts +1 -16
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/runtime/update.ts +28 -8
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/pane-tabs-allowlist.json +65 -0
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1189 -296
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +272 -70
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +20 -14
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +32 -18
- package/src/cli/issuer-membership.ts +103 -0
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +315 -43
- package/src/cli/name-entries.ts +73 -22
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +77 -20
- package/src/cli/pane-functions/catalog.ts +40 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +12 -8
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +48 -16
- package/src/cli/pane-functions/index.ts +82 -21
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +65 -14
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +190 -27
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +122 -25
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +226 -60
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +387 -21
- package/src/components/chart/composite/drawing-store.ts +26 -6
- package/src/components/chart/composite/interactions.ts +9 -3
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +316 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +19 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/command-items.ts +32 -6
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/data-table/view.tsx +23 -3
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +13 -6
- package/src/components/layout/detached-pane-shell.tsx +1 -0
- package/src/components/layout/floating-pane.tsx +1 -0
- package/src/components/layout/header.tsx +234 -60
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/pane/header.tsx +10 -3
- package/src/components/layout/pane/index.tsx +1 -0
- package/src/components/layout/pane/pane-tabs.tsx +9 -1
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/components/ui/stat-grid.tsx +28 -3
- package/src/components/ui/status.tsx +3 -1
- package/src/core/app-services.ts +4 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +51 -12
- package/src/i18n/ja.ts +51 -12
- package/src/i18n/ko.ts +51 -12
- package/src/i18n/zh-cn.ts +51 -12
- package/src/i18n/zh-tw.ts +51 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +108 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +77 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
- package/src/plugins/builtin/attention/pane.tsx +22 -16
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +12 -9
- package/src/plugins/builtin/backtest/export.ts +1 -1
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +34 -18
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/client.ts +2 -2
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +9 -11
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
- package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +89 -31
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +5 -4
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +7 -4
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
- package/src/plugins/builtin/correlation/settings.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +7 -5
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +19 -12
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +77 -5
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +34 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +16 -10
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/board.tsx +4 -1
- package/src/plugins/builtin/gpu/changes.tsx +10 -10
- package/src/plugins/builtin/gpu/equities.tsx +4 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/gpu/history.tsx +4 -2
- package/src/plugins/builtin/gpu/pane.tsx +5 -3
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +15 -2
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +48 -8
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/base-values.ts +11 -7
- package/src/plugins/builtin/insider/client.ts +3 -0
- package/src/plugins/builtin/insider/headless.ts +20 -7
- package/src/plugins/builtin/insider/index.tsx +17 -8
- package/src/plugins/builtin/insider/issuer.ts +34 -4
- package/src/plugins/builtin/insider/signals-client.ts +3 -3
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/insider/table-model.ts +35 -13
- package/src/plugins/builtin/insider/table.tsx +5 -2
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/events.ts +145 -0
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +91 -7
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +14 -8
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +36 -21
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +33 -11
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +50 -15
- package/src/plugins/builtin/notes/export.ts +17 -6
- package/src/plugins/builtin/notes/files.ts +16 -5
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/enrichment-model.ts +10 -9
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +70 -4
- package/src/plugins/builtin/options/view.tsx +51 -23
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
- package/src/plugins/builtin/options-positioning/headless.ts +11 -3
- package/src/plugins/builtin/options-positioning/model.ts +24 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
- package/src/plugins/builtin/options-scenario/client.ts +142 -29
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +49 -21
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +22 -10
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +6 -3
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +44 -32
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/seasonality/client.ts +2 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +6 -4
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +23 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/volatility/options.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/social-mentions/client.ts +2 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +28 -7
- package/src/plugins/builtin/vol-surface/headless.ts +43 -15
- package/src/plugins/builtin/vol-surface/model.ts +34 -12
- package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
- package/src/plugins/builtin/vol-surface/stored.ts +34 -3
- package/src/plugins/builtin/vol-surface/tables.ts +14 -0
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/desktop/controls.tsx +1 -1
- package/src/renderers/dom/desktop/query-bar.tsx +2 -0
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/tabs.tsx +16 -5
- package/src/renderers/dom/host/top-surface.ts +127 -0
- package/src/renderers/dom/styles.css +115 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/core-capabilities.ts +9 -1
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +9 -7
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +8 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +39 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/index.ts +16 -0
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +21 -4
- package/src/telemetry/update-failures-node.ts +59 -0
- package/src/telemetry/update-failures.ts +307 -0
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +215 -36
- package/src/tickers/company-name.ts +43 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-fate.ts +30 -0
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +20 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +83 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/issuer-listings.ts +28 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/failure.ts +163 -0
- package/src/updater/index.ts +97 -28
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-pair.ts +26 -0
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +71 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -5,7 +5,7 @@ import { curveStrip, curveSurfaceMinRows } from "../../../components/chart/curve
|
|
|
5
5
|
import { isAccessDenied } from "../../../api-client/errors";
|
|
6
6
|
import type { FuturesContract } from "../../../api-client/futures-curve";
|
|
7
7
|
import { futuresTickText } from "../../../market-data/futures-contract";
|
|
8
|
-
import { useAsyncResource, usePaneSettingValue, usePluginPaneState, useShortcut } from "../../../public/react";
|
|
8
|
+
import { useAssetData, useAsyncResource, usePaneSettingValue, usePluginPaneState, useShortcut } from "../../../public/react";
|
|
9
9
|
import { usePaneInstance, usePaneTitle } from "../../../state/app/context";
|
|
10
10
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
11
11
|
import type { PaneProps } from "../../../types/plugin";
|
|
@@ -16,8 +16,8 @@ import { useAutoRefresh } from "../../../react/auto-refresh";
|
|
|
16
16
|
import { futuresSessionRefreshInterval } from "../shared/futures-session";
|
|
17
17
|
import { useResearchCloudSession } from "../shared/research-cloud-session";
|
|
18
18
|
import { useQuoteBoard } from "../shared/use-quote-board";
|
|
19
|
-
import { getCachedFuturesCurve, loadFuturesCurve, loadFuturesCurveAsOf } from "./client";
|
|
20
|
-
import { basisSpotSymbol, curveAsOfDate, curveAxisPrice, curveBasisPercent, curveBasisRows, curveChangeText, curveContractChanges, curveContractCode, curvePrice, curveRank, curveSpot, curveSpotLabel, curveSpotSource, curveSpreadLabel, curveTimestamp, curveTitle, curveUnitLabel, DEFAULT_CURVE_HORIZON, futuresCurveSeries, newestQuote, normalizeCurveRoot, paneCurveRoot,
|
|
19
|
+
import { getCachedFuturesCurve, loadCurveSpotBars, loadFuturesCurve, loadFuturesCurveAsOf } from "./client";
|
|
20
|
+
import { BASIS_CONVENTION, basisSpotSymbol, blankBasisNote, curveAsOfDate, curveAxisPrice, curveBasisPercent, curveBasisRows, curveChangeText, curveContractChanges, curveContractCode, curvePrice, curveRank, curveSpot, curveSpotLabel, curveSpotSource, curveSpreadBasis, curveSpreadLabel, curveTimestamp, curveTitle, curveUnitLabel, DEFAULT_CURVE_HORIZON, futuresCurveSeries, newestQuote, noTradeChangeNote, normalizeCurveRoot, paneCurveRoot, shortDatedBasis, shortDatedBasisNote, sortCurveContracts, thinSpreadNotice, unsupportedCurveRootMessage, type CurveContractChanges, type CurveSpot } from "./model";
|
|
21
21
|
|
|
22
22
|
const TABS = [{ value: "curve", label: "Curve" }, { value: "contracts", label: "Contracts" }];
|
|
23
23
|
// One column order for every root. SETTLE is the exchange settlement for the
|
|
@@ -61,6 +61,8 @@ const BASIS_CURVE_COLUMNS: DataTableColumn[] = [
|
|
|
61
61
|
...CURVE_COLUMNS.slice(4),
|
|
62
62
|
];
|
|
63
63
|
const BASIS_DROP_ORDER = ["percentile", "volume", "change1m", "oi", "settle", "change1w", "vsSpot", "expiry"];
|
|
64
|
+
// Inside a week of expiry Vs Spot is the figure to read, so a curve with such a contract keeps it.
|
|
65
|
+
const SHORT_DATED_DROP_ORDER = BASIS_DROP_ORDER.filter((id) => id !== "vsSpot");
|
|
64
66
|
const NO_SYMBOLS: string[] = [];
|
|
65
67
|
/** The spot's age is judged against the clock, so a quote that stops moving still goes stale on screen. */
|
|
66
68
|
const SPOT_CLOCK_MS = 30_000;
|
|
@@ -71,8 +73,12 @@ const contractKey = (row: FuturesContract) => row.symbol;
|
|
|
71
73
|
const contractDate = (row: FuturesContract) => new Date(row.expiration);
|
|
72
74
|
const sentenceCase = (text: string) => text.charAt(0).toUpperCase() + text.slice(1);
|
|
73
75
|
|
|
74
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The footer's latest spot, naming what the quote is and its feed; a narrow footer gives those up before the price
|
|
78
|
+
* and its time. Each basis reads the spot in its own trade's minute, so a quote gone stale only says so.
|
|
79
|
+
*/
|
|
75
80
|
function spotSegment(spot: CurveSpot, root: string, clock: number): PaneFooterSegment {
|
|
81
|
+
if (spot.status !== "ok") return { id: "spot", parts: [{ text: spot.reason ?? `no ${spot.symbol} quote`, tone: "warning" }] };
|
|
76
82
|
const label = curveSpotLabel(spot, root, clock);
|
|
77
83
|
const source = curveSpotSource(spot);
|
|
78
84
|
return { id: "spot", parts: [{ text: source ? `${label} (${source})` : label, tone: "muted" }], ...source ? { variants: [[{ text: label, tone: "muted" }]] } : {} };
|
|
@@ -128,6 +134,12 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
128
134
|
return () => clearInterval(timer);
|
|
129
135
|
}, [basisActive]);
|
|
130
136
|
const spotState = spotSymbol ? spotQuotes.get(spotSymbol) : undefined;
|
|
137
|
+
// Each trade is read against the spot's one-minute bar of its own minute, fetched again whenever the curve is.
|
|
138
|
+
const assetData = useAssetData();
|
|
139
|
+
const barsLoader = useMemo(() => basisActive && spotSymbol && assetData
|
|
140
|
+
? (force: boolean) => loadCurveSpotBars(spotSymbol, assetData, force) : null,
|
|
141
|
+
[assetData, basisActive, spotSymbol, resource.updatedAt]);
|
|
142
|
+
const spotBars = useAsyncResource(barsLoader, { keepPreviousData: true });
|
|
131
143
|
// Until the first answer there is nothing to say: no reason, only blank cells.
|
|
132
144
|
const spot = useMemo(() => !basisActive || !spotSymbol || !spotState || spotState.loading && !spotState.quote ? null
|
|
133
145
|
: curveSpot(spotSymbol, spotState.quote, clock), [basisActive, clock, spotState, spotSymbol]);
|
|
@@ -138,8 +150,9 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
138
150
|
requestedDate ? Date.parse(`${requestedDate}T00:00:00Z`) : Date.now(), requestedDate ? data.asOf ?? requestedDate : undefined) : [],
|
|
139
151
|
[data, colors, horizon, requestedDate]);
|
|
140
152
|
const changes = useMemo<CurveContractChanges>(() => data ? curveContractChanges(data) : new Map(), [data]);
|
|
141
|
-
|
|
142
|
-
const
|
|
153
|
+
// Until the bars first answer there is nothing to say: no reason, only blank cells.
|
|
154
|
+
const bars = basisActive ? spotBars.data : null;
|
|
155
|
+
const basis = useMemo(() => curveBasisRows(basisActive ? data?.contracts ?? [] : [], bars), [basisActive, bars, data]);
|
|
143
156
|
const rows = useMemo(() => sortCurveContracts(data?.contracts ?? [], sort.columnId, sort.direction, changes, basis), [data, sort, changes, basis]);
|
|
144
157
|
// The curve tab lists the contracts the chart plots; Contracts keeps every one.
|
|
145
158
|
const curveRows = useMemo(() => {
|
|
@@ -151,13 +164,20 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
151
164
|
useChartTableSelection({ rows: curveRows, getId: contractKey, getDate: contractDate, selectedId, onSelect: setSelected,
|
|
152
165
|
focused, enabled: curveTab });
|
|
153
166
|
// The highlighted row carries the selected contract's price and rank.
|
|
154
|
-
|
|
167
|
+
// The spread says which prices it subtracts (settlements or two last trades made together); a server that does not say is dated.
|
|
168
|
+
const spreadBasis = data ? curveSpreadBasis(data.slope, newest) : null;
|
|
169
|
+
const slopeDate = !spreadBasis && data?.slope.asOf && curveTimestamp(data.slope.asOf) !== curveTimestamp(newest) ? curveTimestamp(data.slope.asOf) : null;
|
|
170
|
+
// A thin spread makes no curve call: it and the roll yield read from it take the warning tone and give no rank.
|
|
171
|
+
const thin = data?.slope.state === "thin";
|
|
172
|
+
const spreadRank = data && !thin ? curveRank(data.slope.percentile, data.slope.samples) : null;
|
|
173
|
+
const thinSpread = data ? thinSpreadNotice(data) : null;
|
|
155
174
|
const statItems: StatItem[] = data ? [
|
|
156
175
|
{ id: "roll", label: "Ann. roll yield", value: signedPercent(data.slope.annualizedRollYield),
|
|
157
|
-
detail: curveRank(data.slope.rollPercentile, data.slope.samples) },
|
|
176
|
+
...thin ? { tone: "warning" as const } : { detail: curveRank(data.slope.rollPercentile, data.slope.samples) } },
|
|
158
177
|
// Named by the contracts it subtracts: the front is the first month the market trades, not always the first row.
|
|
159
178
|
{ id: "spread", label: curveSpreadLabel(data.slope), value: data.slope.value == null ? "--" : curvePrice(data.slope.value, root),
|
|
160
|
-
|
|
179
|
+
...thin ? { tone: "warning" as const } : {},
|
|
180
|
+
detail: [data.slope.state, spreadBasis, spreadRank, slopeDate].filter(Boolean).join(" · ") },
|
|
161
181
|
...data.spec ? [{ id: "contract", label: "Contract", value: data.spec.size, detail: `tick ${futuresTickText(data.spec)}` }] : [],
|
|
162
182
|
] : [];
|
|
163
183
|
const { strip: tabStrip, rows: tabRows } = usePaneTabs({ tabs: TABS, activeValue: tab, onSelect: setTab, focused, dense: true, queryBarWidth: width });
|
|
@@ -168,6 +188,7 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
168
188
|
const settleLabel = data?.settlementDate ? `SETTLE ${data.settlementDate.slice(5)}` : "SETTLE";
|
|
169
189
|
// Cash-settled roots (ES, CL's Brent, VX) have no first notice day to show.
|
|
170
190
|
const noNotice = !data?.contracts.some((row) => row.firstNotice);
|
|
191
|
+
const shortDated = curveTab && curveRows.some((row) => shortDatedBasis(basis.get(row.symbol)));
|
|
171
192
|
const columns = useMemo(() => {
|
|
172
193
|
// Labelled before fitting: a dated header is wider than the column's numbers.
|
|
173
194
|
const shown = (list: DataTableColumn[]) => list.filter((entry) => !(settlesOnly && entry.id === "price") && !(noNotice && entry.id === "notice"))
|
|
@@ -175,9 +196,9 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
175
196
|
// A curve that only settles keeps its settlement: it is the price.
|
|
176
197
|
const order = (list: string[]) => settlesOnly ? list.filter((id) => id !== "settle") : list;
|
|
177
198
|
return !curveTab ? fitChartTableColumns(shown(COLUMNS), width, order(CONTRACTS_DROP_ORDER))
|
|
178
|
-
: basisActive ? fitChartTableColumns(shown(BASIS_CURVE_COLUMNS), width, order(BASIS_DROP_ORDER))
|
|
199
|
+
: basisActive ? fitChartTableColumns(shown(BASIS_CURVE_COLUMNS), width, order(shortDated ? SHORT_DATED_DROP_ORDER : BASIS_DROP_ORDER))
|
|
179
200
|
: fitChartTableColumns(shown(CURVE_COLUMNS), width, order(CURVE_DROP_ORDER));
|
|
180
|
-
}, [basisActive, curveTab, noNotice, settleLabel, settlesOnly, width]);
|
|
201
|
+
}, [basisActive, curveTab, noNotice, settleLabel, settlesOnly, shortDated, width]);
|
|
181
202
|
const formatValue = useCallback((value: number) => curvePrice(value, root), [root]);
|
|
182
203
|
const formatChange = useCallback((value: number) => curveChangeText(value, root), [root]);
|
|
183
204
|
const unit = data ? curveUnitLabel(data) : null;
|
|
@@ -212,11 +233,16 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
212
233
|
};
|
|
213
234
|
// A past date with no archived curve says why in the body, not behind the warning.
|
|
214
235
|
const emptyPast = !!requestedDate && !!data && !data.contracts.length;
|
|
215
|
-
//
|
|
236
|
+
// The basis notes the report prints under its table: the convention, why a cell is blank, and which rates spot noise swamps.
|
|
237
|
+
const basisNotes = basisActive && bars ? [BASIS_CONVENTION, blankBasisNote(tableRows, basis), shortDatedBasisNote(tableRows, basis)]
|
|
238
|
+
.filter((note): note is string => !!note) : [];
|
|
216
239
|
// A long in these can be assigned delivery: the hedge a trader rolls before first notice.
|
|
217
240
|
const delivering = data?.contracts.filter((row) => row.inDelivery).map((row) => curveContractCode(row.symbol)) ?? [];
|
|
241
|
+
// A blank Change on Contracts says why, as a blank basis does: no trade since the settlement it is measured from.
|
|
242
|
+
const untraded = data && !requestedDate && columns.some((entry) => entry.id === "change")
|
|
243
|
+
? noTradeChangeNote(tableRows, data, { count: true }) : null;
|
|
218
244
|
usePaneNoticeFooter({ registrationId: "futures-curve:notices", focused,
|
|
219
|
-
notices: emptyPast ? [] : [...data?.gaps ?? [], ...
|
|
245
|
+
notices: emptyPast ? [] : [...data?.gaps ?? [], ...thinSpread ? [thinSpread] : [], ...basisNotes, ...untraded ? [untraded] : [],
|
|
220
246
|
...delivering.length ? [`${delivering.join(", ")} ${delivering.length === 1 ? "is" : "are"} past first notice.`] : []] });
|
|
221
247
|
const delay = Math.max(0, ...(data?.contracts.map((row) => row.delayMinutes ?? 0) ?? []));
|
|
222
248
|
usePaneStatusFooter({ registrationId: "futures-curve", loading: resource.loading, error: resource.error,
|
|
@@ -227,8 +253,7 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
227
253
|
info: data ? [
|
|
228
254
|
...splitDelayedStatus({ id: "source", parts: [{ text: `${requestedDate ? "daily archive" : data.source === "cboe" ? "settlement" : delay > 0 ? `${delay}m delayed` : "dated quotes"} · ${unit ?? "units unavailable"} · ${curveTimestamp(newest)}${newest?.includes("T") ? " UTC" : ""}`, tone: "muted" }] }),
|
|
229
255
|
...(staleCount ? [{ id: "stale", parts: [{ text: `${staleCount} of ${data.contracts.length} stale`, tone: "warning" as const }] }] : []),
|
|
230
|
-
...(spot ? [
|
|
231
|
-
: { id: "spot", parts: [{ text: `Basis blank: ${spot.reason}`, tone: "warning" as const }] }] : []),
|
|
256
|
+
...(spot ? [spotSegment(spot, root, clock)] : []),
|
|
232
257
|
] : [],
|
|
233
258
|
});
|
|
234
259
|
const tableChromeRows = chartTableChromeRows(columns, width);
|
|
@@ -250,7 +275,7 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
250
275
|
if (column.id === "price") {
|
|
251
276
|
const lastTrade = requestedDate && row.settlement != null ? null : row.price;
|
|
252
277
|
// Beside its settlement the last trade is the secondary price; without one it is the row's price.
|
|
253
|
-
return { text: curvePrice(lastTrade, root), color: curveTab &&
|
|
278
|
+
return { text: curvePrice(lastTrade, root), color: curveTab && row.stale ? colors.warning
|
|
254
279
|
: row.settlement != null ? colors.textMuted : undefined };
|
|
255
280
|
}
|
|
256
281
|
if (column.id === "change") {
|
|
@@ -263,7 +288,11 @@ function FuturesCurveView({ width, height, focused, root, ownsTitle }: PaneProps
|
|
|
263
288
|
}
|
|
264
289
|
if (column.id === "vsSpot" || column.id === "annBasis") {
|
|
265
290
|
const cell = basis.get(row.symbol);
|
|
266
|
-
|
|
291
|
+
const text = column.id === "vsSpot" ? curveBasisPercent(cell?.vsSpotPct ?? null, 2) : curveBasisPercent(cell?.annualisedBasisPct ?? null, 1);
|
|
292
|
+
// The figure to read is in the text colour, the other greyed: the annualised rate, until a week before
|
|
293
|
+
// expiry, where spot noise swings it by whole points and Vs Spot leads.
|
|
294
|
+
const lead = column.id === "vsSpot" ? shortDatedBasis(cell) : !shortDatedBasis(cell);
|
|
295
|
+
return { text, color: lead && text !== "--" ? undefined : colors.textMuted };
|
|
267
296
|
}
|
|
268
297
|
if (column.id === "percentile") return { text: row.samples < 2 || row.percentile == null ? "--" : row.percentile.toFixed(0) };
|
|
269
298
|
if (column.id === "oi") return { text: integer(row.openInterest) };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
1
2
|
import { MarketDataCoordinator } from "../../../market-data/coordinator";
|
|
2
3
|
import type { QueryEntry } from "../../../market-data/result-types";
|
|
3
4
|
import { resolveEntryData } from "../../../market-data/selectors";
|
|
4
5
|
import type { DataProvider } from "../../../types/data-provider";
|
|
5
6
|
import type { Quote } from "../../../types/financials";
|
|
6
|
-
import {
|
|
7
|
+
import { quoteChangeBasis, type QuoteChangeBasis } from "../../../market-data/market/change-basis";
|
|
8
|
+
import { fxLegMoveReference, fxLegs, liveFxLegEntry, type FxLeg } from "./live-legs";
|
|
7
9
|
|
|
8
10
|
/** One USD leg as the board reads it: the rate it draws and where that rate came from. */
|
|
9
11
|
export interface FxLegReading {
|
|
@@ -13,10 +15,13 @@ export interface FxLegReading {
|
|
|
13
15
|
/** The pair quote, only when the rate is its own: it then says what the rate is (live or delayed, its session). */
|
|
14
16
|
quote: Quote | null;
|
|
15
17
|
/**
|
|
16
|
-
* USD per unit at the pair's previous close,
|
|
17
|
-
* quote's
|
|
18
|
+
* USD per unit at the pair quote's previous daily close, for the rate drawn
|
|
19
|
+
* whether it is the quote's or a loaded rate of the same FX trading day
|
|
20
|
+
* (fxLegMoveReference); null when the quote is stale or has none.
|
|
18
21
|
*/
|
|
19
22
|
reference: number | null;
|
|
23
|
+
/** The close `reference` is, as `quote` names it ("vs Wed 21 Oct close"). */
|
|
24
|
+
changeBasis?: QuoteChangeBasis | null;
|
|
20
25
|
/** Why the leg has no rate, when it has none. */
|
|
21
26
|
error: string | null;
|
|
22
27
|
}
|
|
@@ -25,9 +30,9 @@ export interface FxLegReading {
|
|
|
25
30
|
* The board's USD legs, read once the way the pane reads them, through the
|
|
26
31
|
* same market data coordinator over the same service: each leg's loaded rate
|
|
27
32
|
* (`loadFxRate`, dated by the shared FX cache), replaced by its pair quote when
|
|
28
|
-
* that quote is current and at least as new.
|
|
29
|
-
* previous close a cross's move is read against. A leg with
|
|
30
|
-
* rate, never parity.
|
|
33
|
+
* that quote is current and at least as new. The pair quote brings the
|
|
34
|
+
* previous close a cross's move is read against, for either rate. A leg with
|
|
35
|
+
* neither has no rate, never parity.
|
|
31
36
|
*/
|
|
32
37
|
export async function loadFxBoard(
|
|
33
38
|
currencies: readonly string[],
|
|
@@ -42,18 +47,20 @@ export async function loadFxBoard(
|
|
|
42
47
|
Promise.all(legs.map((leg) => coordinator.loadFxRate(leg.currency, { forceRefresh }))),
|
|
43
48
|
// A pair quote only refines a loaded rate, so a failed batch leaves the loaded rates.
|
|
44
49
|
coordinator.loadQuotesBatch(legs.map((leg) => ({ symbol: leg.symbol, exchange: "" })), { forceRefresh })
|
|
45
|
-
.catch((
|
|
50
|
+
.catch(logFailure("fx-matrix.client", "Load FX pair quotes failed", [] as QueryEntry<Quote>[])),
|
|
46
51
|
]);
|
|
47
52
|
return new Map(legs.map((leg, index) => {
|
|
48
53
|
const rate = rates[index]!;
|
|
49
54
|
const quote = quotes[index];
|
|
50
55
|
const live = liveFxLegEntry(leg, quote, rate);
|
|
51
56
|
const entry = live ?? (resolveEntryData(rate) != null ? rate : null);
|
|
57
|
+
const close = fxLegMoveReference(leg, quote, entry);
|
|
52
58
|
return [leg.currency, {
|
|
53
59
|
leg,
|
|
54
60
|
entry,
|
|
55
61
|
quote: live ? resolveEntryData(quote) : null,
|
|
56
|
-
reference:
|
|
62
|
+
reference: close?.rate ?? null,
|
|
63
|
+
changeBasis: close ? quoteChangeBasis(close.quote) : null,
|
|
57
64
|
error: entry ? null : rate.error?.message ?? "No rate came back.",
|
|
58
65
|
}] as const;
|
|
59
66
|
}));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { HeadlessPaneDefinition, HeadlessRowsResult } from "../../../types/plugin";
|
|
1
|
+
import type { HeadlessPaneColumn, HeadlessPaneDefinition, HeadlessRowsResult } from "../../../types/plugin";
|
|
2
|
+
import { combinedChangeBasisLabel } from "../../../market-data/market/change-basis";
|
|
2
3
|
import { resolveEntryData } from "../../../market-data/selectors";
|
|
3
4
|
import { formatPercentRaw } from "../../../utils/format";
|
|
4
5
|
import { formatUtcTime } from "../../../utils/utc-time";
|
|
@@ -10,6 +11,26 @@ import { FX_MATRIX_REPORT_OPTIONS, fxMatrixReportNotices } from "./settings";
|
|
|
10
11
|
|
|
11
12
|
const iso = (time: number | null | undefined) => time != null && Number.isFinite(time) ? new Date(time).toISOString() : null;
|
|
12
13
|
|
|
14
|
+
const MOVE_COLUMN: HeadlessPaneColumn = { key: "movePercent", header: "Move", align: "right", format: (value) => typeof value === "number" ? formatPercentRaw(value) : "—" };
|
|
15
|
+
const CROSS_COLUMNS: HeadlessPaneColumn[] = [
|
|
16
|
+
{ key: "pair", header: "Pair" },
|
|
17
|
+
{ key: "rate", header: "Rate", align: "right", format: (value) => typeof value === "number" ? formatRate(value) : "—" },
|
|
18
|
+
MOVE_COLUMN,
|
|
19
|
+
{ key: "asOf", header: "As of", shrink: false, format: (value) => typeof value === "string" ? formatUtcTime(value) : "—" },
|
|
20
|
+
{ key: "stale", header: "Status", format: (value, row) => (
|
|
21
|
+
row.rate == null ? "unavailable" : value ? "stale" : row.asOf == null ? "time unknown" : "current"
|
|
22
|
+
) },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The columns with the move's header naming its close, as `quote` names a
|
|
27
|
+
* pair's (`Move vs Wed 21 Oct close`), in the text report; exports keep
|
|
28
|
+
* `Move`, so a column read by its name stays where it was.
|
|
29
|
+
*/
|
|
30
|
+
function crossColumns(basis: string | null): HeadlessPaneColumn[] {
|
|
31
|
+
return basis ? CROSS_COLUMNS.map((column) => column === MOVE_COLUMN ? { ...column, textHeader: `Move ${basis}` } : column) : CROSS_COLUMNS;
|
|
32
|
+
}
|
|
33
|
+
|
|
13
34
|
/** USD per unit, USD itself as 1; null for a leg with no usable rate. */
|
|
14
35
|
function usdPerUnit(readings: ReadonlyMap<string, FxLegReading>, currency: string): number | null {
|
|
15
36
|
if (currency === "USD") return 1;
|
|
@@ -22,9 +43,10 @@ function usdPerUnit(readings: ReadonlyMap<string, FxLegReading>, currency: strin
|
|
|
22
43
|
* reads: one unit of `base` buys `rate` of `quote`, through the USD legs. Each
|
|
23
44
|
* leg is dated as the pane dates it for `fn` and `shot` (`fxRateObservations`),
|
|
24
45
|
* a cross as `fx <PAIR>` dates one (`fxPairObservation`): as old as its older
|
|
25
|
-
* leg, stale when either leg is. It moves
|
|
26
|
-
*
|
|
27
|
-
* closing line is the one the
|
|
46
|
+
* leg, stale when either leg is. It moves from both legs' previous daily
|
|
47
|
+
* closes, the pane's tint rule, and the Move header names that close. The
|
|
48
|
+
* report itself is dated by the legs, so its closing line is the one the
|
|
49
|
+
* pane's capture ends with.
|
|
28
50
|
*/
|
|
29
51
|
export function projectFxCrosses(
|
|
30
52
|
currencies: readonly FxCurrency[],
|
|
@@ -69,12 +91,15 @@ export function projectFxCrosses(
|
|
|
69
91
|
};
|
|
70
92
|
}));
|
|
71
93
|
|
|
94
|
+
// The closes the moves are read from: one day for a board read at once, "vs mixed closes" otherwise.
|
|
95
|
+
const moveBasis = combinedChangeBasisLabel(currencies.map((currency) => readings.get(currency)?.changeBasis));
|
|
72
96
|
const unavailable = currencies.filter((currency) => !rates.has(currency));
|
|
73
97
|
const errors = unavailable.flatMap((currency) => {
|
|
74
98
|
const error = readings.get(currency)?.error;
|
|
75
99
|
return error ? [`${currency}: ${error}`] : [];
|
|
76
100
|
});
|
|
77
101
|
return {
|
|
102
|
+
columns: crossColumns(moveBasis),
|
|
78
103
|
rows,
|
|
79
104
|
...(rows.length === 0 ? { empty: "One currency has no crosses. Add another, such as --currencies USD,EUR." } : {}),
|
|
80
105
|
complete: unavailable.length === 0,
|
|
@@ -86,7 +111,8 @@ export function projectFxCrosses(
|
|
|
86
111
|
currencies,
|
|
87
112
|
unit: "quote currency per one unit of the base currency",
|
|
88
113
|
method: "the base currency's USD rate divided by the quote currency's; the two legs' observation times can differ",
|
|
89
|
-
movePercent: "the cross against both legs' previous closes; empty where a leg has no current pair quote",
|
|
114
|
+
movePercent: "the cross against both legs' previous daily closes, from each pair's quote; empty where a leg has no current pair quote",
|
|
115
|
+
...(moveBasis ? { changeBasis: moveBasis } : {}),
|
|
90
116
|
legs: currencies.filter((currency) => currency !== "USD").map((currency) => {
|
|
91
117
|
const reading = readings.get(currency);
|
|
92
118
|
const observation = observed.get(currency);
|
|
@@ -119,15 +145,7 @@ export const fxMatrixHeadless: HeadlessPaneDefinition<"rows"> = {
|
|
|
119
145
|
screenshotReadiness: "live-dom",
|
|
120
146
|
},
|
|
121
147
|
options: [...FX_MATRIX_REPORT_OPTIONS],
|
|
122
|
-
columns:
|
|
123
|
-
{ key: "pair", header: "Pair" },
|
|
124
|
-
{ key: "rate", header: "Rate", align: "right", format: (value) => typeof value === "number" ? formatRate(value) : "—" },
|
|
125
|
-
{ key: "movePercent", header: "Move", align: "right", format: (value) => typeof value === "number" ? formatPercentRaw(value) : "—" },
|
|
126
|
-
{ key: "asOf", header: "As of", shrink: false, format: (value) => typeof value === "string" ? formatUtcTime(value) : "—" },
|
|
127
|
-
{ key: "stale", header: "Status", format: (value, row) => (
|
|
128
|
-
row.rate == null ? "unavailable" : value ? "stale" : row.asOf == null ? "time unknown" : "current"
|
|
129
|
-
) },
|
|
130
|
-
],
|
|
148
|
+
columns: CROSS_COLUMNS,
|
|
131
149
|
// Ask Gloom gets every cross of all 45 currencies inside its result limit:
|
|
132
150
|
// the pair names both codes, and each leg's feed and delay are in metadata.
|
|
133
151
|
compact: (result) => ({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
1
2
|
import { useCallback, useMemo, useRef, useState, type ReactNode } from "react";
|
|
2
3
|
import {
|
|
3
4
|
DataTableView,
|
|
@@ -24,7 +25,7 @@ import { fxRateObservations } from "../shared/fx-rate-freshness";
|
|
|
24
25
|
import { useLiveQuoteEntries } from "../../../state/hooks/quote-streaming";
|
|
25
26
|
import { useAutoRefresh, useUpdatedAgo } from "../../../react/auto-refresh";
|
|
26
27
|
import { useLiveStreamingSetting } from "../../../state/hooks/live-streaming";
|
|
27
|
-
import { fxLegQuoteKey, fxLegReferenceRate, fxLegTargets, fxLegs, fxLegsBehind, liveFxLegEntry } from "./live-legs";
|
|
28
|
+
import { fxLegMoveReference, fxLegQuoteKey, fxLegReferenceRate, fxLegTargets, fxLegs, fxLegsBehind, liveFxLegEntry } from "./live-legs";
|
|
28
29
|
import { CURRENCY_FLAG_REGIONS, FX_CURRENCIES, formatRate, resolveCurrencies, type FxCurrency } from "./pairs";
|
|
29
30
|
import { crossMovePercent, directionTint, nextTintLevel } from "./direction";
|
|
30
31
|
import { fxMatrixSettings } from "./settings";
|
|
@@ -91,20 +92,21 @@ function FxMatrixPane({ focused, width, height }: PaneProps) {
|
|
|
91
92
|
}
|
|
92
93
|
return references;
|
|
93
94
|
}, [legEntries, legs, rates]);
|
|
94
|
-
// A cell's direction is its cross against the
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
// read against.
|
|
95
|
+
// A cell's direction is its cross against the pairs' previous daily closes,
|
|
96
|
+
// USD (the base) as 1: each leg's pair quote's close, whether the rate drawn
|
|
97
|
+
// is that quote's or a snapshot rate of the same FX trading day
|
|
98
|
+
// (fxLegMoveReference). The first rate this pane drew is no daily reference,
|
|
99
|
+
// and a stale quote has no close to read against.
|
|
99
100
|
const directionReferences = useMemo(() => {
|
|
101
|
+
const coordinator = getSharedMarketDataCoordinator();
|
|
100
102
|
const references = new Map<string, number>([["USD", 1]]);
|
|
101
103
|
for (const leg of legs) {
|
|
102
|
-
|
|
103
|
-
const reference =
|
|
104
|
-
if (reference
|
|
104
|
+
const drawn = liveEntries.get(leg.currency) ?? coordinator?.getFxEntry(leg.currency);
|
|
105
|
+
const reference = fxLegMoveReference(leg, legEntries.get(fxLegQuoteKey(leg)), drawn);
|
|
106
|
+
if (reference) references.set(leg.currency, reference.rate);
|
|
105
107
|
}
|
|
106
108
|
return references;
|
|
107
|
-
}, [legEntries, legs, liveEntries]);
|
|
109
|
+
}, [legEntries, legs, liveEntries, snapshotRates]);
|
|
108
110
|
// The step each cell showed last, which a tick near a boundary keeps.
|
|
109
111
|
const tintLevels = useRef(new Map<string, number>());
|
|
110
112
|
// Export the provenance of this render's rates, even if a provider response
|
|
@@ -156,7 +158,7 @@ function FxMatrixPane({ focused, width, height }: PaneProps) {
|
|
|
156
158
|
if (!coordinator) return;
|
|
157
159
|
for (const currency of codes) {
|
|
158
160
|
if (currency === "USD") continue;
|
|
159
|
-
void coordinator.loadFxRate(currency, { forceRefresh: true }).catch((
|
|
161
|
+
void coordinator.loadFxRate(currency, { forceRefresh: true }).catch(logFailure("fx-matrix", "Refresh FX rate failed"));
|
|
160
162
|
}
|
|
161
163
|
}, []);
|
|
162
164
|
const refresh = useCallback(() => reload(currencies), [currencies, reload]);
|
|
@@ -3,6 +3,7 @@ import { buildQuoteKey, resolveEntryData } from "../../../market-data/selectors"
|
|
|
3
3
|
import type { QuoteSubscriptionTarget } from "../../../types/data-provider";
|
|
4
4
|
import type { Quote } from "../../../types/financials";
|
|
5
5
|
import { isStreamCarryingQuote } from "../shared/use-quote-board";
|
|
6
|
+
import { fxTradingDay } from "../../../utils/fx-market-hours";
|
|
6
7
|
|
|
7
8
|
/** Currencies the market quotes as USD per unit; the rest quote as units per USD. */
|
|
8
9
|
const USD_QUOTED = new Set(["EUR", "GBP", "AUD", "NZD"]);
|
|
@@ -92,3 +93,24 @@ export function fxLegReferenceRate(leg: FxLeg, entry: QueryEntry<Quote> | undefi
|
|
|
92
93
|
if (close == null || !Number.isFinite(close) || close <= 0) return null;
|
|
93
94
|
return leg.inverted ? 1 / close : close;
|
|
94
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* What a leg's move is read against: its pair quote's previous daily close
|
|
99
|
+
* (USD per unit), the close `quote` measures the pair from, whichever rate
|
|
100
|
+
* the board draws. A loaded rate a minute newer than the quote moves from the
|
|
101
|
+
* same close, so it reads against it too, as long as it is of the quote's FX
|
|
102
|
+
* trading day. Null when the quote is stale or carries no previous close, or
|
|
103
|
+
* when the drawn rate is of a later trading day (or undated) than the quote.
|
|
104
|
+
*/
|
|
105
|
+
export function fxLegMoveReference(
|
|
106
|
+
leg: FxLeg,
|
|
107
|
+
entry: QueryEntry<Quote> | undefined,
|
|
108
|
+
drawn: Pick<QueryEntry<number>, "asOf"> | null | undefined,
|
|
109
|
+
): { rate: number; quote: Quote } | null {
|
|
110
|
+
const quote = resolveEntryData(entry);
|
|
111
|
+
const rate = fxLegReferenceRate(leg, entry);
|
|
112
|
+
if (!quote || quote.stale === true || rate == null || !Number.isFinite(quote.lastUpdated)) return null;
|
|
113
|
+
const drawnAt = drawn?.asOf;
|
|
114
|
+
if (drawnAt == null || !Number.isFinite(drawnAt) || fxTradingDay(drawnAt) !== fxTradingDay(quote.lastUpdated)) return null;
|
|
115
|
+
return { rate, quote };
|
|
116
|
+
}
|
|
@@ -16,6 +16,7 @@ function currencyName(code: string): string | null {
|
|
|
16
16
|
const name = currencyNames.of(code);
|
|
17
17
|
return name && name !== code ? name : null;
|
|
18
18
|
} catch {
|
|
19
|
+
// Intentional ignore: runtimes without currency display names keep the currency code as the picker label.
|
|
19
20
|
currencyNames = null;
|
|
20
21
|
return null;
|
|
21
22
|
}
|
|
@@ -98,5 +99,5 @@ export const FX_MATRIX_REPORT_OPTIONS: readonly PaneReportOptionDef[] = [{
|
|
|
98
99
|
/** A report of the default board says it is only the majors, and how to choose others. */
|
|
99
100
|
export function fxMatrixReportNotices(settings: Readonly<Record<string, unknown>>): string[] {
|
|
100
101
|
if (settings.currencies != null) return [];
|
|
101
|
-
return [`Showing the ${MAJOR_CURRENCIES.length} majors. Choose others with --currencies USD,ZAR,NGN;
|
|
102
|
+
return [`Showing the ${MAJOR_CURRENCIES.length} majors. Choose others with --currencies USD,ZAR,NGN; gloom catalog FXC lists all ${FX_CURRENCIES.length}.`];
|
|
102
103
|
}
|
|
@@ -79,9 +79,11 @@ function boardColumns(width: number, options: { windows: GpuChangeKey[]; trend:
|
|
|
79
79
|
];
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
export function GpuBoard({ rows, models, asOf, model, setModel, selectedId, select, emptyTitle, width, height, focused }: {
|
|
82
|
+
export function GpuBoard({ rows, models, asOf, model, setModel, selectedId, select, emptyTitle, width, height, focused, pending = false }: {
|
|
83
83
|
rows: GpuBoardRow[]; models: readonly string[]; asOf: string | null; model: string; setModel: (value: string) => void; selectedId: string; select: (row: GpuBoardRow, open?: boolean) => void;
|
|
84
84
|
emptyTitle: string; width: number; height: number; focused: boolean;
|
|
85
|
+
/** The picked GPU's free preview is still loading. */
|
|
86
|
+
pending?: boolean;
|
|
85
87
|
}) {
|
|
86
88
|
const colors = useThemeColors();
|
|
87
89
|
const sections = useMemo(() => gpuBoardSections(rows, model), [rows, model]);
|
|
@@ -153,6 +155,7 @@ export function GpuBoard({ rows, models, asOf, model, setModel, selectedId, sele
|
|
|
153
155
|
|
|
154
156
|
const query = <GpuModelQuery models={models} model={model} setModel={setModel} width={width} />;
|
|
155
157
|
return <DataTableView<BoardRow> columns={columns} items={items} rootWidth={width} rootHeight={height} focused={focused}
|
|
158
|
+
status={pending && !items.length ? { loading: true, subject: "GPU rental prices" } : undefined}
|
|
156
159
|
rootBefore={ladder.length ? <ChartTableHeader width={width} height={height} tableRows={items.length} tableColumns={columns} query={query}
|
|
157
160
|
chart={{ maxRows: ladder.length + 1, minRows: Math.min(3, ladder.length + 1), strip: null,
|
|
158
161
|
render: (size) => <GpuPriceLadder rows={ladder} width={size.width} height={size.height}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useMemo } from "react";
|
|
2
2
|
import type { GpuEvent } from "../../../api-client/gpu";
|
|
3
3
|
import {
|
|
4
|
-
Badge, buildSectionedRows, DataTableView, EMPTY_TABLE_CELL, isSectionedItemRow,
|
|
4
|
+
Badge, buildSectionedRows, DataTableView, EMPTY_TABLE_CELL, isSectionedItemRow, renderSectionedRowHeader,
|
|
5
5
|
usePaneNoticeFooter, usePaneStatusFooter, type DataTableCell, type DataTableColumn, type SectionedRow,
|
|
6
6
|
} from "../../../components";
|
|
7
7
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
@@ -82,13 +82,13 @@ export function GpuChanges({ models, model, setModel, reloadBoard, width, height
|
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
// A GPU picked from the filter loads under it; the filter stays.
|
|
86
|
+
return <DataTableView<ChangeRow> columns={columns} items={items} rootWidth={width} rootHeight={height} focused={focused}
|
|
87
|
+
rootBefore={<GpuModelQuery models={models} model={model} setModel={setModel} width={width} />}
|
|
88
|
+
status={resource.data ? undefined : { loading: resource.loading, error: resource.error, subject: "GPU price changes" }}
|
|
89
|
+
selection={{ kind: "id", selectedId: selected && items.some((item) => item.key === selected) ? selected : firstId, getId: rowKey,
|
|
90
|
+
onChange: (id) => setSelected(String(id)) }}
|
|
91
|
+
isNavigable={isSectionedItemRow} renderSectionHeader={renderSectionedRowHeader}
|
|
92
|
+
getItemKey={rowKey} onActivate={(row) => setSelected(row.key)} sortColumnId={null} sortDirection="desc"
|
|
93
|
+
selectedTextOverridesCellColor renderCell={renderCell} emptyStateTitle={resource.data?.payload.access?.locked ? "Full change history is available with Pro." : "No price or availability changes recorded yet."} />;
|
|
94
94
|
}
|
|
@@ -39,9 +39,11 @@ function equityColumns(width: number): DataTableColumn[] {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/** Related shares by what ties them to GPU rents, each beside the list price that ties it. */
|
|
42
|
-
export function GpuEquities({ board, models, locked, model, setModel, reloadBoard, width, height, focused }: {
|
|
42
|
+
export function GpuEquities({ board, models, locked, model, setModel, reloadBoard, width, height, focused, pending = false }: {
|
|
43
43
|
board: GpuBoardRow[]; models: readonly string[]; locked: boolean; model: string; setModel: (value: string) => void; reloadBoard: () => void;
|
|
44
44
|
width: number; height: number; focused: boolean;
|
|
45
|
+
/** The picked GPU's free preview is still loading. */
|
|
46
|
+
pending?: boolean;
|
|
45
47
|
}) {
|
|
46
48
|
const colors = useThemeColors();
|
|
47
49
|
const provider = useAssetData();
|
|
@@ -110,6 +112,7 @@ export function GpuEquities({ board, models, locked, model, setModel, reloadBoar
|
|
|
110
112
|
}, [colors, desktop]);
|
|
111
113
|
return <DataTableView<Row> columns={equityColumns(width)} items={items} rootWidth={width} rootHeight={height} focused={focused}
|
|
112
114
|
rootBefore={<GpuModelQuery models={models} model={model || "H100"} setModel={setModel} width={width} allowAll={false} />}
|
|
115
|
+
status={pending ? { loading: true, subject: "GPU rental prices" } : undefined}
|
|
113
116
|
selection={{ kind: "id", selectedId: selected, getId: rowKey, onChange: (id) => setSelected(String(id)) }} getItemKey={rowKey}
|
|
114
117
|
isNavigable={isSectionedItemRow} renderSectionHeader={renderSectionedRowHeader}
|
|
115
118
|
getRowVersion={(row) => isSectionedItemRow(row) ? [quotes.get(row.item.symbol)?.quote?.lastUpdated, quotes.get(row.item.symbol)?.loading,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
gpuLabel, gpuNoMatch, gpuPrice, gpuProvenanceLabel, gpuRows, gpuSource, gpuTab,
|
|
8
8
|
} from "./model";
|
|
9
9
|
import { quoteFreshnessFields } from "../shared/report-freshness";
|
|
10
|
+
import { countOf, freePreviewNote } from "../shared/free-preview";
|
|
10
11
|
import { getRegularSessionDisplay } from "../../../market-data/market/status";
|
|
11
12
|
|
|
12
13
|
const observationRow = (row: GpuObservation) => ({ gpu: gpuLabel(row), source: gpuSource(row), basis: gpuBasisLabel(row.basis),
|
|
@@ -73,8 +74,12 @@ export const gpuHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
73
74
|
const previews = await fetchGpuModelPreviews(gpuPreviewModels(board, tab === "equities" ? gpuEquityModels(selected) : [selected]), ctx.apiClient);
|
|
74
75
|
const rows = [...board.rows, ...previews];
|
|
75
76
|
const previewed = [...new Set(previews.map((row) => row.gpuModel))];
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
// What the free view leaves to Pro is the report's Pro line, never a note or an error.
|
|
78
|
+
const locks = previewed.length
|
|
79
|
+
? [freePreviewNote({ shows: `the latest rows of ${previewed.join(" and ")}, which the free board leaves out`, adds: "every provider and the 1D, 7D and 30D moves" })]
|
|
80
|
+
: board.access?.locked && !model && tab === "board"
|
|
81
|
+
? [freePreviewNote({ shows: `${countOf(board.rows.length, "board row")}, or the latest rows of a GPU you name (GPU H100)`, adds: "every GPU and provider, with the 1D, 7D and 30D moves" })]
|
|
82
|
+
: [];
|
|
78
83
|
if (tab === "equities") {
|
|
79
84
|
const related = gpuEquityRows(rows, selected, !!board.access?.locked);
|
|
80
85
|
const histories = await loadGpuEquityHistory(ctx.marketData);
|
|
@@ -97,12 +102,12 @@ export const gpuHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
97
102
|
{ key: "gpu", header: "GPU" }, { key: "gpuSource", header: "GPU list series", format: (value: unknown, row: HeadlessPaneRow) => typeof value === "string" ? value : String(row.gpuGap ?? "-") },
|
|
98
103
|
{ key: "gpuPrice", header: "$/GPU-hr", align: "right" as const, format: (value: unknown, row: HeadlessPaneRow) => locked(value, row, price) },
|
|
99
104
|
{ key: "gpuChange7d", header: "GPU 7D", align: "right" as const, format: (value: unknown, row: HeadlessPaneRow) => locked(value, row, percent) },
|
|
100
|
-
], rows: equities }], complete: !board.access?.locked, metadata,
|
|
105
|
+
], rows: equities }], complete: !board.access?.locked, metadata, errors: [...locks, ...board.gaps, ...histories.flatMap((entry) => entry.error ? [entry.error] : [])],
|
|
101
106
|
unavailableSymbols: equities.filter((row) => row.price == null || row.change5d == null).map((row) => row.symbol) };
|
|
102
107
|
}
|
|
103
108
|
const boardRows = gpuRows(rows, model).map((row) => ({ ...observationRow(row), change1d: row.change1d, change7d: row.change7d,
|
|
104
109
|
change30d: row.change30d, stale: row.stale, sample: row.stats ?? null, ...(gpuChangesLocked(row) ? { changesLocked: true } : {}) }));
|
|
105
110
|
return { sections: [{ title: "GPU rental prices", columns, rows: boardRows, empty: `No ${model ? `${model} ` : ""}rental prices have been observed yet.` }],
|
|
106
|
-
freshness, complete: !board.access?.locked, metadata,
|
|
111
|
+
freshness, complete: !board.access?.locked, metadata, errors: [...locks, ...board.gaps] };
|
|
107
112
|
},
|
|
108
113
|
};
|
|
@@ -92,9 +92,11 @@ function HistoryDetail({ row, peers, width, height, refreshVersion }: {
|
|
|
92
92
|
</PaneStatusBody>;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
export function GpuHistory({ rows, models: boardModels, model, setModel, selectedId, onSelect, reloadBoard, width, height, focused }: {
|
|
95
|
+
export function GpuHistory({ rows, models: boardModels, model, setModel, selectedId, onSelect, reloadBoard, width, height, focused, pending = false }: {
|
|
96
96
|
rows: GpuBoardRow[]; models: readonly string[]; model: string; setModel: (value: string) => void; selectedId: string; onSelect: (id: string) => void;
|
|
97
97
|
reloadBoard: () => void; width: number; height: number; focused: boolean;
|
|
98
|
+
/** The picked GPU's free preview is still loading. */
|
|
99
|
+
pending?: boolean;
|
|
98
100
|
}) {
|
|
99
101
|
const colors = useThemeColors();
|
|
100
102
|
const [basis, setBasis] = usePluginPaneState<string>("historyBasis", "all");
|
|
@@ -133,7 +135,7 @@ export function GpuHistory({ rows, models: boardModels, model, setModel, selecte
|
|
|
133
135
|
searchPlaceholder="Provider or variant" columns={listColumns} rows={listRows} getRowId={listRowId}
|
|
134
136
|
filters={[{ id: "gpu", label: "GPU", value: activeModel, options: models.map((value) => ({ value, label: value })), onChange: setModel }]}
|
|
135
137
|
isNavigable={isSectionedItemRow} renderSectionHeader={renderSectionedRowHeader}
|
|
136
|
-
renderCell={renderCell} emptyStateTitle="No series match."
|
|
138
|
+
renderCell={renderCell} emptyStateTitle="No series match." status={pending && !listRows.length ? { loading: true, subject: "GPU rental prices" } : undefined}
|
|
137
139
|
renderDetail={(size) => list.selected ? <HistoryDetail key={list.selected.id} row={list.selected} peers={modelRows} refreshVersion={refreshVersion} {...size} />
|
|
138
140
|
: <PaneStatusBody empty emptyTitle={`No ${gpuBasisLabel(basis === "all" ? "list" : basis as GpuBasis)} series yet.`} />} />;
|
|
139
141
|
}
|
|
@@ -61,13 +61,15 @@ function GpuView({ width, height, focused }: PaneProps) {
|
|
|
61
61
|
usePaneFooter("gpu:actions", () => ({ info: data?.access?.preview ? [{ id: "preview", parts: [{ text: "Free preview", tone: "muted" }] }] : [],
|
|
62
62
|
hints: [...(data?.access?.locked ? [{ id: "upgrade", key: CLOUD_PLAN_KEY, label: "upgrade", title: "Unlock full GPU history with Pro", onPress: upgrade }] : []), { id: "buildout", key: "t", label: "BO", title: "Open TheBuildout",
|
|
63
63
|
onPress: () => createPaneFromTemplate("buildout-pane") }] }), [createPaneFromTemplate, data?.access, upgrade]);
|
|
64
|
-
const { strip, rows: tabRows } = usePaneTabs(
|
|
65
|
-
|
|
64
|
+
const { strip, rows: tabRows } = usePaneTabs(!signIn ? { tabs: [...GPU_TABS], activeValue: tab, onSelect: setTab, focused, dense: true } : null);
|
|
65
|
+
// Another GPU's free preview waits in the table under the GPU filter, so picking a model never takes the filter away.
|
|
66
|
+
const pending = !!previewKey && preview.loading && !preview.data;
|
|
67
|
+
const body = { width, height: Math.max(3, height - tabRows), focused, pending };
|
|
66
68
|
const reloadBoard = useCallback(() => { void resource.reload(); void preview.reload(); }, [resource.reload, preview.reload]);
|
|
67
69
|
if (signIn) return <SignInWall placement="gpu" width={width} height={height} action="browse GPU rental prices" needsVerification={session.needsVerification} />;
|
|
68
70
|
return <Box width={width} height={height} flexDirection="column">
|
|
69
71
|
{strip}
|
|
70
|
-
<PaneStatusBody loading={
|
|
72
|
+
<PaneStatusBody loading={resource.loading && !data} error={!data && !notAvailable ? resource.error : null}
|
|
71
73
|
empty={notAvailable} emptyTitle={GPU_NOT_AVAILABLE} subject="GPU rental prices">
|
|
72
74
|
{data ? tab === "board" ? <GpuBoard rows={rows} models={models} asOf={data.asOf} model={activeModel} setModel={setModel} selectedId={selectedId} emptyTitle={emptyTitle}
|
|
73
75
|
select={(row, open) => { setSelectedId(row.id); if (open) setTab("history"); }} {...body} />
|