@gloom-sh/terminal 0.18.5 → 0.19.0
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/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +140 -7
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +17 -6
- package/src/api-client/equity-screener.ts +24 -0
- package/src/api-client/fund-facts.ts +45 -4
- package/src/api-client/index.ts +11 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/market-movers.ts +7 -0
- package/src/api-client/members.ts +1 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/research-activity.ts +3 -2
- package/src/api-client/types.ts +70 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +0 -2
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/pane-tabs-allowlist.json +3 -0
- package/src/architecture/ttl-caches-allowlist.json +19 -0
- package/src/brokers/sync-broker-instance.ts +2 -8
- package/src/capabilities/chart-series.ts +1 -1
- package/src/cli/commands/crypto-hints.ts +40 -24
- package/src/cli/commands/market.ts +72 -26
- package/src/cli/commands/options-chain.ts +48 -7
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +61 -12
- package/src/cli/commands/search.ts +21 -1
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +55 -34
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +8 -0
- package/src/cli/glossary.ts +25 -2
- package/src/cli/history-rows.ts +57 -9
- package/src/cli/index.ts +2 -0
- package/src/cli/listing-arg.ts +180 -52
- package/src/cli/output-file.ts +68 -0
- package/src/cli/pane-functions/capabilities.ts +3 -0
- package/src/cli/pane-functions/catalog.ts +80 -7
- package/src/cli/pane-functions/dom.ts +13 -3
- package/src/cli/pane-functions/freshness.ts +86 -3
- package/src/cli/pane-functions/function-help.ts +13 -10
- package/src/cli/pane-functions/headless.ts +17 -7
- package/src/cli/pane-functions/index.ts +49 -14
- package/src/cli/pane-functions/market-session.ts +66 -4
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/resolver.ts +19 -8
- package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
- package/src/cli/pane-functions/screenshot-types.ts +5 -0
- package/src/cli/quote-answer.ts +22 -11
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +4 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-surface.tsx +52 -3
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +39 -4
- package/src/components/chart/composite/series-cues.ts +14 -0
- package/src/components/chart/composite/text-renderer.ts +9 -2
- package/src/components/chart/composite/tool-catalog.ts +36 -0
- package/src/components/chart/composite/tools.ts +203 -44
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
- package/src/components/command-bar/assist/inventory.ts +2 -1
- package/src/components/command-bar/commands/direct/index.ts +28 -13
- package/src/components/command-bar/pane-templates/items.ts +3 -2
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +12 -7
- package/src/components/onboarding/wizard-broker-sync.ts +0 -1
- package/src/components/onboarding/wizard-positions.ts +3 -3
- package/src/components/ticker/list-table-view.tsx +4 -1
- package/src/components/ui/choice-dialog.tsx +23 -18
- package/src/components/ui/choice-groups.ts +18 -0
- package/src/components/ui/data-table/opentui/index.tsx +9 -7
- package/src/components/ui/data-table/opentui/model.ts +26 -1
- package/src/components/ui/data-table/types.ts +2 -0
- package/src/components/ui/list-view.tsx +8 -4
- package/src/components/ui/query-bar-keys.tsx +2 -0
- package/src/components/ui/query-bar.tsx +1 -0
- package/src/components/ui/select-button.tsx +5 -1
- package/src/components/ui/select-field.tsx +1 -0
- package/src/components/ui/table-layout.ts +8 -5
- package/src/core/app-runtime.ts +2 -0
- package/src/core/app-services.ts +2 -2
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/ticker-repository.ts +16 -9
- package/src/data/ticker-writes.ts +81 -0
- package/src/data/ttl-cache.ts +165 -0
- package/src/docs/snapshot.json +71 -137
- package/src/i18n/es.ts +18 -2
- package/src/i18n/ja.ts +18 -2
- package/src/i18n/ko.ts +18 -2
- package/src/i18n/zh-cn.ts +18 -2
- package/src/i18n/zh-tw.ts +18 -2
- package/src/market-data/depositary-pair.ts +2 -2
- package/src/market-data/fund-facts.ts +50 -0
- package/src/market-data/market/change-basis.ts +16 -3
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/options-alternatives.ts +81 -4
- package/src/news/aggregator.ts +113 -9
- package/src/news/cloud-session.ts +21 -0
- package/src/news/hooks.ts +1 -0
- package/src/news/news-model.ts +1 -0
- package/src/news/types.ts +11 -0
- package/src/plugins/builtin/alerts/alert-engine.ts +20 -1
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +336 -77
- package/src/plugins/builtin/alerts/command.ts +25 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
- package/src/plugins/builtin/alerts/fired-log.ts +73 -9
- package/src/plugins/builtin/alerts/format.ts +75 -5
- package/src/plugins/builtin/alerts/headless.ts +24 -6
- package/src/plugins/builtin/alerts/history-rows.ts +3 -2
- package/src/plugins/builtin/alerts/history.ts +1 -1
- package/src/plugins/builtin/alerts/index.tsx +79 -16
- package/src/plugins/builtin/alerts/metric-command.ts +77 -4
- package/src/plugins/builtin/alerts/metric-data.ts +54 -13
- package/src/plugins/builtin/alerts/metric-model.ts +163 -14
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +1 -1
- package/src/plugins/builtin/alerts/pane.tsx +61 -23
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +12 -8
- package/src/plugins/builtin/alerts/types.ts +4 -0
- package/src/plugins/builtin/analytics/index.tsx +2 -1
- package/src/plugins/builtin/analytics/risk-client.ts +16 -5
- package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
- package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
- package/src/plugins/builtin/analytics/risk-model.ts +55 -9
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
- package/src/plugins/builtin/attention/index.tsx +2 -1
- package/src/plugins/builtin/attention/listing.ts +14 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/buildout/cells.tsx +12 -4
- package/src/plugins/builtin/buildout/format.ts +38 -0
- package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
- package/src/plugins/builtin/buildout/table-model.ts +23 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +6 -2
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +3 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +4 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -0
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +7 -1
- package/src/plugins/builtin/chart-composer/headless.ts +6 -1
- package/src/plugins/builtin/chart-composer/index.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +37 -8
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chat/content/command-suggestions.ts +1 -0
- package/src/plugins/builtin/chat/pane-links/commands.ts +7 -1
- package/src/plugins/builtin/clinical-trials/model.ts +0 -9
- package/src/plugins/builtin/clinical-trials/pane.tsx +15 -22
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +8 -6
- package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
- package/src/plugins/builtin/company-attention/building.tsx +5 -1
- package/src/plugins/builtin/company-attention/client.ts +8 -9
- package/src/plugins/builtin/company-attention/evidence.ts +4 -1
- package/src/plugins/builtin/company-attention/moves.tsx +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +9 -2
- package/src/plugins/builtin/company-attention/signals.tsx +5 -1
- package/src/plugins/builtin/correlation/headless.ts +13 -5
- package/src/plugins/builtin/correlation/history.ts +22 -0
- package/src/plugins/builtin/cot/client.ts +22 -18
- package/src/plugins/builtin/cot/headless.ts +15 -10
- package/src/plugins/builtin/cot/model.ts +14 -1
- package/src/plugins/builtin/cot/pane.tsx +22 -14
- package/src/plugins/builtin/credit-boards/client.ts +6 -10
- package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
- package/src/plugins/builtin/credit-conditions/model.ts +4 -0
- package/src/plugins/builtin/credit-conditions/series.ts +3 -1
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
- package/src/plugins/builtin/credit-documents/export.ts +173 -0
- package/src/plugins/builtin/credit-documents/headless.ts +7 -7
- package/src/plugins/builtin/credit-documents/model.ts +104 -14
- package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
- package/src/plugins/builtin/custom-view/sources.ts +2 -0
- package/src/plugins/builtin/dividend-yield/client.ts +131 -23
- package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
- package/src/plugins/builtin/dividend-yield/model.ts +8 -5
- package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
- package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
- package/src/plugins/builtin/dividend-yield/types.ts +20 -2
- package/src/plugins/builtin/dividend-yield/view.ts +30 -2
- package/src/plugins/builtin/docs/targets.ts +5 -1
- package/src/plugins/builtin/earnings/board-model.ts +16 -15
- package/src/plugins/builtin/earnings/board.tsx +62 -71
- package/src/plugins/builtin/earnings/headless.ts +40 -4
- package/src/plugins/builtin/earnings/scope.ts +31 -43
- package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
- package/src/plugins/builtin/earnings-calls/format.ts +31 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -2
- package/src/plugins/builtin/earnings-calls/model.ts +6 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +5 -4
- package/src/plugins/builtin/econ/types.ts +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +6 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +36 -9
- package/src/plugins/builtin/equity-screener/categories.ts +179 -0
- package/src/plugins/builtin/equity-screener/client.ts +4 -2
- package/src/plugins/builtin/equity-screener/headless.ts +144 -13
- package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
- package/src/plugins/builtin/equity-screener/model.ts +99 -10
- package/src/plugins/builtin/equity-screener/pane.tsx +68 -13
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
- package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
- package/src/plugins/builtin/fx-matrix/client.ts +6 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +1 -1
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -2
- package/src/plugins/builtin/fx-matrix/live-legs.ts +42 -3
- package/src/plugins/builtin/gpu/headless.ts +8 -2
- package/src/plugins/builtin/help/function-index.ts +4 -1
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/help/shortcut-model.ts +1 -1
- package/src/plugins/builtin/holders/fund-holders.ts +51 -0
- package/src/plugins/builtin/holders/headless.ts +18 -1
- package/src/plugins/builtin/iv-history/client.ts +52 -11
- package/src/plugins/builtin/iv-history/format.ts +36 -23
- package/src/plugins/builtin/iv-history/headless.ts +33 -18
- package/src/plugins/builtin/iv-history/index.tsx +2 -2
- package/src/plugins/builtin/iv-history/model.ts +163 -27
- package/src/plugins/builtin/iv-history/pane.tsx +10 -6
- package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
- package/src/plugins/builtin/iv-history/universe.ts +5 -1
- package/src/plugins/builtin/jobs/client.ts +25 -29
- package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
- package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
- package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
- package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
- package/src/plugins/builtin/macro-day/release-table.ts +2 -2
- package/src/plugins/builtin/market-heatmap/data.ts +8 -33
- package/src/plugins/builtin/market-movers/client.ts +25 -7
- package/src/plugins/builtin/market-movers/headless.ts +32 -12
- package/src/plugins/builtin/market-movers/index.tsx +26 -14
- package/src/plugins/builtin/market-movers/min-float.ts +74 -0
- package/src/plugins/builtin/market-movers/model.ts +4 -1
- package/src/plugins/builtin/market-movers/screener.ts +14 -0
- package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
- package/src/plugins/builtin/market-movers/session-table.ts +4 -3
- package/src/plugins/builtin/market-movers/table.ts +17 -5
- package/src/plugins/builtin/members/breadth-pane.tsx +2 -1
- package/src/plugins/builtin/news/index.tsx +1 -0
- package/src/plugins/builtin/news/wire/categories.ts +19 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
- package/src/plugins/builtin/openfda/client.ts +14 -2
- package/src/plugins/builtin/openfda/index.tsx +3 -2
- package/src/plugins/builtin/openfda/model.ts +9 -0
- package/src/plugins/builtin/openfda/pane.tsx +42 -6
- package/src/plugins/builtin/options/analytics.ts +29 -5
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/table.ts +5 -2
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +17 -4
- package/src/plugins/builtin/options-positioning/client.ts +11 -0
- package/src/plugins/builtin/options-positioning/headless.ts +21 -8
- package/src/plugins/builtin/options-positioning/index.tsx +1 -1
- package/src/plugins/builtin/options-positioning/model.ts +78 -9
- package/src/plugins/builtin/options-positioning/pane.tsx +21 -6
- package/src/plugins/builtin/options-scenario/client.ts +116 -47
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
- package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
- package/src/plugins/builtin/options-scenario/csp.ts +8 -2
- package/src/plugins/builtin/options-scenario/index.tsx +9 -7
- package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
- package/src/plugins/builtin/pe-band/model.ts +12 -49
- package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
- package/src/plugins/builtin/perps/cascade.ts +236 -0
- package/src/plugins/builtin/perps/client.ts +56 -2
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +19 -22
- package/src/plugins/builtin/perps/status-line.ts +25 -0
- package/src/plugins/builtin/plugin-module.ts +5 -1
- package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
- package/src/plugins/builtin/portfolio-list/cli/render.ts +7 -5
- package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +4 -1
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +3 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/realized-vol/index.tsx +2 -2
- package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
- package/src/plugins/builtin/relative-rotation/client.ts +18 -4
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
- package/src/plugins/builtin/relative-rotation/model.ts +16 -40
- package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
- package/src/plugins/builtin/research/event-model.ts +10 -8
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/relative-valuation-headless.ts +5 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +7 -5
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
- package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
- package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
- package/src/plugins/builtin/scanner/flow-model.ts +50 -4
- package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
- package/src/plugins/builtin/scanner/flow-session.ts +146 -0
- package/src/plugins/builtin/scanner/headless.ts +204 -35
- package/src/plugins/builtin/scanner/index.ts +16 -5
- package/src/plugins/builtin/scanner/live-headless.ts +27 -3
- package/src/plugins/builtin/scanner/live-model.ts +11 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +3 -3
- package/src/plugins/builtin/scanner/lock-note.ts +3 -2
- package/src/plugins/builtin/seasonality/headless.ts +10 -1
- package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
- package/src/plugins/builtin/sec/fund-facts.ts +116 -34
- package/src/plugins/builtin/sec/headless.ts +2 -1
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +3 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
- package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
- package/src/plugins/builtin/shared/earnings-report.ts +2 -2
- package/src/plugins/builtin/shared/job-posting.ts +1 -0
- package/src/plugins/builtin/shared/members-menu.tsx +3 -2
- package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
- package/src/plugins/builtin/shared/report-freshness.ts +3 -2
- package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
- package/src/plugins/builtin/shared/ticker-company.ts +77 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +2 -1
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +19 -0
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/model.ts +16 -7
- package/src/plugins/builtin/themes/pane.tsx +5 -5
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
- package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
- package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -19
- package/src/plugins/builtin/treasury-daily/client.ts +41 -5
- package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
- package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
- package/src/plugins/builtin/treasury-daily/model.ts +50 -3
- package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
- package/src/plugins/builtin/vol-surface/client.ts +3 -13
- package/src/plugins/builtin/vol-surface/headless.ts +3 -3
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/vol-surface/pane.tsx +7 -5
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +2 -2
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/remote/resources.ts +2 -1
- package/src/renderers/dom/data-table/row.tsx +26 -0
- package/src/renderers/dom/desktop/list-view.tsx +13 -10
- package/src/renderers/dom/desktop/query-bar.tsx +4 -2
- package/src/renderers/dom/desktop/select-field.tsx +4 -2
- package/src/renderers/dom/host/chart-surface.tsx +21 -0
- package/src/renderers/electrobun/bun/desktop/app-name.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend.ts +12 -0
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +115 -14
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/shared/app-name.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
- package/src/renderers/electrobun/view/main.tsx +24 -1
- package/src/renderers/electrobun/view/news-source.ts +3 -1
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
- package/src/renderers/electrobun/view/view-ids.ts +85 -0
- package/src/renderers/opentui/start.tsx +5 -0
- package/src/series/registry.ts +1 -0
- package/src/series/types.ts +6 -0
- package/src/series/validate.ts +1 -0
- package/src/sources/gloomberb-cloud/index.ts +1 -0
- package/src/sources/gloomberb-cloud/news.ts +47 -7
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/index.ts +8 -5
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/controller.ts +4 -3
- package/src/sync/core-contributors.ts +90 -31
- package/src/telemetry/stall-reports-dom.ts +38 -0
- package/src/telemetry/stall-reports-node.ts +75 -0
- package/src/telemetry/stall-reports.ts +214 -0
- package/src/test-support/preload.ts +14 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name.ts +44 -3
- package/src/tickers/listing-venues.ts +15 -3
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +1 -1
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/fundamentals.ts +44 -1
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/resolve-context.ts +3 -1
- package/src/time-series/resolve.ts +56 -4
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +3 -2
- package/src/time-series/studies.ts +8 -2
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +2 -3
- package/src/time-series/types.ts +22 -1
- package/src/types/financials.ts +32 -1
- package/src/types/headless.ts +21 -3
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +9 -0
- package/src/ui/host.tsx +3 -0
- package/src/updater/failure.ts +4 -1
- package/src/utils/cli-output.ts +42 -1
- package/src/utils/crypto-pair.ts +44 -0
- package/src/utils/forward-dividend.ts +2 -0
- package/src/utils/fundamentals.ts +24 -3
- package/src/utils/fx-market-hours.ts +26 -3
- package/src/utils/main-thread-stall.ts +35 -2
- package/src/utils/market-capitalization.ts +24 -1
- package/src/utils/price-history.ts +7 -1
- package/src/utils/shell-word.ts +8 -0
- package/src/utils/trailing-dividend.ts +53 -4
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { CorporateActionsData } from "../types/financials";
|
|
2
|
+
import { cashInMajorUnits } from "../utils/dividend-cash";
|
|
3
|
+
import { resolveCurrencyUnit } from "../utils/currency-units";
|
|
4
|
+
import { logFailure } from "../utils/log-failure";
|
|
5
|
+
import { dividendReferencePrice } from "../utils/trailing-dividend";
|
|
6
|
+
import { observationDate } from "./price-comparison";
|
|
7
|
+
import { CHART_RESOLUTION_STEP_MS, chartBarSizeStepMs } from "./resolution";
|
|
8
|
+
import type { ResolvedSeries, TimeSeriesPoint } from "./types";
|
|
9
|
+
|
|
10
|
+
/** One cash distribution per share: its ex-date (`YYYY-MM-DD`) and its amount in the listing's major currency unit. */
|
|
11
|
+
export interface CashDistribution {
|
|
12
|
+
exDate: string;
|
|
13
|
+
amount: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TotalReturnOptions {
|
|
17
|
+
/** The session day a bar belongs to, `YYYY-MM-DD`. */
|
|
18
|
+
dayOf: (point: TimeSeriesPoint) => string;
|
|
19
|
+
/**
|
|
20
|
+
* A bar's price in the distributions' currency unit, or null when the two
|
|
21
|
+
* currencies differ (nothing is converted).
|
|
22
|
+
*/
|
|
23
|
+
cashPrice: (price: number) => number | null;
|
|
24
|
+
/**
|
|
25
|
+
* Bars longer than a session (weekly, monthly) are dated at their start, so a
|
|
26
|
+
* distribution belongs to the bar that holds its ex-date, not the first one
|
|
27
|
+
* dated on or after it. This is how many days a bar holds; the last bar holds
|
|
28
|
+
* that many from its own date, and a distribution after that precedes no bar.
|
|
29
|
+
*/
|
|
30
|
+
barDays?: number;
|
|
31
|
+
/** Today, `YYYY-MM-DD`: a distribution dated after it has not gone ex. */
|
|
32
|
+
asOf?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface TotalReturnResult {
|
|
36
|
+
points: TimeSeriesPoint[];
|
|
37
|
+
/** Distributions reinvested inside the series; one before its first bar or after its last is not. */
|
|
38
|
+
applied: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The day a bar of `barDays` days dated `day` ends on; 30-day multiples are calendar months. */
|
|
42
|
+
function barEnd(day: string, barDays: number): string {
|
|
43
|
+
const end = new Date(`${day}T00:00:00Z`);
|
|
44
|
+
if (barDays >= 28 && barDays % 30 === 0) end.setUTCMonth(end.getUTCMonth() + barDays / 30);
|
|
45
|
+
else end.setUTCDate(end.getUTCDate() + barDays);
|
|
46
|
+
return end.toISOString().slice(0, 10);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function scaled(value: number | null | undefined, factor: number): number | null | undefined {
|
|
50
|
+
return typeof value === "number" && Number.isFinite(value) ? value * factor : value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A price series as its total return: every cash distribution is reinvested at
|
|
55
|
+
* the close of its ex-date bar, so the series moves by (close + cash) over the
|
|
56
|
+
* bar before. Each price is multiplied by the shares the cash has bought
|
|
57
|
+
* since the series began, which leaves its first bar as it was; volume is
|
|
58
|
+
* left alone. A distribution dated at or before the first bar precedes the
|
|
59
|
+
* series, so nothing is reinvested for it.
|
|
60
|
+
*/
|
|
61
|
+
export function reinvestDistributions(
|
|
62
|
+
points: readonly TimeSeriesPoint[],
|
|
63
|
+
distributions: readonly CashDistribution[],
|
|
64
|
+
{ dayOf, cashPrice, barDays, asOf }: TotalReturnOptions,
|
|
65
|
+
): TotalReturnResult {
|
|
66
|
+
const ordered = [...points].sort((left, right) => left.date.getTime() - right.date.getTime());
|
|
67
|
+
const holdingBar = barDays !== undefined && barDays > 1;
|
|
68
|
+
const cash = distributions
|
|
69
|
+
.filter((entry) => /^\d{4}-\d{2}-\d{2}$/.test(entry.exDate) && Number.isFinite(entry.amount) && entry.amount > 0
|
|
70
|
+
&& (asOf === undefined || entry.exDate <= asOf))
|
|
71
|
+
.sort((left, right) => left.exDate.localeCompare(right.exDate));
|
|
72
|
+
const days = ordered.map(dayOf);
|
|
73
|
+
let factor = 1;
|
|
74
|
+
let applied = 0;
|
|
75
|
+
let next = 0;
|
|
76
|
+
const adjusted = ordered.map((point, index) => {
|
|
77
|
+
const barDay = days[index]!;
|
|
78
|
+
const before = holdingBar ? days[index + 1] ?? barEnd(barDay, barDays!) : null;
|
|
79
|
+
while (next < cash.length) {
|
|
80
|
+
const entry = cash[next]!;
|
|
81
|
+
if (before !== null ? entry.exDate >= before : entry.exDate > barDay) break;
|
|
82
|
+
if (index === 0) { next += 1; continue; }
|
|
83
|
+
const close = point.close ?? point.value;
|
|
84
|
+
// A bar with no price leaves the cash for the next bar that has one.
|
|
85
|
+
if (typeof close !== "number" || !Number.isFinite(close) || close <= 0) break;
|
|
86
|
+
// Cash in another currency than the price buys nothing: the series stays a price series.
|
|
87
|
+
const price = cashPrice(close);
|
|
88
|
+
if (price !== null && price > 0) {
|
|
89
|
+
factor *= 1 + entry.amount / price;
|
|
90
|
+
applied += 1;
|
|
91
|
+
}
|
|
92
|
+
next += 1;
|
|
93
|
+
}
|
|
94
|
+
if (factor === 1) return point;
|
|
95
|
+
return {
|
|
96
|
+
...point,
|
|
97
|
+
value: scaled(point.value, factor) ?? null,
|
|
98
|
+
...point.rawValue !== undefined ? { rawValue: scaled(point.rawValue, factor) ?? null } : {},
|
|
99
|
+
...point.open !== undefined ? { open: scaled(point.open, factor) } : {},
|
|
100
|
+
...point.high !== undefined ? { high: scaled(point.high, factor) } : {},
|
|
101
|
+
...point.low !== undefined ? { low: scaled(point.low, factor) } : {},
|
|
102
|
+
...point.close !== undefined ? { close: scaled(point.close, factor) } : {},
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
return { points: adjusted, applied };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface TotalReturnOutcome {
|
|
109
|
+
series: ResolvedSeries;
|
|
110
|
+
/** Why the series stays a price series, when it does. */
|
|
111
|
+
notice?: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const DAY_MS = 86_400_000;
|
|
115
|
+
|
|
116
|
+
/** How many days a bar holds when it is longer than a session (a month counts as 30), so a distribution belongs to the bar holding its ex-date. */
|
|
117
|
+
function barDaysLongerThanSession(series: Pick<ResolvedSeries, "barSize" | "historyResolution">): number | undefined {
|
|
118
|
+
const step = series.barSize ? chartBarSizeStepMs(series.barSize)
|
|
119
|
+
: series.historyResolution ? CHART_RESOLUTION_STEP_MS[series.historyResolution] : null;
|
|
120
|
+
return step !== null && step > DAY_MS ? Math.round(step / DAY_MS) : undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A price series as its total return, from the cash history its listing pays.
|
|
125
|
+
* The series says which basis it ended up on: `total` once its distributions
|
|
126
|
+
* are reinvested (a listing that pays none is its price), `price` with the
|
|
127
|
+
* reason when the history cannot be read, covers no distributions, or is in
|
|
128
|
+
* another currency than the prices. Nothing is converted.
|
|
129
|
+
*/
|
|
130
|
+
export async function totalReturnSeries(
|
|
131
|
+
series: ResolvedSeries,
|
|
132
|
+
loadActions: () => Promise<CorporateActionsData | null>,
|
|
133
|
+
priceCurrency: string | undefined,
|
|
134
|
+
asOf: Date,
|
|
135
|
+
): Promise<TotalReturnOutcome> {
|
|
136
|
+
const priceOnly = (notice: string): TotalReturnOutcome => ({ series: { ...series, returnBasis: "price" }, notice });
|
|
137
|
+
const actions = await loadActions().catch(logFailure("total-return", "Loading distribution history failed", null));
|
|
138
|
+
if (!actions) return priceOnly("distribution history unavailable; showing the price return.");
|
|
139
|
+
const cash = cashInMajorUnits(actions);
|
|
140
|
+
const dividends = Array.isArray(cash.dividends) ? cash.dividends : [];
|
|
141
|
+
if (cash.coverage?.dividends === "unavailable" || (cash.coverage?.dividends !== "available" && dividends.length === 0)) {
|
|
142
|
+
return priceOnly("distribution history unavailable; showing the price return.");
|
|
143
|
+
}
|
|
144
|
+
const currency = resolveCurrencyUnit(cash.currency).currency;
|
|
145
|
+
if (dividends.length > 0 && !currency) return priceOnly("distribution currency unknown; showing the price return.");
|
|
146
|
+
if (dividends.length > 0 && !resolveCurrencyUnit(priceCurrency).currency) {
|
|
147
|
+
return priceOnly("price currency unknown; showing the price return.");
|
|
148
|
+
}
|
|
149
|
+
if (dividends.length > 0 && dividendReferencePrice(1, priceCurrency, currency) === null) {
|
|
150
|
+
return priceOnly(`distributions are in ${currency}, not the price currency; showing the price return.`);
|
|
151
|
+
}
|
|
152
|
+
const { points } = reinvestDistributions(series.points, dividends, {
|
|
153
|
+
dayOf: (point) => observationDate(point.date.getTime(), series),
|
|
154
|
+
cashPrice: (price) => dividendReferencePrice(price, priceCurrency, currency),
|
|
155
|
+
barDays: barDaysLongerThanSession(series),
|
|
156
|
+
asOf: asOf.toISOString().slice(0, 10),
|
|
157
|
+
});
|
|
158
|
+
// "ECC Close" is its price: a label the chart wrote from the field says what the series is now.
|
|
159
|
+
return { series: { ...series, points, returnBasis: "total", label: series.label.replace(/ (?:Close|Price|Open|High|Low)$/, " Total return") } };
|
|
160
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ResolvedSeries, SeriesTransform, TimeSeriesPoint } from "./types";
|
|
2
2
|
import { calendarMonthsBefore } from "../utils/calendar-date";
|
|
3
3
|
import { isFiniteNumber } from "../utils/guards";
|
|
4
|
+
import { isOhlcSeriesStyle } from "./spec";
|
|
4
5
|
|
|
5
6
|
const DAY_MS = 24 * 60 * 60 * 1_000;
|
|
6
7
|
// Volume is separate supporting data, not another price. A volume series has
|
|
@@ -166,9 +167,7 @@ export function applyResolvedSeriesTransform(
|
|
|
166
167
|
unit: percent ? "%" : transform === "index100" ? "index" : "log",
|
|
167
168
|
unitGroup: percent ? "percent" : transform === "index100" ? "index" : "log",
|
|
168
169
|
dataShape: "scalar",
|
|
169
|
-
style: series.style
|
|
170
|
-
? "line"
|
|
171
|
-
: series.style,
|
|
170
|
+
style: isOhlcSeriesStyle(series.style) ? "line" : series.style,
|
|
172
171
|
points: applySeriesTransform(series.points, transform, options),
|
|
173
172
|
};
|
|
174
173
|
}
|
package/src/time-series/types.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type SeriesPeriod = "auto" | "daily" | "weekly" | "monthly" | "quarterly"
|
|
|
10
10
|
* "band" draws a line through each point's value inside a shaded range from
|
|
11
11
|
* its `low` to its `high`: an average within its historical range.
|
|
12
12
|
*/
|
|
13
|
-
export type SeriesStyle = "line" | "area" | "step" | "columns" | "points" | "candles" | "ohlc" | "hlc" | "band";
|
|
13
|
+
export type SeriesStyle = "line" | "area" | "step" | "columns" | "points" | "candles" | "hollow" | "heikin-ashi" | "ohlc" | "hlc" | "band";
|
|
14
14
|
export type SeriesTransform = "raw" | "percent" | "index100" | "yoy" | "qoq" | "log";
|
|
15
15
|
export type SeriesAxis = "auto" | "left" | "right";
|
|
16
16
|
export type SeriesInterpolation = "none" | "step-after";
|
|
@@ -110,6 +110,11 @@ export interface ChartViewportSpec {
|
|
|
110
110
|
maxPoints?: number;
|
|
111
111
|
/** Intraday market history includes pre-market and after-hours bars where the venue has them. */
|
|
112
112
|
extendedHours?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Security price series are drawn as total returns: each cash distribution
|
|
115
|
+
* is reinvested at the close of its ex-date bar. Price returns otherwise.
|
|
116
|
+
*/
|
|
117
|
+
totalReturn?: boolean;
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
export interface ChartSpec {
|
|
@@ -141,6 +146,8 @@ export interface TimeSeriesPoint {
|
|
|
141
146
|
low?: number | null;
|
|
142
147
|
close?: number | null;
|
|
143
148
|
volume?: number | null;
|
|
149
|
+
/** The bar this figure traded in closed below its open: volume draws it in the falling colour. */
|
|
150
|
+
fell?: boolean;
|
|
144
151
|
periodLabel?: string;
|
|
145
152
|
/**
|
|
146
153
|
* A financial statement period as the FA columns name it: `FY2025`, `Q3 FY26`,
|
|
@@ -183,6 +190,12 @@ export interface ResolvedSeries {
|
|
|
183
190
|
unit: string;
|
|
184
191
|
/** Unit of rawValue, retained when presentation transforms change unit. */
|
|
185
192
|
rawUnit?: string;
|
|
193
|
+
/**
|
|
194
|
+
* What a price series' returns are, set when the chart asked for total
|
|
195
|
+
* returns: `total` once its distributions are reinvested, `price` when the
|
|
196
|
+
* source gave none to reinvest (`warning` says why).
|
|
197
|
+
*/
|
|
198
|
+
returnBasis?: "total" | "price";
|
|
186
199
|
unitGroup: string;
|
|
187
200
|
/**
|
|
188
201
|
* The unit the legend states beside each value, read bare as FUT prints its
|
|
@@ -311,6 +324,14 @@ export interface ChartResolutionResult {
|
|
|
311
324
|
loading: boolean;
|
|
312
325
|
errors: string[];
|
|
313
326
|
warnings: string[];
|
|
327
|
+
/**
|
|
328
|
+
* Where a series' source starts after the range asked for, and why (a
|
|
329
|
+
* publisher's cap on history), as `warnings` also carries it, so a report
|
|
330
|
+
* says it where it would otherwise print a range that quietly starts later.
|
|
331
|
+
*/
|
|
332
|
+
coverageNotices?: string[];
|
|
333
|
+
/** What the price levels of a total-return chart without a comparison are (`warnings` also carries it). */
|
|
334
|
+
returnBasisNotice?: string;
|
|
314
335
|
/**
|
|
315
336
|
* Each charted listing that no longer trades: its symbol and label
|
|
316
337
|
* ("Delisted Oct 27, 2022"), which `warnings` carries as "TWTR: Delisted Oct 27, 2022".
|
package/src/types/financials.ts
CHANGED
|
@@ -330,7 +330,12 @@ export interface Fundamentals extends DepositaryReceiptFacts {
|
|
|
330
330
|
/** Set where Gloom Cloud checked `enterpriseValue` against market cap + total debt - cash; pairs with that value only. */
|
|
331
331
|
enterpriseValueCheck?: EnterpriseValueCheck;
|
|
332
332
|
/** Explicit provider retractions; omitted fields alone remain eligible for fallback. */
|
|
333
|
-
unavailableFields?: Array<"enterpriseValue" | "enterpriseToRevenue">;
|
|
333
|
+
unavailableFields?: Array<"enterpriseValue" | "enterpriseToRevenue" | "marketCap">;
|
|
334
|
+
/**
|
|
335
|
+
* Why `marketCap` is retracted, with "marketCap" in `unavailableFields`: a depositary receipt its source priced as
|
|
336
|
+
* an ordinary share (the receipt's price times the company's ordinary shares), with no ratio to convert them.
|
|
337
|
+
*/
|
|
338
|
+
marketCapUnavailable?: "receipt-priced-as-ordinary";
|
|
334
339
|
operatingCashFlow?: number;
|
|
335
340
|
freeCashFlow?: number;
|
|
336
341
|
dividendYield?: number;
|
|
@@ -345,6 +350,18 @@ export interface Fundamentals extends DepositaryReceiptFacts {
|
|
|
345
350
|
revenue?: number;
|
|
346
351
|
netIncome?: number;
|
|
347
352
|
eps?: number;
|
|
353
|
+
/**
|
|
354
|
+
* Where `eps` and `trailingPE` come from: `filed-quarters` when `eps` is the
|
|
355
|
+
* diluted EPS of the last four filed quarters (or the fiscal year they end
|
|
356
|
+
* with), as PEB and GE read the statements, its last period ending
|
|
357
|
+
* `trailingEpsPeriodEnd`, and `trailingPE` the price over it; `served` when
|
|
358
|
+
* those quarters give none (or one that cannot be priced: see
|
|
359
|
+
* time-series/filed-trailing-eps) and both are Gloom Cloud's trailing
|
|
360
|
+
* figures, including a P/E it serves with no EPS (a fund's). Absent when
|
|
361
|
+
* there is neither an EPS nor a P/E.
|
|
362
|
+
*/
|
|
363
|
+
trailingEpsSource?: "filed-quarters" | "served";
|
|
364
|
+
trailingEpsPeriodEnd?: string;
|
|
348
365
|
operatingMargin?: number;
|
|
349
366
|
profitMargin?: number;
|
|
350
367
|
revenueGrowth?: number;
|
|
@@ -556,10 +573,24 @@ export interface CorporateActionsData {
|
|
|
556
573
|
dividends: DividendAction[];
|
|
557
574
|
/** Declared and unpaid, for the listings Gloom Cloud has them for; absent elsewhere and from older servers. */
|
|
558
575
|
declaredDividends?: DeclaredDividendAction[];
|
|
576
|
+
/**
|
|
577
|
+
* What each paid row was declared as when the company declares in another
|
|
578
|
+
* currency than the listing pays (BP's dollars beside its London pence), per
|
|
579
|
+
* ordinary share, keyed by the paid row's ex-date. Absent elsewhere and from older servers.
|
|
580
|
+
*/
|
|
581
|
+
declaredCash?: DeclaredCash;
|
|
582
|
+
/** Set when `dividends` is the last good history standing in for a refresh that could not read it: when that history was read. */
|
|
583
|
+
dividendsAsOf?: string;
|
|
559
584
|
splits: SplitAction[];
|
|
560
585
|
earnings: EarningsAction[];
|
|
561
586
|
}
|
|
562
587
|
|
|
588
|
+
/** Paid rows as their company declared them, in `currency` (its major unit). */
|
|
589
|
+
export interface DeclaredCash {
|
|
590
|
+
currency: string;
|
|
591
|
+
rows: DividendAction[];
|
|
592
|
+
}
|
|
593
|
+
|
|
563
594
|
export interface CompanyProfile {
|
|
564
595
|
description?: string;
|
|
565
596
|
/**
|
package/src/types/headless.ts
CHANGED
|
@@ -34,6 +34,12 @@ export interface HeadlessPaneArgumentDef {
|
|
|
34
34
|
examples?: readonly string[];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** A list the catalog prints under a function's options, such as the sector names a screen's criteria match. */
|
|
38
|
+
export interface HeadlessPaneReference {
|
|
39
|
+
title: string;
|
|
40
|
+
items: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
export interface HeadlessPaneOptionValue {
|
|
38
44
|
value: string;
|
|
39
45
|
aliases?: string[];
|
|
@@ -83,6 +89,8 @@ export interface HeadlessPaneOptionDef {
|
|
|
83
89
|
* absent.
|
|
84
90
|
*/
|
|
85
91
|
valueWords?: number;
|
|
92
|
+
/** The value is a comma list (`--metric trailingPE,dividendYieldPercent`), and the flag typed again adds to it. */
|
|
93
|
+
list?: boolean;
|
|
86
94
|
/** The option in use as typed after the function, such as `--expiration 2028-01-21`; the catalog shows it as an example. */
|
|
87
95
|
example?: string;
|
|
88
96
|
/** The example runs without the function's optional argument, as an option that works only then does (`fn INS --side sell`). */
|
|
@@ -138,8 +146,10 @@ export interface HeadlessPaneContext {
|
|
|
138
146
|
* known. A code several companies list (BDI) throws asking which, with
|
|
139
147
|
* `quote`'s message; `argumentWith(key)` is the function's argument naming
|
|
140
148
|
* that listing instead (`BDI:TSX`), for the retry each listing offers.
|
|
149
|
+
* `coinNote` is what `quote` says of a bare coin ticker read as a listing
|
|
150
|
+
* that is not the coin (ETH, the Grayscale fund), for the report's warnings.
|
|
141
151
|
*/
|
|
142
|
-
resolveListing?: (symbol: string, argumentWith: (key: string) => string) => Promise<{ symbol: string; exchange?: string; name?: string } | null>;
|
|
152
|
+
resolveListing?: (symbol: string, argumentWith: (key: string) => string) => Promise<{ symbol: string; exchange?: string; name?: string; coinNote?: string } | null>;
|
|
143
153
|
/**
|
|
144
154
|
* What a plugin keeps on this device only (its `ctx.resume` state, never
|
|
145
155
|
* synced), such as ALRT's log of the alerts the app fired; null when none.
|
|
@@ -602,6 +612,8 @@ export interface HeadlessSeries {
|
|
|
602
612
|
interval?: string;
|
|
603
613
|
/** Decimal places the text report prints the latest value to (a correlation to 3); JSON and CSV keep every digit. */
|
|
604
614
|
textDecimals?: number;
|
|
615
|
+
/** The text report prints the latest value as the tables print an amount (63.33B), for a company's reported total; JSON and CSV keep every digit. */
|
|
616
|
+
textCompact?: boolean;
|
|
605
617
|
/** Each point's `value` is its bar's close: `--csv` and `--ndjson` write Close alone, JSON keeps both. */
|
|
606
618
|
valueIsClose?: boolean;
|
|
607
619
|
points: HeadlessSeriesPoint[];
|
|
@@ -615,6 +627,8 @@ export interface HeadlessSeriesResult extends HeadlessPaneResultBase {
|
|
|
615
627
|
export interface HeadlessSnapshotResult extends HeadlessPaneResultBase {
|
|
616
628
|
asOf: string | number | Date;
|
|
617
629
|
items: HeadlessPaneRow[];
|
|
630
|
+
/** What the report says when `items` is empty, in place of "No data.": why there are none. */
|
|
631
|
+
empty?: string;
|
|
618
632
|
}
|
|
619
633
|
|
|
620
634
|
export interface HeadlessPaneResultByShape {
|
|
@@ -640,6 +654,8 @@ export interface HeadlessPaneDefinition<Shape extends HeadlessPaneShape = Headle
|
|
|
640
654
|
intents?: string[];
|
|
641
655
|
dataRequirements?: string[];
|
|
642
656
|
limitations?: string[];
|
|
657
|
+
/** Names an option's values match, listed by the catalog under each title: EQS's sectors and industries. */
|
|
658
|
+
reference?: HeadlessPaneReference[];
|
|
643
659
|
screenshotReadiness?: "ready" | "partial" | "live-dom" | "unsupported";
|
|
644
660
|
};
|
|
645
661
|
/**
|
|
@@ -672,9 +688,11 @@ export interface HeadlessPaneDefinition<Shape extends HeadlessPaneShape = Headle
|
|
|
672
688
|
/**
|
|
673
689
|
* A listing the function has no data for, answered before any request with
|
|
674
690
|
* what exists instead: OPX and OVDV answer a coin nothing lists options on
|
|
675
|
-
* (SOL-USD) with BTC and ETH options
|
|
691
|
+
* (SOL-USD) with BTC and ETH options, and OVDV, VCA and HIVG an FX pair with
|
|
692
|
+
* the currency funds' options. `key` is the listing as read; `details` is
|
|
693
|
+
* the line after `message`, left out when the message says it all.
|
|
676
694
|
*/
|
|
677
|
-
refuseSymbol?(key: string): { message: string; details
|
|
695
|
+
refuseSymbol?(key: string): { message: string; details?: string } | null;
|
|
678
696
|
/**
|
|
679
697
|
* `fn` exits 1 when the report has no name with data: no rows, or every row
|
|
680
698
|
* is one of `unavailableSymbols`. A list that gives data for some names
|
package/src/types/news-source.ts
CHANGED
package/src/types/plugin.ts
CHANGED
|
@@ -20,6 +20,7 @@ export type {
|
|
|
20
20
|
HeadlessPaneOptionType,
|
|
21
21
|
HeadlessPaneOptionValue,
|
|
22
22
|
HeadlessPaneOptionValues,
|
|
23
|
+
HeadlessPaneReference,
|
|
23
24
|
HeadlessPaneResult,
|
|
24
25
|
HeadlessPaneResultByShape,
|
|
25
26
|
HeadlessPaneRow,
|
|
@@ -529,6 +530,14 @@ export interface PaneTemplateDef {
|
|
|
529
530
|
description: string;
|
|
530
531
|
keywords?: string[];
|
|
531
532
|
shortcut?: PaneTemplateShortcut;
|
|
533
|
+
/**
|
|
534
|
+
* False leaves the function out of every list and search of functions
|
|
535
|
+
* (command-bar browse, search and assistant, Help, `gloom catalog` and
|
|
536
|
+
* search, the plugin directory, chat suggestions) while typing its code
|
|
537
|
+
* still opens it, `fn` and `shot` still run it and its help still answers.
|
|
538
|
+
* ATTN until it publishes (attention/listing.ts).
|
|
539
|
+
*/
|
|
540
|
+
listed?: boolean;
|
|
532
541
|
/** Template-specific headless model. Takes precedence over the pane-level model. */
|
|
533
542
|
headless?: HeadlessPaneDefinition;
|
|
534
543
|
/**
|
package/src/ui/host.tsx
CHANGED
|
@@ -82,6 +82,8 @@ export interface ChartVectorShape {
|
|
|
82
82
|
gradient?: readonly string[];
|
|
83
83
|
/** Opacity of the whole shape, so others can recede behind a highlighted one. */
|
|
84
84
|
opacity?: number;
|
|
85
|
+
/** Text set just above the shape's first point, such as a retracement level's ratio and price. */
|
|
86
|
+
label?: string;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
interface TextEditBuffer {
|
|
@@ -508,6 +510,7 @@ export interface HostCheckboxProps {
|
|
|
508
510
|
interface HostQueryBarOption {
|
|
509
511
|
value: string;
|
|
510
512
|
label: string;
|
|
513
|
+
group?: string;
|
|
511
514
|
description?: string;
|
|
512
515
|
disabled?: boolean;
|
|
513
516
|
selected: boolean;
|
package/src/updater/failure.ts
CHANGED
|
@@ -24,7 +24,7 @@ const UPDATE_FAILURE_CODES = [
|
|
|
24
24
|
"no_build",
|
|
25
25
|
/** The download stopped before the whole file arrived. */
|
|
26
26
|
"interrupted",
|
|
27
|
-
/** The
|
|
27
|
+
/** The download does not match its checksum, or does not unpack (part of it is missing or damaged). */
|
|
28
28
|
"corrupt",
|
|
29
29
|
"permission_denied",
|
|
30
30
|
/** The macOS app runs from where it cannot be replaced: a disk image, App Translocation, another volume. */
|
|
@@ -112,6 +112,9 @@ export function classifyUpdateError(error: unknown): UpdateFailureCode {
|
|
|
112
112
|
if (status) return httpStatusFailureCode(Number(status));
|
|
113
113
|
if (/checksum mismatch|hash mismatch/i.test(message)) return "corrupt";
|
|
114
114
|
if (/zstd|decompress|gunzip|incorrect header|unexpected end of (?:file|data)/i.test(message)) return "corrupt";
|
|
115
|
+
// Bun.Archive on a tar that does not read: cut off, damaged, or none at all.
|
|
116
|
+
// Unpacking says only "ReadError", whatever stopped it.
|
|
117
|
+
if (/\bReadError\b|truncated tar|damaged tar|unrecognized archive format/i.test(message)) return "corrupt";
|
|
115
118
|
if (/timed? ?out/i.test(message)) return "timeout";
|
|
116
119
|
if (/rate limit/i.test(message)) return "rate_limited";
|
|
117
120
|
if (/read-only file system/i.test(message)) return "read_only";
|
package/src/utils/cli-output.ts
CHANGED
|
@@ -74,6 +74,47 @@ const PLAIN_EMPTY_CELL = "—";
|
|
|
74
74
|
let colorEnabledOverride: boolean | null = null;
|
|
75
75
|
let widthOverride: number | null = null;
|
|
76
76
|
let plainOverride: boolean | null = null;
|
|
77
|
+
/** Output is being rendered for a file (`renderForFile`), which has no terminal width. */
|
|
78
|
+
let renderingForFile = false;
|
|
79
|
+
|
|
80
|
+
/** Renders for a file from here on; the function returned puts the terminal's rendering back. */
|
|
81
|
+
function enterFileRendering(): () => void {
|
|
82
|
+
const saved = { color: colorEnabledOverride, plain: plainOverride, file: renderingForFile };
|
|
83
|
+
colorEnabledOverride = false;
|
|
84
|
+
plainOverride = true;
|
|
85
|
+
renderingForFile = true;
|
|
86
|
+
return () => {
|
|
87
|
+
colorEnabledOverride = saved.color;
|
|
88
|
+
plainOverride = saved.plain;
|
|
89
|
+
renderingForFile = saved.file;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Output rendered for a file (`fn --output`) as a redirect gets it: plain,
|
|
95
|
+
* without colour, and fitted to no width but `--width`'s.
|
|
96
|
+
*/
|
|
97
|
+
export function renderForFile<T>(render: () => T): T {
|
|
98
|
+
const restore = enterFileRendering();
|
|
99
|
+
try {
|
|
100
|
+
return render();
|
|
101
|
+
} finally {
|
|
102
|
+
restore();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* `renderForFile` around work that renders as it loads: a report whose text is
|
|
108
|
+
* drawn while it is built is drawn for the file, though stdout is a terminal.
|
|
109
|
+
*/
|
|
110
|
+
export async function buildForFile<T>(build: () => Promise<T>): Promise<T> {
|
|
111
|
+
const restore = enterFileRendering();
|
|
112
|
+
try {
|
|
113
|
+
return await build();
|
|
114
|
+
} finally {
|
|
115
|
+
restore();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
77
118
|
|
|
78
119
|
function colorEnabled(): boolean {
|
|
79
120
|
if (colorEnabledOverride != null) return colorEnabledOverride;
|
|
@@ -176,7 +217,7 @@ export function setCliWidthOverride(value: number | null): void {
|
|
|
176
217
|
/** Columns the output is fitted to: `--width`, else the terminal's, or null when output is piped or redirected. */
|
|
177
218
|
export function cliTerminalWidth(): number | null {
|
|
178
219
|
if (widthOverride != null) return widthOverride;
|
|
179
|
-
if (!process.stdout.isTTY) return null;
|
|
220
|
+
if (renderingForFile || !process.stdout.isTTY) return null;
|
|
180
221
|
const columns = process.stdout.columns;
|
|
181
222
|
return typeof columns === "number" && columns > 0 ? columns : null;
|
|
182
223
|
}
|
package/src/utils/crypto-pair.ts
CHANGED
|
@@ -91,6 +91,50 @@ export const MAJOR_COIN_NAMES: ReadonlyMap<string, string> = new Map([
|
|
|
91
91
|
["BNB", "BNB"],
|
|
92
92
|
]);
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* The largest coins by market value, stablecoins and gold tokens left out, with
|
|
96
|
+
* how a note names each: the coins whose bare ticker a listed company or fund
|
|
97
|
+
* may hold instead (SOL is a stale Emeren Group, LINK is Interlink Electronics).
|
|
98
|
+
* A hint reads this list; `MAJOR_COIN_NAMES` stays the shorter one stories and
|
|
99
|
+
* company-name lookups use, so a word such as "stellar" is still a company's.
|
|
100
|
+
*/
|
|
101
|
+
export const TOP_COIN_NAMES: ReadonlyMap<string, string> = new Map([
|
|
102
|
+
...MAJOR_COIN_NAMES,
|
|
103
|
+
["TRX", "tron"],
|
|
104
|
+
["ZEC", "zcash"],
|
|
105
|
+
["HYPE", "hyperliquid"],
|
|
106
|
+
["XMR", "monero"],
|
|
107
|
+
["XLM", "stellar"],
|
|
108
|
+
["NEAR", "near protocol"],
|
|
109
|
+
["TON", "toncoin"],
|
|
110
|
+
["UNI", "uniswap"],
|
|
111
|
+
["SUI", "sui"],
|
|
112
|
+
["HBAR", "hedera"],
|
|
113
|
+
["TAO", "bittensor"],
|
|
114
|
+
["SHIB", "shiba inu"],
|
|
115
|
+
["ENA", "ethena"],
|
|
116
|
+
["CRO", "cronos"],
|
|
117
|
+
["AAVE", "aave"],
|
|
118
|
+
["ONDO", "ondo"],
|
|
119
|
+
["PEPE", "pepe"],
|
|
120
|
+
["ICP", "internet computer"],
|
|
121
|
+
["ETC", "ethereum classic"],
|
|
122
|
+
["ARB", "arbitrum"],
|
|
123
|
+
["ALGO", "algorand"],
|
|
124
|
+
["ATOM", "cosmos"],
|
|
125
|
+
["APT", "aptos"],
|
|
126
|
+
["FIL", "filecoin"],
|
|
127
|
+
["POL", "polygon"],
|
|
128
|
+
["OP", "optimism"],
|
|
129
|
+
["WLD", "worldcoin"],
|
|
130
|
+
["MNT", "mantle"],
|
|
131
|
+
["KAS", "kaspa"],
|
|
132
|
+
["QNT", "quant"],
|
|
133
|
+
["VET", "vechain"],
|
|
134
|
+
["INJ", "injective"],
|
|
135
|
+
["RENDER", "render"],
|
|
136
|
+
]);
|
|
137
|
+
|
|
94
138
|
const COIN_PAIR = /^([A-Z0-9]{1,15})[-/](?:USD|EUR|GBP|USDT|USDC|BTC)$/;
|
|
95
139
|
// What a pair's listing name adds after the coin's: its quote currency, an id in brackets.
|
|
96
140
|
const PAIR_NAME_SUFFIX = /(?:\s*\([^)]*\))+$|\s+(?:USD|EUR|GBP|USDT|USDC|BTC|US Dollars?)$/i;
|
|
@@ -14,6 +14,8 @@ import { formatDistributionAmount } from "./format";
|
|
|
14
14
|
* the rate divided back.
|
|
15
15
|
*/
|
|
16
16
|
export const LATEST_DISTRIBUTION = "latest distribution annualized";
|
|
17
|
+
/** The basis of a forward rate that is the year's regular payments, which differ too widely for one to be annualized (unevenRegularPayments). */
|
|
18
|
+
export const UNEVEN_REGULAR_PAYMENTS = "trailing regular payments: uneven interims";
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* What a trailing dividend yield is everywhere it shows (DVD, a fund's in
|
|
@@ -6,16 +6,19 @@ import { formatCompact } from "./format";
|
|
|
6
6
|
import { formatUtcTime } from "./utc-time";
|
|
7
7
|
|
|
8
8
|
export const RETRACTABLE_VALUATION_FIELDS = ["enterpriseValue", "enterpriseToRevenue"] as const;
|
|
9
|
+
/** Every field a source can retract: the valuation fields, and a receipt's market cap (`marketCapUnavailable`). */
|
|
10
|
+
export const RETRACTED_FUNDAMENTALS_FIELDS = [...RETRACTABLE_VALUATION_FIELDS, "marketCap"] as const;
|
|
9
11
|
|
|
10
|
-
/** A retraction survives serialization and overrides a contradictory cached number. */
|
|
12
|
+
/** A retraction survives serialization and overrides a contradictory cached number; its reason goes with it. */
|
|
11
13
|
export function redactUnavailableFundamentals(value: Fundamentals | undefined): Fundamentals | undefined {
|
|
12
|
-
if (!value || value.unavailableFields === undefined) return value;
|
|
14
|
+
if (!value || (value.unavailableFields === undefined && value.marketCapUnavailable === undefined)) return value;
|
|
13
15
|
const unavailableFields = Array.isArray(value.unavailableFields)
|
|
14
|
-
?
|
|
16
|
+
? RETRACTED_FUNDAMENTALS_FIELDS.filter((field) => value.unavailableFields!.includes(field)) : [];
|
|
15
17
|
const result = { ...value };
|
|
16
18
|
if (unavailableFields.length) result.unavailableFields = unavailableFields;
|
|
17
19
|
else delete result.unavailableFields;
|
|
18
20
|
for (const field of unavailableFields) delete result[field];
|
|
21
|
+
if (!unavailableFields.includes("marketCap")) delete result.marketCapUnavailable;
|
|
19
22
|
return result;
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -243,6 +246,24 @@ export function epsConversionNote(fundamentals: Pick<Fundamentals, "financialCur
|
|
|
243
246
|
return eps && amounts && eps !== amounts ? `EPS (TTM) in ${eps}, converted from ${amounts} at report-date rates.` : undefined;
|
|
244
247
|
}
|
|
245
248
|
|
|
249
|
+
/** What a trailing EPS that is not the filed quarters' is called where it is shown (EE's TTM row). */
|
|
250
|
+
export const SERVED_TRAILING_EPS = "Gloom Cloud's TTM";
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* "EPS (TTM) and P/E (TTM) are Gloom Cloud's trailing figures, not the last four filed quarters'.": the headline EPS
|
|
254
|
+
* and P/E are the filed quarters' (time-series/filed-trailing-eps), so served ones say so, naming those `shown`
|
|
255
|
+
* ("P/E (TTM) is Gloom Cloud's trailing figure, ..." for a fund's P/E with no EPS). Undefined otherwise.
|
|
256
|
+
*/
|
|
257
|
+
export function trailingEpsSourceNote(
|
|
258
|
+
fundamentals: Pick<Fundamentals, "trailingEpsSource"> | undefined,
|
|
259
|
+
shown: { eps: boolean; pe: boolean },
|
|
260
|
+
): string | undefined {
|
|
261
|
+
if (fundamentals?.trailingEpsSource !== "served" || (!shown.eps && !shown.pe)) return undefined;
|
|
262
|
+
const figures = shown.eps && shown.pe ? "EPS (TTM) and P/E (TTM) are Gloom Cloud's trailing figures"
|
|
263
|
+
: `${shown.eps ? "EPS (TTM)" : "P/E (TTM)"} is Gloom Cloud's trailing figure`;
|
|
264
|
+
return `${figures}, not the last four filed quarters'.`;
|
|
265
|
+
}
|
|
266
|
+
|
|
246
267
|
type PriceEarningsBasis = Pick<Fundamentals, "financialCurrency" | "ttmConversion" | "epsCurrency" | "trailingPEConversion">;
|
|
247
268
|
|
|
248
269
|
/** The trailing EPS in the price's currency: converted at the rate the served P/E used when it says so. */
|
|
@@ -30,12 +30,35 @@ export function isFxMarketOpen(time: number): boolean {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* The FX trading day
|
|
34
|
-
* at 17:00 New York time, so Wednesday 18:00 New York is
|
|
33
|
+
* The FX trading day a print made at `time` belongs to, as "YYYY-MM-DD": the
|
|
34
|
+
* day rolls at 17:00 New York time, so Wednesday 18:00 New York is
|
|
35
|
+
* Thursday's. A print stamped exactly 17:00:00 is that day's close, so it is
|
|
36
|
+
* still that day's.
|
|
35
37
|
*/
|
|
36
38
|
export function fxTradingDay(time: number): string {
|
|
37
39
|
// The roll is 17:00, seven hours before New York's midnight, daylight saving or not.
|
|
38
|
-
return zonedDateKey(time + 7 * HOUR_MS, NEW_YORK);
|
|
40
|
+
return zonedDateKey(time - 1 + 7 * HOUR_MS, NEW_YORK);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The FX trading day of a print made at `time` (fxTradingDay), or null for a
|
|
45
|
+
* print made while the market is shut: from just after Friday's 17:00 New
|
|
46
|
+
* York close, whose own print still counts, through Sunday's 17:00 open. A
|
|
47
|
+
* tick over the weekend belongs to no trading day.
|
|
48
|
+
*/
|
|
49
|
+
export function fxPrintTradingDay(time: number): string | null {
|
|
50
|
+
return Number.isFinite(time) && isFxMarketOpen(time - 1) ? fxTradingDay(time) : null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The FX trading day the market is on at `time`: the day in progress while it
|
|
55
|
+
* trades, or the Friday that closed it while it is shut.
|
|
56
|
+
*/
|
|
57
|
+
export function fxTradingDayAt(time: number): string | null {
|
|
58
|
+
const day = fxPrintTradingDay(time);
|
|
59
|
+
if (day != null || !Number.isFinite(time)) return day;
|
|
60
|
+
const shut = currentFxClosureStart(time - 1);
|
|
61
|
+
return shut != null ? fxTradingDay(shut) : null;
|
|
39
62
|
}
|
|
40
63
|
|
|
41
64
|
/** The latest 17:00 New York on `weekday` (0 is Sunday) at or before `time`. */
|