gloomberb 0.18.4 → 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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +169 -5
- package/src/account/auth-model.ts +7 -3
- package/src/api-client/auth.ts +9 -4
- package/src/api-client/catalysts.ts +2 -1
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +31 -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 +171 -11
- package/src/api-client/live-scan.ts +91 -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 +13 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/request.ts +222 -41
- package/src/api-client/research-activity.ts +6 -12
- package/src/api-client/types.ts +74 -0
- package/src/app/keybindings/index.ts +3 -0
- package/src/app/keybindings/labels.ts +18 -1
- package/src/app/keybindings/resolve.ts +14 -0
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +42 -27
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/core-builtin-allowlist.json +1 -1
- 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/fred-series.ts +5 -0
- package/src/cli/commands/keybindings.ts +23 -0
- package/src/cli/commands/market.ts +138 -46
- package/src/cli/commands/options-chain.ts +107 -10
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +176 -39
- package/src/cli/commands/search.ts +39 -3
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +57 -35
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +10 -2
- package/src/cli/export-source.ts +29 -1
- package/src/cli/glossary.ts +73 -1
- package/src/cli/history-rows.ts +87 -16
- package/src/cli/index.ts +2 -0
- package/src/cli/known-gaps.ts +5 -2
- package/src/cli/listing-arg.ts +195 -56
- 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 +111 -16
- package/src/cli/pane-functions/function-help.ts +23 -13
- package/src/cli/pane-functions/headless.ts +56 -12
- package/src/cli/pane-functions/index.ts +58 -16
- package/src/cli/pane-functions/market-session.ts +81 -9
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/report.ts +5 -1
- package/src/cli/pane-functions/resolver.ts +35 -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 +30 -13
- package/src/cli/report-tables.ts +18 -7
- package/src/cli/restore-plugins.ts +13 -1
- package/src/cli/result.ts +57 -5
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +26 -4
- package/src/components/chart/composite/format.ts +27 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/levels.ts +2 -0
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +61 -5
- package/src/components/chart/composite/range-statistics.ts +62 -0
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +46 -7
- package/src/components/chart/composite/series-axis-tags.tsx +16 -9
- 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/types.ts +4 -0
- 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/panel/prompt-binding.ts +0 -8
- package/src/components/command-bar/workflow/alert.ts +1 -1
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/layout/header.tsx +26 -40
- package/src/components/layout/pane/footer/index.tsx +1 -0
- package/src/components/layout/pane/footer/model.ts +27 -0
- package/src/components/onboarding/onboarding-frame.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -9
- 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/display.tsx +5 -1
- 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/core/state/app/layout.ts +2 -0
- package/src/core/state/app/state.ts +9 -0
- package/src/core/state/app/types.ts +3 -0
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/saved-copies.ts +55 -16
- 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 +427 -216
- package/src/i18n/es.ts +19 -3
- package/src/i18n/ja.ts +19 -3
- package/src/i18n/ko.ts +19 -3
- package/src/i18n/zh-cn.ts +19 -3
- package/src/i18n/zh-tw.ts +19 -3
- package/src/market-data/coordinator/financials.ts +10 -2
- package/src/market-data/coordinator/index.ts +3 -1
- package/src/market-data/coordinator/quotes.ts +4 -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 +48 -7
- package/src/market-data/market/dated-previous-close.ts +203 -0
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/market/futures-week.ts +68 -0
- package/src/market-data/market/status.ts +16 -4
- package/src/market-data/options-alternatives.ts +141 -4
- package/src/market-data/quotes/contributions.ts +20 -2
- package/src/market-data/quotes/resolution.ts +3 -0
- package/src/market-data/selectors.ts +3 -0
- 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/notifications/notification-log.ts +6 -4
- package/src/plugins/builtin/alerts/alert-engine.ts +25 -2
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/calendar-events.ts +57 -6
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +380 -82
- package/src/plugins/builtin/alerts/command.ts +31 -0
- package/src/plugins/builtin/alerts/constants.ts +1 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
- package/src/plugins/builtin/alerts/fired-log.ts +113 -8
- package/src/plugins/builtin/alerts/format.ts +80 -4
- package/src/plugins/builtin/alerts/headless.ts +30 -7
- package/src/plugins/builtin/alerts/history-rows.ts +7 -3
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +135 -22
- package/src/plugins/builtin/alerts/live.ts +3 -3
- package/src/plugins/builtin/alerts/metric-command.ts +134 -0
- package/src/plugins/builtin/alerts/metric-data.ts +111 -0
- package/src/plugins/builtin/alerts/metric-model.ts +324 -0
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
- package/src/plugins/builtin/alerts/pane.tsx +90 -39
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +37 -10
- package/src/plugins/builtin/alerts/types.ts +7 -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/backtest/headless.ts +10 -5
- package/src/plugins/builtin/backtest/pane.tsx +9 -4
- package/src/plugins/builtin/backtest/presets.ts +29 -3
- package/src/plugins/builtin/broker-manager/index.tsx +10 -5
- package/src/plugins/builtin/broker-manager/model.ts +6 -1
- package/src/plugins/builtin/broker-trading/controller.ts +22 -12
- package/src/plugins/builtin/broker-trading/index.tsx +13 -1
- package/src/plugins/builtin/broker-trading/order-feed.ts +9 -4
- package/src/plugins/builtin/broker-trading/pane.tsx +1 -1
- 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 +7 -3
- package/src/plugins/builtin/catalysts/model.ts +2 -1
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +6 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +1 -1
- package/src/plugins/builtin/chart-composer/cli-options.ts +9 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +12 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -2
- package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +7 -5
- package/src/plugins/builtin/chart-composer/formula.ts +71 -18
- package/src/plugins/builtin/chart-composer/headless-schema.ts +21 -4
- package/src/plugins/builtin/chart-composer/headless.ts +19 -3
- package/src/plugins/builtin/chart-composer/index.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +53 -9
- package/src/plugins/builtin/chart-composer/presets.ts +50 -15
- package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
- package/src/plugins/builtin/chart-composer/session-history.ts +18 -9
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +40 -26
- package/src/plugins/builtin/chat/content/command-suggestions.ts +93 -0
- package/src/plugins/builtin/chat/content/composer.tsx +13 -6
- package/src/plugins/builtin/chat/content/footer.tsx +6 -3
- package/src/plugins/builtin/chat/content/index.tsx +50 -21
- package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
- package/src/plugins/builtin/chat/index.tsx +23 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
- package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
- package/src/plugins/builtin/chat/pane-links/commands.ts +271 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
- package/src/plugins/builtin/chat/pane-links/open.ts +8 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -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/cloud/plugin.tsx +1 -1
- 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/calendar-model.ts +14 -9
- package/src/plugins/builtin/econ/figures.ts +72 -0
- package/src/plugins/builtin/econ/index.tsx +33 -3
- package/src/plugins/builtin/econ/types.ts +4 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +85 -35
- package/src/plugins/builtin/econ-statistics/stats.ts +37 -9
- package/src/plugins/builtin/econ-statistics/view.ts +3 -0
- 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 +70 -15
- package/src/plugins/builtin/exposure/charts.tsx +2 -2
- package/src/plugins/builtin/exposure/model.ts +13 -1
- package/src/plugins/builtin/exposure/pane.tsx +4 -4
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/index.tsx +1 -0
- package/src/plugins/builtin/futures/model.ts +2 -1
- package/src/plugins/builtin/futures/table.tsx +2 -2
- 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 +11 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +6 -3
- package/src/plugins/builtin/fx-matrix/index.tsx +16 -4
- package/src/plugins/builtin/fx-matrix/live-legs.ts +54 -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/keybindings-editor.tsx +18 -14
- 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 +36 -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/pane.tsx +7 -5
- 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/footer.ts +2 -2
- 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 +82 -0
- package/src/plugins/builtin/members/client.ts +19 -4
- package/src/plugins/builtin/members/headless.ts +20 -7
- package/src/plugins/builtin/members/index.tsx +9 -9
- package/src/plugins/builtin/members/model.ts +23 -4
- package/src/plugins/builtin/members/pane.tsx +25 -15
- 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 +54 -6
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/model-spot.ts +5 -2
- package/src/plugins/builtin/options/strike-window.ts +2 -1
- package/src/plugins/builtin/options/table.ts +6 -9
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +42 -12
- package/src/plugins/builtin/options-positioning/client.ts +30 -0
- package/src/plugins/builtin/options-positioning/headless.ts +74 -21
- package/src/plugins/builtin/options-positioning/index.tsx +4 -4
- package/src/plugins/builtin/options-positioning/model.ts +122 -14
- package/src/plugins/builtin/options-positioning/pane.tsx +87 -42
- 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/freshness.ts +12 -10
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/live-rows.ts +10 -3
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +32 -31
- 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 +12 -7
- package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
- 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/summary/index.tsx +11 -8
- package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/rate-path/pane.tsx +2 -2
- 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 +11 -9
- 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/feed.ts +2 -2
- 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 +40 -6
- package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
- package/src/plugins/builtin/scanner/live-feed.ts +168 -0
- package/src/plugins/builtin/scanner/live-headless.ts +138 -0
- package/src/plugins/builtin/scanner/live-model.ts +362 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
- package/src/plugins/builtin/scanner/live-track.ts +186 -0
- 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 +3 -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/macro-releases.ts +65 -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/scanner-capture.ts +3 -0
- 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 +10 -3
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +26 -1
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/headless.ts +6 -4
- package/src/plugins/builtin/themes/model.ts +17 -8
- package/src/plugins/builtin/themes/pane.tsx +7 -7
- 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-footer.ts +6 -1
- 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/charts.tsx +9 -4
- package/src/plugins/builtin/vol-surface/client.ts +9 -17
- package/src/plugins/builtin/vol-surface/headless.ts +63 -14
- package/src/plugins/builtin/vol-surface/index.tsx +2 -2
- package/src/plugins/builtin/vol-surface/model.ts +22 -7
- package/src/plugins/builtin/vol-surface/pane.tsx +48 -9
- package/src/plugins/builtin/vol-surface/tables.ts +31 -3
- package/src/plugins/builtin/volatility/dvol.ts +46 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +4 -4
- package/src/plugins/builtin/volatility/series.ts +26 -0
- package/src/plugins/builtin/world-indices/footer.ts +1 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/catalog-browser.ts +13 -8
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/column-values.ts +5 -5
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
- package/src/remote/resources.ts +2 -1
- package/src/renderers/browser/app-services.ts +1 -7
- package/src/renderers/browser/config-host.ts +2 -55
- package/src/renderers/browser/main.tsx +7 -57
- 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 +222 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +29 -7
- 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/relaunch.ts +74 -25
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +173 -5
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
- package/src/renderers/electrobun/bun/index.ts +25 -1
- package/src/renderers/electrobun/shared/app-name.ts +30 -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/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -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/renderers/opentui/toast-host.tsx +71 -43
- 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/gloomberb-cloud/normalizers.ts +2 -0
- package/src/sources/provider-router/batches.ts +10 -2
- package/src/sources/provider-router/financial-routes.ts +3 -3
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/history.ts +28 -7
- package/src/sources/provider-router/index.ts +149 -10
- package/src/sources/provider-router/search.ts +13 -2
- package/src/state/app/context/index.tsx +3 -0
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/auth-transition.ts +19 -9
- package/src/sync/baseline.ts +10 -4
- package/src/sync/controller.ts +70 -19
- package/src/sync/core-contributors.ts +90 -31
- package/src/sync/react.ts +4 -1
- package/src/sync/types.ts +3 -0
- 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/telemetry/usage-counts.ts +0 -18
- package/src/test-support/preload.ts +14 -0
- package/src/theme/colors.ts +8 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name.ts +103 -3
- package/src/tickers/listing-venues.ts +38 -3
- package/src/tickers/search/bare-symbol.ts +36 -0
- package/src/tickers/search/index.ts +36 -7
- package/src/tickers/search/ranking.ts +10 -1
- package/src/tickers/search/types.ts +5 -0
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/base-series.ts +13 -5
- package/src/time-series/daily-valuation.ts +62 -0
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +2 -4
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/forward-valuation.ts +32 -0
- package/src/time-series/fundamentals.ts +198 -7
- package/src/time-series/hooks.ts +1 -0
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/price-units.ts +72 -2
- package/src/time-series/resolve-context.ts +7 -1
- package/src/time-series/resolve.ts +116 -15
- package/src/time-series/series-presentation.ts +40 -6
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +5 -3
- package/src/time-series/studies.ts +278 -74
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +3 -3
- package/src/time-series/types.ts +27 -1
- package/src/time-series/valuation-releases.ts +39 -0
- package/src/types/data-provider.ts +9 -1
- package/src/types/desktop-window.ts +2 -0
- package/src/types/financials.ts +73 -2
- package/src/types/headless.ts +61 -5
- package/src/types/instrument.ts +3 -0
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +10 -1
- package/src/ui/host.tsx +3 -0
- package/src/updater/command-names.ts +12 -7
- 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/financial-statements.ts +6 -1
- 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/network-failure.ts +9 -6
- package/src/utils/option-expiry.ts +48 -1
- package/src/utils/options.ts +10 -0
- package/src/utils/plugin-proxy-hosts.json +1 -0
- package/src/utils/price-history.ts +12 -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
- package/src/renderers/browser/first-screen.ts +0 -193
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from "../../../components";
|
|
24
24
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
25
25
|
import {
|
|
26
|
+
useAssetData,
|
|
26
27
|
useDebouncedPluginPaneState,
|
|
27
28
|
usePaneSettingValue,
|
|
28
29
|
usePaneTitle,
|
|
@@ -34,6 +35,7 @@ import type { PaneProps } from "../../../types/plugin";
|
|
|
34
35
|
import { Box, type ScrollBoxRenderable } from "../../../ui";
|
|
35
36
|
import { isPlainArrowUp, stopSearchFocusNavigation } from "../../../utils/search-focus-navigation";
|
|
36
37
|
import { toneColor, withoutQuietColumns } from "../shared/research-cells";
|
|
38
|
+
import { looksLikeTicker, useTickerCompanySearch } from "../shared/ticker-company";
|
|
37
39
|
import { OpenFdaClient, parseOpenFdaDate } from "./client";
|
|
38
40
|
import {
|
|
39
41
|
activeFilters,
|
|
@@ -41,6 +43,7 @@ import {
|
|
|
41
43
|
FILTER_DEFAULT,
|
|
42
44
|
recordColumns,
|
|
43
45
|
recordTone,
|
|
46
|
+
termsCellText,
|
|
44
47
|
type ColumnId,
|
|
45
48
|
type FilterKey,
|
|
46
49
|
type FilterState,
|
|
@@ -75,6 +78,16 @@ const formatDate = (date: Date | null): string => (date ? date.toISOString().sli
|
|
|
75
78
|
|
|
76
79
|
const capitalize = (text: string): string => text.charAt(0).toUpperCase() + text.slice(1);
|
|
77
80
|
|
|
81
|
+
/** A search written as a ticker is, in capitals (`AZN`, `BRK.B`); `cat` or `azn` is a word to search for. */
|
|
82
|
+
const writtenAsTicker = (term: string): boolean => looksLikeTicker(term) && term === term.toUpperCase();
|
|
83
|
+
|
|
84
|
+
/** What a search that matched nothing points to, by what each dataset is searched on. */
|
|
85
|
+
const EMPTY_SEARCH_HINTS: Record<OpenFdaDataset, string> = {
|
|
86
|
+
drug: "Try the drug's brand or generic name…",
|
|
87
|
+
device: "Try the device or manufacturer name…",
|
|
88
|
+
recall: "Try the firm or product name…",
|
|
89
|
+
};
|
|
90
|
+
|
|
78
91
|
/** A generic's record lists every labeler; the cell counts them instead of naming one. */
|
|
79
92
|
function labelerText(record: DrugReport): string | null {
|
|
80
93
|
if (record.manufacturer) return record.manufacturer;
|
|
@@ -95,13 +108,19 @@ function cellFor(record: OpenFdaRecord, column: ColumnId, colors: ThemeColors):
|
|
|
95
108
|
return text ? { text, color: record.manufacturer ? colors.text : colors.textMuted } : missing;
|
|
96
109
|
}
|
|
97
110
|
if (column === "role") return toned(record.role ? capitalize(record.role) : null);
|
|
98
|
-
|
|
111
|
+
// The row names the first few; its export, like the record, keeps every one.
|
|
112
|
+
if (column === "reactions") {
|
|
113
|
+
return record.reactions.length > 0 ? { text: termsCellText(record.reactions), value: record.reactions.join(", "), color: colors.text } : missing;
|
|
114
|
+
}
|
|
99
115
|
if (column === "outcome") return toned(record.outcome);
|
|
100
116
|
break;
|
|
101
117
|
case "device":
|
|
102
118
|
if (column === "product") return { text: record.product, color: colors.textBright };
|
|
103
119
|
if (column === "manufacturer") return record.manufacturer ? { text: record.manufacturer, color: colors.text } : missing;
|
|
104
|
-
if (column === "problems")
|
|
120
|
+
if (column === "problems") {
|
|
121
|
+
return record.productProblems.length > 0
|
|
122
|
+
? { text: termsCellText(record.productProblems), value: record.productProblems.join(", "), color: colors.text } : missing;
|
|
123
|
+
}
|
|
105
124
|
if (column === "event") return toned(record.eventType);
|
|
106
125
|
break;
|
|
107
126
|
case "recall":
|
|
@@ -201,6 +220,7 @@ const isDataset = (value: unknown): value is OpenFdaDataset => DATASETS.some((en
|
|
|
201
220
|
|
|
202
221
|
export function OpenFdaPane({ width, height, focused }: PaneProps) {
|
|
203
222
|
const client = useMemo(() => new OpenFdaClient(), []);
|
|
223
|
+
const dataProvider = useAssetData();
|
|
204
224
|
const [storedQuery] = usePaneSettingValue("query", "");
|
|
205
225
|
const initialQuery = String(storedQuery ?? "").trim();
|
|
206
226
|
const [query, setQuery] = usePluginPaneState("query", initialQuery);
|
|
@@ -278,9 +298,25 @@ export function OpenFdaPane({ width, height, focused }: PaneProps) {
|
|
|
278
298
|
setOpenItemId(null);
|
|
279
299
|
}, [setFilterState, setOpenItemId, setSelectedId]);
|
|
280
300
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
301
|
+
// `FDA AZN`: FDA records name the firm and its products, never a symbol, so a
|
|
302
|
+
// ticker that finds nothing is searched as its company's name (AstraZeneca),
|
|
303
|
+
// as TRIAL reads one, and the search box then shows it. Only a term written in
|
|
304
|
+
// capitals, as a ticker is (the search box or `fn FDA AZN`): a word such as
|
|
305
|
+
// "cat" stays the search it is. Each term is looked up once.
|
|
306
|
+
const companySearch = useTickerCompanySearch(dataProvider, term, {
|
|
307
|
+
eligible: records.status === "loaded" && rows.length === 0 && !records.error && writtenAsTicker(term),
|
|
308
|
+
key: term,
|
|
309
|
+
onCompany: updateQuery,
|
|
310
|
+
});
|
|
311
|
+
const retryCompanySearch = companySearch.retry;
|
|
312
|
+
|
|
313
|
+
const loading = (records.loading && rows.length === 0) || companySearch.resolving;
|
|
314
|
+
const error = records.error?.message ?? companySearch.error;
|
|
315
|
+
const reload = useCallback(() => {
|
|
316
|
+
retryCompanySearch();
|
|
317
|
+
records.reload();
|
|
318
|
+
}, [records, retryCompanySearch]);
|
|
319
|
+
usePaneRefreshKey(reload, { focused, enabled: !searchFocused && !openItemId });
|
|
284
320
|
|
|
285
321
|
const linkRecord = openRecord ?? selected;
|
|
286
322
|
const info = useMemo<PaneFooterSegment[]>(() => [
|
|
@@ -420,7 +456,7 @@ export function OpenFdaPane({ width, height, focused }: PaneProps) {
|
|
|
420
456
|
resetScrollKey={`${dataset}:${term}:${filtersKey}`}
|
|
421
457
|
selectedTextOverridesCellColor
|
|
422
458
|
emptyStateTitle={term ? `No ${datasetLabel.toLowerCase()} match ${term}.` : `No ${datasetLabel.toLowerCase()}.`}
|
|
423
|
-
emptyStateHint="Press / to search…"
|
|
459
|
+
emptyStateHint={term ? EMPTY_SEARCH_HINTS[dataset] : "Press / to search…"}
|
|
424
460
|
/>
|
|
425
461
|
);
|
|
426
462
|
}
|
|
@@ -51,8 +51,26 @@ export interface ChainVolatilities {
|
|
|
51
51
|
/** Valuation instant the volatilities were solved at, reused for the Greeks. */
|
|
52
52
|
valuationTime: number;
|
|
53
53
|
byStrike: ReadonlyMap<number, number>;
|
|
54
|
+
/**
|
|
55
|
+
* Strikes in `byStrike` whose volatility was not solved: with no two-sided
|
|
56
|
+
* out-of-the-money quote to solve from, it is read off the neighbouring solved
|
|
57
|
+
* strikes (flat beyond the last of them). Shown marked, never as a solved figure.
|
|
58
|
+
*/
|
|
59
|
+
filled: ReadonlySet<number>;
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
/**
|
|
63
|
+
* How a chain's IV is solved, said under the chain in a report and in the pane's
|
|
64
|
+
* footer while a strike's IV is filled: marked "~", it is read off the
|
|
65
|
+
* neighbouring solved strikes, not solved from a quote.
|
|
66
|
+
*/
|
|
67
|
+
export const IV_FILLED_NOTE = "~ IV filled from neighbouring strikes";
|
|
68
|
+
export const IV_FILLED_SHORT = "~ IV filled";
|
|
69
|
+
export const IV_FILLED_DETAIL = "Each strike's IV is solved from the midpoint of its out-of-the-money option. A strike with no two-sided quote there "
|
|
70
|
+
+ "has its IV read off the nearest solved strikes, flat beyond the last one, and its cell leads with ~.";
|
|
71
|
+
/** The report's line on how IV was solved, with what "~" marks when a strike is filled. */
|
|
72
|
+
export const ivSolvedNote = (anyFilled: boolean) => `IV solved from quote mids${anyFilled ? ", ~ filled from neighbouring strikes" : ""}`;
|
|
73
|
+
|
|
56
74
|
function tightestQuotes(contracts: readonly OptionContract[], expiration: number): Map<number, OptionContract> {
|
|
57
75
|
const quotes = new Map<number, OptionContract>();
|
|
58
76
|
for (const contract of contracts) {
|
|
@@ -78,8 +96,21 @@ export function solveChainVolatilities(
|
|
|
78
96
|
): ChainVolatilities {
|
|
79
97
|
const valuationTime = optionQuoteValuationTime(chain, now);
|
|
80
98
|
const byStrike = new Map<number, number>();
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
const filled = new Set<number>();
|
|
100
|
+
// A venue that marks every contract (Deribit) states its volatility: the out-of-the-money side's at each strike.
|
|
101
|
+
if ([...chain.calls, ...chain.puts].some((contract) => contract.mark)) {
|
|
102
|
+
for (const [side, contracts] of [["call", chain.calls], ["put", chain.puts]] as const) {
|
|
103
|
+
for (const contract of contracts) {
|
|
104
|
+
const mark = contract.mark;
|
|
105
|
+
if (!mark || !positive(mark.iv)) continue;
|
|
106
|
+
const outOfTheMoney = side === "call" ? contract.strike >= mark.forward : contract.strike < mark.forward;
|
|
107
|
+
if (outOfTheMoney || !byStrike.has(contract.strike)) byStrike.set(contract.strike, mark.iv);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { valuationTime, byStrike, filled };
|
|
111
|
+
}
|
|
112
|
+
if (!positive(spot)) return { valuationTime, byStrike, filled };
|
|
113
|
+
const rate = optionChainRate(chain);
|
|
83
114
|
const carry = Number.isFinite(dividendYield) ? dividendYield! : 0;
|
|
84
115
|
const expirations = new Set([...chain.calls, ...chain.puts].map((contract) => contract.expiration));
|
|
85
116
|
for (const expiration of expirations) {
|
|
@@ -103,7 +134,8 @@ export function solveChainVolatilities(
|
|
|
103
134
|
? solve("call", calls.get(strike)) : solve("put", puts.get(strike)));
|
|
104
135
|
// Without a two-sided out-of-the-money quote a strike's time value sits inside
|
|
105
136
|
// the tick, and the in-the-money quote is intrinsic plus spread noise. Read its
|
|
106
|
-
// volatility off the neighbouring solved strikes so delta stays monotonic
|
|
137
|
+
// volatility off the neighbouring solved strikes so delta stays monotonic, and
|
|
138
|
+
// say it was filled: it is no market's volatility.
|
|
107
139
|
strikes.forEach((strike, index) => {
|
|
108
140
|
let volatility = solved[index];
|
|
109
141
|
if (volatility == null) {
|
|
@@ -116,10 +148,14 @@ export function solveChainVolatilities(
|
|
|
116
148
|
? low + (high - low) * (strike - strikes[below]!) / (strikes[above]! - strikes[below]!)
|
|
117
149
|
: low ?? high;
|
|
118
150
|
}
|
|
119
|
-
if (volatility != null)
|
|
151
|
+
if (volatility != null) {
|
|
152
|
+
byStrike.set(strike, volatility);
|
|
153
|
+
if (solved[index] == null) filled.add(strike);
|
|
154
|
+
else filled.delete(strike);
|
|
155
|
+
}
|
|
120
156
|
});
|
|
121
157
|
}
|
|
122
|
-
return { valuationTime, byStrike };
|
|
158
|
+
return { valuationTime, byStrike, filled };
|
|
123
159
|
}
|
|
124
160
|
|
|
125
161
|
function atmImpliedVolatility(volatilities: ChainVolatilities, spot: number | undefined): number | null {
|
|
@@ -185,7 +221,15 @@ export function calculateOptionsSummary(
|
|
|
185
221
|
};
|
|
186
222
|
}
|
|
187
223
|
|
|
188
|
-
/**
|
|
224
|
+
/** The rate a chain's premiums are valued at: the venue's own when it states one (Deribit's zero), else the model rate. */
|
|
225
|
+
function optionChainRate(chain: Pick<OptionsChain, "rate">): number {
|
|
226
|
+
return Number.isFinite(chain.rate) ? chain.rate! : DEFAULT_OPTION_CALC_DRAFT.rate;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Greeks at the displayed spot, from the strike's solved volatility (0 when the market prices no time value).
|
|
231
|
+
* A contract its venue marks (Deribit) has the venue's greeks, at the expiry's forward.
|
|
232
|
+
*/
|
|
189
233
|
export function calculateOptionGreeks(
|
|
190
234
|
contract: OptionContract | undefined,
|
|
191
235
|
side: OptionSide,
|
|
@@ -193,6 +237,10 @@ export function calculateOptionGreeks(
|
|
|
193
237
|
dividendYield: number | undefined,
|
|
194
238
|
volatilities: ChainVolatilities,
|
|
195
239
|
): OptionValuation | undefined {
|
|
240
|
+
if (contract?.mark) {
|
|
241
|
+
const { price, delta, gamma, theta, vega } = contract.mark;
|
|
242
|
+
return { price, delta, gamma, thetaPerDay: theta, vegaPerPoint: vega, rhoPerPoint: 0 };
|
|
243
|
+
}
|
|
196
244
|
const volatility = contract ? volatilities.byStrike.get(contract.strike) : undefined;
|
|
197
245
|
// A side nobody bids has no market to measure sensitivity against.
|
|
198
246
|
if (!contract || optionMid(contract) == null || !positive(spot) || !positive(contract.strike) || volatility == null || !(volatility >= 0)) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { createTtlCache, type TtlCache } from "../../../data/ttl-cache";
|
|
2
3
|
import type { InstrumentRef } from "../../../market-data/request-types";
|
|
3
4
|
import type { QueryEntry } from "../../../market-data/result-types";
|
|
4
5
|
import { buildOptionsKey, resolveEntryData } from "../../../market-data/selectors";
|
|
@@ -15,6 +16,17 @@ const OPTIONS_LIVE_ANALYTICS_INTERVAL_MS = 1_000;
|
|
|
15
16
|
const LIVE_ANALYTICS_MAX_LOAD = 0.05;
|
|
16
17
|
/** The Treasury curve is daily; a refreshed chain reuses the one it already loaded. */
|
|
17
18
|
const TREASURY_REUSE_MS = 30 * 60_000;
|
|
19
|
+
const TREASURY_CURVE = "treasury";
|
|
20
|
+
|
|
21
|
+
interface Selection {
|
|
22
|
+
key: string | null;
|
|
23
|
+
cache: OptionsEnrichmentCache;
|
|
24
|
+
curve: TtlCache<YieldPoint[]>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const newSelection = (key: string | null): Selection => ({
|
|
28
|
+
key, cache: {}, curve: createTtlCache<YieldPoint[]>({ ttlMs: TREASURY_REUSE_MS }),
|
|
29
|
+
});
|
|
18
30
|
|
|
19
31
|
interface EnrichmentResult {
|
|
20
32
|
key: string;
|
|
@@ -59,9 +71,9 @@ export function useOptionsEnrichment(input: {
|
|
|
59
71
|
const current = useRef(input);
|
|
60
72
|
current.current = input;
|
|
61
73
|
// Per selection: the adjacent model and the Treasury curve outlive a chain refresh.
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
if (store.current.key !== key) store.current =
|
|
74
|
+
const [first] = useState(() => newSelection(key));
|
|
75
|
+
const store = useRef(first);
|
|
76
|
+
if (store.current.key !== key) store.current = newSelection(key);
|
|
65
77
|
const [result, setResult] = useState<EnrichmentResult | null>(null);
|
|
66
78
|
const resultRef = useRef(result);
|
|
67
79
|
resultRef.current = result;
|
|
@@ -71,7 +83,7 @@ export function useOptionsEnrichment(input: {
|
|
|
71
83
|
const request = current.current;
|
|
72
84
|
const identity = { key, entryKey, catalogueKey };
|
|
73
85
|
const selection = store.current;
|
|
74
|
-
const curve = selection.curve
|
|
86
|
+
const curve = selection.curve.peek(TREASURY_CURVE);
|
|
75
87
|
let projection: OptionsEnrichmentProjection | null = null;
|
|
76
88
|
// A refresh of the same expiry swaps in its analytics complete, never
|
|
77
89
|
// through a partial projection that would blank the strip for a moment.
|
|
@@ -93,7 +105,7 @@ export function useOptionsEnrichment(input: {
|
|
|
93
105
|
}).then((snapshot) => {
|
|
94
106
|
if (controller.signal.aborted) return;
|
|
95
107
|
if (projection && !projection.curveLoading && !projection.treasuryError && projection.curve?.length && !curve) {
|
|
96
|
-
selection.curve
|
|
108
|
+
selection.curve.set(TREASURY_CURVE, [...projection.curve]);
|
|
97
109
|
}
|
|
98
110
|
setResult({ ...identity, loading: false, carried: false, snapshot, projection, error: null });
|
|
99
111
|
}).catch((error: unknown) => {
|
|
@@ -154,7 +154,10 @@ export function modelSpotExtendedPrint(
|
|
|
154
154
|
return `${EXTENDED_SESSION_WORDS[print.session]}${print.mark ? " mid" : ""} ${format(print.price)}`;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
/**
|
|
157
|
+
/**
|
|
158
|
+
* Spot as every options pane writes it (OMON, OPX, OVDV): grouped, to the
|
|
159
|
+
* cent, or to the tick it was quoted at below a dollar.
|
|
160
|
+
*/
|
|
158
161
|
export function formatModelSpotPrice(price: number): string {
|
|
159
|
-
return price.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: price < 1 ? 4 : 2
|
|
162
|
+
return price.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: price < 1 ? 4 : 2 });
|
|
160
163
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { OptionsChain } from "../../../types/financials";
|
|
2
2
|
import { calculateOptionGreeks, solveChainVolatilities } from "./analytics";
|
|
3
|
-
import {
|
|
3
|
+
import { formatStrikeLabel } from "../../../utils/options";
|
|
4
|
+
import { findNearestStrikeIndex } from "./table";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Which strikes of an expiry the chain lists. Every strike by default, as
|
|
@@ -4,6 +4,7 @@ import type { OptionContract, OptionsChain } from "../../../types/financials";
|
|
|
4
4
|
import { blendHex, colors } from "../../../theme/colors";
|
|
5
5
|
import { blendForContrast, blendForSeparation, contrastRatio } from "../../../theme/color-utils";
|
|
6
6
|
import { formatCompact } from "../../../utils/format";
|
|
7
|
+
import { formatStrikeLabel } from "../../../utils/options";
|
|
7
8
|
import { formatOptionPrice, optionQuoteSide, optionSpread } from "./market-reference";
|
|
8
9
|
import { formatCarryPercent, formatCostOfSpot } from "./carry";
|
|
9
10
|
import type {
|
|
@@ -162,17 +163,13 @@ export function findNearestStrikeIndex(strikes: number[], targetStrike: number):
|
|
|
162
163
|
return bestIndex;
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
export function
|
|
166
|
-
// 15 significant digits keep every listed decimal but drop binary noise from
|
|
167
|
-
// computed strikes such as spot * 0.9.
|
|
168
|
-
return Number.isFinite(strike)
|
|
169
|
-
? strike.toLocaleString("en-US", { maximumSignificantDigits: 15 }) : "—";
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export function formatIv(value: number | undefined): string {
|
|
166
|
+
export function formatIv(value: number | undefined, filled = false): string {
|
|
173
167
|
// Providers send 0 for contracts with no implied volatility; "0.0%" would read
|
|
174
168
|
// as a real quote of zero vol.
|
|
175
169
|
if (value == null || !Number.isFinite(value) || value <= 0) return "\u2014";
|
|
170
|
+
// A filled figure leads with "~": it was read off the neighbouring strikes, not solved from a quote.
|
|
171
|
+
// Without the decimal it still fits the column at 100% and over.
|
|
172
|
+
if (filled) return value >= 0.9995 ? `~${Math.round(value * 100)}%` : `~${(value * 100).toFixed(1)}%`;
|
|
176
173
|
return `${(value * 100).toFixed(1)}%`;
|
|
177
174
|
}
|
|
178
175
|
|
|
@@ -311,7 +308,7 @@ function formatOptionContractCell(
|
|
|
311
308
|
case "openInterest":
|
|
312
309
|
return formatCompact(contract.openInterest, { fixedDecimals: true });
|
|
313
310
|
case "iv":
|
|
314
|
-
return formatIv(row.impliedVolatility);
|
|
311
|
+
return formatIv(row.impliedVolatility, row.impliedVolatilityFilled);
|
|
315
312
|
case "delta":
|
|
316
313
|
return formatGreek(greeks?.delta);
|
|
317
314
|
case "gamma":
|
|
@@ -32,6 +32,8 @@ export interface OptionTableRow {
|
|
|
32
32
|
put?: OptionContract;
|
|
33
33
|
/** Solved from quote midpoints; the call and put at a strike share it. */
|
|
34
34
|
impliedVolatility?: number;
|
|
35
|
+
/** `impliedVolatility` was filled from neighbouring strikes, not solved from a quote (see `ChainVolatilities.filled`). */
|
|
36
|
+
impliedVolatilityFilled?: boolean;
|
|
35
37
|
callGreeks?: OptionValuation;
|
|
36
38
|
putGreeks?: OptionValuation;
|
|
37
39
|
/** Time value as a share of spot per year (see `carry.ts`); null when it cannot be read. */
|
|
@@ -6,12 +6,15 @@ import { isPlainKey } from "../../../utils/keyboard";
|
|
|
6
6
|
import { formatCompact, formatPercentRaw } from "../../../utils/format";
|
|
7
7
|
import { formatMarketPrice, formatSignedMarketPrice, liveQuoteFormatOptions } from "../../../market-data/market/format";
|
|
8
8
|
import { getRegularSessionDisplay } from "../../../market-data/market/status";
|
|
9
|
-
import { chainOptionContract, formatExpDate, optionContractName, resolveOptionsTarget } from "../../../utils/options";
|
|
9
|
+
import { chainOptionContract, formatExpDate, formatStrikeLabel, optionContractName, resolveOptionsTarget } from "../../../utils/options";
|
|
10
10
|
import {
|
|
11
|
-
expiryIsoDate, findListedExpiry, formatDaysToExpiry, daysToExpiry, isLiveOptionExpiry, missingExpiryMessage, missingExpiryText,
|
|
11
|
+
expiryIsoDate, findListedExpiry, formatDaysToExpiry, daysToExpiry, isLiveOptionExpiry, missingExpiryMessage, missingExpiryText, optionExpiryVenue,
|
|
12
|
+
readOptionExpiration,
|
|
12
13
|
} from "../../../utils/option-expiry";
|
|
13
14
|
import { canonicalTickerKey } from "../../../utils/exchanges";
|
|
14
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
COIN_OPTIONS_HINT, isCoinWithoutOptions, isOptionsUnavailableError, listedOptionsAlternative, optionsUnavailableTitle,
|
|
17
|
+
} from "../../../market-data/options-alternatives";
|
|
15
18
|
import { useChartQueries, useOptionsQuery, useResolvedEntryValue, useTickerFinancials } from "../../../market-data/hooks";
|
|
16
19
|
import {
|
|
17
20
|
Button,
|
|
@@ -41,14 +44,13 @@ import type { OptionContract } from "../../../types/financials";
|
|
|
41
44
|
import { OPTIONS_CALCULATOR_TEMPLATE_ID } from "../options-calculator/model";
|
|
42
45
|
import { buildChainCalcParams, resolveCalcSide } from "./calc-seed";
|
|
43
46
|
import { useOptionsCatalogue } from "./expiry-catalogue";
|
|
44
|
-
import { calculateOptionGreeks, calculateOptionsSummary, solveChainVolatilities, type OptionsSummary } from "./analytics";
|
|
47
|
+
import { calculateOptionGreeks, calculateOptionsSummary, IV_FILLED_DETAIL, IV_FILLED_NOTE, IV_FILLED_SHORT, solveChainVolatilities, type OptionsSummary } from "./analytics";
|
|
45
48
|
import {
|
|
46
49
|
DEFAULT_OPTION_FIELD_IDS,
|
|
47
50
|
buildStrikeList,
|
|
48
51
|
createOptionColumns,
|
|
49
52
|
findNearestStrikeIndex,
|
|
50
53
|
formatIv,
|
|
51
|
-
formatStrikeLabel,
|
|
52
54
|
optionColumnColor,
|
|
53
55
|
renderOptionCell,
|
|
54
56
|
resolveDefaultStrikeTarget,
|
|
@@ -272,7 +274,9 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
|
|
|
272
274
|
// A listing can still carry a date whose last session has closed. The chain
|
|
273
275
|
// never opens there, nor on a saved date that has since passed: it takes the nearest live one.
|
|
274
276
|
const now = Date.now();
|
|
275
|
-
|
|
277
|
+
// Expiries close on the listing's clock: a coin's options (Deribit) settle at 08:00 UTC on any day.
|
|
278
|
+
const expiryVenue = optionExpiryVenue(effectiveTicker, effectiveExchange);
|
|
279
|
+
const liveExpiration = (expiration: number) => isLiveOptionExpiry(expiration, now, expiryVenue);
|
|
276
280
|
const listedExpirations = initialChain?.expirationDates ?? [];
|
|
277
281
|
const openingExpirations = listedExpirations.some(liveExpiration) ? listedExpirations.filter(liveExpiration) : listedExpirations;
|
|
278
282
|
const initialExpiration = openingExpirations.length === 0 ? undefined : openingExpirations.reduce((best, expiration) => (
|
|
@@ -322,9 +326,9 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
|
|
|
322
326
|
const listed = selectedExpirationMissing
|
|
323
327
|
? [...availableExpirations, selectedExpiration!].sort((left, right) => left - right) : availableExpirations;
|
|
324
328
|
// A date whose last session has closed has no contracts left to show; the strip leaves it out, unless every date has.
|
|
325
|
-
const current = (expiration: number) => isLiveOptionExpiry(expiration, Date.now(),
|
|
329
|
+
const current = (expiration: number) => isLiveOptionExpiry(expiration, Date.now(), expiryVenue);
|
|
326
330
|
return listed.some(current) ? listed.filter((expiration) => expiration === selectedExpiration || current(expiration)) : listed;
|
|
327
|
-
}, [availableExpirations,
|
|
331
|
+
}, [availableExpirations, expiryVenue, selectedExpiration, selectedExpirationMissing]);
|
|
328
332
|
// Keep the date strip stable while a mouse press focuses this pane. A new
|
|
329
333
|
// tab list asks the web host to reveal the active tab and can move the date
|
|
330
334
|
// being clicked before mouse-up, cancelling selection of an offscreen expiry.
|
|
@@ -444,7 +448,7 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
|
|
|
444
448
|
const chainAsOfMs = asOfChain?.asOf ? Date.parse(asOfChain.asOf) : Number.NaN;
|
|
445
449
|
const expiryAsOfMs = Number.isFinite(chainAsOfMs) ? chainAsOfMs : Date.now();
|
|
446
450
|
const expiryDate = selectedExpiration == null ? "" : expiryIsoDate(selectedExpiration);
|
|
447
|
-
const expiryDays = selectedExpiration == null ? "" : formatDaysToExpiry(selectedExpiration, expiryAsOfMs,
|
|
451
|
+
const expiryDays = selectedExpiration == null ? "" : formatDaysToExpiry(selectedExpiration, expiryAsOfMs, expiryVenue);
|
|
448
452
|
useRemoteUiNode(expiryDate && chain && !expirationUnavailable ? {
|
|
449
453
|
role: "report-notice",
|
|
450
454
|
label: "Expiry",
|
|
@@ -574,6 +578,7 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
|
|
|
574
578
|
call,
|
|
575
579
|
put,
|
|
576
580
|
impliedVolatility: volatilities?.byStrike.get(strike),
|
|
581
|
+
impliedVolatilityFilled: volatilities?.filled.has(strike) ?? false,
|
|
577
582
|
callGreeks: volatilities ? calculateOptionGreeks(call, "call", greeksSpot, dividendYield, volatilities) : undefined,
|
|
578
583
|
putGreeks: volatilities ? calculateOptionGreeks(put, "put", greeksSpot, dividendYield, volatilities) : undefined,
|
|
579
584
|
callExtrinsicPerYear: call && volatilities ? optionCarry(call, "call", greeksSpot, volatilities.valuationTime)?.extrinsicPerYear ?? null : null,
|
|
@@ -618,9 +623,21 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
|
|
|
618
623
|
+ `${new Date(footerSpot.observedAt).toISOString().slice(11, 16)} UTC` : null,
|
|
619
624
|
strikeChain && !listedOpenInterest.loading ? openInterestAsOf?.date ? `OI ${openInterestAsOf.date.slice(5)}` : "OI undated" : null]
|
|
620
625
|
.filter(Boolean).join(" · ");
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
626
|
+
// How IV was solved is said while the chain shows a figure that was not: a strike with no two-sided
|
|
627
|
+
// out-of-the-money quote has its IV read off the neighbouring strikes, and its cell leads with "~".
|
|
628
|
+
const ivFilledShown = optionFieldIds.includes("iv") && rows.some((row) => row.impliedVolatilityFilled && row.impliedVolatility != null);
|
|
629
|
+
// A report of the pane (`gloom fn OMON`) says it too.
|
|
630
|
+
useRemoteUiNode(ivFilledShown ? {
|
|
631
|
+
role: "report-notice",
|
|
632
|
+
label: "IV filled",
|
|
633
|
+
getMetadata: () => ({ text: IV_FILLED_NOTE, key: "ivFilled", value: true }),
|
|
634
|
+
} : null);
|
|
635
|
+
usePaneFooter("options-basis", () => ({ info: [
|
|
636
|
+
...(basisText ? [{ id: "greeks-basis", parts: [{ text: basisText, tone: "muted" as const }],
|
|
637
|
+
variants: [[{ text: shortBasisText, tone: "muted" as const }], []] }] : []),
|
|
638
|
+
...(ivFilledShown ? [{ id: "iv-filled", parts: [{ text: IV_FILLED_NOTE, tone: "muted" as const }],
|
|
639
|
+
title: IV_FILLED_DETAIL, variants: [[{ text: IV_FILLED_SHORT, tone: "muted" as const }]] }] : []),
|
|
640
|
+
] }), [basisText, shortBasisText, ivFilledShown]);
|
|
624
641
|
// Figures that summarise the whole expiry move at most once a second, so a
|
|
625
642
|
// busy stream reads as a steady strip rather than flicker.
|
|
626
643
|
// A new expiry, a refreshed snapshot or the underlying price arriving or
|
|
@@ -904,6 +921,19 @@ export function OptionsView({ width, height, focused, nestedInTabs = false, ivRa
|
|
|
904
921
|
return <EmptyState title="Select a ticker." />;
|
|
905
922
|
}
|
|
906
923
|
if (loading && !chain) return <Spinner label="Loading options chain..." />;
|
|
924
|
+
if (error && !chain && isOptionsUnavailableError(error) && isCoinWithoutOptions(effectiveTicker)) {
|
|
925
|
+
// A coin other than BTC and ETH: the coins that have options, and a bitcoin-linked fund's.
|
|
926
|
+
return (
|
|
927
|
+
<EmptyState
|
|
928
|
+
title={optionsUnavailableTitle(effectiveTicker)}
|
|
929
|
+
hint={COIN_OPTIONS_HINT}
|
|
930
|
+
actions={<>
|
|
931
|
+
<Button label="BTC-USD options" onPress={() => createPaneFromTemplate("options-pane", { symbol: "BTC-USD" })} />
|
|
932
|
+
<Button label="IBIT options" onPress={() => createPaneFromTemplate("options-pane", { symbol: "IBIT" })} />
|
|
933
|
+
</>}
|
|
934
|
+
/>
|
|
935
|
+
);
|
|
936
|
+
}
|
|
907
937
|
if (error && !chain && isOptionsUnavailableError(error)) {
|
|
908
938
|
// A future or commodity with no chain of its own: the listed fund whose options stand in, and OSA on it.
|
|
909
939
|
const alternative = listedOptionsAlternative(effectiveTicker);
|
|
@@ -12,6 +12,8 @@ export interface ExpiryOpenInterest {
|
|
|
12
12
|
/** Change since `previousOiDate`; null without a stored session to compare with. */
|
|
13
13
|
callChange: number | null;
|
|
14
14
|
putChange: number | null;
|
|
15
|
+
/** The instant it settles, when the venue states one: 08:00 UTC for Deribit's BTC and ETH options. */
|
|
16
|
+
expiresAt?: string;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export interface StrikeOpenInterest {
|
|
@@ -24,6 +26,12 @@ export interface StrikeOpenInterest {
|
|
|
24
26
|
payout: number | null;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/** What one contract is: 1 BTC for Deribit's options, 100 shares for a US listing's (absent from US payloads). */
|
|
30
|
+
interface PositioningContract {
|
|
31
|
+
size: number;
|
|
32
|
+
unit: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
export interface OpenInterestPayload {
|
|
28
36
|
version: 1;
|
|
29
37
|
symbol: string;
|
|
@@ -34,11 +42,19 @@ export interface OpenInterestPayload {
|
|
|
34
42
|
tracked: boolean;
|
|
35
43
|
spot: number | null;
|
|
36
44
|
spotAsOf: string | null;
|
|
45
|
+
/** `close` when spot is a regular session's close at `spotAsOf`: a cash index outside its session. Absent from older servers. */
|
|
46
|
+
spotBasis?: "close";
|
|
37
47
|
delayed: boolean;
|
|
38
48
|
expiries: ExpiryOpenInterest[];
|
|
39
49
|
expiry: string | null;
|
|
40
50
|
strikes: StrikeOpenInterest[];
|
|
41
51
|
warnings: string[];
|
|
52
|
+
/** When the counts were read, for a venue that publishes them live (Deribit); `oiDate` is then that UTC day. */
|
|
53
|
+
oiAsOf?: string | null;
|
|
54
|
+
/** The venue listing the options, when it is not the US exchanges: Deribit. */
|
|
55
|
+
venue?: string;
|
|
56
|
+
/** Open interest counts contracts of this size; absent means 100 shares. */
|
|
57
|
+
contract?: PositioningContract;
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
export interface GammaStrike {
|
|
@@ -56,6 +72,9 @@ interface GammaExpiry {
|
|
|
56
72
|
/** Short, as a positive number. */
|
|
57
73
|
puts: number;
|
|
58
74
|
net: number;
|
|
75
|
+
/** The expiry's strikes with the most call and put gamma; absent from older servers. */
|
|
76
|
+
callWall?: number | null;
|
|
77
|
+
putWall?: number | null;
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
export interface GammaPayload {
|
|
@@ -65,6 +84,8 @@ export interface GammaPayload {
|
|
|
65
84
|
oiDate: string | null;
|
|
66
85
|
spot: number | null;
|
|
67
86
|
spotAsOf: string | null;
|
|
87
|
+
/** `close` when spot is a regular session's close at `spotAsOf`: a cash index outside its session. Absent from older servers. */
|
|
88
|
+
spotBasis?: "close";
|
|
68
89
|
delayed: boolean;
|
|
69
90
|
/** The one expiry measured, or null for all of them. */
|
|
70
91
|
expiry: string | null;
|
|
@@ -82,8 +103,17 @@ export interface GammaPayload {
|
|
|
82
103
|
strikes: GammaStrike[];
|
|
83
104
|
/** Each priced expiry's totals, from the same legs as `total`; absent from older servers. */
|
|
84
105
|
byExpiry?: GammaExpiry[];
|
|
106
|
+
/** When the quotes behind the volatilities were taken: the expiry's own, or the newest priced one's for all. */
|
|
85
107
|
quotesAsOf: string | null;
|
|
108
|
+
/**
|
|
109
|
+
* The instant gamma is evaluated at, which time to expiry runs from: now
|
|
110
|
+
* while the quotes are current, the spot's time with a closed session's
|
|
111
|
+
* quotes (before the open). Absent from older servers.
|
|
112
|
+
*/
|
|
113
|
+
gammaAsOf?: string | null;
|
|
86
114
|
warnings: string[];
|
|
115
|
+
/** The venue listing the options, when it is not the US exchanges: Deribit. */
|
|
116
|
+
venue?: string;
|
|
87
117
|
}
|
|
88
118
|
|
|
89
119
|
export type OptionsPositioningApi = Pick<typeof apiClient, "optionsPositioning">;
|