gloomberb 0.16.4 → 0.16.6
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 +14 -91
- package/package.json +5 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
- package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
- package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/central-bank-rates.ts +6 -1
- package/src/api-client/chat.ts +26 -0
- package/src/api-client/credit-boards.ts +2 -0
- package/src/api-client/data.ts +73 -3
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/europe-energy.ts +106 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +13 -1
- package/src/api-client/market-discovery.ts +13 -1
- package/src/api-client/normalizers.ts +32 -0
- package/src/api-client/paths.ts +7 -0
- package/src/api-client/perps.ts +8 -0
- package/src/api-client/request.ts +9 -2
- package/src/api-client/research-activity.ts +15 -10
- package/src/api-client/socket.ts +29 -0
- package/src/api-client/themes.ts +22 -1
- package/src/api-client/types.ts +78 -2
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +50 -2
- package/src/app/keybindings/actions.ts +12 -1
- package/src/app/pane-runtime/plugin-bindings.ts +2 -2
- package/src/app/pane-runtime/ticker-open-runtime.ts +16 -6
- package/src/app/runtime/desktop-deeplink.ts +10 -5
- package/src/app/runtime/startup.ts +1 -1
- package/src/app.tsx +6 -0
- package/src/architecture/core-builtin-allowlist.json +8 -26
- package/src/ask-gloom/pane-context.ts +114 -0
- package/src/ask-gloom/pane-request.ts +70 -0
- package/src/ask-gloom/pane-text.ts +201 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
- package/src/capabilities/chart-series.ts +19 -2
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/central-bank-events.ts +23 -0
- package/src/cli/command-options.ts +17 -5
- package/src/cli/commands/crypto-hints.ts +35 -2
- package/src/cli/commands/fred-series.ts +146 -0
- package/src/cli/commands/market.ts +501 -115
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-leaps.ts +5 -2
- package/src/cli/commands/overview.ts +132 -26
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +317 -13
- package/src/cli/commands/system.ts +55 -8
- package/src/cli/commands/ticker.ts +155 -18
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +76 -7
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +7 -5
- package/src/cli/exit-codes.ts +8 -0
- package/src/cli/export-source.ts +58 -0
- package/src/cli/freshness.ts +18 -7
- package/src/cli/glossary.ts +483 -0
- package/src/cli/help.ts +10 -0
- package/src/cli/helpers.ts +2 -5
- package/src/cli/history-rows.ts +118 -7
- package/src/cli/index-roots.ts +7 -0
- package/src/cli/index.ts +29 -9
- package/src/cli/known-gaps.ts +84 -0
- package/src/cli/listing-arg.ts +551 -97
- package/src/cli/not-a-ticker.ts +24 -9
- package/src/cli/pane-functions/access-gate.ts +13 -2
- package/src/cli/pane-functions/capabilities.ts +4 -3
- package/src/cli/pane-functions/catalog.ts +214 -40
- package/src/cli/pane-functions/data.ts +42 -8
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +37 -8
- package/src/cli/pane-functions/freshness.ts +393 -49
- package/src/cli/pane-functions/function-help.ts +31 -15
- package/src/cli/pane-functions/headless.ts +98 -30
- package/src/cli/pane-functions/index.ts +101 -19
- package/src/cli/pane-functions/market-session.ts +22 -8
- package/src/cli/pane-functions/options.ts +71 -22
- package/src/cli/pane-functions/report-notices.ts +25 -7
- package/src/cli/pane-functions/report.ts +15 -8
- package/src/cli/pane-functions/resolver.ts +74 -19
- package/src/cli/pane-functions/screenshot.ts +250 -27
- package/src/cli/perpetual-contract.ts +60 -0
- package/src/cli/registry.ts +3 -1
- package/src/cli/report-tables.ts +26 -7
- package/src/cli/result.ts +45 -11
- package/src/cli/series-search.ts +111 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +27 -0
- package/src/cli/symbol-list.ts +154 -0
- package/src/cli/symbol-rows.ts +154 -0
- package/src/cli/ticker-resolution.ts +311 -27
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +14 -3
- package/src/components/chart/composite/composite-chart.tsx +71 -11
- package/src/components/chart/composite/crosshair-readout.tsx +150 -0
- package/src/components/chart/composite/downsample.ts +1 -1
- package/src/components/chart/composite/format.ts +29 -0
- package/src/components/chart/composite/interactions.ts +9 -2
- package/src/components/chart/composite/legend.tsx +100 -33
- package/src/components/chart/composite/panel-bitmap.ts +70 -35
- package/src/components/chart/composite/panel-labels.ts +18 -17
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +46 -21
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +50 -8
- package/src/components/chart/composite/scene.ts +2 -1
- package/src/components/chart/composite/time-scale.ts +26 -9
- package/src/components/chart/composite/types.ts +18 -0
- package/src/components/chart/composite/use-composite-viewport.ts +30 -2
- package/src/components/chart/native/raster/crosshair.ts +8 -3
- package/src/components/chart/native/raster/primitives.ts +85 -21
- package/src/components/chart/native/surface/manager.ts +33 -8
- package/src/components/chart/surface3d/chart.tsx +1 -1
- package/src/components/command-bar/action-runtime.ts +1 -1
- package/src/components/command-bar/commands/collection-list.ts +210 -0
- package/src/components/command-bar/commands/collection.ts +40 -1
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -0
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/routing/actions.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +42 -17
- package/src/components/layout/detached-pane-shell.tsx +68 -39
- package/src/components/layout/floating-pane.tsx +10 -1
- package/src/components/layout/header.tsx +25 -5
- package/src/components/layout/missing-pane.tsx +3 -3
- package/src/components/layout/pane/capture-stamp.ts +41 -0
- package/src/components/layout/pane/capture-status.ts +12 -0
- package/src/components/layout/pane/content.tsx +7 -13
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/keyboard.ts +3 -0
- package/src/components/layout/pane/footer/model.ts +41 -1
- package/src/components/layout/pane/header.tsx +50 -1
- package/src/components/layout/pane/index.tsx +21 -3
- package/src/components/layout/pane/sidebar.tsx +88 -21
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/cursor-occlusion.ts +2 -1
- package/src/components/layout/shell/drag/index.ts +39 -9
- package/src/components/layout/shell/drag/live.ts +61 -51
- package/src/components/layout/shell/drag/runtime.ts +54 -12
- package/src/components/layout/shell/index.tsx +84 -65
- package/src/components/layout/shell/menu.ts +14 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +32 -10
- package/src/components/layout/shell/pane/ask.ts +131 -0
- package/src/components/layout/shell/pane/capture.ts +162 -0
- package/src/components/layout/shell/pane/layers.tsx +218 -50
- package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
- package/src/components/layout/shell/shortcuts.ts +21 -4
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/markdown-text.tsx +62 -20
- package/src/components/metric-treemap/heat-surface.tsx +8 -1
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +2 -2
- package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/reader/article-reader.tsx +642 -0
- package/src/components/reader/article-text.ts +527 -0
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +43 -2
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +7 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +18 -6
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +12 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +6 -1
- package/src/components/ui/query-bar.tsx +10 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/normalize.ts +7 -2
- package/src/data/config/store/portfolio-as-of-column.ts +57 -0
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7555 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +65 -5
- package/src/i18n/ja.ts +65 -5
- package/src/i18n/ko.ts +65 -5
- package/src/i18n/zh-cn.ts +65 -5
- package/src/i18n/zh-tw.ts +65 -5
- package/src/layout/desks.ts +1 -1
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/layout-marketplace/gallery.tsx +1 -1
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +84 -20
- package/src/market-data/market/session-close-note.ts +3 -2
- package/src/market-data/market/status.ts +19 -23
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +5 -0
- package/src/market-data/quotes/metadata.ts +19 -24
- package/src/market-data/quotes/resolution.ts +5 -0
- package/src/market-data/quotes/screener-live-quotes.ts +5 -4
- package/src/market-data/result-types.ts +2 -0
- package/src/notifications/app-notifier.ts +17 -1
- package/src/notifications/notification-log.ts +180 -0
- package/src/plugins/auto-update-node.ts +2 -2
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/model.ts +1 -56
- package/src/plugins/builtin/account-management/pane.tsx +6 -4
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/catalysts.ts +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/focus.ts +27 -0
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +47 -11
- package/src/plugins/builtin/alerts/pane.tsx +27 -1
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +8 -3
- package/src/plugins/builtin/analytics/risk-headless.ts +60 -27
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +35 -5
- package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/headless.ts +88 -18
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/model.ts +41 -1
- package/src/plugins/builtin/awards/pane.tsx +22 -13
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/headless.ts +2 -2
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +1 -1
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +49 -12
- package/src/plugins/builtin/cds/headless.ts +119 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +214 -32
- package/src/plugins/builtin/cds/pane.tsx +58 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
- package/src/plugins/builtin/central-bank-rates/index.tsx +3 -1
- package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
- package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
- package/src/plugins/builtin/central-bank-rates/series.ts +36 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +193 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
- package/src/plugins/builtin/chart-composer/headless.ts +70 -5
- package/src/plugins/builtin/chart-composer/index.tsx +15 -3
- package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
- package/src/plugins/builtin/chat/content/composer.tsx +5 -1
- package/src/plugins/builtin/chat/content/footer.tsx +12 -0
- package/src/plugins/builtin/chat/content/index.tsx +89 -5
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
- package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
- package/src/plugins/builtin/chat/content/scroll.ts +127 -27
- package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
- package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
- package/src/plugins/builtin/chat/content/types.ts +1 -0
- package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
- package/src/plugins/builtin/chat/controller/index.ts +123 -1
- package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
- package/src/plugins/builtin/chat/controller/messages.ts +7 -2
- package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
- package/src/plugins/builtin/chat/controller/send.ts +61 -1
- package/src/plugins/builtin/chat/controller/state.ts +8 -0
- package/src/plugins/builtin/chat/ghost-user.ts +20 -0
- package/src/plugins/builtin/chat/index.tsx +23 -5
- package/src/plugins/builtin/chat/layout.ts +78 -5
- package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
- package/src/plugins/builtin/chat/message/header.tsx +16 -4
- package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
- package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
- package/src/plugins/builtin/chat/message/render-state.ts +18 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
- package/src/plugins/builtin/chat/message/types.ts +12 -0
- package/src/plugins/builtin/chat/reactions.ts +197 -0
- package/src/plugins/builtin/chat/share/flow.tsx +87 -0
- package/src/plugins/builtin/chat/share/targets.ts +27 -0
- package/src/plugins/builtin/chat/status-widget.tsx +6 -3
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
- package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
- package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
- package/src/plugins/builtin/cloud/askg/model.ts +27 -8
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
- package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
- package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
- package/src/plugins/builtin/cloud/plugin.tsx +19 -2
- package/src/plugins/builtin/cloud/team/model.ts +5 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/team/store.ts +8 -3
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +21 -7
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/headless.ts +97 -10
- package/src/plugins/builtin/company-kpis/model.ts +24 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +17 -16
- package/src/plugins/builtin/composite-plugins.ts +19 -13
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/cpi/headless.ts +3 -3
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
- package/src/plugins/builtin/credit-boards/client.ts +6 -2
- package/src/plugins/builtin/credit-boards/headless.ts +108 -31
- package/src/plugins/builtin/credit-boards/index.tsx +2 -0
- package/src/plugins/builtin/credit-boards/model.ts +11 -1
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-conditions/client.ts +12 -9
- package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +18 -9
- package/src/plugins/builtin/credit-conditions/model.ts +19 -11
- package/src/plugins/builtin/credit-conditions/series.ts +16 -0
- package/src/plugins/builtin/credit-documents/headless.ts +33 -3
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/client.ts +3 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +7 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/dividend-yield/types.ts +2 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/headless.ts +12 -8
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/earnings/index.tsx +9 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
- package/src/plugins/builtin/econ/fred-catalog.ts +198 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/equity-screener/headless.ts +3 -3
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
- package/src/plugins/builtin/exposure/drivers.ts +13 -0
- package/src/plugins/builtin/exposure/headless.ts +205 -13
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/index.tsx +1 -0
- package/src/plugins/builtin/exposure/model.ts +23 -3
- package/src/plugins/builtin/exposure/pane.tsx +14 -12
- package/src/plugins/builtin/fear-greed/index.tsx +18 -10
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +71 -10
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/client.ts +63 -0
- package/src/plugins/builtin/fx-matrix/export.ts +2 -1
- package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -4
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +58 -27
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +101 -16
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/function-index.ts +2 -0
- package/src/plugins/builtin/help/index.tsx +31 -9
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +36 -133
- package/src/plugins/builtin/holders/pane.tsx +11 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +26 -9
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
- package/src/plugins/builtin/iv-history/client.ts +20 -6
- package/src/plugins/builtin/iv-history/format.ts +9 -0
- package/src/plugins/builtin/iv-history/headless.ts +56 -21
- package/src/plugins/builtin/iv-history/index.tsx +2 -0
- package/src/plugins/builtin/iv-history/model.ts +143 -8
- package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +26 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/macro-day/client.ts +44 -3
- package/src/plugins/builtin/macro-day/headless.ts +13 -10
- package/src/plugins/builtin/macro-day/model.ts +56 -10
- package/src/plugins/builtin/macro-day/pane.tsx +30 -20
- package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
- package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
- package/src/plugins/builtin/market-heatmap/model.ts +19 -11
- package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/index.tsx +3 -2
- package/src/plugins/builtin/market-movers/model.ts +30 -0
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +8 -3
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +6 -8
- package/src/plugins/builtin/mna/distress/headless.ts +4 -4
- package/src/plugins/builtin/mna/headless.ts +18 -6
- package/src/plugins/builtin/money-markets/headless.ts +5 -4
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/news/index.tsx +0 -2
- package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
- package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +3 -0
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +4 -3
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +2 -1
- package/src/plugins/builtin/options-scenario/headless.ts +1 -0
- package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
- package/src/plugins/builtin/perps/client.ts +90 -16
- package/src/plugins/builtin/perps/equity-row.tsx +52 -17
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +47 -32
- package/src/plugins/builtin/perps/index.tsx +23 -4
- package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
- package/src/plugins/builtin/perps/model.ts +20 -5
- package/src/plugins/builtin/perps/open-market.ts +15 -0
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +73 -67
- package/src/plugins/builtin/plugin-module.ts +3 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
- package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +161 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +384 -74
- package/src/plugins/builtin/portfolio-list/cli/render.ts +437 -71
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +21 -4
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +121 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +104 -26
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +84 -18
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
- package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +52 -9
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +33 -11
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
- package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +9 -4
- package/src/plugins/builtin/portfolio-list/table.tsx +37 -7
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +63 -10
- package/src/plugins/builtin/power/headless.ts +77 -9
- package/src/plugins/builtin/power/index.tsx +28 -3
- package/src/plugins/builtin/power/model.ts +73 -2
- package/src/plugins/builtin/power/pane.tsx +37 -9
- package/src/plugins/builtin/power/prices-client.ts +139 -0
- package/src/plugins/builtin/power/prices-headless.ts +137 -0
- package/src/plugins/builtin/power/prices-model.ts +103 -0
- package/src/plugins/builtin/power/prices.tsx +179 -0
- package/src/plugins/builtin/rate-path/headless.ts +46 -18
- package/src/plugins/builtin/realized-vol/headless.ts +5 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/research/index.tsx +2 -0
- package/src/plugins/builtin/research-search/article.ts +65 -0
- package/src/plugins/builtin/research-search/document-view.tsx +33 -215
- package/src/plugins/builtin/research-search/model.ts +0 -9
- package/src/plugins/builtin/research-search/pane.tsx +41 -30
- package/src/plugins/builtin/research-search/snippet.ts +0 -29
- package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/sec/headless.ts +25 -3
- package/src/plugins/builtin/sec/index.tsx +2 -1
- package/src/plugins/builtin/series-inventory.ts +93 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +30 -12
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/free-preview.ts +47 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +12 -1
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/volatility/options.ts +4 -1
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +2 -0
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +3 -2
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +2 -1
- package/src/plugins/builtin/short-volume/index.tsx +2 -0
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/headless.ts +43 -11
- package/src/plugins/builtin/supply-chain/model.ts +13 -0
- package/src/plugins/builtin/supply-chain/pane.tsx +8 -6
- package/src/plugins/builtin/themes/headless.ts +74 -10
- package/src/plugins/builtin/themes/model.ts +71 -4
- package/src/plugins/builtin/themes/pane.tsx +22 -5
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +26 -11
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +49 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +2 -1
- package/src/plugins/builtin/time-sales/index.tsx +2 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
- package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
- package/src/plugins/builtin/vol-surface/headless.ts +51 -17
- package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
- package/src/plugins/builtin/vol-surface/model.ts +39 -6
- package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
- package/src/plugins/builtin/vol-surface/stored.ts +63 -3
- package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
- package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +2 -1
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +24 -13
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
- package/src/plugins/builtin/world-venue-map/model.ts +56 -19
- package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +4 -2
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/installer.ts +2 -2
- package/src/plugins/loader.ts +15 -0
- package/src/plugins/manager-node.ts +1 -1
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
- package/src/plugins/registry/host-actions.ts +11 -0
- package/src/plugins/registry/index.ts +89 -4
- package/src/portfolio/collection-name.ts +31 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/portfolio/valuation-basis.ts +79 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/react/input.ts +33 -1
- package/src/react/key-repeat.ts +86 -0
- package/src/remote/app-host.tsx +20 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +144 -7
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +65 -2
- package/src/remote/types.ts +30 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +4 -3
- package/src/renderers/browser/research-entry.ts +4 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +30 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +16 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
- package/src/renderers/dom/host/box.tsx +8 -0
- package/src/renderers/dom/host/chart-surface.tsx +33 -2
- package/src/renderers/dom/host/live-frame.ts +6 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/scroll-box.tsx +32 -0
- package/src/renderers/dom/host/size-observer.ts +41 -0
- package/src/renderers/dom/host/sticky-scroll.ts +128 -0
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/surface-3d.tsx +19 -7
- package/src/renderers/dom/host/surface-fit.ts +406 -0
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +1 -0
- package/src/renderers/dom/styles.css +102 -5
- package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
- package/src/renderers/electrobun/bun/index.ts +3 -2
- package/src/renderers/electrobun/shared/protocol.ts +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +29 -2
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +63 -20
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +5 -3
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
- package/src/renderers/opentui/chart-surface.tsx +1 -0
- package/src/renderers/opentui/frame-capture.ts +33 -0
- package/src/renderers/opentui/host.tsx +10 -13
- package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
- package/src/renderers/opentui/pane-image/glyphs.json +1 -0
- package/src/renderers/opentui/pane-image/index.ts +107 -0
- package/src/renderers/opentui/pane-image/raster.ts +428 -0
- package/src/renderers/opentui/start.tsx +3 -3
- package/src/renderers/opentui/test-utils.tsx +3 -0
- package/src/renderers/opentui/ui-host.tsx +29 -1
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +108 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +153 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/chat.ts +34 -0
- package/src/shares/dialog.tsx +295 -0
- package/src/shares/flow.tsx +56 -0
- package/src/shares/live.ts +14 -22
- package/src/shares/pane-image.ts +152 -0
- package/src/shares/personal-pane.ts +64 -0
- package/src/shares/portable-layout.ts +4 -2
- package/src/shares/prepare.ts +20 -0
- package/src/sources/gloomberb-cloud/index.ts +109 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +3 -0
- package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
- package/src/sources/history-result.ts +1 -0
- package/src/sources/history-retention.ts +11 -0
- package/src/sources/listing-symbols.ts +4 -1
- package/src/sources/listing-target.ts +4 -0
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +1 -1
- package/src/sources/provider-router/financial-routes.ts +1 -0
- package/src/sources/provider-router/financials.ts +13 -0
- package/src/sources/provider-router/history.ts +43 -25
- package/src/sources/provider-router/index.ts +14 -0
- package/src/sources/provider-router/search.ts +1 -0
- package/src/state/hooks/inline-tickers.ts +49 -11
- package/src/sync/core-contributors.ts +1 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/theme-context.tsx +15 -1
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +34 -1
- package/src/tickers/listing-name.ts +34 -0
- package/src/tickers/listing-venues.ts +132 -0
- package/src/tickers/open-target.ts +13 -4
- package/src/tickers/perpetual-listing.ts +151 -0
- package/src/tickers/prediction-listing.ts +26 -0
- package/src/tickers/search/index.ts +72 -11
- package/src/tickers/search/ranking.ts +98 -20
- package/src/tickers/search/types.ts +7 -1
- package/src/tickers/ticker-changes.ts +213 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/economic.ts +2 -6
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/ice-credit.ts +39 -0
- package/src/time-series/resolve.ts +211 -29
- package/src/time-series/studies.ts +1 -0
- package/src/time-series/types.ts +12 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +10 -2
- package/src/types/data-provider.ts +11 -0
- package/src/types/financials.ts +62 -1
- package/src/types/headless.ts +113 -0
- package/src/types/instrument.ts +4 -0
- package/src/types/plugin.ts +52 -2
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker-changes.ts +26 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/context-menu.tsx +13 -1
- package/src/ui/host.tsx +57 -3
- package/src/ui/live-resize.ts +91 -0
- package/src/ui/live-stretch.ts +153 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/sticky-scroll.ts +7 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/central-banks.ts +76 -0
- package/src/utils/cli-output.ts +131 -15
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/currency-units.ts +11 -0
- package/src/utils/datetime-format.ts +27 -6
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +439 -52
- package/src/utils/double-escape-close.ts +15 -1
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +143 -1
- package/src/utils/format.ts +35 -5
- package/src/utils/forward-dividend.ts +14 -0
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +15 -5
- package/src/utils/fx-status.ts +6 -1
- package/src/utils/inline-content-tokenizer.ts +22 -3
- package/src/utils/market-capitalization.ts +8 -0
- package/src/utils/one-shot.ts +73 -0
- package/src/utils/options.ts +37 -8
- package/src/utils/price-history.ts +99 -42
- package/src/utils/sec-eps-basis.ts +24 -11
- package/src/utils/sec.ts +61 -7
- package/src/utils/utc-time.ts +63 -4
- package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
- /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { apiClient } from "../../../api-client";
|
|
2
|
+
import type { CarbonBoard, EuropePowerBoard, PowerPriceRow } from "../../../api-client/europe-energy";
|
|
3
|
+
import type { HeadlessBundleResult, HeadlessBundleSection, HeadlessPaneColumn, HeadlessPaneDefinition } from "../../../types/plugin";
|
|
4
|
+
import { fetchCarbonPrice, fetchPowerPriceHistory, fetchPowerPrices } from "./prices-client";
|
|
5
|
+
import {
|
|
6
|
+
CARBON_PRICE_UNIT, formatPowerChange, formatPowerPrice, isCarbonQuery, POWER_PRICE_UNIT, powerPriceMarket, powerRangePosition,
|
|
7
|
+
} from "./prices-model";
|
|
8
|
+
|
|
9
|
+
type PricesClient = Pick<typeof apiClient, "getCloudEuropePower" | "getCloudEuropePowerHistory" | "getCloudEuropeCarbon">;
|
|
10
|
+
|
|
11
|
+
const price = (value: unknown) => typeof value === "number" ? formatPowerPrice(value) : "--";
|
|
12
|
+
const text = (value: unknown) => typeof value === "string" && value ? value : "--";
|
|
13
|
+
|
|
14
|
+
/** A board's columns, in its words: prices to the cent in the board's unit, each row dated by its own day. */
|
|
15
|
+
const boardColumns = (unit: string, label = "Market"): HeadlessPaneColumn[] => [
|
|
16
|
+
{ key: "market", header: label },
|
|
17
|
+
{ key: "date", header: "As of", format: text, shrink: false },
|
|
18
|
+
{ key: "price", header: unit, align: "right", format: price },
|
|
19
|
+
{ key: "change", header: "1D", align: "right", format: (value) => typeof value === "number" ? formatPowerChange(value) : "--" },
|
|
20
|
+
{ key: "average7", header: "7D avg", align: "right", format: price },
|
|
21
|
+
{ key: "average30", header: "30D avg", align: "right", format: price },
|
|
22
|
+
{ key: "yearAgo", header: "1Y ago", align: "right", format: price },
|
|
23
|
+
{ key: "low52w", header: "52W low", align: "right", format: price },
|
|
24
|
+
{ key: "high52w", header: "52W high", align: "right", format: price },
|
|
25
|
+
{ key: "range", header: "In 1Y range", align: "right", format: (value) => typeof value === "number" ? `${value}%` : "--" },
|
|
26
|
+
];
|
|
27
|
+
const COLUMNS = boardColumns(POWER_PRICE_UNIT);
|
|
28
|
+
const AUCTION_COLUMNS: HeadlessPaneColumn[] = [
|
|
29
|
+
{ key: "date", header: "Date", shrink: false },
|
|
30
|
+
{ key: "zone", header: "Zone", format: text },
|
|
31
|
+
{ key: "status", header: "Status" },
|
|
32
|
+
{ key: "price", header: CARBON_PRICE_UNIT, align: "right", format: price },
|
|
33
|
+
{ key: "volume", header: "Volume tCO2", align: "right", format: (value) => typeof value === "number" ? value.toLocaleString("en-US") : "--" },
|
|
34
|
+
{ key: "coverRatio", header: "Cover", align: "right", format: (value) => typeof value === "number" ? `${value.toFixed(2)}x` : "--" },
|
|
35
|
+
{ key: "bidders", header: "Bidders", align: "right", format: (value) => typeof value === "number" ? String(value) : "--" },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function reportRow(row: Omit<PowerPriceRow, "code"> & { code: string }) {
|
|
39
|
+
const { trail: _trail, name, ...figures } = row;
|
|
40
|
+
return { market: name, ...figures, range: powerRangePosition(row as PowerPriceRow) };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The EUA as of its latest auction day, then its latest general-allowance auctions. */
|
|
44
|
+
function carbonSections(carbon: CarbonBoard): HeadlessBundleSection[] {
|
|
45
|
+
const { volume: _volume, auctions: _auctions, ...row } = carbon.row;
|
|
46
|
+
return [
|
|
47
|
+
{ title: `EU carbon allowance (EUA) auction price, ${CARBON_PRICE_UNIT}`, columns: boardColumns(CARBON_PRICE_UNIT, "Allowance"), rows: [reportRow(row)] },
|
|
48
|
+
{ title: "Latest EUA auctions", columns: AUCTION_COLUMNS,
|
|
49
|
+
rows: carbon.auctions.filter((auction) => !auction.aviation).map(({ aviation: _aviation, ...auction }) => ({ ...auction })) },
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The delivery day most markets have reached: the median market's latest
|
|
55
|
+
* day. A few markets publish ahead of the rest (Ireland the day before, most
|
|
56
|
+
* of the continent four days behind), so the freshest one would understate
|
|
57
|
+
* how far behind the board is.
|
|
58
|
+
*/
|
|
59
|
+
function typicalPowerDate(rows: readonly Pick<PowerPriceRow, "date">[]): string | null {
|
|
60
|
+
const dates = rows.flatMap((row) => row.date ? [row.date] : []).sort();
|
|
61
|
+
return dates[Math.floor((dates.length - 1) / 2)] ?? null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* One short line, the same in the report, the pane and a capture: the board
|
|
66
|
+
* is dated by the day most markets have reached and lags from it (`most
|
|
67
|
+
* markets 2026-10-07 · lag 4 days`); one market by its own delivery day; the
|
|
68
|
+
* EUA alone by its last auction.
|
|
69
|
+
*/
|
|
70
|
+
function freshness(board: EuropePowerBoard | null, carbon: CarbonBoard | null, market?: PowerPriceRow): HeadlessBundleResult["freshness"] {
|
|
71
|
+
const asOf = market ? market.date : board ? typicalPowerDate(board.rows) : carbon?.row.date ?? null;
|
|
72
|
+
return {
|
|
73
|
+
source: [board?.source.name, carbon?.source.name].filter(Boolean).join(", "),
|
|
74
|
+
asOf, oldest: null,
|
|
75
|
+
observation: market ? "delivery day" : board ? "most markets" : "last auction",
|
|
76
|
+
status: "not-a-feed", observedKey: "date", basis: board ? "day-ahead auction" : "primary auction", dataset: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const failure = (error: unknown) => error instanceof Error ? error.message : String(error);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Every market's latest day-ahead price and the EUA auction price; one
|
|
84
|
+
* market's figures and its last 30 delivery days when a market is named; the
|
|
85
|
+
* EUA and its latest auctions for EUA (or carbon).
|
|
86
|
+
*/
|
|
87
|
+
export async function loadPowerPricesReport(argument: string | undefined, client: PricesClient = apiClient): Promise<HeadlessBundleResult> {
|
|
88
|
+
if (isCarbonQuery(argument)) {
|
|
89
|
+
const carbon = await fetchCarbonPrice(client);
|
|
90
|
+
return { sections: carbonSections(carbon), notes: [...carbon.gaps], freshness: freshness(null, carbon),
|
|
91
|
+
metadata: { market: carbon.market, unit: carbon.unit, source: carbon.source, publishedAt: carbon.publishedAt, series: "CAP:carbon:eua" } };
|
|
92
|
+
}
|
|
93
|
+
const board = await fetchPowerPrices(client);
|
|
94
|
+
const notes = [...board.gaps];
|
|
95
|
+
if (argument?.trim()) {
|
|
96
|
+
const market = powerPriceMarket(argument);
|
|
97
|
+
const row = market ? board.rows.find((entry) => entry.code === market.code) : null;
|
|
98
|
+
if (!market || !row) throw new Error(`No day-ahead price for "${argument.trim()}". Use a market such as DE, FR, GB or Spain, or EUA.`);
|
|
99
|
+
const history = await fetchPowerPriceHistory(market.code, null, client);
|
|
100
|
+
return {
|
|
101
|
+
sections: [
|
|
102
|
+
{ title: `${market.name} day-ahead power, ${POWER_PRICE_UNIT}`, columns: COLUMNS, rows: [reportRow(row)] },
|
|
103
|
+
{ title: `${market.name}, last 30 delivery days`,
|
|
104
|
+
columns: [{ key: "date", header: "Date", shrink: false }, { key: "price", header: POWER_PRICE_UNIT, align: "right", format: price }],
|
|
105
|
+
rows: history.points.slice(-30).reverse().map((point) => ({ date: point.date, price: point.value })) },
|
|
106
|
+
],
|
|
107
|
+
notes, freshness: freshness(board, null, row),
|
|
108
|
+
metadata: { market: board.market, unit: board.unit, source: board.source, publishedAt: board.publishedAt, row, series: `CAP:day-ahead:${market.code.toLowerCase()}` },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// The carbon allowance rides along; when it cannot load, the power board still reports and says so.
|
|
112
|
+
const carbon = await fetchCarbonPrice(client).catch((error: unknown) => failure(error));
|
|
113
|
+
return {
|
|
114
|
+
sections: [{ title: `Day-ahead power, ${POWER_PRICE_UNIT}`, columns: COLUMNS, rows: board.rows.map(reportRow) },
|
|
115
|
+
...(typeof carbon === "string" ? [] : carbonSections(carbon))],
|
|
116
|
+
notes: [...notes, ...(typeof carbon === "string" ? [carbon] : carbon.gaps)],
|
|
117
|
+
freshness: freshness(board, typeof carbon === "string" ? null : carbon),
|
|
118
|
+
metadata: { market: board.market, unit: board.unit, source: board.source, publishedAt: board.publishedAt,
|
|
119
|
+
...(typeof carbon === "string" ? {} : { carbon: { market: carbon.market, unit: carbon.unit, source: carbon.source, publishedAt: carbon.publishedAt } }) },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const powerPricesHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
124
|
+
shape: "bundle",
|
|
125
|
+
argument: { kind: "free-text", optional: true, placeholder: "market", description: "A market such as DE, FR, GB or Spain, or EUA for the carbon auctions; omit for every market and the EUA." },
|
|
126
|
+
options: [],
|
|
127
|
+
freshness: { source: "Ember", status: "not-a-feed", basis: "day-ahead auction", dataset: true },
|
|
128
|
+
discovery: { aliases: ["EPWR"], dataRequirements: ["Gloom Cloud European power and carbon prices"],
|
|
129
|
+
limitations: ["Daily averages of the day-ahead auction, weighted by load, per country; not intraday or forward prices",
|
|
130
|
+
"Each market is dated by its own latest delivery day: continental markets usually trail by a few days",
|
|
131
|
+
"The EUA price is the primary auction clearing price on business days, volume-weighted across a day's auctions; not a futures settlement"] },
|
|
132
|
+
describe: "European day-ahead power prices by country (EUR/MWh) and the EU carbon allowance auction price (EUR/tCO2)",
|
|
133
|
+
async load(args, ctx) {
|
|
134
|
+
const argument = Array.isArray(args.argument) ? args.argument.join(" ") : args.argument ?? undefined;
|
|
135
|
+
return loadPowerPricesReport(argument, ctx.apiClient);
|
|
136
|
+
},
|
|
137
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { PowerPriceRow } from "../../../api-client/europe-energy";
|
|
2
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
3
|
+
import { fetchCarbonHistory, fetchPowerPriceHistory } from "./prices-client";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The markets the server serves day-ahead prices for, by ISO 3166 alpha-2
|
|
7
|
+
* code, known before the board loads so the data catalog can list them. Great
|
|
8
|
+
* Britain is its own market; Northern Ireland trades with Ireland.
|
|
9
|
+
*/
|
|
10
|
+
export const POWER_PRICE_MARKETS = [
|
|
11
|
+
{ code: "AL", name: "Albania" }, { code: "AT", name: "Austria" }, { code: "BE", name: "Belgium" },
|
|
12
|
+
{ code: "BG", name: "Bulgaria" }, { code: "HR", name: "Croatia" }, { code: "CZ", name: "Czechia" },
|
|
13
|
+
{ code: "DK", name: "Denmark" }, { code: "EE", name: "Estonia" }, { code: "FI", name: "Finland" },
|
|
14
|
+
{ code: "FR", name: "France" }, { code: "DE", name: "Germany" }, { code: "GB", name: "Great Britain" },
|
|
15
|
+
{ code: "GR", name: "Greece" }, { code: "HU", name: "Hungary" }, { code: "IE", name: "Ireland" },
|
|
16
|
+
{ code: "IT", name: "Italy" }, { code: "LV", name: "Latvia" }, { code: "LT", name: "Lithuania" },
|
|
17
|
+
{ code: "LU", name: "Luxembourg" }, { code: "ME", name: "Montenegro" }, { code: "NL", name: "Netherlands" },
|
|
18
|
+
{ code: "MK", name: "North Macedonia" }, { code: "NO", name: "Norway" }, { code: "PL", name: "Poland" },
|
|
19
|
+
{ code: "PT", name: "Portugal" }, { code: "RO", name: "Romania" }, { code: "RS", name: "Serbia" },
|
|
20
|
+
{ code: "SK", name: "Slovakia" }, { code: "SI", name: "Slovenia" }, { code: "ES", name: "Spain" },
|
|
21
|
+
{ code: "SE", name: "Sweden" }, { code: "CH", name: "Switzerland" },
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
export type PowerPriceMarket = (typeof POWER_PRICE_MARKETS)[number];
|
|
25
|
+
|
|
26
|
+
/** Words a market goes by besides its name and code. */
|
|
27
|
+
const ALIASES: Readonly<Record<string, string>> = {
|
|
28
|
+
UK: "GB", "UNITED KINGDOM": "GB", BRITAIN: "GB", ENGLAND: "GB", GBR: "GB",
|
|
29
|
+
DEU: "DE", FRA: "FR", NLD: "NL", BEL: "BE", ESP: "ES", ITA: "IT", AUT: "AT", CHE: "CH", POL: "PL", IRL: "IE",
|
|
30
|
+
"CZECH REPUBLIC": "CZ", HOLLAND: "NL",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** A typed market: its code (DE), alpha-3 code (DEU), name (germany) or a common alias (UK). */
|
|
34
|
+
export function powerPriceMarket(input: string | null | undefined): PowerPriceMarket | null {
|
|
35
|
+
const key = input?.trim().toUpperCase().replace(/\s+/g, " ") ?? "";
|
|
36
|
+
if (!key) return null;
|
|
37
|
+
const code = ALIASES[key] ?? key;
|
|
38
|
+
return POWER_PRICE_MARKETS.find((market) => market.code === code || market.name.toUpperCase() === key) ?? null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const CARBON_PRICE_UNIT = "EUR/tCO2";
|
|
42
|
+
/** The Prices tab's selection when the band charts the carbon allowance instead of a market. */
|
|
43
|
+
export const CARBON_SELECTION = "EUA";
|
|
44
|
+
/** What `EPWR EUA` (or carbon, EU ETS, CO2) asks for: the carbon allowance instead of a market. */
|
|
45
|
+
const CARBON_WORDS = new Set(["EUA", "EUAS", "CARBON", "EU CARBON", "EU ETS", "ETS", "CO2", "EU ALLOWANCE", "EU ALLOWANCES"]);
|
|
46
|
+
export const isCarbonQuery = (input: string | null | undefined) =>
|
|
47
|
+
CARBON_WORDS.has(input?.trim().toUpperCase().replace(/[-\s]+/g, " ") ?? "");
|
|
48
|
+
|
|
49
|
+
/** Germany is the benchmark market a trader reads first. */
|
|
50
|
+
export const DEFAULT_PRICE_MARKET = "DE";
|
|
51
|
+
|
|
52
|
+
export const POWER_PRICE_UNIT = "EUR/MWh";
|
|
53
|
+
export const formatPowerPrice = (value: number | null | undefined) => value == null ? "--" : value.toFixed(2);
|
|
54
|
+
export const formatPowerChange = (value: number | null | undefined) =>
|
|
55
|
+
value == null ? "--" : `${value > 0 ? "+" : ""}${value.toFixed(2)}`;
|
|
56
|
+
/** Where the latest price sits in its 52-week range, 0 at the low and 100 at the high. */
|
|
57
|
+
export function powerRangePosition(row: PowerPriceRow): number | null {
|
|
58
|
+
if (row.price == null || row.low52w == null || row.high52w == null || row.high52w <= row.low52w) return null;
|
|
59
|
+
return Math.round(((row.price - row.low52w) / (row.high52w - row.low52w)) * 100);
|
|
60
|
+
}
|
|
61
|
+
const DAY_AHEAD_PAGE_URL = "https://ember-energy.org/data/european-wholesale-electricity-price-data/";
|
|
62
|
+
|
|
63
|
+
/** The benchmark markets a search lists first; the rest follow by name. */
|
|
64
|
+
const LEAD_MARKETS = ["DE", "FR", "GB", "NL", "BE", "IT", "ES"];
|
|
65
|
+
const leadRank = (code: string) => (LEAD_MARKETS.indexOf(code) + LEAD_MARKETS.length + 1) % (LEAD_MARKETS.length + 1);
|
|
66
|
+
|
|
67
|
+
/** Each market's daily day-ahead price, as `CAP:day-ahead:de`. */
|
|
68
|
+
export const DAY_AHEAD_SERIES: readonly SeriesDefinition[] = [...POWER_PRICE_MARKETS].sort((left, right) =>
|
|
69
|
+
leadRank(left.code) - leadRank(right.code)).map((market): SeriesDefinition => ({
|
|
70
|
+
id: `day-ahead:${market.code.toLowerCase()}`,
|
|
71
|
+
name: `${market.name} day-ahead power price`,
|
|
72
|
+
unit: POWER_PRICE_UNIT,
|
|
73
|
+
frequency: "daily",
|
|
74
|
+
group: "Energy",
|
|
75
|
+
tags: ["electricity", "power price", "day-ahead", "wholesale", "Europe", market.code, ...(market.code === "GB" ? ["UK"] : [])],
|
|
76
|
+
description: `Daily average of the ${market.name} day-ahead auction price, weighted by load, in euros per MWh.`,
|
|
77
|
+
publisher: "Ember",
|
|
78
|
+
url: DAY_AHEAD_PAGE_URL,
|
|
79
|
+
load: async ({ start }) => {
|
|
80
|
+
const history = await fetchPowerPriceHistory(market.code, start?.toISOString().slice(0, 10));
|
|
81
|
+
return history.points;
|
|
82
|
+
},
|
|
83
|
+
}));
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The EU carbon allowance price, as `CAP:carbon:eua`: each business day's
|
|
87
|
+
* primary auction clearing price, volume-weighted across that day's auctions.
|
|
88
|
+
*/
|
|
89
|
+
export const CARBON_SERIES: readonly SeriesDefinition[] = [{
|
|
90
|
+
id: "carbon:eua",
|
|
91
|
+
name: "EU carbon allowance (EUA) auction price",
|
|
92
|
+
unit: CARBON_PRICE_UNIT,
|
|
93
|
+
frequency: "daily",
|
|
94
|
+
group: "Energy",
|
|
95
|
+
tags: ["carbon", "EU carbon", "EUA", "EU ETS", "carbon price", "carbon allowance", "emission allowances", "emissions", "CO2", "Europe"],
|
|
96
|
+
description: "Clearing price of each business day's EU ETS primary auctions of general allowances, volume-weighted, in euros per tonne of CO2. An auction price, not a futures settlement.",
|
|
97
|
+
publisher: "EEX",
|
|
98
|
+
url: "https://www.eex.com/en/markets/environmental-markets/emissions-auctions",
|
|
99
|
+
load: async ({ start }) => {
|
|
100
|
+
const history = await fetchCarbonHistory(start?.toISOString().slice(0, 10));
|
|
101
|
+
return history.points;
|
|
102
|
+
},
|
|
103
|
+
}];
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
import type { CarbonBoard, PowerPriceRow } from "../../../api-client/europe-energy";
|
|
3
|
+
import {
|
|
4
|
+
ChartTableHeader, CompositeChart, MarketBoardStack, PaneStatusBody, spanAxisFormatter, usePaneNoticeFooter, usePaneStatusFooter,
|
|
5
|
+
usePaneTabs, type MarketBoardRow, type PaneHint, type StatItem,
|
|
6
|
+
} from "../../../components";
|
|
7
|
+
import { staticSeries } from "../../../components/chart/static/series";
|
|
8
|
+
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
9
|
+
import { StatChartDetail } from "../../../components/market-board";
|
|
10
|
+
import { useAsyncResource, useAutoRefresh, usePaneSettingValue, usePluginAppActions, usePluginPaneState } from "../../../public/react";
|
|
11
|
+
import { usePaneInstance } from "../../../state/app/context";
|
|
12
|
+
import { useThemeColors } from "../../../theme/theme-context";
|
|
13
|
+
import type { PaneProps } from "../../../types/plugin";
|
|
14
|
+
import { Box, useRendererHost } from "../../../ui";
|
|
15
|
+
import { POWER_TABS } from "./model";
|
|
16
|
+
import { usePowerPricesEvidence, type PowerPricesSnapshot } from "./evidence";
|
|
17
|
+
import { getCachedCarbonPrice, getCachedPowerPrices, loadCarbonHistory, loadCarbonPrice, loadPowerPriceHistory, loadPowerPrices, POWER_PRICES_NOT_AVAILABLE, validateCarbonPrice, validatePowerPrices } from "./prices-client";
|
|
18
|
+
import { CARBON_PRICE_UNIT, CARBON_SELECTION, DEFAULT_PRICE_MARKET, formatPowerChange, formatPowerPrice, POWER_PRICE_UNIT, powerPriceMarket, powerRangePosition } from "./prices-model";
|
|
19
|
+
|
|
20
|
+
const PANELS = [{ id: "main" }];
|
|
21
|
+
const DAY_MS = 86_400_000;
|
|
22
|
+
/** The board's chart: the selected market's year, as the 1Y figures read. */
|
|
23
|
+
const CHART_DAYS = 366;
|
|
24
|
+
const formatAxis = spanAxisFormatter((value, digits) => value.toFixed(digits));
|
|
25
|
+
|
|
26
|
+
interface PriceBoardRow extends MarketBoardRow { price: PowerPriceRow }
|
|
27
|
+
|
|
28
|
+
function boardRow(row: PowerPriceRow): PriceBoardRow {
|
|
29
|
+
const position = powerRangePosition(row);
|
|
30
|
+
return {
|
|
31
|
+
id: row.code, label: row.name, value: row.price, valueText: formatPowerPrice(row.price),
|
|
32
|
+
change: row.change, changeText: formatPowerChange(row.change),
|
|
33
|
+
percentile: position, percentileText: position == null ? "--" : `${position}%`,
|
|
34
|
+
asOf: row.date, status: row.price == null ? "unavailable" : "available",
|
|
35
|
+
history: row.trail.map((point) => ({ date: new Date(`${point.date}T00:00:00Z`), close: point.value })),
|
|
36
|
+
price: row,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const average = (key: "average7" | "average30" | "yearAgo", header: string) => ({
|
|
41
|
+
column: { id: key, label: header, width: 9, align: "right" as const },
|
|
42
|
+
sortValue: (row: PriceBoardRow) => row.price[key],
|
|
43
|
+
renderCell: (row: PriceBoardRow) => ({ text: formatPowerPrice(row.price[key]), ...(row.price[key] != null ? { value: row.price[key]! } : {}) }),
|
|
44
|
+
});
|
|
45
|
+
const EXTRA_COLUMNS = [average("average7", "7D AVG"), average("average30", "30D AVG"), average("yearAgo", "1Y AGO")];
|
|
46
|
+
|
|
47
|
+
function historySeries(row: Pick<PowerPriceRow, "code" | "name" | "date">, points: ReadonlyArray<{ date: string; value: number }>, color: string, days?: number,
|
|
48
|
+
label = `${row.name} day-ahead`) {
|
|
49
|
+
const from = days && row.date ? new Date(Date.parse(`${row.date}T00:00:00Z`) - days * DAY_MS).toISOString().slice(0, 10) : "";
|
|
50
|
+
return [staticSeries(points.filter((point) => point.date >= from).map((point) => {
|
|
51
|
+
const date = new Date(`${point.date}T00:00:00Z`);
|
|
52
|
+
return { date, observedAt: date, value: point.value };
|
|
53
|
+
}), { id: `day-ahead:${row.code}`, label, color, calendarSpaced: true })];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const compactTonnes = (value: number) => value >= 1e6 ? `${(value / 1e6).toFixed(2)}M t` : `${Math.round(value / 1e3)}k t`;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The EU carbon allowance above the board: its latest auction day's price,
|
|
60
|
+
* how it moved, and how the latest general-allowance auction was covered.
|
|
61
|
+
*/
|
|
62
|
+
function carbonFigures(board: CarbonBoard): StatItem[] {
|
|
63
|
+
const row = board.row;
|
|
64
|
+
if (row.price == null) return [];
|
|
65
|
+
const latest = board.auctions.find((auction) => !auction.aviation && auction.price != null);
|
|
66
|
+
return [
|
|
67
|
+
{ id: "eua", label: `EUA ${CARBON_PRICE_UNIT}`, value: formatPowerPrice(row.price), detail: row.date ?? undefined },
|
|
68
|
+
{ id: "eua-change", label: "EUA 1D", value: formatPowerChange(row.change), ...(row.previousDate ? { detail: `vs ${row.previousDate}` } : {}) },
|
|
69
|
+
{ id: "eua-30d", label: "EUA 30D avg", value: formatPowerPrice(row.average30) },
|
|
70
|
+
{ id: "eua-1y", label: "EUA 1Y ago", value: formatPowerPrice(row.yearAgo), ...(row.yearAgoDate ? { detail: row.yearAgoDate } : {}) },
|
|
71
|
+
...(latest?.coverRatio != null ? [{ id: "eua-cover", label: "EUA cover", value: `${latest.coverRatio.toFixed(2)}x`,
|
|
72
|
+
detail: [latest.zone, compactTonnes(latest.volume)].filter(Boolean).join(" ") }] : []),
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function PriceDetail({ row, width, height, focused }: { row: PowerPriceRow; width: number; height: number; focused: boolean }) {
|
|
77
|
+
const colors = useThemeColors();
|
|
78
|
+
const loader = useCallback((force: boolean) => loadPowerPriceHistory(row.code, force), [row.code]);
|
|
79
|
+
const history = useAsyncResource(loader, { keepPreviousData: true });
|
|
80
|
+
const series = useMemo(() => historySeries(row, history.data?.payload.points ?? [], colors.warning), [row, history.data, colors.warning]);
|
|
81
|
+
const items: StatItem[] = [
|
|
82
|
+
{ id: "price", label: POWER_PRICE_UNIT, value: formatPowerPrice(row.price), detail: row.date ?? undefined },
|
|
83
|
+
{ id: "change", label: "1D", value: formatPowerChange(row.change), detail: row.previousDate ? `vs ${row.previousDate}` : undefined },
|
|
84
|
+
{ id: "average7", label: "7D avg", value: formatPowerPrice(row.average7) },
|
|
85
|
+
{ id: "average30", label: "30D avg", value: formatPowerPrice(row.average30) },
|
|
86
|
+
{ id: "yearAgo", label: "1Y ago", value: formatPowerPrice(row.yearAgo), detail: row.yearAgoDate ?? undefined },
|
|
87
|
+
{ id: "range", label: "52W range", value: `${formatPowerPrice(row.low52w)} to ${formatPowerPrice(row.high52w)}` },
|
|
88
|
+
];
|
|
89
|
+
return <StatChartDetail items={items} width={width} height={height} empty={!history.loading && series[0]!.points.length < 2}
|
|
90
|
+
emptySubject="price history" emptyTitle={history.error ?? "No price history available."}
|
|
91
|
+
renderChart={(chartHeight) => <CompositeChart series={series} panels={PANELS} width={width} height={chartHeight} focused={focused}
|
|
92
|
+
showLegend navigable={false} showTimeAxis formatValue={(value) => `${formatPowerPrice(value)} ${POWER_PRICE_UNIT}`}
|
|
93
|
+
formatAxisValue={formatAxis} remoteKind="day-ahead-history" />} />;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* POWER's Prices tab: every European market's latest day-ahead price, each
|
|
98
|
+
* dated by its own delivery day, with the selected market's year above the
|
|
99
|
+
* board and its whole history in the detail. The EU carbon allowance's
|
|
100
|
+
* auction price sits in the figures above, in its own unit.
|
|
101
|
+
*/
|
|
102
|
+
export function PowerPricesView({ width, height, focused }: PaneProps) {
|
|
103
|
+
const colors = useThemeColors();
|
|
104
|
+
const host = useRendererHost();
|
|
105
|
+
const { createPaneFromTemplate } = usePluginAppActions();
|
|
106
|
+
const [openingTab] = usePaneSettingValue("tab", "queue");
|
|
107
|
+
const [, setTab] = usePluginPaneState<string>("power:tab", openingTab);
|
|
108
|
+
// `EPWR DE` opens with the market in the instance params, `EPWR EUA` with the carbon allowance; a saved selection wins.
|
|
109
|
+
const params = usePaneInstance()?.params;
|
|
110
|
+
const [selectedId, setSelectedId] = usePluginPaneState<string | null>("power:prices:selected", powerPriceMarket(params?.market)?.code ?? null);
|
|
111
|
+
const [carbonMode, setCarbonMode] = usePluginPaneState("power:prices:carbon", params?.market === CARBON_SELECTION);
|
|
112
|
+
const [openId, setOpenId] = usePluginPaneState<string | null>("power:prices:open", null);
|
|
113
|
+
// `shot` freezes the boards and the charted history, so the capture and its check read the same days.
|
|
114
|
+
const [snapshotSetting] = usePaneSettingValue<PowerPricesSnapshot | null>("powerPricesSnapshot", null);
|
|
115
|
+
const snapshot = useMemo(() => {
|
|
116
|
+
try {
|
|
117
|
+
return snapshotSetting ? { ...snapshotSetting, board: validatePowerPrices(snapshotSetting.board),
|
|
118
|
+
carbon: snapshotSetting.carbon ? validateCarbonPrice(snapshotSetting.carbon) : null } : null;
|
|
119
|
+
} catch { return null; }
|
|
120
|
+
}, [snapshotSetting]);
|
|
121
|
+
const resource = useAsyncResource(snapshot ? null : loadPowerPrices, { initialData: getCachedPowerPrices });
|
|
122
|
+
const board = snapshot?.board ?? resource.data?.payload ?? null;
|
|
123
|
+
// The carbon allowance loads beside the board; its failure is a notice, never the board's.
|
|
124
|
+
const carbonResource = useAsyncResource(snapshot ? null : loadCarbonPrice, { initialData: getCachedCarbonPrice });
|
|
125
|
+
const carbon = snapshot ? snapshot.carbon : carbonResource.data?.payload ?? null;
|
|
126
|
+
const figures = useMemo(() => carbon ? carbonFigures(carbon) : [], [carbon]);
|
|
127
|
+
const rows = useMemo(() => board?.rows.map(boardRow) ?? [], [board]);
|
|
128
|
+
// The band charts the selected market, or the carbon allowance from `c` or EPWR EUA until a market is chosen.
|
|
129
|
+
const carbonCharted = carbonMode && !!carbon?.row.date;
|
|
130
|
+
const selected = rows.find((row) => row.id === selectedId) ?? rows.find((row) => row.id === DEFAULT_PRICE_MARKET) ?? rows[0];
|
|
131
|
+
const selectMarket = useCallback((id: string) => { setSelectedId(id); setCarbonMode(false); }, [setSelectedId, setCarbonMode]);
|
|
132
|
+
const code = carbonCharted ? CARBON_SELECTION : selected?.price.date ? selected.id : null;
|
|
133
|
+
const historyLoader = useCallback((force: boolean) => code === CARBON_SELECTION ? loadCarbonHistory(force) : loadPowerPriceHistory(code!, force), [code]);
|
|
134
|
+
const loaded = useAsyncResource<{ payload: { code: string; points: ReadonlyArray<{ date: string; value: number }> } }>(
|
|
135
|
+
code && !snapshot ? historyLoader : null, { keepPreviousData: true });
|
|
136
|
+
const history = snapshot ? { ...loaded, data: snapshot.history ? { payload: snapshot.history } : null, loading: false, error: null } : loaded;
|
|
137
|
+
usePowerPricesEvidence(board, carbon, useMemo(() => rows.map((row) => row.id), [rows]), resource.loading || history.loading || carbonResource.loading);
|
|
138
|
+
useAutoRefresh(resource.updatedAt, resource.load);
|
|
139
|
+
useAutoRefresh(carbonResource.updatedAt, carbonResource.load);
|
|
140
|
+
usePaneRefreshKey(() => { void resource.reload(); void history.reload(); void carbonResource.reload(); }, { focused });
|
|
141
|
+
const { strip, rows: tabRows } = usePaneTabs({ tabs: [...POWER_TABS], activeValue: "prices", onSelect: (tab: string) => setTab(tab), focused, dense: true });
|
|
142
|
+
const notAvailable = !board && resource.error === POWER_PRICES_NOT_AVAILABLE;
|
|
143
|
+
const open = rows.find((row) => row.id === openId);
|
|
144
|
+
const charted = carbonCharted ? carbon!.row : selected?.price;
|
|
145
|
+
const unit = carbonCharted ? CARBON_PRICE_UNIT : POWER_PRICE_UNIT;
|
|
146
|
+
const series = useMemo(() => charted && history.data?.payload.code === charted.code
|
|
147
|
+
? historySeries(charted, history.data.payload.points, carbonCharted ? colors.positive : colors.warning, CHART_DAYS, carbonCharted ? "EU carbon (EUA) auction" : undefined)
|
|
148
|
+
: [], [charted, carbonCharted, history.data, colors.warning, colors.positive]);
|
|
149
|
+
const sourceUrl = board?.source.url;
|
|
150
|
+
const chartExpression = carbonCharted ? "CAP:carbon:eua" : selected?.price.date ? `CAP:day-ahead:${selected.id.toLowerCase()}` : null;
|
|
151
|
+
const hints: PaneHint[] = [
|
|
152
|
+
...(sourceUrl ? [{ id: "source", key: "o", label: `pen ${carbonCharted ? carbon!.source.name : board!.source.name}`, title: "Open the publisher's page",
|
|
153
|
+
onPress: () => void host.openExternal(carbonCharted ? carbon!.source.url : sourceUrl) }] : []),
|
|
154
|
+
...(chartExpression ? [{ id: "chart", key: "g", label: "raph", title: "Chart in a custom chart",
|
|
155
|
+
onPress: () => createPaneFromTemplate("chart-composer-pane", { arg: chartExpression }) }] : []),
|
|
156
|
+
...(figures.length && !carbonCharted ? [{ id: "carbon", key: "c", label: "arbon", title: "Chart the EU carbon auction price above the board",
|
|
157
|
+
onPress: () => setCarbonMode(true) }] : []),
|
|
158
|
+
];
|
|
159
|
+
usePaneStatusFooter({ registrationId: "power-prices", loading: resource.loading || history.loading,
|
|
160
|
+
error: board ? resource.error ?? (open ? null : history.error) : null, stale: !!resource.data?.stale, hints });
|
|
161
|
+
usePaneNoticeFooter({ registrationId: "power-prices:notices", focused,
|
|
162
|
+
notices: [...(board?.gaps ?? []), ...(resource.data?.refreshError ? [resource.data.refreshError] : []),
|
|
163
|
+
...(carbon?.gaps ?? []), ...(board && !carbon && carbonResource.error ? [carbonResource.error] : [])] });
|
|
164
|
+
const bodyHeight = Math.max(3, height - tabRows);
|
|
165
|
+
return <Box width={width} height={height} flexDirection="column">
|
|
166
|
+
{strip}
|
|
167
|
+
<PaneStatusBody loading={resource.loading && !board} error={!board && !notAvailable ? resource.error : null}
|
|
168
|
+
empty={notAvailable} emptyTitle={POWER_PRICES_NOT_AVAILABLE} subject="power prices" width={width} height={bodyHeight}>
|
|
169
|
+
{board ? <MarketBoardStack rows={rows} width={width} height={bodyHeight} focused={focused}
|
|
170
|
+
rootBefore={({ columns }) => <ChartTableHeader width={width} height={bodyHeight} tableRows={rows.length} tableColumns={columns}
|
|
171
|
+
figures={figures} chart={charted ? { series, loading: history.loading && !series.length, empty: `No price history for ${charted.name}`,
|
|
172
|
+
formatValue: (value) => `${formatPowerPrice(value)} ${unit}`, formatAxisValue: formatAxis, remoteKind: "day-ahead-history" } : null} />}
|
|
173
|
+
selectedId={selected?.id ?? null} onSelectedIdChange={selectMarket} openId={open?.id ?? null} onOpenIdChange={setOpenId}
|
|
174
|
+
labelHeader="MARKET" labelWidth={16} valueLabel={POWER_PRICE_UNIT} valueWidth={10} percentileLabel="IN 1Y" extraColumns={EXTRA_COLUMNS}
|
|
175
|
+
emptyTitle={POWER_PRICES_NOT_AVAILABLE}
|
|
176
|
+
renderDetail={(row) => <PriceDetail row={row.price} width={width} height={Math.max(5, bodyHeight - 2)} focused={focused} />} /> : null}
|
|
177
|
+
</PaneStatusBody>
|
|
178
|
+
</Box>;
|
|
179
|
+
}
|
|
@@ -10,6 +10,14 @@ const bps = (value: unknown) => {
|
|
|
10
10
|
const bp = finiteOrNull(value);
|
|
11
11
|
return bp == null ? "--" : `${bp > 0 ? "+" : ""}${bp.toFixed(1)}bp`;
|
|
12
12
|
};
|
|
13
|
+
/** What a text report calls each current policy rate; JSON keeps the keys. */
|
|
14
|
+
const POLICY_LABELS: Record<string, string> = {
|
|
15
|
+
effr: "Effective fed funds rate",
|
|
16
|
+
targetLower: "Target range lower",
|
|
17
|
+
targetUpper: "Target range upper",
|
|
18
|
+
};
|
|
19
|
+
const policyLabel = (value: unknown) => POLICY_LABELS[String(value)] ?? String(value);
|
|
20
|
+
const yesNo = (value: unknown) => value === true ? "yes" : value === false ? "no" : "--";
|
|
13
21
|
const timestamp = (value: unknown) => typeof value === "string" ? value.replace("T", " ").slice(0, 16) : "--";
|
|
14
22
|
const probabilities = (value: unknown) => {
|
|
15
23
|
const outcomes = Array.isArray(value) ? value as RateMeeting["probabilities"] : [];
|
|
@@ -17,43 +25,63 @@ const probabilities = (value: unknown) => {
|
|
|
17
25
|
: outcomes.map((outcome) => `${outcome.targetMidpoint.toFixed(3)}% ${(outcome.probability * 100).toFixed(0)}%`).join(" / ");
|
|
18
26
|
};
|
|
19
27
|
|
|
28
|
+
// A narrow terminal leaves out the sample count, status, percentile and quote time (the closing line has it),
|
|
29
|
+
// then moves the staleness and month under each row.
|
|
20
30
|
const contractColumns: HeadlessPaneColumn[] = [
|
|
21
|
-
{ key: "symbol", header: "Symbol" }, { key: "month", header: "Month" },
|
|
31
|
+
{ key: "symbol", header: "Symbol", shrink: false }, { key: "month", header: "Month", shrink: false, stackPriority: 1 },
|
|
22
32
|
{ key: "price", header: "Price", align: "right", format: (value) => finiteOrNull(value)?.toFixed(3) ?? "--" },
|
|
23
33
|
{ key: "impliedRate", header: "Implied rate", align: "right", format: rate },
|
|
24
|
-
{ key: "percentile", header: "Pctl 1Y", align: "right", format: pctl },
|
|
25
|
-
{ key: "samples", header: "Samples", align: "right" },
|
|
26
|
-
{ key: "asOf", header: "As of UTC", format: timestamp },
|
|
27
|
-
{ key: "status", header: "Status" }, { key: "stale", header: "
|
|
34
|
+
{ key: "percentile", header: "Pctl 1Y", align: "right", stackPriority: 4, stackRows: 0, format: pctl },
|
|
35
|
+
{ key: "samples", header: "Samples", align: "right", stackPriority: 6, stackRows: 0 },
|
|
36
|
+
{ key: "asOf", header: "As of UTC", shrink: false, stackPriority: 3, stackRows: 0, format: timestamp },
|
|
37
|
+
{ key: "status", header: "Status", stackPriority: 5, stackRows: 0 }, { key: "stale", header: "Data stale", stackPriority: 2, format: yesNo },
|
|
28
38
|
];
|
|
29
39
|
|
|
40
|
+
/**
|
|
41
|
+
* How far the fed funds and SOFR futures quotes are held back. The rate-path
|
|
42
|
+
* endpoint does not carry a delay. CME Group's delayed market data is at least
|
|
43
|
+
* 10 minutes behind its real-time feed (its information license agreement
|
|
44
|
+
* defines delayed data as published more than 10 minutes after it is
|
|
45
|
+
* disseminated), and the futures-curve endpoint reports `delayMinutes: 10` on
|
|
46
|
+
* every CME contract.
|
|
47
|
+
*/
|
|
48
|
+
const CME_FUTURES_DELAY_MINUTES = 10;
|
|
49
|
+
|
|
30
50
|
export const ratePathHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
31
51
|
discovery: { aliases: ["WIRP", "FFIP"], dataRequirements: ["Gloom Cloud rate-path endpoint"],
|
|
32
|
-
limitations: ["Conditional two-outcome probabilities", "SR3 history from hourly trades", "Maintained FOMC schedule and SEP snapshot"] },
|
|
52
|
+
limitations: ["Conditional two-outcome probabilities.", "SR3 history from hourly trades.", "Maintained FOMC schedule and SEP snapshot."] },
|
|
33
53
|
shape: "bundle", argument: { kind: "none" }, options: [], describe: "US rate path",
|
|
34
|
-
// Delayed futures quotes
|
|
35
|
-
freshness: { status: "delayed" },
|
|
54
|
+
// Delayed CME futures quotes.
|
|
55
|
+
freshness: { source: "CME futures", status: "delayed", delayMinutes: CME_FUTURES_DELAY_MINUTES },
|
|
36
56
|
async load(_args, ctx) {
|
|
37
57
|
const data = await fetchRatePath(ctx.apiClient);
|
|
38
58
|
const moves = meetingMoves(data.meetings);
|
|
59
|
+
// The line cites CME futures, so the contracts alone date it and count its stale rows. The policy rates
|
|
60
|
+
// (FRED) keep their own date and stale flag in their table, and the meetings are read from the contracts.
|
|
61
|
+
const contracts = [...data.fedFunds, ...data.sofr].filter((contract) => contract.status !== "unavailable")
|
|
62
|
+
.map(({ asOf, stale }) => ({ asOf, stale }));
|
|
39
63
|
return {
|
|
64
|
+
freshness: { observedKey: "asOf", observations: contracts },
|
|
40
65
|
sections: [
|
|
41
66
|
{ title: "Current policy", columns: [
|
|
42
|
-
{ key: "name", header: "Name" }, { key: "value", header: "Value", align: "right", format: rate },
|
|
43
|
-
{ key: "asOf", header: "As of" }, { key: "percentile", header: "Pctl 1Y", align: "right", format: pctl },
|
|
44
|
-
{ key: "samples", header: "Samples", align: "right"
|
|
67
|
+
{ key: "name", header: "Name", minWidth: 18, format: policyLabel }, { key: "value", header: "Value", align: "right", format: rate },
|
|
68
|
+
{ key: "asOf", header: "As of", shrink: false }, { key: "percentile", header: "Pctl 1Y", align: "right", stackPriority: 1, format: pctl },
|
|
69
|
+
{ key: "samples", header: "Samples", align: "right", stackPriority: 2, stackRows: 0 }, { key: "stale", header: "Data stale", format: yesNo },
|
|
45
70
|
], rows: Object.entries(data.current).map(([name, metric]) => ({ name, ...metric })) },
|
|
71
|
+
// A narrow terminal keeps the moves and change, prints the probabilities of the next two meetings
|
|
72
|
+
// under their rows, and leaves out the rest; a reason a meeting has no rate stays under its row.
|
|
46
73
|
{ title: "FOMC meetings", columns: [
|
|
47
|
-
{ key: "date", header: "Date" },
|
|
74
|
+
{ key: "date", header: "Date", shrink: false },
|
|
48
75
|
{ key: "moves", header: "Moves", align: "right", format: (value) => movesText(finiteOrNull(value)) },
|
|
49
76
|
{ key: "moveOdds", header: "P(move)", align: "right", format: (value) => moveOddsText(finiteOrNull(value)) },
|
|
50
|
-
{ key: "impliedRate", header: "Implied rate", align: "right", format: rate },
|
|
51
|
-
{ key: "targetMidpoint", header: "Target midpoint", align: "right", format: (value) => finiteOrNull(value)?.toFixed(3) ?? "--" },
|
|
77
|
+
{ key: "impliedRate", header: "Implied rate", align: "right", stackPriority: 3, stackRows: 0, format: rate },
|
|
78
|
+
{ key: "targetMidpoint", header: "Target midpoint", align: "right", stackPriority: 6, stackRows: 0, format: (value) => finiteOrNull(value)?.toFixed(3) ?? "--" },
|
|
52
79
|
{ key: "changeBps", header: "Change", align: "right", format: bps },
|
|
53
|
-
{ key: "percentile", header: "Pctl 1Y", align: "right", format: pctl },
|
|
54
|
-
{ key: "samples", header: "Samples", align: "right"
|
|
55
|
-
{ key: "
|
|
56
|
-
{ key: "
|
|
80
|
+
{ key: "percentile", header: "Pctl 1Y", align: "right", stackPriority: 7, stackRows: 0, format: pctl },
|
|
81
|
+
{ key: "samples", header: "Samples", align: "right", stackPriority: 8, stackRows: 0 },
|
|
82
|
+
{ key: "asOf", header: "As of UTC", shrink: false, stackPriority: 5, stackRows: 0, format: timestamp },
|
|
83
|
+
{ key: "probabilities", header: "Probabilities", shrink: false, stackPriority: 4, stackRows: 2, format: probabilities },
|
|
84
|
+
{ key: "method", header: "Method", stackPriority: 9, stackRows: 0 }, { key: "reason", header: "Reason", stackPriority: 10 },
|
|
57
85
|
], rows: data.meetings.map((meeting) => ({ ...meeting, moves: movesPriced(meeting), moveOdds: moves.get(meeting.date) ?? null })) },
|
|
58
86
|
{ title: "Fed funds contracts", columns: contractColumns, rows: data.fedFunds.map((contract) => ({ ...contract })) },
|
|
59
87
|
{ title: "SOFR contracts", columns: contractColumns, rows: data.sofr.map((contract) => ({ ...contract })) },
|
|
@@ -5,6 +5,7 @@ import { createRealizedVolatilityDependencies, loadCurrentAtmIv, loadRealizedVol
|
|
|
5
5
|
import { projectRealizedVolatility, type CurrentAtmIvSnapshot } from "./model";
|
|
6
6
|
import { ESTIMATOR_OPTIONS, selectedWindows } from "./settings";
|
|
7
7
|
import { DAILY_CLOSES } from "../shared/report-freshness";
|
|
8
|
+
import { listingAbroadVenue } from "../../../utils/sec";
|
|
8
9
|
|
|
9
10
|
export function realizedVolHeadless(initialView: "graph" | "cone"): HeadlessPaneDefinition<"bundle"> {
|
|
10
11
|
return {
|
|
@@ -26,8 +27,11 @@ export function realizedVolHeadless(initialView: "graph" | "cone"): HeadlessPane
|
|
|
26
27
|
throw new Error("Choose session windows from 10,20,30,60,90,180,260");
|
|
27
28
|
}
|
|
28
29
|
const instrument = await resolveHeadlessInstrument(ctx, args.symbols[0]!);
|
|
30
|
+
// Options are US listings'; SAN:EPA has none, and bare SAN's chain is another company's.
|
|
31
|
+
const abroad = listingAbroadVenue(args.symbols[0]!) != null;
|
|
29
32
|
const currentIv = async (): Promise<CurrentAtmIvSnapshot | null> => {
|
|
30
33
|
if (!args.options.showIv) return null;
|
|
34
|
+
if (abroad) return { reference: null, error: null, warnings: [], noOptionChain: true };
|
|
31
35
|
try {
|
|
32
36
|
const quote = await ctx.marketData.getQuote(instrument.symbol, instrument.exchange);
|
|
33
37
|
if (quote.stale || !(quote.price > 0) || !Number.isFinite(quote.price)) throw new Error("Underlying quote is missing or stale");
|
|
@@ -71,6 +75,7 @@ export function realizedVolHeadless(initialView: "graph" | "cone"): HeadlessPane
|
|
|
71
75
|
&& (!args.options.showIv || iv?.reference != null || iv?.noOptionChain === true),
|
|
72
76
|
unavailableSymbols: model.history.length ? [] : [instrument.symbol], errors,
|
|
73
77
|
metadata: { unit: "decimal annualized volatility", annualization: 252, model, currentIv: iv,
|
|
78
|
+
...(abroad && args.options.showIv ? { notices: [`Options data covers US listings only, so ${args.symbols[0]} has no current IV.`] } : {}),
|
|
74
79
|
source: history.source, stale: history.stale, fetchedAt: history.fetchedAt,
|
|
75
80
|
methodology: "docs/research-data.md#shared-volatility-calculations" },
|
|
76
81
|
};
|
|
@@ -37,9 +37,9 @@ export const rotationHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
37
37
|
aliases: ["RRG", "GRR"],
|
|
38
38
|
dataRequirements: ["Cloud daily history and listing currencies"],
|
|
39
39
|
limitations: [
|
|
40
|
-
"Transparent 13-week strength and 4-week momentum, not proprietary JdK indices",
|
|
41
|
-
"Same-currency price returns; dividends are not reinvested",
|
|
42
|
-
"Completed weeks only",
|
|
40
|
+
"Transparent 13-week strength and 4-week momentum, not proprietary JdK indices.",
|
|
41
|
+
"Same-currency price returns; dividends are not reinvested.",
|
|
42
|
+
"Completed weeks only.",
|
|
43
43
|
],
|
|
44
44
|
},
|
|
45
45
|
async load(args, ctx) {
|
|
@@ -283,8 +283,11 @@ export function buildEventDetail({
|
|
|
283
283
|
if (row.status !== "Earnings") return sections;
|
|
284
284
|
|
|
285
285
|
const comparison: EventDetailBlock[] = [
|
|
286
|
-
detailRow("
|
|
287
|
-
detailRow("
|
|
286
|
+
...(row.dateStatus && row.dateStatus !== "reported" ? [detailRow("Report date", row.date, row.dateStatus)] : []),
|
|
287
|
+
detailRow("Actual", earningsInput(row.epsActual, row.epsCurrency),
|
|
288
|
+
row.epsBasis === "unknown" ? "basis unknown" : row.epsBasis),
|
|
289
|
+
detailRow("Consensus", earningsInput(row.epsEstimate, row.epsCurrency),
|
|
290
|
+
row.epsAnalysts != null ? `${row.epsAnalysts} analysts` : undefined),
|
|
288
291
|
];
|
|
289
292
|
if (row.epsDifference != null) comparison.push(detailRow("Difference", earningsInput(row.epsDifference, row.epsCurrency)));
|
|
290
293
|
if (row.surprisePercent != null) {
|