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
|
@@ -15,17 +15,18 @@ import type { ResolvedSeries } from "../../../time-series/types";
|
|
|
15
15
|
import type { PaneProps } from "../../../types/plugin";
|
|
16
16
|
import { Box } from "../../../ui";
|
|
17
17
|
import { loadSeasonalityHistory } from "./client";
|
|
18
|
-
import { MONTH_LABELS, OVERLAY_YEAR, projectSeasonality, type SeasonalityModel
|
|
18
|
+
import { type DailyReturnStat, MONTH_LABELS, OVERLAY_YEAR, projectSeasonality, projectWeekdays, type SeasonalityModel,
|
|
19
|
+
TURN_OF_MONTH_LABELS, type WeekdayModel } from "./model";
|
|
19
20
|
|
|
20
|
-
const TABS = [{ value: "returns", label: "Returns" }, { value: "overlay", label: "Overlay" }];
|
|
21
|
+
const TABS = [{ value: "returns", label: "Returns" }, { value: "overlay", label: "Overlay" }, { value: "weekdays", label: "Weekdays" }];
|
|
21
22
|
export const LOOKBACK_OPTIONS = [{ value: "5", label: "5Y" }, { value: "10", label: "10Y" }, { value: "20", label: "20Y" }];
|
|
22
|
-
/** The move that tints a cell at full strength: a month of ±10%, a year of ±30%. */
|
|
23
|
-
const MONTH_SCALE = 0.1, YEAR_SCALE = 0.3;
|
|
24
|
-
function pct(value: number | null | undefined): string {
|
|
23
|
+
/** The move that tints a cell at full strength: a month of ±10%, a year of ±30%, an average session of ±0.5%. */
|
|
24
|
+
const MONTH_SCALE = 0.1, YEAR_SCALE = 0.3, SESSION_SCALE = 0.005;
|
|
25
|
+
function pct(value: number | null | undefined, digits = 1): string {
|
|
25
26
|
if (value == null) return "--";
|
|
26
|
-
const fixed = (value * 100).toFixed(
|
|
27
|
+
const fixed = (value * 100).toFixed(digits);
|
|
27
28
|
// A return that rounds to zero reads 0.0%, never -0.0%.
|
|
28
|
-
return /[1-9]/.test(fixed) ? `${value > 0 ? "+" : ""}${fixed}%` :
|
|
29
|
+
return /[1-9]/.test(fixed) ? `${value > 0 ? "+" : ""}${fixed}%` : `${(0).toFixed(digits)}%`;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
interface Row { id: string; label: string; cells: (number | null)[]; total: number | null; kind: "stat" | "hit" | "year"; partial?: boolean }
|
|
@@ -46,14 +47,16 @@ function tableRows(model: SeasonalityModel): Row[] {
|
|
|
46
47
|
];
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
function hitCell(value: number | null, quiet = false): DataTableCell {
|
|
51
|
+
const heat = resolveHeatCellColors(value == null ? null : (value - 0.5) * 2, { quiet });
|
|
52
|
+
return { text: value == null ? "--" : `${Math.round(value * 100)}%`, value: value == null ? null : value * 100,
|
|
53
|
+
backgroundColor: heat.background, color: heat.foreground };
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
function renderCell(row: Row, column: DataTableColumn, runningMonth: number | null): DataTableCell {
|
|
50
57
|
if (column.id === "label") return { text: row.label };
|
|
51
58
|
const value = column.id === "total" ? row.total : row.cells[Number(column.id.slice(1))] ?? null;
|
|
52
|
-
if (row.kind === "hit")
|
|
53
|
-
const heat = resolveHeatCellColors(value == null ? null : (value - 0.5) * 2);
|
|
54
|
-
return { text: value == null ? "--" : `${Math.round(value * 100)}%`, value: value == null ? null : value * 100,
|
|
55
|
-
backgroundColor: heat.background, color: heat.foreground };
|
|
56
|
-
}
|
|
59
|
+
if (row.kind === "hit") return hitCell(value);
|
|
57
60
|
const scale = column.id === "total" ? YEAR_SCALE : MONTH_SCALE;
|
|
58
61
|
// The month still running is a return to date: shown, but not tinted as a finished month.
|
|
59
62
|
const quiet = value == null || (row.partial && column.id === `m${runningMonth}`);
|
|
@@ -61,6 +64,40 @@ function renderCell(row: Row, column: DataTableColumn, runningMonth: number | nu
|
|
|
61
64
|
return { text: pct(value), value: value == null ? null : value * 100, backgroundColor: heat.background, color: heat.foreground };
|
|
62
65
|
}
|
|
63
66
|
|
|
67
|
+
type WeekdayRow = { kind: "section"; id: string; label: string } | { kind: "stat"; id: string; label: string; stat: DailyReturnStat };
|
|
68
|
+
|
|
69
|
+
const WEEKDAY_COLUMNS: DataTableColumn[] = [
|
|
70
|
+
{ id: "label", label: "Day", width: 10, align: "left" },
|
|
71
|
+
{ id: "mean", label: "Avg", width: 9, align: "right" },
|
|
72
|
+
{ id: "median", label: "Median", width: 9, align: "right" },
|
|
73
|
+
{ id: "hitRate", label: "Up %", width: 7, align: "right" },
|
|
74
|
+
{ id: "count", label: "Sessions", width: 9, align: "right" },
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
function weekdayRows(model: WeekdayModel): WeekdayRow[] {
|
|
78
|
+
const stat = (label: string, value: DailyReturnStat): WeekdayRow => ({ kind: "stat", id: label, label, stat: value });
|
|
79
|
+
return [
|
|
80
|
+
{ kind: "section", id: "weekdays", label: "By weekday" },
|
|
81
|
+
...model.weekdays.map((value) => stat(value.day, value)),
|
|
82
|
+
{ kind: "section", id: "turn", label: "Turn of month" },
|
|
83
|
+
...model.turnOfMonth.map((value, index) => stat(TURN_OF_MONTH_LABELS[index]!, value)),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** A row with fewer sessions (an exchange's rare Saturday session) is shown but not tinted. */
|
|
88
|
+
const MIN_TINTED_SESSIONS = 20;
|
|
89
|
+
|
|
90
|
+
function renderWeekdayCell(row: WeekdayRow, column: DataTableColumn): DataTableCell {
|
|
91
|
+
if (row.kind === "section") return { text: "" };
|
|
92
|
+
if (column.id === "label") return { text: row.label };
|
|
93
|
+
if (column.id === "count") return { text: String(row.stat.count), value: row.stat.count };
|
|
94
|
+
const quiet = row.stat.count < MIN_TINTED_SESSIONS;
|
|
95
|
+
if (column.id === "hitRate") return hitCell(row.stat.hitRate, quiet);
|
|
96
|
+
const value = column.id === "mean" ? row.stat.mean : row.stat.median;
|
|
97
|
+
const heat = resolveHeatCellColors(value == null ? null : value / SESSION_SCALE, { quiet });
|
|
98
|
+
return { text: pct(value, 2), value: value == null ? null : value * 100, backgroundColor: heat.background, color: heat.foreground };
|
|
99
|
+
}
|
|
100
|
+
|
|
64
101
|
function overlaySeries(model: SeasonalityModel, colors: ReturnType<typeof useThemeColors>): ResolvedSeries[] {
|
|
65
102
|
const toSeries = (id: string, label: string, color: string, points: { date: Date; value: number }[]): ResolvedSeries => ({
|
|
66
103
|
...staticSeries(points.map((point) => ({ date: point.date, observedAt: point.date, value: point.value * 100 })),
|
|
@@ -77,6 +114,29 @@ function overlaySeries(model: SeasonalityModel, colors: ReturnType<typeof useThe
|
|
|
77
114
|
];
|
|
78
115
|
}
|
|
79
116
|
|
|
117
|
+
/** Green above zero, red below; a figure that rounds to zero is neither. */
|
|
118
|
+
const tone = (value: number | null, digits = 1) => value == null || !/[1-9]/.test((value * 100).toFixed(digits)) ? undefined
|
|
119
|
+
: value > 0 ? "positive" as const : "negative" as const;
|
|
120
|
+
|
|
121
|
+
function weekdayStats(model: WeekdayModel): StatItem[] {
|
|
122
|
+
const figure = (id: string, label: string, stat: DailyReturnStat): StatItem => ({ id, label, value: pct(stat.mean, 2), tone: tone(stat.mean, 2),
|
|
123
|
+
detail: stat.count ? `${Math.round(stat.hitRate! * 100)}% up` : undefined });
|
|
124
|
+
return [figure("turn", "Turn of month", model.turnWindow), figure("other", "Other days", model.otherDays)];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function monthStats(model: SeasonalityModel): StatItem[] {
|
|
128
|
+
if (!model.asOf || !model.years.length) return [];
|
|
129
|
+
const month = model.asOf.getUTCMonth();
|
|
130
|
+
const stat = model.months[month]!;
|
|
131
|
+
const current = model.years[0]!;
|
|
132
|
+
return [
|
|
133
|
+
{ id: "month-avg", label: `${MONTH_LABELS[month]} avg`, value: pct(stat.mean), tone: tone(stat.mean) },
|
|
134
|
+
{ id: "month-hit", label: `${MONTH_LABELS[month]} up`, value: stat.count ? `${Math.round(stat.hitRate! * 100)}%` : "--",
|
|
135
|
+
detail: stat.count ? `${Math.round(stat.hitRate! * stat.count)} of ${stat.count} yrs` : undefined },
|
|
136
|
+
...(current.partial ? [{ id: "ytd", label: `${current.year} YTD`, value: pct(current.total), tone: tone(current.total) }] : []),
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
|
|
80
140
|
export function SeasonalityPane({ width, height, focused }: PaneProps) {
|
|
81
141
|
const colors = useThemeColors();
|
|
82
142
|
const { symbol, ticker, error: identityError } = usePaneTicker();
|
|
@@ -85,57 +145,68 @@ export function SeasonalityPane({ width, height, focused }: PaneProps) {
|
|
|
85
145
|
const [selectedRow, setSelectedRow] = usePluginPaneState<string | null>("selectedRow", null);
|
|
86
146
|
const instrument = instrumentFromTicker(ticker, symbol);
|
|
87
147
|
const instrumentKey = JSON.stringify(instrument);
|
|
148
|
+
const exchange = instrument?.exchange;
|
|
149
|
+
// Weekdays reads daily closes, the other tabs monthly ones; only the open tab's cadence is fetched.
|
|
150
|
+
const cadence = view === "weekdays" ? "daily" : "monthly";
|
|
88
151
|
const controller = useRef<AbortController | null>(null);
|
|
89
152
|
const loader = useCallback(async (force: boolean) => {
|
|
90
153
|
controller.current?.abort();
|
|
91
154
|
controller.current = new AbortController();
|
|
92
|
-
const snapshot = await loadSeasonalityHistory({ instrument: instrument!, forceRefresh: force, signal: controller.current.signal });
|
|
155
|
+
const snapshot = await loadSeasonalityHistory({ instrument: instrument!, cadence, forceRefresh: force, signal: controller.current.signal });
|
|
93
156
|
if (!snapshot.history.length && snapshot.error) throw new Error(snapshot.error);
|
|
94
157
|
return snapshot;
|
|
95
|
-
}, [instrumentKey]);
|
|
158
|
+
}, [instrumentKey, cadence]);
|
|
96
159
|
const history = useAsyncResource(instrument ? loader : null);
|
|
97
160
|
useEffect(() => () => controller.current?.abort(), [loader]);
|
|
98
161
|
useAutoRefresh(history.updatedAt, history.load);
|
|
99
162
|
usePaneRefreshKey(() => { void history.reload(); }, { focused });
|
|
100
163
|
|
|
101
|
-
const
|
|
102
|
-
|
|
164
|
+
const lookbackYears = Number(lookback) || 10;
|
|
165
|
+
const model = useMemo(() => history.data && cadence === "monthly"
|
|
166
|
+
? projectSeasonality(history.data.history, { symbol: symbol ?? "", lookbackYears }) : null, [history.data, cadence, lookbackYears, symbol]);
|
|
167
|
+
// Daily closes are served for five years, so Weekdays counts all of them and has no lookback.
|
|
168
|
+
const weekdayModel = useMemo(() => history.data && cadence === "daily"
|
|
169
|
+
? projectWeekdays(history.data.history, { symbol: symbol ?? "", exchange, fetchedAt: history.data.fetchedAt }) : null,
|
|
170
|
+
[history.data, cadence, symbol, exchange]);
|
|
103
171
|
const rows = useMemo(() => model ? tableRows(model) : [], [model]);
|
|
172
|
+
const dailyRows = useMemo(() => weekdayModel ? weekdayRows(weekdayModel) : [], [weekdayModel]);
|
|
104
173
|
const series = useMemo(() => model ? overlaySeries(model, colors) : [], [model, colors]);
|
|
105
174
|
const runningMonth = model?.years[0]?.partial && model.asOf ? model.asOf.getUTCMonth() : null;
|
|
106
175
|
|
|
107
176
|
usePaneNoticeFooter({ registrationId: "seasonality-notices", focused,
|
|
108
177
|
notices: [...new Set([identityError, history.error, history.data?.error].filter((value): value is string => !!value))] });
|
|
178
|
+
const closes = model?.asOf ? `monthly closes to ${model.asOf.toISOString().slice(0, 7)}`
|
|
179
|
+
: weekdayModel?.start ? `daily closes ${weekdayModel.start} to ${weekdayModel.asOf}` : null;
|
|
109
180
|
usePaneFooter("seasonality", () => ({ info: [
|
|
110
181
|
...(history.loading ? [{ id: "loading", parts: [{ text: "loading history", tone: "muted" as const }] }] : []),
|
|
111
182
|
...(history.data?.stale ? [{ id: "stale", parts: [{ text: "stale history", tone: "warning" as const }] }] : []),
|
|
112
|
-
...(
|
|
113
|
-
] }), [history.loading, history.data?.stale,
|
|
114
|
-
|
|
115
|
-
const stats = useMemo((): StatItem[] =>
|
|
116
|
-
|
|
117
|
-
const month = model.asOf.getUTCMonth();
|
|
118
|
-
const stat = model.months[month]!;
|
|
119
|
-
const current = model.years[0]!;
|
|
120
|
-
const tone = (value: number | null) => value == null ? undefined : value >= 0 ? "positive" as const : "negative" as const;
|
|
121
|
-
return [
|
|
122
|
-
{ id: "month-avg", label: `${MONTH_LABELS[month]} avg`, value: pct(stat.mean), tone: tone(stat.mean) },
|
|
123
|
-
{ id: "month-hit", label: `${MONTH_LABELS[month]} up`, value: stat.count ? `${Math.round(stat.hitRate! * 100)}%` : "--",
|
|
124
|
-
detail: stat.count ? `${Math.round(stat.hitRate! * stat.count)} of ${stat.count} yrs` : undefined },
|
|
125
|
-
...(current.partial ? [{ id: "ytd", label: `${current.year} YTD`, value: pct(current.total), tone: tone(current.total) }] : []),
|
|
126
|
-
];
|
|
127
|
-
}, [model]);
|
|
183
|
+
...(closes ? [{ id: "date", parts: [{ text: closes, tone: "muted" as const }] }] : []),
|
|
184
|
+
] }), [history.loading, history.data?.stale, closes]);
|
|
185
|
+
|
|
186
|
+
const stats = useMemo((): StatItem[] => weekdayModel?.start ? weekdayStats(weekdayModel) : model ? monthStats(model) : [],
|
|
187
|
+
[model, weekdayModel]);
|
|
128
188
|
|
|
129
189
|
const { strip, rows: tabRows } = usePaneTabs({ tabs: TABS, activeValue: view, onSelect: setView, focused, dense: true });
|
|
130
|
-
const
|
|
190
|
+
const queryRows = cadence === "monthly" ? 1 : 0;
|
|
191
|
+
const contentHeight = Math.max(4, height - queryRows - tabRows - statGridRows(stats, width));
|
|
131
192
|
const palette = resolveChartPalette(colors);
|
|
132
193
|
|
|
133
194
|
return <Box width={width} height={height} flexDirection="column" overflow="hidden">
|
|
134
195
|
{strip}
|
|
135
|
-
<QueryBar width={width} filters={[{ id: "lookback", label: "Lookback", value: String(lookback), options: LOOKBACK_OPTIONS, onChange: setLookback }]} />
|
|
136
|
-
{!symbol ? <EmptyState title="Select a ticker." /> : <PaneStatusBody subject="seasonality" loading={history.loading && !model}
|
|
137
|
-
error={!model ? history.error ?? identityError ?? null : null}
|
|
138
|
-
{model ?
|
|
196
|
+
{queryRows ? <QueryBar width={width} filters={[{ id: "lookback", label: "Lookback", value: String(lookback), options: LOOKBACK_OPTIONS, onChange: setLookback }]} /> : null}
|
|
197
|
+
{!symbol ? <EmptyState title="Select a ticker." /> : <PaneStatusBody subject="seasonality" loading={history.loading && !model && !weekdayModel}
|
|
198
|
+
error={!model && !weekdayModel ? history.error ?? identityError ?? null : null}
|
|
199
|
+
empty={model ? !model.years.length : !!weekdayModel && !weekdayModel.start}>
|
|
200
|
+
{weekdayModel ? <>
|
|
201
|
+
<StatGrid items={stats} width={width} />
|
|
202
|
+
<DataTableView<WeekdayRow> focused={focused} columns={WEEKDAY_COLUMNS} items={dailyRows} rootWidth={width} rootHeight={contentHeight}
|
|
203
|
+
getItemKey={(row) => row.id} emptyStateTitle="No daily returns." sortColumnId={null} sortDirection="desc"
|
|
204
|
+
isNavigable={(row) => row.kind === "stat"} renderSectionHeader={(row) => row.kind === "section" ? { text: row.label } : null}
|
|
205
|
+
selection={{ kind: "id", selectedId: selectedRow, getId: (row) => row.id, onChange: (id) => setSelectedRow(id) }}
|
|
206
|
+
getExportMetadata={() => [["symbol", weekdayModel.symbol], ["from", weekdayModel.start], ["as of", weekdayModel.asOf],
|
|
207
|
+
["units", "percent, local-price session close to close"]]}
|
|
208
|
+
renderCell={renderWeekdayCell} />
|
|
209
|
+
</> : model ? <>
|
|
139
210
|
<StatGrid items={stats} width={width} />
|
|
140
211
|
{view === "overlay"
|
|
141
212
|
? <CompositeChart series={series} panels={[{ id: "main" }]} width={width} height={contentHeight} focused={focused}
|
|
@@ -42,11 +42,31 @@ export interface SecHeadlessOptions {
|
|
|
42
42
|
forms?: readonly string[];
|
|
43
43
|
title?: string;
|
|
44
44
|
argumentDescription?: string;
|
|
45
|
+
/**
|
|
46
|
+
* What the report says when none of the issuer's filings is one of `forms`,
|
|
47
|
+
* in place of "No data.": `searched` filings were read, all of them when `complete`.
|
|
48
|
+
*/
|
|
49
|
+
empty?(symbol: string, searched: { count: number; complete: boolean }): string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const FUND_FACTS_NOTE = "Fund facts (fee, NAV, premium) are not available yet";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* ETF's empty report: a fund that files none of the fund forms, such as a
|
|
56
|
+
* grantor trust (IBIT, GLD) filing 10-Qs, says so and where its filings are.
|
|
57
|
+
*/
|
|
58
|
+
export function fundFilingsEmpty(symbol: string, searched: { count: number; complete: boolean }): string {
|
|
59
|
+
if (searched.count === 0) return `No SEC filings found for ${symbol}. ${FUND_FACTS_NOTE}.`;
|
|
60
|
+
const forms = "prospectus, shareholder reports, N-CEN, N-PORT";
|
|
61
|
+
const none = searched.complete
|
|
62
|
+
? `${symbol} files none of the fund forms ETF lists (${forms}).`
|
|
63
|
+
: `None of ${symbol}'s latest ${searched.count} SEC filings is a fund form ETF lists (${forms}).`;
|
|
64
|
+
return `${none} ${FUND_FACTS_NOTE}; try fn SEC ${symbol}.`;
|
|
45
65
|
}
|
|
46
66
|
|
|
47
67
|
export function createSecHeadless(
|
|
48
68
|
dependencies: SecHeadlessDependencies = defaultDependencies,
|
|
49
|
-
{ forms, title = "SEC Filings", argumentDescription = "US equity ticker." }: SecHeadlessOptions = {},
|
|
69
|
+
{ forms, title = "SEC Filings", argumentDescription = "US equity ticker.", empty }: SecHeadlessOptions = {},
|
|
50
70
|
): HeadlessPaneDefinition<"rows"> {
|
|
51
71
|
return {
|
|
52
72
|
shape: "rows",
|
|
@@ -79,10 +99,12 @@ export function createSecHeadless(
|
|
|
79
99
|
}
|
|
80
100
|
const issuerFilings = await dependencies.loadFilings(symbol, SEC_FILING_FETCH_LIMIT, args, ctx);
|
|
81
101
|
const filings = filterFilingsByForms(issuerFilings, forms).slice(0, limit);
|
|
102
|
+
// A full page of issuer filings can hide older matches past it.
|
|
103
|
+
const complete = issuerFilings.length < SEC_FILING_FETCH_LIMIT;
|
|
82
104
|
return {
|
|
83
105
|
rows: buildSecFilingRows(filings),
|
|
84
|
-
|
|
85
|
-
complete
|
|
106
|
+
...(empty && filings.length === 0 ? { empty: empty(symbol, { count: issuerFilings.length, complete }) } : {}),
|
|
107
|
+
complete,
|
|
86
108
|
metadata: {
|
|
87
109
|
acceptanceNote: SEC_ACCEPTANCE_NOTE,
|
|
88
110
|
symbol,
|
|
@@ -35,7 +35,7 @@ import { usePaneStatusLinkFooter } from "../../../components/layout/pane/status-
|
|
|
35
35
|
import { isCloudSessionRequired, useResearchCloudSession } from "../shared/research-cloud-session";
|
|
36
36
|
import { SignInWall } from "../cloud/auth-actions";
|
|
37
37
|
import { ETF_FILING_FORMS, ETF_FORMS_SETTING, filterFilingsByForms, parseFormsSetting, SEC_FILING_FETCH_LIMIT } from "./forms";
|
|
38
|
-
import { createSecHeadless, secHeadless } from "./headless";
|
|
38
|
+
import { createSecHeadless, fundFilingsEmpty, secHeadless } from "./headless";
|
|
39
39
|
import {
|
|
40
40
|
getFilingDisplayTitle,
|
|
41
41
|
getFilingColumnText,
|
|
@@ -469,6 +469,7 @@ export const secModule: PluginModule = {
|
|
|
469
469
|
forms: ETF_FILING_FORMS,
|
|
470
470
|
title: "Fund Filings",
|
|
471
471
|
argumentDescription: "US-listed fund ticker.",
|
|
472
|
+
empty: fundFilingsEmpty,
|
|
472
473
|
}),
|
|
473
474
|
},
|
|
474
475
|
],
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every chart a built-in pane draws, and whether its series is in the data
|
|
3
|
+
* catalog. `series-inventory.test.ts` fails when a module starts drawing a
|
|
4
|
+
* chart without an entry here, when an entry names a series nobody
|
|
5
|
+
* registers, or when a built-in registers a series this list does not name,
|
|
6
|
+
* so the audit cannot drift from the code.
|
|
7
|
+
*
|
|
8
|
+
* `series` lists catalog ids, with a trailing `*` for a prefix. A chart that
|
|
9
|
+
* is not in the catalog says why:
|
|
10
|
+
* - `not-a-time-series`: plotted against something other than dates (a
|
|
11
|
+
* curve by maturity, a surface, a treemap, strikes, a distribution).
|
|
12
|
+
* - `derived`: a chart composer study draws it from catalog series
|
|
13
|
+
* (correlation, realized volatility, a spread between two tickers).
|
|
14
|
+
* - `per-item`: one deal, trial, filing or model run, with no stable id to list.
|
|
15
|
+
* - `account`: built from the user's own portfolio or inputs.
|
|
16
|
+
* - `not-yet`: a dated series that could be registered and is not yet.
|
|
17
|
+
*/
|
|
18
|
+
type SeriesInventoryStatus =
|
|
19
|
+
/** `runtime`: registered while the app runs (files, accounts), so none exist in a test. */
|
|
20
|
+
| { series: readonly string[]; runtime?: true }
|
|
21
|
+
| { notInCatalog: "not-a-time-series" | "derived" | "per-item" | "account" | "not-yet"; reason: string };
|
|
22
|
+
|
|
23
|
+
export type SeriesInventoryEntry = SeriesInventoryStatus & {
|
|
24
|
+
/** The module's folder under `src/plugins/builtin`. */
|
|
25
|
+
module: string;
|
|
26
|
+
/** What the pane draws. */
|
|
27
|
+
chart: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const SERIES_INVENTORY: readonly SeriesInventoryEntry[] = [
|
|
31
|
+
{ module: "chart-composer", chart: "Any ticker field: price, volume, fundamentals, valuation multiples", series: ["field:*", "option:*"] },
|
|
32
|
+
{ module: "chart-composer", chart: "CSV files in the profile's series folder", series: ["user:*"], runtime: true },
|
|
33
|
+
{ module: "ticker-detail", chart: "Price history and the overview's sparklines", series: ["field:market.*"] },
|
|
34
|
+
{ module: "fear-greed", chart: "Fear & Greed index and its seven indicator charts, with their moving averages", series: ["fear-greed:*"] },
|
|
35
|
+
{ module: "volatility", chart: "VIX curve history, the 3M/30D ratio and the cross-asset volatility board", series: ["volatility:*", "fred:VIXCLS", "fred:VXVCLS"] },
|
|
36
|
+
{ module: "iv-history", chart: "A ticker's implied volatility by tenor", series: ["implied-vol:*"] },
|
|
37
|
+
{ module: "realized-vol", chart: "Realized volatility cone and rolling windows", notInCatalog: "derived", reason: "The composer's realized volatility study draws it from any price series." },
|
|
38
|
+
{ module: "vol-surface", chart: "Implied volatility surface by strike and expiry", notInCatalog: "not-a-time-series", reason: "A surface over strike and tenor." },
|
|
39
|
+
{ module: "options-positioning", chart: "Open interest and gamma by strike and expiry", notInCatalog: "not-a-time-series", reason: "Plotted by strike and expiry, not by date." },
|
|
40
|
+
{ module: "options-scenario", chart: "Option payoff by underlying price", notInCatalog: "not-a-time-series", reason: "A payoff curve over prices." },
|
|
41
|
+
{ module: "kelly-sizer", chart: "Position size against win rate", notInCatalog: "account", reason: "Drawn from the inputs typed into the sizer." },
|
|
42
|
+
{ module: "yield-curve", chart: "Treasury curve and each maturity's history", series: ["ust:*", "fred:T10Y2Y", "fred:T10Y3M", "fred:DFII*"] },
|
|
43
|
+
{ module: "yield-curve", chart: "Government curves for Germany, the UK, Japan, Canada and euro AAA", series: ["bond-yield:*"] },
|
|
44
|
+
{ module: "rate-path", chart: "Implied policy path by meeting", notInCatalog: "not-a-time-series", reason: "A path over future meetings; the rates it starts from are FRED series in the catalog." },
|
|
45
|
+
{ module: "money-markets", chart: "Money market rates, bill yields, liquidity and net liquidity", series: ["money-markets:*", "fred:SOFR", "fred:EFFR", "fred:IORB", "fred:OBFR", "fred:DTB*", "fred:RRPONTSYD", "fred:WDTGAL", "fred:WRESBAL", "fred:WALCL"] },
|
|
46
|
+
{ module: "central-bank-rates", chart: "Policy rate history for each central bank", series: ["policy-rate:*"] },
|
|
47
|
+
{ module: "econ", chart: "Release history of each economic calendar event", series: ["fred:*"] },
|
|
48
|
+
{ module: "econ-statistics", chart: "Inflation, labor and growth statistics with their ranges", series: ["fred:CPIAUCNS", "fred:CPILFENS", "fred:PCEPI", "fred:PCEPILFE", "fred:PPIFID", "fred:UNRATE", "fred:PAYEMS", "fred:ICSA", "fred:JTSJOL", "fred:GDPC1", "fred:INDPRO"] },
|
|
49
|
+
{ module: "cpi", chart: "CPI components, month on month and year on year", series: ["fred:CPI*", "fred:CUSR*"] },
|
|
50
|
+
{ module: "market-valuation", chart: "Whole-market valuation ratios against their history", series: ["market-valuation:*"] },
|
|
51
|
+
{ module: "credit-conditions", chart: "Corporate bond spreads by rating", series: ["fred:BAML*"] },
|
|
52
|
+
{ module: "credit-boards", chart: "Index CDS (CDX, iTraxx) and sovereign 5Y CDS", series: ["cdx:*", "sovereign-cds:*"] },
|
|
53
|
+
{ module: "cds", chart: "A company's 5Y CDS spread", series: ["cds:*"] },
|
|
54
|
+
{ module: "credit-documents", chart: "Principal due by year", notInCatalog: "not-a-time-series", reason: "A maturity schedule, not a history." },
|
|
55
|
+
{ module: "debt-maturities", chart: "A company's principal and the share due soon, across annual filings", series: ["debt-maturities:*"] },
|
|
56
|
+
{ module: "debt-maturities", chart: "A company's maturity wall", notInCatalog: "not-a-time-series", reason: "A schedule by maturity year from one filing; its total and near-term shares across filings are in the catalog." },
|
|
57
|
+
{ module: "doe", chart: "Weekly oil and gas inventories against their five-year range", series: ["doe:*"] },
|
|
58
|
+
{ module: "cot", chart: "Net positioning by trader class, over the front-month price", series: ["cot:*"] },
|
|
59
|
+
{ module: "futures", chart: "Front-month futures board, charted from the board", series: ["fut:*"] },
|
|
60
|
+
{ module: "futures-curve", chart: "Futures curve by contract month", notInCatalog: "not-a-time-series", reason: "Plotted by delivery month; each front month is in the catalog as FUT:code." },
|
|
61
|
+
{ module: "crypto-board", chart: "Price sparklines for the large coins", series: ["crypto:*"] },
|
|
62
|
+
{ module: "perps", chart: "Perpetual funding, open interest, premium and long/short account share", series: ["perps:*"] },
|
|
63
|
+
{ module: "perps", chart: "Perpetual mark price", notInCatalog: "not-yet", reason: "The pair's price is in the catalog; the perpetual's own mark price could be a crypto series." },
|
|
64
|
+
{ module: "short-interest", chart: "A ticker's short interest and days to cover", series: ["short-interest:*"] },
|
|
65
|
+
{ module: "short-volume", chart: "A ticker's daily short volume ratio", series: ["short-volume:*"] },
|
|
66
|
+
{ module: "social-mentions", chart: "A ticker's daily posts", series: ["social-mentions:*"] },
|
|
67
|
+
{ module: "jobs", chart: "A company's open job postings", series: ["jobs:*"] },
|
|
68
|
+
{ module: "attention", chart: "Research hours on a ticker, hour by hour", series: ["attention:*"] },
|
|
69
|
+
{ module: "company-attention", chart: "A company's weekly open roles and daily app attention score", series: ["hiring:*", "app-attention:*"] },
|
|
70
|
+
{ module: "gpu", chart: "GPU rental list index per model", series: ["gpu:*"] },
|
|
71
|
+
{ module: "gpu", chart: "GPU rental prices per provider listing", notInCatalog: "per-item", reason: "One provider listing each, listed by the server and changing without a release." },
|
|
72
|
+
{ module: "power", chart: "Interconnection queue capacity and project generation", notInCatalog: "per-item", reason: "Per project and per queue filter." },
|
|
73
|
+
{ module: "power", chart: "European day-ahead power price by country", series: ["day-ahead:*"] },
|
|
74
|
+
{ module: "power", chart: "EU carbon allowance (EUA) auction price", series: ["carbon:*"] },
|
|
75
|
+
{ module: "awards", chart: "A company's government award totals by period", series: ["awards:*"] },
|
|
76
|
+
{ module: "company-kpis", chart: "A company's reported operating metrics", notInCatalog: "per-item", reason: "Each company reports its own metrics, with no shared list to register." },
|
|
77
|
+
{ module: "estimate-revisions", chart: "Consensus estimate for one fiscal period over time", notInCatalog: "per-item", reason: "One fiscal period of one company." },
|
|
78
|
+
{ module: "earnings", chart: "Implied and actual moves around past earnings", notInCatalog: "per-item", reason: "One bar per earnings event." },
|
|
79
|
+
{ module: "dividend-yield", chart: "A ticker's trailing 12-month cash dividends", series: ["dividends:*"] },
|
|
80
|
+
{ module: "pe-band", chart: "Price against P/E multiples", notInCatalog: "derived", reason: "The composer charts price and the P/E fields for any ticker." },
|
|
81
|
+
{ module: "research", chart: "Analyst price targets over price", notInCatalog: "per-item", reason: "Targets are dated events on one ticker." },
|
|
82
|
+
{ module: "catalysts", chart: "Clinical trial enrollment", notInCatalog: "per-item", reason: "One trial." },
|
|
83
|
+
{ module: "mna", chart: "Deal spread for one merger", notInCatalog: "per-item", reason: "One deal." },
|
|
84
|
+
{ module: "correlation", chart: "Rolling correlation of two tickers and the matrix", notInCatalog: "derived", reason: "The composer's correlation study draws it for any two series." },
|
|
85
|
+
{ module: "relative-rotation", chart: "Relative strength and momentum against a benchmark", notInCatalog: "derived", reason: "Built from two price series; the rotation plot is not dated." },
|
|
86
|
+
{ module: "seasonality", chart: "Average returns by month and weekday", notInCatalog: "not-a-time-series", reason: "Plotted by calendar month, not by date." },
|
|
87
|
+
{ module: "backtest", chart: "A strategy's equity curve", notInCatalog: "account", reason: "One run of the user's own strategy settings." },
|
|
88
|
+
{ module: "analytics", chart: "Portfolio value, drawdown and factor exposure", notInCatalog: "account", reason: "Built from the user's own portfolio; the factor legs are tickers in the catalog." },
|
|
89
|
+
{ module: "holders", chart: "Holders treemap", notInCatalog: "not-a-time-series", reason: "A treemap of one filing date." },
|
|
90
|
+
{ module: "market-heatmap", chart: "Market heat map", notInCatalog: "not-a-time-series", reason: "A treemap of today's moves." },
|
|
91
|
+
{ module: "portfolio-list", chart: "Portfolio treemap", notInCatalog: "not-a-time-series", reason: "A treemap of current positions." },
|
|
92
|
+
{ module: "world-venue-map", chart: "Chokepoint transits and the map's place series", series: ["geo:*"] },
|
|
93
|
+
];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ApiRequestError } from "../../../api-client/errors";
|
|
2
|
+
|
|
3
|
+
/** A Gloom Cloud refusal the reader can act on: signed out, an unverified email, or no Pro plan. */
|
|
4
|
+
export type CloudDeniedStatus = 401 | 402 | 403;
|
|
5
|
+
|
|
6
|
+
/** The account refusal behind a failed request, or null when it failed for another reason. */
|
|
7
|
+
export function cloudDeniedStatus(error: unknown): CloudDeniedStatus | null {
|
|
8
|
+
const status = error instanceof ApiRequestError ? error.status : undefined;
|
|
9
|
+
return status === 401 || status === 402 || status === 403 ? status : null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** What the refused account needs, as a report finishes "JOBS needs ...". */
|
|
13
|
+
export function cloudAccountNeed(status: CloudDeniedStatus): string {
|
|
14
|
+
return status === 401 ? "sign-in" : status === 403 ? "a verified email" : "Gloom Pro";
|
|
15
|
+
}
|
|
@@ -12,7 +12,7 @@ import { requestAccountManagementTab } from "../account-management/navigation";
|
|
|
12
12
|
import { resolvePlanAccess, usePlanAccess, type PlanAccess } from "../../../api-client/plan-access";
|
|
13
13
|
import { useViewport } from "../../../react/input";
|
|
14
14
|
import { useOptionalDialog } from "../../../ui/dialog";
|
|
15
|
-
import { promptCloudUpgrade } from "
|
|
15
|
+
import { promptCloudUpgrade } from "../../../account/upgrade-dialog";
|
|
16
16
|
|
|
17
17
|
const CLOUD_UPGRADE_URL = "https://gloom.sh/cloud?upgrade=pro";
|
|
18
18
|
|
|
@@ -3,9 +3,17 @@ import { usePluginPaneState } from "../../../public/react";
|
|
|
3
3
|
import { usePaneInstance } from "../../../state/app/context";
|
|
4
4
|
import type { PaneTemplateDef, PaneTemplateInstanceConfig } from "../../../types/plugin";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* A command's request (a market, a record), stamped so a later command can ask again: a pane the command reuses
|
|
8
|
+
* sees the newer stamp even when it asks for the same thing.
|
|
9
|
+
*/
|
|
10
|
+
export function commandRequestParams(params: Record<string, string>): Record<string, string> {
|
|
11
|
+
return { ...params, tabAt: String(Date.now()) };
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
/** A command's request to show one tab, stamped so a later command can ask again. */
|
|
7
15
|
export function commandTabParams(tab: string, params?: Record<string, string>): Record<string, string> {
|
|
8
|
-
return { ...(params ?? {}), tab
|
|
16
|
+
return commandRequestParams({ ...(params ?? {}), tab });
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
/** The template's pane, with the command's tab written onto the instance. */
|
|
@@ -26,26 +34,36 @@ export function withCommandTab(template: PaneTemplateDef, tab: string): PaneTemp
|
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
/**
|
|
29
|
-
*
|
|
30
|
-
* newer command arrives.
|
|
31
|
-
* around a nested tab, are ignored.
|
|
37
|
+
* A value a command asked this pane to show, kept in pane state like a choice made in the pane: the stored
|
|
38
|
+
* choice wins until a newer command arrives. `read` takes the value from the command's params, null when the
|
|
39
|
+
* command names none. Another pane's params, such as Ticker Research around a nested tab, are ignored.
|
|
32
40
|
*/
|
|
33
|
-
export function
|
|
41
|
+
export function useCommandValue<T>(
|
|
34
42
|
paneId: string,
|
|
35
43
|
stateKey: string,
|
|
36
|
-
|
|
44
|
+
read: (params: Readonly<Record<string, string>>) => T | null,
|
|
37
45
|
fallback: T,
|
|
38
46
|
): [T, (next: T) => void] {
|
|
39
47
|
const instance = usePaneInstance();
|
|
40
48
|
const params = instance?.paneId === paneId ? instance.params : undefined;
|
|
41
|
-
const requested = params
|
|
49
|
+
const requested = params ? read(params) : null;
|
|
42
50
|
const requestAt = params?.tabAt ?? "";
|
|
43
|
-
const [
|
|
51
|
+
const [value, setValue] = usePluginPaneState<T>(stateKey, requested ?? fallback);
|
|
44
52
|
const seen = useRef(requestAt);
|
|
45
53
|
useEffect(() => {
|
|
46
|
-
if (
|
|
54
|
+
if (requested === null || requestAt === seen.current) return;
|
|
47
55
|
seen.current = requestAt;
|
|
48
|
-
|
|
49
|
-
}, [requestAt, requested,
|
|
50
|
-
return [
|
|
56
|
+
setValue(requested);
|
|
57
|
+
}, [requestAt, requested, setValue]);
|
|
58
|
+
return [value, setValue];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The tab a command asked this pane to show, one of `tabs`. */
|
|
62
|
+
export function useCommandTab<T extends string>(
|
|
63
|
+
paneId: string,
|
|
64
|
+
stateKey: string,
|
|
65
|
+
tabs: readonly T[],
|
|
66
|
+
fallback: T,
|
|
67
|
+
): [T, (next: T) => void] {
|
|
68
|
+
return useCommandValue<T>(paneId, stateKey, (params) => (tabs as readonly string[]).includes(params.tab ?? "") ? params.tab as T : null, fallback);
|
|
51
69
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { EarningsDateStatus, EarningsEpsBasis } from "../../../types/financials";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How every earnings surface (ERN, EE, the corporate-actions events and
|
|
5
|
+
* their headless rows) reads and names a reported quarter's EPS basis and a
|
|
6
|
+
* report date's status. Gloom Cloud resolves one figure per quarter; this
|
|
7
|
+
* keeps the panes from naming it differently.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const BASES: ReadonlySet<string> = new Set<EarningsEpsBasis>(["gaap", "adjusted"]);
|
|
11
|
+
const STATUSES: ReadonlySet<string> = new Set<EarningsDateStatus>(["reported", "confirmed", "projected"]);
|
|
12
|
+
|
|
13
|
+
/** A server value read defensively: anything unrecognised is an unknown basis. */
|
|
14
|
+
export function earningsEpsBasis(value: unknown): EarningsEpsBasis | null {
|
|
15
|
+
return typeof value === "string" && BASES.has(value) ? value as EarningsEpsBasis : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function earningsDateStatus(value: unknown): EarningsDateStatus | null {
|
|
19
|
+
return typeof value === "string" && STATUSES.has(value) ? value as EarningsDateStatus : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The per-ticker calendar flags an estimated date; it says nothing about a date it does not flag. */
|
|
23
|
+
export function dateStatusFromEstimateFlag(isDateEstimate: boolean | null | undefined): EarningsDateStatus | null {
|
|
24
|
+
return isDateEstimate === true ? "projected" : isDateEstimate === false ? "confirmed" : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type EpsBasisName = "GAAP" | "adjusted" | "unknown";
|
|
28
|
+
|
|
29
|
+
/** What the basis names mean, in every report's metadata. */
|
|
30
|
+
export const EPS_BASIS_NOTE = "One reported EPS per quarter. GAAP: the quarter's diluted statement EPS. adjusted: the consensus-basis figure the estimate is measured against, which leaves out items the statements include. unknown: no statement on a comparable share basis to tell.";
|
|
31
|
+
|
|
32
|
+
/** The basis as rows, exports and tools name it. */
|
|
33
|
+
export function epsBasisName(basis: EarningsEpsBasis | null): EpsBasisName {
|
|
34
|
+
return basis === "gaap" ? "GAAP" : basis === "adjusted" ? "adjusted" : "unknown";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The basis in a table cell or a detail line. */
|
|
38
|
+
export function epsBasisShort(basis: EarningsEpsBasis | null): string {
|
|
39
|
+
return basis === "gaap" ? "GAAP" : basis === "adjusted" ? "adj" : "?";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Actual over estimate minus one, against the estimate's size so a negative estimate reads the right way. */
|
|
43
|
+
export function epsSurprise(actual: number | null | undefined, estimate: number | null | undefined): number | null {
|
|
44
|
+
if (actual == null || estimate == null || estimate === 0) return null;
|
|
45
|
+
return (actual - estimate) / Math.abs(estimate);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A fiscal quarter end month (YYYY-MM) holds a period end in that month, or a 52/53-week end a few days either side. */
|
|
49
|
+
export function inFiscalMonth(periodEnd: string | null | undefined, fiscalPeriod: string | null | undefined): boolean {
|
|
50
|
+
const month = /^(\d{4})-(\d{2})$/.exec(fiscalPeriod ?? "");
|
|
51
|
+
const end = Date.parse(`${periodEnd ?? ""}T00:00:00Z`);
|
|
52
|
+
if (!month || !Number.isFinite(end)) return false;
|
|
53
|
+
const monthEnd = Date.UTC(Number(month[1]), Number(month[2]), 0);
|
|
54
|
+
return end >= monthEnd - 35 * 86_400_000 && end <= monthEnd + 10 * 86_400_000;
|
|
55
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { apiClient } from "../../../api-client";
|
|
2
|
+
import { loadCachedFredSeries } from "../../../sources/gloomberb-cloud/fred-series";
|
|
3
|
+
|
|
4
|
+
/** A FRED series from `start` on, oldest first, through the shared FRED cache. */
|
|
5
|
+
export async function loadFredPoints(seriesId: string, start?: Date): Promise<{
|
|
6
|
+
points: Array<{ date: string; value: number | null }>;
|
|
7
|
+
stale: boolean;
|
|
8
|
+
refreshError?: string;
|
|
9
|
+
}> {
|
|
10
|
+
const startDate = start ? start.toISOString().slice(0, 10) : "1900-01-01";
|
|
11
|
+
const result = await loadCachedFredSeries(
|
|
12
|
+
{ seriesId, startDate, sortOrder: "asc" },
|
|
13
|
+
() => apiClient.getCloudFredSeries(seriesId, { startDate, sortOrder: "asc" }),
|
|
14
|
+
);
|
|
15
|
+
return {
|
|
16
|
+
points: (result.data.observations ?? []).map((row) => ({ date: row.date, value: row.value })),
|
|
17
|
+
stale: result.stale,
|
|
18
|
+
...(result.refreshError ? { refreshError: result.refreshError } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the free preview of a Pro function says in place of a bare "requires
|
|
3
|
+
* Gloom Pro": what the free rows are, what Pro adds and when its history
|
|
4
|
+
* starts. Each clause comes from the response; one the response cannot back
|
|
5
|
+
* is left out rather than guessed. The line names Gloom Pro, so reports print
|
|
6
|
+
* it as the lock it is (under "Pro") and a bot-safe check still calls it one.
|
|
7
|
+
*/
|
|
8
|
+
export interface FreePreviewNote {
|
|
9
|
+
/** What the free rows are, after "Free shows": `3 of 6 KPI values`, `the 3 latest awards`. */
|
|
10
|
+
shows: string;
|
|
11
|
+
/** What Pro adds, after "Gloom Pro adds": `the other 3`. Left out, the line says "the rest". */
|
|
12
|
+
adds?: string | null;
|
|
13
|
+
/** The first day Pro's history covers, as YYYY-MM-DD or an ISO instant. */
|
|
14
|
+
historyFrom?: string | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
18
|
+
|
|
19
|
+
/** "1 Oct 2024", the way report lines write a day; null for anything that is not a date. */
|
|
20
|
+
function day(value: string | null | undefined): string | null {
|
|
21
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value ?? "");
|
|
22
|
+
if (!match) return null;
|
|
23
|
+
const date = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])));
|
|
24
|
+
if (date.toISOString().slice(0, 10) !== match[0]) return null;
|
|
25
|
+
return `${date.getUTCDate()} ${MONTHS[date.getUTCMonth()]} ${date.getUTCFullYear()}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** "Free shows 3 of 6 KPI values. Gloom Pro adds the other 3, with history from 31 Dec 2024." */
|
|
29
|
+
export function freePreviewNote({ shows, adds, historyFrom }: FreePreviewNote): string {
|
|
30
|
+
const since = day(historyFrom);
|
|
31
|
+
return `Free shows ${shows}. Gloom Pro adds ${adds?.trim() || "the rest"}${since ? `, with history from ${since}` : ""}.`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** "3 awards", "1 award", "no earnings calls": a count as a sentence says it. */
|
|
35
|
+
export function countOf(count: number, singular: string, plural = `${singular}s`): string {
|
|
36
|
+
return count === 0 ? `no ${plural}` : `${count.toLocaleString("en-US")} ${count === 1 ? singular : plural}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* "the preview can't filter by ticker", "... by ticker or country": the same
|
|
41
|
+
* words wherever a preview shows the same rows whatever was asked for.
|
|
42
|
+
*/
|
|
43
|
+
export function previewCantFilter(filters: readonly string[]): string {
|
|
44
|
+
const names = [...new Set(filters)];
|
|
45
|
+
if (!names.length) return "the preview can't filter";
|
|
46
|
+
return `the preview can't filter by ${names.length === 1 ? names[0] : `${names.slice(0, -1).join(", ")} or ${names.at(-1)}`}`;
|
|
47
|
+
}
|