gloomberb 0.18.2 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/patches/electrobun@1.18.1.patch +106 -5
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +99 -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 +24 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +26 -7
- 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/telemetry.ts +17 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/global-shortcuts.ts +1 -16
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/runtime/update.ts +28 -8
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/pane-tabs-allowlist.json +65 -0
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1189 -296
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +272 -70
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +20 -14
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +32 -18
- package/src/cli/issuer-membership.ts +103 -0
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +315 -43
- package/src/cli/name-entries.ts +73 -22
- 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 +77 -20
- package/src/cli/pane-functions/catalog.ts +40 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +12 -8
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +48 -16
- package/src/cli/pane-functions/index.ts +82 -21
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +65 -14
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +190 -27
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +122 -25
- 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 +226 -60
- 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 +387 -21
- package/src/components/chart/composite/drawing-store.ts +26 -6
- package/src/components/chart/composite/interactions.ts +9 -3
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +316 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +19 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/command-items.ts +32 -6
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/data-table/view.tsx +23 -3
- 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 +13 -6
- package/src/components/layout/detached-pane-shell.tsx +1 -0
- package/src/components/layout/floating-pane.tsx +1 -0
- package/src/components/layout/header.tsx +234 -60
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/pane/header.tsx +10 -3
- package/src/components/layout/pane/index.tsx +1 -0
- package/src/components/layout/pane/pane-tabs.tsx +9 -1
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/components/ui/stat-grid.tsx +28 -3
- package/src/components/ui/status.tsx +3 -1
- package/src/core/app-services.ts +4 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +51 -12
- package/src/i18n/ja.ts +51 -12
- package/src/i18n/ko.ts +51 -12
- package/src/i18n/zh-cn.ts +51 -12
- package/src/i18n/zh-tw.ts +51 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +108 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +77 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
- package/src/plugins/builtin/attention/pane.tsx +22 -16
- 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 +12 -9
- package/src/plugins/builtin/backtest/export.ts +1 -1
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
- 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 +34 -18
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/client.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 +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +9 -11
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
- package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
- 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 +89 -31
- 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 +5 -4
- 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 +7 -4
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
- package/src/plugins/builtin/correlation/settings.ts +1 -0
- 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 +7 -5
- 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/credit-documents/pane.tsx +8 -7
- 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/debt-maturities/pane.tsx +4 -3
- 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 +19 -12
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +77 -5
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +34 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +16 -10
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/board.tsx +4 -1
- package/src/plugins/builtin/gpu/changes.tsx +10 -10
- package/src/plugins/builtin/gpu/equities.tsx +4 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/gpu/history.tsx +4 -2
- package/src/plugins/builtin/gpu/pane.tsx +5 -3
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +15 -2
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +48 -8
- 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/thirteenf-match.ts +3 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/base-values.ts +11 -7
- package/src/plugins/builtin/insider/client.ts +3 -0
- package/src/plugins/builtin/insider/headless.ts +20 -7
- package/src/plugins/builtin/insider/index.tsx +17 -8
- package/src/plugins/builtin/insider/issuer.ts +34 -4
- package/src/plugins/builtin/insider/signals-client.ts +3 -3
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/insider/table-model.ts +35 -13
- package/src/plugins/builtin/insider/table.tsx +5 -2
- 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/events.ts +145 -0
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +91 -7
- 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 +14 -8
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +36 -21
- 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 +33 -11
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +50 -15
- package/src/plugins/builtin/notes/export.ts +17 -6
- package/src/plugins/builtin/notes/files.ts +16 -5
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/enrichment-model.ts +10 -9
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/model-spot.ts +70 -4
- package/src/plugins/builtin/options/view.tsx +51 -23
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
- package/src/plugins/builtin/options-positioning/headless.ts +11 -3
- package/src/plugins/builtin/options-positioning/model.ts +24 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
- package/src/plugins/builtin/options-scenario/client.ts +142 -29
- 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 +49 -21
- 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 +22 -10
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +6 -3
- 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 +44 -32
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/seasonality/client.ts +2 -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 +6 -4
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +23 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/shared/volatility/options.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/social-mentions/client.ts +2 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +28 -7
- package/src/plugins/builtin/vol-surface/headless.ts +43 -15
- package/src/plugins/builtin/vol-surface/model.ts +34 -12
- package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
- package/src/plugins/builtin/vol-surface/stored.ts +34 -3
- package/src/plugins/builtin/vol-surface/tables.ts +14 -0
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/desktop/controls.tsx +1 -1
- package/src/renderers/dom/desktop/query-bar.tsx +2 -0
- 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/host/tabs.tsx +16 -5
- package/src/renderers/dom/host/top-surface.ts +127 -0
- package/src/renderers/dom/styles.css +115 -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/core-capabilities.ts +9 -1
- 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/update.ts +210 -30
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +9 -7
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
- 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 +8 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +39 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/index.ts +16 -0
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +21 -4
- package/src/telemetry/update-failures-node.ts +59 -0
- package/src/telemetry/update-failures.ts +307 -0
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +215 -36
- package/src/tickers/company-name.ts +43 -0
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/listing-fate.ts +30 -0
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +20 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +83 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/issuer-listings.ts +28 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/failure.ts +163 -0
- package/src/updater/index.ts +97 -28
- 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-pair.ts +26 -0
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +71 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -5,7 +5,7 @@ import { canonicalExchange } from "../../utils/exchanges";
|
|
|
5
5
|
import { isFiniteNumber } from "../../utils/guards";
|
|
6
6
|
import { formatUtcDayTime } from "../../utils/utc-time";
|
|
7
7
|
import { zonedDateKey } from "../../utils/zoned-date-time";
|
|
8
|
-
import { futuresChangeBasis, isFuturesInstrument } from "../futures-contract";
|
|
8
|
+
import { futuresChangeBasis, futuresSettleText, isFuturesInstrument } from "../futures-contract";
|
|
9
9
|
import { quoteTradingDay } from "../quotes/day-range";
|
|
10
10
|
import { previousPublishedSession } from "./freshness";
|
|
11
11
|
import { getActiveQuoteDisplay, getRegularSessionDisplay, regularSessionDisplayDate } from "./status";
|
|
@@ -65,6 +65,30 @@ function quoteVenue(quote: Quote): string {
|
|
|
65
65
|
return canonicalExchange(quote.listingExchangeName || quote.exchangeName);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* The venue whose calendar an index's sessions follow, where its quote names
|
|
70
|
+
* the index's publisher or feed instead of a venue: the Hang Seng family's
|
|
71
|
+
* HKSE trades HKEX's days, the Nikkei 225's OSAKA JPX's, and the US
|
|
72
|
+
* publishers' the US equity calendar. An index quoted under a venue (KRX, NSE,
|
|
73
|
+
* SSE) is that venue's already.
|
|
74
|
+
*/
|
|
75
|
+
const INDEX_CALENDAR_VENUES: Readonly<Record<string, string>> = {
|
|
76
|
+
HKSE: "HKEX",
|
|
77
|
+
OSAKA: "JPX",
|
|
78
|
+
SNP: "NYSE",
|
|
79
|
+
DJI: "NYSE",
|
|
80
|
+
"NASDAQ GIDS": "NASDAQ",
|
|
81
|
+
"CBOE INDICES": "CBOE",
|
|
82
|
+
"CHICAGO OPTIONS": "CBOE",
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** The venue whose published calendar dates the quote's sessions. */
|
|
86
|
+
function calendarVenue(quote: Quote): string {
|
|
87
|
+
const venue = quoteVenue(quote);
|
|
88
|
+
const index = classifyInstrumentType(quote.instrumentType) === "index" || kindFromListingSyntax(quote.symbol) === "index";
|
|
89
|
+
return (index && INDEX_CALENDAR_VENUES[venue]) || venue;
|
|
90
|
+
}
|
|
91
|
+
|
|
68
92
|
function isCurrencyPair(quote: Quote): boolean {
|
|
69
93
|
return classifyInstrumentType(quote.instrumentType) === "currency"
|
|
70
94
|
|| kindFromListingSyntax(quote.symbol, quote.listingExchangeName || quote.exchangeName) === "currency";
|
|
@@ -93,11 +117,12 @@ function previousIndexSession(quote: Quote, date: string): string | null {
|
|
|
93
117
|
|
|
94
118
|
/**
|
|
95
119
|
* The session before the one a move is dated to: from the venue's published
|
|
96
|
-
* calendar, with the closures in between
|
|
97
|
-
* for
|
|
120
|
+
* calendar, with the closures in between (an index's, the venue whose days it
|
|
121
|
+
* follows); otherwise for an index from its own sessions; for a currency pair
|
|
122
|
+
* the weekday before. Null when nothing dates it.
|
|
98
123
|
*/
|
|
99
124
|
function previousSession(quote: Quote, sessionDate: string): DatedChangeBasis | null {
|
|
100
|
-
const venue =
|
|
125
|
+
const venue = calendarVenue(quote);
|
|
101
126
|
const published = previousPublishedSession(venue, sessionDate);
|
|
102
127
|
if (published) return { kind: "close", date: published.date, venue, closed: published.closed };
|
|
103
128
|
const index = previousIndexSession(quote, sessionDate);
|
|
@@ -110,7 +135,8 @@ function previousSession(quote: Quote, sessionDate: string): DatedChangeBasis |
|
|
|
110
135
|
* What the quote's move is measured from. A coin moves from its previous UTC
|
|
111
136
|
* day's close, the price at 00:00 UTC, unless Gloom Cloud says it moves over
|
|
112
137
|
* the last 24 hours; a perpetual always moves over 24 hours. A future's is the
|
|
113
|
-
* settlement or trade its terms name
|
|
138
|
+
* settlement or trade its terms name, or the close of the trade date before
|
|
139
|
+
* on its venue's holiday calendar (futuresChangeBasis). Anything else is
|
|
114
140
|
* the close of the session before the move's, dated by the venue's calendar;
|
|
115
141
|
* a venue without one has a previous close that is left undated, never
|
|
116
142
|
* guessed. Null for a quote with no move: none reported, or a listing that no
|
|
@@ -127,13 +153,27 @@ export function quoteChangeBasis(
|
|
|
127
153
|
if (isSpotCoin(quote)) return { kind: "utc day" };
|
|
128
154
|
const sessionDate = (session === "active" ? quote.changeSessionDate : regularSessionDisplayDate(quote)) ?? quoteTradingDay(quote);
|
|
129
155
|
if (isFuturesInstrument(quote.symbol, quote.instrumentType)) {
|
|
130
|
-
const basis = futuresChangeBasis(terms ?? { settlement: null }, { ...display, sessionDate });
|
|
156
|
+
const basis = futuresChangeBasis(terms ?? { settlement: null }, { ...display, sessionDate }, quoteVenue(quote));
|
|
131
157
|
return basis ? { kind: basis.kind, date: basis.session } : { kind: "previous close" };
|
|
132
158
|
}
|
|
133
159
|
if (!sessionDate || !ISO_DATE.test(sessionDate)) return { kind: "previous close" };
|
|
134
160
|
return previousSession(quote, sessionDate) ?? { kind: "previous close" };
|
|
135
161
|
}
|
|
136
162
|
|
|
163
|
+
/**
|
|
164
|
+
* A futures quote's Settle line, paired with its Change line: the settlement
|
|
165
|
+
* is shown when it is of the session the move is measured from or a later one,
|
|
166
|
+
* and reads `--` with that session when the terms have not caught up to it
|
|
167
|
+
* (futuresSettleText), so the two lines never name different sessions.
|
|
168
|
+
*/
|
|
169
|
+
export function quoteSettleText(
|
|
170
|
+
quote: Quote | null | undefined,
|
|
171
|
+
terms: NonNullable<QuoteChangeBasisOptions["terms"]> & Parameters<typeof futuresSettleText>[0],
|
|
172
|
+
): string {
|
|
173
|
+
const basis = quoteChangeBasis(quote, { terms });
|
|
174
|
+
return futuresSettleText(terms, quote, basis && "date" in basis ? basis.date : null);
|
|
175
|
+
}
|
|
176
|
+
|
|
137
177
|
/**
|
|
138
178
|
* The exchange-local date of `quote.previousClose`: the session before the
|
|
139
179
|
* one the quote's change is declared for (changeSessionDate), the UTC day
|
|
@@ -146,7 +186,9 @@ export function quotePreviousCloseDate(quote: Quote | null | undefined): string
|
|
|
146
186
|
const sessionDate = quote.changeSessionDate ?? quoteTradingDay(quote);
|
|
147
187
|
if (!sessionDate || !ISO_DATE.test(sessionDate)) return null;
|
|
148
188
|
if (isSpotCoin(quote)) return dayBefore(sessionDate);
|
|
149
|
-
if (isFuturesInstrument(quote.symbol, quote.instrumentType))
|
|
189
|
+
if (isFuturesInstrument(quote.symbol, quote.instrumentType)) {
|
|
190
|
+
return futuresChangeBasis({ settlement: null }, { price: quote.price, change: 0, sessionDate }, quoteVenue(quote))?.session ?? null;
|
|
191
|
+
}
|
|
150
192
|
return previousSession(quote, sessionDate)?.date ?? null;
|
|
151
193
|
}
|
|
152
194
|
|
|
@@ -2,6 +2,7 @@ import type { MarketState, QuoteIndexSession } from "../../types/financials";
|
|
|
2
2
|
import { canonicalExchange, EXCHANGE_TIME_ZONES, isUsListingExchange } from "../../utils/exchanges";
|
|
3
3
|
import { hasPublishedApacCalendar, isPublishedApacClosure } from "../published-apac-sessions";
|
|
4
4
|
import { hasPublishedCnCalendar, isPublishedCnClosure } from "../published-cn-sessions";
|
|
5
|
+
import { hasPublishedFuturesCalendar, isPublishedFuturesClosure, isPublishedFuturesVenue } from "../published-futures-sessions";
|
|
5
6
|
import { hasPublishedJpxCalendar, isPublishedJpxClosure } from "../published-jpx-sessions";
|
|
6
7
|
import { hasPublishedNseCalendar, isPublishedNseClosure } from "../published-nse-sessions";
|
|
7
8
|
import { getPublishedUsEquityCalendarDay, getPublishedUsEquityCalendarYears, getPublishedUsEquitySession } from "../published-us-sessions";
|
|
@@ -275,7 +276,7 @@ function isPublishedClosure(exchange: string, date: string): boolean {
|
|
|
275
276
|
if (exchange === "JPX") return isPublishedJpxClosure(date);
|
|
276
277
|
if (exchange === "NSE" || exchange === "BSE") return isPublishedNseClosure(date);
|
|
277
278
|
if (exchange === "SSE" || exchange === "SZSE") return isPublishedCnClosure(date);
|
|
278
|
-
if (isPublishedApacClosure(exchange, date)) return true;
|
|
279
|
+
if (isPublishedApacClosure(exchange, date) || isPublishedFuturesClosure(exchange, date)) return true;
|
|
279
280
|
return getPublishedUsEquityCalendarDay(exchange, date) === "closed";
|
|
280
281
|
}
|
|
281
282
|
|
|
@@ -284,6 +285,16 @@ export function isTradingWeekday(exchange: string, weekday: number, weekendDays?
|
|
|
284
285
|
return !(weekendDays ?? WEEKEND_DAYS[exchange] ?? DEFAULT_WEEKEND_DAYS).includes(weekday);
|
|
285
286
|
}
|
|
286
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Whether the venue trades on its local `date` (YYYY-MM-DD): a day of its
|
|
290
|
+
* trading week that is not a published closure. A venue without published
|
|
291
|
+
* closures counts every day of its trading week; an unknown venue Monday to
|
|
292
|
+
* Friday.
|
|
293
|
+
*/
|
|
294
|
+
export function isVenueTradingDay(exchange: string | undefined, date: string): boolean {
|
|
295
|
+
return isLocalTradingDay(canonicalExchange(exchange), date);
|
|
296
|
+
}
|
|
297
|
+
|
|
287
298
|
/** `weekendDays` replaces the venue's days off (historySourceWeekendDays). */
|
|
288
299
|
function isLocalTradingDay(exchange: string, date: string, weekendDays?: readonly number[]): boolean {
|
|
289
300
|
const weekday = localWeekday(date);
|
|
@@ -319,6 +330,11 @@ function regularCloseMinutes(exchange: string, date: string): number | undefined
|
|
|
319
330
|
return (weekday == null ? undefined : WEEKDAY_CLOSE_MINUTES[exchange]?.[weekday]) ?? REGULAR_CLOSE_MINUTES[exchange];
|
|
320
331
|
}
|
|
321
332
|
|
|
333
|
+
/** Whether the venue's regular close hour is known, so its sessions end on its own clock rather than at local midnight. */
|
|
334
|
+
export function hasRegularCloseHour(exchange: string | undefined): boolean {
|
|
335
|
+
return REGULAR_CLOSE_MINUTES[canonicalExchange(exchange)] !== undefined;
|
|
336
|
+
}
|
|
337
|
+
|
|
322
338
|
/** The zone a venue's session dates are read in, or null when unknown. */
|
|
323
339
|
export function sessionCalendarTimeZone(exchange: string | undefined): string | null {
|
|
324
340
|
const canonical = canonicalExchange(exchange);
|
|
@@ -487,9 +503,13 @@ export function isRegularSessionTime(
|
|
|
487
503
|
* True when the venue's full-day closures for the year of `date` are
|
|
488
504
|
* published: US venues, JPX, NSE, BSE, SSE, SZSE, KRX, KOSDAQ, TWSE, TPEX,
|
|
489
505
|
* HKEX, SGX, ASX and EGX. Elsewhere a local holiday reads as a trading day.
|
|
506
|
+
* For the futures venues (CME, CBT, NYM, CMX, NYB) a closure is a weekday
|
|
507
|
+
* with no trade date, and a day some of a venue's contracts settled and
|
|
508
|
+
* others did not is unknown.
|
|
490
509
|
*/
|
|
491
510
|
export function hasPublishedSessionCalendar(exchange: string | undefined, date: string): boolean {
|
|
492
511
|
const canonical = canonicalExchange(exchange);
|
|
512
|
+
if (isPublishedFuturesVenue(canonical)) return hasPublishedFuturesCalendar(canonical, date);
|
|
493
513
|
const year = Number(date.slice(0, 4));
|
|
494
514
|
if (canonical === "JPX") return hasPublishedJpxCalendar(year);
|
|
495
515
|
if (canonical === "NSE" || canonical === "BSE") return hasPublishedNseCalendar(year);
|
|
@@ -505,17 +525,22 @@ export function hasPublishedSessionCalendar(exchange: string | undefined, date:
|
|
|
505
525
|
* Mon 19 Oct 2026 lies between Fri 16 and Tue 20 Oct). A `date` that is no
|
|
506
526
|
* session (a quote dated by when it was read, on a Saturday or a holiday) is
|
|
507
527
|
* the latest session on or before it: Friday's move, read on Saturday, is
|
|
508
|
-
* from Thursday's close.
|
|
509
|
-
*
|
|
510
|
-
*
|
|
528
|
+
* from Thursday's close. With `closedDayRollsForward`, a `date` the venue had
|
|
529
|
+
* no session on is instead the next session's: CME Globex trades most US
|
|
530
|
+
* holidays and books those trades on the next trade date, so a future's move
|
|
531
|
+
* dated Memorial Day is Tuesday's, from Friday's settlement. Null for
|
|
532
|
+
* round-the-clock and unknown venues, and when a day the walk passes is in a
|
|
533
|
+
* year whose closures the venue has not published: a holiday there would
|
|
534
|
+
* read as a session.
|
|
511
535
|
*/
|
|
512
536
|
export function previousPublishedSession(
|
|
513
537
|
exchange: string | undefined,
|
|
514
538
|
date: string,
|
|
539
|
+
{ closedDayRollsForward = false }: { closedDayRollsForward?: boolean } = {},
|
|
515
540
|
): { date: string; closed: string[] } | null {
|
|
516
541
|
const canonical = canonicalExchange(exchange);
|
|
517
542
|
const day = isoLocalDateToUtcDay(date);
|
|
518
|
-
if (day == null || ALWAYS_OPEN_EXCHANGES.has(canonical)
|
|
543
|
+
if (day == null || ALWAYS_OPEN_EXCHANGES.has(canonical)) return null;
|
|
519
544
|
let session: number | null = null;
|
|
520
545
|
const closed: string[] = [];
|
|
521
546
|
for (let offset = 0; offset <= SESSION_LOOKBACK_DAYS * 2; offset++) {
|
|
@@ -527,6 +552,10 @@ export function previousPublishedSession(
|
|
|
527
552
|
// First the session the move is from's own day, then the one before it.
|
|
528
553
|
if (session == null) {
|
|
529
554
|
if (open) session = offset;
|
|
555
|
+
else if (offset === 0 && closedDayRollsForward) {
|
|
556
|
+
session = offset;
|
|
557
|
+
closed.push(iso);
|
|
558
|
+
}
|
|
530
559
|
continue;
|
|
531
560
|
}
|
|
532
561
|
if (offset - session > SESSION_LOOKBACK_DAYS) return null;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { calendarMonthsBefore } from "../../utils/calendar-date";
|
|
2
|
+
import { zonedDateKey } from "../../utils/zoned-date-time";
|
|
3
|
+
import { isAlwaysOpenExchange, latestRegularSessionClose, sessionCalendarTimeZone } from "./freshness";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One convention for every period return (CMP, RETURN, the futures board,
|
|
7
|
+
* sector and short-interest boards, the volatility curve's look-backs): a
|
|
8
|
+
* period runs from the close on or before the same calendar date one period
|
|
9
|
+
* before its end, and says so, `from Mon 21 Sep close`. A month before Wed 21
|
|
10
|
+
* Oct is Mon 21 Sep, so 1M is measured from Mon 21 Sep's close; a month
|
|
11
|
+
* before Tue 20 Oct is Sun 20 Sep, so from Fri 18 Sep's close.
|
|
12
|
+
*/
|
|
13
|
+
export type ReturnPeriod = "1W" | "1M" | "3M" | "6M" | "1Y" | "3Y" | "5Y" | "YTD";
|
|
14
|
+
|
|
15
|
+
const PERIOD_MONTHS: Readonly<Record<Exclude<ReturnPeriod, "1W" | "YTD">, number>> = { "1M": 1, "3M": 3, "6M": 6, "1Y": 12, "3Y": 36, "5Y": 60 };
|
|
16
|
+
const PERIODS: ReadonlySet<string> = new Set<ReturnPeriod>(["1W", "1M", "3M", "6M", "1Y", "3Y", "5Y", "YTD"]);
|
|
17
|
+
const DAY_MS = 86_400_000;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* How far before its base day a base close may be: a weekend with the longest
|
|
21
|
+
* closures markets take (Spring Festival put TWSE's previous session twelve
|
|
22
|
+
* days back in February 2026). A close further back is a gap in the history (a
|
|
23
|
+
* halt, a listing that started later), so the period has no base.
|
|
24
|
+
*/
|
|
25
|
+
export const PERIOD_BASE_MAX_GAP_DAYS = 14;
|
|
26
|
+
|
|
27
|
+
/** What a period whose newest point is the session still trading says of that point. */
|
|
28
|
+
export const LATEST_INTRADAY_TEXT = "latest, intraday";
|
|
29
|
+
|
|
30
|
+
export function isReturnPeriod(value: unknown): value is ReturnPeriod {
|
|
31
|
+
return typeof value === "string" && PERIODS.has(value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function shiftDay(day: string, days: number): string {
|
|
35
|
+
return new Date(Date.parse(`${day}T00:00:00Z`) + days * DAY_MS).toISOString().slice(0, 10);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The calendar date a period ending on `endDay` (`YYYY-MM-DD`) is measured
|
|
40
|
+
* from: seven days before for a week, the same day of the month before for a
|
|
41
|
+
* month (31 Mar's is 28 or 29 Feb), and 31 Dec of the year before for YTD.
|
|
42
|
+
*/
|
|
43
|
+
export function periodBaseDay(endDay: string, period: ReturnPeriod): string {
|
|
44
|
+
const day = endDay.slice(0, 10);
|
|
45
|
+
if (period === "YTD") return `${Number(day.slice(0, 4)) - 1}-12-31`;
|
|
46
|
+
if (period === "1W") return shiftDay(day, -7);
|
|
47
|
+
return calendarMonthsBefore(new Date(`${day}T00:00:00Z`), PERIOD_MONTHS[period]).toISOString().slice(0, 10);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The session day of a daily or longer bar stamped at `time`, `YYYY-MM-DD`:
|
|
52
|
+
* a date-only stamp (UTC midnight) is its UTC date; any other is read on the
|
|
53
|
+
* venue's clock, as feeds stamp a JPX bar at 00:00 JST (15:00 UTC the day
|
|
54
|
+
* before) and a European one at local midnight. The UTC date for a venue
|
|
55
|
+
* that trades every day or whose sessions are unknown.
|
|
56
|
+
*/
|
|
57
|
+
export function barSessionDay(time: number, venue?: string): string {
|
|
58
|
+
const utc = new Date(time).toISOString().slice(0, 10);
|
|
59
|
+
if (time % DAY_MS === 0 || !venue || isAlwaysOpenExchange(venue)) return utc;
|
|
60
|
+
const zone = sessionCalendarTimeZone(venue);
|
|
61
|
+
return zone ? zonedDateKey(time, zone) : utc;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The day a bar's close is from, to compare with a base day: a daily bar's own
|
|
66
|
+
* date, a weekly bar's (dated by the Monday its week starts) Friday, or Sunday
|
|
67
|
+
* at a venue that trades every day, a monthly bar's last day of the month.
|
|
68
|
+
* `YYYY-MM-DD`.
|
|
69
|
+
*/
|
|
70
|
+
export function barCloseDay(day: string, interval?: string | null, venue?: string): string {
|
|
71
|
+
const date = day.slice(0, 10);
|
|
72
|
+
if (interval === "1wk") return shiftDay(date, venue && isAlwaysOpenExchange(venue) ? 6 : 4);
|
|
73
|
+
if (interval === "1mo") {
|
|
74
|
+
const start = new Date(`${date}T00:00:00Z`);
|
|
75
|
+
return new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth() + 1, 0)).toISOString().slice(0, 10);
|
|
76
|
+
}
|
|
77
|
+
return date;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The index of the close a period is measured from among chronological
|
|
82
|
+
* `days` (each close's day, barCloseDay): the last on or before `baseDay`,
|
|
83
|
+
* at most `maxGapDays` before it. -1 when there is none, because the history
|
|
84
|
+
* starts after the base day or has a gap there.
|
|
85
|
+
*/
|
|
86
|
+
export function periodBaseIndex(days: readonly string[], baseDay: string, maxGapDays = PERIOD_BASE_MAX_GAP_DAYS): number {
|
|
87
|
+
const earliest = Number.isFinite(maxGapDays) ? shiftDay(baseDay, -maxGapDays) : "";
|
|
88
|
+
for (let index = days.length - 1; index >= 0; index -= 1) {
|
|
89
|
+
const day = days[index]!;
|
|
90
|
+
if (day > baseDay) continue;
|
|
91
|
+
return day >= earliest ? index : -1;
|
|
92
|
+
}
|
|
93
|
+
return -1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface PeriodClose {
|
|
97
|
+
/** The close's day, `YYYY-MM-DD`. */
|
|
98
|
+
day: string;
|
|
99
|
+
close: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface PeriodReturn {
|
|
103
|
+
/** The calendar date the period is measured back to (periodBaseDay). */
|
|
104
|
+
baseDay: string;
|
|
105
|
+
/** The close it is measured from: the last on or before `baseDay`. */
|
|
106
|
+
base: PeriodClose;
|
|
107
|
+
/** The price it runs to: the newest close, or the live price given. */
|
|
108
|
+
end: PeriodClose;
|
|
109
|
+
/** The return in percent. */
|
|
110
|
+
percent: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* A period return over chronological closes, from the close on or before
|
|
115
|
+
* the base day (periodBaseIndex) to the newest close, or to `latest` when a
|
|
116
|
+
* live price is given, dated by its session day. Null without a base, an end,
|
|
117
|
+
* or a positive base close.
|
|
118
|
+
*/
|
|
119
|
+
export function periodReturn(
|
|
120
|
+
closes: readonly PeriodClose[],
|
|
121
|
+
period: ReturnPeriod,
|
|
122
|
+
latest?: PeriodClose | null,
|
|
123
|
+
maxGapDays = PERIOD_BASE_MAX_GAP_DAYS,
|
|
124
|
+
): PeriodReturn | null {
|
|
125
|
+
const end = latest && Number.isFinite(latest.close) ? latest : closes.at(-1);
|
|
126
|
+
if (!end) return null;
|
|
127
|
+
const baseDay = periodBaseDay(end.day, period);
|
|
128
|
+
const index = periodBaseIndex(closes.map((close) => close.day), baseDay, maxGapDays);
|
|
129
|
+
const base = index < 0 ? null : closes[index]!;
|
|
130
|
+
if (!base || !(base.close > 0) || !Number.isFinite(end.close)) return null;
|
|
131
|
+
const percent = (end.close / base.close - 1) * 100;
|
|
132
|
+
return Number.isFinite(percent) ? { baseDay, base, end, percent } : null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] as const;
|
|
136
|
+
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] as const;
|
|
137
|
+
|
|
138
|
+
/** `Mon 21 Sep`, with the year when it is not `currentYear`'s: `Tue 21 Oct 2025`. */
|
|
139
|
+
export function periodDayText(day: string, currentYear: number): string {
|
|
140
|
+
const date = new Date(`${day.slice(0, 10)}T00:00:00Z`);
|
|
141
|
+
if (!Number.isFinite(date.getTime())) return day;
|
|
142
|
+
const year = date.getUTCFullYear() === currentYear ? "" : ` ${date.getUTCFullYear()}`;
|
|
143
|
+
return `${WEEKDAYS[date.getUTCDay()]} ${date.getUTCDate()} ${MONTHS[date.getUTCMonth()]}${year}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** `from Mon 21 Sep close`: the close a period is measured from, as its output names it. */
|
|
147
|
+
export function periodBaseText(day: string, now = Date.now()): string {
|
|
148
|
+
return `from ${periodDayText(day, new Date(now).getUTCFullYear())} close`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Whether a daily bar dated `day` is the session still trading at `venue`
|
|
153
|
+
* at `now`: dated after the venue's latest closed session, or today's UTC
|
|
154
|
+
* date for a venue that never closes. False where the venue's sessions are
|
|
155
|
+
* unknown, which cannot tell.
|
|
156
|
+
*/
|
|
157
|
+
export function isIntradayDailyBar(day: string, venue: string | undefined, now: number): boolean {
|
|
158
|
+
if (!venue || !Number.isFinite(now)) return false;
|
|
159
|
+
if (isAlwaysOpenExchange(venue)) return day.slice(0, 10) === new Date(now).toISOString().slice(0, 10);
|
|
160
|
+
if (!sessionCalendarTimeZone(venue)) return false;
|
|
161
|
+
const last = latestRegularSessionClose(venue, now);
|
|
162
|
+
return !!last && day.slice(0, 10) > last.date;
|
|
163
|
+
}
|
|
@@ -72,6 +72,19 @@ export function latestTradingSessionOpen(symbol: string | undefined, exchange: s
|
|
|
72
72
|
return futures ? latestOpen(futures, time) : latestRegularSessionOpen(exchange, time);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* When a futures listing's sessions open, in minutes after local midnight:
|
|
77
|
+
* its source's minute and hour bars start on the clock, not at the open, so a
|
|
78
|
+
* bar built from them must not straddle it. Null for other listings, whose
|
|
79
|
+
* bars start at the open.
|
|
80
|
+
*/
|
|
81
|
+
export function futuresSessionOpenMinute(symbol: string | undefined, exchange: string | undefined): number | null {
|
|
82
|
+
const session = symbol || exchange ? futuresSessionOpen(symbol ?? "", exchange) : null;
|
|
83
|
+
if (!session) return null;
|
|
84
|
+
const gcd = (left: number, right: number): number => (right === 0 ? left : gcd(right, left % right));
|
|
85
|
+
return session.sundayOpen === undefined ? session.open : gcd(session.open, session.sundayOpen);
|
|
86
|
+
}
|
|
87
|
+
|
|
75
88
|
/**
|
|
76
89
|
* The zone a listing's intraday times read in: a futures venue's own clock
|
|
77
90
|
* (Chicago for CME Group, New York for ICE U.S.), otherwise the venue's. Null
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { barLastSession } from "./bar-period";
|
|
2
|
+
import { barCloseDay, barSessionDay, periodBaseDay, periodBaseIndex } from "./period-return";
|
|
2
3
|
|
|
3
4
|
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] as const;
|
|
4
5
|
|
|
@@ -29,18 +30,12 @@ export function yearToDateBaseLabel(day: string, venue: string | undefined, now
|
|
|
29
30
|
* every bar is from the year itself (a listing that started trading in it);
|
|
30
31
|
* -1 without bars.
|
|
31
32
|
*/
|
|
32
|
-
export function yearToDateStartIndex(dates: readonly string[], interval?: string | null): number {
|
|
33
|
-
|
|
33
|
+
export function yearToDateStartIndex(dates: readonly string[], interval?: string | null, venue?: string): number {
|
|
34
|
+
// A timestamped bar is read on the venue's clock (barSessionDay), a crypto week as running through Sunday.
|
|
35
|
+
const days = dates.map((date) => date.length > 10 && Number.isFinite(Date.parse(date)) ? barSessionDay(Date.parse(date), venue) : date.slice(0, 10));
|
|
36
|
+
const last = days.at(-1);
|
|
34
37
|
if (!last) return -1;
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
if (interval === "1wk") return new Date(day + 6 * 86_400_000).toISOString().slice(0, 10);
|
|
39
|
-
if (interval === "1mo") return new Date(Date.UTC(new Date(day).getUTCFullYear(), new Date(day).getUTCMonth() + 1, 0)).toISOString().slice(0, 10);
|
|
40
|
-
return date.slice(0, 10);
|
|
41
|
-
};
|
|
42
|
-
for (let index = dates.length - 1; index >= 0; index -= 1) {
|
|
43
|
-
if (closes(dates[index]!) <= yearEnd) return index;
|
|
44
|
-
}
|
|
45
|
-
return 0;
|
|
38
|
+
// The listing's whole history counts here, however far before 31 Dec its last close of the year was.
|
|
39
|
+
const index = periodBaseIndex(days.map((day) => barCloseDay(day, interval, venue)), periodBaseDay(last, "YTD"), Number.POSITIVE_INFINITY);
|
|
40
|
+
return Math.max(0, index);
|
|
46
41
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PricePoint, Quote } from "../types/financials";
|
|
2
2
|
import { pricePointIntegrity } from "../utils/price-history-integrity";
|
|
3
3
|
import { calendarMonthsBefore } from "../utils/calendar-date";
|
|
4
|
+
import { barSessionDay, isReturnPeriod, periodBaseDay, periodBaseIndex } from "./market/period-return";
|
|
4
5
|
|
|
5
6
|
export interface PriceReturnHorizon {
|
|
6
7
|
id: string;
|
|
@@ -66,20 +67,26 @@ export function appendQuoteToPriceReturnHistory(
|
|
|
66
67
|
];
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
/** The calendar date a horizon ending on `day` is measured back to (periodBaseDay). */
|
|
71
|
+
function horizonBaseDay(day: string, horizon: PriceReturnHorizon): string {
|
|
72
|
+
return isReturnPeriod(horizon.id)
|
|
73
|
+
? periodBaseDay(day, horizon.id)
|
|
74
|
+
: calendarMonthsBefore(new Date(`${day}T00:00:00Z`), horizon.amount * (horizon.unit === "year" ? 12 : 1)).toISOString().slice(0, 10);
|
|
71
75
|
}
|
|
72
76
|
|
|
77
|
+
/** `venue` is the listing's exchange, whose clock dates its bars and quote (barSessionDay). */
|
|
73
78
|
export function computePriceReturnForHorizon(
|
|
74
79
|
points: readonly PricePoint[],
|
|
75
80
|
horizon: PriceReturnHorizon,
|
|
81
|
+
venue?: string,
|
|
76
82
|
): number | null {
|
|
77
|
-
return priceReturnForHorizon(points, horizon).value;
|
|
83
|
+
return priceReturnForHorizon(points, horizon, venue).value;
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
function priceReturnForHorizon(
|
|
81
87
|
points: readonly PricePoint[],
|
|
82
88
|
horizon: PriceReturnHorizon,
|
|
89
|
+
venue: string | undefined,
|
|
83
90
|
): Pick<PriceReturnField, "value" | "unavailableReason"> {
|
|
84
91
|
const history = normalizePriceReturnHistory(points);
|
|
85
92
|
if (history.length < 2) return {
|
|
@@ -88,16 +95,14 @@ function priceReturnForHorizon(
|
|
|
88
95
|
};
|
|
89
96
|
|
|
90
97
|
const latest = history.at(-1)!;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
}
|
|
98
|
+
// The close on or before the same date a horizon earlier, as every period return is measured. No gap
|
|
99
|
+
// limit: the overview's history can be sparse, and its base is whatever close it holds on or before then.
|
|
100
|
+
// Each bar and the quote by its session day: a JPX bar stamped 00:00 JST, or a quote after a New York close, is not the UTC date's.
|
|
101
|
+
const days = history.map((point) => barSessionDay(point.date.getTime(), venue));
|
|
102
|
+
const baseDay = horizonBaseDay(days.at(-1)!, horizon);
|
|
103
|
+
const baseIndex = periodBaseIndex(days, baseDay, Number.POSITIVE_INFINITY);
|
|
104
|
+
const baseline = baseIndex < 0 ? null : history[baseIndex]!;
|
|
105
|
+
const cutoff = new Date(`${baseDay}T00:00:00Z`);
|
|
101
106
|
|
|
102
107
|
if (history.some((point) => point.date >= (baseline?.date ?? cutoff) && pricePointIntegrity(point))) {
|
|
103
108
|
return { value: null, unavailableReason: "inconsistent-ohlc" };
|
|
@@ -109,11 +114,12 @@ function priceReturnForHorizon(
|
|
|
109
114
|
|
|
110
115
|
export function buildPriceReturnFields(
|
|
111
116
|
points: readonly PricePoint[],
|
|
117
|
+
venue?: string,
|
|
112
118
|
horizons: readonly PriceReturnHorizon[] = PRICE_RETURN_HORIZONS,
|
|
113
119
|
): PriceReturnField[] {
|
|
114
120
|
return horizons.map((horizon) => ({
|
|
115
121
|
id: horizon.id,
|
|
116
122
|
label: horizon.label,
|
|
117
|
-
...priceReturnForHorizon(points, horizon),
|
|
123
|
+
...priceReturnForHorizon(points, horizon, venue),
|
|
118
124
|
}));
|
|
119
125
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Quote } from "../types/financials";
|
|
2
|
+
|
|
3
|
+
/** What a stock perpetual's premium to its stock is worked out from: its row, as PERP and the lists read it. */
|
|
4
|
+
export interface PerpetualPremiumRow {
|
|
5
|
+
markPrice?: number | null;
|
|
6
|
+
priceMultiplier?: number;
|
|
7
|
+
underlying?: { currency: string } | null;
|
|
8
|
+
/**
|
|
9
|
+
* How Gloom Cloud matched the contract to the listing asked about: that very listing, or another of its issuer's
|
|
10
|
+
* (a GOOGL contract for GOOG, BRK.A's for BRK.B), whose price is not the contract's reference.
|
|
11
|
+
*/
|
|
12
|
+
equityMatch?: { basis: "listing" | "issuer" } | null;
|
|
13
|
+
/** Gloom Cloud's figure: against the stock's stored price, or its regular close while its market is shut. */
|
|
14
|
+
underlyingPremium: number | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A stock perpetual's premium to its stock. While the stock's market is open, the stored price Gloom Cloud compares a
|
|
19
|
+
* streaming mark with is minutes old, so a live quote of the stock, where the screen has one, is the reference
|
|
20
|
+
* instead, when the contract tracks that very listing. Otherwise (another listing of the issuer, a quote that is
|
|
21
|
+
* itself a contract's, a delayed quote, a shut market, another currency) the row's own figure stands.
|
|
22
|
+
*/
|
|
23
|
+
export function premiumToUnderlying(row: PerpetualPremiumRow, stock: Quote | null | undefined): number | null {
|
|
24
|
+
const mark = row.markPrice;
|
|
25
|
+
if (
|
|
26
|
+
mark == null || !row.underlying || row.equityMatch?.basis !== "listing" || !stock || stock.instrumentType === "PERP"
|
|
27
|
+
|| stock.stale === true || stock.dataSource !== "live"
|
|
28
|
+
|| stock.marketState !== "REGULAR" || stock.currency !== row.underlying.currency
|
|
29
|
+
|| !Number.isFinite(stock.price) || stock.price <= 0
|
|
30
|
+
) return row.underlyingPremium;
|
|
31
|
+
return mark / (row.priceMultiplier ?? 1) / stock.price - 1;
|
|
32
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// KRX, also KOSDAQ: http://open.krx.co.kr/contents/MKD/01/0110/01100305/MKD01100305.jsp
|
|
6
6
|
// TWSE, whose closures TPEx shares: https://www.twse.com.tw/en/trading/holiday.html
|
|
7
7
|
// (2027 not yet published; 12 and 13 Feb 2026 are clearing-only days without trading)
|
|
8
|
+
// and a day it closed unscheduled: 23 Oct 2026 for Typhoon Champi, announced the evening before
|
|
8
9
|
// BHB closes on the dates its own daily closes skip in 2026, which match the holidays it lists
|
|
9
10
|
// (some moved, as its list warns), and on National Day, 16 and 17 Dec. Its week is Sunday to Thursday.
|
|
10
11
|
// HKEX: https://www.hkex.com.hk/-/media/HKEX-Market/Services/Circulars-and-Notices/Participant-and-Members-Circulars/SEHK/2025/ce_SEHK_CT_075_2025.pdf
|
|
@@ -39,7 +40,7 @@ const WIENER_BOERSE_CLOSURES: Record<number, readonly string[]> = {
|
|
|
39
40
|
const TWSE_CLOSURES: Record<number, readonly string[]> = {
|
|
40
41
|
2026: [
|
|
41
42
|
"01-01", "02-12", "02-13", "02-16", "02-17", "02-18", "02-19", "02-20", "02-27",
|
|
42
|
-
"04-03", "04-06", "05-01", "06-19", "09-25", "09-28", "10-09", "10-26", "12-25",
|
|
43
|
+
"04-03", "04-06", "05-01", "06-19", "09-25", "09-28", "10-09", "10-23", "10-26", "12-25",
|
|
43
44
|
],
|
|
44
45
|
};
|
|
45
46
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Published trade-date holidays of the futures venues quotes name (weekend
|
|
2
|
+
// dates omitted), not a holiday-rule engine: weekdays with no trade date, on
|
|
3
|
+
// which nothing settles. CME Globex trades an abbreviated session on most of
|
|
4
|
+
// them and books it on the next trade date; ICE Futures U.S. softs do not
|
|
5
|
+
// trade at all. A year a venue has not published is unknown, not open.
|
|
6
|
+
// Checked 2026-10-21:
|
|
7
|
+
// CME Group, one calendar for CME, CBOT, NYMEX and COMEX:
|
|
8
|
+
// https://www.cmegroup.com/trading-hours.html (2026 and 2027 Globex holiday schedules and notes)
|
|
9
|
+
// and its clearing advisories, such as
|
|
10
|
+
// https://www.cmegroup.com/tools-information/holiday-calendar/files/2026/2026-memorial-day-clearing-advisory.pdf
|
|
11
|
+
// ("Prices will be carried forward from Prior day").
|
|
12
|
+
// ICE Futures U.S. softs (cocoa, coffee, cotton, FCOJ, sugar):
|
|
13
|
+
// https://www.ice.com/publicdocs/futures_us/exchange_notices/ICE_Futures_US_Exchange_Notice_2026_Holiday_Calendar_20260609.pdf
|
|
14
|
+
// https://www.ice.com/publicdocs/futures_us/exchange_notices/ICE_Futures_US_Exchange_Notice-2027_Holiday_Calendar_20260604.pdf
|
|
15
|
+
// Its canola closes on Canada's holidays and its financial contracts trade most US ones; Gloom
|
|
16
|
+
// Cloud quotes neither (RS=F and DX=F are not tickers), so NYB is its softs.
|
|
17
|
+
// ICE Futures Europe has no listing Gloom Cloud quotes, so no calendar.
|
|
18
|
+
const CME_GROUP_CLOSURES: Record<number, readonly string[]> = {
|
|
19
|
+
2026: ["01-01", "01-19", "02-16", "04-03", "05-25", "06-19", "07-03", "09-07", "11-26", "12-25"],
|
|
20
|
+
2027: ["01-01", "01-18", "02-15", "03-26", "05-31", "06-18", "07-05", "09-06", "11-25", "12-24"],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const ICE_US_SOFTS_CLOSURES: Record<number, readonly string[]> = {
|
|
24
|
+
2026: ["01-01", "01-19", "02-16", "04-03", "05-25", "06-19", "07-03", "09-07", "11-26", "12-25"],
|
|
25
|
+
2027: ["01-01", "01-18", "02-15", "03-26", "05-31", "06-18", "07-05", "09-06", "11-25", "12-24"],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Closures by canonical venue code. */
|
|
29
|
+
export const PUBLISHED_FUTURES_CLOSURES: Readonly<Record<string, Record<number, readonly string[]>>> = {
|
|
30
|
+
CME: CME_GROUP_CLOSURES,
|
|
31
|
+
CBT: CME_GROUP_CLOSURES,
|
|
32
|
+
NYM: CME_GROUP_CLOSURES,
|
|
33
|
+
CMX: CME_GROUP_CLOSURES,
|
|
34
|
+
NYB: ICE_US_SOFTS_CLOSURES,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Closures some of a venue's contracts settled on and others did not, which
|
|
39
|
+
* its calendar cannot say either way. Good Friday 2026 fell on a payrolls
|
|
40
|
+
* release: CME and CBOT settled their FX, interest rate and crypto contracts
|
|
41
|
+
* and rolled their equity index and agricultural ones forward from Thursday
|
|
42
|
+
* (https://www.cmegroup.com/tools-information/holiday-calendar/files/2026/2026-good-friday-clearing-advisory.pdf).
|
|
43
|
+
* NYMEX and COMEX settled nothing.
|
|
44
|
+
*/
|
|
45
|
+
const PARTIAL_CLOSURES: Readonly<Record<string, readonly string[]>> = {
|
|
46
|
+
CME: ["2026-04-03"],
|
|
47
|
+
CBT: ["2026-04-03"],
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Whether `exchange` (a canonical venue code) is a futures venue with a published calendar. */
|
|
51
|
+
export function isPublishedFuturesVenue(exchange: string): boolean {
|
|
52
|
+
return Object.hasOwn(PUBLISHED_FUTURES_CLOSURES, exchange);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** True only for a published trade-date holiday; unpublished years are unknown, not open. */
|
|
56
|
+
export function isPublishedFuturesClosure(exchange: string, date: string): boolean {
|
|
57
|
+
if (!isPublishedFuturesVenue(exchange)) return false;
|
|
58
|
+
return PUBLISHED_FUTURES_CLOSURES[exchange]![Number(date.slice(0, 4))]?.includes(date.slice(5)) ?? false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* True when the venue's calendar says whether `date` had a trade date: its
|
|
63
|
+
* year is published and the day is not one some of its contracts settled and
|
|
64
|
+
* others did not.
|
|
65
|
+
*/
|
|
66
|
+
export function hasPublishedFuturesCalendar(exchange: string, date: string): boolean {
|
|
67
|
+
return isPublishedFuturesVenue(exchange) && PUBLISHED_FUTURES_CLOSURES[exchange]![Number(date.slice(0, 4))] !== undefined
|
|
68
|
+
&& !PARTIAL_CLOSURES[exchange]?.includes(date);
|
|
69
|
+
}
|
|
@@ -214,6 +214,10 @@ export function mergeQuoteContribution(
|
|
|
214
214
|
tradingExchangeName: next.tradingExchangeName,
|
|
215
215
|
// Whether the listing no longer trades is said with each observation: a symbol that trades again drops it.
|
|
216
216
|
delisting: next.delisting,
|
|
217
|
+
// So is a pair's price being its bar's close, and why a stale one stands; a bar's close is no trade.
|
|
218
|
+
intradayBar: next.intradayBar,
|
|
219
|
+
staleReason: next.staleReason,
|
|
220
|
+
...(next.intradayBar ? { lastTradePrice: next.lastTradePrice, lastTradeTime: next.lastTradeTime } : {}),
|
|
217
221
|
regularClose: next.regularClose,
|
|
218
222
|
regularCloseSessionDate: next.regularClose != null ? next.regularCloseSessionDate : undefined,
|
|
219
223
|
regularChange: next.regularClose != null ? next.regularChange : undefined,
|
|
@@ -221,7 +225,7 @@ export function mergeQuoteContribution(
|
|
|
221
225
|
};
|
|
222
226
|
|
|
223
227
|
// What this observation's move is from, when not its previous close (a coin's
|
|
224
|
-
// 24 hours
|
|
228
|
+
// 24 hours), is said with each one: a quote back on its
|
|
225
229
|
// previous close drops an earlier "24h", and one on 24 hours drops the
|
|
226
230
|
// earlier close its move no longer runs from.
|
|
227
231
|
if (next.changeBasis == null) {
|