fix: CCXT contract resolution + provider resilience#40
Merged
luokerenx4 merged 34 commits intomasterfrom Mar 5, 2026
Merged
Conversation
…anager, TradingGit
Introduces the IBKR-style unified trading architecture (new files only, zero changes to existing code):
- Contract: 1:1 IBKR replica with conId→aliceId ("{provider}-{nativeId}")
- ITradingAccount: unified account interface replacing ICryptoTradingEngine/ISecuritiesTradingEngine
- AccountManager: multi-account registry with cross-account equity aggregation and contract search
- TradingGit: merged Wallet+SecWallet into a single Trading-as-Git implementation (~330 lines vs ~1230 combined)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Unified GuardContext uses Position[] + AccountInfo from the new trading interfaces. MaxPositionSizeGuard handles both crypto (usd_size/size) and securities (notional/qty) params. Guard pipeline takes ITradingAccount instead of engine-specific types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… main.ts rewrite PR4+PR5 combined: replace separate crypto-trading and securities-trading extensions with the unified IBKR-style account model. - Add AlpacaAccount and CcxtAccount (direct ITradingAccount implementations) - Add unified operation-dispatcher (Operation → ITradingAccount bridge) - Add unified tool factory (createTradingTools) with capability-gated tools - Add TradingGit adapter (git-style commit/push/log tools) - Add wallet-state-bridge (ITradingAccount → GitState) - Add factory.ts (wireAccountTrading + config-to-account helpers) - Rewrite main.ts to use AccountManager with per-account TradingGit - Replace EngineContext engine-specific getters with accountManager - Add unified /api/trading/ web routes, remove old /api/crypto + /api/securities - Update UI API client with backward-compat wrappers - Archive old extensions to trading-archived/ (not yet deleted) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 99 tests across 7 files for unified trading architecture (TradingGit, AccountManager, OperationDispatcher, WalletStateBridge, Guards, Factory) with shared MockTradingAccount test helper - Fix CCXT constructor crash: options:undefined overriding internal defaults — use conditional spread instead - Merge Crypto and Securities frontend into unified Trading view: sidebar 2 NavGroups → 1, TradingPage absorbs SecuritiesPage, PortfolioPage uses dynamic per-account API, remove all legacy API wrappers, unify types (AccountInfo/Position/TradingAccount) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace per-account tool registration (which caused ToolCenter overwrites) with a single set of tools that route dynamically via `source` parameter. Drop the legacy `sec` prefix from all tool names. - Query tools (getAccount, getPortfolio, etc.) default to all accounts - Mutation tools (placeOrder, walletCommit, etc.) require explicit source - New listAccounts tool for AI to discover available accounts - Merge git/adapter.ts into adapter.ts (both need source routing) - Simplify main.ts: one toolCenter.register() call for trading Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tional - walletLog/Show/Status/Commit/Push/Sync → tradingLog/Show/Status/Commit/Push/Sync - tradingCommit/Push/Sync source now optional — omit to operate on all accounts (like git push without specifying a remote) - Clean up remaining "wallet" references in tool descriptions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of routing to first available account, try all accounts and return quotes from every account that supports the symbol. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detect empty API keys at construction time and short-circuit auth-required methods with a clear error instead of making doomed network calls. Public endpoints (getQuote, getFundingRate, getOrderBook) still work. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move provider-specific tools (getFundingRate, getOrderBook, adjustLeverage) from adapter.ts into CcxtAccount.createProviderTools(), registered dynamically when CCXT comes online. Slim AccountCapabilities to just supportedSecTypes + supportedOrderTypes, removing all boolean flags. Make getMarketClock required on ITradingAccount (every broker implements it). Operation dispatcher uses duck-typing for provider-specific actions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
adjustLeverage is not a meaningful standalone operation — leverage is a margin setting, not a trade. placeOrder already handles leverage at order time. Remove adjustLeverage tool, instance method, operation dispatcher case, and leverage field from OrderRequest/Order interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract OrderType (7 types: +trailing_stop, trailing_stop_limit, moc) and TimeInForce (6 values: +opg, gtd) as standalone type aliases - Add IBKR fields to OrderRequest/Order: trailingAmount, trailingPercent, goodTillDate, parentId, ocaGroup - Add modifyOrder to ITradingAccount core interface (IBKR replace semantics) - Implement modifyOrder in AlpacaAccount (replaceOrder), CcxtAccount (editOrder) - Add trailing_stop support to AlpacaAccount (trail_price/trail_percent) - Expand placeOrder/modifyOrder tool schemas in adapter with all new fields - Add modifyOrder to OperationAction, dispatcher, and TradingGit formatting - Delete MaxLeverageGuard (dead after adjustLeverage removal) - Clean up all adjustLeverage references from git types, TradingGit, comments Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ails Align contract search with IBKR's dual interface pattern: - searchContracts(pattern) for fuzzy discovery (reqMatchingSymbols) - getContractDetails(query) for exact specification lookup (reqContractDetails) Both exposed as AI tools with source filtering for multi-account attribution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…license to AGPL-3.0 - Delete trading-archived/ (superseded by unified trading/) - Remove MaxLeverageGuard from barrel export (guard was deleted previously) - Switch license from MIT to AGPL-3.0-only to prevent closed-source forks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent agent from redundantly calling searchContracts after equitySearch by clearly distinguishing broker-level contract search from market data research tools. Add when-to-use / when-not-to-use guidance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ketSearchForResearch Single entry point for market data symbol discovery across all asset classes. Results tagged with assetClass attribution. Equity sub-tool descriptions updated to reference the new tool name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ptions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e-search Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Includes: - IBKR-aligned unified trading (multi-account, Contract model, searchContracts/getContractDetails) - Unified marketSearchForResearch (merged equitySearch + cryptoSearch + currencySearch) - Relicense MIT → AGPL-3.0-only - Remove trading-archived/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Platform defines the compatibility structure (exchange type, market mode,
sandbox) that can be shared by multiple accounts. Config splits into
platforms.json + accounts.json with auto-migration from legacy
crypto.json + securities.json.
- IPlatform interface + CcxtPlatform/AlpacaPlatform implementations
- platform-factory: createPlatformFromConfig, createAccountFromConfig
- loadTradingConfig() with legacy config migration (read-only)
- AccountManager: platformId field on entries and summaries
- main.ts: platform-driven N-account init loop, per-account git state
paths (data/trading/{accountId}/commit.json) with legacy fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: add /api/trading/config endpoints for platform and account CRUD with credential masking. Frontend: rewrite TradingPage from nested cards to compact table + right-sliding panel layout for better overview and reduced scrolling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove standalone platform management (PlatformsBar, Add Platform, Platform tab). Platform is now an internal detail auto-created/updated when saving accounts and cleaned up on account deletion. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Creation flow now uses a 3-step wizard dialog (platform type → connection config → credentials). Editing uses a single-page centered modal with all sections inline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AlpacaAccount: compute realized PnL from FILL activities using FIFO lot matching with 60s TTL cache (replaces hardcoded 0) - AccountManager: use Promise.allSettled in getAggregatedEquity so one failing account doesn't take down the entire endpoint - PortfolioPage: unified layout with hero metrics from /equity endpoint, compact account strip, cost-basis column, resilient data fetching Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CCXT's fetchMarkets uses Promise.all to fire all market-type requests concurrently (6 for bybit: spot, linear, inverse, option×3). A single failure kills the entire batch. This is unreliable on unstable networks. Changes: - Monkey-patch fetchMarkets to load each type sequentially with independent retries (8 attempts, 500ms backoff) - Skip option markets by default (reduces requests from 6 to 3) - Failed types are skipped instead of blocking the entire init Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace state-based page switching with react-router-dom Routes - Sidebar nav items now use Link + useLocation instead of button + onClick - Each page has its own URL path (/portfolio, /trading, /settings, etc.) - Browser refresh preserves current page, back/forward navigation works - Unknown routes redirect to / (Chat) - Also: throttle getAggregatedEquity warnings to once per 5 min per account Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract from the 761-line monolith: - ccxt-types.ts: CcxtAccountConfig, CcxtMarket, retry constants - ccxt-contracts.ts: contract resolution as pure functions - ccxt-tools.ts: createCcxtProviderTools (was static method) CcxtAccount.ts shrinks from 761 to 558 lines. All contract helpers are now standalone functions parameterized by (markets, exchangeName), making them independently testable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract types, contract helpers, and PnL computation into separate files following the same pattern used for CcxtAccount. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getQuote, getFundingRate, getOrderBook, placeOrder, closePosition now require aliceId instead of bare symbol. Fixes CCXT tools failing when symbol matches multiple markets (e.g. BTC → spot + swap). Also adds CCXT unified symbol lookup in contractToCcxt so "BTC/USDT:USDT" resolves directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fetchMarketsfires 6 concurrent requests viaPromise.all; one failure kills the batch. Monkey-patched to load each market type sequentially with independent retries (8 attempts, exponential backoff). Skips option markets by default.getAccount()during init now retries 5 times with exponential backoff instead of failing immediately.getQuote,getFundingRate,getOrderBook,placeOrder,closePositionnow requirealiceIdinstead of bare symbol. Fixes CCXT tools failing when symbol matches multiple markets (e.g. "BTC" → spot + swap). Also adds CCXT unified symbol lookup incontractToCcxt.Test plan
npx tsc --noEmit— no type errorsnpx vitest run src/extension/trading/— 109 tests passsearchContracts("BTC")returns aliceId, thengetQuote({ aliceId })works🤖 Generated with Claude Code