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,52 @@
|
|
|
1
|
+
import type { AppAttentionPayload } from "../../../api-client/app-attention";
|
|
2
|
+
import type { HiringPayload } from "../../../api-client/hiring";
|
|
3
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
4
|
+
import { fetchAttention } from "./client";
|
|
5
|
+
|
|
6
|
+
const DAY_MS = 86_400_000;
|
|
7
|
+
|
|
8
|
+
/** The app history window a chart asks for, in the days the server takes (7 to 730). */
|
|
9
|
+
function appHistoryDays(start: Date | undefined): number {
|
|
10
|
+
if (!start) return 730;
|
|
11
|
+
return Math.min(730, Math.max(7, Math.ceil((Date.now() - start.getTime()) / DAY_MS)));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The company signals HIRE and APPS chart: observed open roles each week and
|
|
16
|
+
* the app attention score each day. Pro readings: the free preview carries no
|
|
17
|
+
* history, so they fail with the pane's own words.
|
|
18
|
+
*/
|
|
19
|
+
export const COMPANY_ATTENTION_SERIES: readonly SeriesDefinition[] = [
|
|
20
|
+
{
|
|
21
|
+
id: "hiring:open-roles",
|
|
22
|
+
name: "Observed open roles",
|
|
23
|
+
unit: "jobs",
|
|
24
|
+
frequency: "weekly",
|
|
25
|
+
group: "Alternative data",
|
|
26
|
+
tags: ["hiring", "hiring momentum", "roles", "requisitions", "careers"],
|
|
27
|
+
description: "Requisitions observed on public career boards each week, subsidiaries rolled up through evidenced ownership, as HIRE charts them. Needs Pro.",
|
|
28
|
+
input: "ticker",
|
|
29
|
+
load: async ({ ticker, signal }) => {
|
|
30
|
+
const data = await fetchAttention("hiring", ticker!, {}, undefined, signal) as HiringPayload;
|
|
31
|
+
if (data.preview) throw new Error("Full hiring history requires Pro.");
|
|
32
|
+
if (!data.series.length) throw new Error("History is accumulating from the first capture.");
|
|
33
|
+
return data.series.map((point) => ({ date: point.week, value: point.openCount }));
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "app-attention:score",
|
|
38
|
+
name: "App attention score",
|
|
39
|
+
unit: "score",
|
|
40
|
+
frequency: "daily",
|
|
41
|
+
group: "Alternative data",
|
|
42
|
+
tags: ["apps", "app attention", "mobile", "app ranks", "ratings"],
|
|
43
|
+
description: "A 0 to 100 summary of the public chart ranks of the company's apps across countries, as APPS charts it. Needs Pro.",
|
|
44
|
+
input: "ticker",
|
|
45
|
+
load: async ({ ticker, start, signal }) => {
|
|
46
|
+
const data = await fetchAttention("apps", ticker!, { days: appHistoryDays(start) }, undefined, signal) as AppAttentionPayload;
|
|
47
|
+
if (data.access === "preview") throw new Error("Full app history requires Pro.");
|
|
48
|
+
if (!data.history.length) throw new Error("History is accumulating from the first capture.");
|
|
49
|
+
return data.history.map((point) => ({ date: point.date, value: point.attentionScore }));
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
];
|
|
@@ -1,6 +1,80 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DataTableColumn } from "../../../components";
|
|
2
|
+
import type { HeadlessBundleSection, HeadlessPaneColumn, HeadlessPaneDefinition } from "../../../types/plugin";
|
|
3
|
+
import { withoutQuietColumns } from "../shared/research-cells";
|
|
2
4
|
import { resolveHeadlessIssuerListing } from "../shared/headless-market-data";
|
|
3
|
-
import { companyQuery, fetchCompanyData, type CompanyMode } from "./client";
|
|
5
|
+
import { companyQuery, fetchCompanyData, type CompanyDataset, type CompanyMode } from "./client";
|
|
6
|
+
import { allGuidance, allObservations, companyCellText, companyColumns, companyPreviewNote, QUIET_COLUMNS, type CompanyRow } from "./model";
|
|
7
|
+
import type { KpiObservation } from "../../../api-client/company-kpis";
|
|
8
|
+
|
|
9
|
+
/** What the server takes as a metric; anything else is not a metric id and is not sent. */
|
|
10
|
+
const METRIC_ID = /^[a-z0-9_]{1,80}$/;
|
|
11
|
+
/** Filters the free preview ignores: it is fixed at the latest disclosures. */
|
|
12
|
+
const PRO_FILTERS = ["basis", "from", "to", "asOf"] as const;
|
|
13
|
+
/** The row field behind each pane column, where there is one; exports keep that field's value. */
|
|
14
|
+
const ROW_KEYS: Record<string, string> = { scope: "dimensions", issued: "issuedDate" };
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The pane's table columns, printed as the pane prints them: fiscal labels
|
|
18
|
+
* (FY2024), compact values with their unit (12.48B USD), the scope in words,
|
|
19
|
+
* and Basis and Scope only when a row is not the reported, consolidated
|
|
20
|
+
* figure. Each row's disclosure date follows. The rows keep every field the
|
|
21
|
+
* server sent for exports.
|
|
22
|
+
*/
|
|
23
|
+
function reportColumns(mode: CompanyMode, history: boolean, revisions: boolean, rows: CompanyRow[], observations: KpiObservation[]): HeadlessPaneColumn[] {
|
|
24
|
+
const columns: DataTableColumn[] = [...companyColumns(mode === "guidance", false, history),
|
|
25
|
+
...(revisions ? [{ id: "revision", label: "Revision", width: 12, align: "left" as const }] : [])];
|
|
26
|
+
return [...withoutQuietColumns(columns, rows, (row, id) => companyCellText(row, id, observations), QUIET_COLUMNS).map((column): HeadlessPaneColumn => ({
|
|
27
|
+
key: column.id === "value" && mode === "guidance" ? "rangeText" : ROW_KEYS[column.id] ?? column.id, header: column.label, align: column.align === "right" ? "right" : "left",
|
|
28
|
+
format: (_value, row) => companyCellText(row as unknown as CompanyRow, column.id, observations),
|
|
29
|
+
})), { key: "asOf", header: "As of", format: (value) => typeof value === "string" ? value.slice(0, 10) : "--" }];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function datasetRows(data: CompanyDataset): CompanyRow[] {
|
|
33
|
+
return "series" in data ? allObservations(data) : allGuidance(data);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The metrics a report has rows for, `revenue (Revenue)`, in the order the server lists them. */
|
|
37
|
+
function metricList(rows: CompanyRow[]): string {
|
|
38
|
+
return [...new Map(rows.map((row) => [row.metricId, `${row.metricId} (${row.metric.name})`])).values()].join(", ");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The free preview is fixed, so a metric asked for is picked out of it here,
|
|
43
|
+
* never answered with another metric's rows. An id the dictionary does not
|
|
44
|
+
* know fails naming the ones this company has. A known metric the preview has
|
|
45
|
+
* no rows for may be among the values it holds back, so that case gives the
|
|
46
|
+
* preview's own counts; only a company with nothing held back has none.
|
|
47
|
+
*/
|
|
48
|
+
function metricFilter(requested: string, data: CompanyDataset, mode: CompanyMode): { keep: (row: CompanyRow) => boolean; empty?: string } {
|
|
49
|
+
if (!requested) return { keep: () => true };
|
|
50
|
+
const rows = datasetRows(data);
|
|
51
|
+
const whose = data.access === "preview" ? `${data.symbol}'s free preview` : data.symbol;
|
|
52
|
+
const offered = metricList(rows);
|
|
53
|
+
const has = offered ? `${whose} has ${offered}` : `${whose} has no ${mode === "kpis" ? "KPI" : "guidance"} disclosures`;
|
|
54
|
+
const known = data.dictionary.find((metric) => metric.id === requested) ?? rows.find((row) => row.metricId === requested)?.metric;
|
|
55
|
+
if (!known) throw new Error(`${requested} is not a known metric id. ${has}.`);
|
|
56
|
+
const keep = (row: CompanyRow) => row.metricId === requested;
|
|
57
|
+
if (rows.some(keep)) return { keep };
|
|
58
|
+
if (data.access === "preview" && data.lockedRows > 0) {
|
|
59
|
+
const shown = Math.max(0, data.totalRows - data.lockedRows);
|
|
60
|
+
const noun = (count: number) => `${mode === "kpis" ? "KPI value" : "guidance figure"}${count === 1 ? "" : "s"}`;
|
|
61
|
+
const all = `Gloom Pro shows all ${data.totalRows.toLocaleString("en-US")}`;
|
|
62
|
+
return { keep, empty: shown === 0 ? `The free preview shows no ${noun(0)}; ${all}.`
|
|
63
|
+
: `${known.name} is not ${shown === 1 ? "the" : "among the"} ${shown.toLocaleString("en-US")} free ${noun(shown)}; ${all}.` };
|
|
64
|
+
}
|
|
65
|
+
return { keep, empty: `${data.symbol} has no ${known.name} (${known.id}) ${mode === "kpis" ? "disclosures" : "guidance"}${offered ? `; it has ${offered}` : ""}.` };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* How old a free preview's rows are: the footer dates the company's newest
|
|
70
|
+
* disclosure, which the fixed preview may not show.
|
|
71
|
+
*/
|
|
72
|
+
function ageNote(data: CompanyDataset, latest: CompanyRow[], mode: CompanyMode): string | null {
|
|
73
|
+
const shown = latest.map((row) => row.asOf.slice(0, 10)).sort().at(-1);
|
|
74
|
+
const newest = data.asOf?.slice(0, 10);
|
|
75
|
+
if (data.access !== "preview" || !shown || !newest || newest <= shown) return null;
|
|
76
|
+
return `The free preview's latest ${mode === "kpis" ? "KPIs are" : "guidance is"} as of ${shown}, older than ${data.symbol}'s newest disclosure (${newest}).`;
|
|
77
|
+
}
|
|
4
78
|
|
|
5
79
|
export function companyHeadless(mode: CompanyMode): HeadlessPaneDefinition<"bundle"> {
|
|
6
80
|
return {
|
|
@@ -8,10 +82,10 @@ export function companyHeadless(mode: CompanyMode): HeadlessPaneDefinition<"bund
|
|
|
8
82
|
freshness: { source: "Company filings and calls", status: "not-a-feed", basis: "reported data" },
|
|
9
83
|
argument: { kind: "ticker", description: "Listed company ticker, including exchange-qualified global symbols.", placeholder: "ticker" },
|
|
10
84
|
discovery: { aliases: [mode === "kpis" ? "KPIS" : "GUIDE"], dataRequirements: ["Gloom Cloud company disclosures"],
|
|
11
|
-
limitations: ["Pro dataset with a fixed latest preview on Free", "Coverage follows available company disclosures; missing data is not zero", "Compare matching definition, period, currency, basis and scope", "Fiscal labels without explicit calendar dates are retained without inferred dates"] },
|
|
85
|
+
limitations: ["Pro dataset with a fixed latest preview on Free.", "Coverage follows available company disclosures; missing data is not zero.", "Compare matching definition, period, currency, basis and scope.", "Fiscal labels without explicit calendar dates are retained without inferred dates."] },
|
|
12
86
|
options: [
|
|
13
87
|
{ key: "tab", type: "enum", settingKey: "tab", defaultValue: "table", values: [{ value: "table" }, { value: "chart" }, ...(mode === "guidance" ? [{ value: "history" }] : []), { value: "evidence" }], description: "The pane section to render." },
|
|
14
|
-
{ key: "metric", type: "string", settingKey: "metric", description: "Canonical metric ID, such as arr or subscribers." },
|
|
88
|
+
{ key: "metric", type: "string", settingKey: "metric", description: "Canonical metric ID, such as arr or subscribers.", normalize: (value) => value.trim().toLowerCase() },
|
|
15
89
|
{ key: "basis", type: "enum", values: [{ value: "reported" }, { value: "adjusted" }, { value: "constant_currency" }, { value: "organic" }], description: "Accounting basis filter (Pro)." },
|
|
16
90
|
{ key: "from", type: "string", description: "First calendar period end, YYYY-MM-DD (Pro)." },
|
|
17
91
|
{ key: "to", type: "string", description: "Last calendar period end, YYYY-MM-DD (Pro)." },
|
|
@@ -19,15 +93,28 @@ export function companyHeadless(mode: CompanyMode): HeadlessPaneDefinition<"bund
|
|
|
19
93
|
],
|
|
20
94
|
describe: (args) => `${mode === "kpis" ? "Company KPIs" : "Company guidance"} | ${args.symbols[0]}`,
|
|
21
95
|
async load(args, ctx) {
|
|
22
|
-
const
|
|
96
|
+
const requested = typeof args.options.metric === "string" && args.options.metric !== "all" ? args.options.metric.trim().toLowerCase() : "";
|
|
97
|
+
const options = companyQuery({ ...args.options, metric: METRIC_ID.test(requested) ? requested : undefined });
|
|
23
98
|
const symbol = args.symbols[0]!;
|
|
24
99
|
const data = await fetchCompanyData(mode, symbol, options, ctx.apiClient, await resolveHeadlessIssuerListing(ctx, symbol));
|
|
25
|
-
|
|
100
|
+
const { keep, empty } = metricFilter(requested, data, mode);
|
|
101
|
+
const observations = "series" in data ? allObservations(data) : [];
|
|
102
|
+
// A metric with no rows says why once, in the first section.
|
|
103
|
+
const section = (title: string, rows: CompanyRow[], { history = false, revisions = false, first = false } = {}): HeadlessBundleSection => {
|
|
104
|
+
const shown = rows.filter(keep);
|
|
105
|
+
return { title, columns: reportColumns(mode, history, revisions, shown, observations), rows: shown.map((row) => ({ ...row })), ...(empty && first ? { empty } : {}) };
|
|
106
|
+
};
|
|
107
|
+
const latest = ("series" in data ? data.series.map((series) => series.latest) : data.guidance).filter(keep);
|
|
108
|
+
const ignored = data.access === "preview" ? PRO_FILTERS.filter((key) => typeof args.options[key] === "string" && args.options[key] !== "") : [];
|
|
109
|
+
const notes = [ageNote(data, latest, mode),
|
|
110
|
+
ignored.length ? `The free preview is fixed: ${ignored.map((key) => `--${key}`).join(", ")} ${ignored.length > 1 ? "need" : "needs"} Gloom Pro.` : null].filter((note): note is string => !!note);
|
|
111
|
+
return { complete: !data.truncated, errors: data.truncated ? [data.access === "preview" ? companyPreviewNote(data, mode === "guidance") : "Response limit reached; narrow the metric or date range"] : [],
|
|
112
|
+
...(notes.length ? { notes } : {}),
|
|
26
113
|
sections: "series" in data ? [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
] : [
|
|
114
|
+
section("Latest KPIs", data.series.map((series) => series.latest), { first: true }),
|
|
115
|
+
section("KPI history", data.series.flatMap((series) => series.observations)),
|
|
116
|
+
section("Revisions and conflicts", data.revisions, { revisions: true }),
|
|
117
|
+
] : [section("Current guidance", data.guidance, { first: true }), section("Guidance history", data.history, { history: true })],
|
|
31
118
|
metadata: { symbol: data.symbol, asOf: data.asOf, access: data.access, coverage: data.coverage, dictionary: data.dictionary,
|
|
32
119
|
lockedRows: data.lockedRows, totalRows: data.totalRows, methodology: data.methodology } };
|
|
33
120
|
},
|
|
@@ -3,6 +3,7 @@ import type { DataTableColumn } from "../../../components";
|
|
|
3
3
|
import { scalarPoint, staticSeries } from "../../../components/chart/static/series";
|
|
4
4
|
import type { CompositeChartXAxis } from "../../../components/chart/composite/types";
|
|
5
5
|
import { formatCompact, formatNumber } from "../../../utils/format";
|
|
6
|
+
import { freePreviewNote } from "../shared/free-preview";
|
|
6
7
|
|
|
7
8
|
export type CompanyRow = KpiObservation | KpiGuidance;
|
|
8
9
|
export const isGuidance = (row: CompanyRow): row is KpiGuidance => "issuedDate" in row;
|
|
@@ -29,7 +30,7 @@ export const rangeText = (row: KpiGuidance, withUnit = true) => row.status === "
|
|
|
29
30
|
: row.low !== null ? `${row.hedge === "greater_than" ? ">" : "≥"} ${valueText(row, row.low, withUnit)}`
|
|
30
31
|
: row.high !== null ? `${row.hedge === "less_than" ? "<" : "≤"} ${valueText(row, row.high, withUnit)}` : row.rangeText;
|
|
31
32
|
/** The unit a value cell carries after its number; percent, bp and x are already in the number. */
|
|
32
|
-
|
|
33
|
+
function unitSuffix(row: Pick<CompanyRow, "unit" | "currency" | "dimensions">): string {
|
|
33
34
|
if (row.unit === "currency") return row.currency ? ` ${row.currency}` : "";
|
|
34
35
|
if (row.unit === "currency_per_share") return ` ${row.currency ?? ""}/sh`.replace(" /", " ");
|
|
35
36
|
if (row.unit === "currency_per_unit" || row.unit === "volume") return ` ${unitLabel(row)}`;
|
|
@@ -68,7 +69,7 @@ export function observationChange(row: KpiObservation, observations: KpiObservat
|
|
|
68
69
|
return { value: (row.value - prior.value) / Math.abs(prior.value) * 100, unit: "%" };
|
|
69
70
|
}
|
|
70
71
|
export const changeText = (change: { value: number | null; unit: string }) => change.value === null ? "--" : `${change.value > 0 ? "+" : ""}${formatNumber(change.value, 2)}${change.unit}`;
|
|
71
|
-
export const fiscalLabel = (row: CompanyRow) => row.period.fiscalYear === null ? row.period.label
|
|
72
|
+
export const fiscalLabel = (row: Pick<CompanyRow, "period">) => row.period.fiscalYear === null ? row.period.label
|
|
72
73
|
: row.period.kind === "year" ? `FY${row.period.fiscalYear}`
|
|
73
74
|
: row.period.fiscalQuarter !== null ? `Q${row.period.fiscalQuarter} FY${row.period.fiscalYear}${row.period.kind === "ytd" ? " YTD" : ""}` : row.period.label;
|
|
74
75
|
export const periodOrder = (row: CompanyRow) => row.period.fiscalYear !== null
|
|
@@ -104,6 +105,19 @@ export function guidanceSeries(rows: KpiGuidance[], selected: KpiGuidance | unde
|
|
|
104
105
|
if (actual && series.length) series.push(staticSeries(timeline.map((row) => scalarPoint(new Date(row.issuedDate), actual.value)), { id: "actual", label: "Later actual", color: colors.actual, calendarSpaced: true }));
|
|
105
106
|
return series;
|
|
106
107
|
}
|
|
108
|
+
/** Columns that say nothing while every row is the company's consolidated, as-reported figure. */
|
|
109
|
+
export const QUIET_COLUMNS = { basis: ["Reported"], scope: ["Consolidated"] };
|
|
110
|
+
/** The text of a table cell as the pane draws it; the report prints the same words. */
|
|
111
|
+
export function companyCellText(row: CompanyRow, column: string, observations: KpiObservation[]): string {
|
|
112
|
+
const guide = isGuidance(row) ? row : null;
|
|
113
|
+
if (column === "change") return guide ? directionLabel(guide.direction) : changeText(observationChange(row as KpiObservation, observations));
|
|
114
|
+
return column === "metric" ? row.metric.name : column === "period" ? fiscalLabel(row) : column === "value" ? `${guide ? rangeText(guide) : observationValue(row as KpiObservation)}${guide?.status === "withdrawn" || guide?.hedge === "qualitative" ? "" : unitSuffix(row)}`
|
|
115
|
+
: column === "unit" ? unitLabel(row)
|
|
116
|
+
: column === "basis" ? basisLabel(row.basis) : column === "scope" ? dimensionLabel(row.dimensions) || "Consolidated"
|
|
117
|
+
: column === "issued" ? guide?.issuedDate ?? "--" : column === "actual" ? guide?.actual ? `${valueText(row, guide.actual.value)}${unitSuffix(row)}` : "--"
|
|
118
|
+
: column === "outcome" ? guide ? outcomeLabel(guide) : "--" : column === "published" ? row.evidence[0]!.publishedAt.slice(0, 10)
|
|
119
|
+
: column === "confidence" ? `${Math.round(row.confidence * 100)}%` : column === "revision" ? `${row.revision} ${row.current ? "current" : "superseded"}` : row.evidence[0]!.quote;
|
|
120
|
+
}
|
|
107
121
|
export function companyColumns(guidance: boolean, evidence: boolean, history: boolean, trend = false): DataTableColumn[] {
|
|
108
122
|
const columns: DataTableColumn[] = [
|
|
109
123
|
{ id: "metric", label: "Metric", width: 27, flexGrow: 1, align: "left" },
|
|
@@ -122,3 +136,11 @@ export function companyColumns(guidance: boolean, evidence: boolean, history: bo
|
|
|
122
136
|
: history ? ["metric", "period", "actual", "outcome", "value", "issued", "change", "basis", "scope"] : null;
|
|
123
137
|
return order ? columns.sort((a, b) => order.indexOf(a.id) - order.indexOf(b.id)) : columns;
|
|
124
138
|
}
|
|
139
|
+
|
|
140
|
+
/** The lock line of a free preview, in the same words in the pane and `fn KPIS` / `fn GUIDE`. */
|
|
141
|
+
export function companyPreviewNote(data: Pick<KpisPayload, "lockedRows" | "totalRows" | "coverage">, guidance: boolean): string {
|
|
142
|
+
const count = (value: number) => value.toLocaleString("en-US");
|
|
143
|
+
const rows = `${count(data.totalRows)} ${guidance ? "guidance figures" : "KPI values"}`;
|
|
144
|
+
return freePreviewNote({ shows: data.lockedRows > 0 ? `${count(Math.max(0, data.totalRows - data.lockedRows))} of ${rows}` : rows,
|
|
145
|
+
adds: data.lockedRows > 0 ? `the other ${count(data.lockedRows)}` : null, historyFrom: data.coverage.firstPeriod });
|
|
146
|
+
}
|
|
@@ -13,21 +13,22 @@ import type { PaneProps } from "../../../types/plugin";
|
|
|
13
13
|
import { Box, Text, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
|
|
14
14
|
import { SignInWall } from "../cloud/auth-actions";
|
|
15
15
|
import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
|
|
16
|
+
import { useOpenDescription } from "../shared/open-description";
|
|
16
17
|
import { Blurred, LockedOverlay, UpgradeLabel } from "../shared/locked-rows";
|
|
17
18
|
import { isCloudSessionRequired, useResearchCloudSession } from "../shared/research-cloud-session";
|
|
18
19
|
import { cachedCompanyData, loadCompanyData, KPI_UNAVAILABLE, validateCompanyData, type CompanyDataset, type CompanyMode } from "./client";
|
|
19
20
|
import { useCompanyEvidence } from "./screenshot-evidence";
|
|
20
|
-
import { allGuidance, allObservations, basisLabel, changeText, changeTone, companyColumns, dimensionLabel, directionLabel, directionTone, guideGroupKey, guidanceSeries, fiscalLabel,
|
|
21
|
-
isGuidance, exactObservation, observationValue, observationChange, observationChart, periodOrder, outcomeLabel, rangeText, seriesLabel, unitLabel,
|
|
21
|
+
import { allGuidance, allObservations, basisLabel, changeText, changeTone, companyCellText, companyColumns, dimensionLabel, directionLabel, directionTone, guideGroupKey, guidanceSeries, fiscalLabel,
|
|
22
|
+
isGuidance, exactObservation, observationValue, observationChange, observationChart, periodOrder, outcomeLabel, QUIET_COLUMNS, rangeText, seriesLabel, unitLabel, valueText, companyPreviewNote,
|
|
23
|
+
type CompanyRow } from "./model";
|
|
22
24
|
import { PriceSparkline } from "../../../components/price-sparkline/view";
|
|
23
25
|
import type { PricePoint } from "../../../types/financials";
|
|
24
26
|
import { toneColor, withoutQuietColumns } from "../shared/research-cells";
|
|
25
27
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
type Item = { id: string; row: CompanyRow } | { id: string; row: null };
|
|
28
|
+
/** A locked placeholder, or with `note` the line above them saying what free shows and what Pro adds. */
|
|
29
|
+
type Item = { id: string; row: CompanyRow } | { id: string; row: null; note?: string };
|
|
30
30
|
const getId = (item: Item) => item.id;
|
|
31
|
+
const isNote = (item: Item) => "note" in item && !!item.note;
|
|
31
32
|
function DisclosureEvidence({ row, sourceId, onSource, width }: { row: CompanyRow; sourceId: string | null; onSource: (id: string) => void; width: number }) {
|
|
32
33
|
const colors = useThemeColors();
|
|
33
34
|
const evidence = row.evidence.find((entry) => entry.id === sourceId) ?? row.evidence[0]!;
|
|
@@ -77,6 +78,7 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
|
|
|
77
78
|
const host = useRendererHost();
|
|
78
79
|
const desktop = !!useUiCapabilities().nativePaneChrome;
|
|
79
80
|
const { createPaneFromTemplate } = usePluginAppActions();
|
|
81
|
+
const openDescription = useOpenDescription();
|
|
80
82
|
const session = useResearchCloudSession();
|
|
81
83
|
const access = usePlanAccess();
|
|
82
84
|
const accessKey = `${session.requestKey}:${access.hasProAccess ? "full" : "preview"}`;
|
|
@@ -132,7 +134,9 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
|
|
|
132
134
|
const activeRow = openRow ?? selected;
|
|
133
135
|
const preview = data?.access === "preview" && data.lockedRows > 0;
|
|
134
136
|
const lockedCount = preview ? Math.min(3, data.lockedRows) : 0;
|
|
135
|
-
const
|
|
137
|
+
const previewNote = preview ? companyPreviewNote(data, mode === "guidance") : null;
|
|
138
|
+
const items = useMemo<Item[]>(() => [...rows.map((row) => ({ id: row.id, row })), ...(previewNote ? [{ id: "note:preview", row: null, note: previewNote }] : []),
|
|
139
|
+
...Array.from({ length: lockedCount }, (_, index) => ({ id: `locked:${index}`, row: null }))], [rows, lockedCount, previewNote]);
|
|
136
140
|
// One trend per series beside its latest value, once a series has three comparable points.
|
|
137
141
|
const trends = useMemo(() => {
|
|
138
142
|
const map = new Map<string, PricePoint[]>();
|
|
@@ -165,10 +169,10 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
|
|
|
165
169
|
...(preview ? [{ id: "upgrade", key: CLOUD_PLAN_KEY, label: "upgrade", title: "Upgrade to Pro", onPress: openUpgrade }] : []),
|
|
166
170
|
];
|
|
167
171
|
usePaneMenuItems("company-disclosures:research", () => symbol ? [
|
|
168
|
-
{ id: "description", label: "Description (DES)", onSelect: () =>
|
|
172
|
+
{ id: "description", label: "Description (DES)", onSelect: () => openDescription(symbol) },
|
|
169
173
|
{ id: "financials", label: "Financial Analysis (FA)", onSelect: () => createPaneFromTemplate("financial-analysis-pane", { symbol }) },
|
|
170
174
|
{ id: "price-chart", label: "Price Chart (G)", onSelect: () => createPaneFromTemplate("chart-composer-pane", { arg: symbol }) },
|
|
171
|
-
] : null, [symbol, createPaneFromTemplate]);
|
|
175
|
+
] : null, [symbol, createPaneFromTemplate, openDescription]);
|
|
172
176
|
usePaneStatusFooter({ registrationId: "company-kpis", loading: resource.loading, error: data ? resource.error : null, stale: resource.data?.stale,
|
|
173
177
|
info: data?.asOf ? [{ id: "as-of", parts: [{ text: `as of ${data.asOf.slice(0, 10)}`, tone: "muted" as const }] }] : [], hints });
|
|
174
178
|
usePaneNoticeFooter({ registrationId: "company-kpis:notices", focused, notices: [resource.data?.refreshError,
|
|
@@ -183,6 +187,7 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
|
|
|
183
187
|
const renderCell = (item: Item, column: (typeof columns)[number]): DataTableCell => {
|
|
184
188
|
const row = item.row;
|
|
185
189
|
if (!row) {
|
|
190
|
+
if (isNote(item)) return { text: "" };
|
|
186
191
|
if (!desktop && column.id === "metric" && item.id === "locked:0") return { text: "Unlock with Pro", content: <UpgradeLabel text="Unlock with Pro" onPress={openUpgrade} />, onMouseDown: openUpgrade };
|
|
187
192
|
return desktop ? { text: "", content: <Blurred><Text fg={colors.textDim}>{column.id === "metric" ? "Additional disclosure" : "Hidden"}</Text></Blurred> } : { text: "░░░░░", color: colors.textDim };
|
|
188
193
|
}
|
|
@@ -199,12 +204,7 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
|
|
|
199
204
|
const change = observationChange(row as KpiObservation, observations);
|
|
200
205
|
return { text: changeText(change), value: change.value, color: toneColor(changeTone(row as KpiObservation, change.value), colors) };
|
|
201
206
|
}
|
|
202
|
-
const text =
|
|
203
|
-
: column.id === "unit" ? unitLabel(row)
|
|
204
|
-
: column.id === "basis" ? basisLabel(row.basis) : column.id === "scope" ? dimensionLabel(row.dimensions) || "Consolidated"
|
|
205
|
-
: column.id === "issued" ? guide?.issuedDate ?? "--" : column.id === "actual" ? guide?.actual ? `${valueText(row, guide.actual.value)}${unitSuffix(row)}` : "--"
|
|
206
|
-
: column.id === "outcome" ? guide ? outcomeLabel(guide) : "--" : column.id === "published" ? row.evidence[0]!.publishedAt.slice(0, 10)
|
|
207
|
-
: column.id === "confidence" ? `${Math.round(row.confidence * 100)}%` : column.id === "revision" ? `${row.revision} ${row.current ? "current" : "superseded"}` : row.evidence[0]!.quote;
|
|
207
|
+
const text = companyCellText(row, column.id, observations);
|
|
208
208
|
return { text, ...(column.id === "value" && !guide ? { value: exactObservation(row as KpiObservation) ? (row as KpiObservation).value : observationValue(row as KpiObservation) } : column.id === "actual" ? { value: guide?.actual?.value } : {}),
|
|
209
209
|
color: column.id === "metric" ? colors.textBright : column.id === "value" || column.id === "actual" ? colors.textBright
|
|
210
210
|
: column.id === "outcome" && guide?.actual ? guide.actual.favorable === "beat" ? colors.positive : guide.actual.favorable === "miss" ? colors.negative : colors.text
|
|
@@ -217,7 +217,8 @@ function CompanyView({ symbol, exchange, name, mode, width, height, focused }: P
|
|
|
217
217
|
empty={!data && resource.error === KPI_UNAVAILABLE} emptyTitle={KPI_UNAVAILABLE} subject="company disclosures">
|
|
218
218
|
{data ? <DataTableStackView<Item> focused={focused} rootWidth={width} rootHeight={bodyHeight} columns={columns} items={items} getItemKey={getId}
|
|
219
219
|
selection={{ kind: "id", selectedId: selected?.id ?? null, getId, onChange: setSelected }}
|
|
220
|
-
onActivate={(item) => item.row ? setOpen(item.row.id) : openUpgrade()} renderCell={renderCell}
|
|
220
|
+
onActivate={(item) => item.row ? setOpen(item.row.id) : isNote(item) ? undefined : openUpgrade()} renderCell={renderCell}
|
|
221
|
+
isNavigable={(item) => !isNote(item)} renderSectionHeader={(item) => "note" in item && item.note ? { text: item.note } : null} freezeFirstColumn selectedTextOverridesCellColor showHorizontalScrollbar
|
|
221
222
|
detailOpen={!!openRow} onBack={() => setOpen(null)} detailTitle={openRow ? `${openRow.metric.name} · ${fiscalLabel(openRow)}` : undefined}
|
|
222
223
|
detailScrollRef={detailScrollRef} detailContent={openRow ? <DetailScrollBody ref={detailScrollRef} resetScrollKey={openRow.id}><DisclosureEvidence row={openRow} sourceId={sourceId} onSource={setSource} width={width} /></DetailScrollBody> : null}
|
|
223
224
|
sortColumnId={sort.column} sortDirection={sort.direction} onHeaderClick={(column) => setSort((previous) => ({ column, direction: previous.column === column && previous.direction === "desc" ? "asc" : "desc" }))}
|
|
@@ -32,6 +32,7 @@ import { cotModule } from "./cot";
|
|
|
32
32
|
import { doeModule } from "./doe";
|
|
33
33
|
import { gpuModule } from "./gpu";
|
|
34
34
|
import { fxMatrixModule } from "./fx-matrix";
|
|
35
|
+
import { docsModule } from "./docs";
|
|
35
36
|
import { helpModule } from "./help";
|
|
36
37
|
import { positionSizerModule } from "./kelly-sizer";
|
|
37
38
|
import { layoutManagerModule } from "./layout-manager";
|
|
@@ -57,6 +58,7 @@ import { socialMentionsModule } from "./social-mentions";
|
|
|
57
58
|
import { timeSalesModule } from "./time-sales";
|
|
58
59
|
import { estimateRevisionsModule } from "./estimate-revisions";
|
|
59
60
|
import { chartComposerModule } from "./chart-composer";
|
|
61
|
+
import { userSeriesModule } from "./chart-composer/user-series";
|
|
60
62
|
import { congressResearchModule } from "./congress-trades";
|
|
61
63
|
import { dividendYieldModule } from "./dividend-yield";
|
|
62
64
|
import { executivesModule } from "./executives";
|
|
@@ -104,7 +106,7 @@ import {
|
|
|
104
106
|
|
|
105
107
|
export const applicationPlugin = composeBuiltinPlugin({
|
|
106
108
|
...applicationPluginMeta,
|
|
107
|
-
modules: [layoutManagerModule, pluginMarketplaceModule, helpModule, changelogModule, connectionsModule],
|
|
109
|
+
modules: [layoutManagerModule, pluginMarketplaceModule, helpModule, changelogModule, connectionsModule, docsModule],
|
|
108
110
|
});
|
|
109
111
|
|
|
110
112
|
export const portfolioPlugin = composeBuiltinPlugin({
|
|
@@ -121,18 +123,22 @@ const tickerResearchModule = (module: PluginModule) => ({ module, stateId: "tick
|
|
|
121
123
|
export const tickerCorePlugin = composeBuiltinPlugin({
|
|
122
124
|
...tickerCorePluginMeta,
|
|
123
125
|
modules: [
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
...[
|
|
127
|
+
tickerDetailModule,
|
|
128
|
+
chartComposerModule,
|
|
129
|
+
researchModule,
|
|
130
|
+
estimateRevisionsModule,
|
|
131
|
+
companyKpisModule,
|
|
132
|
+
revenueBreakdownModule,
|
|
133
|
+
dividendYieldModule,
|
|
134
|
+
reverseDcfModule,
|
|
135
|
+
peBandModule,
|
|
136
|
+
executivesModule,
|
|
137
|
+
timeSalesModule,
|
|
138
|
+
].map(rendererOnly),
|
|
139
|
+
// Reads the profile's series folder, so it runs where the disk is: the desktop backend too.
|
|
140
|
+
userSeriesModule,
|
|
141
|
+
],
|
|
136
142
|
});
|
|
137
143
|
|
|
138
144
|
export const optionsVolatilityPlugin = composeBuiltinPlugin({
|
|
@@ -32,7 +32,7 @@ export const cotHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
32
32
|
options: [{ key: "report", type: "enum", values: [{ value: "legacy" }, { value: "disaggregated" }], defaultValue: "legacy", description: "CFTC report family." },
|
|
33
33
|
{ key: "traderClass", type: "enum", values: ["noncommercial", "commercial", "producer", "swap", "managed-money", "other-reportable", "nonreportable"].map((value) => ({ value })), description: "Trader class for the extremes board; defaults by report family." },
|
|
34
34
|
{ key: "scope", type: "enum", values: COT_SCOPES.map(({ value }) => ({ value })), defaultValue: "major", description: "Markets on the extremes board, as in the pane." }],
|
|
35
|
-
discovery: { aliases: ["COT", "CFTC"], dataRequirements: ["Gloom Cloud CFTC history"], limitations: ["Futures-only positions aggregate all maturities", "Legacy and disaggregated classes differ", "Observation date is not publication date", "Some markets have short or suppressed histories"] },
|
|
35
|
+
discovery: { aliases: ["COT", "CFTC"], dataRequirements: ["Gloom Cloud CFTC history"], limitations: ["Futures-only positions aggregate all maturities.", "Legacy and disaggregated classes differ.", "Observation date is not publication date.", "Some markets have short or suppressed histories."] },
|
|
36
36
|
describe: "CFTC positioning",
|
|
37
37
|
async load(args, ctx) {
|
|
38
38
|
const family = args.options.report === "disaggregated" ? "disaggregated" : "legacy";
|
|
@@ -3,14 +3,16 @@ import { cotBoardCache } from "./client";
|
|
|
3
3
|
import { cotHeadless } from "./headless";
|
|
4
4
|
import { COT_ROOT_OPTIONS, cotContractCode, cotContractCodeForTicker, cotRoot, cotUnknownMarketMessage } from "./model";
|
|
5
5
|
import { CotPane } from "./pane";
|
|
6
|
+
import { COT_SERIES } from "./series";
|
|
6
7
|
|
|
7
8
|
export const cotModule: PluginModule = {
|
|
9
|
+
series: COT_SERIES,
|
|
8
10
|
panes: [{ id: "cot", name: "CFTC Positioning", icon: "P", component: CotPane,
|
|
9
11
|
defaultPosition: "right", defaultMode: "floating", defaultFloatingSize: { width: 106, height: 30 },
|
|
10
12
|
tableExport: true, headless: cotHeadless }],
|
|
11
13
|
paneTemplates: [{ id: "cot-cot", paneId: "cot", label: "CFTC Positioning",
|
|
12
14
|
description: "Weekly futures positioning, changes, historical percentiles and cross-market extremes.",
|
|
13
|
-
keywords: ["cot", "cftc", "positioning", "commitments", "managed money", "net spec"],
|
|
15
|
+
keywords: ["cot", "cftc", "positioning", "commitments", "managed money", "net spec", "crude oil", "natural gas"],
|
|
14
16
|
shortcut: { prefix: "COT", aliases: ["CFTC"], argKind: "text" as const, argPlaceholder: "code or root", argOptional: true,
|
|
15
17
|
argOptions: () => COT_ROOT_OPTIONS }, headless: cotHeadless,
|
|
16
18
|
createInstance: (context, options) => {
|
|
@@ -5,6 +5,7 @@ import type { PricePoint } from "../../../types/financials";
|
|
|
5
5
|
import { formatPriceObservation } from "../../../market-data/market/format";
|
|
6
6
|
import { cleanFloat32Price } from "../../../cli/history-rows";
|
|
7
7
|
import { cryptoPairCoin, isFuturesSymbol } from "../shared/crypto-pair";
|
|
8
|
+
import { FUTURES_CONTRACTS, futuresBoardContract, futuresBoardContractForTicker, type FuturesContract } from "../../../market-data/futures-board";
|
|
8
9
|
|
|
9
10
|
export const COT_CLASSES: Record<CotFamily, Array<{ value: CotClass; label: string }>> = {
|
|
10
11
|
legacy: [{ value: "noncommercial", label: "Noncommercial" }, { value: "commercial", label: "Commercial" }, { value: "nonreportable", label: "Nonreportable" }],
|
|
@@ -29,7 +30,7 @@ const ROOTS: Record<string, { code: string; exchange: string; priceSymbol: strin
|
|
|
29
30
|
SOL: { code: "177741", exchange: "CME", priceSymbol: null, name: "Solana", crypto: true },
|
|
30
31
|
XRP: { code: "176740", exchange: "CME", priceSymbol: null, name: "XRP", crypto: true },
|
|
31
32
|
};
|
|
32
|
-
/** The
|
|
33
|
+
/** The verified root aliases, labeled "ZQ 30-Day Fed Funds"; `cotContractCode` also takes every FUT board root the CFTC reports. */
|
|
33
34
|
export const COT_ROOT_OPTIONS = Object.entries(ROOTS).map(([root, row]) => ({ value: root, label: root === row.name ? root : `${root} ${row.name}` }));
|
|
34
35
|
/** The crypto roots named for a coin, which a coin pair (BTC-USD) can stand for. The micros have no pair. */
|
|
35
36
|
const COIN_PAIR_ROOTS: ReadonlySet<string> = new Set(["BTC", "ETH", "SOL", "XRP"]);
|
|
@@ -37,9 +38,12 @@ const COIN_PAIR_ROOTS: ReadonlySet<string> = new Set(["BTC", "ETH", "SOL", "XRP"
|
|
|
37
38
|
* Front-month price overlays for major markets without a root alias, each
|
|
38
39
|
* checked to return five years of daily history (2026-09-24). Keyed by CFTC
|
|
39
40
|
* code, never added to ROOTS: an alias would also claim the equity ticker under
|
|
40
|
-
* the cursor (ZM, ZS, PL).
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* the cursor (ZM, ZS, PL). A FUT board root typed as an argument finds its
|
|
42
|
+
* market here through its price symbol (NG is NG=F, so 023651). No cash index
|
|
43
|
+
* stands in, so the dollar index has none. Orange juice and lumber were added
|
|
44
|
+
* on 2026-10-11 so their board roots open a market; lumber's contract (LBR)
|
|
45
|
+
* started in August 2022, so its price begins there. Bitcoin and ether are in
|
|
46
|
+
* ROOTS, where `cotContractCodeForTicker` keeps the same guard for their aliases.
|
|
43
47
|
*/
|
|
44
48
|
const PRICE_OVERLAYS: Record<string, { exchange: string; priceSymbol: string }> = {
|
|
45
49
|
"209742": { exchange: "CME", priceSymbol: "NQ=F" }, "239742": { exchange: "CME", priceSymbol: "RTY=F" },
|
|
@@ -60,9 +64,16 @@ const PRICE_OVERLAYS: Record<string, { exchange: string; priceSymbol: string }>
|
|
|
60
64
|
"007601": { exchange: "CBT", priceSymbol: "ZL=F" }, "026603": { exchange: "CBT", priceSymbol: "ZM=F" },
|
|
61
65
|
"083731": { exchange: "NYB", priceSymbol: "KC=F" }, "080732": { exchange: "NYB", priceSymbol: "SB=F" },
|
|
62
66
|
"033661": { exchange: "NYB", priceSymbol: "CT=F" }, "073732": { exchange: "NYB", priceSymbol: "CC=F" },
|
|
67
|
+
"040701": { exchange: "NYB", priceSymbol: "OJ=F" }, "058644": { exchange: "CME", priceSymbol: "LBR=F" },
|
|
63
68
|
"057642": { exchange: "CME", priceSymbol: "LE=F" }, "054642": { exchange: "CME", priceSymbol: "HE=F" },
|
|
64
69
|
"061641": { exchange: "CME", priceSymbol: "GF=F" },
|
|
65
70
|
};
|
|
71
|
+
/** The CFTC market a FUT board root reports under, by its price symbol; null for one the CFTC does not report (TTF). */
|
|
72
|
+
function boardMarketCode(contract: FuturesContract): string | null {
|
|
73
|
+
return Object.values(ROOTS).find((row) => row.priceSymbol === contract.symbol)?.code
|
|
74
|
+
?? Object.entries(PRICE_OVERLAYS).find(([, row]) => row.priceSymbol === contract.symbol)?.[0]
|
|
75
|
+
?? null;
|
|
76
|
+
}
|
|
66
77
|
/**
|
|
67
78
|
* The markets most readers mean by "positioning", verified against the live
|
|
68
79
|
* CFTC boards on 2026-09-22. A code missing from a report family simply does
|
|
@@ -90,14 +101,26 @@ export const COT_SCOPES = [{ value: "major", label: "Major markets" }, { value:
|
|
|
90
101
|
export type CotScope = typeof COT_SCOPES[number]["value"];
|
|
91
102
|
export function cotScope(value: unknown): CotScope { return value === "all" ? "all" : "major"; }
|
|
92
103
|
|
|
93
|
-
|
|
104
|
+
const rootAlias = (input: string) => ROOTS[input === "VIX" ? "VX" : input]?.code ?? null;
|
|
105
|
+
const marketCode = (input: string) => /^[0-9A-Z]{5}[0-9A-Z+]$/.test(input) ? input : null;
|
|
106
|
+
/**
|
|
107
|
+
* A CFTC code or root typed as an argument or stored in a pane: every alias,
|
|
108
|
+
* crypto included, and every FUT board root the CFTC reports. A typed root is
|
|
109
|
+
* always the future, so ZM here is soybean meal, never Zoom.
|
|
110
|
+
*/
|
|
94
111
|
export function cotContractCode(value: unknown): string | null {
|
|
95
112
|
if (typeof value !== "string") return null;
|
|
96
113
|
const input = value.trim().toUpperCase().replace(/=F$/, "");
|
|
97
|
-
|
|
114
|
+
const board = futuresBoardContract(value);
|
|
115
|
+
return rootAlias(input) ?? (board ? boardMarketCode(board) : null) ?? marketCode(input);
|
|
98
116
|
}
|
|
99
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* What a market `cotContractCode` does not know is told: a FUT board root the
|
|
119
|
+
* CFTC does not report says so; anything else gets roots and a code that work.
|
|
120
|
+
*/
|
|
100
121
|
export function cotUnknownMarketMessage(value: unknown): string {
|
|
122
|
+
const board = futuresBoardContract(value);
|
|
123
|
+
if (board) return `${board.code} (${board.name}) is not reported in the CFTC COT.`;
|
|
101
124
|
const roots = ["ES", "CL", "GC", "ZN"].filter((root) => ROOTS[root]);
|
|
102
125
|
return `Unknown market "${String(value)}". Try ${roots.join(", ")} or a CFTC market code such as ${ROOTS.GC!.code}.`;
|
|
103
126
|
}
|
|
@@ -106,18 +129,24 @@ export function cotUnknownMarketMessage(value: unknown): string {
|
|
|
106
129
|
* argument. The crypto aliases are also US ticker symbols (Grayscale's mini
|
|
107
130
|
* trusts are BTC and ETH, MetLife is MET), so a bare one is the equity's and
|
|
108
131
|
* never claims the market: only a futures symbol (BTC=F) or a coin pair
|
|
109
|
-
* (BTC-USD) does.
|
|
132
|
+
* (BTC-USD) does. A FUT board root claims it the same way: as its futures
|
|
133
|
+
* symbol (NG=F) or a code no security uses (ZW), never a bare code a security
|
|
134
|
+
* keeps (ZM is Zoom).
|
|
110
135
|
*/
|
|
111
136
|
export function cotContractCodeForTicker(ticker: unknown): string | null {
|
|
112
137
|
if (typeof ticker !== "string") return null;
|
|
113
138
|
const coin = cryptoPairCoin(ticker);
|
|
114
139
|
if (coin) return COIN_PAIR_ROOTS.has(coin) ? ROOTS[coin]!.code : null;
|
|
115
140
|
const input = ticker.trim().toUpperCase().replace(/=F$/, "");
|
|
116
|
-
|
|
141
|
+
if (ROOTS[input]?.crypto && !isFuturesSymbol(ticker)) return null;
|
|
142
|
+
const board = futuresBoardContractForTicker(ticker);
|
|
143
|
+
return rootAlias(input) ?? (board ? boardMarketCode(board) : null) ?? marketCode(input);
|
|
117
144
|
}
|
|
118
|
-
/** The
|
|
145
|
+
/** The futures root a CFTC code belongs to, for titles readers recognize: a verified alias, else its FUT board root. */
|
|
119
146
|
export function cotRoot(code: string): string | null {
|
|
120
|
-
return Object.entries(ROOTS).find(([, row]) => row.code === code)?.[0]
|
|
147
|
+
return Object.entries(ROOTS).find(([, row]) => row.code === code)?.[0]
|
|
148
|
+
?? FUTURES_CONTRACTS.find((contract) => boardMarketCode(contract) === code)?.code
|
|
149
|
+
?? null;
|
|
121
150
|
}
|
|
122
151
|
export function cotPriceMapping(code: string) { return Object.values(ROOTS).find((row) => row.code === code) ?? PRICE_OVERLAYS[code] ?? null; }
|
|
123
152
|
export function cotClass(family: CotFamily, value: unknown): CotClass {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
2
|
+
import { fetchCotContract } from "./client";
|
|
3
|
+
import { COT_ROOT_OPTIONS, cotContractCode, cotNetPoints } from "./model";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Speculative (noncommercial) net positioning for each market the COT pane
|
|
7
|
+
* names by root, from the legacy report every market is in. The pane's other
|
|
8
|
+
* trader classes and markets stay in the pane.
|
|
9
|
+
*/
|
|
10
|
+
export const COT_SERIES: readonly SeriesDefinition[] = COT_ROOT_OPTIONS.flatMap((option): SeriesDefinition[] => {
|
|
11
|
+
const code = cotContractCode(option.value);
|
|
12
|
+
if (!code) return [];
|
|
13
|
+
const market = option.label.startsWith(`${option.value} `) ? option.label.slice(option.value.length + 1) : option.label;
|
|
14
|
+
return [{
|
|
15
|
+
id: `cot:${option.value.toLowerCase()}-noncommercial-net`,
|
|
16
|
+
name: `${market}: noncommercial net position`,
|
|
17
|
+
unit: "contracts",
|
|
18
|
+
frequency: "weekly",
|
|
19
|
+
group: "Positioning",
|
|
20
|
+
tags: ["COT", "commitments of traders", "speculators", "net spec", option.value],
|
|
21
|
+
publisher: "CFTC",
|
|
22
|
+
load: async () => {
|
|
23
|
+
const payload = await fetchCotContract(code, "legacy");
|
|
24
|
+
return { points: cotNetPoints(payload.history, "noncommercial").map((point) => ({ date: point.date, value: point.value })) };
|
|
25
|
+
},
|
|
26
|
+
}];
|
|
27
|
+
});
|
|
@@ -42,9 +42,9 @@ export const cpiHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
42
42
|
argument: { kind: "free-text", optional: true, placeholder: "component", description: "A component such as shelter, core, gasoline or supercore; omit for the table." },
|
|
43
43
|
options: [],
|
|
44
44
|
discovery: { aliases: ["CPI", "ECAN"], dataRequirements: ["Gloom Cloud US consumer price history"],
|
|
45
|
-
limitations: ["Monthly data, published by BLS at 08:30 ET on its release schedule",
|
|
46
|
-
"Weights and contributions are BLS's for the month; services ex shelter is computed from two BLS series",
|
|
47
|
-
"No October 2025 index was published, so changes that need it are empty"] },
|
|
45
|
+
limitations: ["Monthly data, published by BLS at 08:30 ET on its release schedule.",
|
|
46
|
+
"Weights and contributions are BLS's for the month; services ex shelter is computed from two BLS series.",
|
|
47
|
+
"No October 2025 index was published, so changes that need it are empty."] },
|
|
48
48
|
describe: "US consumer prices by component",
|
|
49
49
|
async load(args) {
|
|
50
50
|
const data = await fetchCpiBoard();
|