gloomberb 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -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
|
}
|
|
@@ -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
|
};
|
|
@@ -267,8 +267,17 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
267
267
|
entry("place", ["Enter", "Arrows"], "With a tool picked, Enter starts it at the cursor, the arrows move its end, and Enter finishes it."),
|
|
268
268
|
entry("drawings", ["[", "]"], "With a drawing tool picked, pick a drawing."),
|
|
269
269
|
entry("colour", ["c", "Backspace"], "Cycle the drawing colour, or delete the picked drawing (the last one while a drawing tool is picked)."),
|
|
270
|
-
entry("zoom-pointer", ["Ctrl+Scroll"], "Zoom around the pointer."),
|
|
271
|
-
entry("
|
|
270
|
+
entry("zoom-pointer", shortcutDisplayMode === "terminal" ? ["Ctrl+Scroll"] : ["Ctrl+Scroll", "Pinch"], "Zoom time around the pointer."),
|
|
271
|
+
entry("time-axis", ["Drag"], "On the time axis, zoom time: left zooms in, right zooms out. Double-click fits it again."),
|
|
272
|
+
entry("value-axis", ["Drag", "Scroll"], "On a value axis, stretch or squeeze that panel's values. Dragging the plot then moves them too."),
|
|
273
|
+
entry("value-fit", ["Double-click", "Auto"], "Fit a hand-scaled panel's values again, from its axis or the Auto button at its foot."),
|
|
274
|
+
entry("zoom-keys", ["+/-", "0"], "Zoom the focused chart in or out, or reset it, values included."),
|
|
275
|
+
shortcutDisplayMode === "terminal"
|
|
276
|
+
? entry("panel-height", ["Shift+Up/Down"], "Make the top panel taller or shorter; Reset Panel Heights in the pane menu puts back the split.")
|
|
277
|
+
: entry("panel-height", ["Drag", "Shift+Up/Down"], "Drag the line between two panels to resize them, double-click it for the default split; Shift+Up and Shift+Down resize the top panel."),
|
|
278
|
+
entry("panel-max", ["Double-click"], "Double-click a panel to give it the whole chart, and again to show every panel."),
|
|
279
|
+
entry("tools-hide", ["Shift+T"], "Hide the drawing tools to a single button, or show them again."),
|
|
280
|
+
entry("legend-fold", ["Shift+L"], "Fold the legend to its first series and a count of the rest, or open it again."),
|
|
272
281
|
],
|
|
273
282
|
},
|
|
274
283
|
{
|
|
@@ -334,7 +343,7 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
334
343
|
)}
|
|
335
344
|
|
|
336
345
|
<Box flexDirection="column" gap={1}>
|
|
337
|
-
<SectionHeading title="How To Use
|
|
346
|
+
<SectionHeading title="How To Use Gloom" />
|
|
338
347
|
<Box flexDirection="column">
|
|
339
348
|
<Text fg={colors.textDim} wrapText>{t("Click anything to use it; the keys shown beside actions are shortcuts.")}</Text>
|
|
340
349
|
<Text fg={colors.textDim} wrapText>
|
|
@@ -413,6 +422,7 @@ export const helpModule: PluginModule = {
|
|
|
413
422
|
name: "Help",
|
|
414
423
|
icon: "?",
|
|
415
424
|
component: HelpPane,
|
|
425
|
+
reportFreshness: { status: "not-a-feed", basis: "documentation" },
|
|
416
426
|
defaultPosition: "right",
|
|
417
427
|
defaultMode: "floating",
|
|
418
428
|
defaultFloatingSize: { width: 88, height: 32 },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BeneficialOwnerFiling, BeneficialOwnerStatus } from "../../../api-client/beneficial-owners";
|
|
2
2
|
import type { DataTableColumn } from "../../../components";
|
|
3
3
|
import type { HolderRecord } from "../../../types/financials";
|
|
4
|
-
import { clipToDisplayWidth, displayWidth, formatCompact } from "../../../utils/format";
|
|
4
|
+
import { clipToDisplayWidth, displayWidth, formatCompact, MISSING_VALUE } from "../../../utils/format";
|
|
5
5
|
import { compareSortValues, type SortDirection } from "../../../utils/sort-values";
|
|
6
6
|
import { matchFilerToHolder, type Holder13FMatch } from "./thirteenf-match";
|
|
7
7
|
|
|
@@ -98,11 +98,8 @@ export function thirteenFAction(holder: HolderRecord | undefined): ThirteenFActi
|
|
|
98
98
|
if (changeShares > 0 && prior === 0) return { label: "NEW", value: Number.POSITIVE_INFINITY };
|
|
99
99
|
if (prior > 0) return { label: signedPercent(changeShares / prior), value: changeShares / prior };
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const fraction = Math.abs(changePercent) <= 1 ? changePercent : changePercent / 100;
|
|
104
|
-
return { label: signedPercent(fraction), value: fraction };
|
|
105
|
-
}
|
|
101
|
+
// A holder record's change is a fraction of the prior position, as the Table tab reads it.
|
|
102
|
+
if (changePercent != null && Number.isFinite(changePercent)) return { label: signedPercent(changePercent), value: changePercent };
|
|
106
103
|
return null;
|
|
107
104
|
}
|
|
108
105
|
|
|
@@ -166,9 +163,9 @@ export function stakeToday(
|
|
|
166
163
|
return { percent, sharesOutstanding };
|
|
167
164
|
}
|
|
168
165
|
|
|
169
|
-
/** `about 49.4% on 35.26M sh today
|
|
170
|
-
export function formatStakeToday(today: StakeToday): string {
|
|
171
|
-
return `about ${formatClassPercent(today.percent)} on ${formatCompact(today.sharesOutstanding)} sh today`;
|
|
166
|
+
/** `about 49.4% on 35.26M sh today`, or `as of 2026-09-03` for a count dated by its filing. */
|
|
167
|
+
export function formatStakeToday(today: StakeToday, sharesOutstandingAsOf?: string | null): string {
|
|
168
|
+
return `about ${formatClassPercent(today.percent)} on ${formatCompact(today.sharesOutstanding)} sh ${sharesOutstandingAsOf ? `as of ${sharesOutstandingAsOf}` : "today"}`;
|
|
172
169
|
}
|
|
173
170
|
|
|
174
171
|
function beneficialFormLabel(filing: Pick<BeneficialOwnerFiling, "kind" | "amendment">): string {
|
|
@@ -308,7 +305,7 @@ export function formatPercentOfClass(
|
|
|
308
305
|
): string {
|
|
309
306
|
const value = row.filing.percentOfClass;
|
|
310
307
|
const mark = marker ? stakeMarker(row.stake) : "";
|
|
311
|
-
if (value == null) return mark ||
|
|
308
|
+
if (value == null) return mark || MISSING_VALUE;
|
|
312
309
|
return mark ? `${formatClassPercent(value)} ${mark}` : formatClassPercent(value);
|
|
313
310
|
}
|
|
314
311
|
|
|
@@ -320,7 +317,7 @@ export function formatPointChange(value: number | null): string {
|
|
|
320
317
|
}
|
|
321
318
|
|
|
322
319
|
export function formatOwnerShares(value: number | null): string {
|
|
323
|
-
return value == null ?
|
|
320
|
+
return value == null ? MISSING_VALUE : formatCompact(value);
|
|
324
321
|
}
|
|
325
322
|
|
|
326
323
|
/**
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
type BeneficialSortPreference,
|
|
15
15
|
} from "./beneficial-model";
|
|
16
16
|
import { buildRows } from "./table-model";
|
|
17
|
-
import { formatCompact } from "../../../utils/format";
|
|
17
|
+
import { formatCompact, MISSING_VALUE } from "../../../utils/format";
|
|
18
18
|
|
|
19
19
|
/** What `holders --form` lists: the 13F table, or the 13D/13G beneficial owners. */
|
|
20
20
|
export type HolderForm = "13f" | "13d" | "13g" | "all";
|
|
@@ -53,7 +53,7 @@ export const BENEFICIAL_REPORT_COLUMNS = [
|
|
|
53
53
|
align: "right" as const,
|
|
54
54
|
format: (value: unknown, row: Record<string, unknown>) => {
|
|
55
55
|
const marker = stakeMarker(row.status === "below-threshold" || row.status === "exited" ? row.status : null);
|
|
56
|
-
if (typeof value !== "number") return marker ||
|
|
56
|
+
if (typeof value !== "number") return marker || MISSING_VALUE;
|
|
57
57
|
return marker ? `${formatClassPercent(value)} ${marker}` : formatClassPercent(value);
|
|
58
58
|
},
|
|
59
59
|
},
|
|
@@ -76,9 +76,9 @@ export const BENEFICIAL_REPORT_COLUMNS = [
|
|
|
76
76
|
align: "right" as const,
|
|
77
77
|
format: (value: unknown) => formatOwnerShares(typeof value === "number" ? value : null),
|
|
78
78
|
},
|
|
79
|
-
{ key: "eventDate", header: "Event", format: (value: unknown) => typeof value === "string" ? value :
|
|
79
|
+
{ key: "eventDate", header: "Event", format: (value: unknown) => typeof value === "string" ? value : MISSING_VALUE },
|
|
80
80
|
{ key: "filingDate", header: "Filed" },
|
|
81
|
-
{ key: "thirteenF", header: "13F", align: "right" as const, format: (value: unknown) => typeof value === "string" ? value :
|
|
81
|
+
{ key: "thirteenF", header: "13F", align: "right" as const, format: (value: unknown) => typeof value === "string" ? value : MISSING_VALUE },
|
|
82
82
|
];
|
|
83
83
|
|
|
84
84
|
/** The 13D/13G columns these rows fill: `% Today` only when a report's base is no longer today's count. */
|
|
@@ -94,10 +94,11 @@ export function beneficialReportColumns(rows: readonly BeneficialReportRow[]): t
|
|
|
94
94
|
export function beneficialReportLegend(
|
|
95
95
|
rows: readonly BeneficialReportRow[],
|
|
96
96
|
sharesOutstanding: number | null | undefined,
|
|
97
|
+
sharesOutstandingAsOf?: string | null,
|
|
97
98
|
): string | null {
|
|
98
99
|
if (rows.length === 0) return null;
|
|
99
100
|
const today = sharesOutstanding != null && rows.some((row) => row.percentToday != null)
|
|
100
|
-
? `; % Today is the same shares over ${formatCompact(sharesOutstanding)} shares outstanding today`
|
|
101
|
+
? `; % Today is the same shares over ${formatCompact(sharesOutstanding)} shares outstanding ${sharesOutstandingAsOf ? `as of ${sharesOutstandingAsOf}` : "today"}`
|
|
101
102
|
: "";
|
|
102
103
|
const others = rows.some((row) => row.otherPersons > 0) ? " +N after a name: other reporting persons on the same report." : "";
|
|
103
104
|
return `% Class is as filed${today}.${others}`;
|