gloomberb 0.18.3 → 0.18.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/patches/electrobun@1.18.1.patch +32 -1
- package/src/account/auth-model.ts +7 -3
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +11 -6
- package/src/api-client/catalysts.ts +2 -1
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +98 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +182 -16
- package/src/api-client/live-scan.ts +91 -0
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +18 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +224 -26
- package/src/api-client/research-activity.ts +3 -10
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +96 -2
- package/src/app/keybindings/index.ts +3 -0
- package/src/app/keybindings/labels.ts +18 -1
- package/src/app/keybindings/resolve.ts +14 -0
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/broker-import.ts +43 -26
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +9 -2
- package/src/cli/commands/keybindings.ts +25 -2
- package/src/cli/commands/market.ts +1177 -278
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-chain.ts +59 -3
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +222 -61
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +82 -46
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +194 -48
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +21 -3
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +38 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +113 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +226 -50
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +123 -27
- package/src/cli/listing-arg.ts +316 -46
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +193 -30
- package/src/cli/pane-functions/function-help.ts +76 -30
- package/src/cli/pane-functions/headless.ts +59 -12
- package/src/cli/pane-functions/index.ts +28 -19
- package/src/cli/pane-functions/market-session.ts +15 -5
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +10 -6
- package/src/cli/pane-functions/resolver.ts +64 -11
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +45 -4
- package/src/cli/report-tables.ts +75 -19
- package/src/cli/restore-plugins.ts +42 -15
- package/src/cli/result.ts +164 -23
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +395 -20
- package/src/components/chart/composite/format.ts +27 -0
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +7 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +314 -13
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/range-statistics.ts +62 -0
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +20 -4
- package/src/components/chart/composite/series-axis-tags.tsx +16 -9
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +17 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/panel/prompt-binding.ts +0 -8
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/alert.ts +1 -1
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +33 -46
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/index.tsx +1 -0
- package/src/components/layout/pane/footer/model.ts +38 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-frame.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +10 -2
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +6 -4
- package/src/core/state/app/state.ts +9 -0
- package/src/core/state/app/types.ts +3 -0
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +123 -0
- package/src/docs/snapshot.json +422 -112
- package/src/i18n/es.ts +30 -13
- package/src/i18n/ja.ts +30 -13
- package/src/i18n/ko.ts +30 -13
- package/src/i18n/zh-cn.ts +30 -13
- package/src/i18n/zh-tw.ts +30 -13
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/coordinator/financials.ts +10 -2
- package/src/market-data/coordinator/index.ts +3 -1
- package/src/market-data/coordinator/quotes.ts +4 -2
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +81 -11
- package/src/market-data/market/dated-previous-close.ts +203 -0
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/futures-week.ts +68 -0
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/status.ts +16 -4
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/options-alternatives.ts +60 -0
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +25 -3
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +7 -2
- package/src/market-data/selectors.ts +3 -0
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/notifications/notification-log.ts +6 -4
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +34 -20
- package/src/plugins/builtin/alerts/calendar-events.ts +429 -0
- package/src/plugins/builtin/alerts/cli.ts +533 -85
- package/src/plugins/builtin/alerts/command.ts +12 -10
- package/src/plugins/builtin/alerts/constants.ts +1 -1
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +119 -0
- package/src/plugins/builtin/alerts/format.ts +10 -3
- package/src/plugins/builtin/alerts/headless.ts +107 -41
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +92 -0
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +107 -30
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/live.ts +3 -3
- package/src/plugins/builtin/alerts/metric-command.ts +61 -0
- package/src/plugins/builtin/alerts/metric-data.ts +70 -0
- package/src/plugins/builtin/alerts/metric-model.ts +175 -0
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
- package/src/plugins/builtin/alerts/pane.tsx +130 -49
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +38 -12
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/alerts/types.ts +3 -0
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +13 -8
- package/src/plugins/builtin/backtest/pane.tsx +9 -4
- package/src/plugins/builtin/backtest/presets.ts +29 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +24 -14
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +18 -3
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +66 -24
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +19 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +83 -10
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +111 -24
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +2 -2
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +51 -5
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +4 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +3 -2
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +7 -10
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -3
- package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -0
- package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +9 -4
- package/src/plugins/builtin/chart-composer/formula.ts +71 -18
- package/src/plugins/builtin/chart-composer/headless-schema.ts +42 -29
- package/src/plugins/builtin/chart-composer/headless.ts +266 -37
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +144 -30
- package/src/plugins/builtin/chart-composer/presets.ts +50 -15
- package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +31 -28
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +44 -31
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/command-suggestions.ts +92 -0
- package/src/plugins/builtin/chat/content/composer.tsx +13 -6
- package/src/plugins/builtin/chat/content/footer.tsx +6 -3
- package/src/plugins/builtin/chat/content/index.tsx +51 -22
- package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
- package/src/plugins/builtin/chat/index.tsx +23 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
- package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
- package/src/plugins/builtin/chat/pane-links/commands.ts +265 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
- package/src/plugins/builtin/chat/pane-links/open.ts +9 -2
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/plugin.tsx +1 -1
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +144 -27
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/figures.ts +72 -0
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +144 -27
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +34 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +87 -28
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +104 -0
- package/src/plugins/builtin/econ-statistics/view.ts +19 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +47 -12
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/charts.tsx +2 -2
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +20 -1
- package/src/plugins/builtin/exposure/pane.tsx +10 -5
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/index.tsx +1 -0
- package/src/plugins/builtin/futures/model.ts +12 -10
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +3 -3
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +20 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +37 -16
- package/src/plugins/builtin/fx-matrix/index.tsx +25 -13
- package/src/plugins/builtin/fx-matrix/live-legs.ts +34 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +7 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +51 -13
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/footer.ts +2 -2
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/breadth-pane.tsx +81 -0
- package/src/plugins/builtin/members/client.ts +19 -4
- package/src/plugins/builtin/members/headless.ts +24 -10
- package/src/plugins/builtin/members/index.tsx +9 -9
- package/src/plugins/builtin/members/model.ts +23 -4
- package/src/plugins/builtin/members/pane.tsx +31 -14
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/analytics.ts +26 -2
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +5 -2
- package/src/plugins/builtin/options/strike-window.ts +2 -1
- package/src/plugins/builtin/options/table.ts +1 -7
- package/src/plugins/builtin/options/view.tsx +30 -13
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-positioning/client.ts +19 -0
- package/src/plugins/builtin/options-positioning/headless.ts +54 -14
- package/src/plugins/builtin/options-positioning/index.tsx +3 -3
- package/src/plugins/builtin/options-positioning/model.ts +47 -8
- package/src/plugins/builtin/options-positioning/pane.tsx +68 -38
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +14 -9
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +168 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +49 -26
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +54 -22
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +7 -4
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/rate-path/pane.tsx +2 -2
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +80 -13
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/feed.ts +2 -2
- package/src/plugins/builtin/scanner/index.ts +24 -1
- package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
- package/src/plugins/builtin/scanner/live-feed.ts +168 -0
- package/src/plugins/builtin/scanner/live-headless.ts +114 -0
- package/src/plugins/builtin/scanner/live-model.ts +351 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
- package/src/plugins/builtin/scanner/live-track.ts +186 -0
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +3 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/macro-releases.ts +65 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +8 -2
- package/src/plugins/builtin/shared/volatility/pricing.ts +7 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +11 -6
- package/src/plugins/builtin/themes/model.ts +15 -5
- package/src/plugins/builtin/themes/pane.tsx +27 -8
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +14 -4
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
- package/src/plugins/builtin/vol-surface/client.ts +7 -4
- package/src/plugins/builtin/vol-surface/headless.ts +71 -13
- package/src/plugins/builtin/vol-surface/index.tsx +2 -2
- package/src/plugins/builtin/vol-surface/model.ts +26 -9
- package/src/plugins/builtin/vol-surface/pane.tsx +44 -7
- package/src/plugins/builtin/vol-surface/tables.ts +31 -3
- package/src/plugins/builtin/volatility/dvol.ts +46 -0
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/volatility/pane.tsx +2 -2
- package/src/plugins/builtin/volatility/series.ts +26 -0
- package/src/plugins/builtin/world-indices/footer.ts +1 -1
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +15 -9
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +15 -13
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +15 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/app-services.ts +1 -7
- package/src/renderers/browser/config-host.ts +5 -55
- package/src/renderers/browser/main.tsx +30 -60
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +70 -3
- package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +36 -2
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/app-name.ts +17 -0
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/opentui/toast-host.tsx +71 -43
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +16 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/batches.ts +10 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +58 -15
- package/src/sources/provider-router/index.ts +146 -10
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/sources/provider-router/search.ts +13 -2
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/app/context/index.tsx +3 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/auth-transition.ts +19 -9
- package/src/sync/baseline.ts +10 -4
- package/src/sync/controller.ts +67 -17
- package/src/sync/core-contributors.ts +46 -14
- package/src/sync/react.ts +4 -1
- package/src/sync/types.ts +3 -0
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/telemetry/usage-counts.ts +0 -18
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +11 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/company-name.ts +59 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-venues.ts +23 -0
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/bare-symbol.ts +36 -0
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +111 -33
- package/src/tickers/search/ranking.ts +64 -5
- package/src/tickers/search/types.ts +5 -0
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +315 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/daily-valuation.ts +62 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/field-catalog.ts +1 -3
- package/src/time-series/forward-valuation.ts +32 -0
- package/src/time-series/fundamentals.ts +173 -10
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/hooks.ts +1 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/price-units.ts +72 -2
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +161 -0
- package/src/time-series/resolve.ts +185 -1587
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +242 -0
- package/src/time-series/spec.ts +13 -7
- package/src/time-series/studies.ts +377 -82
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/transforms.ts +1 -0
- package/src/time-series/types.ts +34 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/time-series/valuation-releases.ts +39 -0
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +23 -1
- package/src/types/desktop-window.ts +2 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +145 -8
- package/src/types/headless.ts +117 -9
- package/src/types/instrument.ts +6 -0
- package/src/types/plugin.ts +66 -9
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +180 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +89 -5
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +86 -0
- package/src/utils/option-expiry.ts +186 -7
- package/src/utils/options.ts +10 -0
- package/src/utils/plugin-proxy-hosts.json +1 -0
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +23 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
- package/src/renderers/browser/first-screen.ts +0 -193
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
2
|
+
import type { ChartSeriesSpec, ChartSpec, ChartStudySpec } from "../../../time-series/types";
|
|
3
|
+
import { isLeverageFactor } from "../../../time-series/leverage";
|
|
4
|
+
import { priceComparisonSeriesIds } from "../../../time-series/price-comparison";
|
|
5
|
+
import { isUsListingExchange, parsePublicTickerKey } from "../../../utils/exchanges";
|
|
6
|
+
import { MAX_CHART_COMPOSER_SERIES } from "./chart-spec";
|
|
7
|
+
import { buildSeriesSpec, reconcilePanels } from "./chart-spec-edit";
|
|
8
|
+
import { normalizeInstrument } from "./series-expression";
|
|
9
|
+
|
|
10
|
+
/** A fund's daily objective as CMP draws it: `factor` times the index fund `proxy` each session. */
|
|
11
|
+
export interface DailyObjective {
|
|
12
|
+
factor: number;
|
|
13
|
+
proxy: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** What CMP needs of a fund's facts: a daily objective with an index fund to draw it from. */
|
|
17
|
+
export interface LeverageFacts {
|
|
18
|
+
leverage?: { value: number; reset: string; proxy: { ticker: string } | null } | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function dailyObjective(facts: LeverageFacts | null | undefined): DailyObjective | null {
|
|
22
|
+
const leverage = facts?.leverage;
|
|
23
|
+
if (!leverage || leverage.reset !== "daily" || !isLeverageFactor(leverage.value) || !leverage.proxy?.ticker) return null;
|
|
24
|
+
return { factor: leverage.value, proxy: leverage.proxy.ticker.toUpperCase() };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const LEVERAGE_STUDY_PREFIX = "leverage:";
|
|
28
|
+
const DECAY_STUDY_PREFIX = "leverage-decay:";
|
|
29
|
+
|
|
30
|
+
/** The bare ticker a compared leg is of (`TQQQ` for TQQQ:NASDAQ). */
|
|
31
|
+
function legTicker(series: ChartSeriesSpec): string | null {
|
|
32
|
+
return series.source.kind === "security" ? parsePublicTickerKey(series.source.instrument.symbol).symbol.toUpperCase() : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A ticker the fund facts read: US-listed, as its symbol is written there (SPY, BRK.B). */
|
|
36
|
+
const US_FUND_TICKER = /^[A-Z][A-Z0-9]{0,5}(?:\.[A-Z])?$/;
|
|
37
|
+
|
|
38
|
+
/** The US-listed tickers of a price comparison, whose facts can say they are leveraged funds. */
|
|
39
|
+
export function comparedFundTickers(spec: ChartSpec): string[] {
|
|
40
|
+
const compared = new Set(priceComparisonSeriesIds(spec) ?? []);
|
|
41
|
+
return [...new Set(spec.series.flatMap((series) => {
|
|
42
|
+
if (!compared.has(series.id) || series.source.kind !== "security") return [];
|
|
43
|
+
const exchange = series.source.instrument.exchange || parsePublicTickerKey(series.source.instrument.symbol).exchange;
|
|
44
|
+
const ticker = legTicker(series);
|
|
45
|
+
return ticker && US_FUND_TICKER.test(ticker) && (!exchange || isUsListingExchange(exchange)) ? [ticker] : [];
|
|
46
|
+
}))];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Whether the chart already draws a fund's objective, as built here or kept from before. */
|
|
50
|
+
function hasLeverageOverlay(spec: ChartSpec): boolean {
|
|
51
|
+
return spec.studies.some((study) => study.kind === "leverage" || study.kind === "leverage-decay");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Whether a report of this chart could draw a daily objective at all: a
|
|
56
|
+
* price comparison without one yet, over daily bars. One session's chart, or
|
|
57
|
+
* bars asked for by the week, month or hour, would only warn that the line
|
|
58
|
+
* needs daily bars, so its legs' facts are not asked for.
|
|
59
|
+
*/
|
|
60
|
+
export function mayDrawDailyObjective(spec: ChartSpec): boolean {
|
|
61
|
+
if (hasLeverageOverlay(spec) || !priceComparisonSeriesIds(spec)) return false;
|
|
62
|
+
if (spec.viewport.range === "1D" && !spec.viewport.dateWindow) return false;
|
|
63
|
+
return spec.viewport.resolution === "auto" || spec.viewport.resolution === "1d";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A price comparison with each leveraged or inverse fund's daily objective
|
|
68
|
+
* drawn beside it: `factor` times its index fund each session, compounded
|
|
69
|
+
* from where the chart compares (3× daily QQQ beside TQQQ), with the index
|
|
70
|
+
* fund added as a leg when the chart has no room for it otherwise, and the
|
|
71
|
+
* fund's decay against that line and against the factor times the index
|
|
72
|
+
* fund's period return in a Decay panel. Any other chart, or a chart that
|
|
73
|
+
* already draws an objective, is returned as it was.
|
|
74
|
+
*/
|
|
75
|
+
export function withLeverageOverlay(spec: ChartSpec, objectives: ReadonlyMap<string, DailyObjective>): ChartSpec {
|
|
76
|
+
const compared = priceComparisonSeriesIds(spec);
|
|
77
|
+
if (!compared || hasLeverageOverlay(spec) || objectives.size === 0) return spec;
|
|
78
|
+
const series = [...spec.series];
|
|
79
|
+
const studies: ChartStudySpec[] = [...spec.studies];
|
|
80
|
+
for (const fund of spec.series.filter((entry) => compared.includes(entry.id))) {
|
|
81
|
+
const objective = objectives.get(legTicker(fund) ?? "");
|
|
82
|
+
if (!objective || fund.source.kind !== "security") continue;
|
|
83
|
+
// A compared leg of the index fund, or the one added for another fund (TQQQ and SQQQ share QQQ).
|
|
84
|
+
let index = series.find((entry) => legTicker(entry) === objective.proxy && (compared.includes(entry.id) || !spec.series.includes(entry)));
|
|
85
|
+
if (!index) {
|
|
86
|
+
const instrument = normalizeInstrument(objective.proxy, true);
|
|
87
|
+
if (!instrument || series.length >= MAX_CHART_COMPOSER_SERIES) continue;
|
|
88
|
+
index = buildSeriesSpec({ kind: "security", ...instrument, fieldId: fund.source.fieldId }, series.length, {
|
|
89
|
+
style: fund.style, transform: fund.transform, axis: fund.axis, panelId: fund.panelId,
|
|
90
|
+
});
|
|
91
|
+
series.push(index);
|
|
92
|
+
}
|
|
93
|
+
const parameters = { factor: objective.factor };
|
|
94
|
+
studies.push(
|
|
95
|
+
{ id: `${LEVERAGE_STUDY_PREFIX}${fund.id}`, kind: "leverage", inputSeriesIds: [index.id], parameters, panelId: fund.panelId, axis: "left" },
|
|
96
|
+
{ id: `${DECAY_STUDY_PREFIX}${fund.id}`, kind: "leverage-decay", inputSeriesIds: [fund.id, index.id], parameters, panelId: "decay", axis: "auto" },
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (studies.length === spec.studies.length) return spec;
|
|
100
|
+
return { ...spec, series, studies, panels: reconcilePanels(spec.panels, series, studies) };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** How long a comparison waits for its legs' fund facts before it is charted without objectives. */
|
|
104
|
+
const DAILY_OBJECTIVES_TIMEOUT_MS = 2_500;
|
|
105
|
+
/** A pane draws its chart meanwhile and adds the objectives when they come. */
|
|
106
|
+
export const LEVERAGE_FACTS_PANE_TIMEOUT_MS = 15_000;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Each compared fund's daily objective, from its facts. A fund whose facts
|
|
110
|
+
* fail to load, or are not in by `timeoutMs`, is charted without one: the
|
|
111
|
+
* comparison never waits long on them. The reads still running then are
|
|
112
|
+
* aborted through the signal `loadFacts` is given, as they are when `signal`
|
|
113
|
+
* (the caller's) aborts.
|
|
114
|
+
*/
|
|
115
|
+
export async function loadDailyObjectives(
|
|
116
|
+
tickers: readonly string[],
|
|
117
|
+
loadFacts: (ticker: string, signal: AbortSignal) => Promise<LeverageFacts | null>,
|
|
118
|
+
{ timeoutMs = DAILY_OBJECTIVES_TIMEOUT_MS, signal }: { timeoutMs?: number; signal?: AbortSignal } = {},
|
|
119
|
+
): Promise<Map<string, DailyObjective>> {
|
|
120
|
+
const objectives = new Map<string, DailyObjective>();
|
|
121
|
+
if (tickers.length === 0) return objectives;
|
|
122
|
+
const deadline = new AbortController();
|
|
123
|
+
const expired = new Promise<null>((resolve) => deadline.signal.addEventListener("abort", () => resolve(null), { once: true }));
|
|
124
|
+
const timer = setTimeout(() => deadline.abort(new DOMException("Fund facts took too long.", "TimeoutError")), timeoutMs);
|
|
125
|
+
const cancel = () => deadline.abort(signal?.reason);
|
|
126
|
+
if (signal?.aborted) cancel();
|
|
127
|
+
else signal?.addEventListener("abort", cancel, { once: true });
|
|
128
|
+
try {
|
|
129
|
+
await Promise.all(tickers.map(async (ticker) => {
|
|
130
|
+
const facts = await Promise.race([loadFacts(ticker, deadline.signal).catch(logFailure("chart-composer.leverage-overlay", "Load chart fund objective failed", null)), expired]);
|
|
131
|
+
const objective = dailyObjective(facts);
|
|
132
|
+
// An index fund charted beside its leveraged fund is not leveraged itself.
|
|
133
|
+
if (objective && objective.proxy !== ticker) objectives.set(ticker, objective);
|
|
134
|
+
}));
|
|
135
|
+
} finally {
|
|
136
|
+
clearTimeout(timer);
|
|
137
|
+
signal?.removeEventListener("abort", cancel);
|
|
138
|
+
// Reads still running are no longer waited for.
|
|
139
|
+
deadline.abort();
|
|
140
|
+
}
|
|
141
|
+
return objectives;
|
|
142
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logFailure } from "../../../utils/log-failure";
|
|
1
2
|
import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../../../utils/financial-statements";
|
|
2
3
|
import { usePaneSharePreparation } from "../../../shares/prepare";
|
|
3
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -26,10 +27,13 @@ import type { PaneProps, TickerResearchTabProps } from "../../../types/plugin";
|
|
|
26
27
|
import type { ChartResolution, TimeRange } from "../../../components/chart/core/types";
|
|
27
28
|
import type { ChartSpec, ResolvedSeries } from "../../../time-series/types";
|
|
28
29
|
import {
|
|
29
|
-
|
|
30
|
+
getSupportedChartBarSizesForViewport,
|
|
30
31
|
isIntradayResolution,
|
|
32
|
+
parseChartBarSize,
|
|
33
|
+
type ChartBarSize,
|
|
31
34
|
type ManualChartResolution,
|
|
32
35
|
} from "../../../time-series/resolution";
|
|
36
|
+
import { futuresSessionOpenMinute } from "../../../market-data/market/trading-sessions";
|
|
33
37
|
import { useResolvedChartSpec } from "../../../time-series/hooks";
|
|
34
38
|
import { shortCompanyName } from "../../../tickers/company-name";
|
|
35
39
|
import { useSeriesListings } from "./series-listings";
|
|
@@ -50,15 +54,19 @@ import {
|
|
|
50
54
|
} from "../../../state/app/context";
|
|
51
55
|
import { colors } from "../../../theme/colors";
|
|
52
56
|
import { isUsListingExchange, parsePublicTickerKey, publicTickerKey } from "../../../utils/exchanges";
|
|
53
|
-
import { isMarketFieldId } from "../../../time-series/field-catalog";
|
|
57
|
+
import { getTimeSeriesField, isMarketFieldId } from "../../../time-series/field-catalog";
|
|
54
58
|
import { isDatasetChart } from "../../../time-series/spec";
|
|
59
|
+
import { seriesMessageName, studyMessageName } from "../../../time-series/series-name";
|
|
55
60
|
import { CHART_COMPOSER_PANE_ID } from "../../../types/config";
|
|
56
61
|
import { useRemoteUiNode } from "../../../remote/semantic-tree";
|
|
57
62
|
import { SeriesEditorDialog } from "./editor";
|
|
58
63
|
import { chartComposerSemanticMetadata } from "./semantic";
|
|
64
|
+
import { comparedFundTickers, LEVERAGE_FACTS_PANE_TIMEOUT_MS, loadDailyObjectives, withLeverageOverlay } from "./leverage-overlay";
|
|
65
|
+
import { loadFundFacts } from "../sec/fund-facts";
|
|
59
66
|
import {
|
|
60
67
|
canToggleChartSeries,
|
|
61
68
|
CHART_INTERACTION_VIEWPORT_SETTING_KEY,
|
|
69
|
+
CHART_LEVERAGE_PENDING_SETTING_KEY,
|
|
62
70
|
CHART_PINNED_MOMENT_SETTING_KEY,
|
|
63
71
|
CHART_SPEC_SETTING_KEY,
|
|
64
72
|
parseChartInteractionViewport,
|
|
@@ -106,11 +114,13 @@ import { buildEmptyChartPreset, buildPriceChartPreset } from "./presets";
|
|
|
106
114
|
import type { ChartInteractionViewport } from "./chart-spec";
|
|
107
115
|
import {
|
|
108
116
|
CHART_FORMULA_OPTIONS,
|
|
117
|
+
CHART_BAR_SIZE_PRESETS,
|
|
109
118
|
CHART_RANGES as RANGES,
|
|
110
|
-
CHART_RESOLUTIONS
|
|
119
|
+
CHART_RESOLUTIONS,
|
|
111
120
|
chartStudyOptionsFor,
|
|
112
121
|
chartStudyPeriodTitle,
|
|
113
122
|
chartStudySettingLabel,
|
|
123
|
+
withChartBarSize,
|
|
114
124
|
} from "./settings";
|
|
115
125
|
import { resolveChartComposerShortcut } from "./shortcuts";
|
|
116
126
|
import { describeChartResolution, formatChartDateWindow, formatChartResolution } from "./viewport-labels";
|
|
@@ -134,6 +144,9 @@ import { CHART_FOLLOW_SERIES_SETTING_KEY, rebindFollowChartSpec, resolveFollowSe
|
|
|
134
144
|
import type { InstrumentRef } from "../../../market-data/request-types";
|
|
135
145
|
|
|
136
146
|
const RANGE_OPTIONS = RANGES.map((range, index) => ({ label: range, value: range, hint: String(index + 1) }));
|
|
147
|
+
const SOURCE_BAR_SIZES = CHART_RESOLUTIONS.filter((value): value is ManualChartResolution => value !== "auto");
|
|
148
|
+
/** The bar size dialog's last choice, which asks for a size to type. */
|
|
149
|
+
const CUSTOM_BAR_SIZE_CHOICE = "custom";
|
|
137
150
|
const AUTO_VIEWPORT_DEBOUNCE_MS = 350;
|
|
138
151
|
/** A load for a moving view that has not answered in this long no longer holds the next one back. */
|
|
139
152
|
const LOAD_AHEAD_TIMEOUT_MS = 4_000;
|
|
@@ -379,28 +392,46 @@ function ChartComposerSurface({
|
|
|
379
392
|
const hasMarketSeries = spec.series.some((entry) => (
|
|
380
393
|
entry.source.kind === "security" && isMarketFieldId(entry.source.fieldId)
|
|
381
394
|
));
|
|
382
|
-
|
|
395
|
+
// Bars built from a future's clock-aligned bars must not straddle its session's open.
|
|
396
|
+
const openMinute = useMemo(() => {
|
|
397
|
+
const listing = spec.series.find((entry) => entry.source.kind === "security" && isMarketFieldId(entry.source.fieldId));
|
|
398
|
+
return listing?.source.kind === "security" ? futuresSessionOpenMinute(listing.source.instrument.symbol, listing.source.instrument.exchange) : null;
|
|
399
|
+
}, [spec.series]);
|
|
400
|
+
// The sizes of `sizes` this chart can draw now, after Auto.
|
|
401
|
+
const availableOf = useCallback((sizes: readonly ChartBarSize[]): ChartResolution[] => {
|
|
383
402
|
if (!resolution.resolutionSupport) {
|
|
384
403
|
if (!hasMarketSeries) return ["auto"];
|
|
385
|
-
if (!resolution.loading) return
|
|
404
|
+
if (!resolution.loading) return ["auto", ...sizes];
|
|
386
405
|
return spec.viewport.resolution === "auto"
|
|
387
406
|
? ["auto"]
|
|
388
407
|
: ["auto", spec.viewport.resolution];
|
|
389
408
|
}
|
|
390
|
-
|
|
409
|
+
return ["auto", ...getSupportedChartBarSizesForViewport(
|
|
391
410
|
spec.viewport.range,
|
|
392
411
|
resolution.resolutionSupport,
|
|
412
|
+
sizes,
|
|
393
413
|
spec.viewport.dateWindow,
|
|
394
|
-
|
|
395
|
-
|
|
414
|
+
openMinute,
|
|
415
|
+
)];
|
|
396
416
|
}, [
|
|
397
417
|
hasMarketSeries,
|
|
418
|
+
openMinute,
|
|
398
419
|
resolution.loading,
|
|
399
420
|
resolution.resolutionSupport,
|
|
400
421
|
spec.viewport.dateWindow,
|
|
401
422
|
spec.viewport.range,
|
|
402
423
|
spec.viewport.resolution,
|
|
403
424
|
]);
|
|
425
|
+
// The bar lists the sizes sources serve, and a built one (4h) while the chart is set to it;
|
|
426
|
+
// the bar size dialog (b) lists the built ones too, and takes any other typed in.
|
|
427
|
+
const availableResolutions = useMemo(
|
|
428
|
+
() => availableOf(withChartBarSize(SOURCE_BAR_SIZES, spec.viewport.resolution)),
|
|
429
|
+
[availableOf, spec.viewport.resolution],
|
|
430
|
+
);
|
|
431
|
+
const dialogResolutions = useMemo(
|
|
432
|
+
() => availableOf(withChartBarSize(CHART_BAR_SIZE_PRESETS, spec.viewport.resolution)),
|
|
433
|
+
[availableOf, spec.viewport.resolution],
|
|
434
|
+
);
|
|
404
435
|
// Auto names the bars it is on, which change as the view moves: a pan back
|
|
405
436
|
// past where a source keeps 30-minute bars charts days instead.
|
|
406
437
|
const autoBars = spec.viewport.resolution === "auto" ? resolution.resolution ?? null : null;
|
|
@@ -415,6 +446,14 @@ function ChartComposerSurface({
|
|
|
415
446
|
const selectedPairStudies = getSelectedPairStudies(spec);
|
|
416
447
|
const viewport = resolution.viewport;
|
|
417
448
|
const baseSeriesIds = useMemo(() => new Set(spec.series.map((series) => series.id)), [spec.series]);
|
|
449
|
+
const rangeStatisticsSeriesId = spec.series.length === 1
|
|
450
|
+
&& spec.series[0]!.source.kind === "security"
|
|
451
|
+
&& spec.series[0]!.source.fieldId.startsWith("valuation.")
|
|
452
|
+
&& spec.series[0]!.source.period === "daily"
|
|
453
|
+
&& resolution.series.find(series => series.id === spec.series[0]!.id)?.nativeFrequency === "daily"
|
|
454
|
+
&& spec.series[0]!.transform === "raw"
|
|
455
|
+
&& spec.series[0]!.visible !== false
|
|
456
|
+
? spec.series[0]!.id : undefined;
|
|
418
457
|
// Hidden series are never loaded, so the resolver has nothing to report for
|
|
419
458
|
// them. Without a placeholder they vanish from the legend entirely and the
|
|
420
459
|
// only way back is the series dialog.
|
|
@@ -422,6 +461,12 @@ function ChartComposerSurface({
|
|
|
422
461
|
// Each security series names its company once, beside its label: "AAPL Price · Apple".
|
|
423
462
|
const named = new Set<string>();
|
|
424
463
|
const resolved = (resolution.legendSeries ?? []).map((entry) => {
|
|
464
|
+
const authored = spec.series.find((series) => series.id === entry.id);
|
|
465
|
+
if (authored?.source.kind === "security" && authored.source.fieldId.startsWith("valuation.")) {
|
|
466
|
+
const field = getTimeSeriesField(authored.source.fieldId);
|
|
467
|
+
return { ...entry, label: authored.label?.trim()
|
|
468
|
+
|| `${authored.source.instrument.symbol} ${field?.shortLabel ?? "Multiple"}` };
|
|
469
|
+
}
|
|
425
470
|
const name = nameSeries ? listings.names.get(entry.id) : undefined;
|
|
426
471
|
const company = name ? shortCompanyName(name) : "";
|
|
427
472
|
if (!company || named.has(company)) return entry;
|
|
@@ -430,7 +475,7 @@ function ChartComposerSurface({
|
|
|
430
475
|
});
|
|
431
476
|
const resolvedIds = new Set(resolved.map((entry) => entry.id));
|
|
432
477
|
const missing = spec.series.filter((entry) => !resolvedIds.has(entry.id));
|
|
433
|
-
if (missing.length === 0) return
|
|
478
|
+
if (missing.length === 0) return resolved;
|
|
434
479
|
const bySpecOrder = new Map(spec.series.map((entry, index) => [entry.id, index] as const));
|
|
435
480
|
return [
|
|
436
481
|
...resolved,
|
|
@@ -474,7 +519,15 @@ function ChartComposerSurface({
|
|
|
474
519
|
() => listingRef.current,
|
|
475
520
|
[freshListing?.seriesId, freshListing?.key, freshListing?.target.symbol, freshListing?.target.exchange],
|
|
476
521
|
);
|
|
522
|
+
// The ticket's levels (its draft and working orders) move through the ticket, which reviews any change.
|
|
523
|
+
const tradeRef = useRef(trade);
|
|
524
|
+
tradeRef.current = trade;
|
|
477
525
|
const editLevels = useCallback((edit: CompositeLevelEdit) => {
|
|
526
|
+
const ticket = tradeRef.current;
|
|
527
|
+
if (ticket?.levels.some((level) => level.id === edit.id)) {
|
|
528
|
+
if (edit.kind === "move") ticket.moveLevel?.(edit.id, edit.value);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
478
531
|
const key = listingRef.current?.key;
|
|
479
532
|
if (!key) return;
|
|
480
533
|
setLevelStore((current: unknown) => {
|
|
@@ -578,7 +631,7 @@ function ChartComposerSurface({
|
|
|
578
631
|
]}
|
|
579
632
|
/>
|
|
580
633
|
),
|
|
581
|
-
}).catch((
|
|
634
|
+
}).catch(logFailure("chart-composer.pane", "Open VWAP anchor choices failed"));
|
|
582
635
|
if (choice === "pick") {
|
|
583
636
|
pickAnchorAfterDialogRef.current = true;
|
|
584
637
|
return { close: true };
|
|
@@ -594,7 +647,7 @@ function ChartComposerSurface({
|
|
|
594
647
|
content: (ctx: PromptContext<string>) => (
|
|
595
648
|
<TextPromptDialog {...ctx} title="Anchor VWAP at" placeholder="2026-09-30 or 2026-09-30 10:00" confirmLabel="Anchor" width={44} />
|
|
596
649
|
),
|
|
597
|
-
}).catch((
|
|
650
|
+
}).catch(logFailure("chart-composer.pane", "Open VWAP date prompt failed"));
|
|
598
651
|
if (!text) return;
|
|
599
652
|
const anchor = parseVwapAnchor(text, anchorInputRef.current);
|
|
600
653
|
if (anchor === null) {
|
|
@@ -661,6 +714,11 @@ function ChartComposerSurface({
|
|
|
661
714
|
},
|
|
662
715
|
onCancel: () => setPickingAnchor(false),
|
|
663
716
|
} : null, [pickingAnchor, updateSpec]);
|
|
717
|
+
// The ticket beside the chart asks for a price: a press on the plot, or Enter at the cursor, sets it.
|
|
718
|
+
const tradeOnChart = !!trade && !!listing && researchTradeMatches(trade, { ...listing.instrument, exchange: listing.target.exchange });
|
|
719
|
+
const pricePick = useMemo(() => tradeOnChart && trade?.picking && trade.finishPick && trade.cancelPick ? {
|
|
720
|
+
label: `set ${trade.picking.label}`, onPick: trade.finishPick, onCancel: trade.cancelPick,
|
|
721
|
+
} : null, [tradeOnChart, trade?.picking, trade?.finishPick, trade?.cancelPick]);
|
|
664
722
|
const formulasDialogRef = useRef<MultiSelectDialogButtonHandle | null>(null);
|
|
665
723
|
const indicatorsDisabled = !isPriceStudyTarget(spec);
|
|
666
724
|
const formulasDisabled = spec.series.filter((series) => series.visible !== false).length < 2;
|
|
@@ -830,7 +888,7 @@ function ChartComposerSurface({
|
|
|
830
888
|
content: (context: PromptContext<ChartSpec | null>) => (
|
|
831
889
|
<SeriesEditorDialog {...context} initialSpec={spec} />
|
|
832
890
|
),
|
|
833
|
-
}).catch((
|
|
891
|
+
}).catch(logFailure("chart-composer.pane", "Open chart series editor failed", null));
|
|
834
892
|
if (next) setSpec(next);
|
|
835
893
|
} finally {
|
|
836
894
|
setInteractionCaptured("prompt", false);
|
|
@@ -871,23 +929,57 @@ function ChartComposerSurface({
|
|
|
871
929
|
content: (context: PromptContext<string>) => (
|
|
872
930
|
<ChoiceDialog
|
|
873
931
|
{...context}
|
|
874
|
-
title="
|
|
932
|
+
title="Bar Size"
|
|
875
933
|
selectedChoiceId={spec.viewport.resolution}
|
|
876
|
-
choices={
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
934
|
+
choices={[
|
|
935
|
+
...dialogResolutions.map((value) => ({
|
|
936
|
+
id: value,
|
|
937
|
+
label: formatChartResolution(value),
|
|
938
|
+
description: describeChartResolution(value),
|
|
939
|
+
})),
|
|
940
|
+
...(hasMarketSeries ? [{ id: CUSTOM_BAR_SIZE_CHOICE, label: "Custom…", description: "Type any number of minutes, hours, days, weeks or months." }] : []),
|
|
941
|
+
]}
|
|
881
942
|
/>
|
|
882
943
|
),
|
|
883
|
-
}).catch((
|
|
884
|
-
if (
|
|
944
|
+
}).catch(logFailure("chart-composer.pane", "Open chart bar size choices failed", ""));
|
|
945
|
+
if (next === CUSTOM_BAR_SIZE_CHOICE) {
|
|
946
|
+
// A row picked with the mouse closes on mousedown; the field opens after the
|
|
947
|
+
// click has placed the focus, or the desktop leaves it on the dialog.
|
|
948
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
949
|
+
const typed = await dialog.prompt<string>({
|
|
950
|
+
content: (ctx: PromptContext<string>) => (
|
|
951
|
+
<TextPromptDialog {...ctx} title="Custom Bar Size" placeholder="10m, 90m, 4h, 2D, 3W, 6mo" confirmLabel="Chart" width={44} />
|
|
952
|
+
),
|
|
953
|
+
}).catch(logFailure("chart-composer.pane", "Open custom chart bar size prompt failed"));
|
|
954
|
+
if (!typed) return;
|
|
955
|
+
const size = parseChartBarSize(typed);
|
|
956
|
+
const count = /^\s*(\d+)\s*M\s*$/.exec(typed)?.[1];
|
|
957
|
+
if (!size) {
|
|
958
|
+
notify({
|
|
959
|
+
body: count
|
|
960
|
+
? `Write ${count}m for ${count} minutes or ${count}mo for ${count} months.`
|
|
961
|
+
: `${typed} is not a bar size. Use a number and a unit: 10m, 4h, 2D, 3W, 6mo; up to a day of minutes or hours, a year of days or weeks, or 12 months.`,
|
|
962
|
+
type: "error",
|
|
963
|
+
});
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
if (!availableOf(withChartBarSize([], size)).includes(size)) {
|
|
967
|
+
notify({ body: `${formatChartResolution(size)} bars are unavailable for this range.`, type: "error" });
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
setResolution(size);
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
if (dialogResolutions.includes(next as ChartResolution)) setResolution(next as ChartResolution);
|
|
885
974
|
} finally {
|
|
886
975
|
setInteractionCaptured("prompt", false);
|
|
887
976
|
}
|
|
888
977
|
}, [
|
|
889
|
-
|
|
978
|
+
availableOf,
|
|
890
979
|
dialog,
|
|
980
|
+
dialogResolutions,
|
|
981
|
+
hasMarketSeries,
|
|
982
|
+
notify,
|
|
891
983
|
setInteractionCaptured,
|
|
892
984
|
setResolution,
|
|
893
985
|
spec.viewport.resolution,
|
|
@@ -923,7 +1015,7 @@ function ChartComposerSurface({
|
|
|
923
1015
|
void openSeriesEditor();
|
|
924
1016
|
return;
|
|
925
1017
|
case "resolution":
|
|
926
|
-
if (
|
|
1018
|
+
if (dialogResolutions.length > 1) void openResolutionPicker();
|
|
927
1019
|
}
|
|
928
1020
|
}, { enabled: focused && !dialogOpen });
|
|
929
1021
|
|
|
@@ -936,13 +1028,13 @@ function ChartComposerSurface({
|
|
|
936
1028
|
const loading = resolution.loading || listings.pending;
|
|
937
1029
|
// A bare code several companies list asks which, as `quote` does, before anything else is said.
|
|
938
1030
|
const statusError = listings.errors[0] ?? resolution.errors[0];
|
|
939
|
-
// A spread or formula error names its legs and their units; the study's
|
|
1031
|
+
// A spread or formula error names its legs and their units; the study's name adds nothing to it.
|
|
940
1032
|
const formulaStudy = spec.studies.find((study) => (study.kind === "spread" || study.kind === "formula")
|
|
941
|
-
&& statusError?.startsWith(`${study
|
|
942
|
-
const statusErrorNotice = formulaStudy ? statusError?.slice(`${formulaStudy
|
|
943
|
-
// Failed series
|
|
944
|
-
const errorSeries = spec.series.find((entry) => statusError?.startsWith(`${entry
|
|
945
|
-
const errorMessage = errorSeries ? statusError?.slice(`${errorSeries
|
|
1033
|
+
&& statusError?.startsWith(`${studyMessageName(study)}: `));
|
|
1034
|
+
const statusErrorNotice = formulaStudy ? statusError?.slice(`${studyMessageName(formulaStudy)}: `.length) : statusError;
|
|
1035
|
+
// Failed series name what was asked for in errors and their display label in warnings.
|
|
1036
|
+
const errorSeries = spec.series.find((entry) => statusError?.startsWith(`${seriesMessageName(entry)}: `));
|
|
1037
|
+
const errorMessage = errorSeries ? statusError?.slice(`${seriesMessageName(errorSeries)}: `.length) : undefined;
|
|
946
1038
|
// The label the resolver wrote its warnings with, before the legend named the company.
|
|
947
1039
|
const errorSeriesLabel = (resolution.legendSeries?.find((entry) => entry.id === errorSeries?.id)
|
|
948
1040
|
?? legendSeries?.find((entry) => entry.id === errorSeries?.id))?.label;
|
|
@@ -965,9 +1057,9 @@ function ChartComposerSurface({
|
|
|
965
1057
|
&& !FORWARD_VALUATION_BASIS_NOTICES.has(warning)
|
|
966
1058
|
&& !duplicateErrorNotices.has(warning) && !comparisonEmptyNotices.has(warning)
|
|
967
1059
|
&& !spec.studies.some((study) => (
|
|
968
|
-
(study.kind === "ratio" && warning.startsWith(`${study
|
|
1060
|
+
(study.kind === "ratio" && warning.startsWith(`${studyMessageName(study)}: ratio inputs use different currencies (`)
|
|
969
1061
|
&& warning.endsWith("); raw values are not FX-converted."))
|
|
970
|
-
|| (study.kind === "correlation" && warning.startsWith(`${study
|
|
1062
|
+
|| (study.kind === "correlation" && warning.startsWith(`${studyMessageName(study)}: correlation mixes `)
|
|
971
1063
|
&& warning.endsWith("; only matching observation times contribute."))
|
|
972
1064
|
))
|
|
973
1065
|
));
|
|
@@ -1192,7 +1284,9 @@ function ChartComposerSurface({
|
|
|
1192
1284
|
onToggleSeries={toggleSeries}
|
|
1193
1285
|
isSeriesToggleable={isSeriesToggleable}
|
|
1194
1286
|
timePick={timePick}
|
|
1287
|
+
pricePick={pricePick}
|
|
1195
1288
|
levels={chartLevels}
|
|
1289
|
+
rangeStatisticsSeriesId={rangeStatisticsSeriesId}
|
|
1196
1290
|
emptyMessage={emptyMessage}
|
|
1197
1291
|
emptyDetail={emptyDetail}
|
|
1198
1292
|
legendAccessory={(
|
|
@@ -1287,6 +1381,26 @@ export function ChartComposerPane({ paneId, focused, width, height }: PaneProps)
|
|
|
1287
1381
|
savedForTarget.current = targetKey;
|
|
1288
1382
|
}
|
|
1289
1383
|
}, [follows, ownedIds, savedIds, setSpec, spec, stored, target, unlinkedFrom, updateSettings]);
|
|
1384
|
+
// A comparison CMP opened draws each leveraged or inverse fund's daily objective once its facts are read.
|
|
1385
|
+
const leveragePending = instance?.settings?.[CHART_LEVERAGE_PENDING_SETTING_KEY] === true;
|
|
1386
|
+
const storedRef = useRef(stored);
|
|
1387
|
+
storedRef.current = stored;
|
|
1388
|
+
useEffect(() => {
|
|
1389
|
+
if (!leveragePending) return;
|
|
1390
|
+
const mounted = new AbortController();
|
|
1391
|
+
// The chart draws meanwhile, so it can wait longer for them than a report does.
|
|
1392
|
+
void loadDailyObjectives(comparedFundTickers(storedRef.current),
|
|
1393
|
+
async (ticker, signal) => (await loadFundFacts(ticker, false, { signal })).payload,
|
|
1394
|
+
{ timeoutMs: LEVERAGE_FACTS_PANE_TIMEOUT_MS, signal: mounted.signal })
|
|
1395
|
+
.then((objectives) => {
|
|
1396
|
+
if (mounted.signal.aborted) return;
|
|
1397
|
+
updateSettings({
|
|
1398
|
+
[CHART_SPEC_SETTING_KEY]: withLeverageOverlay(storedRef.current, objectives),
|
|
1399
|
+
[CHART_LEVERAGE_PENDING_SETTING_KEY]: undefined,
|
|
1400
|
+
});
|
|
1401
|
+
});
|
|
1402
|
+
return () => mounted.abort();
|
|
1403
|
+
}, [leveragePending, updateSettings]);
|
|
1290
1404
|
if (follows && !target && ownedIds.length > 0) {
|
|
1291
1405
|
return <EmptyState title={error ?? "Select a ticker."} />;
|
|
1292
1406
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "../../../time-series/types";
|
|
7
7
|
import type { ChartResolution, TimeRange } from "../../../components/chart/core/types";
|
|
8
8
|
import { MAX_CHART_COMPOSER_SERIES } from "./chart-spec";
|
|
9
|
-
import { appendChartSeries, appendPlacedSeries, buildCustomSeries, buildSeriesSpec, panelsForSeries } from "./chart-spec-edit";
|
|
9
|
+
import { appendChartSeries, appendPlacedSeries, buildCustomSeries, buildSeriesSpec, nextGeneratedPanelId, panelsForSeries } from "./chart-spec-edit";
|
|
10
10
|
import { currencyPairSpelling } from "../../../utils/currency-pair";
|
|
11
11
|
import { dashedCoinPair } from "../../../utils/crypto-pair";
|
|
12
12
|
import {
|
|
@@ -82,21 +82,51 @@ function placeFormulaLeg(formula: ParsedFormula, index: number, series: ChartSer
|
|
|
82
82
|
return mixed && series.panelId === "main" && !formula.legs[index]!.perBarrel ? { ...series, axis: "right" } : series;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* A series the formula is divided or multiplied by (an FX rate) counts
|
|
87
|
+
* something else again: it is drawn in a panel of its own, not on the legs' axes.
|
|
88
|
+
*/
|
|
89
|
+
function placeFormulaFactor(spec: Pick<ChartSpec, "panels" | "series" | "studies">, series: ChartSeriesSpec): ChartSeriesSpec {
|
|
90
|
+
return { ...series, panelId: nextGeneratedPanelId(spec), axis: "auto" };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** A factor's panel is shorter than a series panel, so the legs and the formula keep their room. */
|
|
94
|
+
const FACTOR_PANEL_HEIGHT = 0.2;
|
|
95
|
+
|
|
96
|
+
/** The panels with each new factor's last and short: the formula reads right under its legs. */
|
|
97
|
+
function withFactorPanels(panels: ChartSpec["panels"], factors: readonly ChartSeriesSpec[]): ChartSpec["panels"] {
|
|
98
|
+
const ids = new Set(factors.map((series) => series.panelId));
|
|
99
|
+
return [
|
|
100
|
+
...panels.filter((panel) => !ids.has(panel.id)),
|
|
101
|
+
...panels.filter((panel) => ids.has(panel.id)).map((panel) => ({ ...panel, height: FACTOR_PANEL_HEIGHT })),
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** The study that weighs a formula's legs and scales the sum, charted as the given series, in the Formula panel. */
|
|
86
106
|
function formulaStudy(formula: ParsedFormula, inputSeriesIds: string[]): ChartStudySpec {
|
|
87
107
|
const parameters: ChartStudySpec["parameters"] = { divisor: formula.divisor };
|
|
88
108
|
formula.legs.forEach((leg, index) => {
|
|
89
109
|
parameters[`weight${index + 1}`] = leg.weight;
|
|
90
110
|
if (leg.perBarrel) parameters[`perBarrel${index + 1}`] = 1;
|
|
111
|
+
if (leg.perTonne) parameters[`perTonne${index + 1}`] = leg.perTonne;
|
|
112
|
+
});
|
|
113
|
+
formula.factors.forEach((factor, index) => {
|
|
114
|
+
parameters[`power${formula.legs.length + index + 1}`] = factor.power;
|
|
91
115
|
});
|
|
92
116
|
return { id: FORMULA_STUDY_ID, kind: "formula", inputSeriesIds, parameters, panelId: "formula", axis: "auto" };
|
|
93
117
|
}
|
|
94
118
|
|
|
95
|
-
/** A formula's legs as series, with the study that sums them in the Formula panel. */
|
|
119
|
+
/** A formula's legs and factors as series, with the study that sums them in the Formula panel. */
|
|
96
120
|
function formulaChartPreset(formula: ParsedFormula): ChartSpec {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
121
|
+
const legs = buildCustomSeries([...formula.legs, ...formula.factors].map((entry) => entry.series));
|
|
122
|
+
const series: ChartSeriesSpec[] = [];
|
|
123
|
+
legs.forEach((entry, index) => {
|
|
124
|
+
series.push(index < formula.legs.length
|
|
125
|
+
? placeFormulaLeg(formula, index, entry)
|
|
126
|
+
: placeFormulaFactor({ panels: [], series, studies: [] }, entry));
|
|
127
|
+
});
|
|
128
|
+
const spec = chartSpec(series, { studies: [formulaStudy(formula, series.map((entry) => entry.id))] });
|
|
129
|
+
return { ...spec, panels: withFactorPanels(spec.panels, series.slice(formula.legs.length)) };
|
|
100
130
|
}
|
|
101
131
|
|
|
102
132
|
/**
|
|
@@ -107,17 +137,22 @@ function appendChartFormula(spec: ChartSpec, expression: string): { spec: ChartS
|
|
|
107
137
|
const formula = parseFormulaExpression(expression);
|
|
108
138
|
if (!formula) throw new Error(`"${expression}" is not a formula.`);
|
|
109
139
|
const key = (series: ChartSeriesSpec) => formatSeriesExpression(series).toLowerCase();
|
|
110
|
-
const
|
|
140
|
+
const terms = [...formula.legs, ...formula.factors];
|
|
141
|
+
const legs = terms.map((leg) => key(buildSeriesSpec(leg.series, 0)));
|
|
111
142
|
const missing = legs.filter((leg) => !spec.series.some((series) => key(series) === leg)).length;
|
|
112
143
|
if (spec.series.length + missing > MAX_CHART_COMPOSER_SERIES) {
|
|
113
144
|
throw new Error(`Charts support up to ${MAX_CHART_COMPOSER_SERIES} base series.`);
|
|
114
145
|
}
|
|
115
146
|
let next: ChartSpec = { ...spec, studies: spec.studies.filter((study) => study.id !== FORMULA_STUDY_ID) };
|
|
116
|
-
const
|
|
147
|
+
const placedFactors: ChartSeriesSpec[] = [];
|
|
148
|
+
const inputs = terms.map((leg, index) => {
|
|
117
149
|
const charted = next.series.find((series) => key(series) === legs[index]);
|
|
118
150
|
if (charted) return charted;
|
|
119
151
|
const appended = appendChartSeries(next, leg.series);
|
|
120
|
-
const placed =
|
|
152
|
+
const placed = index < formula.legs.length
|
|
153
|
+
? placeFormulaLeg(formula, index, appended.series)
|
|
154
|
+
: placeFormulaFactor(next, appended.series);
|
|
155
|
+
if (index >= formula.legs.length) placedFactors.push(placed);
|
|
121
156
|
next = { ...appended.spec, series: appended.spec.series.map((series) => series.id === placed.id ? placed : series) };
|
|
122
157
|
return placed;
|
|
123
158
|
});
|
|
@@ -127,7 +162,10 @@ function appendChartFormula(spec: ChartSpec, expression: string): { spec: ChartS
|
|
|
127
162
|
spec: {
|
|
128
163
|
...next,
|
|
129
164
|
studies,
|
|
130
|
-
panels:
|
|
165
|
+
panels: withFactorPanels(
|
|
166
|
+
[...next.panels, ...panelsForSeries(next.series, studies).filter((panel) => !known.has(panel.id))],
|
|
167
|
+
placedFactors,
|
|
168
|
+
),
|
|
131
169
|
},
|
|
132
170
|
series: inputs.at(-1)!,
|
|
133
171
|
};
|
|
@@ -275,11 +313,8 @@ export function buildValuationChartPreset(
|
|
|
275
313
|
const series = buildSeriesSpec(
|
|
276
314
|
{ kind: "security", ...instrument, fieldId: resolvedField },
|
|
277
315
|
index,
|
|
278
|
-
{ style:
|
|
316
|
+
{ style: "line", axis: "left" },
|
|
279
317
|
);
|
|
280
|
-
|
|
281
|
-
// reconstruct, so a quarterly trailing multiple has only its latest few
|
|
282
|
-
// quarters. Quarterly is the series' Period control away.
|
|
283
|
-
return series.source.kind === "security" ? { ...series, source: { ...series.source, period: "annual" } } : series;
|
|
318
|
+
return series.source.kind === "security" ? { ...series, source: { ...series.source, period: "daily" } } : series;
|
|
284
319
|
}));
|
|
285
320
|
}
|