gloomberb 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -6,16 +6,19 @@ import { useShortcut } from "../../../react/input";
|
|
|
6
6
|
import { afterLayout, revealInScrollBox } from "../../../components/ui/reveal-in-scroll-box";
|
|
7
7
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
8
8
|
import type { Quote } from "../../../types/financials";
|
|
9
|
+
import { quoteAgeText } from "../../../market-data/quotes/freshness";
|
|
9
10
|
import { formatPercentRaw } from "../../../utils/format";
|
|
10
11
|
import type { BrokerAccount, BrokerOrder, BrokerOrderPreview, BrokerOrderRequest, BrokerTradingCapabilities } from "../../../types/trading";
|
|
11
12
|
import { Box, ScrollBox, Text, TextAttributes, useUiCapabilities, type BoxRenderable, type ScrollBoxRenderable } from "../../../ui";
|
|
12
13
|
import { useDialogState } from "../../../ui/dialog";
|
|
13
14
|
import { BrokerAccountPicker, type BrokerAccountChoice } from "./account-picker";
|
|
14
|
-
import { TicketLegs, TicketSection, TicketOrderHeadline, TicketOrderSummary, TicketReceiptRow, TicketStatus, ticketMoney as money, ticketNumber as number, ticketTifName, ticketTypeName as typeName } from "./ticket-parts";
|
|
15
|
+
import { TicketExits, TicketLegs, TicketSection, TicketOrderHeadline, TicketOrderSummary, TicketReceiptRow, TicketStatus, ticketImpactMoney, ticketImpactSource, ticketMoney as money, ticketNumber as number, ticketTifName, ticketTypeName as typeName } from "./ticket-parts";
|
|
15
16
|
import { brokerOrderDone, orderEstimatePrice, ticketEditingPriceStep } from "./orders-data";
|
|
17
|
+
import { linkedFeature, trailingText, trailingUnit, type LinkedFeature } from "./linked-orders";
|
|
16
18
|
|
|
17
|
-
export type TicketAction = "enable" | "review" | "submit" | "back" | "confirm" | "refresh" | "orders" | "new" | "cancel" | "all" | "quantity25" | "quantity50" | "priceBid" | "priceMid" | "priceAsk" | "priceLast";
|
|
18
|
-
export type TicketField = "action" | "orderType" | "quantity" | "limitPrice" | "stopPrice" | "tif" | "outsideRth" | "typedConfirmation" | "confirmOrders"
|
|
19
|
+
export type TicketAction = "enable" | "review" | "submit" | "back" | "confirm" | "refresh" | "orders" | "new" | "cancel" | "all" | "quantity25" | "quantity50" | "priceBid" | "priceMid" | "priceAsk" | "priceLast" | "priceChart";
|
|
20
|
+
export type TicketField = "action" | "orderType" | "quantity" | "limitPrice" | "stopPrice" | "tif" | "outsideRth" | "typedConfirmation" | "confirmOrders"
|
|
21
|
+
| "bracket" | "takeProfitPrice" | "stopLossPrice" | "trailing" | "trailingUnit";
|
|
19
22
|
export interface TicketViewModel {
|
|
20
23
|
brokerName: string; symbol: string; accounts: BrokerAccount[]; accountId?: string;
|
|
21
24
|
accountChoices?: readonly BrokerAccountChoice[]; accountChoiceValue?: string;
|
|
@@ -51,21 +54,26 @@ export interface BrokerTicketViewProps {
|
|
|
51
54
|
onClose?(): void;
|
|
52
55
|
/** Terminal content measurement; the DOM uses intrinsic flex layout. */
|
|
53
56
|
onContentHeight?(height: number): void;
|
|
57
|
+
/** With a chart beside the ticket: pick a price on it for this field, or for the entry's without one. */
|
|
58
|
+
onPickPrice?(field?: TicketField): void;
|
|
54
59
|
}
|
|
55
|
-
/**
|
|
56
|
-
|
|
60
|
+
/**
|
|
61
|
+
* "Limit at $759.50 · Day", "Stop $750.00 · Day", "Trailing $1.50 · Day", "Limit $790.00 · stop $740.00, one cancels
|
|
62
|
+
* the other · GTC": an order's terms, each named once.
|
|
63
|
+
*/
|
|
64
|
+
function orderTerms(order: Pick<BrokerOrder, "orderType" | "limitPrice" | "stopPrice" | "tif" | "trailingAmount" | "trailingPercent"> & Pick<BrokerOrderRequest, "orderClass" | "stopLossPrice"> & { outsideRth?: boolean },
|
|
65
|
+
limitWord: string, money: (value: number) => string): string {
|
|
57
66
|
const limit = order.limitPrice !== undefined ? `${limitWord} ${money(order.limitPrice)}` : "";
|
|
58
67
|
const stop = order.stopPrice !== undefined ? `Stop ${money(order.stopPrice)}` : "";
|
|
59
|
-
const price = order.orderType === "
|
|
68
|
+
const price = order.orderType === "TRAIL" ? [trailingText(order, money)]
|
|
69
|
+
: order.orderClass === "oco" ? [`Limit ${money(order.limitPrice ?? NaN)}`, `stop ${money(order.stopLossPrice ?? NaN)}, one cancels the other`]
|
|
70
|
+
: order.orderType === "STP" && stop ? [stop] : order.orderType === "STP LMT" && stop ? [stop, ...(order.limitPrice !== undefined ? [`limit ${money(order.limitPrice)}`] : [])]
|
|
60
71
|
: [`${typeName[order.orderType] ?? order.orderType}${limit ? ` ${limit}` : ""}`, ...(stop ? [stop] : [])];
|
|
61
72
|
return [...price, ...(order.tif ? [ticketTifName[order.tif] ?? order.tif] : []), ...(order.outsideRth ? ["Outside RTH"] : [])].join(" · ");
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
export function ticketQuoteAge(quote: Quote | undefined, now = Date.now()): string {
|
|
65
|
-
|
|
66
|
-
if (!at || at > now) return "Age unknown";
|
|
67
|
-
const seconds = Math.max(0, Math.floor((now - at) / 1000));
|
|
68
|
-
return seconds < 60 ? `${seconds}s old` : seconds < 3600 ? `${Math.floor(seconds / 60)}m old` : `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m old`;
|
|
76
|
+
return quoteAgeText(quote?.lastTradeTime ?? quote?.lastUpdated, now);
|
|
69
77
|
}
|
|
70
78
|
/** The decimals a price step needs: 0.01 and 0.05 take two, 0.0001 four. Never fewer than two. */
|
|
71
79
|
function stepDecimals(step: number): number {
|
|
@@ -86,6 +94,8 @@ function replacementChanges(original: BrokerOrder, draft: BrokerOrderRequest, pr
|
|
|
86
94
|
original.quantity !== draft.quantity ? `Quantity ${number(original.quantity)} → ${number(draft.quantity)}` : "",
|
|
87
95
|
original.limitPrice !== draft.limitPrice && draft.limitPrice !== undefined ? `Limit ${price(original.limitPrice)} → ${price(draft.limitPrice)}` : "",
|
|
88
96
|
original.stopPrice !== draft.stopPrice && draft.stopPrice !== undefined ? `Stop ${price(original.stopPrice)} → ${price(draft.stopPrice)}` : "",
|
|
97
|
+
original.trailingAmount !== draft.trailingAmount && draft.trailingAmount !== undefined ? `Trail ${price(original.trailingAmount)} → ${price(draft.trailingAmount)}` : "",
|
|
98
|
+
original.trailingPercent !== draft.trailingPercent && draft.trailingPercent !== undefined ? `Trail ${number(original.trailingPercent)}% → ${number(draft.trailingPercent)}%` : "",
|
|
89
99
|
].filter(Boolean);
|
|
90
100
|
return changes.length ? changes.join(" · ") : "No change from the working order";
|
|
91
101
|
}
|
|
@@ -151,8 +161,11 @@ function DockedQuote({ quote, delayed, stale, source, updated, price, change, wi
|
|
|
151
161
|
</Box>;
|
|
152
162
|
}
|
|
153
163
|
|
|
164
|
+
/** The ticket prices a pick on the chart can set. */
|
|
165
|
+
const PRICE_FIELDS: readonly string[] = ["limitPrice", "stopPrice", "takeProfitPrice", "stopLossPrice"];
|
|
166
|
+
|
|
154
167
|
/** One ticket presentation, with the same review and focus gates on every renderer. */
|
|
155
|
-
export function BrokerTicketView({ model: m, width, height, focused, onEdit, onAction, onAccountChange, onCapture, docked = false, blocked = false, asking = false, onClose, onContentHeight }: BrokerTicketViewProps) {
|
|
168
|
+
export function BrokerTicketView({ model: m, width, height, focused, onEdit, onAction, onAccountChange, onCapture, docked = false, blocked = false, asking = false, onClose, onContentHeight, onPickPrice }: BrokerTicketViewProps) {
|
|
156
169
|
const c = useThemeColors();
|
|
157
170
|
const native = useUiCapabilities().nativePaneChrome;
|
|
158
171
|
const dialogOpen = useDialogState((state) => state.isOpen);
|
|
@@ -171,6 +184,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
171
184
|
// A credit spread's preview reports what it receives as a negative cost.
|
|
172
185
|
const previewCredit = (m.preview?.estimatedCost ?? 0) < 0;
|
|
173
186
|
const previewCost = m.preview?.estimatedCost === undefined ? undefined : Math.abs(m.preview.estimatedCost);
|
|
187
|
+
const impactSource = ticketImpactSource(m.preview);
|
|
174
188
|
const unit = strategy ? "spreads" : draft?.contract.secType === "OPT" ? "contracts" : "shares";
|
|
175
189
|
const busy = blocked || ["previewing", "submitting", "cancelling"].includes(m.phase);
|
|
176
190
|
const fast = mode === "simulation" && m.confirmOrders === false && !m.modifying;
|
|
@@ -179,6 +193,21 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
179
193
|
const editing = m.phase === "editing" || m.phase === "previewing" || fastSubmitting;
|
|
180
194
|
const showLimit = draft?.orderType === "LMT" || draft?.orderType === "STP LMT";
|
|
181
195
|
const showStop = draft?.orderType === "STP" || draft?.orderType === "STP LMT";
|
|
196
|
+
// An OCO is a limit and a stop on one side; a bracket adds exits to an entry; a trailing stop follows the market.
|
|
197
|
+
const oco = draft?.orderClass === "oco";
|
|
198
|
+
const bracket = draft?.orderClass === "bracket";
|
|
199
|
+
const trailing = draft?.orderType === "TRAIL";
|
|
200
|
+
// A price can come from the chart beside the ticket; a spread's net premium is not on it.
|
|
201
|
+
const chartPick = !!onPickPrice && !strategy && (showLimit || showStop);
|
|
202
|
+
const trailUnit = draft ? trailingUnit(draft) : "amount";
|
|
203
|
+
const trailValue = trailUnit === "percent" ? draft?.trailingPercent : draft?.trailingAmount;
|
|
204
|
+
// What the broker cannot take is not offered. A draft that already holds one still shows it, to be taken off;
|
|
205
|
+
// review refuses it with the reason.
|
|
206
|
+
const offers = (feature: LinkedFeature, held: boolean) => held || linkedFeature(m.capabilities, feature, m.brokerName).available;
|
|
207
|
+
const showBracket = !!draft && !strategy && !m.modifying && !trailing && !oco && offers("bracket", bracket);
|
|
208
|
+
// One unit needs no switch: the field's suffix says which it is.
|
|
209
|
+
const trailUnits = m.capabilities?.trailing ?? [];
|
|
210
|
+
const showTrailUnit = trailUnits.length > 1 || !trailUnits.includes(trailUnit);
|
|
182
211
|
const extendedHours = m.capabilities?.extendedHours && (!m.capabilities.extendedHoursTif || m.capabilities.extendedHoursTif.includes(draft?.tif ?? "DAY"));
|
|
183
212
|
const inner = Math.max(28, width - (docked ? 2 : native ? 6 : 2));
|
|
184
213
|
const formWidth = wide ? Math.min(74, Math.floor((inner - 3) * 0.58)) : inner;
|
|
@@ -207,8 +236,12 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
207
236
|
if (m.phase === "enable") return ["enable", "back"];
|
|
208
237
|
if (editing) return [
|
|
209
238
|
"account", "action", "orderType", "quantity", "quantity25", "quantity50", "all",
|
|
210
|
-
...(showLimit ? ["limitPrice", "priceBid", "priceMid", "priceAsk", "priceLast"] : []),
|
|
211
|
-
...(showStop ? ["stopPrice"] : []),
|
|
239
|
+
...(showLimit ? ["limitPrice", "priceBid", "priceMid", "priceAsk", "priceLast", ...(chartPick ? ["priceChart"] : [])] : []),
|
|
240
|
+
...(showStop ? ["stopPrice", ...(chartPick && !showLimit ? ["priceChart"] : [])] : []),
|
|
241
|
+
...(oco ? ["stopLossPrice"] : []),
|
|
242
|
+
...(trailing ? ["trailing", ...(showTrailUnit ? ["trailingUnit"] : [])] : []),
|
|
243
|
+
...(showBracket ? ["bracket"] : []),
|
|
244
|
+
...(bracket ? ["takeProfitPrice", "stopLossPrice"] : []),
|
|
212
245
|
"tif",
|
|
213
246
|
...(extendedHours ? ["outsideRth"] : []),
|
|
214
247
|
...(mode === "simulation" && !m.modifying ? ["confirmOrders"] : []),
|
|
@@ -220,7 +253,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
220
253
|
if (finished) return ["new", "orders"];
|
|
221
254
|
if (resultStatus === "UNKNOWN") return ["refresh", "orders"];
|
|
222
255
|
return ["refresh", "orders", "new"];
|
|
223
|
-
}, [m.phase, editing, review, live, showLimit, showStop, extendedHours, resultStatus, finished, m.tradingEnabled, mode, m.modifying]);
|
|
256
|
+
}, [m.phase, editing, review, live, showLimit, showStop, oco, trailing, showTrailUnit, showBracket, bracket, extendedHours, resultStatus, finished, m.tradingEnabled, mode, m.modifying, chartPick]);
|
|
224
257
|
const previousFocus = useRef<{ phase: TicketViewModel["phase"]; revision?: number } | undefined>(undefined);
|
|
225
258
|
useEffect(() => {
|
|
226
259
|
if (previousFocus.current?.phase !== m.phase || previousFocus.current?.revision !== m.focusRevision) {
|
|
@@ -241,11 +274,15 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
241
274
|
const typedMatches = !live || m.typedConfirmation?.trim().toUpperCase() === confirmationSymbol;
|
|
242
275
|
const holdingBlocked = sell && !strategy && !m.capabilities?.shortSelling && (m.position === undefined || (draft?.quantity ?? 0) > Math.max(0, m.position));
|
|
243
276
|
const validPrice = (value: number | undefined) => value !== undefined && Number.isFinite(value) && value > 0;
|
|
277
|
+
// A bracket needs one exit at least; each one shown is a price or left empty.
|
|
278
|
+
const exitOk = (value: number | undefined) => value === undefined || validPrice(value);
|
|
244
279
|
const canReview = m.connected && m.tradingEnabled && !!account && !!draft && validPrice(draft.quantity) && !holdingBlocked && !busy
|
|
245
|
-
&& (!showLimit || validPrice(draft.limitPrice)) && (!showStop || validPrice(draft.stopPrice))
|
|
280
|
+
&& (!showLimit || validPrice(draft.limitPrice)) && (!showStop || validPrice(draft.stopPrice)) && (!oco || validPrice(draft.stopLossPrice))
|
|
281
|
+
&& (!trailing || validPrice(trailValue))
|
|
282
|
+
&& (!bracket || exitOk(draft.takeProfitPrice) && exitOk(draft.stopLossPrice) && (validPrice(draft.takeProfitPrice) || validPrice(draft.stopLossPrice)));
|
|
246
283
|
const blockingPreview = !!m.preview?.errors?.length;
|
|
247
284
|
const canConfirm = review && typedMatches && !blockingPreview && m.connected && m.tradingEnabled && !busy;
|
|
248
|
-
const textActive = ["quantity", "limitPrice", "stopPrice", "typedConfirmation"].includes(active);
|
|
285
|
+
const textActive = ["quantity", "limitPrice", "stopPrice", "takeProfitPrice", "stopLossPrice", "trailing", "typedConfirmation"].includes(active);
|
|
249
286
|
// Leaving a field must return h/l to the research strip, including after a command.
|
|
250
287
|
useEffect(() => {
|
|
251
288
|
onCapture?.(focused && textActive);
|
|
@@ -263,8 +300,15 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
263
300
|
if (active === "confirmOrders") { if (mode === "simulation" && !m.modifying) onEdit("confirmOrders", m.confirmOrders === false); return; }
|
|
264
301
|
if (active === "tif") { if (!m.modifying) tifControl.current?.open(); return; }
|
|
265
302
|
if (active === "outsideRth") { if (!m.modifying && extendedHours) onEdit("outsideRth", !draft?.outsideRth); return; }
|
|
303
|
+
if (active === "bracket") { onEdit("bracket", !bracket); return; }
|
|
304
|
+
if (active === "trailingUnit") {
|
|
305
|
+
const other = trailUnit === "percent" ? "amount" : "percent";
|
|
306
|
+
if (m.capabilities?.trailing?.includes(other)) onEdit("trailingUnit", other);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
266
309
|
if (active === "review") { if (canReview) onAction("submit"); return; }
|
|
267
310
|
if (active === "confirm") { if (canConfirm) onAction("confirm"); return; }
|
|
311
|
+
if (active === "priceChart") { onPickPrice?.(showLimit ? "limitPrice" : "stopPrice"); return; }
|
|
268
312
|
if (quickActions.includes(active as TicketAction)) { if (!quickDisabled(active as TicketAction)) onAction(active as TicketAction); return; }
|
|
269
313
|
if (active === "enable" && !m.connected) return;
|
|
270
314
|
if (["back", "refresh", "orders", "new", "enable", "cancel"].includes(active)) onAction(active as TicketAction);
|
|
@@ -283,6 +327,8 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
283
327
|
...(showLimit || showStop ? ([["8", "Bid", "priceBid"], ["9", "Mid", "priceMid"], ["0", "Ask", "priceAsk"], ...(strategy ? [] : [["p", "Last", "priceLast"]] as const)] as const)
|
|
284
328
|
.map(([key, label, action]) => actionShortcut(key, label, action, quickDisabled(action))) : []),
|
|
285
329
|
...(extendedHours ? [editShortcut("x", "Extended", "outsideRth", !draft?.outsideRth, !!m.modifying)] : []),
|
|
330
|
+
// The price being typed, or the entry's, from the chart beside the ticket.
|
|
331
|
+
...(chartPick ? [keyAction("c", "hart price", () => onPickPrice!(PRICE_FIELDS.includes(active) ? active as TicketField : undefined))] : []),
|
|
286
332
|
] : review ? [actionShortcut("e", "dit", "back"), actionShortcut("o", "rders", "orders")]
|
|
287
333
|
: m.phase === "enable" ? [actionShortcut("e", "nable", "enable", !m.connected)]
|
|
288
334
|
: m.phase === "cancel-review" ? [actionShortcut("e", "dit", "back")]
|
|
@@ -305,6 +351,12 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
305
351
|
if (!event.repeat) activate();
|
|
306
352
|
return;
|
|
307
353
|
}
|
|
354
|
+
// A price holds no letters: c in a price field picks that price on the chart beside the ticket.
|
|
355
|
+
if (chartPick && editing && !busy && event.name === "c" && !event.shift && PRICE_FIELDS.includes(active)) {
|
|
356
|
+
event.preventDefault(); event.stopPropagation();
|
|
357
|
+
if (!event.repeat) onPickPrice!(active as TicketField);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
308
360
|
if (event.shift || event.targetEditable || textActive) return;
|
|
309
361
|
const shortcut = shortcuts.find((item) => item.key === event.name);
|
|
310
362
|
if (!shortcut) return;
|
|
@@ -348,8 +400,9 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
348
400
|
};
|
|
349
401
|
const quick = (key: TicketAction, label: string, disabled = false) => <Box ref={nodeRef(key)} key={key}>
|
|
350
402
|
<Button label={label} displayLabel={!native && marker(key) ? `> ${label}` : undefined} variant="quiet" compact active={active === key && focused}
|
|
351
|
-
disabled={disabled || busy} onPress={() => { setActive(key); onAction(key); }} />
|
|
403
|
+
disabled={disabled || busy} onPress={() => { setActive(key); if (key === "priceChart") onPickPrice?.(showLimit ? "limitPrice" : "stopPrice"); else onAction(key); }} />
|
|
352
404
|
</Box>;
|
|
405
|
+
const numericLabels: Partial<Record<TicketField, string>> = { limitPrice: "Limit price", stopPrice: "Stop price", takeProfitPrice: "Take profit price", stopLossPrice: oco ? "Stop price" : "Stop loss price", trailing: trailUnit === "percent" ? "Trailing percent" : "Trailing amount" };
|
|
353
406
|
const numeric = (key: TicketField, label: string, value: number | undefined, suffix: string, picks?: ReactNode) => {
|
|
354
407
|
const inlinePicks = !!picks && formWidth >= 60;
|
|
355
408
|
const quantity = key === "quantity";
|
|
@@ -357,12 +410,13 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
357
410
|
const quantityStep = m.capabilities?.fractionalQuantity ? reportedStep : wholeNumberStep(reportedStep) ?? NaN;
|
|
358
411
|
// Decimal precision is not a declared exchange tick. The fallback is an editing convenience only.
|
|
359
412
|
const priceStep = m.capabilities?.priceStep ?? ticketEditingPriceStep(value ?? m.quote?.price, m.capabilities?.priceDecimals);
|
|
360
|
-
|
|
413
|
+
// A trailing percent steps by a tenth of a point.
|
|
414
|
+
const step = quantity ? quantityStep : key === "trailing" && trailUnit === "percent" ? 0.1 : priceStep;
|
|
361
415
|
return <Box flexDirection="column" gap={0}>
|
|
362
416
|
<Box flexDirection="row" alignItems="center" gap={1}>
|
|
363
417
|
<Box ref={nodeRef(key)} onMouseDown={() => { if (!busy) setActive(key); }} flexDirection="row" alignItems="center" gap={1} flexGrow={1}>
|
|
364
418
|
<FieldLabel label={label} width={labelWidth} active={active === key} />
|
|
365
|
-
<Box flexGrow={1}><TicketNumberInput accessibleLabel={key
|
|
419
|
+
<Box flexGrow={1}><TicketNumberInput accessibleLabel={numericLabels[key] ?? label} value={value}
|
|
366
420
|
width={Math.max(14, formWidth - (docked ? 11 : native ? 21 : 24) - (inlinePicks ? 20 : 0))} focused={focused && active === key && !busy} active={active === key} disabled={busy}
|
|
367
421
|
step={step} min={quantity ? Math.max(step, m.capabilities?.minQuantity ?? step) : step} max={quantity && sell && !m.capabilities?.shortSelling ? Math.max(0, m.position ?? 0) : undefined}
|
|
368
422
|
onChange={(text) => { if (!busy) onEdit(key, text); }} onSubmit={() => setActive(m.tradingEnabled ? "review" : "enable")} /></Box>
|
|
@@ -452,7 +506,7 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
452
506
|
<TicketSection width={formWidth} title={m.modifying ? "Modify order" : docked ? undefined : "Order details"}>
|
|
453
507
|
<Box flexDirection="column" gap={rowGap}>
|
|
454
508
|
{!m.connected ? m.reconnecting ? <Notice tone="muted">{`Reconnecting to ${m.brokerName}...`}</Notice> : <Notice variant="callout">Broker disconnected. Connect in Brokers.</Notice>
|
|
455
|
-
: !m.tradingEnabled ? <Notice variant="callout">Trading is off for this profile
|
|
509
|
+
: !m.tradingEnabled ? <Notice variant="callout">{m.capabilities?.disabledReason ?? "Trading is off for this profile."}</Notice> : null}
|
|
456
510
|
<Box ref={nodeRef("action")} flexDirection="row" onMouseDown={() => setActive("action")}>
|
|
457
511
|
{!native ? <FieldLabel label="" width={2} active={focused && active === "action"} /> : null}
|
|
458
512
|
<Box flexGrow={1}><SegmentedControl variant="flat" accessibleLabel="Order side" value={draft.action} size="large" width="100%"
|
|
@@ -461,8 +515,13 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
461
515
|
</Box>
|
|
462
516
|
<Box ref={nodeRef("orderType")} flexDirection="row" gap={1} alignItems="center" onMouseDown={() => { if (!busy) setActive("orderType"); }}>
|
|
463
517
|
<FieldLabel label={docked ? "Type" : "Order type"} width={labelWidth} active={active === "orderType"} />
|
|
464
|
-
<SelectButton label="Order type" showLabel={false} variant="well" width={selectWidth} value={draft.orderType}
|
|
465
|
-
options={(m.capabilities?.orderTypes ?? ["LMT"]).map((t) => ({ value: t, label: typeName[t] ?? t }))
|
|
518
|
+
<SelectButton label="Order type" showLabel={false} variant="well" width={selectWidth} value={oco ? "OCO" : draft.orderType}
|
|
519
|
+
options={[...(m.capabilities?.orderTypes ?? ["LMT"]).filter((t) => t !== "TRAIL").map((t) => ({ value: t, label: typeName[t] ?? t })),
|
|
520
|
+
// A spread takes neither; elsewhere each is listed where the broker takes it.
|
|
521
|
+
...(strategy ? [] : [
|
|
522
|
+
...(offers("trailing", trailing) ? [{ value: "TRAIL", label: typeName.TRAIL! }] : []),
|
|
523
|
+
...(offers("oco", oco) ? [{ value: "OCO", label: "OCO", description: "A limit and a stop: one filling cancels the other" }] : []),
|
|
524
|
+
])]} disabled={busy || m.modifying}
|
|
466
525
|
emphasized={focused && active === "orderType"} controlRef={orderTypeControl} onFocus={() => setActive("orderType")} onChange={(v) => onEdit("orderType", v)} />
|
|
467
526
|
</Box>
|
|
468
527
|
{strategy ? <TicketLegs model={m} width={formWidth} inset /> : null}
|
|
@@ -476,8 +535,23 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
476
535
|
{quick("priceMid", "Mid", !(m.quote?.bid! > 0) || !(m.quote?.ask! > 0))}
|
|
477
536
|
{quick("priceAsk", "Ask", !(m.quote?.ask! > 0))}
|
|
478
537
|
{strategy ? null : quick("priceLast", "Last", !m.quote?.price)}
|
|
538
|
+
{chartPick ? quick("priceChart", "Chart") : null}
|
|
479
539
|
</>) : null}
|
|
480
|
-
{showStop ? numeric("stopPrice", docked ? "Stop" : "Stop price", draft.stopPrice, currency) : null}
|
|
540
|
+
{showStop ? numeric("stopPrice", docked ? "Stop" : "Stop price", draft.stopPrice, currency, chartPick && !showLimit ? quick("priceChart", "Chart") : undefined) : null}
|
|
541
|
+
{oco ? numeric("stopLossPrice", docked ? "Stop" : "Stop price", draft.stopLossPrice, currency) : null}
|
|
542
|
+
{trailing ? numeric("trailing", "Trail", trailValue, trailUnit === "percent" ? "%" : currency, showTrailUnit ? <Box ref={nodeRef("trailingUnit")} onMouseDown={() => { if (!busy) setActive("trailingUnit"); }}>
|
|
543
|
+
<SegmentedControl accessibleLabel="Trailing unit" value={trailUnit} focused={focused && active === "trailingUnit"} shortcutScope={scope}
|
|
544
|
+
options={[{ value: "amount", label: "Price", disabled: busy || !m.capabilities?.trailing?.includes("amount") },
|
|
545
|
+
{ value: "percent", label: "%", disabled: busy || !m.capabilities?.trailing?.includes("percent") }]}
|
|
546
|
+
onChange={(value) => { setActive("trailingUnit"); onEdit("trailingUnit", value); }} />
|
|
547
|
+
</Box> : undefined) : null}
|
|
548
|
+
{showBracket ? <Box ref={nodeRef("bracket")} flexDirection="column" onMouseDown={() => { if (!busy) setActive("bracket"); }}>
|
|
549
|
+
<Checkbox label="Take profit / stop loss" checked={bracket} disabled={busy} active={focused && active === "bracket"}
|
|
550
|
+
onChange={(value) => { setActive("bracket"); onEdit("bracket", value); }} />
|
|
551
|
+
</Box> : null}
|
|
552
|
+
{/* Beside the chart, under "Take profit / stop loss", as the order rows tag them. */}
|
|
553
|
+
{bracket ? numeric("takeProfitPrice", docked ? "TP" : "Take profit", draft.takeProfitPrice, currency) : null}
|
|
554
|
+
{bracket ? numeric("stopLossPrice", docked ? "SL" : "Stop loss", draft.stopLossPrice, currency) : null}
|
|
481
555
|
<Box flexDirection="row" flexWrap="wrap" alignItems="center" gap={docked ? rowGap : 1}>
|
|
482
556
|
<Box ref={nodeRef("tif")} flexDirection="row" alignItems="center" gap={1} onMouseDown={() => setActive("tif")}>
|
|
483
557
|
<FieldLabel label="TIF" width={labelWidth} active={active === "tif"} />
|
|
@@ -518,17 +592,22 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
518
592
|
<TicketOrderHeadline model={m} large />
|
|
519
593
|
{strategy ? <TicketLegs model={m} width={formWidth} /> : null}
|
|
520
594
|
<Text fg={c.textDim}>{orderTerms({ orderType: draft?.orderType ?? "LMT", limitPrice: showLimit ? draft?.limitPrice : undefined,
|
|
521
|
-
stopPrice: showStop ? draft?.stopPrice : undefined, tif: draft?.tif ?? "DAY", outsideRth: draft?.outsideRth
|
|
595
|
+
stopPrice: showStop ? draft?.stopPrice : undefined, tif: draft?.tif ?? "DAY", outsideRth: draft?.outsideRth, trailingAmount: draft?.trailingAmount, trailingPercent: draft?.trailingPercent,
|
|
596
|
+
orderClass: draft?.orderClass, stopLossPrice: draft?.stopLossPrice }, strategy ? sell ? "net credit" : "net debit" : "at", (value) => money(value, currency))}</Text>
|
|
522
597
|
{m.original && draft ? <Text fg={c.warning}>{replacementChanges(m.original, draft, (value) => money(value, currency))}</Text> : null}
|
|
598
|
+
{bracket ? <TicketExits model={m} width={formWidth} currency={currency} /> : null}
|
|
523
599
|
<Box marginTop={native && wide ? 1 : 0} flexDirection="column" gap={native && wide ? 0.4 : 0}>
|
|
524
|
-
<TicketReceiptRow label="
|
|
525
|
-
<TicketReceiptRow label="
|
|
600
|
+
{impactSource ? <TicketReceiptRow label="Impact source" value={impactSource} width={formWidth} /> : null}
|
|
601
|
+
<TicketReceiptRow label="Fees" value={ticketImpactMoney(m.preview, m.preview?.fees, currency)} width={formWidth} />
|
|
602
|
+
<TicketReceiptRow label="Commission" value={ticketImpactMoney(m.preview, m.preview?.commission, m.preview?.commissionCurrency ?? currency)} width={formWidth} />
|
|
526
603
|
{!wide ? <TicketOrderSummary model={m} width={formWidth} compact receipt /> : null}
|
|
527
604
|
</Box>
|
|
528
605
|
<Box flexDirection="row" justifyContent="space-between" alignItems={native ? "baseline" : "center"} paddingTop={native && wide ? 0.7 : 0}>
|
|
529
606
|
<Text fg={c.textDim}>{previewCredit ? "Estimated credit" : "Estimated cost"}</Text>
|
|
530
|
-
<FigureText>{
|
|
607
|
+
<FigureText>{ticketImpactMoney(m.preview, previewCost, currency)}</FigureText>
|
|
531
608
|
</Box>
|
|
609
|
+
{/* The broker's terms for its figures, before the order is confirmed. */}
|
|
610
|
+
{m.preview?.disclosure ? <Text fg={c.textDim} wrapText>{m.preview.disclosure}</Text> : null}
|
|
532
611
|
{/* Beside the chart, warnings are lines, so the place button fits without scrolling. */}
|
|
533
612
|
{warnings.map((warning, index) => <Notice key={index} variant={docked ? undefined : "callout"} tone="warning">{warning}</Notice>)}
|
|
534
613
|
{m.preview?.errors?.map((error, index) => <Notice key={index} variant={docked ? undefined : "callout"} tone="negative">{error}</Notice>)}
|
|
@@ -550,16 +629,18 @@ export function BrokerTicketView({ model: m, width, height, focused, onEdit, onA
|
|
|
550
629
|
</TicketSection> : null}
|
|
551
630
|
{m.phase === "result" ? <Box flexDirection={wide ? "row" : "column"} gap={3}><TicketSection width={formWidth} title={title} selectable>
|
|
552
631
|
<TicketOrderHeadline model={m} large />{strategy ? <TicketLegs model={m} width={formWidth} /> : null}
|
|
553
|
-
{m.result ? <Text fg={c.textDim}>{orderTerms(m.result, strategy ? "net" : "at", (value) => money(value, currency))}</Text> : null}
|
|
632
|
+
{m.result ? <Text fg={c.textDim}>{orderTerms({ ...m.result, orderClass: draft?.orderClass, stopLossPrice: draft?.stopLossPrice }, strategy ? "net" : "at", (value) => money(value, currency))}</Text> : null}
|
|
633
|
+
{bracket ? <TicketExits model={m} width={formWidth} currency={currency} /> : null}
|
|
554
634
|
<TicketStatus model={m} width={formWidth} />
|
|
555
635
|
{m.resultQuantities === "last-known" ? <Text fg={c.warning}>Last known quantities</Text> : null}
|
|
556
636
|
{!["PARTIALLY_FILLED", "FILLED"].includes(resultStatus) ? <TicketReceiptRow label="Filled" value={resultQuantity(m.result?.filled)} width={formWidth} /> : null}
|
|
557
637
|
<TicketReceiptRow label="Remaining" value={resultQuantity(m.result?.remaining)} width={formWidth} />
|
|
558
638
|
<Text fg={c.textDim}>Estimates from order preview</Text>
|
|
559
|
-
<TicketReceiptRow label={previewCredit ? "Preview credit" : "Preview cost"} value={
|
|
560
|
-
<TicketReceiptRow label="Fees" value={
|
|
561
|
-
<TicketReceiptRow label="Commission" value={
|
|
639
|
+
<TicketReceiptRow label={previewCredit ? "Preview credit" : "Preview cost"} value={ticketImpactMoney(m.preview, previewCost, currency)} width={formWidth} />
|
|
640
|
+
<TicketReceiptRow label="Fees" value={ticketImpactMoney(m.preview, m.preview?.fees, currency)} width={formWidth} />
|
|
641
|
+
<TicketReceiptRow label="Commission" value={ticketImpactMoney(m.preview, m.preview?.commission, m.preview?.commissionCurrency ?? currency)} width={formWidth} />
|
|
562
642
|
{m.preview?.buyingPowerAfter !== undefined ? <TicketReceiptRow label="Buying power after" value={money(m.preview.buyingPowerAfter, currency)} width={formWidth} /> : null}
|
|
643
|
+
{m.preview?.cashAfter !== undefined ? <TicketReceiptRow label="Cash after" value={money(m.preview.cashAfter, currency)} width={formWidth} /> : null}
|
|
563
644
|
{m.error && !["UNKNOWN", "REJECTED"].includes(resultStatus) ? <Notice variant="callout" tone="negative">{m.error}</Notice> : null}
|
|
564
645
|
{!finished && resultStatus !== "UNKNOWN" ? <Box flexDirection="row" alignItems="center" gap={1}>
|
|
565
646
|
{action("refresh", "Refresh status", false, false, "neutral", true)}<Text fg={c.textDim}>·</Text>
|
|
@@ -19,6 +19,8 @@ import { favoriteKey } from "./table-model";
|
|
|
19
19
|
|
|
20
20
|
interface BuildoutCellContext {
|
|
21
21
|
favoriteBusyKey: string | null;
|
|
22
|
+
/** The row's last star did not take. */
|
|
23
|
+
favoriteFailed?: boolean;
|
|
22
24
|
toggleFavorite: (row: BuildoutRow) => void | Promise<void>;
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -60,6 +62,7 @@ export function renderBuildoutCell(
|
|
|
60
62
|
<FavoriteCell
|
|
61
63
|
starred={company.starred === true}
|
|
62
64
|
busy={busy}
|
|
65
|
+
failed={context.favoriteFailed}
|
|
63
66
|
selected={rowState.selected}
|
|
64
67
|
onPress={() => { void context.toggleFavorite(row); }}
|
|
65
68
|
/>
|
|
@@ -120,6 +123,7 @@ export function renderBuildoutCell(
|
|
|
120
123
|
<FavoriteCell
|
|
121
124
|
starred={site.starred === true}
|
|
122
125
|
busy={busy}
|
|
126
|
+
failed={context.favoriteFailed}
|
|
123
127
|
selected={rowState.selected}
|
|
124
128
|
onPress={() => { void context.toggleFavorite(row); }}
|
|
125
129
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Box, ScrollBox } from "../../../../ui";
|
|
2
|
-
import { EmptyState } from "../../../../components";
|
|
2
|
+
import { EmptyState, Notice } from "../../../../components";
|
|
3
3
|
import type { BuildoutRow } from "../model/types";
|
|
4
4
|
import type { InlineTickerCatalog } from "./ui";
|
|
5
5
|
import { CompanyDetail } from "./company";
|
|
@@ -13,12 +13,15 @@ export {
|
|
|
13
13
|
|
|
14
14
|
export function BuildoutDetail({
|
|
15
15
|
row,
|
|
16
|
+
note = null,
|
|
16
17
|
width,
|
|
17
18
|
height,
|
|
18
19
|
catalog,
|
|
19
20
|
openTicker,
|
|
20
21
|
}: {
|
|
21
22
|
row: BuildoutRow | null;
|
|
23
|
+
/** What the row's last star ran into, in full. */
|
|
24
|
+
note?: string | null;
|
|
22
25
|
width: number;
|
|
23
26
|
height: number;
|
|
24
27
|
catalog: InlineTickerCatalog;
|
|
@@ -45,6 +48,7 @@ export function BuildoutDetail({
|
|
|
45
48
|
focusable={false}
|
|
46
49
|
>
|
|
47
50
|
<Box flexDirection="column" paddingX={1} width={bodyWidth}>
|
|
51
|
+
{note ? <Box paddingBottom={1}><Notice tone="negative">{note}</Notice></Box> : null}
|
|
48
52
|
{row.kind === "company" ? (
|
|
49
53
|
<CompanyDetail
|
|
50
54
|
company={row.item}
|
|
@@ -5,7 +5,7 @@ import { ExternalLinkText } from "../../../../components/ui/external-link";
|
|
|
5
5
|
import { ClippedText } from "../../../../components/ui/display";
|
|
6
6
|
import type { InlineTickerCatalogEntry } from "../../../../state/hooks/inline-tickers";
|
|
7
7
|
import { colors } from "../../../../theme/colors";
|
|
8
|
-
import { Box, Text } from "../../../../ui";
|
|
8
|
+
import { Box, Text, TextAttributes } from "../../../../ui";
|
|
9
9
|
import { truncateWithEllipsis } from "../../../../utils/text-wrap";
|
|
10
10
|
import { sourceDetailEntries, text, textOrNull, tickerSymbol } from "../format";
|
|
11
11
|
import type { BuildoutCompany, BuildoutRelatedCompany, BuildoutSource } from "../model/types";
|
|
@@ -182,18 +182,21 @@ export function MarkdownBlock({
|
|
|
182
182
|
export function FavoriteCell({
|
|
183
183
|
starred,
|
|
184
184
|
busy,
|
|
185
|
+
failed = false,
|
|
185
186
|
selected,
|
|
186
187
|
onPress,
|
|
187
188
|
}: {
|
|
188
189
|
starred: boolean;
|
|
189
190
|
busy: boolean;
|
|
191
|
+
/** The last star did not take: a `!` in the error tone, the reason in the row's detail. */
|
|
192
|
+
failed?: boolean;
|
|
190
193
|
selected: boolean;
|
|
191
194
|
onPress?: () => void;
|
|
192
195
|
}) {
|
|
193
196
|
return (
|
|
194
197
|
<Button
|
|
195
|
-
label={starred ? "Remove favorite" : "Add favorite"}
|
|
196
|
-
displayLabel={busy ? "*" : starred ? "★" : "☆"}
|
|
198
|
+
label={failed ? starred ? "Unstarring failed. Remove favorite" : "Starring failed. Add favorite" : starred ? "Remove favorite" : "Add favorite"}
|
|
199
|
+
displayLabel={busy ? "*" : failed ? "!" : starred ? "★" : "☆"}
|
|
197
200
|
width={2}
|
|
198
201
|
compact
|
|
199
202
|
variant="plain"
|
|
@@ -201,7 +204,7 @@ export function FavoriteCell({
|
|
|
201
204
|
disabled={busy || !onPress}
|
|
202
205
|
stopPropagation
|
|
203
206
|
onPress={onPress}
|
|
204
|
-
|
|
207
|
+
>{failed && !busy ? <Text fg={colors.negative} attributes={TextAttributes.BOLD}>!</Text> : undefined}</Button>
|
|
205
208
|
);
|
|
206
209
|
}
|
|
207
210
|
|
|
@@ -17,6 +17,7 @@ import type { PaneProps } from "../../../../types/plugin";
|
|
|
17
17
|
import { useOptionalDialog, type PromptContext } from "../../../../ui/dialog";
|
|
18
18
|
import { isPlainKey } from "../../../../utils/keyboard";
|
|
19
19
|
import { logFailure } from "../../../../utils/log-failure";
|
|
20
|
+
import { useRowNotes } from "../../../../components/ui/row-notes";
|
|
20
21
|
import { nextHeaderSort, type SortPreference } from "../../../../utils/sort-values";
|
|
21
22
|
import { usePaneStateValue } from "../../../../state/app/context";
|
|
22
23
|
import { useInlineTickerQuoteFact, useInlineTickers } from "../../../../state/hooks/inline-tickers";
|
|
@@ -63,6 +64,15 @@ import { useBuildoutDataRuntime } from "../data-runtime";
|
|
|
63
64
|
|
|
64
65
|
const BUILDOUT_UPGRADE_URL = "https://thebuildout.ai/pricing";
|
|
65
66
|
|
|
67
|
+
/** A star a row's company or site did not take: said by its star cell, in full at the top of its detail. */
|
|
68
|
+
const favoriteNoteKey = (row: BuildoutRow) => favoriteKey(row) ?? rowKey(row);
|
|
69
|
+
|
|
70
|
+
function favoriteFailureText(row: BuildoutRow, starring: boolean, error: unknown): string {
|
|
71
|
+
// The service may answer with a page of its own; its first line says enough.
|
|
72
|
+
const reason = error instanceof Error ? error.message.trim().split("\n")[0]!.slice(0, 240) : "";
|
|
73
|
+
return `Could not ${starring ? "star" : "unstar"} ${rowTitle(row)}${reason ? `: ${reason}` : "."}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
|
|
67
77
|
const NO_TICKER_TEXTS: string[] = [];
|
|
68
78
|
|
|
@@ -86,6 +96,7 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
86
96
|
const dialog = useOptionalDialog();
|
|
87
97
|
const tableScrollRef = useRef<ScrollBoxRenderable | null>(null);
|
|
88
98
|
const favoriteBusyKeysRef = useRef<Set<string>>(new Set());
|
|
99
|
+
const clearFavoriteNotesRef = useRef<() => void>(() => {});
|
|
89
100
|
const [activeTab, setActiveTab] = usePaneStateValue<BuildoutTabId>("activeTab", "companies");
|
|
90
101
|
const [selectedList, setSelectedList] = useState<BuildoutList | null>(null);
|
|
91
102
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
@@ -94,14 +105,13 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
94
105
|
const [upgradeBusy, setUpgradeBusy] = useState(false);
|
|
95
106
|
const [upgradeMessage, setUpgradeMessage] = useState<string | null>(null);
|
|
96
107
|
const [favoriteBusyKey, setFavoriteBusyKey] = useState<string | null>(null);
|
|
97
|
-
const [favoriteMessage, setFavoriteMessage] = useState<string | null>(null);
|
|
98
108
|
|
|
99
109
|
const handleBeforeLoad = useCallback(() => {
|
|
100
110
|
favoriteBusyKeysRef.current.clear();
|
|
101
111
|
setDetailRow(null);
|
|
102
112
|
setSelectedList(null);
|
|
103
113
|
setUpgradeMessage(null);
|
|
104
|
-
|
|
114
|
+
clearFavoriteNotesRef.current();
|
|
105
115
|
setFavoriteBusyKey(null);
|
|
106
116
|
}, []);
|
|
107
117
|
const {
|
|
@@ -136,7 +146,6 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
136
146
|
useEffect(() => {
|
|
137
147
|
setSelectedIndex(0);
|
|
138
148
|
setDetailRow(null);
|
|
139
|
-
setFavoriteMessage(null);
|
|
140
149
|
const nextColumn: BuildoutColumnId | null = activeTab === "companies"
|
|
141
150
|
? selectedList ? "marketCap" : null
|
|
142
151
|
: activeTab === "sites" ? "capture" : "time";
|
|
@@ -147,6 +156,10 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
147
156
|
() => sortRows(activeRows(state, activeTab, selectedList), sort.columnId, sort.direction),
|
|
148
157
|
[activeTab, selectedList, sort, state],
|
|
149
158
|
);
|
|
159
|
+
// Until the next star on that row, or a reload.
|
|
160
|
+
const favoriteNotes = useRowNotes<BuildoutRow, string>(rows, { key: favoriteNoteKey });
|
|
161
|
+
const { setNote: setFavoriteNote, noteFor: favoriteNoteFor } = favoriteNotes;
|
|
162
|
+
clearFavoriteNotesRef.current = favoriteNotes.clearNotes;
|
|
150
163
|
const columns = useMemo(() => columnsForTab(activeTab, selectedList, canFavorite), [activeTab, canFavorite, selectedList]);
|
|
151
164
|
const selectedRow = rows[selectedIndex] ?? rows[0] ?? null;
|
|
152
165
|
// The table's cells carry their own badges; this catalog only serves the open
|
|
@@ -226,7 +239,6 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
226
239
|
setSelectedIndex(0);
|
|
227
240
|
setDetailRow(null);
|
|
228
241
|
setUpgradeMessage(null);
|
|
229
|
-
setFavoriteMessage(null);
|
|
230
242
|
setSort({ columnId: "marketCap", direction: "desc" });
|
|
231
243
|
resetCompanies();
|
|
232
244
|
}, [resetCompanies]);
|
|
@@ -236,7 +248,6 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
236
248
|
setSelectedIndex(0);
|
|
237
249
|
setDetailRow(null);
|
|
238
250
|
setUpgradeMessage(null);
|
|
239
|
-
setFavoriteMessage(null);
|
|
240
251
|
setSort({ columnId: null, direction: "asc" });
|
|
241
252
|
}, []);
|
|
242
253
|
|
|
@@ -265,20 +276,21 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
265
276
|
const next = !previous;
|
|
266
277
|
favoriteBusyKeysRef.current.add(key);
|
|
267
278
|
setFavoriteBusyKey(key);
|
|
268
|
-
|
|
279
|
+
setFavoriteNote(key, null);
|
|
269
280
|
updateFavorite(key, next);
|
|
270
281
|
|
|
271
282
|
try {
|
|
272
283
|
const response = await buildoutApi<{ starred?: boolean }>(path, favoriteToken, { method: "POST" });
|
|
273
284
|
updateFavorite(key, typeof response.starred === "boolean" ? response.starred : next);
|
|
274
|
-
} catch {
|
|
285
|
+
} catch (error) {
|
|
286
|
+
// The star goes back, and the row says it did not take.
|
|
275
287
|
updateFavorite(key, previous);
|
|
276
|
-
|
|
288
|
+
setFavoriteNote(key, favoriteFailureText(row, next, error));
|
|
277
289
|
} finally {
|
|
278
290
|
favoriteBusyKeysRef.current.delete(key);
|
|
279
291
|
setFavoriteBusyKey((current) => current === key ? null : current);
|
|
280
292
|
}
|
|
281
|
-
}, [favoriteToken, updateFavorite]);
|
|
293
|
+
}, [favoriteToken, setFavoriteNote, updateFavorite]);
|
|
282
294
|
|
|
283
295
|
const toggleFavoriteRow = useCallback((row: BuildoutRow | null) => {
|
|
284
296
|
if (!canFavorite || !row || !favoriteKey(row)) return false;
|
|
@@ -314,14 +326,13 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
314
326
|
|
|
315
327
|
usePaneFooter("buildout", () => ({
|
|
316
328
|
info: updateBuildoutFooterInfo(state, activeTab, selectedList, {
|
|
317
|
-
favoriteMessage,
|
|
318
329
|
upgradeMessage,
|
|
319
330
|
partialList,
|
|
320
331
|
onUpgrade: startUpgrade,
|
|
321
332
|
quoteFreshness: detailQuoteFreshness,
|
|
322
333
|
}),
|
|
323
334
|
hints: footerHints,
|
|
324
|
-
}), [activeTab, detailQuoteFreshness,
|
|
335
|
+
}), [activeTab, detailQuoteFreshness, footerHints, partialList, selectedList, startUpgrade, state, upgradeMessage]);
|
|
325
336
|
|
|
326
337
|
const activePage = state.status === "ready" ? activeBuildoutPage(state, activeTab, selectedList) : null;
|
|
327
338
|
const loadMoreActiveRows = useTableLoadMore(
|
|
@@ -367,8 +378,9 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
367
378
|
rowState: { selected: boolean },
|
|
368
379
|
) => renderBuildoutCell(row, column, rowState, {
|
|
369
380
|
favoriteBusyKey,
|
|
381
|
+
favoriteFailed: favoriteNoteFor(row) !== null,
|
|
370
382
|
toggleFavorite,
|
|
371
|
-
}), [favoriteBusyKey, toggleFavorite]);
|
|
383
|
+
}), [favoriteBusyKey, favoriteNoteFor, toggleFavorite]);
|
|
372
384
|
|
|
373
385
|
const { strip: tabStrip, rows: tabRows } = usePaneTabs({
|
|
374
386
|
tabs,
|
|
@@ -401,6 +413,7 @@ export function BuildoutPane({ focused, width, height }: PaneProps) {
|
|
|
401
413
|
detailContent={(
|
|
402
414
|
<BuildoutDetail
|
|
403
415
|
row={detailRow}
|
|
416
|
+
note={detailRow ? favoriteNoteFor(detailRow) : null}
|
|
404
417
|
width={width}
|
|
405
418
|
height={height}
|
|
406
419
|
catalog={tickerCatalog}
|
|
@@ -26,7 +26,6 @@ export function updateBuildoutFooterInfo(
|
|
|
26
26
|
activeTab: BuildoutTabId,
|
|
27
27
|
selectedList: BuildoutList | null,
|
|
28
28
|
messages: {
|
|
29
|
-
favoriteMessage: string | null;
|
|
30
29
|
upgradeMessage: string | null;
|
|
31
30
|
partialList: boolean;
|
|
32
31
|
onUpgrade: () => void;
|
|
@@ -66,9 +65,6 @@ export function updateBuildoutFooterInfo(
|
|
|
66
65
|
if (page?.error) {
|
|
67
66
|
info.push({ id: "page-error", parts: [{ text: page.error, tone: "negative" }] });
|
|
68
67
|
}
|
|
69
|
-
if (messages.favoriteMessage) {
|
|
70
|
-
info.push({ id: "favorite-error", parts: [{ text: messages.favoriteMessage, tone: "negative" }] });
|
|
71
|
-
}
|
|
72
68
|
if (messages.upgradeMessage) {
|
|
73
69
|
info.push({ id: "upgrade-error", parts: [{ text: messages.upgradeMessage, tone: "negative" }] });
|
|
74
70
|
}
|
|
@@ -107,7 +107,7 @@ export const cryptoPluginMeta = {
|
|
|
107
107
|
stateId: "market-overview",
|
|
108
108
|
name: "Crypto & Perps",
|
|
109
109
|
version: "1.0.0",
|
|
110
|
-
description: "Top crypto assets by market cap, and perpetual funding, open interest and premiums.",
|
|
110
|
+
description: "Top crypto assets by market cap, daily spot bitcoin and ether ETF flows, and perpetual funding, open interest and premiums.",
|
|
111
111
|
toggleable: true,
|
|
112
112
|
};
|
|
113
113
|
|
|
@@ -6,7 +6,7 @@ import { usePluginPaneState } from "../../../public/react";
|
|
|
6
6
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
7
7
|
import { Box, ScrollBox, Text, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
|
|
8
8
|
import { UpgradeLabel } from "../shared/locked-rows";
|
|
9
|
-
import { catalystAgency, catalystChangeText, catalystDate, catalystDateBasis, catalystFacts, catalystLabel } from "./model";
|
|
9
|
+
import { CATALYST_DATE_WITHHELD, catalystAgency, catalystChangeText, catalystDate, catalystDateBasis, catalystDateWithheld, catalystFacts, catalystLabel } from "./model";
|
|
10
10
|
import { humanLabel } from "../shared/research-cells";
|
|
11
11
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
12
12
|
import { loadCatalystDetail } from "./client";
|
|
@@ -23,7 +23,8 @@ function Evidence({ event, width, height }: { event: CatalystEvent; width: numbe
|
|
|
23
23
|
<KeyValueRow label="Status" value={humanLabel(event.status)} detail={`Revision ${event.revision}`} labelWidth={18} />
|
|
24
24
|
<KeyValueRow label="Announced" value={catalystDate(event, "announced")} labelWidth={18} />
|
|
25
25
|
{event.effectiveDate ? <KeyValueRow label={catalystDateBasis(event, "effective")} value={catalystDate(event, "effective")} labelWidth={18} /> : null}
|
|
26
|
-
{event.deadlineDate ? <KeyValueRow label={catalystDateBasis(event, "deadline")} value={catalystDate(event, "deadline")} labelWidth={18} />
|
|
26
|
+
{event.deadlineDate ? <KeyValueRow label={catalystDateBasis(event, "deadline")} value={catalystDate(event, "deadline")} labelWidth={18} />
|
|
27
|
+
: catalystDateWithheld(event) ? <KeyValueRow label={catalystLabel("deadline")} value={CATALYST_DATE_WITHHELD} labelWidth={18} /> : null}
|
|
27
28
|
<KeyValueRow label="Observed (UTC)" value={catalystDate(event, "observed")} labelWidth={18} />
|
|
28
29
|
<KeyValueRow label="Confidence" value={`${Math.round(event.confidence * 100)}%`} labelWidth={18} />
|
|
29
30
|
{facts.map((fact) => <KeyValueRow key={fact.label} label={fact.label} value={fact.value} labelWidth={18} />)}
|