gloomberb 0.16.4 → 0.16.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -91
- package/package.json +4 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
- package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
- package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/data.ts +24 -2
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +4 -1
- package/src/api-client/market-discovery.ts +10 -1
- package/src/api-client/paths.ts +7 -0
- package/src/api-client/research-activity.ts +15 -10
- package/src/api-client/types.ts +17 -1
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +15 -1
- package/src/app/pane-runtime/ticker-open-runtime.ts +7 -3
- package/src/architecture/core-builtin-allowlist.json +4 -13
- package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
- package/src/capabilities/chart-series.ts +11 -1
- package/src/cli/commands/crypto-hints.ts +7 -0
- package/src/cli/commands/fred-series.ts +61 -0
- package/src/cli/commands/market.ts +407 -104
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-leaps.ts +5 -2
- package/src/cli/commands/overview.ts +93 -20
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +82 -9
- package/src/cli/commands/system.ts +55 -8
- package/src/cli/commands/ticker.ts +88 -11
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +59 -7
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/freshness.ts +18 -7
- package/src/cli/glossary.ts +429 -0
- package/src/cli/history-rows.ts +48 -7
- package/src/cli/index-roots.ts +7 -0
- package/src/cli/index.ts +21 -7
- package/src/cli/known-gaps.ts +27 -0
- package/src/cli/listing-arg.ts +417 -56
- package/src/cli/not-a-ticker.ts +12 -5
- package/src/cli/pane-functions/access-gate.ts +5 -0
- package/src/cli/pane-functions/capabilities.ts +3 -2
- package/src/cli/pane-functions/catalog.ts +35 -5
- package/src/cli/pane-functions/data.ts +12 -8
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +20 -6
- package/src/cli/pane-functions/freshness.ts +363 -43
- package/src/cli/pane-functions/function-help.ts +12 -5
- package/src/cli/pane-functions/headless.ts +45 -17
- package/src/cli/pane-functions/index.ts +63 -10
- package/src/cli/pane-functions/market-session.ts +22 -8
- package/src/cli/pane-functions/options.ts +63 -22
- package/src/cli/pane-functions/report-notices.ts +25 -7
- package/src/cli/pane-functions/report.ts +15 -8
- package/src/cli/pane-functions/resolver.ts +49 -12
- package/src/cli/pane-functions/screenshot.ts +110 -23
- package/src/cli/report-tables.ts +3 -0
- package/src/cli/result.ts +4 -1
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +9 -0
- package/src/cli/symbol-list.ts +172 -0
- package/src/cli/ticker-resolution.ts +223 -30
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +6 -2
- package/src/components/chart/composite/composite-chart.tsx +40 -6
- package/src/components/chart/composite/legend.tsx +49 -2
- package/src/components/chart/composite/panel-surface.tsx +44 -17
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/workflow/tickers.ts +23 -4
- package/src/components/layout/detached-pane-shell.tsx +9 -0
- package/src/components/layout/floating-pane.tsx +3 -0
- package/src/components/layout/header.tsx +20 -5
- package/src/components/layout/pane/content.tsx +7 -13
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/model.ts +35 -1
- package/src/components/layout/pane/header.tsx +24 -1
- package/src/components/layout/pane/index.tsx +12 -2
- package/src/components/layout/pane/sidebar.tsx +78 -10
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/drag/index.ts +39 -9
- package/src/components/layout/shell/drag/live.ts +61 -51
- package/src/components/layout/shell/drag/runtime.ts +54 -12
- package/src/components/layout/shell/index.tsx +25 -7
- package/src/components/layout/shell/menu.ts +5 -0
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/layers.tsx +192 -45
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/markdown-text.tsx +62 -20
- package/src/components/metric-treemap/heat-surface.tsx +10 -1
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +2 -2
- package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +24 -1
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +7 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +17 -6
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +12 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +2 -0
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/store/normalize.ts +7 -2
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7416 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +61 -4
- package/src/i18n/ja.ts +61 -4
- package/src/i18n/ko.ts +61 -4
- package/src/i18n/zh-cn.ts +61 -4
- package/src/i18n/zh-tw.ts +61 -4
- package/src/layout/desks.ts +1 -1
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +81 -18
- package/src/market-data/market/status.ts +19 -23
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +3 -0
- package/src/market-data/quotes/metadata.ts +7 -24
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +5 -4
- package/src/market-data/result-types.ts +2 -0
- package/src/plugins/builtin/account-management/model.ts +1 -56
- package/src/plugins/builtin/account-management/pane.tsx +6 -4
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +41 -9
- package/src/plugins/builtin/alerts/pane.tsx +8 -0
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +4 -2
- package/src/plugins/builtin/analytics/risk-headless.ts +30 -12
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +35 -5
- package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/pane.tsx +3 -1
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +70 -13
- package/src/plugins/builtin/cds/headless.ts +116 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +193 -31
- package/src/plugins/builtin/cds/pane.tsx +56 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
- package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless.ts +8 -3
- package/src/plugins/builtin/chart-composer/index.tsx +9 -2
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/controller/index.ts +2 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
- package/src/plugins/builtin/cloud/askg/model.ts +27 -8
- package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +19 -5
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/pane.tsx +4 -2
- package/src/plugins/builtin/composite-plugins.ts +19 -13
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/credit-boards/index.tsx +2 -0
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
- package/src/plugins/builtin/credit-conditions/series.ts +26 -0
- package/src/plugins/builtin/credit-documents/headless.ts +31 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +2 -0
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/pane.tsx +3 -1
- package/src/plugins/builtin/fear-greed/index.tsx +4 -0
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +70 -9
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/index.tsx +1 -1
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +56 -25
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +101 -16
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/index.tsx +17 -8
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +36 -133
- package/src/plugins/builtin/holders/pane.tsx +11 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +26 -9
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/iv-history/client.ts +14 -4
- package/src/plugins/builtin/iv-history/headless.ts +7 -4
- package/src/plugins/builtin/iv-history/index.tsx +2 -0
- package/src/plugins/builtin/iv-history/model.ts +111 -7
- package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +28 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/macro-day/client.ts +44 -3
- package/src/plugins/builtin/macro-day/headless.ts +13 -10
- package/src/plugins/builtin/macro-day/model.ts +56 -10
- package/src/plugins/builtin/macro-day/pane.tsx +30 -20
- package/src/plugins/builtin/market-heatmap/model.ts +19 -11
- package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/index.tsx +3 -2
- package/src/plugins/builtin/market-movers/model.ts +30 -0
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +7 -2
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +3 -6
- package/src/plugins/builtin/mna/headless.ts +15 -3
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +1 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +2 -1
- package/src/plugins/builtin/options-scenario/headless.ts +1 -0
- package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
- package/src/plugins/builtin/perps/client.ts +40 -6
- package/src/plugins/builtin/perps/equity-row.tsx +33 -11
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +45 -30
- package/src/plugins/builtin/perps/index.tsx +18 -1
- package/src/plugins/builtin/perps/model.ts +20 -5
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +67 -61
- package/src/plugins/builtin/plugin-module.ts +3 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +331 -65
- package/src/plugins/builtin/portfolio-list/cli/render.ts +200 -31
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +24 -0
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +34 -4
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +6 -2
- package/src/plugins/builtin/power/headless.ts +71 -7
- package/src/plugins/builtin/power/index.tsx +4 -1
- package/src/plugins/builtin/power/model.ts +72 -1
- package/src/plugins/builtin/power/pane.tsx +32 -9
- package/src/plugins/builtin/rate-path/headless.ts +11 -3
- package/src/plugins/builtin/realized-vol/headless.ts +5 -0
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/series-inventory.ts +91 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +30 -12
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +9 -0
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +2 -0
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/index.tsx +2 -0
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +1 -0
- package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
- package/src/plugins/builtin/vol-surface/headless.ts +1 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +2 -1
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +3 -1
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/registry/index.ts +89 -4
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/remote/app-host.tsx +20 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +123 -6
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +62 -0
- package/src/remote/types.ts +30 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +3 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +27 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +7 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/box.tsx +3 -0
- package/src/renderers/dom/host/chart-surface.tsx +6 -2
- package/src/renderers/dom/host/live-frame.ts +6 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/size-observer.ts +26 -0
- package/src/renderers/dom/host/surface-3d.tsx +7 -2
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/styles.css +61 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +17 -2
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +19 -11
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +2 -0
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +107 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +145 -0
- package/src/series/validate.ts +171 -0
- package/src/sources/gloomberb-cloud/index.ts +7 -7
- package/src/sources/gloomberb-cloud/normalizers.ts +1 -0
- package/src/sources/history-result.ts +1 -0
- package/src/sources/listing-symbols.ts +4 -1
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +1 -1
- package/src/sources/provider-router/financial-routes.ts +1 -0
- package/src/sources/provider-router/financials.ts +13 -0
- package/src/sources/provider-router/history.ts +43 -25
- package/src/sources/provider-router/search.ts +1 -0
- package/src/sync/core-contributors.ts +1 -0
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +25 -0
- package/src/tickers/open-target.ts +3 -2
- package/src/tickers/search/index.ts +45 -7
- package/src/tickers/search/ranking.ts +33 -17
- package/src/tickers/search/types.ts +7 -1
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/resolve.ts +95 -16
- package/src/time-series/types.ts +4 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +6 -0
- package/src/types/data-provider.ts +5 -0
- package/src/types/financials.ts +52 -1
- package/src/types/headless.ts +61 -0
- package/src/types/plugin.ts +19 -0
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/host.tsx +18 -0
- package/src/ui/live-resize.ts +81 -0
- package/src/ui/live-stretch.ts +121 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/pane-fill.ts +11 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/cli-output.ts +7 -1
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +437 -52
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +107 -1
- package/src/utils/format.ts +16 -3
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +15 -5
- package/src/utils/price-history.ts +99 -42
- package/src/utils/sec-eps-basis.ts +24 -11
- package/src/utils/sec.ts +61 -7
- package/src/utils/utc-time.ts +51 -4
- package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
- /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PricePoint } from "../../../types/financials";
|
|
2
2
|
import { rollingRealizedVolatility } from "../shared/volatility";
|
|
3
|
-
import type { IvHistoryPayload, IvMethod, IvPoint, IvScreenRow, IvStats } from "./client";
|
|
3
|
+
import type { IvCoverageStatus, IvHistoryPayload, IvMethod, IvPoint, IvScreenRow, IvStats } from "./client";
|
|
4
4
|
|
|
5
5
|
export const HV_WINDOWS = [20, 30] as const;
|
|
6
6
|
export type HvWindow = (typeof HV_WINDOWS)[number];
|
|
@@ -26,6 +26,44 @@ export interface IvStatRow {
|
|
|
26
26
|
}
|
|
27
27
|
/** Rank and percentile need this many prior sessions, matching the server. */
|
|
28
28
|
const MIN_RANK_SAMPLES = 120;
|
|
29
|
+
/**
|
|
30
|
+
* Minutes a symbol's first backfill usually takes from the request that
|
|
31
|
+
* queued it: nine in ten have history by then (docs/research-data.md).
|
|
32
|
+
*/
|
|
33
|
+
const FIRST_BACKFILL_MINUTES = 10;
|
|
34
|
+
const FIRST_BACKFILL_TEXT = `a first backfill usually takes under ${FIRST_BACKFILL_MINUTES} minutes`;
|
|
35
|
+
|
|
36
|
+
/** "06:41 UTC" today, with the date on another day: "2026-10-09 06:41 UTC". */
|
|
37
|
+
function utcClock(time: number, now: number): string {
|
|
38
|
+
const iso = new Date(time).toISOString();
|
|
39
|
+
return iso.slice(0, 10) === new Date(now).toISOString().slice(0, 10)
|
|
40
|
+
? `${iso.slice(11, 16)} UTC` : `${iso.slice(0, 16).replace("T", " ")} UTC`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** When a symbol was queued, or null when the answer does not say (older servers) or says a time still to come. */
|
|
44
|
+
function queuedTime(queuedAt: string | null | undefined, now: number): number | null {
|
|
45
|
+
const time = queuedAt ? Date.parse(queuedAt) : Number.NaN;
|
|
46
|
+
return Number.isFinite(time) && time <= now ? time : null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* When to look again for history queued at `from`: "a first backfill usually
|
|
51
|
+
* takes under 10 minutes, try again after 06:41 UTC". One queued for longer
|
|
52
|
+
* than that is running late, and says so rather than give a time it cannot
|
|
53
|
+
* know. A view that checks again by itself (`retry: false`) needs no time to
|
|
54
|
+
* come back at.
|
|
55
|
+
*/
|
|
56
|
+
function firstBackfillText(from: number, now: number, retry: boolean): string {
|
|
57
|
+
const retryAt = from + FIRST_BACKFILL_MINUTES * 60_000;
|
|
58
|
+
if (retryAt <= now) return `longer than the usual ${FIRST_BACKFILL_MINUTES} minutes${retry ? ", try again shortly" : ""}`;
|
|
59
|
+
return retry ? `${FIRST_BACKFILL_TEXT}, try again after ${utcClock(retryAt, now)}` : FIRST_BACKFILL_TEXT;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** "queued for backfill since 06:31 UTC; a first backfill usually takes under 10 minutes, try again after 06:41 UTC" */
|
|
63
|
+
function queuedText(queuedAt: string | null | undefined, now: number): string {
|
|
64
|
+
const queued = queuedTime(queuedAt, now);
|
|
65
|
+
return `queued for backfill${queued == null ? "" : ` since ${utcClock(queued, now)}`}; ${firstBackfillText(queued ?? now, now, true)}`;
|
|
66
|
+
}
|
|
29
67
|
export interface IvHistoryModel {
|
|
30
68
|
symbol: string;
|
|
31
69
|
status: IvHistoryPayload["status"];
|
|
@@ -93,7 +131,7 @@ function byMethod(series: readonly IvPoint[], method: IvMethod, field: "iv30" |
|
|
|
93
131
|
*/
|
|
94
132
|
export function projectIvHistory(
|
|
95
133
|
payload: IvHistoryPayload, prices: readonly PricePoint[],
|
|
96
|
-
options: { lookback?: IvLookback; hvWindow?: HvWindow } = {},
|
|
134
|
+
options: { lookback?: IvLookback; hvWindow?: HvWindow; now?: number } = {},
|
|
97
135
|
): IvHistoryModel {
|
|
98
136
|
const lookback = options.lookback ?? "1Y";
|
|
99
137
|
const window = options.hvWindow ?? 20;
|
|
@@ -139,9 +177,12 @@ export function projectIvHistory(
|
|
|
139
177
|
seriesStat("spread", `IV 30d - HV ${window}`, "points", spreadAll, "trade-close"),
|
|
140
178
|
seriesStat("term", "IV 30d / 90d", "ratio", termAll, "trade-close"));
|
|
141
179
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
else if (payload.status === "
|
|
180
|
+
// Worded as VCA words each symbol (screenCoverage).
|
|
181
|
+
if (payload.status === "queued") warnings.push(`${payload.symbol} ${queuedText(payload.coverage?.addedAt, options.now ?? Date.now())}.`);
|
|
182
|
+
else if (payload.status === "backfilling") {
|
|
183
|
+
const through = payload.coverage?.backfilledThrough;
|
|
184
|
+
warnings.push(`${payload.symbol} backfilling${through ? ` through ${through}` : ""}.`);
|
|
185
|
+
} else if (payload.status === "unavailable" && !payload.warnings.length) warnings.push(`No options history for ${payload.symbol}.`);
|
|
145
186
|
if (!prices.length) warnings.push("Realized volatility unavailable: daily price history is missing.");
|
|
146
187
|
|
|
147
188
|
const tradeIv365 = byMethod(payload.series, "trade-close", "iv365");
|
|
@@ -163,7 +204,14 @@ export function projectIvHistory(
|
|
|
163
204
|
export type RichCheap = "rich" | "cheap" | "fair" | null;
|
|
164
205
|
export interface RichCheapRow {
|
|
165
206
|
symbol: string;
|
|
166
|
-
|
|
207
|
+
/** Where the symbol's history stands, as HIVG reads it; an older server says only ready or queued. */
|
|
208
|
+
status: IvCoverageStatus;
|
|
209
|
+
/** When the symbol was queued for backfill, when the server says. */
|
|
210
|
+
queuedAt: string | null;
|
|
211
|
+
/** The last session its backfill has reached. */
|
|
212
|
+
backfilledThrough: string | null;
|
|
213
|
+
/** Why an unavailable symbol is not covered yet (demand coverage is full): not final, unlike one with no options history. */
|
|
214
|
+
warning: string | null;
|
|
167
215
|
iv30: number | null;
|
|
168
216
|
date: string | null;
|
|
169
217
|
method: IvMethod | null;
|
|
@@ -228,7 +276,9 @@ export function projectRichCheap(rows: readonly IvScreenRow[], hv: ReadonlyMap<s
|
|
|
228
276
|
const realized = hv.get(row.symbol) ?? null;
|
|
229
277
|
const percentile = row.iv30?.percentile ?? null;
|
|
230
278
|
return {
|
|
231
|
-
symbol: row.symbol, status: row.
|
|
279
|
+
symbol: row.symbol, status: row.coverageStatus ?? row.status, queuedAt: row.coverage?.addedAt ?? null,
|
|
280
|
+
backfilledThrough: row.coverage?.backfilledThrough ?? null, warning: row.warnings?.[0] ?? null,
|
|
281
|
+
iv30, date: latest?.date ?? null, method: latest?.method ?? null,
|
|
232
282
|
rank: row.iv30?.rank ?? null, percentile, rankDate: row.iv30?.date ?? null,
|
|
233
283
|
termSlope: iv30 != null && latest?.iv90 != null ? iv30 - latest.iv90 : null,
|
|
234
284
|
iv1y: latest?.iv365 ?? null,
|
|
@@ -240,6 +290,60 @@ export function projectRichCheap(rows: readonly IvScreenRow[], hv: ReadonlyMap<s
|
|
|
240
290
|
});
|
|
241
291
|
}
|
|
242
292
|
|
|
293
|
+
interface ScreenCoverage {
|
|
294
|
+
/** One line per state, each symbol dated: queued since when, backfilled through which session. */
|
|
295
|
+
notes: string[];
|
|
296
|
+
/** Symbols whose history is still to come or not covered yet: the screen is incomplete while there are any. */
|
|
297
|
+
pending: string[];
|
|
298
|
+
/** Those of them with no reading to show yet. */
|
|
299
|
+
missing: string[];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* What VCA says about symbols without a full history, in the report's notes
|
|
304
|
+
* and the pane's notices. A queued symbol says since when and, with `retry`,
|
|
305
|
+
* when to look again: ten minutes after the newest of them was queued. One
|
|
306
|
+
* backfilling says how far it has got. One that finished with no options
|
|
307
|
+
* history is final and leaves the screen complete; one demand coverage could
|
|
308
|
+
* not take is not final. An older server says only ready or queued, without
|
|
309
|
+
* dates, so its queued symbols are counted from now as before.
|
|
310
|
+
*/
|
|
311
|
+
export function screenCoverage(rows: readonly RichCheapRow[], options: { now?: number; retry?: boolean } = {}): ScreenCoverage {
|
|
312
|
+
const now = options.now ?? Date.now();
|
|
313
|
+
const queued = rows.filter((row) => row.status === "queued");
|
|
314
|
+
const backfilling = rows.filter((row) => row.status === "backfilling");
|
|
315
|
+
const final = rows.filter((row) => row.status === "unavailable" && !row.warning);
|
|
316
|
+
const uncovered = rows.filter((row) => row.status === "unavailable" && row.warning);
|
|
317
|
+
const notes: string[] = [];
|
|
318
|
+
if (queued.length) {
|
|
319
|
+
const times = queued.map((row) => queuedTime(row.queuedAt, now));
|
|
320
|
+
const listed = queued.map((row, index) => times[index] == null ? row.symbol : `${row.symbol} since ${utcClock(times[index]!, now)}`);
|
|
321
|
+
const newest = Math.max(...times.map((time) => time ?? now));
|
|
322
|
+
notes.push(`Queued for backfill: ${listed.join(", ")}; ${firstBackfillText(newest, now, options.retry ?? true)}.`);
|
|
323
|
+
}
|
|
324
|
+
if (backfilling.length) {
|
|
325
|
+
notes.push(`Backfilling: ${backfilling.map((row) => row.backfilledThrough ? `${row.symbol} through ${row.backfilledThrough}` : row.symbol).join(", ")}.`);
|
|
326
|
+
}
|
|
327
|
+
if (final.length) notes.push(`No options history: ${final.map((row) => row.symbol).join(", ")}.`);
|
|
328
|
+
const reasons = new Map<string, string[]>();
|
|
329
|
+
for (const row of uncovered) reasons.set(row.warning!, [...(reasons.get(row.warning!) ?? []), row.symbol]);
|
|
330
|
+
for (const [reason, symbols] of reasons) notes.push(`Not queued: ${symbols.join(", ")}. ${reason}`);
|
|
331
|
+
const pending = [...queued, ...backfilling, ...uncovered];
|
|
332
|
+
return { notes, pending: pending.map((row) => row.symbol),
|
|
333
|
+
missing: pending.filter((row) => row.iv30 == null && row.date == null).map((row) => row.symbol) };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* The VCA pane's notices: the report's wording without a time to come back
|
|
338
|
+
* at, since the pane checks again by itself, and a count of ready symbols with
|
|
339
|
+
* no IV30, which is how an older server reports one that found no options.
|
|
340
|
+
*/
|
|
341
|
+
export function screenPaneNotices(rows: readonly RichCheapRow[], now = Date.now()): string[] {
|
|
342
|
+
const empty = rows.filter((row) => row.status === "ready" && row.iv30 == null).length;
|
|
343
|
+
return [...screenCoverage(rows, { now, retry: false }).notes,
|
|
344
|
+
...(empty ? [`${empty} symbol${empty === 1 ? " has" : "s have"} no stored implied volatility yet.`] : [])];
|
|
345
|
+
}
|
|
346
|
+
|
|
243
347
|
export const VCA_PRESETS = {
|
|
244
348
|
etfs: ["SPY", "QQQ", "IWM", "DIA", "EEM", "EFA", "FXI", "EWZ", "GLD", "SLV", "GDX", "USO", "TLT", "HYG",
|
|
245
349
|
"XLE", "XLF", "XLK", "XLV", "XLY", "XLP", "XLI", "XLU", "SMH", "XBI", "KRE"],
|
|
@@ -10,7 +10,7 @@ import { useAutoRefresh } from "../../../react/auto-refresh";
|
|
|
10
10
|
import { compareSortValues, nextHeaderSort, type SortDirection } from "../../../utils/sort-values";
|
|
11
11
|
import { loadIvScreen, loadRealizedVolatilities } from "./client";
|
|
12
12
|
import { formatPoints, formatRank, formatVol, readingLabel, sharedDates, shortDate, VCA_DEFINITIONS, verdictLabel } from "./format";
|
|
13
|
-
import { projectRichCheap, type RichCheapRow, richCheapDates, type VcaPreset } from "./model";
|
|
13
|
+
import { projectRichCheap, type RichCheapRow, richCheapDates, screenPaneNotices, type VcaPreset } from "./model";
|
|
14
14
|
import { vcaUniverse } from "./universe";
|
|
15
15
|
|
|
16
16
|
type SortId = keyof RichCheapRow;
|
|
@@ -78,12 +78,8 @@ export function IvScreenPane({ width, height, focused }: PaneProps) {
|
|
|
78
78
|
}
|
|
79
79
|
}), [rows, dates]);
|
|
80
80
|
const [selected, setSelected] = useState<string | null>(null);
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
const notices = [universe.error, resource.error,
|
|
84
|
-
...(queued ? [`${queued} symbol${queued === 1 ? "" : "s"} queued for implied volatility history; they fill in after backfill.`] : []),
|
|
85
|
-
...(uncovered ? [`${uncovered} symbol${uncovered === 1 ? " has" : "s have"} no stored implied volatility yet.`] : [])]
|
|
86
|
-
.filter((value): value is string => !!value);
|
|
81
|
+
const coverageNotices = useMemo(() => screenPaneNotices(rows), [rows]);
|
|
82
|
+
const notices = [universe.error, resource.error, ...coverageNotices].filter((value): value is string => !!value);
|
|
87
83
|
usePaneNoticeFooter({ registrationId: "iv-screen-notices", notices, focused });
|
|
88
84
|
const openHistory = (row: RichCheapRow) => createPaneFromTemplate("iv-history-pane", { symbol: row.symbol });
|
|
89
85
|
// The full wording gives way to the short form in a pane too narrow to show the rank date.
|
|
@@ -102,8 +98,8 @@ export function IvScreenPane({ width, height, focused }: PaneProps) {
|
|
|
102
98
|
switch (id) {
|
|
103
99
|
case "symbol": return { text: row.symbol, color: colors.textBright };
|
|
104
100
|
case "iv30": return { text: formatVol(row.iv30), color: colors.warning };
|
|
105
|
-
case "date": return { text: row.date ? readingLabel(row.date, row.method, true)
|
|
106
|
-
color: colors.textDim };
|
|
101
|
+
case "date": return { text: row.date ? readingLabel(row.date, row.method, true)
|
|
102
|
+
: row.status === "queued" || row.status === "backfilling" ? row.status : "--", color: colors.textDim };
|
|
107
103
|
case "rankDate": return { text: row.rankDate ? `${shortDate(row.rankDate)} close` : "--", color: colors.textDim };
|
|
108
104
|
case "rank": return { text: formatRank(row.rank) };
|
|
109
105
|
case "percentile": return { text: formatRank(row.percentile) };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
2
|
+
import { loadIvHistory, type IvPoint } from "./client";
|
|
3
|
+
|
|
4
|
+
const TENORS: ReadonlyArray<readonly [key: "iv30" | "iv90" | "iv365", label: string]> = [
|
|
5
|
+
["iv30", "30-day"],
|
|
6
|
+
["iv90", "90-day"],
|
|
7
|
+
["iv365", "1-year"],
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
/** A ticker's at-the-money implied volatility by tenor, one close per session. */
|
|
11
|
+
export const IV_SERIES: readonly SeriesDefinition[] = TENORS.map(([key, label]): SeriesDefinition => ({
|
|
12
|
+
id: `implied-vol:${key}`,
|
|
13
|
+
name: `${label} implied volatility`,
|
|
14
|
+
unit: "%",
|
|
15
|
+
frequency: "daily",
|
|
16
|
+
group: "Volatility",
|
|
17
|
+
tags: ["IV", "implied volatility", "options", key],
|
|
18
|
+
input: "ticker",
|
|
19
|
+
load: async ({ ticker, signal }) => {
|
|
20
|
+
const payload = await loadIvHistory(ticker!, { ...(signal ? { signal } : {}) });
|
|
21
|
+
return {
|
|
22
|
+
points: payload.series.map((point: IvPoint) => ({
|
|
23
|
+
date: point.sessionDate,
|
|
24
|
+
value: point[key] == null ? null : point[key]! * 100,
|
|
25
|
+
})),
|
|
26
|
+
...(payload.warnings.length ? { warning: payload.warnings.join("; ") } : {}),
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
HeadlessBundleResult,
|
|
3
|
+
HeadlessPaneContext,
|
|
3
4
|
HeadlessPaneDefinition,
|
|
4
5
|
} from "../../../types/plugin";
|
|
6
|
+
import { ApiRequestError } from "../../../api-client/errors";
|
|
5
7
|
import { formatCompact, formatNumber } from "../../../utils/format";
|
|
6
8
|
import { fetchJobs, fetchJobsMovers, type JobsCloudClient, type JobsCompanyState } from "./client";
|
|
7
9
|
import {
|
|
@@ -13,8 +15,21 @@ import {
|
|
|
13
15
|
functionLabel,
|
|
14
16
|
} from "./model";
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* What a refused account needs, and the free preview to try instead: HIRE
|
|
20
|
+
* reads the same careers systems, and is named only when it answers for this
|
|
21
|
+
* company.
|
|
22
|
+
*/
|
|
23
|
+
async function jobsDeniedMessage(symbol: string | undefined, status: 401 | 402 | 403, client: Pick<HeadlessPaneContext["apiClient"], "getCloudHiring">): Promise<string> {
|
|
24
|
+
const need = status === 401 ? "sign-in" : status === 403 ? "a verified email" : "Gloom Pro";
|
|
25
|
+
const preview = await client.getCloudHiring(symbol, { limit: 1 })
|
|
26
|
+
.then((payload) => !!payload && (symbol ? "symbol" in payload : "companies" in payload), () => false);
|
|
27
|
+
return `JOBS needs ${need}${preview ? `; HIRE${symbol ? ` ${symbol}` : ""} is free to preview` : ""}.`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const DENIED = new Set([401, 402, 403]);
|
|
31
|
+
|
|
32
|
+
function companyBundle(symbol: string, state: Exclude<JobsCompanyState, { kind: "denied" }>, roleLimit: number): HeadlessBundleResult {
|
|
18
33
|
if (state.kind === "pending") {
|
|
19
34
|
return {
|
|
20
35
|
sections: [{ title: "Hiring", entries: [{ label: "Status", value: "pending", formatted: state.message }] }],
|
|
@@ -169,15 +184,25 @@ export const jobsHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
169
184
|
maximum: 200,
|
|
170
185
|
},
|
|
171
186
|
],
|
|
187
|
+
// No aliases: the template's keywords stay the catalog's search terms.
|
|
188
|
+
discovery: {
|
|
189
|
+
dataRequirements: ["Gloom Cloud Pro account"],
|
|
190
|
+
limitations: ["Pro only; HIRE <ticker> previews a company's hiring for free"],
|
|
191
|
+
},
|
|
172
192
|
describe: (args) => (args.symbols[0] ? `Hiring | ${args.symbols[0]}` : "Hiring | coverage"),
|
|
173
193
|
async load(args, ctx): Promise<HeadlessBundleResult> {
|
|
174
194
|
const limit = Number(args.options.roles);
|
|
175
195
|
const symbol = args.symbols[0];
|
|
176
196
|
if (symbol) {
|
|
177
197
|
const state = await fetchJobs(symbol, { force: true, client: ctx.apiClient as JobsCloudClient });
|
|
198
|
+
if (state.kind === "denied") throw new Error(await jobsDeniedMessage(symbol, state.status, ctx.apiClient));
|
|
178
199
|
return companyBundle(symbol, state, limit);
|
|
179
200
|
}
|
|
180
|
-
const payload = await fetchJobsMovers(ctx.apiClient as JobsCloudClient)
|
|
201
|
+
const payload = await fetchJobsMovers(ctx.apiClient as JobsCloudClient).catch(async (error: unknown) => {
|
|
202
|
+
const status = error instanceof ApiRequestError ? error.status ?? 0 : 0;
|
|
203
|
+
if (DENIED.has(status)) throw new Error(await jobsDeniedMessage(undefined, status as 401 | 402 | 403, ctx.apiClient));
|
|
204
|
+
throw error;
|
|
205
|
+
});
|
|
181
206
|
const rows = buildMoverRows(payload.movers).slice(0, Math.max(limit, 15)).map((row) => ({
|
|
182
207
|
ticker: row.ticker,
|
|
183
208
|
company: row.company,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { publicTickerBindingSymbol } from "../../../tickers/selection";
|
|
2
2
|
import type { PluginModule } from "../plugin-module";
|
|
3
|
+
import { JOBS_SERIES } from "./series";
|
|
3
4
|
import { resetJobsCache } from "./client";
|
|
4
5
|
import { jobsHeadless } from "./headless";
|
|
5
6
|
import { JOBS_PANE_ID, JobsPane, JobsResearchTab } from "./pane";
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
const description =
|
|
9
|
-
"
|
|
10
|
+
"Pro hiring read from the company's own careers system: open roles over time, by function and location, new roles, pay ranges. Alone, every covered company ranked.";
|
|
10
11
|
|
|
11
12
|
function explicitSymbol(options?: { arg?: string; symbol?: string | null }): string | null {
|
|
12
13
|
const symbol = (options?.symbol ?? options?.arg ?? "").trim().toUpperCase();
|
|
@@ -14,6 +15,7 @@ function explicitSymbol(options?: { arg?: string; symbol?: string | null }): str
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export const jobsModule: PluginModule = {
|
|
18
|
+
series: JOBS_SERIES,
|
|
17
19
|
setup(ctx) {
|
|
18
20
|
ctx.registerTickerResearchTab({
|
|
19
21
|
id: "jobs",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
2
|
+
import { fetchJobs } from "./client";
|
|
3
|
+
|
|
4
|
+
/** A company's open job postings each day, as the jobs pane charts them. */
|
|
5
|
+
export const JOBS_SERIES: readonly SeriesDefinition[] = [{
|
|
6
|
+
id: "jobs:open-roles",
|
|
7
|
+
name: "Open job postings",
|
|
8
|
+
unit: "jobs",
|
|
9
|
+
frequency: "daily",
|
|
10
|
+
group: "Alternative data",
|
|
11
|
+
tags: ["hiring", "jobs", "postings", "headcount"],
|
|
12
|
+
input: "ticker",
|
|
13
|
+
load: async ({ ticker }) => {
|
|
14
|
+
const state = await fetchJobs(ticker!);
|
|
15
|
+
if (state.kind === "pending") throw new Error(state.message || `Postings for ${ticker} are still being collected.`);
|
|
16
|
+
if (state.kind !== "ready") throw new Error(state.message || `No postings for ${ticker}.`);
|
|
17
|
+
return state.summary.series.map((point) => ({ date: point.day, value: point.open }));
|
|
18
|
+
},
|
|
19
|
+
}];
|
|
@@ -85,7 +85,8 @@ import {
|
|
|
85
85
|
buildKellyHistoryItems,
|
|
86
86
|
buildKellyResultItems,
|
|
87
87
|
} from "./sections";
|
|
88
|
-
import {
|
|
88
|
+
import { resolveActivePortfolioId, resolveKellyBankroll } from "./portfolio";
|
|
89
|
+
import { getPortfolioPositionValue } from "../../../portfolio/position-value";
|
|
89
90
|
import { useKellyCommonAssumptions } from "./state";
|
|
90
91
|
|
|
91
92
|
export function KellySizerPane({ focused, width, height }: PaneProps) {
|
|
@@ -1,46 +1,7 @@
|
|
|
1
1
|
import type { AppConfig } from "../../../types/config";
|
|
2
|
-
import type { TickerFinancials } from "../../../types/financials";
|
|
3
2
|
import type { TickerRecord } from "../../../types/ticker";
|
|
4
|
-
import { convertCurrency } from "../../../utils/format";
|
|
5
3
|
import { allocationTotal, type AllocationHolding } from "../portfolio-list/allocation";
|
|
6
4
|
import { getCollectionTypeFromConfig } from "../portfolio-list/pane/data";
|
|
7
|
-
import { getPortfolioPositionMetrics, getPortfolioQuoteDisplay, resolvePortfolioMarketValue } from "../portfolio-list/position-metrics";
|
|
8
|
-
|
|
9
|
-
export function getPortfolioPositionValue({
|
|
10
|
-
ticker,
|
|
11
|
-
financials,
|
|
12
|
-
portfolioId,
|
|
13
|
-
baseCurrency,
|
|
14
|
-
exchangeRates,
|
|
15
|
-
}: {
|
|
16
|
-
ticker: TickerRecord | null;
|
|
17
|
-
financials: TickerFinancials | null;
|
|
18
|
-
portfolioId: string | null;
|
|
19
|
-
baseCurrency: string;
|
|
20
|
-
exchangeRates: Map<string, number>;
|
|
21
|
-
}): number {
|
|
22
|
-
if (!ticker) return 0;
|
|
23
|
-
const scopedTicker: TickerRecord = portfolioId
|
|
24
|
-
? {
|
|
25
|
-
...ticker,
|
|
26
|
-
metadata: {
|
|
27
|
-
...ticker.metadata,
|
|
28
|
-
positions: ticker.metadata.positions.filter((position) => position.portfolio === portfolioId),
|
|
29
|
-
},
|
|
30
|
-
}
|
|
31
|
-
: ticker;
|
|
32
|
-
const quote = financials?.quote;
|
|
33
|
-
|
|
34
|
-
const quoteCurrency = quote?.currency || ticker.metadata.currency || baseCurrency;
|
|
35
|
-
const metrics = getPortfolioPositionMetrics(scopedTicker, undefined, quoteCurrency, {
|
|
36
|
-
currency: baseCurrency, convert: (value, currency) => convertCurrency(value, currency, baseCurrency, exchangeRates),
|
|
37
|
-
}, quote);
|
|
38
|
-
const activeQuote = getPortfolioQuoteDisplay(metrics, quote);
|
|
39
|
-
|
|
40
|
-
return resolvePortfolioMarketValue(metrics, activeQuote
|
|
41
|
-
? convertCurrency(activeQuote.price, quoteCurrency, baseCurrency, exchangeRates) : null)?.gross
|
|
42
|
-
?? (metrics.positionCount > 0 ? Number.NaN : 0);
|
|
43
|
-
}
|
|
44
5
|
|
|
45
6
|
/**
|
|
46
7
|
* What the portfolio is worth to bet with: its equity. A broker account's is
|
|
@@ -7,7 +7,9 @@ import type { DataProvider } from "../../../types/data-provider";
|
|
|
7
7
|
import type { PricePoint } from "../../../types/financials";
|
|
8
8
|
import { abortable, abortError } from "../../../utils/async-deadline";
|
|
9
9
|
import { errorMessage } from "../../../utils/errors";
|
|
10
|
-
import { resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
10
|
+
import { parsePublicTickerKey, resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
11
|
+
import { loadEarningsHistory } from "../earnings/client";
|
|
12
|
+
import type { MacroDayEarningsReport } from "./model";
|
|
11
13
|
import { bundledMacroReleases, mergeMacroReleases, type MacroReleaseList } from "./releases";
|
|
12
14
|
|
|
13
15
|
export const macroReleaseCache = createPluginCache<CloudMacroReleaseDaysPayload>({
|
|
@@ -43,11 +45,12 @@ const US_LISTINGS_ONLY = "Macro-day moves are for US listings.";
|
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* A listing whose venue sits outside New York trades US releases on a different clock.
|
|
46
|
-
* A bare symbol such as 7203.T carries no exchange, so its venue suffix names it
|
|
48
|
+
* A bare symbol such as 7203.T carries no exchange, so its venue suffix names it,
|
|
49
|
+
* and a listing key such as SAP:XETR names it before the ticker record has loaded.
|
|
47
50
|
*/
|
|
48
51
|
function isNonUsVenue(instrument: InstrumentRef): boolean {
|
|
49
52
|
if (tickerHasListingSuffix(instrument.symbol)) return true;
|
|
50
|
-
const zone = resolveExchangeTimeZone(instrument.exchange);
|
|
53
|
+
const zone = resolveExchangeTimeZone(instrument.exchange || parsePublicTickerKey(instrument.symbol).exchange);
|
|
51
54
|
return !!zone && zone !== "America/New_York";
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -72,3 +75,41 @@ export async function loadMacroDayHistory(
|
|
|
72
75
|
return { history: [], stale: false, error: errorMessage(error), fetchedAt: now };
|
|
73
76
|
}
|
|
74
77
|
}
|
|
78
|
+
|
|
79
|
+
export interface MacroDayEarnings {
|
|
80
|
+
reports: MacroDayEarningsReport[];
|
|
81
|
+
stale: boolean;
|
|
82
|
+
/** Why the reports are missing; the study then runs without the earnings marker. */
|
|
83
|
+
error: string | null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The earnings history's own depth: the oldest report that can matter is five years back, about twenty quarters. */
|
|
87
|
+
const EARNINGS_REPORT_LIMIT = 24;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The ticker's own earnings reports, from the history `ERN` shows. Never
|
|
91
|
+
* rejects but on cancel: a listing outside the US or without reports has none,
|
|
92
|
+
* and a failed read leaves the study as it was, with the reason in `error`.
|
|
93
|
+
*/
|
|
94
|
+
export async function loadMacroDayEarnings(
|
|
95
|
+
request: { instrument: InstrumentRef; signal?: AbortSignal; forceRefresh?: boolean },
|
|
96
|
+
load: typeof loadEarningsHistory = loadEarningsHistory,
|
|
97
|
+
): Promise<MacroDayEarnings> {
|
|
98
|
+
if (request.signal?.aborted) throw abortError(CANCELLED);
|
|
99
|
+
if (isNonUsVenue(request.instrument)) return { reports: [], stale: false, error: null };
|
|
100
|
+
try {
|
|
101
|
+
// Earnings are keyed by the bare US symbol; a listing key ("CRWV:XNAS") drops its exchange.
|
|
102
|
+
const symbol = parsePublicTickerKey(request.instrument.symbol.trim()).symbol.toUpperCase();
|
|
103
|
+
const resource = await abortable(load(symbol, request.forceRefresh, EARNINGS_REPORT_LIMIT), request.signal, CANCELLED);
|
|
104
|
+
return { reports: resource.payload.reports.map((report) => ({ date: report.date, timing: report.timing, reactionSession: report.realized?.afterSession ?? null })),
|
|
105
|
+
stale: resource.stale, error: null };
|
|
106
|
+
} catch (error) {
|
|
107
|
+
if (request.signal?.aborted || (error instanceof Error && error.name === "AbortError")) throw abortError(CANCELLED);
|
|
108
|
+
return { reports: [], stale: false, error: errorMessage(error) };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** What the pane footer and the report notes say when the earnings marker could not be applied. */
|
|
113
|
+
export function macroDayEarningsNotice(earnings: MacroDayEarnings): string | null {
|
|
114
|
+
return earnings.error ? `Earnings dates unavailable (${earnings.error}); release days on the company's own report are not marked.` : null;
|
|
115
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { HeadlessPaneDefinition } from "../../../types/plugin";
|
|
2
2
|
import { resolveHeadlessInstrument } from "../shared/headless-market-data";
|
|
3
|
-
import { loadMacroDayHistory, loadMacroReleases } from "./client";
|
|
4
|
-
import { projectMacroDays, type MacroDayStats } from "./model";
|
|
3
|
+
import { loadMacroDayEarnings, loadMacroDayHistory, loadMacroReleases, macroDayEarningsNotice } from "./client";
|
|
4
|
+
import { macroDayEventLabel, projectMacroDays, type MacroDayStats } from "./model";
|
|
5
5
|
import { MACRO_EVENT_KINDS, MACRO_EVENT_LABELS, MACRO_RELEASE_SOURCES, staleMacroReleasesNotice } from "./releases";
|
|
6
6
|
|
|
7
7
|
// A mean that rounds to zero reads 0.00%, never -0.00%.
|
|
@@ -11,12 +11,14 @@ const share = (value: unknown) => typeof value === "number" ? `${Math.round(valu
|
|
|
11
11
|
|
|
12
12
|
export const macroDayHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
13
13
|
shape: "bundle", argument: { kind: "ticker", description: "Ticker" },
|
|
14
|
+
usListingsOnly: "Macro release day data",
|
|
14
15
|
// Dated by the release list (releasesThrough) as much as by the closes, so no session schedule applies.
|
|
15
16
|
freshness: { status: "not-a-feed", basis: "release-day study on daily closes" },
|
|
16
17
|
describe: (args) => `MDAY ${args.symbols[0] ?? ""}`,
|
|
17
18
|
discovery: { screenshotReadiness: "live-dom", limitations: [
|
|
18
19
|
"US listings; close-to-close on the release day.",
|
|
19
20
|
"Published CPI, jobs and FOMC days; sessions after the list's last covered day (releasesThrough) are left out.",
|
|
21
|
+
"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.",
|
|
20
22
|
] },
|
|
21
23
|
options: [
|
|
22
24
|
{ key: "release", type: "enum", values: [{ value: "all" }, ...MACRO_EVENT_KINDS.map((value) => ({ value }))], defaultValue: "all",
|
|
@@ -25,11 +27,12 @@ export const macroDayHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
25
27
|
],
|
|
26
28
|
async load(args, ctx) {
|
|
27
29
|
const instrument = await resolveHeadlessInstrument(ctx, args.symbols[0]!);
|
|
28
|
-
const [history, releases] = await Promise.all([loadMacroDayHistory({ instrument, signal: ctx.signal }, ctx.marketData), loadMacroReleases()
|
|
30
|
+
const [history, releases, earnings] = await Promise.all([loadMacroDayHistory({ instrument, signal: ctx.signal }, ctx.marketData), loadMacroReleases(),
|
|
31
|
+
loadMacroDayEarnings({ instrument, signal: ctx.signal })]);
|
|
29
32
|
ctx.signal.throwIfAborted();
|
|
30
33
|
const model = projectMacroDays(history.history, { symbol: instrument.symbol, lookbackYears: Number(args.options.lookbackYears) || 5,
|
|
31
|
-
releases: releases.releases, coveredThrough: releases.coveredThrough });
|
|
32
|
-
const
|
|
34
|
+
releases: releases.releases, coveredThrough: releases.coveredThrough, earnings: earnings.reports });
|
|
35
|
+
const notes = [staleMacroReleasesNotice(releases), macroDayEarningsNotice(earnings)].filter((note): note is string => !!note);
|
|
33
36
|
const row = (label: string, stats: MacroDayStats) => ({ label, ...stats });
|
|
34
37
|
const release = String(args.options.release ?? "all");
|
|
35
38
|
const events = release === "all" ? model.events : model.events.filter((event) => event.kind === release);
|
|
@@ -39,18 +42,18 @@ export const macroDayHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
39
42
|
{ key: "meanAbs", header: "Avg |move|", format: percent }, { key: "multiple", header: "vs normal", format: multiple },
|
|
40
43
|
{ key: "mean", header: "Avg move", format: percent }, { key: "hitRate", header: "Up", format: share }],
|
|
41
44
|
rows: [...MACRO_EVENT_KINDS.map((kind) => row(MACRO_EVENT_LABELS[kind], model.byKind[kind])),
|
|
42
|
-
row("Any release", model.allEvents), row("Normal day", model.normal)] },
|
|
45
|
+
row("Any release", model.allEvents), ...(model.earnings.count ? [row("Earnings", model.earnings)] : []), row("Normal day", model.normal)] },
|
|
43
46
|
{ title: "Release days", columns: [{ key: "date", header: "Date" }, { key: "event", header: "Release" },
|
|
44
47
|
{ key: "session", header: "Session" }, { key: "move", header: "Move", format: percent }, { key: "multiple", header: "vs normal", format: multiple }],
|
|
45
|
-
rows: events.map((event) => ({ ...event, event:
|
|
48
|
+
rows: events.map((event) => ({ ...event, event: macroDayEventLabel(event) })) },
|
|
46
49
|
],
|
|
47
|
-
complete: !history.stale && !history.error && !
|
|
50
|
+
complete: !history.stale && !earnings.stale && !history.error && !notes.length && model.events.length > 0,
|
|
48
51
|
unavailableSymbols: model.events.length ? [] : [instrument.symbol],
|
|
49
52
|
errors: history.error ? [history.error] : [],
|
|
50
|
-
...(
|
|
53
|
+
...(notes.length ? { notes } : {}),
|
|
51
54
|
metadata: { unit: "decimal return, close to close on the release day", start: model.start, asOf: model.asOf,
|
|
52
55
|
releasesThrough: releases.coveredThrough, releaseSources: Object.values(MACRO_RELEASE_SOURCES),
|
|
53
|
-
stale: history.stale, fetchedAt: history.fetchedAt, methodology: "docs/research-data.md#macro-day-reaction" },
|
|
56
|
+
stale: history.stale || earnings.stale, fetchedAt: history.fetchedAt, methodology: "docs/research-data.md#macro-day-reaction" },
|
|
54
57
|
};
|
|
55
58
|
},
|
|
56
59
|
};
|