gloomberb 0.18.3 → 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/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 +84 -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 +22 -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 +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- 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/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- 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 +192 -47
- 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 +19 -13
- 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 +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- 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 +47 -10
- 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 +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +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 +305 -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 +13 -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/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/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- 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/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/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 +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -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 +29 -19
- 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 +107 -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 +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +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 +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +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 +22 -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 +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- 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 +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +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 +127 -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 +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +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 +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- 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 +6 -1
- 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/headless.ts +9 -4
- 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 +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +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 +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/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 +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +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 +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +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 +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/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/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.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/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 +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- 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/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -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/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 +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +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/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 +17 -4
- 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 +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- 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 +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -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/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +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 +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -32,6 +32,7 @@ import { useAsyncResource } from "../../../react/async-resource";
|
|
|
32
32
|
import { useShortcut } from "../../../react/input";
|
|
33
33
|
import { colors } from "../../../theme/colors";
|
|
34
34
|
import { Box, Text, TextAttributes, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
|
|
35
|
+
import { withCountryFlag } from "../../../components/ui/country-flag";
|
|
35
36
|
import { formatNumber } from "../../../utils/format";
|
|
36
37
|
import { isPlainKey } from "../../../utils/keyboard";
|
|
37
38
|
import { nextHeaderSort } from "../../../utils/sort-values";
|
|
@@ -85,7 +86,7 @@ function HiringProWall({ symbol, exchange, width, height }: { symbol: string | n
|
|
|
85
86
|
placement="jobs-wall"
|
|
86
87
|
symbol={symbol} exchange={exchange} width={width} height={height}
|
|
87
88
|
title="Hiring data is part of Gloom Cloud Pro."
|
|
88
|
-
message={`
|
|
89
|
+
message={`Gloom reads every listed company's own careers system daily: open roles over time, hiring by function and location, new roles, and pay ranges.${symbol ? ` Open ${symbol}'s hiring picture with Pro.` : ""}`}
|
|
89
90
|
/>
|
|
90
91
|
);
|
|
91
92
|
}
|
|
@@ -486,7 +487,7 @@ function CompanyView({
|
|
|
486
487
|
<Box flexDirection="column" paddingX={1} paddingTop={1}>
|
|
487
488
|
{countryRows.length === 0
|
|
488
489
|
? <Text fg={colors.textDim}>No locations in the postings collected so far.</Text>
|
|
489
|
-
: <ShareBars rows={countryRows} width={Math.min(width - 2, 80)} color={colors.warning} showDelta />}
|
|
490
|
+
: <ShareBars rows={countryRows} width={Math.min(width - 2, 80)} color={colors.warning} showDelta flags />}
|
|
490
491
|
</Box>
|
|
491
492
|
) : tab === "seniority" ? (
|
|
492
493
|
<Box flexDirection="column" paddingX={1} paddingTop={1}>
|
|
@@ -575,7 +576,7 @@ function CompanyPanel({
|
|
|
575
576
|
<PaneStatusBody
|
|
576
577
|
empty
|
|
577
578
|
emptyTitle={`No careers system found for ${symbol}.`}
|
|
578
|
-
emptyMessage="
|
|
579
|
+
emptyMessage="Gloom reads companies' own careers systems. This one either has none we can read or lists roles only on third-party job boards."
|
|
579
580
|
retry={{ onRetry: reload, pending: loading, label: "Look again", pendingLabel: "Looking again...", unchanged: "Still no careers system." }}
|
|
580
581
|
/>
|
|
581
582
|
);
|
|
@@ -682,9 +683,10 @@ function HomeView({ width, height, focused, registrationId }: { width: number; h
|
|
|
682
683
|
case "function":
|
|
683
684
|
return { text: row.function, color: colors.textDim };
|
|
684
685
|
case "country":
|
|
685
|
-
|
|
686
|
+
// The column has room for the flag beside the code and its share.
|
|
687
|
+
return withCountryFlag({ text: row.country, color: colors.textDim }, row.mover.topCountry?.code, nativePaneChrome === true);
|
|
686
688
|
}
|
|
687
|
-
}, []);
|
|
689
|
+
}, [nativePaneChrome]);
|
|
688
690
|
|
|
689
691
|
if (status === "loading" && !data) return <PaneStatusBody loading align="center" loadingLabel="Loading hiring data..." />;
|
|
690
692
|
if (status === "error" && !data) return <PaneStatusBody error={error ?? "Could not load hiring data."} errorTitle="Could not load hiring data." retry={{ onRetry: reload }} />;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { COUNTRY_FLAG_CELLS, CountryFlagLead } from "../../../components/ui/country-flag";
|
|
1
2
|
import { RatioBar } from "../../../components/ui/ratio-bar";
|
|
2
|
-
import { Box, Text, TextAttributes } from "../../../ui";
|
|
3
|
+
import { Box, Text, TextAttributes, useUiCapabilities } from "../../../ui";
|
|
3
4
|
import { colors } from "../../../theme/colors";
|
|
4
5
|
import { formatNumber, truncateToDisplayWidth } from "../../../utils/format";
|
|
5
6
|
import type { ShareBarRow } from "./model";
|
|
@@ -16,6 +17,8 @@ export interface ShareBarsProps {
|
|
|
16
17
|
color?: string;
|
|
17
18
|
/** Show the 30d delta column when any row has one. */
|
|
18
19
|
showDelta?: boolean;
|
|
20
|
+
/** Rows are countries: the desktop and the web lead each with its flag. */
|
|
21
|
+
flags?: boolean;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
const COUNT_WIDTH = 6;
|
|
@@ -36,9 +39,11 @@ function deltaColor(delta: number | null): string {
|
|
|
36
39
|
return delta > 0 ? colors.positive : colors.negative;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
export function ShareBars({ rows, width, color = colors.borderFocused, showDelta = false }: ShareBarsProps) {
|
|
42
|
+
export function ShareBars({ rows, width, color = colors.borderFocused, showDelta = false, flags = false }: ShareBarsProps) {
|
|
43
|
+
const desktop = useUiCapabilities().nativePaneChrome === true;
|
|
44
|
+
const flagged = flags && desktop;
|
|
40
45
|
const hasDelta = showDelta && rows.some((row) => row.delta != null && row.delta !== 0);
|
|
41
|
-
const labelWidth = labelWidthFor(width);
|
|
46
|
+
const labelWidth = labelWidthFor(width) + (flagged ? COUNTRY_FLAG_CELLS : 0);
|
|
42
47
|
const trailing = COUNT_WIDTH + SHARE_WIDTH + (hasDelta ? DELTA_WIDTH + 1 : 0) + 2;
|
|
43
48
|
const barWidth = Math.max(4, width - labelWidth - trailing - 2);
|
|
44
49
|
|
|
@@ -46,9 +51,10 @@ export function ShareBars({ rows, width, color = colors.borderFocused, showDelta
|
|
|
46
51
|
<Box flexDirection="column" width={width} data-gloom-ui="share-bars">
|
|
47
52
|
{rows.map((row) => (
|
|
48
53
|
<Box key={row.key} flexDirection="row" height={1} alignItems="center">
|
|
49
|
-
<Box width={labelWidth} flexShrink={0} overflow="hidden">
|
|
54
|
+
<Box width={labelWidth} flexShrink={0} overflow="hidden" flexDirection="row" alignItems="center">
|
|
55
|
+
{flagged ? <CountryFlagLead value={row.key === "rest" ? null : row.label} reserve /> : null}
|
|
50
56
|
<Text fg={row.key === "rest" ? colors.textDim : colors.text}>
|
|
51
|
-
{truncateToDisplayWidth(row.label, labelWidth - 1)}
|
|
57
|
+
{truncateToDisplayWidth(row.label, labelWidth - 1 - (flagged ? COUNTRY_FLAG_CELLS : 0))}
|
|
52
58
|
</Text>
|
|
53
59
|
</Box>
|
|
54
60
|
<RatioBar ratio={row.ratio} width={barWidth} color={color} track />
|
|
@@ -13,7 +13,8 @@ import { useAsyncResource } from "../../../react/async-resource";
|
|
|
13
13
|
import { useAutoRefresh } from "../../../react/auto-refresh";
|
|
14
14
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
15
15
|
import type { PaneProps } from "../../../types/plugin";
|
|
16
|
-
import { Box, TextAttributes } from "../../../ui";
|
|
16
|
+
import { Box, TextAttributes, useUiCapabilities } from "../../../ui";
|
|
17
|
+
import { withCountryFlag, withFlagRoom } from "../../../components/ui/country-flag";
|
|
17
18
|
import { usePluginPaneState } from "../../runtime";
|
|
18
19
|
import { fetchBalances } from "./client";
|
|
19
20
|
import {
|
|
@@ -43,7 +44,12 @@ export function JodiPane({ focused, width, height }: PaneProps) {
|
|
|
43
44
|
const board = tab === "gas" ? gas : balances?.oil ?? null;
|
|
44
45
|
const rows = board?.rows ?? EMPTY_ROWS;
|
|
45
46
|
const [selectedId, setSelectedId] = usePluginPaneState<string | null>("selected", null);
|
|
46
|
-
|
|
47
|
+
// The desktop and the web lead each country with its flag.
|
|
48
|
+
const flagged = useUiCapabilities().nativePaneChrome === true;
|
|
49
|
+
const columns = useMemo(
|
|
50
|
+
() => balanceColumns(tab).map((column) => (column.id === "country" ? withFlagRoom(column, flagged) : column)),
|
|
51
|
+
[flagged, tab],
|
|
52
|
+
);
|
|
47
53
|
const refresh = useCallback(() => {
|
|
48
54
|
resource.reload();
|
|
49
55
|
}, [resource.reload]);
|
|
@@ -84,7 +90,7 @@ export function JodiPane({ focused, width, height }: PaneProps) {
|
|
|
84
90
|
});
|
|
85
91
|
switch (column.id) {
|
|
86
92
|
case "country":
|
|
87
|
-
return { text: row.country, color: colors.textBright, attributes: TextAttributes.BOLD };
|
|
93
|
+
return withCountryFlag({ text: row.country, color: colors.textBright, attributes: TextAttributes.BOLD }, row.country, flagged);
|
|
88
94
|
case "month":
|
|
89
95
|
return { text: row.month ? formatBalanceMonth(row.month) : "—", value: row.month, color: colors.textMuted };
|
|
90
96
|
case "production":
|
|
@@ -102,7 +108,7 @@ export function JodiPane({ focused, width, height }: PaneProps) {
|
|
|
102
108
|
default:
|
|
103
109
|
return { text: "" };
|
|
104
110
|
}
|
|
105
|
-
}, [colors]);
|
|
111
|
+
}, [colors, flagged]);
|
|
106
112
|
|
|
107
113
|
if (!balances) {
|
|
108
114
|
return (
|
|
@@ -111,6 +111,7 @@ export const layoutManagerModule: PluginModule = {
|
|
|
111
111
|
name: "Layouts",
|
|
112
112
|
icon: "L",
|
|
113
113
|
component: LayoutMarketplacePane,
|
|
114
|
+
reportFreshness: { status: "not-a-feed", basis: "layout listings" },
|
|
114
115
|
defaultPosition: "right",
|
|
115
116
|
defaultMode: "floating",
|
|
116
117
|
defaultFloatingSize: { width: 118, height: 34 },
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { HeadlessPaneDefinition } from "../../../types/plugin";
|
|
2
2
|
import { resolveHeadlessInstrument } from "../shared/headless-market-data";
|
|
3
3
|
import { loadMacroDayEarnings, loadMacroDayHistory, loadMacroReleases, macroDayEarningsNotice } from "./client";
|
|
4
|
-
import { macroDayEventLabel, projectMacroDays, type MacroDayStats } from "./model";
|
|
5
|
-
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, MACRO_RELEASE_SOURCES,
|
|
4
|
+
import { macroDayEventLabel, macroDayStats, matchesSurprise, projectMacroDays, type MacroDayStats } from "./model";
|
|
5
|
+
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, MACRO_RELEASE_SOURCES, MACRO_SURPRISE_LABELS, MACRO_SURPRISES, staleMacroReleasesNotice,
|
|
6
|
+
type MacroEventKind, type MacroSurprise } from "./releases";
|
|
6
7
|
|
|
7
8
|
// A mean that rounds to zero reads 0.00%, never -0.00%.
|
|
8
9
|
const percent = (value: unknown) => typeof value !== "number" ? "--" : /[1-9]/.test((value * 100).toFixed(2)) ? `${(value * 100).toFixed(2)}%` : "0.00%";
|
|
@@ -17,12 +18,16 @@ export const macroDayHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
17
18
|
describe: (args) => `MDAY ${args.symbols[0] ?? ""}`,
|
|
18
19
|
discovery: { screenshotReadiness: "live-dom", limitations: [
|
|
19
20
|
"US listings; close-to-close on the release day.",
|
|
20
|
-
"Published CPI, jobs and FOMC days; sessions after the list's last covered day (releasesThrough) are left out.",
|
|
21
|
+
"Published CPI, jobs and FOMC days, and Brazil's IPCA days from Gloom Cloud; sessions after the list's last covered day (releasesThrough) are left out.",
|
|
22
|
+
"Actual, forecast and prior for the days Gloom Cloud has them (the US headlines from its kept economic calendar, IPCA from the central bank's SGS series); --surprise keeps the days that came in hot, cool or in line with the forecast.",
|
|
21
23
|
"A release day that is also the reaction session of the company's own earnings report is marked earnings and left out of the release averages and the normal day.",
|
|
22
24
|
] },
|
|
23
25
|
options: [
|
|
24
26
|
{ key: "release", type: "enum", values: [{ value: "all" }, ...MACRO_EVENT_KINDS.map((value) => ({ value }))], defaultValue: "all",
|
|
25
27
|
description: "Release the pane lists", pluginState: { pluginId: "ticker-research", key: "release" } },
|
|
28
|
+
{ key: "surprise", type: "enum", values: [{ value: "all" }, ...MACRO_SURPRISES.map((value) => ({ value }))], defaultValue: "all",
|
|
29
|
+
description: "Release days whose print came in above (hot), below (cool) or at (in-line) the forecast",
|
|
30
|
+
example: "--release cpi --surprise hot", pluginState: { pluginId: "ticker-research", key: "surprise" } },
|
|
26
31
|
{ key: "lookbackYears", type: "integer", minimum: 1, maximum: 5, defaultValue: 5, description: "Years of daily closes" },
|
|
27
32
|
],
|
|
28
33
|
async load(args, ctx) {
|
|
@@ -35,17 +40,25 @@ export const macroDayHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
35
40
|
const notes = [staleMacroReleasesNotice(releases), macroDayEarningsNotice(earnings)].filter((note): note is string => !!note);
|
|
36
41
|
const row = (label: string, stats: MacroDayStats) => ({ label, ...stats });
|
|
37
42
|
const release = String(args.options.release ?? "all");
|
|
38
|
-
const
|
|
43
|
+
const surprise = String(args.options.surprise ?? "all") as MacroSurprise | "all";
|
|
44
|
+
const events = model.events.filter((event) => (release === "all" || event.kind === release) && matchesSurprise(event, surprise));
|
|
45
|
+
// The days the filter keeps get a row of their own: how the name moved on hot CPI days.
|
|
46
|
+
const selected = surprise === "all" ? [] : [row(`${MACRO_SURPRISE_LABELS[surprise]} ${release === "all" ? "release"
|
|
47
|
+
: MACRO_EVENT_LABELS[release as MacroEventKind]}`, macroDayStats(events, model.normal.meanAbs))];
|
|
39
48
|
return {
|
|
40
49
|
sections: [
|
|
41
50
|
{ title: "By release", columns: [{ key: "label", header: "Day" }, { key: "count", header: "Days" },
|
|
42
51
|
{ key: "meanAbs", header: "Avg |move|", format: percent }, { key: "multiple", header: "vs normal", format: multiple },
|
|
43
52
|
{ key: "mean", header: "Avg move", format: percent }, { key: "hitRate", header: "Up", format: share }],
|
|
44
|
-
rows: [...
|
|
45
|
-
row("Any release", model.allEvents), ...(model.earnings.count ? [row("Earnings", model.earnings)] : []), row("Normal day", model.normal)] },
|
|
53
|
+
rows: [...model.kinds.map((kind) => row(MACRO_EVENT_LABELS[kind], model.byKind[kind])), ...selected,
|
|
54
|
+
row(model.kinds.includes("ipca") ? "Any US release" : "Any release", model.allEvents), ...(model.earnings.count ? [row("Earnings", model.earnings)] : []), row("Normal day", model.normal)] },
|
|
46
55
|
{ title: "Release days", columns: [{ key: "date", header: "Date" }, { key: "event", header: "Release" },
|
|
56
|
+
{ key: "actual", header: "Actual" }, { key: "forecast", header: "Forecast" }, { key: "prior", header: "Prior" },
|
|
57
|
+
{ key: "surprise", header: "Surprise" },
|
|
47
58
|
{ key: "session", header: "Session" }, { key: "move", header: "Move", format: percent }, { key: "multiple", header: "vs normal", format: multiple }],
|
|
48
|
-
rows: events.map((event) => ({ ...event, event: macroDayEventLabel(event)
|
|
59
|
+
rows: events.map(({ figures, ...event }) => ({ ...event, event: macroDayEventLabel(event), actual: figures?.actual ?? null,
|
|
60
|
+
forecast: figures?.forecast ?? null, prior: figures?.prior ?? null, surprise: figures?.surprise ?? null,
|
|
61
|
+
...(figures ? { headline: figures.event } : {}) })) },
|
|
49
62
|
],
|
|
50
63
|
complete: !history.stale && !earnings.stale && !history.error && !notes.length && model.events.length > 0,
|
|
51
64
|
unavailableSymbols: model.events.length ? [] : [instrument.symbol],
|
|
@@ -15,8 +15,9 @@ export const macroDayModule: PluginModule = {
|
|
|
15
15
|
}],
|
|
16
16
|
paneTemplates: [{ ...createTickerSurfacePaneTemplate({
|
|
17
17
|
id: "macro-day-pane", paneId: "macro-day", label: "Macro-Day Reaction",
|
|
18
|
-
description: "How a name moves on CPI, jobs and
|
|
19
|
-
keywords: ["mday", "macro day", "cpi day", "fomc day", "jobs day", "nfp", "payrolls", "event study", "release reaction"
|
|
18
|
+
description: "How a name moves on CPI, jobs, FOMC and Brazil IPCA days against a normal day: average move, direction, hit rate, and every release day with its actual, forecast and prior.",
|
|
19
|
+
keywords: ["mday", "macro day", "cpi day", "fomc day", "jobs day", "nfp", "payrolls", "event study", "release reaction", "ipca",
|
|
20
|
+
"hot cpi", "cpi surprise", "release surprise"],
|
|
20
21
|
shortcut: "MDAY", publicShare: true,
|
|
21
22
|
}), headless: macroDayHeadless }],
|
|
22
23
|
setup(ctx) { macroReleaseCache.attach(ctx.persistence); },
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { EarningsTiming } from "../../../api-client/earnings";
|
|
2
2
|
import type { PricePoint } from "../../../types/financials";
|
|
3
3
|
import { zonedDateTimeParts } from "../../../utils/zoned-date-time";
|
|
4
|
-
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, type MacroEventKind, type MacroRelease
|
|
4
|
+
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, US_MACRO_EVENT_KINDS, type MacroEventKind, type MacroRelease, type MacroReleaseFigures,
|
|
5
|
+
type MacroSurprise } from "./releases";
|
|
5
6
|
|
|
6
7
|
const DAY_MS = 86_400_000;
|
|
7
8
|
/** Longest calendar gap between two closes that is still one session apart: Thursday to Monday over a Friday holiday. */
|
|
@@ -28,6 +29,8 @@ export interface MacroDayEvent {
|
|
|
28
29
|
move: number;
|
|
29
30
|
/** |move| over the normal day's average |move|. */
|
|
30
31
|
multiple: number | null;
|
|
32
|
+
/** What the release came out with, when the list has it. */
|
|
33
|
+
figures: MacroReleaseFigures | null;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
export interface MacroDayStats {
|
|
@@ -44,13 +47,19 @@ export interface MacroDayModel {
|
|
|
44
47
|
symbol: string;
|
|
45
48
|
/** Newest first. */
|
|
46
49
|
events: MacroDayEvent[];
|
|
50
|
+
/** The kinds the list carries: the US releases, and IPCA when Gloom Cloud lists its days. */
|
|
51
|
+
kinds: MacroEventKind[];
|
|
47
52
|
/** Without the earnings days. */
|
|
48
53
|
byKind: Record<MacroEventKind, MacroDayStats>;
|
|
49
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Every US release day together, without the earnings days; a day with two
|
|
56
|
+
* releases counts once. IPCA days are summed up on their own only, so a US
|
|
57
|
+
* name's figures do not move with Brazil's calendar.
|
|
58
|
+
*/
|
|
50
59
|
allEvents: MacroDayStats;
|
|
51
|
-
/**
|
|
60
|
+
/** US release days that are the ticker's earnings reaction, which no other figure counts; a day with two releases counts once. */
|
|
52
61
|
earnings: MacroDayStats;
|
|
53
|
-
/** Sessions with no release
|
|
62
|
+
/** Sessions with no US release, and none of the earnings days among them. */
|
|
54
63
|
normal: MacroDayStats;
|
|
55
64
|
start: string | null;
|
|
56
65
|
asOf: string | null;
|
|
@@ -70,6 +79,15 @@ function sessionDate(time: number): string {
|
|
|
70
79
|
const dayNumber = (date: string) => Date.parse(`${date}T00:00:00Z`) / DAY_MS;
|
|
71
80
|
const isWeekday = (date: string) => { const day = new Date(`${date}T00:00:00Z`).getUTCDay(); return day > 0 && day < 6; };
|
|
72
81
|
|
|
82
|
+
/** The figures over some of the model's release days (the hot CPI days): their moves, the earnings days left out as the kinds' are. */
|
|
83
|
+
export function macroDayStats(events: readonly MacroDayEvent[], normalAbs: number | null): MacroDayStats {
|
|
84
|
+
return stats(events.filter((event) => !event.earnings).map((event) => event.move), normalAbs);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Whether a release day's print matches a surprise filter; `all` matches every day, figures or not. */
|
|
88
|
+
export const matchesSurprise = (event: Pick<MacroDayEvent, "figures">, surprise: MacroSurprise | "all") =>
|
|
89
|
+
surprise === "all" || event.figures?.surprise === surprise;
|
|
90
|
+
|
|
73
91
|
function stats(moves: number[], normalAbs: number | null): MacroDayStats {
|
|
74
92
|
if (!moves.length) return { count: 0, meanAbs: null, mean: null, hitRate: null, multiple: null };
|
|
75
93
|
const meanAbs = moves.reduce((sum, move) => sum + Math.abs(move), 0) / moves.length;
|
|
@@ -99,6 +117,8 @@ function earningsReactionSessions(reports: readonly MacroDayEarningsReport[], se
|
|
|
99
117
|
return reacted;
|
|
100
118
|
}
|
|
101
119
|
|
|
120
|
+
const US_KINDS: ReadonlySet<MacroEventKind> = new Set(US_MACRO_EVENT_KINDS);
|
|
121
|
+
|
|
102
122
|
/**
|
|
103
123
|
* Close to close on the release day: 8:30 ET releases land before the open
|
|
104
124
|
* and 14:00 FOMC statements before the close, so the release day's close
|
|
@@ -129,7 +149,8 @@ export function projectMacroDays(history: readonly PricePoint[], options: {
|
|
|
129
149
|
const sessions = [...byDate.keys()].sort();
|
|
130
150
|
const last = sessions.at(-1) ?? null;
|
|
131
151
|
const empty = (): MacroDayStats => stats([], null);
|
|
132
|
-
|
|
152
|
+
const kinds = MACRO_EVENT_KINDS.filter((kind) => US_KINDS.has(kind) || options.releases.some((release) => release.kind === kind));
|
|
153
|
+
if (!last) return { symbol: options.symbol, events: [], kinds, byKind: { cpi: empty(), jobs: empty(), fomc: empty(), ipca: empty() },
|
|
133
154
|
allEvents: empty(), earnings: empty(), normal: empty(), start: null, asOf: null };
|
|
134
155
|
|
|
135
156
|
// Sessions after the published lists end may be unlisted release days, so they are left out of both sides.
|
|
@@ -157,8 +178,8 @@ export function projectMacroDays(history: readonly PricePoint[], options: {
|
|
|
157
178
|
const session = sessions[at]!;
|
|
158
179
|
const move = moves.get(session);
|
|
159
180
|
if (move == null || (session !== release.date && skipsAnotherWeekday(release.date, sessions[at - 1]!, session))) continue;
|
|
160
|
-
reactionSessions.add(session);
|
|
161
|
-
found.push({ kind: release.kind, date: release.date, session, move });
|
|
181
|
+
if (US_KINDS.has(release.kind)) reactionSessions.add(session);
|
|
182
|
+
found.push({ kind: release.kind, date: release.date, session, move, figures: release.figures ?? null });
|
|
162
183
|
}
|
|
163
184
|
|
|
164
185
|
const normalMoves = [...moves].filter(([date]) => !reactionSessions.has(date)).map(([, move]) => move);
|
|
@@ -170,7 +191,7 @@ export function projectMacroDays(history: readonly PricePoint[], options: {
|
|
|
170
191
|
const byKind = Object.fromEntries(MACRO_EVENT_KINDS.map((kind) =>
|
|
171
192
|
[kind, stats(events.filter((event) => event.kind === kind && !event.earnings).map((event) => event.move), normalAbs)])) as Record<MacroEventKind, MacroDayStats>;
|
|
172
193
|
const sessionMoves = (flagged: boolean) => [...reactionSessions].filter((session) => reacted.has(session) === flagged).map((session) => moves.get(session)!);
|
|
173
|
-
return { symbol: options.symbol, events, byKind, allEvents: stats(sessionMoves(false), normalAbs), earnings: stats(sessionMoves(true), normalAbs),
|
|
194
|
+
return { symbol: options.symbol, events, kinds, byKind, allEvents: stats(sessionMoves(false), normalAbs), earnings: stats(sessionMoves(true), normalAbs),
|
|
174
195
|
normal, start, asOf: end };
|
|
175
196
|
}
|
|
176
197
|
|
|
@@ -2,6 +2,8 @@ import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
|
2
2
|
import { DataTableView, EmptyState, PaneStatusBody, QueryBar, StatGrid, statGridRows, usePaneFooter, usePaneNoticeFooter,
|
|
3
3
|
usePaneTicker, type DataTableCell, type DataTableColumn, type StatItem } from "../../../components";
|
|
4
4
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
5
|
+
import { tableColumnWidth } from "../../../components/ui/table-layout";
|
|
6
|
+
import { displayWidth } from "../../../utils/format";
|
|
5
7
|
import { instrumentFromTicker } from "../../../market-data/request-types";
|
|
6
8
|
import { usePaneSettingValue, usePluginPaneState } from "../../../public/react";
|
|
7
9
|
import { useAsyncResource } from "../../../react/async-resource";
|
|
@@ -10,11 +12,13 @@ import { useThemeColors } from "../../../theme/theme-context";
|
|
|
10
12
|
import type { PaneProps } from "../../../types/plugin";
|
|
11
13
|
import { Box } from "../../../ui";
|
|
12
14
|
import { loadMacroDayEarnings, loadMacroDayHistory, loadMacroReleases, macroDayEarningsNotice } from "./client";
|
|
13
|
-
import { macroDayEventLabel, projectMacroDays, type MacroDayEvent, type MacroDayModel } from "./model";
|
|
14
|
-
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, staleMacroReleasesNotice, type MacroEventKind
|
|
15
|
+
import { macroDayEventLabel, macroDayStats, matchesSurprise, projectMacroDays, type MacroDayEvent, type MacroDayModel } from "./model";
|
|
16
|
+
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, MACRO_SURPRISE_LABELS, MACRO_SURPRISES, staleMacroReleasesNotice, type MacroEventKind,
|
|
17
|
+
type MacroSurprise } from "./releases";
|
|
15
18
|
|
|
16
19
|
export const LOOKBACK_OPTIONS = [{ value: "1", label: "1Y" }, { value: "2", label: "2Y" }, { value: "3", label: "3Y" }, { value: "5", label: "5Y" }];
|
|
17
20
|
const RELEASE_OPTIONS = [{ value: "all", label: "All" }, ...MACRO_EVENT_KINDS.map((kind) => ({ value: kind, label: MACRO_EVENT_LABELS[kind] }))];
|
|
21
|
+
const SURPRISE_OPTIONS = [{ value: "all", label: "All" }, ...MACRO_SURPRISES.map((surprise) => ({ value: surprise, label: MACRO_SURPRISE_LABELS[surprise] }))];
|
|
18
22
|
|
|
19
23
|
function pct(value: number | null | undefined, signed = true): string {
|
|
20
24
|
if (value == null) return "--";
|
|
@@ -29,21 +33,45 @@ const MOVE: DataTableColumn[] = [
|
|
|
29
33
|
{ id: "move", label: "Move", width: 9, align: "right" },
|
|
30
34
|
{ id: "multiple", label: "vs Normal", width: 10, align: "right" },
|
|
31
35
|
];
|
|
36
|
+
/** What each release came out with, under the labels the economic calendar gives them. */
|
|
37
|
+
const FIGURES = [["actual", "Actual"], ["forecast", "Forecast"], ["prior", "Prior"]] as const;
|
|
38
|
+
|
|
39
|
+
/** The figure columns, shown once any listed day has figures, each as wide as its header and its widest value. */
|
|
40
|
+
function figureColumns(rows: readonly MacroDayEvent[]): DataTableColumn[] {
|
|
41
|
+
if (!rows.some((event) => event.figures)) return [];
|
|
42
|
+
return FIGURES.map(([id, label]) => ({ id, label, align: "right", width: tableColumnWidth({ label,
|
|
43
|
+
width: Math.max(6, ...rows.map((event) => displayWidth(event.figures?.[id] ?? ""))) }) }));
|
|
44
|
+
}
|
|
32
45
|
|
|
33
46
|
/**
|
|
34
47
|
* With every release listed, the release's name, widened to take the earnings marker where a row has one. With one
|
|
35
48
|
* selected, a column only for the marker: every row would repeat the name.
|
|
36
49
|
*/
|
|
37
|
-
function columnsFor(release: string, rows: readonly MacroDayEvent[]): DataTableColumn[] {
|
|
50
|
+
export function columnsFor(release: string, rows: readonly MacroDayEvent[]): DataTableColumn[] {
|
|
38
51
|
const marked = rows.some((event) => event.earnings);
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
const values = [...figureColumns(rows), ...MOVE];
|
|
53
|
+
if (release === "all") return [DATE, { id: "release", label: "Release", width: marked ? 15 : 8, align: "left" }, ...values];
|
|
54
|
+
return marked ? [DATE, { id: "release", label: "Note", width: EARNINGS_MARK.length, align: "left" }, ...values] : [DATE, ...values];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const tone = (value: number | null) => value == null ? undefined : value >= 0 ? "positive" as const : "negative" as const;
|
|
58
|
+
|
|
59
|
+
/** The figures over the days a surprise filter keeps: the same four as one release's. */
|
|
60
|
+
function surpriseFigures(model: MacroDayModel, rows: readonly MacroDayEvent[]): StatItem[] {
|
|
61
|
+
const stats = macroDayStats(rows, model.normal.meanAbs);
|
|
62
|
+
return [
|
|
63
|
+
{ id: "abs", label: "Avg |move|", value: pct(stats.meanAbs, false), detail: stats.count ? `${times(stats.multiple)} normal` : undefined },
|
|
64
|
+
{ id: "mean", label: "Avg move", value: pct(stats.mean), tone: tone(stats.mean) },
|
|
65
|
+
{ id: "up", label: "Up", value: stats.hitRate == null ? "--" : `${Math.round(stats.hitRate * 100)}%`,
|
|
66
|
+
detail: stats.count ? `${Math.round(stats.hitRate! * stats.count)} of ${stats.count}` : undefined },
|
|
67
|
+
{ id: "normal", label: "Normal day", value: pct(model.normal.meanAbs, false), detail: "avg |move|" },
|
|
68
|
+
];
|
|
41
69
|
}
|
|
42
70
|
|
|
43
71
|
function figures(model: MacroDayModel, release: string): StatItem[] {
|
|
44
72
|
const normal: StatItem = { id: "normal", label: "Normal day", value: pct(model.normal.meanAbs, false), detail: "avg |move|" };
|
|
45
73
|
if (release === "all") {
|
|
46
|
-
return [...
|
|
74
|
+
return [...model.kinds.map((kind): StatItem => {
|
|
47
75
|
const stats = model.byKind[kind];
|
|
48
76
|
return { id: kind, label: `${MACRO_EVENT_LABELS[kind]} day`, value: pct(stats.meanAbs, false),
|
|
49
77
|
detail: stats.count ? `${times(stats.multiple)} normal` : undefined };
|
|
@@ -51,7 +79,6 @@ function figures(model: MacroDayModel, release: string): StatItem[] {
|
|
|
51
79
|
detail: `${times(model.earnings.multiple)} normal` }] : []), normal];
|
|
52
80
|
}
|
|
53
81
|
const stats = model.byKind[release as MacroEventKind];
|
|
54
|
-
const tone = (value: number | null) => value == null ? undefined : value >= 0 ? "positive" as const : "negative" as const;
|
|
55
82
|
return [
|
|
56
83
|
{ id: "abs", label: "Avg |move|", value: pct(stats.meanAbs, false), detail: stats.count ? `${times(stats.multiple)} normal` : undefined },
|
|
57
84
|
{ id: "mean", label: "Avg move", value: pct(stats.mean), tone: tone(stats.mean) },
|
|
@@ -66,6 +93,7 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
66
93
|
const { symbol, ticker, error: identityError } = usePaneTicker();
|
|
67
94
|
const [lookback, setLookback] = usePaneSettingValue("lookbackYears", "5");
|
|
68
95
|
const [release, setRelease] = usePluginPaneState("release", "all");
|
|
96
|
+
const [surprise, setSurprise] = usePluginPaneState<MacroSurprise | "all">("surprise", "all");
|
|
69
97
|
const [selectedRow, setSelectedRow] = usePluginPaneState<string | null>("selectedRow", null);
|
|
70
98
|
const instrument = instrumentFromTicker(ticker, symbol);
|
|
71
99
|
const instrumentKey = JSON.stringify(instrument);
|
|
@@ -88,8 +116,10 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
88
116
|
[history.data, lookback, symbol]);
|
|
89
117
|
const releasesNotice = history.data ? staleMacroReleasesNotice(history.data.releases) : null;
|
|
90
118
|
const earningsNotice = history.data ? macroDayEarningsNotice(history.data.earnings) : null;
|
|
91
|
-
const rows = useMemo(() => model ? model.events.filter((event) => release === "all" || event.kind === release)
|
|
92
|
-
|
|
119
|
+
const rows = useMemo(() => model ? model.events.filter((event) => (release === "all" || event.kind === release)
|
|
120
|
+
&& matchesSurprise(event, surprise)) : [], [model, release, surprise]);
|
|
121
|
+
const stats = useMemo(() => !model?.events.length ? [] : surprise === "all" ? figures(model, release) : surpriseFigures(model, rows),
|
|
122
|
+
[model, release, surprise, rows]);
|
|
93
123
|
const columns = useMemo(() => columnsFor(release, rows), [release, rows]);
|
|
94
124
|
|
|
95
125
|
usePaneNoticeFooter({ registrationId: "macro-day-notices", focused,
|
|
@@ -103,6 +133,11 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
103
133
|
const renderCell = useCallback((event: MacroDayEvent, column: DataTableColumn): DataTableCell => {
|
|
104
134
|
if (column.id === "date") return { text: event.session === event.date ? event.date : `${event.date} → ${event.session.slice(5)}`, value: event.date };
|
|
105
135
|
if (column.id === "release") return { text: release === "all" ? macroDayEventLabel(event) : event.earnings ? EARNINGS_MARK : "" };
|
|
136
|
+
// The print colored against the consensus, as the economic calendar colors it.
|
|
137
|
+
if (column.id === "actual") return { text: event.figures?.actual ?? "", color: event.figures?.surprise === "hot" ? colors.positive
|
|
138
|
+
: event.figures?.surprise === "cool" ? colors.negative : undefined };
|
|
139
|
+
if (column.id === "forecast") return { text: event.figures?.forecast ?? "" };
|
|
140
|
+
if (column.id === "prior") return { text: event.figures?.prior ?? "" };
|
|
106
141
|
if (column.id === "move") return { text: pct(event.move), value: event.move * 100,
|
|
107
142
|
color: event.move > 0 ? colors.positive : event.move < 0 ? colors.negative : undefined };
|
|
108
143
|
return { text: times(event.multiple), value: event.multiple };
|
|
@@ -114,6 +149,7 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
114
149
|
return <Box width={width} height={height} flexDirection="column" overflow="hidden">
|
|
115
150
|
<QueryBar width={width} filters={[
|
|
116
151
|
{ id: "release", label: "Release", value: release, options: RELEASE_OPTIONS, onChange: setRelease, inline: true },
|
|
152
|
+
{ id: "surprise", label: "Surprise", value: surprise, options: SURPRISE_OPTIONS, onChange: (value) => setSurprise(value as MacroSurprise | "all") },
|
|
117
153
|
{ id: "lookback", label: "Lookback", value: String(lookback), options: LOOKBACK_OPTIONS, onChange: setLookback },
|
|
118
154
|
]} />
|
|
119
155
|
{!symbol ? <EmptyState title="Select a ticker." /> : <PaneStatusBody subject="macro-day moves" loading={history.loading && !model}
|
|
@@ -121,7 +157,7 @@ export function MacroDayPane({ width, height, focused }: PaneProps) {
|
|
|
121
157
|
{model ? <>
|
|
122
158
|
<StatGrid items={stats} width={width} />
|
|
123
159
|
<DataTableView<MacroDayEvent> focused={focused} columns={columns} items={rows} rootWidth={width} rootHeight={contentHeight}
|
|
124
|
-
getItemKey={key} emptyStateTitle="No release days." sortColumnId={null} sortDirection="desc" selectedTextOverridesCellColor
|
|
160
|
+
getItemKey={key} emptyStateTitle={surprise === "all" ? "No release days." : `No ${MACRO_SURPRISE_LABELS[surprise].toLowerCase()} prints.`} sortColumnId={null} sortDirection="desc" selectedTextOverridesCellColor
|
|
125
161
|
selection={{ kind: "id", selectedId: selectedRow, getId: key, onChange: (id) => setSelectedRow(id) }}
|
|
126
162
|
getExportMetadata={() => [["symbol", model.symbol], ["from", model.start ?? ""], ["to", model.asOf ?? ""],
|
|
127
163
|
["units", "percent, close to close on the release day"]]}
|
|
@@ -1,27 +1,47 @@
|
|
|
1
|
-
// Published
|
|
1
|
+
// Published release days, not a rule engine: the dates each release came
|
|
2
2
|
// out, read from the publishers' own archives. A release cancelled or moved (the
|
|
3
3
|
// 2025 shutdown) is as published, and a scheduled date is not a release day
|
|
4
|
-
// until it is out. Dates are New York calendar days.
|
|
4
|
+
// until it is out. Dates are New York calendar days. Brazil's IPCA days come
|
|
5
|
+
// from Gloom Cloud only; the list the app ships with has the US releases.
|
|
5
6
|
import { zonedDateKey } from "../../../utils/zoned-date-time";
|
|
6
7
|
import { MACRO_RELEASE_TABLE } from "./release-table";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/** The US releases the bundled list carries, and the ones HIVG reads around. */
|
|
10
|
+
export type UsMacroEventKind = "cpi" | "jobs" | "fomc";
|
|
11
|
+
export type MacroEventKind = UsMacroEventKind | "ipca";
|
|
9
12
|
|
|
10
|
-
export const
|
|
13
|
+
export const US_MACRO_EVENT_KINDS: readonly UsMacroEventKind[] = ["cpi", "jobs", "fomc"];
|
|
14
|
+
export const MACRO_EVENT_KINDS: readonly MacroEventKind[] = [...US_MACRO_EVENT_KINDS, "ipca"];
|
|
11
15
|
|
|
12
|
-
export const MACRO_EVENT_LABELS: Record<MacroEventKind, string> = { cpi: "CPI", jobs: "Jobs", fomc: "FOMC" };
|
|
16
|
+
export const MACRO_EVENT_LABELS: Record<MacroEventKind, string> = { cpi: "CPI", jobs: "Jobs", fomc: "FOMC", ipca: "IPCA" };
|
|
13
17
|
|
|
14
|
-
/** BLS news release archives for CPI and the Employment Situation,
|
|
18
|
+
/** BLS news release archives for CPI and the Employment Situation, the Federal Reserve's meeting calendar, IBGE's calendar. */
|
|
15
19
|
export const MACRO_RELEASE_SOURCES: Record<MacroEventKind, string> = {
|
|
16
20
|
cpi: "https://www.bls.gov/bls/news-release/cpi.htm",
|
|
17
21
|
jobs: "https://www.bls.gov/bls/news-release/empsit.htm",
|
|
18
22
|
fomc: "https://www.federalreserve.gov/monetarypolicy/fomccalendars.htm",
|
|
23
|
+
ipca: "https://www.ibge.gov.br/calendario-indicadores-novoportal.html",
|
|
19
24
|
};
|
|
20
25
|
|
|
21
26
|
/** A list more than this many days behind today says so: a release day may be missing from its end. */
|
|
22
27
|
export const MACRO_RELEASES_STALE_DAYS = 14;
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
/** Above the consensus (hot), below it (cool), at it (in-line). */
|
|
30
|
+
export type MacroSurprise = "hot" | "cool" | "in-line";
|
|
31
|
+
export const MACRO_SURPRISES: readonly MacroSurprise[] = ["hot", "cool", "in-line"];
|
|
32
|
+
export const MACRO_SURPRISE_LABELS: Record<MacroSurprise, string> = { hot: "Hot", cool: "Cool", "in-line": "In line" };
|
|
33
|
+
|
|
34
|
+
/** What a release day came out with: the headline, its print, the consensus before it and the figure before that. */
|
|
35
|
+
export interface MacroReleaseFigures {
|
|
36
|
+
/** The headline the figures are for: "Inflation Rate YoY", "IPCA m/m". */
|
|
37
|
+
event: string;
|
|
38
|
+
actual: string | null;
|
|
39
|
+
forecast: string | null;
|
|
40
|
+
prior: string | null;
|
|
41
|
+
surprise: MacroSurprise | null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MacroRelease { kind: MacroEventKind; date: string; figures?: MacroReleaseFigures }
|
|
25
45
|
|
|
26
46
|
export interface MacroReleaseList {
|
|
27
47
|
/** Oldest first. */
|
|
@@ -37,29 +57,51 @@ const byDate = (left: MacroRelease, right: MacroRelease) => left.date.localeComp
|
|
|
37
57
|
|
|
38
58
|
/** The list the app ships with: the floor whenever the server's list is missing or older. */
|
|
39
59
|
export function bundledMacroReleases(): MacroReleaseList {
|
|
40
|
-
const releases =
|
|
60
|
+
const releases = US_MACRO_EVENT_KINDS.flatMap((kind) => Object.entries(MACRO_RELEASE_TABLE.days[kind]).flatMap(([year, days]) =>
|
|
41
61
|
days.map((day) => ({ kind, date: `${year}-${day}` }))));
|
|
42
62
|
return { releases: releases.sort(byDate), coveredThrough: MACRO_RELEASE_TABLE.coveredThrough };
|
|
43
63
|
}
|
|
44
64
|
|
|
65
|
+
const text = (value: unknown) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
66
|
+
|
|
67
|
+
/** A day's figures as served, or undefined when they break the contract. */
|
|
68
|
+
function servedFigures(value: unknown): MacroReleaseFigures | undefined {
|
|
69
|
+
const figures = value as Partial<Record<keyof MacroReleaseFigures, unknown>> | null;
|
|
70
|
+
const event = text(figures?.event);
|
|
71
|
+
if (!event) return undefined;
|
|
72
|
+
const surprise = MACRO_SURPRISES.find((candidate) => candidate === figures?.surprise) ?? null;
|
|
73
|
+
return { event, actual: text(figures?.actual), forecast: text(figures?.forecast), prior: text(figures?.prior), surprise };
|
|
74
|
+
}
|
|
75
|
+
|
|
45
76
|
/**
|
|
46
77
|
* The served list extends the floor past its end; the floor keeps its own
|
|
47
|
-
* days up to there.
|
|
48
|
-
*
|
|
78
|
+
* days up to there. IPCA, which the floor does not carry, is the served list's
|
|
79
|
+
* through its end, and left out when the server lists none. Every day takes
|
|
80
|
+
* the figures the server has for it. A served list that breaks the contract,
|
|
81
|
+
* or ends no later than the floor, adds nothing.
|
|
49
82
|
*/
|
|
50
83
|
export function mergeMacroReleases(floor: MacroReleaseList, served: unknown): MacroReleaseList {
|
|
51
|
-
const payload = served as { coveredThrough?: unknown; releases?: Partial<Record<MacroEventKind, unknown
|
|
84
|
+
const payload = served as { coveredThrough?: unknown; releases?: Partial<Record<MacroEventKind, unknown>>;
|
|
85
|
+
figures?: Partial<Record<MacroEventKind, Record<string, unknown>>> } | null;
|
|
52
86
|
const coveredThrough = payload?.coveredThrough;
|
|
53
87
|
if (!isDate(coveredThrough) || coveredThrough <= floor.coveredThrough) return floor;
|
|
54
88
|
const later: MacroRelease[] = [];
|
|
55
|
-
for (const kind of
|
|
89
|
+
for (const kind of US_MACRO_EVENT_KINDS) {
|
|
56
90
|
const dates = payload?.releases?.[kind];
|
|
57
91
|
if (!Array.isArray(dates) || !dates.every(isDate)) return floor;
|
|
58
92
|
for (const date of new Set(dates)) {
|
|
59
93
|
if (date > floor.coveredThrough && date <= coveredThrough) later.push({ kind, date });
|
|
60
94
|
}
|
|
61
95
|
}
|
|
62
|
-
|
|
96
|
+
const ipca = payload?.releases?.ipca;
|
|
97
|
+
if (Array.isArray(ipca) && ipca.every(isDate)) {
|
|
98
|
+
for (const date of new Set(ipca)) if (date <= coveredThrough) later.push({ kind: "ipca", date });
|
|
99
|
+
}
|
|
100
|
+
const figuresOf = (release: MacroRelease): MacroRelease => {
|
|
101
|
+
const figures = servedFigures(payload?.figures?.[release.kind]?.[release.date]);
|
|
102
|
+
return figures ? { ...release, figures } : release;
|
|
103
|
+
};
|
|
104
|
+
return { releases: [...floor.releases, ...later].map(figuresOf).sort(byDate), coveredThrough };
|
|
63
105
|
}
|
|
64
106
|
|
|
65
107
|
/** Whole days from the list's last covered day to today in New York. */
|
|
@@ -31,7 +31,14 @@ export interface MarketHeatmapBoard extends MarketHeatmapResult {
|
|
|
31
31
|
const DEFAULT_COUNT = 80;
|
|
32
32
|
/** The most names one board asks for; a server that serves fewer answers with its own maximum. */
|
|
33
33
|
const MAX_MARKET_HEATMAP_COUNT = 500;
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* How often a board is worth checking again: a real-time board's live read
|
|
36
|
+
* is renewed every 15 seconds on the server, a delayed board's snapshot is
|
|
37
|
+
* cached there for a minute.
|
|
38
|
+
*/
|
|
39
|
+
export function heatmapCheckIntervalMs(board: Pick<MarketHeatmapResult, "access"> | null | undefined): number {
|
|
40
|
+
return board?.access === "realtime" ? 15_000 : 60_000;
|
|
41
|
+
}
|
|
35
42
|
const activeFetches = new Map<string, Promise<MarketHeatmapBoard>>();
|
|
36
43
|
const memoryCache = new Map<string, { expiresAt: number; result: MarketHeatmapBoard }>();
|
|
37
44
|
|
|
@@ -90,7 +97,7 @@ export async function fetchMarketHeatmap(
|
|
|
90
97
|
const fetchPromise = loadMarketHeatmap(universe, count, sources)
|
|
91
98
|
.then((result) => {
|
|
92
99
|
if (useCache) {
|
|
93
|
-
memoryCache.set(cacheKey, { result, expiresAt: Date.now() +
|
|
100
|
+
memoryCache.set(cacheKey, { result, expiresAt: Date.now() + heatmapCheckIntervalMs(result) });
|
|
94
101
|
}
|
|
95
102
|
return result;
|
|
96
103
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What `
|
|
2
|
+
* What `gloom shot HM` certifies: the tab the heat map drew, what its tiles
|
|
3
3
|
* are sized by, how many tiles and sectors are plotted, and whether its
|
|
4
4
|
* snapshot had loaded. The heat map has
|
|
5
5
|
* no table rows or labeled values, so this is how a capture counts as data.
|