gloomberb 0.16.3 → 0.16.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -91
- package/package.json +7 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +42 -17
- package/src/account/upgrade-personalization.ts +57 -0
- package/src/account/upgrade-tickers.ts +124 -0
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +58 -18
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +16 -1
- package/src/api-client/market-discovery.ts +10 -1
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +95 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +46 -10
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +74 -2
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +26 -2
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +61 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/chart-series.ts +11 -1
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +19 -4
- package/src/cli/commands/fred-series.ts +61 -0
- package/src/cli/commands/market.ts +744 -181
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +425 -0
- package/src/cli/commands/overview.ts +251 -40
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +109 -15
- package/src/cli/commands/system.ts +151 -24
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +149 -40
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +150 -17
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +22 -8
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/glossary.ts +429 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/history-rows.ts +48 -7
- package/src/cli/index-roots.ts +58 -0
- package/src/cli/index.ts +29 -12
- package/src/cli/known-gaps.ts +27 -0
- package/src/cli/listing-arg.ts +595 -26
- package/src/cli/not-a-ticker.ts +44 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/access-gate.ts +5 -0
- package/src/cli/pane-functions/capabilities.ts +11 -4
- package/src/cli/pane-functions/catalog.ts +48 -7
- package/src/cli/pane-functions/data.ts +48 -13
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +41 -19
- package/src/cli/pane-functions/freshness.ts +531 -32
- package/src/cli/pane-functions/function-help.ts +77 -25
- package/src/cli/pane-functions/headless.ts +50 -21
- package/src/cli/pane-functions/index.ts +66 -10
- package/src/cli/pane-functions/market-session.ts +147 -0
- package/src/cli/pane-functions/options.ts +77 -25
- package/src/cli/pane-functions/report-notices.ts +81 -0
- package/src/cli/pane-functions/report.ts +19 -8
- package/src/cli/pane-functions/resolver.ts +53 -18
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +199 -30
- package/src/cli/registry.ts +2 -1
- package/src/cli/report-tables.ts +3 -0
- package/src/cli/result.ts +53 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +9 -0
- package/src/cli/symbol-list.ts +172 -0
- package/src/cli/ticker-resolution.ts +223 -30
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +6 -2
- package/src/components/chart/composite/composite-chart.tsx +83 -10
- package/src/components/chart/composite/legend.tsx +88 -8
- package/src/components/chart/composite/panel-surface.tsx +44 -17
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/command-bar/workflow/tickers.ts +23 -4
- package/src/components/data-table/view.tsx +28 -9
- package/src/components/layout/detached-pane-shell.tsx +9 -0
- package/src/components/layout/floating-pane.tsx +9 -2
- package/src/components/layout/header.tsx +20 -5
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +40 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/model.ts +35 -1
- package/src/components/layout/pane/header.tsx +26 -2
- package/src/components/layout/pane/index.tsx +12 -2
- package/src/components/layout/pane/sidebar.tsx +78 -10
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/drag/index.ts +43 -9
- package/src/components/layout/shell/drag/live.ts +87 -6
- package/src/components/layout/shell/drag/runtime.ts +62 -20
- package/src/components/layout/shell/index.tsx +71 -12
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +33 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +216 -28
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +69 -23
- package/src/components/metric-treemap/heat-surface.tsx +37 -9
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +50 -41
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +24 -1
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +17 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +49 -0
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +20 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +13 -2
- package/src/components/ui/index.ts +1 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +44 -5
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7416 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +75 -5
- package/src/i18n/ja.ts +75 -5
- package/src/i18n/ko.ts +75 -5
- package/src/i18n/zh-cn.ts +75 -5
- package/src/i18n/zh-tw.ts +75 -5
- package/src/layout/desks.ts +2 -3
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +193 -30
- package/src/market-data/market/status.ts +59 -23
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +22 -2
- package/src/market-data/quotes/metadata.ts +8 -9
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +61 -9
- package/src/market-data/result-types.ts +2 -0
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +2 -56
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +37 -8
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +41 -9
- package/src/plugins/builtin/alerts/pane.tsx +8 -0
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +4 -2
- package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +71 -12
- package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/pane.tsx +3 -1
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +70 -13
- package/src/plugins/builtin/cds/headless.ts +116 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +193 -31
- package/src/plugins/builtin/cds/pane.tsx +56 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
- package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless.ts +8 -3
- package/src/plugins/builtin/chart-composer/index.tsx +9 -2
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +50 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
- package/src/plugins/builtin/cloud/askg/model.ts +156 -78
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
- package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +19 -5
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +116 -67
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +23 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
- package/src/plugins/builtin/credit-conditions/series.ts +26 -0
- package/src/plugins/builtin/credit-documents/headless.ts +31 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/earnings-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +70 -22
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/pane.tsx +3 -1
- package/src/plugins/builtin/fear-greed/index.tsx +4 -0
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +70 -9
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +64 -27
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +114 -20
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/index.tsx +18 -8
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +62 -14
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +42 -134
- package/src/plugins/builtin/holders/pane.tsx +14 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +27 -10
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +26 -6
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +27 -12
- package/src/plugins/builtin/iv-history/index.tsx +5 -3
- package/src/plugins/builtin/iv-history/model.ts +172 -20
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +28 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +68 -3
- package/src/plugins/builtin/macro-day/headless.ts +18 -12
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +66 -15
- package/src/plugins/builtin/macro-day/pane.tsx +34 -20
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +102 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +11 -3
- package/src/plugins/builtin/market-movers/model.ts +101 -17
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +7 -2
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +3 -6
- package/src/plugins/builtin/mna/headless.ts +15 -3
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +162 -13
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +5 -2
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +75 -18
- package/src/plugins/builtin/options-scenario/headless.ts +72 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/client.ts +40 -6
- package/src/plugins/builtin/perps/equity-row.tsx +33 -8
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +45 -30
- package/src/plugins/builtin/perps/index.tsx +18 -1
- package/src/plugins/builtin/perps/model.ts +32 -6
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +90 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
- package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +6 -2
- package/src/plugins/builtin/power/headless.ts +71 -7
- package/src/plugins/builtin/power/index.tsx +4 -1
- package/src/plugins/builtin/power/model.ts +72 -1
- package/src/plugins/builtin/power/pane.tsx +32 -9
- package/src/plugins/builtin/rate-path/headless.ts +11 -3
- package/src/plugins/builtin/realized-vol/headless.ts +8 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/sec/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/series-inventory.ts +91 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +69 -0
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +4 -4
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +59 -2
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +21 -4
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/index.tsx +3 -10
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +1 -0
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
- package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +125 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -2
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +4 -2
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +129 -64
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +173 -28
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +25 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +126 -59
- package/src/remote/matching.ts +69 -0
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +63 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +32 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +3 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +27 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +21 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/box.tsx +4 -1
- package/src/renderers/dom/host/chart-surface.tsx +6 -2
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +14 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/size-observer.ts +26 -0
- package/src/renderers/dom/host/surface-3d.tsx +7 -2
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +74 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +6 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +107 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +145 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +26 -17
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
- package/src/sources/history-result.ts +1 -0
- package/src/sources/listing-symbols.ts +14 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +9 -5
- package/src/sources/provider-router/financial-routes.ts +12 -5
- package/src/sources/provider-router/financials.ts +55 -15
- package/src/sources/provider-router/history.ts +68 -34
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/provider-router/search.ts +1 -0
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +5 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +25 -0
- package/src/tickers/open-target.ts +3 -2
- package/src/tickers/search/index.ts +67 -9
- package/src/tickers/search/ranking.ts +78 -18
- package/src/tickers/search/types.ts +10 -2
- package/src/tickers/starter-symbols.ts +8 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/resolve.ts +96 -30
- package/src/time-series/types.ts +4 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +67 -1
- package/src/types/data-provider.ts +5 -0
- package/src/types/financials.ts +52 -1
- package/src/types/headless.ts +72 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +68 -3
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/host.tsx +26 -4
- package/src/ui/index.tsx +2 -0
- package/src/ui/live-resize.ts +81 -0
- package/src/ui/live-stretch.ts +121 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/pane-fill.ts +11 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/cli-output.ts +21 -2
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +437 -52
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +120 -1
- package/src/utils/format.ts +17 -3
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +44 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +130 -40
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +178 -36
- package/src/utils/sec.ts +98 -40
- package/src/utils/throttled-fetch.ts +51 -22
- package/src/utils/utc-time.ts +51 -4
|
@@ -9,6 +9,11 @@ import { quoteFutureToleranceMs } from "../quotes/clock";
|
|
|
9
9
|
import { zonedDateKey, zonedDateTimeParts, zonedWallClockToUtcMs } from "../../utils/zoned-date-time";
|
|
10
10
|
|
|
11
11
|
const ALWAYS_OPEN_EXCHANGES = new Set(["CCC"]);
|
|
12
|
+
|
|
13
|
+
/** Spot crypto venues have no equity open or close. */
|
|
14
|
+
export function isAlwaysOpenExchange(exchange: string | undefined): boolean {
|
|
15
|
+
return ALWAYS_OPEN_EXCHANGES.has(canonicalExchange(exchange));
|
|
16
|
+
}
|
|
12
17
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
13
18
|
const OVERNIGHT_CLOSE_MAX_AGE_MS = 20 * 60 * 60 * 1000;
|
|
14
19
|
const ALWAYS_OPEN_MAX_AGE_MS = 2 * 60 * 60 * 1000;
|
|
@@ -61,6 +66,15 @@ const REGULAR_OPEN_MINUTES: Record<string, number> = {
|
|
|
61
66
|
B3: 10 * 60,
|
|
62
67
|
BYMA: 11 * 60,
|
|
63
68
|
JSE: 9 * 60,
|
|
69
|
+
// The opening auction ends at 10:00 and the feed stamps its first bar 09:59.
|
|
70
|
+
TASE: 9 * 60 + 59,
|
|
71
|
+
TADAWUL: 10 * 60,
|
|
72
|
+
QE: 9 * 60 + 30,
|
|
73
|
+
BHB: 9 * 60 + 30,
|
|
74
|
+
DFM: 10 * 60,
|
|
75
|
+
MSX: 10 * 60,
|
|
76
|
+
KUWAIT: 9 * 60,
|
|
77
|
+
EGX: 10 * 60,
|
|
64
78
|
};
|
|
65
79
|
// Local regular close with the closing auction, rounded up. A close taken too
|
|
66
80
|
// early would let a copy fetched during the auction pass as final.
|
|
@@ -74,7 +88,79 @@ const REGULAR_CLOSE_MINUTES: Record<string, number> = {
|
|
|
74
88
|
JPX: 15 * 60 + 30, HKEX: 16 * 60 + 10, TWSE: 14 * 60 + 30, TPEX: 14 * 60 + 30,
|
|
75
89
|
NSE: 16 * 60, BSE: 16 * 60, ASX: 16 * 60 + 15, SGX: 17 * 60 + 20, KRX: 16 * 60, KOSDAQ: 16 * 60,
|
|
76
90
|
NZX: 17 * 60, SSE: 15 * 60 + 30, SZSE: 15 * 60 + 30,
|
|
77
|
-
BMV: 15 * 60 + 10, B3: 18 * 60 + 30, BYMA: 17 * 60 + 10, JSE: 17 * 60 + 15,
|
|
91
|
+
BMV: 15 * 60 + 10, B3: 18 * 60 + 30, BYMA: 17 * 60 + 10, JSE: 17 * 60 + 15,
|
|
92
|
+
// Monday to Thursday: trading at last ends 17:30, after the closing auction.
|
|
93
|
+
// Not later: a complete 5-minute copy ends with its 17:09 bar, which must
|
|
94
|
+
// reach the close less the half hour a history copy may lag.
|
|
95
|
+
TASE: 17 * 60 + 30,
|
|
96
|
+
// Continuous trading to 15:00, the closing auction to 15:10 and trading at
|
|
97
|
+
// last to 15:20. A complete 5-minute copy ends with its 14:55 bar.
|
|
98
|
+
TADAWUL: 15 * 60 + 20,
|
|
99
|
+
// Continuous trading to 13:00, the closing auction to 13:10 and trading at
|
|
100
|
+
// last to 13:15. A complete 5-minute copy ends with its 13:05 or 13:10 bar.
|
|
101
|
+
QE: 13 * 60 + 15,
|
|
102
|
+
// Bahrain Bourse trades continuously to 13:00, with no closing auction.
|
|
103
|
+
BHB: 13 * 60,
|
|
104
|
+
// Continuous trading to 14:45, the closing auction to 14:55 and trading at
|
|
105
|
+
// the close to 15:00. A complete 5-minute copy ends with its 14:55 bar.
|
|
106
|
+
DFM: 15 * 60,
|
|
107
|
+
// The Muscat Stock Exchange since 1 Jun 2026: continuous trading to 14:45,
|
|
108
|
+
// the closing auction to 14:55 and trade at last to 15:00. A complete
|
|
109
|
+
// 5-minute copy ends with its 14:55 bar.
|
|
110
|
+
MSX: 15 * 60,
|
|
111
|
+
// Boursa Kuwait: continuous trading to 13:00, the closing auction to 13:10
|
|
112
|
+
// and trade at last to 13:15. Not later than the auction's end: a complete
|
|
113
|
+
// 5-minute copy ends with its 12:40 bar (the source still closes its
|
|
114
|
+
// period at 12:45), which must reach the close less the half hour a
|
|
115
|
+
// history copy may lag.
|
|
116
|
+
KUWAIT: 13 * 60 + 10,
|
|
117
|
+
// The Egyptian Exchange: continuous trading to 14:15, the closing auction
|
|
118
|
+
// to 14:25 and trading at the close to 14:30.
|
|
119
|
+
EGX: 14 * 60 + 25,
|
|
120
|
+
};
|
|
121
|
+
// Venues whose week is not Monday to Friday, as their days off (0 is Sunday).
|
|
122
|
+
// Tadawul, Qatar, Boursa Kuwait and the Egyptian Exchange trade Sunday to
|
|
123
|
+
// Thursday. Dubai's DFM has traded Monday to Friday since 2022, like the
|
|
124
|
+
// venues not listed here.
|
|
125
|
+
const WEEKEND_DAYS: Record<string, readonly number[]> = {
|
|
126
|
+
TADAWUL: [5, 6],
|
|
127
|
+
// Bahrain Bourse trades Sunday to Thursday.
|
|
128
|
+
BHB: [5, 6],
|
|
129
|
+
QE: [5, 6],
|
|
130
|
+
// The Muscat Stock Exchange trades Sunday to Thursday.
|
|
131
|
+
MSX: [5, 6],
|
|
132
|
+
KUWAIT: [5, 6],
|
|
133
|
+
EGX: [5, 6],
|
|
134
|
+
};
|
|
135
|
+
const DEFAULT_WEEKEND_DAYS: readonly number[] = [0, 6];
|
|
136
|
+
// History only: venues whose chart source files their bars on another week,
|
|
137
|
+
// as its days off. The chart source still files DFM Sunday to Thursday, the
|
|
138
|
+
// week Dubai traded until 2022, and has no Friday bars, so DFM history ends
|
|
139
|
+
// with Thursday's session from Friday until Monday's opens.
|
|
140
|
+
const HISTORY_SOURCE_WEEKEND_DAYS: Record<string, readonly number[]> = {
|
|
141
|
+
DFM: [5, 6],
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* For history only, the days off of the sessions a venue's chart source has
|
|
146
|
+
* bars for, where its week differs from the venue's: the days both weeks
|
|
147
|
+
* trade (DFM Monday to Thursday, since Dubai does not trade the source's
|
|
148
|
+
* Sundays). Undefined for every other venue. Quotes and the calendar keep the
|
|
149
|
+
* venue's own week.
|
|
150
|
+
*/
|
|
151
|
+
export function historySourceWeekendDays(exchange: string | undefined): readonly number[] | undefined {
|
|
152
|
+
const canonical = canonicalExchange(exchange);
|
|
153
|
+
const source = HISTORY_SOURCE_WEEKEND_DAYS[canonical];
|
|
154
|
+
return source && [...new Set([...(WEEKEND_DAYS[canonical] ?? DEFAULT_WEEKEND_DAYS), ...source])];
|
|
155
|
+
}
|
|
156
|
+
// Venues whose regular session ends earlier on one weekday every week, as
|
|
157
|
+
// local minutes by weekday (0 is Sunday); the other days close as above. TASE
|
|
158
|
+
// has traded Monday to Friday since January 2026, and on Fridays trading at
|
|
159
|
+
// last ends 13:50 (closing auction 13:44 to 13:45). A complete 5-minute copy
|
|
160
|
+
// ends with its 13:29 bar. Holidays and the shortened days around Sukkot and
|
|
161
|
+
// Pesach are not weekly and are not listed.
|
|
162
|
+
const WEEKDAY_CLOSE_MINUTES: Record<string, Partial<Record<number, number>>> = {
|
|
163
|
+
TASE: { 5: 13 * 60 + 50 },
|
|
78
164
|
};
|
|
79
165
|
// Venues that pause at midday, as local minutes [start, end), with a zone for
|
|
80
166
|
// those the session tables above do not cover. Jakarta pauses longer on Fridays.
|
|
@@ -189,20 +275,31 @@ function isPublishedClosure(exchange: string, date: string): boolean {
|
|
|
189
275
|
return getPublishedUsEquityCalendarDay(exchange, date) === "closed";
|
|
190
276
|
}
|
|
191
277
|
|
|
192
|
-
|
|
278
|
+
/** Whether `weekday` (0 is Sunday) is in the venue's trading week. */
|
|
279
|
+
export function isTradingWeekday(exchange: string, weekday: number, weekendDays?: readonly number[]): boolean {
|
|
280
|
+
return !(weekendDays ?? WEEKEND_DAYS[exchange] ?? DEFAULT_WEEKEND_DAYS).includes(weekday);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** `weekendDays` replaces the venue's days off (historySourceWeekendDays). */
|
|
284
|
+
function isLocalTradingDay(exchange: string, date: string, weekendDays?: readonly number[]): boolean {
|
|
193
285
|
const weekday = localWeekday(date);
|
|
194
|
-
return weekday != null &&
|
|
286
|
+
return weekday != null && isTradingWeekday(exchange, weekday, weekendDays) && !isPublishedClosure(exchange, date);
|
|
195
287
|
}
|
|
196
288
|
|
|
197
|
-
/**
|
|
198
|
-
function localTradingDaysBetween(
|
|
289
|
+
/** Days of the venue's trading week in (earlier, later], less published closures for venues with a calendar. */
|
|
290
|
+
function localTradingDaysBetween(
|
|
291
|
+
exchange: string,
|
|
292
|
+
earlierDate: string,
|
|
293
|
+
laterDate: string,
|
|
294
|
+
weekendDays?: readonly number[],
|
|
295
|
+
): number {
|
|
199
296
|
const earlierDay = isoLocalDateToUtcDay(earlierDate);
|
|
200
297
|
const laterDay = isoLocalDateToUtcDay(laterDate);
|
|
201
298
|
if (earlierDay == null || laterDay == null || laterDay <= earlierDay) return 0;
|
|
202
299
|
|
|
203
300
|
let sessions = 0;
|
|
204
301
|
for (let day = earlierDay + 1; day <= laterDay; day += 1) {
|
|
205
|
-
if (isLocalTradingDay(exchange, new Date(day * MS_PER_DAY).toISOString().slice(0, 10))) sessions += 1;
|
|
302
|
+
if (isLocalTradingDay(exchange, new Date(day * MS_PER_DAY).toISOString().slice(0, 10), weekendDays)) sessions += 1;
|
|
206
303
|
}
|
|
207
304
|
return sessions;
|
|
208
305
|
}
|
|
@@ -212,6 +309,12 @@ function localWeekday(date: string): number | null {
|
|
|
212
309
|
return day == null ? null : new Date(day * MS_PER_DAY).getUTCDay();
|
|
213
310
|
}
|
|
214
311
|
|
|
312
|
+
/** The local close of the venue's regular session on `date`, in minutes of the day. */
|
|
313
|
+
function regularCloseMinutes(exchange: string, date: string): number | undefined {
|
|
314
|
+
const weekday = localWeekday(date);
|
|
315
|
+
return (weekday == null ? undefined : WEEKDAY_CLOSE_MINUTES[exchange]?.[weekday]) ?? REGULAR_CLOSE_MINUTES[exchange];
|
|
316
|
+
}
|
|
317
|
+
|
|
215
318
|
/** The zone a venue's session dates are read in, or null when unknown. */
|
|
216
319
|
export function sessionCalendarTimeZone(exchange: string | undefined): string | null {
|
|
217
320
|
const canonical = canonicalExchange(exchange);
|
|
@@ -221,13 +324,14 @@ export function sessionCalendarTimeZone(exchange: string | undefined): string |
|
|
|
221
324
|
|
|
222
325
|
/**
|
|
223
326
|
* The latest regular session that closed at or before `time`: the published
|
|
224
|
-
* calendar for US venues, otherwise
|
|
225
|
-
* venue without a known close hour is taken to close at
|
|
226
|
-
* for round-the-clock and unknown venues.
|
|
327
|
+
* calendar for US venues, otherwise the days of the venue's trading week less
|
|
328
|
+
* published closures. A venue without a known close hour is taken to close at
|
|
329
|
+
* local midnight. Null for round-the-clock and unknown venues.
|
|
227
330
|
*/
|
|
228
331
|
export function latestRegularSessionClose(
|
|
229
332
|
exchange: string | undefined,
|
|
230
333
|
time: number,
|
|
334
|
+
weekendDays?: readonly number[],
|
|
231
335
|
): { date: string; close: number; timeZone: string } | null {
|
|
232
336
|
const canonical = canonicalExchange(exchange);
|
|
233
337
|
const timeZone = sessionCalendarTimeZone(canonical);
|
|
@@ -240,8 +344,8 @@ export function latestRegularSessionClose(
|
|
|
240
344
|
let close: number | null = null;
|
|
241
345
|
if (published) {
|
|
242
346
|
if (published.kind === "session") close = published.close;
|
|
243
|
-
} else if (isLocalTradingDay(canonical, date)) {
|
|
244
|
-
const minutes =
|
|
347
|
+
} else if (isLocalTradingDay(canonical, date, weekendDays)) {
|
|
348
|
+
const minutes = regularCloseMinutes(canonical, date) ?? 24 * 60;
|
|
245
349
|
close = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)),
|
|
246
350
|
Number(date.slice(8, 10)), Math.floor(minutes / 60), minutes % 60, 0);
|
|
247
351
|
}
|
|
@@ -267,10 +371,14 @@ export function regularSessionCloseUtcMinute(exchange: string | undefined, time:
|
|
|
267
371
|
/**
|
|
268
372
|
* The open of the regular session `time` falls in, or of the latest one
|
|
269
373
|
* before it: the published calendar for US venues, otherwise the venue's
|
|
270
|
-
* local open on a
|
|
271
|
-
* round-the-clock venues and venues without a known open hour.
|
|
374
|
+
* local open on a day of its trading week that is not a published closure.
|
|
375
|
+
* Null for round-the-clock venues and venues without a known open hour.
|
|
272
376
|
*/
|
|
273
|
-
export function latestRegularSessionOpen(
|
|
377
|
+
export function latestRegularSessionOpen(
|
|
378
|
+
exchange: string | undefined,
|
|
379
|
+
time: number,
|
|
380
|
+
weekendDays?: readonly number[],
|
|
381
|
+
): number | null {
|
|
274
382
|
const canonical = canonicalExchange(exchange);
|
|
275
383
|
const timeZone = sessionCalendarTimeZone(canonical);
|
|
276
384
|
if (!timeZone || ALWAYS_OPEN_EXCHANGES.has(canonical) || !Number.isFinite(time)) return null;
|
|
@@ -285,7 +393,7 @@ export function latestRegularSessionOpen(exchange: string | undefined, time: num
|
|
|
285
393
|
if (published.kind === "session") open = published.open;
|
|
286
394
|
} else if (minutes === undefined) {
|
|
287
395
|
return null;
|
|
288
|
-
} else if (isLocalTradingDay(canonical, date)) {
|
|
396
|
+
} else if (isLocalTradingDay(canonical, date, weekendDays)) {
|
|
289
397
|
open = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)),
|
|
290
398
|
Number(date.slice(8, 10)), Math.floor(minutes / 60), minutes % 60, 0);
|
|
291
399
|
}
|
|
@@ -294,22 +402,60 @@ export function latestRegularSessionOpen(exchange: string | undefined, time: num
|
|
|
294
402
|
return null;
|
|
295
403
|
}
|
|
296
404
|
|
|
405
|
+
/**
|
|
406
|
+
* The open of the first regular session after `time`, with its local date and
|
|
407
|
+
* the venue's zone: the published calendar for US venues, otherwise the
|
|
408
|
+
* venue's local open on the next day of its trading week that is not a
|
|
409
|
+
* published closure. Null for round-the-clock venues and venues without a
|
|
410
|
+
* known open hour.
|
|
411
|
+
*/
|
|
412
|
+
export function nextRegularSessionOpen(
|
|
413
|
+
exchange: string | undefined,
|
|
414
|
+
time: number,
|
|
415
|
+
): { date: string; open: number; timeZone: string } | null {
|
|
416
|
+
const canonical = canonicalExchange(exchange);
|
|
417
|
+
const timeZone = sessionCalendarTimeZone(canonical);
|
|
418
|
+
if (!timeZone || ALWAYS_OPEN_EXCHANGES.has(canonical) || !Number.isFinite(time)) return null;
|
|
419
|
+
const minutes = REGULAR_OPEN_MINUTES[canonical];
|
|
420
|
+
const { year, month, day } = zonedDateTimeParts(time, timeZone);
|
|
421
|
+
const today = Date.UTC(year, month - 1, day) / MS_PER_DAY;
|
|
422
|
+
for (let offset = 0; offset <= SESSION_LOOKBACK_DAYS; offset++) {
|
|
423
|
+
const date = new Date((today + offset) * MS_PER_DAY).toISOString().slice(0, 10);
|
|
424
|
+
const published = getPublishedUsEquitySession(canonical, date);
|
|
425
|
+
let open: number | null = null;
|
|
426
|
+
if (published) {
|
|
427
|
+
if (published.kind === "session") open = published.open;
|
|
428
|
+
} else if (minutes === undefined) {
|
|
429
|
+
return null;
|
|
430
|
+
} else if (isLocalTradingDay(canonical, date)) {
|
|
431
|
+
open = zonedWallClockToUtcMs(timeZone, Number(date.slice(0, 4)), Number(date.slice(5, 7)),
|
|
432
|
+
Number(date.slice(8, 10)), Math.floor(minutes / 60), minutes % 60, 0);
|
|
433
|
+
}
|
|
434
|
+
if (open != null && open > time) return { date, open, timeZone };
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
|
|
297
439
|
/**
|
|
298
440
|
* Whether `time` is inside a regular session: at or after its open and
|
|
299
441
|
* before its close. Null for venues without known hours.
|
|
300
442
|
*/
|
|
301
|
-
export function isRegularSessionTime(
|
|
302
|
-
|
|
443
|
+
export function isRegularSessionTime(
|
|
444
|
+
exchange: string | undefined,
|
|
445
|
+
time: number,
|
|
446
|
+
weekendDays?: readonly number[],
|
|
447
|
+
): boolean | null {
|
|
448
|
+
const open = latestRegularSessionOpen(exchange, time, weekendDays);
|
|
303
449
|
if (open === null) return null;
|
|
304
450
|
// Before this session's close, the latest close is still the one before it opened.
|
|
305
|
-
const close = latestRegularSessionClose(exchange, time);
|
|
451
|
+
const close = latestRegularSessionClose(exchange, time, weekendDays);
|
|
306
452
|
return !close || close.close < open;
|
|
307
453
|
}
|
|
308
454
|
|
|
309
455
|
/**
|
|
310
456
|
* True when the venue's full-day closures for the year of `date` are
|
|
311
457
|
* published: US venues, JPX, NSE, BSE, SSE, SZSE, KRX, KOSDAQ, TWSE, TPEX,
|
|
312
|
-
* HKEX, SGX and
|
|
458
|
+
* HKEX, SGX, ASX and EGX. Elsewhere a local holiday reads as a trading day.
|
|
313
459
|
*/
|
|
314
460
|
export function hasPublishedSessionCalendar(exchange: string | undefined, date: string): boolean {
|
|
315
461
|
const canonical = canonicalExchange(exchange);
|
|
@@ -345,7 +491,7 @@ export function isMiddayBreakPrint(
|
|
|
345
491
|
if (!pause || !timeZone || !Number.isFinite(timestampMs) || !Number.isFinite(now) || timestampMs > now) return false;
|
|
346
492
|
const { year, month, day } = zonedDateTimeParts(now, timeZone);
|
|
347
493
|
const weekday = new Date(Date.UTC(year, month - 1, day)).getUTCDay();
|
|
348
|
-
if (
|
|
494
|
+
if (!isTradingWeekday(canonical, weekday)) return false;
|
|
349
495
|
const [start, end] = weekday === 5 && pause.friday ? pause.friday : pause.weekdays;
|
|
350
496
|
const at = (minutes: number) => zonedWallClockToUtcMs(timeZone, year, month, day, Math.floor(minutes / 60), minutes % 60, 0);
|
|
351
497
|
const breakStart = at(start);
|
|
@@ -443,20 +589,35 @@ export function isUsRegularCloseQuoteInPostSession(
|
|
|
443
589
|
}
|
|
444
590
|
|
|
445
591
|
/**
|
|
446
|
-
* Whether a US print belongs to the
|
|
447
|
-
*
|
|
592
|
+
* Whether a US print belongs to the extended-hours session the source labels,
|
|
593
|
+
* or to the regular session it extends. POST, after today's regular close (a
|
|
594
|
+
* published early close included) and before 20:00: a print from today's
|
|
595
|
+
* regular session or its after-hours. PRE, before today's open: a print from
|
|
596
|
+
* the previous regular session or since, so its after-hours or this morning's
|
|
597
|
+
* pre-market. An earlier print is not, and neither is any print on a day
|
|
598
|
+
* without a session.
|
|
448
599
|
*/
|
|
449
|
-
export function
|
|
600
|
+
export function isUsExtendedHoursSessionPrint(
|
|
450
601
|
timestampMs: number,
|
|
451
602
|
exchange: string | undefined,
|
|
603
|
+
marketState: MarketState | undefined,
|
|
452
604
|
now = Date.now(),
|
|
453
605
|
): boolean {
|
|
454
606
|
const canonical = canonicalExchange(exchange);
|
|
455
|
-
if (!isUsListingExchange(canonical)) return false;
|
|
607
|
+
if ((marketState !== "PRE" && marketState !== "POST") || !isUsListingExchange(canonical)) return false;
|
|
456
608
|
if (!Number.isFinite(timestampMs) || !Number.isFinite(now) || timestampMs > now + quoteFutureToleranceMs()) return false;
|
|
457
|
-
if (!Number.isFinite(new Date(now).getTime())
|
|
458
|
-
const
|
|
459
|
-
|
|
609
|
+
if (!Number.isFinite(new Date(now).getTime())) return false;
|
|
610
|
+
const today = exchangeLocalDate(canonical, now);
|
|
611
|
+
const close = latestRegularSessionClose(canonical, now);
|
|
612
|
+
if (!today || !close || !isLocalTradingDay(canonical, today)) return false;
|
|
613
|
+
const session = usSessionState(now);
|
|
614
|
+
const closedToday = close.date === today;
|
|
615
|
+
if (marketState === "POST" ? !closedToday || (session !== "REGULAR" && session !== "POST") : closedToday || session !== "PRE") {
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
// The open of the session that closed last: today's after the close, the previous one before the open.
|
|
619
|
+
const open = latestRegularSessionOpen(canonical, close.close);
|
|
620
|
+
return open != null && timestampMs >= open;
|
|
460
621
|
}
|
|
461
622
|
|
|
462
623
|
export function isTimestampStaleForExchangeSession(
|
|
@@ -464,9 +625,10 @@ export function isTimestampStaleForExchangeSession(
|
|
|
464
625
|
exchange?: string,
|
|
465
626
|
now = Date.now(),
|
|
466
627
|
marketState?: MarketState,
|
|
628
|
+
weekendDays?: readonly number[],
|
|
467
629
|
): boolean {
|
|
468
630
|
try {
|
|
469
|
-
return isTimestampStaleForExchangeSessionUnsafe(timestampMs, exchange, now, marketState);
|
|
631
|
+
return isTimestampStaleForExchangeSessionUnsafe(timestampMs, exchange, now, marketState, weekendDays);
|
|
470
632
|
} catch {
|
|
471
633
|
return true;
|
|
472
634
|
}
|
|
@@ -477,6 +639,7 @@ function isTimestampStaleForExchangeSessionUnsafe(
|
|
|
477
639
|
exchange?: string,
|
|
478
640
|
now = Date.now(),
|
|
479
641
|
marketState?: MarketState,
|
|
642
|
+
weekendDays?: readonly number[],
|
|
480
643
|
): boolean {
|
|
481
644
|
const canonical = canonicalExchange(exchange);
|
|
482
645
|
if (!canonical || !Number.isFinite(timestampMs) || !Number.isFinite(now)) return false;
|
|
@@ -498,13 +661,13 @@ function isTimestampStaleForExchangeSessionUnsafe(
|
|
|
498
661
|
}
|
|
499
662
|
}
|
|
500
663
|
|
|
501
|
-
const sessionsBehind = localTradingDaysBetween(canonical, timestampDate, currentDate);
|
|
664
|
+
const sessionsBehind = localTradingDaysBetween(canonical, timestampDate, currentDate, weekendDays);
|
|
502
665
|
if (sessionsBehind > 1) return true;
|
|
503
666
|
if (sessionsBehind === 1 && now - timestampMs > OVERNIGHT_CLOSE_MAX_AGE_MS) {
|
|
504
667
|
// When today is the first session after a weekend or exchange holiday,
|
|
505
668
|
// the last close stays current until the provider reports the new session.
|
|
506
669
|
const calendarDaysBehind = isoLocalDateToUtcDay(currentDate)! - isoLocalDateToUtcDay(timestampDate)!;
|
|
507
|
-
return !(isLocalTradingDay(canonical, currentDate) && (calendarDaysBehind > 1 || localWeekday(currentDate) === 1));
|
|
670
|
+
return !(isLocalTradingDay(canonical, currentDate, weekendDays) && (calendarDaysBehind > 1 || localWeekday(currentDate) === 1));
|
|
508
671
|
}
|
|
509
672
|
return false;
|
|
510
673
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MarketState, Quote } from "../../types/financials";
|
|
2
2
|
import { blendHex, colors, priceColor, type ThemeColors } from "../../theme/colors";
|
|
3
3
|
import { isFiniteNumber } from "../../utils/guards";
|
|
4
|
+
import { canonicalExchange, isKnownExchangeCode } from "../../utils/exchanges";
|
|
4
5
|
import { quoteTradingDay } from "../quotes/day-range";
|
|
5
6
|
|
|
6
7
|
const CLOSED_CHANGE_MUTING_RATIO = 0.55;
|
|
@@ -24,6 +25,9 @@ export interface ActiveQuoteDisplay {
|
|
|
24
25
|
|
|
25
26
|
export type ExtendedSession = "PRE" | "POST";
|
|
26
27
|
|
|
28
|
+
/** What reports call each extended session's line or column. */
|
|
29
|
+
export const EXTENDED_SESSION_LABELS: Record<ExtendedSession, string> = { PRE: "Pre-Market", POST: "After Hours" };
|
|
30
|
+
|
|
27
31
|
export interface ExtendedSessionDisplay extends ActiveQuoteDisplay {
|
|
28
32
|
session: ExtendedSession;
|
|
29
33
|
}
|
|
@@ -105,31 +109,14 @@ export function marketChangeColor(change: number | undefined, state?: MarketStat
|
|
|
105
109
|
return blendHex(directionalColor, colors.textDim, CLOSED_CHANGE_MUTING_RATIO);
|
|
106
110
|
}
|
|
107
111
|
|
|
108
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* The venue's code as a listing key names it (EPA, JPX), from the app's one
|
|
114
|
+
* venue list, so the code a pane shows is the one to type after the symbol.
|
|
115
|
+
* A venue the list does not know keeps the name it came with.
|
|
116
|
+
*/
|
|
109
117
|
export function exchangeShortName(exchangeName?: string, fullExchangeName?: string): string {
|
|
110
|
-
if (!exchangeName && !fullExchangeName) return "";
|
|
111
118
|
const name = exchangeName || fullExchangeName || "";
|
|
112
|
-
|
|
113
|
-
const map: Record<string, string> = {
|
|
114
|
-
NMS: "NASDAQ", NGM: "NASDAQ", NCM: "NASDAQ", NAS: "NASDAQ",
|
|
115
|
-
NYQ: "NYSE", NYS: "NYSE",
|
|
116
|
-
PCX: "ARCA", NYSEArca: "ARCA", "NYSE Arca": "ARCA", ASE: "AMEX",
|
|
117
|
-
HKG: "HKEX",
|
|
118
|
-
TYO: "TYO",
|
|
119
|
-
LSE: "LSE",
|
|
120
|
-
ASX: "ASX",
|
|
121
|
-
SGX: "SGX",
|
|
122
|
-
KSC: "KRX", KOE: "KOSDAQ",
|
|
123
|
-
TAI: "TWSE",
|
|
124
|
-
SHH: "SSE", SHZ: "SZSE",
|
|
125
|
-
PAR: "EURONEXT", AMS: "EURONEXT", BRU: "EURONEXT",
|
|
126
|
-
GER: "XETRA",
|
|
127
|
-
OSL: "OSE",
|
|
128
|
-
BOM: "BSE", NSI: "NSE",
|
|
129
|
-
SAO: "B3",
|
|
130
|
-
JPX: "TYO",
|
|
131
|
-
};
|
|
132
|
-
return map[name] || name;
|
|
119
|
+
return isKnownExchangeCode(name) ? canonicalExchange(name) : name;
|
|
133
120
|
}
|
|
134
121
|
|
|
135
122
|
/**
|
|
@@ -278,11 +265,48 @@ export function getExtendedSessionDisplay(quote: Quote | null | undefined): Exte
|
|
|
278
265
|
return { session: "POST", price, change, changePercent: (change / close) * 100 };
|
|
279
266
|
}
|
|
280
267
|
|
|
268
|
+
/**
|
|
269
|
+
* A quote's headline and extended print as flat figures, for a report row or
|
|
270
|
+
* an export: price, change and changePercent are the regular session's
|
|
271
|
+
* (getRegularSessionDisplay), the extended fields the pre-market or
|
|
272
|
+
* after-hours print measured from its close (getExtendedSessionDisplay), all
|
|
273
|
+
* null when there is none.
|
|
274
|
+
*/
|
|
275
|
+
export function getQuoteSessionFields(quote: Quote | null | undefined) {
|
|
276
|
+
const headline = getRegularSessionDisplay(quote);
|
|
277
|
+
const extended = getExtendedSessionDisplay(quote);
|
|
278
|
+
return {
|
|
279
|
+
price: headline?.price ?? null,
|
|
280
|
+
change: headline?.change ?? null,
|
|
281
|
+
changePercent: headline?.changePercent ?? null,
|
|
282
|
+
extendedSession: extended?.session ?? null,
|
|
283
|
+
extendedPrice: extended?.price ?? null,
|
|
284
|
+
extendedChange: extended?.change ?? null,
|
|
285
|
+
extendedChangePercent: extended?.changePercent ?? null,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
281
289
|
/** The extended display only while its session is open: the pre-market or the after-hours session. */
|
|
282
290
|
function getOpenExtendedSessionDisplay(quote: Quote | null | undefined): ExtendedSessionDisplay | null {
|
|
283
291
|
return quote?.marketState === "PRE" || quote?.marketState === "POST" ? getExtendedSessionDisplay(quote) : null;
|
|
284
292
|
}
|
|
285
293
|
|
|
294
|
+
/**
|
|
295
|
+
* The regular session alone, for a board that never shows extended trading:
|
|
296
|
+
* the live quote while the session trades, then the completed session's close
|
|
297
|
+
* and its move (getCompletedRegularSessionDisplay). Null outside the session
|
|
298
|
+
* when the quote cannot say which close that is, rather than an extended
|
|
299
|
+
* print or a flat move standing in for one. A quote that does not say its
|
|
300
|
+
* session is read as the regular one, as getRegularSessionDisplay does.
|
|
301
|
+
*/
|
|
302
|
+
export function getRegularSessionMoveDisplay(quote: Quote | null | undefined): ActiveQuoteDisplay | null {
|
|
303
|
+
if (!quote) return null;
|
|
304
|
+
if (quote.marketState == null || quote.marketState === "REGULAR") {
|
|
305
|
+
return { price: quote.price, change: quote.change, changePercent: quote.changePercent };
|
|
306
|
+
}
|
|
307
|
+
return getCompletedRegularSessionDisplay(quote);
|
|
308
|
+
}
|
|
309
|
+
|
|
286
310
|
/**
|
|
287
311
|
* The move a board of tiles colors by: the open pre-market or after-hours
|
|
288
312
|
* session's, from the regular close, otherwise the day's regular session.
|
|
@@ -292,3 +316,15 @@ export function getSessionMoveDisplay(
|
|
|
292
316
|
): (ActiveQuoteDisplay & { session?: ExtendedSession }) | null {
|
|
293
317
|
return getOpenExtendedSessionDisplay(quote) ?? getRegularSessionDisplay(quote);
|
|
294
318
|
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* getSessionMoveDisplay for a board that marks an extended move on each tile
|
|
322
|
+
* (the heat map): while a quote says nothing has traded in the open session
|
|
323
|
+
* yet (extendedSessionPrint false), its extended figures are the close
|
|
324
|
+
* carried forward, not a flat print, so the regular session stands.
|
|
325
|
+
*/
|
|
326
|
+
export function getTradedSessionMoveDisplay(
|
|
327
|
+
quote: Quote | null | undefined,
|
|
328
|
+
): (ActiveQuoteDisplay & { session?: ExtendedSession }) | null {
|
|
329
|
+
return quote?.extendedSessionPrint === false ? getRegularSessionDisplay(quote) : getSessionMoveDisplay(quote);
|
|
330
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { parseFuturesGeneric } from "../utils/futures-generic";
|
|
2
|
+
|
|
3
|
+
/** A US-listed fund whose options track an instrument that has none of its own. */
|
|
4
|
+
export interface ListedOptionsAlternative {
|
|
5
|
+
symbol: string;
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Futures roots with no option chain here, and the listed fund whose options
|
|
11
|
+
* are the nearest stand-in. One table for every surface that says so.
|
|
12
|
+
*/
|
|
13
|
+
const FUTURES_ALTERNATIVES: Readonly<Record<string, ListedOptionsAlternative>> = {
|
|
14
|
+
GC: { symbol: "GLD", name: "SPDR Gold Shares" },
|
|
15
|
+
SI: { symbol: "SLV", name: "iShares Silver Trust" },
|
|
16
|
+
HG: { symbol: "CPER", name: "United States Copper Index Fund" },
|
|
17
|
+
PL: { symbol: "PPLT", name: "abrdn Physical Platinum Shares" },
|
|
18
|
+
PA: { symbol: "PALL", name: "abrdn Physical Palladium Shares" },
|
|
19
|
+
CL: { symbol: "USO", name: "United States Oil Fund" },
|
|
20
|
+
BZ: { symbol: "BNO", name: "United States Brent Oil Fund" },
|
|
21
|
+
NG: { symbol: "UNG", name: "United States Natural Gas Fund" },
|
|
22
|
+
LTH: { symbol: "LIT", name: "Global X Lithium & Battery Tech ETF" },
|
|
23
|
+
UX: { symbol: "URA", name: "Global X Uranium ETF" },
|
|
24
|
+
ZC: { symbol: "CORN", name: "Teucrium Corn Fund" },
|
|
25
|
+
ZW: { symbol: "WEAT", name: "Teucrium Wheat Fund" },
|
|
26
|
+
ZS: { symbol: "SOYB", name: "Teucrium Soybean Fund" },
|
|
27
|
+
ES: { symbol: "SPY", name: "SPDR S&P 500 ETF" },
|
|
28
|
+
NQ: { symbol: "QQQ", name: "Invesco QQQ Trust" },
|
|
29
|
+
YM: { symbol: "DIA", name: "SPDR Dow Jones Industrial Average ETF" },
|
|
30
|
+
RTY: { symbol: "IWM", name: "iShares Russell 2000 ETF" },
|
|
31
|
+
ZB: { symbol: "TLT", name: "iShares 20+ Year Treasury Bond ETF" },
|
|
32
|
+
ZN: { symbol: "IEF", name: "iShares 7-10 Year Treasury Bond ETF" },
|
|
33
|
+
"6E": { symbol: "FXE", name: "Invesco CurrencyShares Euro Trust" },
|
|
34
|
+
"6J": { symbol: "FXY", name: "Invesco CurrencyShares Japanese Yen Trust" },
|
|
35
|
+
BTC: { symbol: "IBIT", name: "iShares Bitcoin Trust" },
|
|
36
|
+
ETH: { symbol: "ETHA", name: "iShares Ethereum Trust" },
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const MONTH_CODE_CONTRACT = /^([A-Z0-9]{1,3}?)[FGHJKMNQUVXZ]\d{1,4}$/;
|
|
40
|
+
|
|
41
|
+
/** The futures root a symbol names: GC=F, GCZ26 and the generic GC1 all give GC. */
|
|
42
|
+
function futuresRoot(symbol: string): string | null {
|
|
43
|
+
const ticker = symbol.trim().toUpperCase().replace(/[.:][A-Z]+$/, "");
|
|
44
|
+
if (ticker.endsWith("=F")) {
|
|
45
|
+
const body = ticker.slice(0, -2);
|
|
46
|
+
return FUTURES_ALTERNATIVES[body] ? body : MONTH_CODE_CONTRACT.exec(body)?.[1] ?? body;
|
|
47
|
+
}
|
|
48
|
+
const generic = parseFuturesGeneric(ticker);
|
|
49
|
+
if (generic) return generic.root;
|
|
50
|
+
const contract = MONTH_CODE_CONTRACT.exec(ticker)?.[1];
|
|
51
|
+
return contract && FUTURES_ALTERNATIVES[contract] ? contract : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The listed fund whose options stand in for an instrument with no chain, if there is one. */
|
|
55
|
+
export function listedOptionsAlternative(symbol: string): ListedOptionsAlternative | null {
|
|
56
|
+
const root = futuresRoot(symbol);
|
|
57
|
+
return root ? FUTURES_ALTERNATIVES[root] ?? null : null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Whether an options request failed because nothing lists options on the instrument. */
|
|
61
|
+
export function isOptionsUnavailableError(error: unknown): boolean {
|
|
62
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
63
|
+
return /\boptions provider available for\b/i.test(message);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** "Options are not available for GC=F.": the dead end itself, before any follow-up. */
|
|
67
|
+
export function optionsUnavailableTitle(symbol: string): string {
|
|
68
|
+
return `Options are not available for ${symbol.trim().toUpperCase()}.`;
|
|
69
|
+
}
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
// Published full-day closures (weekend dates omitted) for Asia-Pacific venues,
|
|
1
|
+
// Published full-day closures (weekend dates omitted) for Asia-Pacific venues and EGX,
|
|
2
2
|
// not a holiday-rule engine. A year a venue has not published is unknown, not
|
|
3
3
|
// open: every weekday of it reads as a session. Half-day sessions (HKEX and
|
|
4
4
|
// SGX eves, ASX's 14:10 closes) are not modelled. Checked 2026-10-09:
|
|
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
|
+
// BHB closes on the dates its own daily closes skip in 2026, which match the holidays it lists
|
|
9
|
+
// (some moved, as its list warns), and on National Day, 16 and 17 Dec. Its week is Sunday to Thursday.
|
|
8
10
|
// 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
|
|
9
11
|
// and https://www.hkex.com.hk/-/media/HKEX-Market/Services/Circulars-and-Notices/Participant-and-Members-Circulars/SEHK/2026/ce_SEHK_CT_077_2026.pdf
|
|
10
12
|
// SGX closes on Singapore's gazetted public holidays, one on a Sunday moving to the Monday:
|
|
11
13
|
// https://www.sgx.com/stock-exchange/trading and https://www.mom.gov.sg/employment-practices/public-holidays
|
|
14
|
+
// MSX closes on the holidays its site lists (msx.om exchange holidays, read 10 Oct 2026).
|
|
15
|
+
// Its week is Sunday to Thursday.
|
|
12
16
|
// ASX: https://www.asx.com.au/markets/market-resources/trading-hours-calendar/cash-market-trading-hours/trading-calendar
|
|
17
|
+
// EGX closes on Egypt's public holidays, often moved to the Thursday of their
|
|
18
|
+
// week (Armed Forces Day, Tuesday 6 Oct 2026, to Thursday 8 Oct, by the
|
|
19
|
+
// exchange's statement of 5 Oct). Its week is Sunday to Thursday.
|
|
13
20
|
const KRX_CLOSURES: Record<number, readonly string[]> = {
|
|
14
21
|
2026: [
|
|
15
22
|
"01-01", "02-16", "02-17", "02-18", "03-02", "05-01", "05-05", "05-25", "06-03",
|
|
@@ -34,6 +41,12 @@ export const PUBLISHED_APAC_CLOSURES: Readonly<Record<string, Record<number, rea
|
|
|
34
41
|
KOSDAQ: KRX_CLOSURES,
|
|
35
42
|
TWSE: TWSE_CLOSURES,
|
|
36
43
|
TPEX: TWSE_CLOSURES,
|
|
44
|
+
BHB: {
|
|
45
|
+
2026: [
|
|
46
|
+
"01-01", "03-22", "03-23", "03-24", "05-03", "05-26", "05-27", "05-28", "05-31", "06-16", "06-25", "06-28",
|
|
47
|
+
"08-25", "12-16", "12-17",
|
|
48
|
+
],
|
|
49
|
+
},
|
|
37
50
|
HKEX: {
|
|
38
51
|
2026: [
|
|
39
52
|
"01-01", "02-17", "02-18", "02-19", "04-03", "04-06", "04-07", "05-01", "05-25",
|
|
@@ -48,10 +61,19 @@ export const PUBLISHED_APAC_CLOSURES: Readonly<Record<string, Record<number, rea
|
|
|
48
61
|
2026: ["01-01", "02-17", "02-18", "04-03", "05-01", "05-27", "06-01", "08-10", "11-09", "12-25"],
|
|
49
62
|
2027: ["01-01", "02-08", "03-10", "03-26", "05-17", "05-20", "08-09", "10-28"],
|
|
50
63
|
},
|
|
64
|
+
MSX: {
|
|
65
|
+
2026: ["01-15", "01-18", "03-19", "03-22", "03-23", "05-26", "05-27", "05-28", "06-18", "08-27", "11-25", "11-26"],
|
|
66
|
+
},
|
|
51
67
|
ASX: {
|
|
52
68
|
2026: ["01-01", "01-26", "04-03", "04-06", "06-08", "12-25", "12-28"],
|
|
53
69
|
2027: ["01-01", "01-26", "03-26", "03-29", "06-14", "12-27", "12-28"],
|
|
54
70
|
},
|
|
71
|
+
EGX: {
|
|
72
|
+
2026: [
|
|
73
|
+
"01-01", "01-07", "01-29", "03-19", "03-22", "03-23", "04-12", "04-13", "05-07",
|
|
74
|
+
"05-26", "05-27", "05-28", "05-31", "06-18", "07-02", "07-23", "08-27", "10-08",
|
|
75
|
+
],
|
|
76
|
+
},
|
|
55
77
|
};
|
|
56
78
|
|
|
57
79
|
/** True only for a published full-day closure; unpublished years are unknown, not open. */
|