diff --git a/.gitignore b/.gitignore index 1680a852..fdf8b5e9 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ packages/ibkr/ref/source/cppclient/ packages/ibkr/ref/samples/Java/ packages/ibkr/ref/samples/Cpp/ packages/ibkr/ref/CMakeLists.txt + +# Turborepo +.turbo/ diff --git a/CLAUDE.md b/CLAUDE.md index a8ef21cf..27ee8ed2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,6 +9,7 @@ pnpm install pnpm dev # Dev mode (tsx watch, port 3002) pnpm build # Production build (backend + UI) pnpm test # Vitest +pnpm test:e2e # e2e test ``` ## Project Structure @@ -138,3 +139,4 @@ Cron jobs persist in `data/cron/jobs.json`. If config and persisted state diverg - When merging PRs, **prefer `--merge` over `--squash`** — squash destroys individual commit history. If the PR has clean, meaningful commits, merge them as-is - If squash is needed (messy history), do it — but never combine with `--delete-branch` - `archive/dev-pre-beta6` is a historical snapshot — do not modify or delete +- **After merging a PR**, always `git pull origin master` to sync local master. Stale local master causes confusion about what's merged and what's not. diff --git a/package.json b/package.json index 20973548..5b24a59a 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,17 @@ { "name": "open-alice", - "version": "0.9.0-beta.8", + "version": "0.9.0-beta.9", "description": "File-based trading agent engine", "type": "module", "scripts": { "dev": "tsx src/main.ts", "dev:ui": "pnpm --filter open-alice-ui dev", - "predev": "pnpm --filter opentypebb build && pnpm --filter @traderalice/ibkr build", - "build": "pnpm --filter opentypebb build && pnpm --filter @traderalice/ibkr build && pnpm build:ui && pnpm build:backend", - "build:ui": "pnpm --filter open-alice-ui build", - "build:backend": "tsup src/main.ts --format esm --dts", + "predev": "turbo run build --filter=@traderalice/opentypebb --filter=@traderalice/ibkr", + "build": "turbo run build && tsup src/main.ts --format esm --dts", "start": "node dist/main.js", "test": "vitest run", "test:e2e": "vitest run --config vitest.e2e.config.ts", + "test:bbProvider": "vitest run --config vitest.bbProvider.config.ts", "test:watch": "vitest" }, "keywords": [ @@ -79,6 +78,7 @@ "jsdom": "^29.0.0", "tsup": "^8.5.1", "tsx": "^4.21.0", + "turbo": "^2.9.3", "typescript": "^5.9.3", "vitest": "^4.0.18" } diff --git a/packages/ibkr/generate-proto.sh b/packages/ibkr/generate-proto.sh index 50b05549..469fe649 100755 --- a/packages/ibkr/generate-proto.sh +++ b/packages/ibkr/generate-proto.sh @@ -16,6 +16,7 @@ protoc \ --ts_proto_opt=esModuleInterop=true \ --ts_proto_opt=outputTypeRegistry=false \ --ts_proto_opt=useExactTypes=false \ + --ts_proto_opt=importSuffix=.js \ --proto_path="$PROTO_DIR" \ "$PROTO_DIR"/*.proto diff --git a/packages/ibkr/src/client/base.ts b/packages/ibkr/src/client/base.ts index 1ba88475..39b8c620 100644 --- a/packages/ibkr/src/client/base.ts +++ b/packages/ibkr/src/client/base.ts @@ -8,7 +8,7 @@ import { makeMsg, makeMsgProto, makeField, makeInitialMsg, readMsg, readFields } from '../comm.js' import { Connection } from '../connection.js' import { EReader } from '../reader.js' -import { Decoder, applyAllHandlers } from '../decoder' +import { Decoder, applyAllHandlers } from '../decoder/index.js' import type { EWrapper } from '../wrapper.js' import { OUT } from '../message.js' import { diff --git a/packages/ibkr/src/decoder/index.ts b/packages/ibkr/src/decoder/index.ts index 4af8bfd0..e56172f0 100644 --- a/packages/ibkr/src/decoder/index.ts +++ b/packages/ibkr/src/decoder/index.ts @@ -7,14 +7,14 @@ * applyAllHandlers(decoder) */ -import { Decoder } from './base' -import { applyMarketDataHandlers } from './market-data' -import { applyOrderHandlers } from './orders' -import { applyAccountHandlers } from './account' -import { applyContractHandlers } from './contract' -import { applyExecutionHandlers } from './execution' -import { applyHistoricalHandlers } from './historical' -import { applyMiscHandlers } from './misc' +import { Decoder } from './base.js' +import { applyMarketDataHandlers } from './market-data.js' +import { applyOrderHandlers } from './orders.js' +import { applyAccountHandlers } from './account.js' +import { applyContractHandlers } from './contract.js' +import { applyExecutionHandlers } from './execution.js' +import { applyHistoricalHandlers } from './historical.js' +import { applyMiscHandlers } from './misc.js' export function applyAllHandlers(decoder: Decoder): void { applyMarketDataHandlers(decoder) diff --git a/packages/ibkr/src/index.ts b/packages/ibkr/src/index.ts index f095099f..07d3a47e 100644 --- a/packages/ibkr/src/index.ts +++ b/packages/ibkr/src/index.ts @@ -30,7 +30,7 @@ export * from './common.js' export { makeField, makeFieldHandleEmpty, makeMsg, readMsg, readFields } from './comm.js' export { Connection } from './connection.js' export { EReader } from './reader.js' -export { Decoder } from './decoder' +export { Decoder } from './decoder/index.js' // Client & Wrapper export { type EWrapper, DefaultEWrapper } from './wrapper.js' diff --git a/packages/ibkr/src/protobuf/AccountDataEnd.ts b/packages/ibkr/src/protobuf/AccountDataEnd.ts index b2246df6..73f01bab 100644 --- a/packages/ibkr/src/protobuf/AccountDataEnd.ts +++ b/packages/ibkr/src/protobuf/AccountDataEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountDataEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountDataRequest.ts b/packages/ibkr/src/protobuf/AccountDataRequest.ts index b5f30b13..6e2de4d4 100644 --- a/packages/ibkr/src/protobuf/AccountDataRequest.ts +++ b/packages/ibkr/src/protobuf/AccountDataRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountDataRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountSummary.ts b/packages/ibkr/src/protobuf/AccountSummary.ts index d6938037..2267c248 100644 --- a/packages/ibkr/src/protobuf/AccountSummary.ts +++ b/packages/ibkr/src/protobuf/AccountSummary.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountSummary.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountSummaryEnd.ts b/packages/ibkr/src/protobuf/AccountSummaryEnd.ts index 71be69d1..cd253466 100644 --- a/packages/ibkr/src/protobuf/AccountSummaryEnd.ts +++ b/packages/ibkr/src/protobuf/AccountSummaryEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountSummaryEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountSummaryRequest.ts b/packages/ibkr/src/protobuf/AccountSummaryRequest.ts index 21669fda..17178918 100644 --- a/packages/ibkr/src/protobuf/AccountSummaryRequest.ts +++ b/packages/ibkr/src/protobuf/AccountSummaryRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountSummaryRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountUpdateMulti.ts b/packages/ibkr/src/protobuf/AccountUpdateMulti.ts index 99c418e8..f298f276 100644 --- a/packages/ibkr/src/protobuf/AccountUpdateMulti.ts +++ b/packages/ibkr/src/protobuf/AccountUpdateMulti.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountUpdateMulti.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountUpdateMultiEnd.ts b/packages/ibkr/src/protobuf/AccountUpdateMultiEnd.ts index 13b388e7..19f2827a 100644 --- a/packages/ibkr/src/protobuf/AccountUpdateMultiEnd.ts +++ b/packages/ibkr/src/protobuf/AccountUpdateMultiEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountUpdateMultiEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountUpdateTime.ts b/packages/ibkr/src/protobuf/AccountUpdateTime.ts index 309b7f07..b883ea79 100644 --- a/packages/ibkr/src/protobuf/AccountUpdateTime.ts +++ b/packages/ibkr/src/protobuf/AccountUpdateTime.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountUpdateTime.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountUpdatesMultiRequest.ts b/packages/ibkr/src/protobuf/AccountUpdatesMultiRequest.ts index ef6f3c88..ac2682f0 100644 --- a/packages/ibkr/src/protobuf/AccountUpdatesMultiRequest.ts +++ b/packages/ibkr/src/protobuf/AccountUpdatesMultiRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountUpdatesMultiRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AccountValue.ts b/packages/ibkr/src/protobuf/AccountValue.ts index c5e65abb..252073ff 100644 --- a/packages/ibkr/src/protobuf/AccountValue.ts +++ b/packages/ibkr/src/protobuf/AccountValue.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AccountValue.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AllOpenOrdersRequest.ts b/packages/ibkr/src/protobuf/AllOpenOrdersRequest.ts index abf7833b..4c3aacad 100644 --- a/packages/ibkr/src/protobuf/AllOpenOrdersRequest.ts +++ b/packages/ibkr/src/protobuf/AllOpenOrdersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AllOpenOrdersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ApiConfig.ts b/packages/ibkr/src/protobuf/ApiConfig.ts index b4b28262..9aa7d1c0 100644 --- a/packages/ibkr/src/protobuf/ApiConfig.ts +++ b/packages/ibkr/src/protobuf/ApiConfig.ts @@ -1,13 +1,13 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ApiConfig.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ApiPrecautionsConfig } from "./ApiPrecautionsConfig"; -import { ApiSettingsConfig } from "./ApiSettingsConfig"; +import { ApiPrecautionsConfig } from "./ApiPrecautionsConfig.js"; +import { ApiSettingsConfig } from "./ApiSettingsConfig.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ApiPrecautionsConfig.ts b/packages/ibkr/src/protobuf/ApiPrecautionsConfig.ts index 84bf96be..97d2a2b0 100644 --- a/packages/ibkr/src/protobuf/ApiPrecautionsConfig.ts +++ b/packages/ibkr/src/protobuf/ApiPrecautionsConfig.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ApiPrecautionsConfig.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ApiSettingsConfig.ts b/packages/ibkr/src/protobuf/ApiSettingsConfig.ts index 530c9de0..5c6eb4e5 100644 --- a/packages/ibkr/src/protobuf/ApiSettingsConfig.ts +++ b/packages/ibkr/src/protobuf/ApiSettingsConfig.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ApiSettingsConfig.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AttachedOrders.ts b/packages/ibkr/src/protobuf/AttachedOrders.ts index 4353a381..b980dc07 100644 --- a/packages/ibkr/src/protobuf/AttachedOrders.ts +++ b/packages/ibkr/src/protobuf/AttachedOrders.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AttachedOrders.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/AutoOpenOrdersRequest.ts b/packages/ibkr/src/protobuf/AutoOpenOrdersRequest.ts index af8edb57..23a8416d 100644 --- a/packages/ibkr/src/protobuf/AutoOpenOrdersRequest.ts +++ b/packages/ibkr/src/protobuf/AutoOpenOrdersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: AutoOpenOrdersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CalculateImpliedVolatilityRequest.ts b/packages/ibkr/src/protobuf/CalculateImpliedVolatilityRequest.ts index 9553a09d..92ad2b98 100644 --- a/packages/ibkr/src/protobuf/CalculateImpliedVolatilityRequest.ts +++ b/packages/ibkr/src/protobuf/CalculateImpliedVolatilityRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CalculateImpliedVolatilityRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/CalculateOptionPriceRequest.ts b/packages/ibkr/src/protobuf/CalculateOptionPriceRequest.ts index c4b76465..ba492afc 100644 --- a/packages/ibkr/src/protobuf/CalculateOptionPriceRequest.ts +++ b/packages/ibkr/src/protobuf/CalculateOptionPriceRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CalculateOptionPriceRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/CancelAccountSummary.ts b/packages/ibkr/src/protobuf/CancelAccountSummary.ts index 74fc640a..3cba5916 100644 --- a/packages/ibkr/src/protobuf/CancelAccountSummary.ts +++ b/packages/ibkr/src/protobuf/CancelAccountSummary.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelAccountSummary.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelAccountUpdatesMulti.ts b/packages/ibkr/src/protobuf/CancelAccountUpdatesMulti.ts index 589a77e4..a87d323c 100644 --- a/packages/ibkr/src/protobuf/CancelAccountUpdatesMulti.ts +++ b/packages/ibkr/src/protobuf/CancelAccountUpdatesMulti.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelAccountUpdatesMulti.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelCalculateImpliedVolatility.ts b/packages/ibkr/src/protobuf/CancelCalculateImpliedVolatility.ts index b391010e..6ce65ff6 100644 --- a/packages/ibkr/src/protobuf/CancelCalculateImpliedVolatility.ts +++ b/packages/ibkr/src/protobuf/CancelCalculateImpliedVolatility.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelCalculateImpliedVolatility.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelCalculateOptionPrice.ts b/packages/ibkr/src/protobuf/CancelCalculateOptionPrice.ts index ccde8f0a..27b21276 100644 --- a/packages/ibkr/src/protobuf/CancelCalculateOptionPrice.ts +++ b/packages/ibkr/src/protobuf/CancelCalculateOptionPrice.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelCalculateOptionPrice.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelContractData.ts b/packages/ibkr/src/protobuf/CancelContractData.ts index 95e70f9d..8113e028 100644 --- a/packages/ibkr/src/protobuf/CancelContractData.ts +++ b/packages/ibkr/src/protobuf/CancelContractData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelContractData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelFundamentalsData.ts b/packages/ibkr/src/protobuf/CancelFundamentalsData.ts index 3737528e..78383e6e 100644 --- a/packages/ibkr/src/protobuf/CancelFundamentalsData.ts +++ b/packages/ibkr/src/protobuf/CancelFundamentalsData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelFundamentalsData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelHeadTimestamp.ts b/packages/ibkr/src/protobuf/CancelHeadTimestamp.ts index abc2d3df..7da0a66a 100644 --- a/packages/ibkr/src/protobuf/CancelHeadTimestamp.ts +++ b/packages/ibkr/src/protobuf/CancelHeadTimestamp.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelHeadTimestamp.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelHistogramData.ts b/packages/ibkr/src/protobuf/CancelHistogramData.ts index 4759f862..1e4e7bc3 100644 --- a/packages/ibkr/src/protobuf/CancelHistogramData.ts +++ b/packages/ibkr/src/protobuf/CancelHistogramData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelHistogramData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelHistoricalData.ts b/packages/ibkr/src/protobuf/CancelHistoricalData.ts index ef645e3f..39f9b2d1 100644 --- a/packages/ibkr/src/protobuf/CancelHistoricalData.ts +++ b/packages/ibkr/src/protobuf/CancelHistoricalData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelHistoricalData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelHistoricalTicks.ts b/packages/ibkr/src/protobuf/CancelHistoricalTicks.ts index 2d7dac1f..2e2ab6ad 100644 --- a/packages/ibkr/src/protobuf/CancelHistoricalTicks.ts +++ b/packages/ibkr/src/protobuf/CancelHistoricalTicks.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelHistoricalTicks.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelMarketData.ts b/packages/ibkr/src/protobuf/CancelMarketData.ts index 1cb1de23..0c855919 100644 --- a/packages/ibkr/src/protobuf/CancelMarketData.ts +++ b/packages/ibkr/src/protobuf/CancelMarketData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelMarketData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelMarketDepth.ts b/packages/ibkr/src/protobuf/CancelMarketDepth.ts index 5ebc1b4d..92623d9b 100644 --- a/packages/ibkr/src/protobuf/CancelMarketDepth.ts +++ b/packages/ibkr/src/protobuf/CancelMarketDepth.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelMarketDepth.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelNewsBulletins.ts b/packages/ibkr/src/protobuf/CancelNewsBulletins.ts index e5f2af9c..48693e08 100644 --- a/packages/ibkr/src/protobuf/CancelNewsBulletins.ts +++ b/packages/ibkr/src/protobuf/CancelNewsBulletins.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelNewsBulletins.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelOrderRequest.ts b/packages/ibkr/src/protobuf/CancelOrderRequest.ts index 7faa7b6c..bdbcb068 100644 --- a/packages/ibkr/src/protobuf/CancelOrderRequest.ts +++ b/packages/ibkr/src/protobuf/CancelOrderRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelOrderRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { OrderCancel } from "./OrderCancel"; +import { OrderCancel } from "./OrderCancel.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/CancelPnL.ts b/packages/ibkr/src/protobuf/CancelPnL.ts index 7a82b358..fb69d69f 100644 --- a/packages/ibkr/src/protobuf/CancelPnL.ts +++ b/packages/ibkr/src/protobuf/CancelPnL.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelPnL.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelPnLSingle.ts b/packages/ibkr/src/protobuf/CancelPnLSingle.ts index c091da1d..2e266906 100644 --- a/packages/ibkr/src/protobuf/CancelPnLSingle.ts +++ b/packages/ibkr/src/protobuf/CancelPnLSingle.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelPnLSingle.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelPositions.ts b/packages/ibkr/src/protobuf/CancelPositions.ts index 8d9e177f..35117450 100644 --- a/packages/ibkr/src/protobuf/CancelPositions.ts +++ b/packages/ibkr/src/protobuf/CancelPositions.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelPositions.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelPositionsMulti.ts b/packages/ibkr/src/protobuf/CancelPositionsMulti.ts index d798f38e..93652ac6 100644 --- a/packages/ibkr/src/protobuf/CancelPositionsMulti.ts +++ b/packages/ibkr/src/protobuf/CancelPositionsMulti.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelPositionsMulti.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelRealTimeBars.ts b/packages/ibkr/src/protobuf/CancelRealTimeBars.ts index ec0c6739..623e58ac 100644 --- a/packages/ibkr/src/protobuf/CancelRealTimeBars.ts +++ b/packages/ibkr/src/protobuf/CancelRealTimeBars.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelRealTimeBars.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelScannerSubscription.ts b/packages/ibkr/src/protobuf/CancelScannerSubscription.ts index b5d390db..406545ba 100644 --- a/packages/ibkr/src/protobuf/CancelScannerSubscription.ts +++ b/packages/ibkr/src/protobuf/CancelScannerSubscription.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelScannerSubscription.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelTickByTick.ts b/packages/ibkr/src/protobuf/CancelTickByTick.ts index 70a24789..6b31ba0d 100644 --- a/packages/ibkr/src/protobuf/CancelTickByTick.ts +++ b/packages/ibkr/src/protobuf/CancelTickByTick.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelTickByTick.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelWshEventData.ts b/packages/ibkr/src/protobuf/CancelWshEventData.ts index befb8a1e..f61ad43c 100644 --- a/packages/ibkr/src/protobuf/CancelWshEventData.ts +++ b/packages/ibkr/src/protobuf/CancelWshEventData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelWshEventData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CancelWshMetaData.ts b/packages/ibkr/src/protobuf/CancelWshMetaData.ts index 266aa0ad..6493311c 100644 --- a/packages/ibkr/src/protobuf/CancelWshMetaData.ts +++ b/packages/ibkr/src/protobuf/CancelWshMetaData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CancelWshMetaData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ComboLeg.ts b/packages/ibkr/src/protobuf/ComboLeg.ts index 4fd56508..3df617e9 100644 --- a/packages/ibkr/src/protobuf/ComboLeg.ts +++ b/packages/ibkr/src/protobuf/ComboLeg.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ComboLeg.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CommissionAndFeesReport.ts b/packages/ibkr/src/protobuf/CommissionAndFeesReport.ts index 4df0f454..91cd3283 100644 --- a/packages/ibkr/src/protobuf/CommissionAndFeesReport.ts +++ b/packages/ibkr/src/protobuf/CommissionAndFeesReport.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CommissionAndFeesReport.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CompletedOrder.ts b/packages/ibkr/src/protobuf/CompletedOrder.ts index 626b4705..661dc65d 100644 --- a/packages/ibkr/src/protobuf/CompletedOrder.ts +++ b/packages/ibkr/src/protobuf/CompletedOrder.ts @@ -1,14 +1,14 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CompletedOrder.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; -import { Order } from "./Order"; -import { OrderState } from "./OrderState"; +import { Contract } from "./Contract.js"; +import { Order } from "./Order.js"; +import { OrderState } from "./OrderState.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/CompletedOrdersEnd.ts b/packages/ibkr/src/protobuf/CompletedOrdersEnd.ts index b75ed85b..224eaeda 100644 --- a/packages/ibkr/src/protobuf/CompletedOrdersEnd.ts +++ b/packages/ibkr/src/protobuf/CompletedOrdersEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CompletedOrdersEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CompletedOrdersRequest.ts b/packages/ibkr/src/protobuf/CompletedOrdersRequest.ts index 8324aacb..268975b9 100644 --- a/packages/ibkr/src/protobuf/CompletedOrdersRequest.ts +++ b/packages/ibkr/src/protobuf/CompletedOrdersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CompletedOrdersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ConfigRequest.ts b/packages/ibkr/src/protobuf/ConfigRequest.ts index b0b41968..b354e92c 100644 --- a/packages/ibkr/src/protobuf/ConfigRequest.ts +++ b/packages/ibkr/src/protobuf/ConfigRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ConfigRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ConfigResponse.ts b/packages/ibkr/src/protobuf/ConfigResponse.ts index 1cd0291d..206a4acc 100644 --- a/packages/ibkr/src/protobuf/ConfigResponse.ts +++ b/packages/ibkr/src/protobuf/ConfigResponse.ts @@ -1,15 +1,15 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ConfigResponse.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ApiConfig } from "./ApiConfig"; -import { LockAndExitConfig } from "./LockAndExitConfig"; -import { MessageConfig } from "./MessageConfig"; -import { OrdersConfig } from "./OrdersConfig"; +import { ApiConfig } from "./ApiConfig.js"; +import { LockAndExitConfig } from "./LockAndExitConfig.js"; +import { MessageConfig } from "./MessageConfig.js"; +import { OrdersConfig } from "./OrdersConfig.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/Contract.ts b/packages/ibkr/src/protobuf/Contract.ts index 2012af92..3b4b2e17 100644 --- a/packages/ibkr/src/protobuf/Contract.ts +++ b/packages/ibkr/src/protobuf/Contract.ts @@ -1,13 +1,13 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: Contract.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ComboLeg } from "./ComboLeg"; -import { DeltaNeutralContract } from "./DeltaNeutralContract"; +import { ComboLeg } from "./ComboLeg.js"; +import { DeltaNeutralContract } from "./DeltaNeutralContract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ContractData.ts b/packages/ibkr/src/protobuf/ContractData.ts index 866baae5..c4155eaf 100644 --- a/packages/ibkr/src/protobuf/ContractData.ts +++ b/packages/ibkr/src/protobuf/ContractData.ts @@ -1,13 +1,13 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ContractData.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; -import { ContractDetails } from "./ContractDetails"; +import { Contract } from "./Contract.js"; +import { ContractDetails } from "./ContractDetails.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ContractDataEnd.ts b/packages/ibkr/src/protobuf/ContractDataEnd.ts index 34708550..cb311c9a 100644 --- a/packages/ibkr/src/protobuf/ContractDataEnd.ts +++ b/packages/ibkr/src/protobuf/ContractDataEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ContractDataEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ContractDataRequest.ts b/packages/ibkr/src/protobuf/ContractDataRequest.ts index c8fe8980..16981b3a 100644 --- a/packages/ibkr/src/protobuf/ContractDataRequest.ts +++ b/packages/ibkr/src/protobuf/ContractDataRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ContractDataRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ContractDescription.ts b/packages/ibkr/src/protobuf/ContractDescription.ts index 914ebe99..038309ab 100644 --- a/packages/ibkr/src/protobuf/ContractDescription.ts +++ b/packages/ibkr/src/protobuf/ContractDescription.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ContractDescription.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ContractDetails.ts b/packages/ibkr/src/protobuf/ContractDetails.ts index b60262bd..06ffd84f 100644 --- a/packages/ibkr/src/protobuf/ContractDetails.ts +++ b/packages/ibkr/src/protobuf/ContractDetails.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ContractDetails.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { IneligibilityReason } from "./IneligibilityReason"; +import { IneligibilityReason } from "./IneligibilityReason.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/CurrentTime.ts b/packages/ibkr/src/protobuf/CurrentTime.ts index c3d31a61..95cd280f 100644 --- a/packages/ibkr/src/protobuf/CurrentTime.ts +++ b/packages/ibkr/src/protobuf/CurrentTime.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CurrentTime.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CurrentTimeInMillis.ts b/packages/ibkr/src/protobuf/CurrentTimeInMillis.ts index 416474cb..76c3ba84 100644 --- a/packages/ibkr/src/protobuf/CurrentTimeInMillis.ts +++ b/packages/ibkr/src/protobuf/CurrentTimeInMillis.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CurrentTimeInMillis.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CurrentTimeInMillisRequest.ts b/packages/ibkr/src/protobuf/CurrentTimeInMillisRequest.ts index 42721f7a..76a7c71f 100644 --- a/packages/ibkr/src/protobuf/CurrentTimeInMillisRequest.ts +++ b/packages/ibkr/src/protobuf/CurrentTimeInMillisRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CurrentTimeInMillisRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/CurrentTimeRequest.ts b/packages/ibkr/src/protobuf/CurrentTimeRequest.ts index b50d4807..2d052bc7 100644 --- a/packages/ibkr/src/protobuf/CurrentTimeRequest.ts +++ b/packages/ibkr/src/protobuf/CurrentTimeRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: CurrentTimeRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/DeltaNeutralContract.ts b/packages/ibkr/src/protobuf/DeltaNeutralContract.ts index 986fd25e..33d331b4 100644 --- a/packages/ibkr/src/protobuf/DeltaNeutralContract.ts +++ b/packages/ibkr/src/protobuf/DeltaNeutralContract.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: DeltaNeutralContract.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/DepthMarketDataDescription.ts b/packages/ibkr/src/protobuf/DepthMarketDataDescription.ts index 36c97558..125ecff0 100644 --- a/packages/ibkr/src/protobuf/DepthMarketDataDescription.ts +++ b/packages/ibkr/src/protobuf/DepthMarketDataDescription.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: DepthMarketDataDescription.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/DisplayGroupList.ts b/packages/ibkr/src/protobuf/DisplayGroupList.ts index 91d33105..ade47bf1 100644 --- a/packages/ibkr/src/protobuf/DisplayGroupList.ts +++ b/packages/ibkr/src/protobuf/DisplayGroupList.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: DisplayGroupList.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/DisplayGroupUpdated.ts b/packages/ibkr/src/protobuf/DisplayGroupUpdated.ts index b7da4a9e..4e198bc5 100644 --- a/packages/ibkr/src/protobuf/DisplayGroupUpdated.ts +++ b/packages/ibkr/src/protobuf/DisplayGroupUpdated.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: DisplayGroupUpdated.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ErrorMessage.ts b/packages/ibkr/src/protobuf/ErrorMessage.ts index b9cc509a..10660f9b 100644 --- a/packages/ibkr/src/protobuf/ErrorMessage.ts +++ b/packages/ibkr/src/protobuf/ErrorMessage.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ErrorMessage.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/Execution.ts b/packages/ibkr/src/protobuf/Execution.ts index 913bd309..1ea30af9 100644 --- a/packages/ibkr/src/protobuf/Execution.ts +++ b/packages/ibkr/src/protobuf/Execution.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: Execution.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ExecutionDetails.ts b/packages/ibkr/src/protobuf/ExecutionDetails.ts index b422e80d..5b2d1658 100644 --- a/packages/ibkr/src/protobuf/ExecutionDetails.ts +++ b/packages/ibkr/src/protobuf/ExecutionDetails.ts @@ -1,13 +1,13 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ExecutionDetails.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; -import { Execution } from "./Execution"; +import { Contract } from "./Contract.js"; +import { Execution } from "./Execution.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ExecutionDetailsEnd.ts b/packages/ibkr/src/protobuf/ExecutionDetailsEnd.ts index 14c92abc..8e6afda3 100644 --- a/packages/ibkr/src/protobuf/ExecutionDetailsEnd.ts +++ b/packages/ibkr/src/protobuf/ExecutionDetailsEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ExecutionDetailsEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ExecutionFilter.ts b/packages/ibkr/src/protobuf/ExecutionFilter.ts index c36b100c..5b4830b8 100644 --- a/packages/ibkr/src/protobuf/ExecutionFilter.ts +++ b/packages/ibkr/src/protobuf/ExecutionFilter.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ExecutionFilter.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ExecutionRequest.ts b/packages/ibkr/src/protobuf/ExecutionRequest.ts index b81f3be4..22cf9984 100644 --- a/packages/ibkr/src/protobuf/ExecutionRequest.ts +++ b/packages/ibkr/src/protobuf/ExecutionRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ExecutionRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ExecutionFilter } from "./ExecutionFilter"; +import { ExecutionFilter } from "./ExecutionFilter.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ExerciseOptionsRequest.ts b/packages/ibkr/src/protobuf/ExerciseOptionsRequest.ts index f74d85f4..8004e56e 100644 --- a/packages/ibkr/src/protobuf/ExerciseOptionsRequest.ts +++ b/packages/ibkr/src/protobuf/ExerciseOptionsRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ExerciseOptionsRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/FAReplace.ts b/packages/ibkr/src/protobuf/FAReplace.ts index 5d12ee7a..83e00e0c 100644 --- a/packages/ibkr/src/protobuf/FAReplace.ts +++ b/packages/ibkr/src/protobuf/FAReplace.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FAReplace.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/FARequest.ts b/packages/ibkr/src/protobuf/FARequest.ts index 8e0f40c8..42c51197 100644 --- a/packages/ibkr/src/protobuf/FARequest.ts +++ b/packages/ibkr/src/protobuf/FARequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FARequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/FamilyCode.ts b/packages/ibkr/src/protobuf/FamilyCode.ts index 13e5d9e6..3bb4fa85 100644 --- a/packages/ibkr/src/protobuf/FamilyCode.ts +++ b/packages/ibkr/src/protobuf/FamilyCode.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FamilyCode.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/FamilyCodes.ts b/packages/ibkr/src/protobuf/FamilyCodes.ts index b37ac45f..4d13abc5 100644 --- a/packages/ibkr/src/protobuf/FamilyCodes.ts +++ b/packages/ibkr/src/protobuf/FamilyCodes.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FamilyCodes.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { FamilyCode } from "./FamilyCode"; +import { FamilyCode } from "./FamilyCode.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/FamilyCodesRequest.ts b/packages/ibkr/src/protobuf/FamilyCodesRequest.ts index c59cb98d..9c2361a4 100644 --- a/packages/ibkr/src/protobuf/FamilyCodesRequest.ts +++ b/packages/ibkr/src/protobuf/FamilyCodesRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FamilyCodesRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/FundamentalsData.ts b/packages/ibkr/src/protobuf/FundamentalsData.ts index fd6b4881..6f0ecd32 100644 --- a/packages/ibkr/src/protobuf/FundamentalsData.ts +++ b/packages/ibkr/src/protobuf/FundamentalsData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FundamentalsData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/FundamentalsDataRequest.ts b/packages/ibkr/src/protobuf/FundamentalsDataRequest.ts index a7bfcec6..e6e2cb8c 100644 --- a/packages/ibkr/src/protobuf/FundamentalsDataRequest.ts +++ b/packages/ibkr/src/protobuf/FundamentalsDataRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: FundamentalsDataRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/GlobalCancelRequest.ts b/packages/ibkr/src/protobuf/GlobalCancelRequest.ts index 44a3acee..3f4dc76e 100644 --- a/packages/ibkr/src/protobuf/GlobalCancelRequest.ts +++ b/packages/ibkr/src/protobuf/GlobalCancelRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: GlobalCancelRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { OrderCancel } from "./OrderCancel"; +import { OrderCancel } from "./OrderCancel.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HeadTimestamp.ts b/packages/ibkr/src/protobuf/HeadTimestamp.ts index a19f38f9..3223fb29 100644 --- a/packages/ibkr/src/protobuf/HeadTimestamp.ts +++ b/packages/ibkr/src/protobuf/HeadTimestamp.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HeadTimestamp.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HeadTimestampRequest.ts b/packages/ibkr/src/protobuf/HeadTimestampRequest.ts index 71b1f102..d9c62b4e 100644 --- a/packages/ibkr/src/protobuf/HeadTimestampRequest.ts +++ b/packages/ibkr/src/protobuf/HeadTimestampRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HeadTimestampRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistogramData.ts b/packages/ibkr/src/protobuf/HistogramData.ts index 92b90777..b685f5ab 100644 --- a/packages/ibkr/src/protobuf/HistogramData.ts +++ b/packages/ibkr/src/protobuf/HistogramData.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistogramData.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistogramDataEntry } from "./HistogramDataEntry"; +import { HistogramDataEntry } from "./HistogramDataEntry.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistogramDataEntry.ts b/packages/ibkr/src/protobuf/HistogramDataEntry.ts index bbe21b92..afd3ecd8 100644 --- a/packages/ibkr/src/protobuf/HistogramDataEntry.ts +++ b/packages/ibkr/src/protobuf/HistogramDataEntry.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistogramDataEntry.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistogramDataRequest.ts b/packages/ibkr/src/protobuf/HistogramDataRequest.ts index 821a3817..e70a1cd6 100644 --- a/packages/ibkr/src/protobuf/HistogramDataRequest.ts +++ b/packages/ibkr/src/protobuf/HistogramDataRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistogramDataRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalData.ts b/packages/ibkr/src/protobuf/HistoricalData.ts index e4a279e8..2fb69c96 100644 --- a/packages/ibkr/src/protobuf/HistoricalData.ts +++ b/packages/ibkr/src/protobuf/HistoricalData.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalData.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalDataBar } from "./HistoricalDataBar"; +import { HistoricalDataBar } from "./HistoricalDataBar.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalDataBar.ts b/packages/ibkr/src/protobuf/HistoricalDataBar.ts index 9f8f91ce..4458b8ac 100644 --- a/packages/ibkr/src/protobuf/HistoricalDataBar.ts +++ b/packages/ibkr/src/protobuf/HistoricalDataBar.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalDataBar.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalDataEnd.ts b/packages/ibkr/src/protobuf/HistoricalDataEnd.ts index 87379080..72879066 100644 --- a/packages/ibkr/src/protobuf/HistoricalDataEnd.ts +++ b/packages/ibkr/src/protobuf/HistoricalDataEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalDataEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalDataRequest.ts b/packages/ibkr/src/protobuf/HistoricalDataRequest.ts index 0a9ab724..4208798b 100644 --- a/packages/ibkr/src/protobuf/HistoricalDataRequest.ts +++ b/packages/ibkr/src/protobuf/HistoricalDataRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalDataRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalDataUpdate.ts b/packages/ibkr/src/protobuf/HistoricalDataUpdate.ts index a2339a74..485cef8d 100644 --- a/packages/ibkr/src/protobuf/HistoricalDataUpdate.ts +++ b/packages/ibkr/src/protobuf/HistoricalDataUpdate.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalDataUpdate.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalDataBar } from "./HistoricalDataBar"; +import { HistoricalDataBar } from "./HistoricalDataBar.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalNews.ts b/packages/ibkr/src/protobuf/HistoricalNews.ts index 1de7bb2a..719d6178 100644 --- a/packages/ibkr/src/protobuf/HistoricalNews.ts +++ b/packages/ibkr/src/protobuf/HistoricalNews.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalNews.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalNewsEnd.ts b/packages/ibkr/src/protobuf/HistoricalNewsEnd.ts index 262970bc..ee745afc 100644 --- a/packages/ibkr/src/protobuf/HistoricalNewsEnd.ts +++ b/packages/ibkr/src/protobuf/HistoricalNewsEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalNewsEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalNewsRequest.ts b/packages/ibkr/src/protobuf/HistoricalNewsRequest.ts index d3e9a42f..7968acbb 100644 --- a/packages/ibkr/src/protobuf/HistoricalNewsRequest.ts +++ b/packages/ibkr/src/protobuf/HistoricalNewsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalNewsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalSchedule.ts b/packages/ibkr/src/protobuf/HistoricalSchedule.ts index 33e0991e..da9e03d6 100644 --- a/packages/ibkr/src/protobuf/HistoricalSchedule.ts +++ b/packages/ibkr/src/protobuf/HistoricalSchedule.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalSchedule.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalSession } from "./HistoricalSession"; +import { HistoricalSession } from "./HistoricalSession.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalSession.ts b/packages/ibkr/src/protobuf/HistoricalSession.ts index e9ab91a7..f8f9db2b 100644 --- a/packages/ibkr/src/protobuf/HistoricalSession.ts +++ b/packages/ibkr/src/protobuf/HistoricalSession.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalSession.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalTick.ts b/packages/ibkr/src/protobuf/HistoricalTick.ts index 06676c9e..33e0a57d 100644 --- a/packages/ibkr/src/protobuf/HistoricalTick.ts +++ b/packages/ibkr/src/protobuf/HistoricalTick.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTick.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/HistoricalTickBidAsk.ts b/packages/ibkr/src/protobuf/HistoricalTickBidAsk.ts index 8bbe286d..e220446f 100644 --- a/packages/ibkr/src/protobuf/HistoricalTickBidAsk.ts +++ b/packages/ibkr/src/protobuf/HistoricalTickBidAsk.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTickBidAsk.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { TickAttribBidAsk } from "./TickAttribBidAsk"; +import { TickAttribBidAsk } from "./TickAttribBidAsk.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalTickLast.ts b/packages/ibkr/src/protobuf/HistoricalTickLast.ts index 8c884d41..3900d02f 100644 --- a/packages/ibkr/src/protobuf/HistoricalTickLast.ts +++ b/packages/ibkr/src/protobuf/HistoricalTickLast.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTickLast.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { TickAttribLast } from "./TickAttribLast"; +import { TickAttribLast } from "./TickAttribLast.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalTicks.ts b/packages/ibkr/src/protobuf/HistoricalTicks.ts index 31587f3a..626d0fd7 100644 --- a/packages/ibkr/src/protobuf/HistoricalTicks.ts +++ b/packages/ibkr/src/protobuf/HistoricalTicks.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTicks.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalTick } from "./HistoricalTick"; +import { HistoricalTick } from "./HistoricalTick.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalTicksBidAsk.ts b/packages/ibkr/src/protobuf/HistoricalTicksBidAsk.ts index bd1084e6..dc25b7f9 100644 --- a/packages/ibkr/src/protobuf/HistoricalTicksBidAsk.ts +++ b/packages/ibkr/src/protobuf/HistoricalTicksBidAsk.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTicksBidAsk.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalTickBidAsk } from "./HistoricalTickBidAsk"; +import { HistoricalTickBidAsk } from "./HistoricalTickBidAsk.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalTicksLast.ts b/packages/ibkr/src/protobuf/HistoricalTicksLast.ts index 1efde3c3..84f1fa89 100644 --- a/packages/ibkr/src/protobuf/HistoricalTicksLast.ts +++ b/packages/ibkr/src/protobuf/HistoricalTicksLast.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTicksLast.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalTickLast } from "./HistoricalTickLast"; +import { HistoricalTickLast } from "./HistoricalTickLast.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/HistoricalTicksRequest.ts b/packages/ibkr/src/protobuf/HistoricalTicksRequest.ts index c627fa45..8b926747 100644 --- a/packages/ibkr/src/protobuf/HistoricalTicksRequest.ts +++ b/packages/ibkr/src/protobuf/HistoricalTicksRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: HistoricalTicksRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/IdsRequest.ts b/packages/ibkr/src/protobuf/IdsRequest.ts index c4503655..c2da1b33 100644 --- a/packages/ibkr/src/protobuf/IdsRequest.ts +++ b/packages/ibkr/src/protobuf/IdsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: IdsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/IneligibilityReason.ts b/packages/ibkr/src/protobuf/IneligibilityReason.ts index 4b25fef1..54dd4dcc 100644 --- a/packages/ibkr/src/protobuf/IneligibilityReason.ts +++ b/packages/ibkr/src/protobuf/IneligibilityReason.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: IneligibilityReason.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/LockAndExitConfig.ts b/packages/ibkr/src/protobuf/LockAndExitConfig.ts index 97c2640d..d7f49c6b 100644 --- a/packages/ibkr/src/protobuf/LockAndExitConfig.ts +++ b/packages/ibkr/src/protobuf/LockAndExitConfig.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: LockAndExitConfig.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ManagedAccounts.ts b/packages/ibkr/src/protobuf/ManagedAccounts.ts index 783c3973..24b8f693 100644 --- a/packages/ibkr/src/protobuf/ManagedAccounts.ts +++ b/packages/ibkr/src/protobuf/ManagedAccounts.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ManagedAccounts.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ManagedAccountsRequest.ts b/packages/ibkr/src/protobuf/ManagedAccountsRequest.ts index 54dbad22..39b198be 100644 --- a/packages/ibkr/src/protobuf/ManagedAccountsRequest.ts +++ b/packages/ibkr/src/protobuf/ManagedAccountsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ManagedAccountsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MarketDataRequest.ts b/packages/ibkr/src/protobuf/MarketDataRequest.ts index 4bafcccf..49ec7d6d 100644 --- a/packages/ibkr/src/protobuf/MarketDataRequest.ts +++ b/packages/ibkr/src/protobuf/MarketDataRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDataRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/MarketDataType.ts b/packages/ibkr/src/protobuf/MarketDataType.ts index 0b4ca521..09545c30 100644 --- a/packages/ibkr/src/protobuf/MarketDataType.ts +++ b/packages/ibkr/src/protobuf/MarketDataType.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDataType.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MarketDataTypeRequest.ts b/packages/ibkr/src/protobuf/MarketDataTypeRequest.ts index 41c82676..2b86ad38 100644 --- a/packages/ibkr/src/protobuf/MarketDataTypeRequest.ts +++ b/packages/ibkr/src/protobuf/MarketDataTypeRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDataTypeRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MarketDepth.ts b/packages/ibkr/src/protobuf/MarketDepth.ts index 5d452c2b..afe05bbc 100644 --- a/packages/ibkr/src/protobuf/MarketDepth.ts +++ b/packages/ibkr/src/protobuf/MarketDepth.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDepth.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { MarketDepthData } from "./MarketDepthData"; +import { MarketDepthData } from "./MarketDepthData.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/MarketDepthData.ts b/packages/ibkr/src/protobuf/MarketDepthData.ts index 34ce26d7..9842c4f4 100644 --- a/packages/ibkr/src/protobuf/MarketDepthData.ts +++ b/packages/ibkr/src/protobuf/MarketDepthData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDepthData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MarketDepthExchanges.ts b/packages/ibkr/src/protobuf/MarketDepthExchanges.ts index ea352104..adfef942 100644 --- a/packages/ibkr/src/protobuf/MarketDepthExchanges.ts +++ b/packages/ibkr/src/protobuf/MarketDepthExchanges.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDepthExchanges.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { DepthMarketDataDescription } from "./DepthMarketDataDescription"; +import { DepthMarketDataDescription } from "./DepthMarketDataDescription.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/MarketDepthExchangesRequest.ts b/packages/ibkr/src/protobuf/MarketDepthExchangesRequest.ts index 86a66bbb..56d03712 100644 --- a/packages/ibkr/src/protobuf/MarketDepthExchangesRequest.ts +++ b/packages/ibkr/src/protobuf/MarketDepthExchangesRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDepthExchangesRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MarketDepthL2.ts b/packages/ibkr/src/protobuf/MarketDepthL2.ts index fb6c72cc..6ea7dd61 100644 --- a/packages/ibkr/src/protobuf/MarketDepthL2.ts +++ b/packages/ibkr/src/protobuf/MarketDepthL2.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDepthL2.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { MarketDepthData } from "./MarketDepthData"; +import { MarketDepthData } from "./MarketDepthData.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/MarketDepthRequest.ts b/packages/ibkr/src/protobuf/MarketDepthRequest.ts index 7ad2bc8f..15a06ee6 100644 --- a/packages/ibkr/src/protobuf/MarketDepthRequest.ts +++ b/packages/ibkr/src/protobuf/MarketDepthRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketDepthRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/MarketRule.ts b/packages/ibkr/src/protobuf/MarketRule.ts index 44000ecb..7d31f338 100644 --- a/packages/ibkr/src/protobuf/MarketRule.ts +++ b/packages/ibkr/src/protobuf/MarketRule.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketRule.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { PriceIncrement } from "./PriceIncrement"; +import { PriceIncrement } from "./PriceIncrement.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/MarketRuleRequest.ts b/packages/ibkr/src/protobuf/MarketRuleRequest.ts index b48a3102..e55886c2 100644 --- a/packages/ibkr/src/protobuf/MarketRuleRequest.ts +++ b/packages/ibkr/src/protobuf/MarketRuleRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MarketRuleRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MatchingSymbolsRequest.ts b/packages/ibkr/src/protobuf/MatchingSymbolsRequest.ts index 4b583aa4..2c46eb6a 100644 --- a/packages/ibkr/src/protobuf/MatchingSymbolsRequest.ts +++ b/packages/ibkr/src/protobuf/MatchingSymbolsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MatchingSymbolsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/MessageConfig.ts b/packages/ibkr/src/protobuf/MessageConfig.ts index 72238013..ba0e8274 100644 --- a/packages/ibkr/src/protobuf/MessageConfig.ts +++ b/packages/ibkr/src/protobuf/MessageConfig.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: MessageConfig.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NewsArticle.ts b/packages/ibkr/src/protobuf/NewsArticle.ts index cee6ee65..b024ffe3 100644 --- a/packages/ibkr/src/protobuf/NewsArticle.ts +++ b/packages/ibkr/src/protobuf/NewsArticle.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsArticle.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NewsArticleRequest.ts b/packages/ibkr/src/protobuf/NewsArticleRequest.ts index ffb64a3c..4b359748 100644 --- a/packages/ibkr/src/protobuf/NewsArticleRequest.ts +++ b/packages/ibkr/src/protobuf/NewsArticleRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsArticleRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NewsBulletin.ts b/packages/ibkr/src/protobuf/NewsBulletin.ts index d7506c8c..cc40feec 100644 --- a/packages/ibkr/src/protobuf/NewsBulletin.ts +++ b/packages/ibkr/src/protobuf/NewsBulletin.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsBulletin.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NewsBulletinsRequest.ts b/packages/ibkr/src/protobuf/NewsBulletinsRequest.ts index dfa07dc8..16521eca 100644 --- a/packages/ibkr/src/protobuf/NewsBulletinsRequest.ts +++ b/packages/ibkr/src/protobuf/NewsBulletinsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsBulletinsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NewsProvider.ts b/packages/ibkr/src/protobuf/NewsProvider.ts index 39ac5ee6..10734eba 100644 --- a/packages/ibkr/src/protobuf/NewsProvider.ts +++ b/packages/ibkr/src/protobuf/NewsProvider.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsProvider.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NewsProviders.ts b/packages/ibkr/src/protobuf/NewsProviders.ts index bb914558..261e8c9b 100644 --- a/packages/ibkr/src/protobuf/NewsProviders.ts +++ b/packages/ibkr/src/protobuf/NewsProviders.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsProviders.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { NewsProvider } from "./NewsProvider"; +import { NewsProvider } from "./NewsProvider.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/NewsProvidersRequest.ts b/packages/ibkr/src/protobuf/NewsProvidersRequest.ts index cc1f7b24..ec389afb 100644 --- a/packages/ibkr/src/protobuf/NewsProvidersRequest.ts +++ b/packages/ibkr/src/protobuf/NewsProvidersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NewsProvidersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/NextValidId.ts b/packages/ibkr/src/protobuf/NextValidId.ts index d154c6a7..454f8d74 100644 --- a/packages/ibkr/src/protobuf/NextValidId.ts +++ b/packages/ibkr/src/protobuf/NextValidId.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: NextValidId.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OpenOrder.ts b/packages/ibkr/src/protobuf/OpenOrder.ts index 39a0ba5e..69e0007c 100644 --- a/packages/ibkr/src/protobuf/OpenOrder.ts +++ b/packages/ibkr/src/protobuf/OpenOrder.ts @@ -1,14 +1,14 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OpenOrder.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; -import { Order } from "./Order"; -import { OrderState } from "./OrderState"; +import { Contract } from "./Contract.js"; +import { Order } from "./Order.js"; +import { OrderState } from "./OrderState.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/OpenOrdersEnd.ts b/packages/ibkr/src/protobuf/OpenOrdersEnd.ts index 4beccfe2..28ec2535 100644 --- a/packages/ibkr/src/protobuf/OpenOrdersEnd.ts +++ b/packages/ibkr/src/protobuf/OpenOrdersEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OpenOrdersEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OpenOrdersRequest.ts b/packages/ibkr/src/protobuf/OpenOrdersRequest.ts index f20a9775..92bc99ff 100644 --- a/packages/ibkr/src/protobuf/OpenOrdersRequest.ts +++ b/packages/ibkr/src/protobuf/OpenOrdersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OpenOrdersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/Order.ts b/packages/ibkr/src/protobuf/Order.ts index 02e386b3..839a6959 100644 --- a/packages/ibkr/src/protobuf/Order.ts +++ b/packages/ibkr/src/protobuf/Order.ts @@ -1,13 +1,13 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: Order.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { OrderCondition } from "./OrderCondition"; -import { SoftDollarTier } from "./SoftDollarTier"; +import { OrderCondition } from "./OrderCondition.js"; +import { SoftDollarTier } from "./SoftDollarTier.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/OrderAllocation.ts b/packages/ibkr/src/protobuf/OrderAllocation.ts index 2acbcabf..6676706f 100644 --- a/packages/ibkr/src/protobuf/OrderAllocation.ts +++ b/packages/ibkr/src/protobuf/OrderAllocation.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrderAllocation.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OrderBound.ts b/packages/ibkr/src/protobuf/OrderBound.ts index 5d51464b..85771708 100644 --- a/packages/ibkr/src/protobuf/OrderBound.ts +++ b/packages/ibkr/src/protobuf/OrderBound.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrderBound.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OrderCancel.ts b/packages/ibkr/src/protobuf/OrderCancel.ts index dfd5d0cf..ae6ac783 100644 --- a/packages/ibkr/src/protobuf/OrderCancel.ts +++ b/packages/ibkr/src/protobuf/OrderCancel.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrderCancel.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OrderCondition.ts b/packages/ibkr/src/protobuf/OrderCondition.ts index dce5cc25..5afa311b 100644 --- a/packages/ibkr/src/protobuf/OrderCondition.ts +++ b/packages/ibkr/src/protobuf/OrderCondition.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrderCondition.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OrderState.ts b/packages/ibkr/src/protobuf/OrderState.ts index 2d2bd719..6c30d015 100644 --- a/packages/ibkr/src/protobuf/OrderState.ts +++ b/packages/ibkr/src/protobuf/OrderState.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrderState.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { OrderAllocation } from "./OrderAllocation"; +import { OrderAllocation } from "./OrderAllocation.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/OrderStatus.ts b/packages/ibkr/src/protobuf/OrderStatus.ts index 5cbda3a3..585150df 100644 --- a/packages/ibkr/src/protobuf/OrderStatus.ts +++ b/packages/ibkr/src/protobuf/OrderStatus.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrderStatus.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/OrdersConfig.ts b/packages/ibkr/src/protobuf/OrdersConfig.ts index 94c348ba..cb209228 100644 --- a/packages/ibkr/src/protobuf/OrdersConfig.ts +++ b/packages/ibkr/src/protobuf/OrdersConfig.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrdersConfig.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { OrdersSmartRoutingConfig } from "./OrdersSmartRoutingConfig"; +import { OrdersSmartRoutingConfig } from "./OrdersSmartRoutingConfig.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/OrdersSmartRoutingConfig.ts b/packages/ibkr/src/protobuf/OrdersSmartRoutingConfig.ts index b37b0f6e..dfa729b3 100644 --- a/packages/ibkr/src/protobuf/OrdersSmartRoutingConfig.ts +++ b/packages/ibkr/src/protobuf/OrdersSmartRoutingConfig.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: OrdersSmartRoutingConfig.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PlaceOrderRequest.ts b/packages/ibkr/src/protobuf/PlaceOrderRequest.ts index 23db7ce0..ee0dd7d7 100644 --- a/packages/ibkr/src/protobuf/PlaceOrderRequest.ts +++ b/packages/ibkr/src/protobuf/PlaceOrderRequest.ts @@ -1,14 +1,14 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PlaceOrderRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { AttachedOrders } from "./AttachedOrders"; -import { Contract } from "./Contract"; -import { Order } from "./Order"; +import { AttachedOrders } from "./AttachedOrders.js"; +import { Contract } from "./Contract.js"; +import { Order } from "./Order.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/PnL.ts b/packages/ibkr/src/protobuf/PnL.ts index f0e15157..49282b06 100644 --- a/packages/ibkr/src/protobuf/PnL.ts +++ b/packages/ibkr/src/protobuf/PnL.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PnL.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PnLRequest.ts b/packages/ibkr/src/protobuf/PnLRequest.ts index e0c6ba80..069fc695 100644 --- a/packages/ibkr/src/protobuf/PnLRequest.ts +++ b/packages/ibkr/src/protobuf/PnLRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PnLRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PnLSingle.ts b/packages/ibkr/src/protobuf/PnLSingle.ts index e0e2fb2b..34da6593 100644 --- a/packages/ibkr/src/protobuf/PnLSingle.ts +++ b/packages/ibkr/src/protobuf/PnLSingle.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PnLSingle.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PnLSingleRequest.ts b/packages/ibkr/src/protobuf/PnLSingleRequest.ts index d0fa2786..fe595276 100644 --- a/packages/ibkr/src/protobuf/PnLSingleRequest.ts +++ b/packages/ibkr/src/protobuf/PnLSingleRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PnLSingleRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PortfolioValue.ts b/packages/ibkr/src/protobuf/PortfolioValue.ts index 5cd7800b..2c5552b5 100644 --- a/packages/ibkr/src/protobuf/PortfolioValue.ts +++ b/packages/ibkr/src/protobuf/PortfolioValue.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PortfolioValue.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/Position.ts b/packages/ibkr/src/protobuf/Position.ts index 3c8c359b..39dc8ad9 100644 --- a/packages/ibkr/src/protobuf/Position.ts +++ b/packages/ibkr/src/protobuf/Position.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: Position.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/PositionEnd.ts b/packages/ibkr/src/protobuf/PositionEnd.ts index 49777693..a6e2835c 100644 --- a/packages/ibkr/src/protobuf/PositionEnd.ts +++ b/packages/ibkr/src/protobuf/PositionEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PositionEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PositionMulti.ts b/packages/ibkr/src/protobuf/PositionMulti.ts index 984865d1..336ec004 100644 --- a/packages/ibkr/src/protobuf/PositionMulti.ts +++ b/packages/ibkr/src/protobuf/PositionMulti.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PositionMulti.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/PositionMultiEnd.ts b/packages/ibkr/src/protobuf/PositionMultiEnd.ts index dcf3da57..e5f3e437 100644 --- a/packages/ibkr/src/protobuf/PositionMultiEnd.ts +++ b/packages/ibkr/src/protobuf/PositionMultiEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PositionMultiEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PositionsMultiRequest.ts b/packages/ibkr/src/protobuf/PositionsMultiRequest.ts index d5fcd6ad..172cc047 100644 --- a/packages/ibkr/src/protobuf/PositionsMultiRequest.ts +++ b/packages/ibkr/src/protobuf/PositionsMultiRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PositionsMultiRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PositionsRequest.ts b/packages/ibkr/src/protobuf/PositionsRequest.ts index 5327c497..790ff775 100644 --- a/packages/ibkr/src/protobuf/PositionsRequest.ts +++ b/packages/ibkr/src/protobuf/PositionsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PositionsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/PriceIncrement.ts b/packages/ibkr/src/protobuf/PriceIncrement.ts index d3bd4634..83490e26 100644 --- a/packages/ibkr/src/protobuf/PriceIncrement.ts +++ b/packages/ibkr/src/protobuf/PriceIncrement.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: PriceIncrement.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/QueryDisplayGroupsRequest.ts b/packages/ibkr/src/protobuf/QueryDisplayGroupsRequest.ts index 6a69e9a0..2a1ff13c 100644 --- a/packages/ibkr/src/protobuf/QueryDisplayGroupsRequest.ts +++ b/packages/ibkr/src/protobuf/QueryDisplayGroupsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: QueryDisplayGroupsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/RealTimeBarTick.ts b/packages/ibkr/src/protobuf/RealTimeBarTick.ts index 3e065353..9b3000ed 100644 --- a/packages/ibkr/src/protobuf/RealTimeBarTick.ts +++ b/packages/ibkr/src/protobuf/RealTimeBarTick.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: RealTimeBarTick.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/RealTimeBarsRequest.ts b/packages/ibkr/src/protobuf/RealTimeBarsRequest.ts index e33197cd..1692bd10 100644 --- a/packages/ibkr/src/protobuf/RealTimeBarsRequest.ts +++ b/packages/ibkr/src/protobuf/RealTimeBarsRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: RealTimeBarsRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ReceiveFA.ts b/packages/ibkr/src/protobuf/ReceiveFA.ts index 35487721..883f092b 100644 --- a/packages/ibkr/src/protobuf/ReceiveFA.ts +++ b/packages/ibkr/src/protobuf/ReceiveFA.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ReceiveFA.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ReplaceFAEnd.ts b/packages/ibkr/src/protobuf/ReplaceFAEnd.ts index 0204a246..c05a644c 100644 --- a/packages/ibkr/src/protobuf/ReplaceFAEnd.ts +++ b/packages/ibkr/src/protobuf/ReplaceFAEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ReplaceFAEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/RerouteMarketDataRequest.ts b/packages/ibkr/src/protobuf/RerouteMarketDataRequest.ts index 7dba1e5f..bd617774 100644 --- a/packages/ibkr/src/protobuf/RerouteMarketDataRequest.ts +++ b/packages/ibkr/src/protobuf/RerouteMarketDataRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: RerouteMarketDataRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/RerouteMarketDepthRequest.ts b/packages/ibkr/src/protobuf/RerouteMarketDepthRequest.ts index 3c2602d6..1070335c 100644 --- a/packages/ibkr/src/protobuf/RerouteMarketDepthRequest.ts +++ b/packages/ibkr/src/protobuf/RerouteMarketDepthRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: RerouteMarketDepthRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ScannerData.ts b/packages/ibkr/src/protobuf/ScannerData.ts index f0abfce3..ad47a3c5 100644 --- a/packages/ibkr/src/protobuf/ScannerData.ts +++ b/packages/ibkr/src/protobuf/ScannerData.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ScannerData.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ScannerDataElement } from "./ScannerDataElement"; +import { ScannerDataElement } from "./ScannerDataElement.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ScannerDataElement.ts b/packages/ibkr/src/protobuf/ScannerDataElement.ts index 17987e2b..5dd5bc64 100644 --- a/packages/ibkr/src/protobuf/ScannerDataElement.ts +++ b/packages/ibkr/src/protobuf/ScannerDataElement.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ScannerDataElement.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/ScannerParameters.ts b/packages/ibkr/src/protobuf/ScannerParameters.ts index 78ee0381..ad810729 100644 --- a/packages/ibkr/src/protobuf/ScannerParameters.ts +++ b/packages/ibkr/src/protobuf/ScannerParameters.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ScannerParameters.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ScannerParametersRequest.ts b/packages/ibkr/src/protobuf/ScannerParametersRequest.ts index 540eb609..d29f992c 100644 --- a/packages/ibkr/src/protobuf/ScannerParametersRequest.ts +++ b/packages/ibkr/src/protobuf/ScannerParametersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ScannerParametersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ScannerSubscription.ts b/packages/ibkr/src/protobuf/ScannerSubscription.ts index 179d096a..97ff57f0 100644 --- a/packages/ibkr/src/protobuf/ScannerSubscription.ts +++ b/packages/ibkr/src/protobuf/ScannerSubscription.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ScannerSubscription.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/ScannerSubscriptionRequest.ts b/packages/ibkr/src/protobuf/ScannerSubscriptionRequest.ts index bbc86181..e3599372 100644 --- a/packages/ibkr/src/protobuf/ScannerSubscriptionRequest.ts +++ b/packages/ibkr/src/protobuf/ScannerSubscriptionRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: ScannerSubscriptionRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ScannerSubscription } from "./ScannerSubscription"; +import { ScannerSubscription } from "./ScannerSubscription.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/SecDefOptParameter.ts b/packages/ibkr/src/protobuf/SecDefOptParameter.ts index a2878815..d4a21298 100644 --- a/packages/ibkr/src/protobuf/SecDefOptParameter.ts +++ b/packages/ibkr/src/protobuf/SecDefOptParameter.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SecDefOptParameter.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SecDefOptParameterEnd.ts b/packages/ibkr/src/protobuf/SecDefOptParameterEnd.ts index 42f4ea26..0806b6bc 100644 --- a/packages/ibkr/src/protobuf/SecDefOptParameterEnd.ts +++ b/packages/ibkr/src/protobuf/SecDefOptParameterEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SecDefOptParameterEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SecDefOptParamsRequest.ts b/packages/ibkr/src/protobuf/SecDefOptParamsRequest.ts index 5410bdf9..350928ed 100644 --- a/packages/ibkr/src/protobuf/SecDefOptParamsRequest.ts +++ b/packages/ibkr/src/protobuf/SecDefOptParamsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SecDefOptParamsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SetServerLogLevelRequest.ts b/packages/ibkr/src/protobuf/SetServerLogLevelRequest.ts index ea93185e..2a919979 100644 --- a/packages/ibkr/src/protobuf/SetServerLogLevelRequest.ts +++ b/packages/ibkr/src/protobuf/SetServerLogLevelRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SetServerLogLevelRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SmartComponent.ts b/packages/ibkr/src/protobuf/SmartComponent.ts index db381e0e..62551309 100644 --- a/packages/ibkr/src/protobuf/SmartComponent.ts +++ b/packages/ibkr/src/protobuf/SmartComponent.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SmartComponent.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SmartComponents.ts b/packages/ibkr/src/protobuf/SmartComponents.ts index ab619b37..1bf9a851 100644 --- a/packages/ibkr/src/protobuf/SmartComponents.ts +++ b/packages/ibkr/src/protobuf/SmartComponents.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SmartComponents.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { SmartComponent } from "./SmartComponent"; +import { SmartComponent } from "./SmartComponent.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/SmartComponentsRequest.ts b/packages/ibkr/src/protobuf/SmartComponentsRequest.ts index 528f4f04..41601785 100644 --- a/packages/ibkr/src/protobuf/SmartComponentsRequest.ts +++ b/packages/ibkr/src/protobuf/SmartComponentsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SmartComponentsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SoftDollarTier.ts b/packages/ibkr/src/protobuf/SoftDollarTier.ts index 5566d076..aa7fb4fb 100644 --- a/packages/ibkr/src/protobuf/SoftDollarTier.ts +++ b/packages/ibkr/src/protobuf/SoftDollarTier.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SoftDollarTier.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SoftDollarTiers.ts b/packages/ibkr/src/protobuf/SoftDollarTiers.ts index e8339dc6..e682d467 100644 --- a/packages/ibkr/src/protobuf/SoftDollarTiers.ts +++ b/packages/ibkr/src/protobuf/SoftDollarTiers.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SoftDollarTiers.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { SoftDollarTier } from "./SoftDollarTier"; +import { SoftDollarTier } from "./SoftDollarTier.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/SoftDollarTiersRequest.ts b/packages/ibkr/src/protobuf/SoftDollarTiersRequest.ts index abf8b8bd..d8543b78 100644 --- a/packages/ibkr/src/protobuf/SoftDollarTiersRequest.ts +++ b/packages/ibkr/src/protobuf/SoftDollarTiersRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SoftDollarTiersRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/StartApiRequest.ts b/packages/ibkr/src/protobuf/StartApiRequest.ts index 770d9b49..a96bddca 100644 --- a/packages/ibkr/src/protobuf/StartApiRequest.ts +++ b/packages/ibkr/src/protobuf/StartApiRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: StartApiRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SubscribeToGroupEventsRequest.ts b/packages/ibkr/src/protobuf/SubscribeToGroupEventsRequest.ts index 2d25601b..15a24e59 100644 --- a/packages/ibkr/src/protobuf/SubscribeToGroupEventsRequest.ts +++ b/packages/ibkr/src/protobuf/SubscribeToGroupEventsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SubscribeToGroupEventsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/SymbolSamples.ts b/packages/ibkr/src/protobuf/SymbolSamples.ts index 7ec3fdf5..de14a446 100644 --- a/packages/ibkr/src/protobuf/SymbolSamples.ts +++ b/packages/ibkr/src/protobuf/SymbolSamples.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: SymbolSamples.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ContractDescription } from "./ContractDescription"; +import { ContractDescription } from "./ContractDescription.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/TickAttribBidAsk.ts b/packages/ibkr/src/protobuf/TickAttribBidAsk.ts index e4b1e471..defc71ef 100644 --- a/packages/ibkr/src/protobuf/TickAttribBidAsk.ts +++ b/packages/ibkr/src/protobuf/TickAttribBidAsk.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickAttribBidAsk.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickAttribLast.ts b/packages/ibkr/src/protobuf/TickAttribLast.ts index 119c795a..3c00b0d6 100644 --- a/packages/ibkr/src/protobuf/TickAttribLast.ts +++ b/packages/ibkr/src/protobuf/TickAttribLast.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickAttribLast.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickByTickData.ts b/packages/ibkr/src/protobuf/TickByTickData.ts index 579b50a6..adea05bf 100644 --- a/packages/ibkr/src/protobuf/TickByTickData.ts +++ b/packages/ibkr/src/protobuf/TickByTickData.ts @@ -1,14 +1,14 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickByTickData.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { HistoricalTick } from "./HistoricalTick"; -import { HistoricalTickBidAsk } from "./HistoricalTickBidAsk"; -import { HistoricalTickLast } from "./HistoricalTickLast"; +import { HistoricalTick } from "./HistoricalTick.js"; +import { HistoricalTickBidAsk } from "./HistoricalTickBidAsk.js"; +import { HistoricalTickLast } from "./HistoricalTickLast.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/TickByTickRequest.ts b/packages/ibkr/src/protobuf/TickByTickRequest.ts index d3bb45ec..9bdeb4f7 100644 --- a/packages/ibkr/src/protobuf/TickByTickRequest.ts +++ b/packages/ibkr/src/protobuf/TickByTickRequest.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickByTickRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { Contract } from "./Contract"; +import { Contract } from "./Contract.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/TickGeneric.ts b/packages/ibkr/src/protobuf/TickGeneric.ts index 28832bd4..fc289618 100644 --- a/packages/ibkr/src/protobuf/TickGeneric.ts +++ b/packages/ibkr/src/protobuf/TickGeneric.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickGeneric.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickNews.ts b/packages/ibkr/src/protobuf/TickNews.ts index 473668aa..2206b6e1 100644 --- a/packages/ibkr/src/protobuf/TickNews.ts +++ b/packages/ibkr/src/protobuf/TickNews.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickNews.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickOptionComputation.ts b/packages/ibkr/src/protobuf/TickOptionComputation.ts index db5d9715..608a7858 100644 --- a/packages/ibkr/src/protobuf/TickOptionComputation.ts +++ b/packages/ibkr/src/protobuf/TickOptionComputation.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickOptionComputation.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickPrice.ts b/packages/ibkr/src/protobuf/TickPrice.ts index 46067cbc..840fa9f9 100644 --- a/packages/ibkr/src/protobuf/TickPrice.ts +++ b/packages/ibkr/src/protobuf/TickPrice.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickPrice.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickReqParams.ts b/packages/ibkr/src/protobuf/TickReqParams.ts index 1475a181..08e38d9e 100644 --- a/packages/ibkr/src/protobuf/TickReqParams.ts +++ b/packages/ibkr/src/protobuf/TickReqParams.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickReqParams.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickSize.ts b/packages/ibkr/src/protobuf/TickSize.ts index 17b1e6d5..a549767d 100644 --- a/packages/ibkr/src/protobuf/TickSize.ts +++ b/packages/ibkr/src/protobuf/TickSize.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickSize.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickSnapshotEnd.ts b/packages/ibkr/src/protobuf/TickSnapshotEnd.ts index 034a7b9e..21538cb4 100644 --- a/packages/ibkr/src/protobuf/TickSnapshotEnd.ts +++ b/packages/ibkr/src/protobuf/TickSnapshotEnd.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickSnapshotEnd.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/TickString.ts b/packages/ibkr/src/protobuf/TickString.ts index f5a76eaa..73e4ba50 100644 --- a/packages/ibkr/src/protobuf/TickString.ts +++ b/packages/ibkr/src/protobuf/TickString.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: TickString.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/UnsubscribeFromGroupEventsRequest.ts b/packages/ibkr/src/protobuf/UnsubscribeFromGroupEventsRequest.ts index f6c587a2..ffef3bf5 100644 --- a/packages/ibkr/src/protobuf/UnsubscribeFromGroupEventsRequest.ts +++ b/packages/ibkr/src/protobuf/UnsubscribeFromGroupEventsRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UnsubscribeFromGroupEventsRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/UpdateConfigRequest.ts b/packages/ibkr/src/protobuf/UpdateConfigRequest.ts index 38b7696c..6c4fa089 100644 --- a/packages/ibkr/src/protobuf/UpdateConfigRequest.ts +++ b/packages/ibkr/src/protobuf/UpdateConfigRequest.ts @@ -1,16 +1,16 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UpdateConfigRequest.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { ApiConfig } from "./ApiConfig"; -import { LockAndExitConfig } from "./LockAndExitConfig"; -import { MessageConfig } from "./MessageConfig"; -import { OrdersConfig } from "./OrdersConfig"; -import { UpdateConfigWarning } from "./UpdateConfigWarning"; +import { ApiConfig } from "./ApiConfig.js"; +import { LockAndExitConfig } from "./LockAndExitConfig.js"; +import { MessageConfig } from "./MessageConfig.js"; +import { OrdersConfig } from "./OrdersConfig.js"; +import { UpdateConfigWarning } from "./UpdateConfigWarning.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/UpdateConfigResponse.ts b/packages/ibkr/src/protobuf/UpdateConfigResponse.ts index 6ce1fb48..1a93bdcb 100644 --- a/packages/ibkr/src/protobuf/UpdateConfigResponse.ts +++ b/packages/ibkr/src/protobuf/UpdateConfigResponse.ts @@ -1,12 +1,12 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UpdateConfigResponse.proto /* eslint-disable */ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { UpdateConfigWarning } from "./UpdateConfigWarning"; +import { UpdateConfigWarning } from "./UpdateConfigWarning.js"; export const protobufPackage = "protobuf"; diff --git a/packages/ibkr/src/protobuf/UpdateConfigWarning.ts b/packages/ibkr/src/protobuf/UpdateConfigWarning.ts index 8cf9a989..3fc26a8d 100644 --- a/packages/ibkr/src/protobuf/UpdateConfigWarning.ts +++ b/packages/ibkr/src/protobuf/UpdateConfigWarning.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UpdateConfigWarning.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/UpdateDisplayGroupRequest.ts b/packages/ibkr/src/protobuf/UpdateDisplayGroupRequest.ts index 3765321f..41fb8dfe 100644 --- a/packages/ibkr/src/protobuf/UpdateDisplayGroupRequest.ts +++ b/packages/ibkr/src/protobuf/UpdateDisplayGroupRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UpdateDisplayGroupRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/UserInfo.ts b/packages/ibkr/src/protobuf/UserInfo.ts index 1c0b0973..d79ce001 100644 --- a/packages/ibkr/src/protobuf/UserInfo.ts +++ b/packages/ibkr/src/protobuf/UserInfo.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UserInfo.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/UserInfoRequest.ts b/packages/ibkr/src/protobuf/UserInfoRequest.ts index 205bf2e2..00b61772 100644 --- a/packages/ibkr/src/protobuf/UserInfoRequest.ts +++ b/packages/ibkr/src/protobuf/UserInfoRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: UserInfoRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/VerifyCompleted.ts b/packages/ibkr/src/protobuf/VerifyCompleted.ts index a638f9b4..cb483669 100644 --- a/packages/ibkr/src/protobuf/VerifyCompleted.ts +++ b/packages/ibkr/src/protobuf/VerifyCompleted.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: VerifyCompleted.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/VerifyMessageApi.ts b/packages/ibkr/src/protobuf/VerifyMessageApi.ts index 66c8d9ba..f27e1e5c 100644 --- a/packages/ibkr/src/protobuf/VerifyMessageApi.ts +++ b/packages/ibkr/src/protobuf/VerifyMessageApi.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: VerifyMessageApi.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/VerifyMessageRequest.ts b/packages/ibkr/src/protobuf/VerifyMessageRequest.ts index f4eaf0ff..9eaa1c1a 100644 --- a/packages/ibkr/src/protobuf/VerifyMessageRequest.ts +++ b/packages/ibkr/src/protobuf/VerifyMessageRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: VerifyMessageRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/VerifyRequest.ts b/packages/ibkr/src/protobuf/VerifyRequest.ts index 5e97bb95..1987b8cb 100644 --- a/packages/ibkr/src/protobuf/VerifyRequest.ts +++ b/packages/ibkr/src/protobuf/VerifyRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: VerifyRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/WshEventData.ts b/packages/ibkr/src/protobuf/WshEventData.ts index cfa5f7f9..c9d67eba 100644 --- a/packages/ibkr/src/protobuf/WshEventData.ts +++ b/packages/ibkr/src/protobuf/WshEventData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: WshEventData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/WshEventDataRequest.ts b/packages/ibkr/src/protobuf/WshEventDataRequest.ts index 73bf4284..4f37f3fc 100644 --- a/packages/ibkr/src/protobuf/WshEventDataRequest.ts +++ b/packages/ibkr/src/protobuf/WshEventDataRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: WshEventDataRequest.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/WshMetaData.ts b/packages/ibkr/src/protobuf/WshMetaData.ts index 69307e09..af0fd55e 100644 --- a/packages/ibkr/src/protobuf/WshMetaData.ts +++ b/packages/ibkr/src/protobuf/WshMetaData.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: WshMetaData.proto /* eslint-disable */ diff --git a/packages/ibkr/src/protobuf/WshMetaDataRequest.ts b/packages/ibkr/src/protobuf/WshMetaDataRequest.ts index 30b8426e..d2809345 100644 --- a/packages/ibkr/src/protobuf/WshMetaDataRequest.ts +++ b/packages/ibkr/src/protobuf/WshMetaDataRequest.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v7.34.0 +// protoc v7.34.1 // source: WshMetaDataRequest.proto /* eslint-disable */ diff --git a/packages/opentypebb/src/index.ts b/packages/opentypebb/src/index.ts index 7dddce4f..8848c451 100644 --- a/packages/opentypebb/src/index.ts +++ b/packages/opentypebb/src/index.ts @@ -43,6 +43,9 @@ export { createRegistry, createExecutor, loadAllRouters } from './core/api/app-l export { buildWidgetsJson } from './core/api/widgets.js' export { mountWidgetsEndpoint } from './core/api/rest-api.js' +// Standard models — data types for all asset classes +export * from './standard-models/index.js' + // Pre-built providers (for direct import if needed) export { fmpProvider } from './providers/fmp/index.js' export { yfinanceProvider } from './providers/yfinance/index.js' diff --git a/packages/opentypebb/src/providers/fmp/index.ts b/packages/opentypebb/src/providers/fmp/index.ts index fd6cb0d8..5fa0a177 100644 --- a/packages/opentypebb/src/providers/fmp/index.ts +++ b/packages/opentypebb/src/providers/fmp/index.ts @@ -71,6 +71,8 @@ import { FMPEarningsCallTranscriptFetcher } from './models/earnings-call-transcr import { FMPDiscoveryFilingsFetcher } from './models/discovery-filings.js' import { FMPEsgScoreFetcher } from './models/esg-score.js' import { FMPHistoricalMarketCapFetcher } from './models/historical-market-cap.js' +import { FMPEquitySearchFetcher } from './models/equity-search.js' +import { FMPCommoditySpotPriceFetcher } from './models/commodity-spot-price.js' export const fmpProvider = new Provider({ name: 'fmp', @@ -130,6 +132,7 @@ export const fmpProvider = new Provider({ HistoricalEmployees: FMPHistoricalEmployeesFetcher, ShareStatistics: FMPShareStatisticsFetcher, EquityPeers: FMPEquityPeersFetcher, + EquitySearch: FMPEquitySearchFetcher, EquityScreener: FMPEquityScreenerFetcher, CompanyFilings: FMPCompanyFilingsFetcher, PricePerformance: FMPPricePerformanceFetcher, @@ -146,5 +149,6 @@ export const fmpProvider = new Provider({ DiscoveryFilings: FMPDiscoveryFilingsFetcher, EsgScore: FMPEsgScoreFetcher, HistoricalMarketCap: FMPHistoricalMarketCapFetcher, + CommoditySpotPrice: FMPCommoditySpotPriceFetcher, }, }) diff --git a/packages/opentypebb/src/providers/fmp/models/commodity-spot-price.ts b/packages/opentypebb/src/providers/fmp/models/commodity-spot-price.ts new file mode 100644 index 00000000..3b39e85a --- /dev/null +++ b/packages/opentypebb/src/providers/fmp/models/commodity-spot-price.ts @@ -0,0 +1,76 @@ +/** + * FMP Commodity Spot Price Model. + * + * Uses the same /stable/historical-price-eod/full endpoint as equities — + * FMP treats commodity futures symbols (GCUSD, CLUSD, etc.) identically. + */ + +import { z } from 'zod' +import { Fetcher } from '../../../core/provider/abstract/fetcher.js' +import { CommoditySpotPriceQueryParamsSchema, CommoditySpotPriceDataSchema } from '../../../standard-models/commodity-spot-price.js' +import { getHistoricalOhlc } from '../utils/helpers.js' +import { EmptyDataError } from '../../../core/provider/utils/errors.js' + +export const FMPCommoditySpotPriceQueryParamsSchema = CommoditySpotPriceQueryParamsSchema +export type FMPCommoditySpotPriceQueryParams = z.infer + +export const FMPCommoditySpotPriceDataSchema = CommoditySpotPriceDataSchema.extend({ + vwap: z.number().nullable().default(null).describe('Volume-weighted average price.'), + change: z.number().nullable().default(null).describe('Change from previous close.'), + change_percent: z.number().nullable().default(null).describe('Change percent from previous close.'), +}).passthrough() +export type FMPCommoditySpotPriceData = z.infer + +export class FMPCommoditySpotPriceFetcher extends Fetcher { + static override transformQuery(params: Record): FMPCommoditySpotPriceQueryParams { + const now = new Date() + if (!params.start_date) { + const oneYearAgo = new Date(now) + oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1) + params.start_date = oneYearAgo.toISOString().split('T')[0] + } + if (!params.end_date) { + params.end_date = now.toISOString().split('T')[0] + } + return FMPCommoditySpotPriceQueryParamsSchema.parse(params) + } + + static override async extractData( + query: FMPCommoditySpotPriceQueryParams, + credentials: Record | null, + ): Promise[]> { + return getHistoricalOhlc( + { + symbol: query.symbol, + interval: '1d', + start_date: query.start_date, + end_date: query.end_date, + }, + credentials, + ) + } + + static override transformData( + query: FMPCommoditySpotPriceQueryParams, + data: Record[], + ): FMPCommoditySpotPriceData[] { + if (!data || data.length === 0) { + throw new EmptyDataError() + } + + for (const d of data) { + if (typeof d.changePercentage === 'number') { + d.change_percent = d.changePercentage / 100 + delete d.changePercentage + } + } + + const sorted = data.sort((a, b) => { + const da = String(a.date ?? '') + const db = String(b.date ?? '') + return da.localeCompare(db) + }) + + return sorted.map(d => FMPCommoditySpotPriceDataSchema.parse(d)) + } +} diff --git a/packages/opentypebb/src/providers/fmp/models/currency-pairs.ts b/packages/opentypebb/src/providers/fmp/models/currency-pairs.ts index 50507958..3b245052 100644 --- a/packages/opentypebb/src/providers/fmp/models/currency-pairs.ts +++ b/packages/opentypebb/src/providers/fmp/models/currency-pairs.ts @@ -7,8 +7,16 @@ import { z } from 'zod' import { Fetcher } from '../../../core/provider/abstract/fetcher.js' import { CurrencyPairsQueryParamsSchema, CurrencyPairsDataSchema } from '../../../standard-models/currency-pairs.js' import { EmptyDataError } from '../../../core/provider/utils/errors.js' +import { applyAliases } from '../../../core/provider/utils/helpers.js' import { getDataMany } from '../utils/helpers.js' +const ALIAS_DICT: Record = { + from_currency: 'fromCurrency', + to_currency: 'toCurrency', + from_name: 'fromName', + to_name: 'toName', +} + export const FMPCurrencyPairsQueryParamsSchema = CurrencyPairsQueryParamsSchema export type FMPCurrencyPairsQueryParams = z.infer @@ -57,6 +65,6 @@ export class FMPCurrencyPairsFetcher extends Fetcher { throw new EmptyDataError(`No results were found with the query supplied. -> ${query.query}`) } - return filtered.map((d) => FMPCurrencyPairsDataSchema.parse(d)) + return filtered.map((d) => FMPCurrencyPairsDataSchema.parse(applyAliases(d, ALIAS_DICT))) } } diff --git a/packages/opentypebb/src/providers/fmp/models/equity-profile.ts b/packages/opentypebb/src/providers/fmp/models/equity-profile.ts index 3052c98b..51896eb9 100644 --- a/packages/opentypebb/src/providers/fmp/models/equity-profile.ts +++ b/packages/opentypebb/src/providers/fmp/models/equity-profile.ts @@ -39,10 +39,10 @@ const ALIAS_DICT: Record = { } export const FMPEquityProfileDataSchema = EquityInfoDataSchema.extend({ - is_etf: z.boolean().describe('If the symbol is an ETF.'), - is_actively_trading: z.boolean().describe('If the company is actively trading.'), - is_adr: z.boolean().describe('If the stock is an ADR.'), - is_fund: z.boolean().describe('If the company is a fund.'), + is_etf: z.boolean().default(false).describe('If the symbol is an ETF.'), + is_actively_trading: z.boolean().default(true).describe('If the company is actively trading.'), + is_adr: z.boolean().default(false).describe('If the stock is an ADR.'), + is_fund: z.boolean().default(false).describe('If the company is a fund.'), image: z.string().nullable().default(null).describe('Image of the company.'), currency: z.string().nullable().default(null).describe('Currency in which the stock is traded.'), market_cap: z.number().nullable().default(null).describe('Market capitalization of the company.'), @@ -114,6 +114,8 @@ export class FMPEquityProfileFetcher extends Fetcher { } const cleaned = replaceEmptyStrings(d) const aliased = applyAliases(cleaned, ALIAS_DICT) + // FMP returns employees as string — coerce to number + if (typeof aliased.employees === 'string') aliased.employees = parseInt(aliased.employees, 10) || null return FMPEquityProfileDataSchema.parse(aliased) }) } diff --git a/packages/opentypebb/src/providers/fmp/models/equity-search.ts b/packages/opentypebb/src/providers/fmp/models/equity-search.ts new file mode 100644 index 00000000..c8d21e3a --- /dev/null +++ b/packages/opentypebb/src/providers/fmp/models/equity-search.ts @@ -0,0 +1,59 @@ +/** + * FMP Equity Search Model. + * + * Uses FMP's /stable/search-name endpoint to search equities by name or symbol. + */ + +import { z } from 'zod' +import { Fetcher } from '../../../core/provider/abstract/fetcher.js' +import { EquitySearchQueryParamsSchema, EquitySearchDataSchema } from '../../../standard-models/equity-search.js' +import { EmptyDataError } from '../../../core/provider/utils/errors.js' +import { amakeRequest } from '../../../core/provider/utils/helpers.js' +import { responseCallback } from '../utils/helpers.js' + +export const FMPEquitySearchQueryParamsSchema = EquitySearchQueryParamsSchema +export type FMPEquitySearchQueryParams = z.infer + +export const FMPEquitySearchDataSchema = EquitySearchDataSchema.extend({ + currency: z.string().nullable().default(null).describe('Currency the equity trades in.'), + exchange: z.string().nullable().default(null).describe('Exchange code.'), + exchange_name: z.string().nullable().default(null).describe('Full exchange name.'), +}).passthrough() +export type FMPEquitySearchData = z.infer + +const ALIAS_DICT: Record = { + exchange_name: 'exchangeFullName', +} + +export class FMPEquitySearchFetcher extends Fetcher { + static override transformQuery(params: Record): FMPEquitySearchQueryParams { + return FMPEquitySearchQueryParamsSchema.parse(params) + } + + static override async extractData( + query: FMPEquitySearchQueryParams, + credentials: Record | null, + ): Promise[]> { + const apiKey = credentials?.fmp_api_key ?? '' + const q = encodeURIComponent(query.query) + const url = `https://financialmodelingprep.com/stable/search-name?query=${q}&apikey=${apiKey}` + return amakeRequest[]>(url, { responseCallback }) + } + + static override transformData( + query: FMPEquitySearchQueryParams, + data: Record[], + ): FMPEquitySearchData[] { + if (!data || data.length === 0) { + throw new EmptyDataError('No results found for the search query.') + } + return data.map((d) => { + // Alias exchangeFullName → exchange_name + if (d.exchangeFullName && !d.exchange_name) { + d.exchange_name = d.exchangeFullName + delete d.exchangeFullName + } + return FMPEquitySearchDataSchema.parse(d) + }) + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60ec16a6..62877d53 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,6 +133,9 @@ importers: tsx: specifier: ^4.21.0 version: 4.21.0 + turbo: + specifier: ^2.9.3 + version: 2.9.3 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -1293,6 +1296,36 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@turbo/darwin-64@2.9.3': + resolution: {integrity: sha512-P8foouaP+y/p+hhEGBoZpzMbpVvUMwPjDpcy6wN7EYfvvyISD1USuV27qWkczecihwuPJzQ1lDBuL8ERcavTyg==} + cpu: [x64] + os: [darwin] + + '@turbo/darwin-arm64@2.9.3': + resolution: {integrity: sha512-SIzEkvtNdzdI50FJDaIQ6kQGqgSSdFPcdn0wqmmONN6iGKjy6hsT+EH99GP65FsfV7DLZTh2NmtTIRl2kdoz5Q==} + cpu: [arm64] + os: [darwin] + + '@turbo/linux-64@2.9.3': + resolution: {integrity: sha512-pLRwFmcHHNBvsCySLS6OFabr/07kDT2pxEt/k6eBf/3asiVQZKJ7Rk88AafQx2aYA641qek4RsXvYO3JYpiBug==} + cpu: [x64] + os: [linux] + + '@turbo/linux-arm64@2.9.3': + resolution: {integrity: sha512-gy6ApUroC2Nzv+qjGtE/uPNkhHAFU4c8God+zd5Aiv9L9uBgHlxVJpHT3XWl5xwlJZ2KWuMrlHTaS5kmNB+q1Q==} + cpu: [arm64] + os: [linux] + + '@turbo/windows-64@2.9.3': + resolution: {integrity: sha512-d0YelTX6hAsB7kIEtGB3PzIzSfAg3yDoUlHwuwJc3adBXUsyUIs0YLG+1NNtuhcDOUGnWQeKUoJ2pGWvbpRj7w==} + cpu: [x64] + os: [win32] + + '@turbo/windows-arm64@2.9.3': + resolution: {integrity: sha512-/08CwpKJl3oRY8nOlh2YgilZVJDHsr60XTNxRhuDeuFXONpUZ5X+Nv65izbG/xBew9qxcJFbDX9/sAmAX+ITcQ==} + cpu: [arm64] + os: [win32] + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -2834,6 +2867,10 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + turbo@2.9.3: + resolution: {integrity: sha512-J/VUvsGRykPb9R8Kh8dHVBOqioDexLk9BhLCU/ZybRR+HN9UR3cURdazFvNgMDt9zPP8TF6K73Z+tplfmi0PqQ==} + hasBin: true + tweetnacl@1.0.3: resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} @@ -3914,6 +3951,24 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@turbo/darwin-64@2.9.3': + optional: true + + '@turbo/darwin-arm64@2.9.3': + optional: true + + '@turbo/linux-64@2.9.3': + optional: true + + '@turbo/linux-arm64@2.9.3': + optional: true + + '@turbo/windows-64@2.9.3': + optional: true + + '@turbo/windows-arm64@2.9.3': + optional: true + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -5522,6 +5577,15 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + turbo@2.9.3: + optionalDependencies: + '@turbo/darwin-64': 2.9.3 + '@turbo/darwin-arm64': 2.9.3 + '@turbo/linux-64': 2.9.3 + '@turbo/linux-arm64': 2.9.3 + '@turbo/windows-64': 2.9.3 + '@turbo/windows-arm64': 2.9.3 + tweetnacl@1.0.3: {} type-is@2.0.1: diff --git a/src/ai-providers/agent-sdk/tool-bridge.ts b/src/ai-providers/agent-sdk/tool-bridge.ts index 9b424801..fded8f7b 100644 --- a/src/ai-providers/agent-sdk/tool-bridge.ts +++ b/src/ai-providers/agent-sdk/tool-bridge.ts @@ -1,47 +1,13 @@ /** * Tool bridge — converts ToolCenter's Vercel AI SDK tools to an Agent SDK MCP server. * - * Reuses the same pattern as `src/server/mcp.ts` (extract .shape, wrap execute), - * but targets `createSdkMcpServer()` instead of `@modelcontextprotocol/sdk McpServer`. + * Uses shared MCP export utilities from `core/mcp-export.ts` for schema extraction + * (with number coercion) and execute wrapping. */ -import { randomUUID } from 'node:crypto' import { tool, createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk' import type { Tool } from 'ai' - -type McpContent = - | { type: 'text'; text: string } - | { type: 'image'; data: string; mimeType: string } - -/** - * Convert a Vercel AI SDK tool result to MCP content blocks. - * Handles both plain values and OpenClaw AgentToolResult `{ content: [...] }` format. - */ -function toMcpContent(result: unknown): McpContent[] { - if ( - result != null && - typeof result === 'object' && - 'content' in result && - Array.isArray((result as { content: unknown }).content) - ) { - const items = (result as { content: Array> }).content - const blocks: McpContent[] = [] - for (const item of items) { - if (item.type === 'image' && typeof item.data === 'string' && typeof item.mimeType === 'string') { - blocks.push({ type: 'image', data: item.data, mimeType: item.mimeType }) - } else if (item.type === 'text' && typeof item.text === 'string') { - blocks.push({ type: 'text', text: item.text }) - } else { - blocks.push({ type: 'text', text: JSON.stringify(item) }) - } - } - if ('details' in result && (result as { details: unknown }).details != null) { - blocks.push({ type: 'text', text: JSON.stringify((result as { details: unknown }).details) }) - } - return blocks.length > 0 ? blocks : [{ type: 'text', text: JSON.stringify(result) }] - } - return [{ type: 'text', text: JSON.stringify(result) }] -} +import { extractMcpShape, wrapToolExecute } from '../../core/mcp-export.js' /** * Build an Agent SDK MCP server from a Vercel AI SDK tool map. @@ -59,23 +25,7 @@ export function buildAgentSdkMcpServer( const sdkTools = Object.entries(tools) .filter(([name, t]) => t.execute && !disabledSet.has(name)) .map(([name, t]) => { - // Extract Zod raw shape — same approach as mcp.ts line 76 - const shape = (t.inputSchema as any)?.shape ?? {} - - return tool(name, t.description ?? name, shape, async (args: any) => { - try { - const result = await t.execute!(args, { - toolCallId: randomUUID(), - messages: [], - }) - return { content: toMcpContent(result) } - } catch (err) { - return { - content: [{ type: 'text' as const, text: `Error: ${err}` }], - isError: true, - } - } - }) + return tool(name, t.description ?? name, extractMcpShape(t), wrapToolExecute(t)) }) return createSdkMcpServer({ name: 'open-alice', tools: sdkTools }) diff --git a/src/connectors/web/routes/config.ts b/src/connectors/web/routes/config.ts index f2dfce43..0a9738fd 100644 --- a/src/connectors/web/routes/config.ts +++ b/src/connectors/web/routes/config.ts @@ -1,5 +1,6 @@ import { Hono } from 'hono' -import { loadConfig, writeConfigSection, readAIProviderConfig, readMarketDataConfig, validSections, writeAIBackend, type ConfigSection, type AIBackend } from '../../../core/config.js' +import { loadConfig, writeConfigSection, readAIProviderConfig, validSections, writeAIBackend, type ConfigSection, type AIBackend } from '../../../core/config.js' +import type { EngineContext } from '../../../core/types.js' interface ConfigRouteOpts { onConnectorsChange?: () => Promise @@ -70,16 +71,16 @@ export function createConfigRoutes(opts?: ConfigRouteOpts) { } /** Market data routes: POST /test-provider */ -export function createMarketDataRoutes() { - const TEST_ENDPOINTS: Record = { - fred: { credField: 'fred_api_key', path: '/api/v1/economy/fred_search?query=GDP&provider=federal_reserve' }, - bls: { credField: 'bls_api_key', path: '/api/v1/economy/survey/bls_search?query=unemployment&provider=bls' }, - eia: { credField: 'eia_api_key', path: '/api/v1/commodity/short_term_energy_outlook?provider=eia' }, - econdb: { credField: 'econdb_api_key', path: '/api/v1/economy/available_indicators?provider=econdb' }, - fmp: { credField: 'fmp_api_key', path: '/api/v1/equity/screener?provider=fmp&limit=1' }, - nasdaq: { credField: 'nasdaq_api_key', path: '/api/v1/equity/search?query=AAPL&provider=nasdaq&is_symbol=true' }, - intrinio: { credField: 'intrinio_api_key', path: '/api/v1/equity/search?query=AAPL&provider=intrinio&limit=1' }, - tradingeconomics: { credField: 'tradingeconomics_api_key', path: '/api/v1/economy/calendar?provider=tradingeconomics' }, +export function createMarketDataRoutes(ctx: EngineContext) { + const TEST_ENDPOINTS: Record }> = { + fred: { credField: 'fred_api_key', provider: 'fred', model: 'FredSearch', params: { query: 'GDP' } }, + bls: { credField: 'bls_api_key', provider: 'bls', model: 'BlsSearch', params: { query: 'unemployment' } }, + eia: { credField: 'eia_api_key', provider: 'eia', model: 'ShortTermEnergyOutlook', params: {} }, + econdb: { credField: 'econdb_api_key', provider: 'econdb', model: 'AvailableIndicators', params: {} }, + fmp: { credField: 'fmp_api_key', provider: 'fmp', model: 'EquityScreener', params: { limit: 1 } }, + nasdaq: { credField: 'nasdaq_api_key', provider: 'nasdaq', model: 'EquitySearch', params: { query: 'AAPL', is_symbol: true } }, + intrinio: { credField: 'intrinio_api_key', provider: 'intrinio', model: 'EquitySearch', params: { query: 'AAPL', limit: 1 } }, + tradingeconomics: { credField: 'tradingeconomics_api_key', provider: 'tradingeconomics', model: 'EconomicCalendar', params: {} }, } const app = new Hono() @@ -91,30 +92,16 @@ export function createMarketDataRoutes() { if (!endpoint) return c.json({ ok: false, error: `Unknown provider: ${provider}` }, 400) if (!key) return c.json({ ok: false, error: 'No API key provided' }, 400) - const marketDataConfig = await readMarketDataConfig() - const creds: Record = { [endpoint.credField]: key } - // federal_reserve provider declares credentials: ['api_key'] but the - // canonical field is fred_api_key — include both so filterCredentials passes it through - if (endpoint.credField === 'fred_api_key') creds.api_key = key - const credHeader = JSON.stringify(creds) - // Use embedded API server if running typebb-sdk backend - const apiServerPort = marketDataConfig.apiServer?.port ?? 6901 - const baseUrl = marketDataConfig.backend === 'typebb-sdk' - ? `http://localhost:${apiServerPort}` - : marketDataConfig.apiUrl - const url = `${baseUrl}${endpoint.path}` - - const res = await fetch(url, { - signal: AbortSignal.timeout(15_000), - headers: { 'X-OpenBB-Credentials': credHeader }, - }) - - if (res.ok) return c.json({ ok: true }) - const body = await res.text().catch(() => '') - return c.json({ ok: false, error: `OpenBB returned ${res.status}: ${body.slice(0, 200)}` }) + const result = await ctx.bbEngine.execute( + endpoint.provider, endpoint.model, endpoint.params, + { [endpoint.credField]: key }, + ) + const data = result as unknown[] + if (data && data.length > 0) return c.json({ ok: true }) + return c.json({ ok: false, error: 'API returned empty data — key may be invalid or endpoint restricted' }) } catch (err) { const msg = err instanceof Error ? err.message : String(err) - return c.json({ ok: false, error: msg.includes('timeout') ? 'Cannot reach OpenBB API' : msg }) + return c.json({ ok: false, error: msg }) } }) diff --git a/src/connectors/web/web-plugin.ts b/src/connectors/web/web-plugin.ts index d004c6b2..e134597c 100644 --- a/src/connectors/web/web-plugin.ts +++ b/src/connectors/web/web-plugin.ts @@ -75,7 +75,7 @@ export class WebPlugin implements Plugin { app.route('/api/config', createConfigRoutes({ onConnectorsChange: async () => { await ctx.reconnectConnectors() }, })) - app.route('/api/market-data', createMarketDataRoutes()) + app.route('/api/market-data', createMarketDataRoutes(ctx)) app.route('/api/events', createEventsRoutes(ctx)) app.route('/api/cron', createCronRoutes(ctx)) app.route('/api/heartbeat', createHeartbeatRoutes(ctx)) diff --git a/src/core/config.ts b/src/core/config.ts index 0e1c76dd..925cee3d 100644 --- a/src/core/config.ts +++ b/src/core/config.ts @@ -101,10 +101,12 @@ const marketDataSchema = z.object({ equity: z.string().default('yfinance'), crypto: z.string().default('yfinance'), currency: z.string().default('yfinance'), + commodity: z.string().default('yfinance'), }).default({ equity: 'yfinance', crypto: 'yfinance', currency: 'yfinance', + commodity: 'yfinance', }), providerKeys: z.object({ fred: z.string().optional(), diff --git a/src/core/mcp-export.ts b/src/core/mcp-export.ts new file mode 100644 index 00000000..9f78fd48 --- /dev/null +++ b/src/core/mcp-export.ts @@ -0,0 +1,130 @@ +/** + * MCP Export — shared bridge from Vercel AI SDK tools to MCP format. + * + * Used by both `src/server/mcp.ts` (external MCP server) and + * `src/ai-providers/agent-sdk/tool-bridge.ts` (Agent SDK in-process MCP). + * + * Handles: + * - Zod shape extraction with number coercion (MCP clients may send "80" instead of 80) + * - Tool result → MCP content block conversion + * - Execute wrapper (try/catch + toolCallId generation) + */ + +import { z } from 'zod' +import type { Tool } from 'ai' + +// ==================== Types ==================== + +export type McpContent = + | { type: 'text'; text: string } + | { type: 'image'; data: string; mimeType: string } + +export type McpToolResult = { + content: McpContent[] + isError?: boolean +} + +// ==================== Result conversion ==================== + +/** + * Convert a Vercel AI SDK tool result to MCP content blocks. + * + * If the result has a `.content` array (OpenClaw AgentToolResult format), + * map each item to native MCP text/image blocks. This avoids stringify-ing + * base64 image data into a giant JSON text blob. + * + * Otherwise, fall back to JSON.stringify. + */ +export function toMcpContent(result: unknown): McpContent[] { + if ( + result != null && + typeof result === 'object' && + 'content' in result && + Array.isArray((result as { content: unknown }).content) + ) { + const items = (result as { content: Array> }).content + const blocks: McpContent[] = [] + for (const item of items) { + if (item.type === 'image' && typeof item.data === 'string' && typeof item.mimeType === 'string') { + blocks.push({ type: 'image', data: item.data, mimeType: item.mimeType }) + } else if (item.type === 'text' && typeof item.text === 'string') { + blocks.push({ type: 'text', text: item.text }) + } else { + blocks.push({ type: 'text', text: JSON.stringify(item) }) + } + } + if ('details' in result && (result as { details: unknown }).details != null) { + blocks.push({ type: 'text', text: JSON.stringify((result as { details: unknown }).details) }) + } + return blocks.length > 0 ? blocks : [{ type: 'text', text: JSON.stringify(result) }] + } + return [{ type: 'text', text: JSON.stringify(result) }] +} + +// ==================== Schema coercion ==================== + +/** + * If the schema is a Zod v4 number type (possibly wrapped in optional), + * return a coerced copy that accepts string → number conversion. + * Preserves all refinements (int, positive, min, max, nonnegative). + * + * This is the MCP boundary adaptation: tool definitions stay strict, + * but MCP clients that send "80" instead of 80 won't be rejected. + */ +function coerceIfNumber(schema: z.ZodType): z.ZodType { + const def = (schema as any)._zod?.def + if (!def) return schema + + // z.number() / z.number().int().positive() etc. + if (def.type === 'number' && !def.coerce) { + let coerced: any = z.coerce.number() + if (def.checks?.length > 0) coerced = coerced.with(...def.checks) + return coerced + } + + // z.number().optional() + if (def.type === 'optional' && def.innerType?._zod?.def?.type === 'number' && !def.innerType._zod.def.coerce) { + let coerced: any = z.coerce.number() + const innerChecks = def.innerType._zod.def.checks + if (innerChecks?.length > 0) coerced = coerced.with(...innerChecks) + return coerced.optional() + } + + return schema +} + +/** + * Extract the Zod raw shape from a Vercel AI SDK tool's inputSchema, + * applying number coercion for MCP boundary safety. + */ +export function extractMcpShape(tool: Tool): Record { + const rawShape: Record = (tool.inputSchema as any)?.shape ?? {} + const coerced: Record = {} + for (const [key, schema] of Object.entries(rawShape)) { + coerced[key] = coerceIfNumber(schema) + } + return coerced +} + +// ==================== Execute wrapper ==================== + +/** + * Wrap a Vercel AI SDK tool's execute function for MCP consumption. + * Adds try/catch error handling and toolCallId generation. + */ +export function wrapToolExecute(tool: Tool): (args: any) => Promise { + return async (args: any) => { + try { + const result = await tool.execute!(args, { + toolCallId: crypto.randomUUID(), + messages: [], + }) + return { content: toMcpContent(result) } + } catch (err) { + return { + content: [{ type: 'text' as const, text: `Error: ${err}` }], + isError: true, + } + } + } +} diff --git a/src/core/types.ts b/src/core/types.ts index 744bad2c..4b9e1861 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -1,3 +1,4 @@ +import type { QueryExecutor } from '@traderalice/opentypebb' import type { AccountManager } from '../domain/trading/index.js' import type { SnapshotService } from '../domain/trading/snapshot/index.js' import type { CronEngine } from '../task/cron/engine.js' @@ -33,6 +34,9 @@ export interface EngineContext { cronEngine: CronEngine toolCenter: ToolCenter + // Market data + bbEngine: QueryExecutor + // Trading (unified account model) accountManager: AccountManager snapshotService?: SnapshotService diff --git a/src/domain/market-data/__tests__/bbProviders/fmp.bbProvider.spec.ts b/src/domain/market-data/__tests__/bbProviders/fmp.bbProvider.spec.ts new file mode 100644 index 00000000..a93d300a --- /dev/null +++ b/src/domain/market-data/__tests__/bbProviders/fmp.bbProvider.spec.ts @@ -0,0 +1,95 @@ +/** + * FMP bbProvider integration test. + * + * Verifies FMP fetchers can reach the API and return schema-compliant data. + * Requires fmp_api_key in config — skips all tests if not configured. + */ + +import { describe, it, expect, beforeAll, beforeEach } from 'vitest' +import { getTestContext, hasCredential, type TestContext } from './setup.js' + +let ctx: TestContext + +beforeAll(async () => { ctx = await getTestContext() }) + +const exec = (model: string, params: Record = {}) => + ctx.executor.execute('fmp', model, params, ctx.credentials) + +describe('fmp — equity', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('EquityHistorical', async () => { expect((await exec('EquityHistorical', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquityQuote', async () => { expect((await exec('EquityQuote', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquityInfo', async () => { expect((await exec('EquityInfo', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquitySearch', async () => { expect((await exec('EquitySearch', { query: 'Apple' })).length).toBeGreaterThan(0) }) + it('EquityScreener', async () => { expect((await exec('EquityScreener', { market_cap_min: 1e11 })).length).toBeGreaterThan(0) }, 60_000) + it('KeyMetrics', async () => { expect((await exec('KeyMetrics', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('KeyExecutives', async () => { expect((await exec('KeyExecutives', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquityPeers', async () => { expect((await exec('EquityPeers', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) +}) + +describe('fmp — financials', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('IncomeStatement', async () => { expect((await exec('IncomeStatement', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('BalanceSheet', async () => { expect((await exec('BalanceSheet', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('CashFlowStatement', async () => { expect((await exec('CashFlowStatement', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('FinancialRatios', async () => { expect((await exec('FinancialRatios', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) +}) + +describe('fmp — calendar & events', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('CalendarEarnings', async () => { expect((await exec('CalendarEarnings')).length).toBeGreaterThan(0) }) + it('CalendarDividend', async () => { expect((await exec('CalendarDividend')).length).toBeGreaterThan(0) }) + it('CalendarIpo', async () => { expect((await exec('CalendarIpo')).length).toBeGreaterThan(0) }) +}) + +describe('fmp — ownership', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('InsiderTrading', async () => { expect((await exec('InsiderTrading', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it.skip('InstitutionalOwnership — returns empty for most symbols', async () => { expect((await exec('InstitutionalOwnership', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) +}) + +describe('fmp — discovery', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('EquityGainers', async () => { expect((await exec('EquityGainers')).length).toBeGreaterThan(0) }) + it('EquityLosers', async () => { expect((await exec('EquityLosers')).length).toBeGreaterThan(0) }) + it('EquityActive', async () => { expect((await exec('EquityActive')).length).toBeGreaterThan(0) }) +}) + +describe('fmp — crypto & currency', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('CryptoSearch', async () => { expect((await exec('CryptoSearch')).length).toBeGreaterThan(0) }) + it('CryptoHistorical', async () => { expect((await exec('CryptoHistorical', { symbol: 'BTCUSD' })).length).toBeGreaterThan(0) }) + it('CurrencyHistorical', async () => { expect((await exec('CurrencyHistorical', { symbol: 'EURUSD' })).length).toBeGreaterThan(0) }) + it('CurrencyPairs', async () => { expect((await exec('CurrencyPairs')).length).toBeGreaterThan(0) }) + it.skip('CurrencySnapshots — requires higher FMP tier', async () => { expect((await exec('CurrencySnapshots')).length).toBeGreaterThan(0) }) +}) + +describe('fmp — ETF', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('EtfSearch', async () => { expect((await exec('EtfSearch', { query: 'SPY' })).length).toBeGreaterThan(0) }) + it('EtfInfo', async () => { expect((await exec('EtfInfo', { symbol: 'SPY' })).length).toBeGreaterThan(0) }) + it('EtfSectors', async () => { expect((await exec('EtfSectors', { symbol: 'SPY' })).length).toBeGreaterThan(0) }) + it.skip('EtfHoldings — requires higher FMP tier', async () => { expect((await exec('EtfHoldings', { symbol: 'SPY' })).length).toBeGreaterThan(0) }) +}) + +describe('fmp — index', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('IndexHistorical', async () => { expect((await exec('IndexHistorical', { symbol: '^GSPC' })).length).toBeGreaterThan(0) }) + it.skip('IndexConstituents — requires higher FMP tier', async () => { expect((await exec('IndexConstituents', { symbol: 'dowjones' })).length).toBeGreaterThan(0) }) + // SP500Multiples — registered in multpl provider, not fmp + it('RiskPremium', async () => { expect((await exec('RiskPremium')).length).toBeGreaterThan(0) }) +}) + +describe('fmp — commodity', () => { + beforeEach(({ skip }) => { if (!hasCredential(ctx.credentials, 'fmp')) skip('no fmp_api_key') }) + + it('CommoditySpotPrice', async () => { expect((await exec('CommoditySpotPrice', { symbol: 'GCUSD' })).length).toBeGreaterThan(0) }) +}) diff --git a/src/domain/market-data/__tests__/bbProviders/setup.ts b/src/domain/market-data/__tests__/bbProviders/setup.ts new file mode 100644 index 00000000..408eb4d9 --- /dev/null +++ b/src/domain/market-data/__tests__/bbProviders/setup.ts @@ -0,0 +1,34 @@ +/** + * bbProvider test setup — shared executor + credentials. + * + * Reads config.json for provider API keys, initializes the openTypeBB executor. + * Lazily cached: first call loads config, subsequent calls return same instance. + */ + +import { loadConfig } from '@/core/config.js' +import { buildSDKCredentials } from '@/domain/market-data/credential-map.js' +import { createExecutor, type QueryExecutor } from '@traderalice/opentypebb' + +export interface TestContext { + executor: QueryExecutor + credentials: Record +} + +let _ctx: TestContext | null = null + +export async function getTestContext(): Promise { + if (!_ctx) { + const config = await loadConfig() + _ctx = { + executor: createExecutor(), + credentials: buildSDKCredentials(config.marketData.providerKeys), + } + } + return _ctx +} + +/** Check whether a specific bbProvider's API key is configured. */ +export function hasCredential(credentials: Record, bbProvider: string): boolean { + const key = `${bbProvider}_api_key` + return !!credentials[key] +} diff --git a/src/domain/market-data/__tests__/bbProviders/yfinance.bbProvider.spec.ts b/src/domain/market-data/__tests__/bbProviders/yfinance.bbProvider.spec.ts new file mode 100644 index 00000000..a4bdaadf --- /dev/null +++ b/src/domain/market-data/__tests__/bbProviders/yfinance.bbProvider.spec.ts @@ -0,0 +1,66 @@ +/** + * yfinance bbProvider integration test. + * + * Verifies all 32 yfinance fetchers can reach the API and return + * schema-compliant data. Free provider — no API key required. + */ + +import { describe, it, expect, beforeAll } from 'vitest' +import { getTestContext, type TestContext } from './setup.js' + +let ctx: TestContext + +beforeAll(async () => { ctx = await getTestContext() }) + +const exec = (model: string, params: Record = {}) => + ctx.executor.execute('yfinance', model, params, ctx.credentials) + +describe('yfinance — equity', () => { + it('EquityQuote', async () => { expect((await exec('EquityQuote', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquityInfo', async () => { expect((await exec('EquityInfo', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquityHistorical', async () => { expect((await exec('EquityHistorical', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('EquityScreener', async () => { expect((await exec('EquityScreener')).length).toBeGreaterThan(0) }) + it('KeyMetrics', async () => { expect((await exec('KeyMetrics', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('KeyExecutives', async () => { expect((await exec('KeyExecutives', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('ShareStatistics', async () => { expect((await exec('ShareStatistics', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('PriceTargetConsensus', async () => { expect((await exec('PriceTargetConsensus', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('CompanyNews', async () => { expect((await exec('CompanyNews', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('HistoricalDividends', async () => { expect((await exec('HistoricalDividends', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) +}) + +describe('yfinance — financials', () => { + it('IncomeStatement', async () => { expect((await exec('IncomeStatement', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('BalanceSheet', async () => { expect((await exec('BalanceSheet', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('CashFlowStatement', async () => { expect((await exec('CashFlowStatement', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) +}) + +describe('yfinance — discovery', () => { + it('EquityGainers', async () => { expect((await exec('EquityGainers')).length).toBeGreaterThan(0) }) + it('EquityLosers', async () => { expect((await exec('EquityLosers')).length).toBeGreaterThan(0) }) + it('EquityActive', async () => { expect((await exec('EquityActive')).length).toBeGreaterThan(0) }) + it('EquityAggressiveSmallCaps', async () => { expect((await exec('EquityAggressiveSmallCaps')).length).toBeGreaterThan(0) }) + it('GrowthTechEquities', async () => { expect((await exec('GrowthTechEquities')).length).toBeGreaterThan(0) }) + it('EquityUndervaluedGrowth', async () => { expect((await exec('EquityUndervaluedGrowth')).length).toBeGreaterThan(0) }) + it('EquityUndervaluedLargeCaps', async () => { expect((await exec('EquityUndervaluedLargeCaps')).length).toBeGreaterThan(0) }) +}) + +describe('yfinance — crypto & currency', () => { + it('CryptoSearch', async () => { expect((await exec('CryptoSearch', { query: 'bitcoin' })).length).toBeGreaterThan(0) }) + it('CryptoHistorical', async () => { expect((await exec('CryptoHistorical', { symbol: 'BTCUSD' })).length).toBeGreaterThan(0) }) + it('CurrencyPairs', async () => { expect((await exec('CurrencyPairs', { query: 'USD' })).length).toBeGreaterThan(0) }) + it('CurrencyHistorical', async () => { expect((await exec('CurrencyHistorical', { symbol: 'EURUSD' })).length).toBeGreaterThan(0) }) +}) + +describe('yfinance — ETF & index', () => { + it('EtfInfo', async () => { expect((await exec('EtfInfo', { symbol: 'SPY' })).length).toBeGreaterThan(0) }) + it('EtfHistorical', async () => { expect((await exec('EtfHistorical', { symbol: 'SPY' })).length).toBeGreaterThan(0) }) + it('IndexHistorical', async () => { expect((await exec('IndexHistorical', { symbol: '^GSPC' })).length).toBeGreaterThan(0) }) + it('AvailableIndices', async () => { expect((await exec('AvailableIndices')).length).toBeGreaterThan(0) }) +}) + +describe('yfinance — derivatives & commodity', () => { + it('OptionsChains', async () => { expect((await exec('OptionsChains', { symbol: 'AAPL' })).length).toBeGreaterThan(0) }) + it('FuturesHistorical', async () => { expect((await exec('FuturesHistorical', { symbol: 'ES=F' })).length).toBeGreaterThan(0) }) + it('FuturesCurve', async () => { expect((await exec('FuturesCurve', { symbol: 'ES' })).length).toBeGreaterThan(0) }) + it('CommoditySpotPrice', async () => { expect((await exec('CommoditySpotPrice', { symbol: 'GC=F' })).length).toBeGreaterThan(0) }) +}) diff --git a/src/domain/market-data/client/openbb-api/commodity-client.ts b/src/domain/market-data/client/openbb-api/commodity-client.ts index 1dc84714..406b3623 100644 --- a/src/domain/market-data/client/openbb-api/commodity-client.ts +++ b/src/domain/market-data/client/openbb-api/commodity-client.ts @@ -7,6 +7,7 @@ import type { OBBjectResponse } from '../../commodity/types/index' import { buildCredentialsHeader } from '../../credential-map' +import type { CommoditySpotPriceData } from '@traderalice/opentypebb' export class OpenBBCommodityClient { private baseUrl: string @@ -22,7 +23,7 @@ export class OpenBBCommodityClient { // ==================== Price ==================== async getSpotPrices(params: Record) { - return this.request('/price/spot', params) + return this.request('/price/spot', params) } // ==================== PSD ==================== diff --git a/src/domain/market-data/client/openbb-api/crypto-client.ts b/src/domain/market-data/client/openbb-api/crypto-client.ts index 3c41e07c..6c3b99e0 100644 --- a/src/domain/market-data/client/openbb-api/crypto-client.ts +++ b/src/domain/market-data/client/openbb-api/crypto-client.ts @@ -7,6 +7,7 @@ import type { OBBjectResponse } from '../../crypto/types/index' import { buildCredentialsHeader } from '../../credential-map' +import type { CryptoHistoricalData, CryptoSearchData } from '@traderalice/opentypebb' export class OpenBBCryptoClient { private baseUrl: string @@ -22,13 +23,13 @@ export class OpenBBCryptoClient { // ==================== Price ==================== async getHistorical(params: Record) { - return this.request('/price/historical', params) + return this.request('/price/historical', params) } // ==================== Search ==================== async search(params: Record) { - return this.request('/search', params) + return this.request('/search', params) } // ==================== Internal ==================== diff --git a/src/domain/market-data/client/openbb-api/currency-client.ts b/src/domain/market-data/client/openbb-api/currency-client.ts index 5e10763a..10c8bedf 100644 --- a/src/domain/market-data/client/openbb-api/currency-client.ts +++ b/src/domain/market-data/client/openbb-api/currency-client.ts @@ -7,6 +7,7 @@ import type { OBBjectResponse } from '../../currency/types/index' import { buildCredentialsHeader } from '../../credential-map' +import type { CurrencyHistoricalData } from '@traderalice/opentypebb' export class OpenBBCurrencyClient { private baseUrl: string @@ -22,7 +23,7 @@ export class OpenBBCurrencyClient { // ==================== Price ==================== async getHistorical(params: Record) { - return this.request('/price/historical', params) + return this.request('/price/historical', params) } // ==================== Search ==================== diff --git a/src/domain/market-data/client/openbb-api/equity-client.ts b/src/domain/market-data/client/openbb-api/equity-client.ts index ad955c13..80236321 100644 --- a/src/domain/market-data/client/openbb-api/equity-client.ts +++ b/src/domain/market-data/client/openbb-api/equity-client.ts @@ -7,6 +7,11 @@ import type { OBBjectResponse } from '../../equity/types/base' import { buildCredentialsHeader } from '../../credential-map' +import type { + EquitySearchData, EquityHistoricalData, EquityInfoData, KeyMetricsData, + IncomeStatementData, BalanceSheetData, CashFlowStatementData, FinancialRatiosData, + PriceTargetConsensusData, CalendarEarningsData, InsiderTradingData, EquityDiscoveryData, +} from '@traderalice/opentypebb' export class OpenBBEquityClient { private baseUrl: string @@ -22,7 +27,7 @@ export class OpenBBEquityClient { // ==================== Price ==================== async getHistorical(params: Record) { - return this.request('/price/historical', params) + return this.request('/price/historical', params) } async getQuote(params: Record) { @@ -40,7 +45,7 @@ export class OpenBBEquityClient { // ==================== Info ==================== async search(params: Record) { - return this.request('/search', params) + return this.request('/search', params) } async screener(params: Record) { @@ -48,7 +53,7 @@ export class OpenBBEquityClient { } async getProfile(params: Record) { - return this.request('/profile', params) + return this.request('/profile', params) } async getMarketSnapshots(params: Record = {}) { @@ -62,7 +67,7 @@ export class OpenBBEquityClient { // ==================== Fundamental ==================== async getBalanceSheet(params: Record) { - return this.request('/fundamental/balance', params) + return this.request('/fundamental/balance', params) } async getBalanceSheetGrowth(params: Record) { @@ -70,7 +75,7 @@ export class OpenBBEquityClient { } async getIncomeStatement(params: Record) { - return this.request('/fundamental/income', params) + return this.request('/fundamental/income', params) } async getIncomeStatementGrowth(params: Record) { @@ -78,7 +83,7 @@ export class OpenBBEquityClient { } async getCashFlow(params: Record) { - return this.request('/fundamental/cash', params) + return this.request('/fundamental/cash', params) } async getCashFlowGrowth(params: Record) { @@ -90,11 +95,11 @@ export class OpenBBEquityClient { } async getFinancialRatios(params: Record) { - return this.request('/fundamental/ratios', params) + return this.request('/fundamental/ratios', params) } async getKeyMetrics(params: Record) { - return this.request('/fundamental/metrics', params) + return this.request('/fundamental/metrics', params) } async getDividends(params: Record) { @@ -172,7 +177,7 @@ export class OpenBBEquityClient { } async getCalendarEarnings(params: Record = {}) { - return this.request('/calendar/earnings', params) + return this.request('/calendar/earnings', params) } async getCalendarEvents(params: Record = {}) { @@ -190,7 +195,7 @@ export class OpenBBEquityClient { } async getEstimateConsensus(params: Record) { - return this.request('/estimates/consensus', params) + return this.request('/estimates/consensus', params) } async getAnalystSearch(params: Record) { @@ -216,15 +221,15 @@ export class OpenBBEquityClient { // ==================== Discovery ==================== async getGainers(params: Record = {}) { - return this.request('/discovery/gainers', params) + return this.request('/discovery/gainers', params) } async getLosers(params: Record = {}) { - return this.request('/discovery/losers', params) + return this.request('/discovery/losers', params) } async getActive(params: Record = {}) { - return this.request('/discovery/active', params) + return this.request('/discovery/active', params) } async getUndervaluedLargeCaps(params: Record = {}) { @@ -266,7 +271,7 @@ export class OpenBBEquityClient { } async getInsiderTrading(params: Record) { - return this.request('/ownership/insider_trading', params) + return this.request('/ownership/insider_trading', params) } async getShareStatistics(params: Record) { diff --git a/src/domain/market-data/client/typebb/commodity-client.ts b/src/domain/market-data/client/typebb/commodity-client.ts index 45b10573..8db2daaf 100644 --- a/src/domain/market-data/client/typebb/commodity-client.ts +++ b/src/domain/market-data/client/typebb/commodity-client.ts @@ -7,11 +7,12 @@ * "No SDK route for: /commodity/..." until the corresponding fetchers are added. */ +import type { CommoditySpotPriceData, PetroleumStatusReportData, ShortTermEnergyOutlookData } from '@traderalice/opentypebb' import { SDKBaseClient } from './base-client.js' export class SDKCommodityClient extends SDKBaseClient { async getSpotPrices(params: Record) { - return this.request('/price/spot', params) + return this.request('/price/spot', params) } async getPsdData(params: Record) { @@ -19,11 +20,11 @@ export class SDKCommodityClient extends SDKBaseClient { } async getPetroleumStatus(params: Record) { - return this.request('/petroleum_status_report', params) + return this.request('/petroleum_status_report', params) } async getEnergyOutlook(params: Record) { - return this.request('/short_term_energy_outlook', params) + return this.request('/short_term_energy_outlook', params) } async getPsdReport(params: Record) { diff --git a/src/domain/market-data/client/typebb/crypto-client.ts b/src/domain/market-data/client/typebb/crypto-client.ts index 82b2a9b1..34c49f16 100644 --- a/src/domain/market-data/client/typebb/crypto-client.ts +++ b/src/domain/market-data/client/typebb/crypto-client.ts @@ -4,14 +4,15 @@ * Drop-in replacement for OpenBBCryptoClient. */ +import type { CryptoHistoricalData, CryptoSearchData } from '@traderalice/opentypebb' import { SDKBaseClient } from './base-client.js' export class SDKCryptoClient extends SDKBaseClient { async getHistorical(params: Record) { - return this.request('/price/historical', params) + return this.request('/price/historical', params) } async search(params: Record) { - return this.request('/search', params) + return this.request('/search', params) } } diff --git a/src/domain/market-data/client/typebb/currency-client.ts b/src/domain/market-data/client/typebb/currency-client.ts index 26bc7674..cc5ebc5a 100644 --- a/src/domain/market-data/client/typebb/currency-client.ts +++ b/src/domain/market-data/client/typebb/currency-client.ts @@ -4,11 +4,12 @@ * Drop-in replacement for OpenBBCurrencyClient. */ +import type { CurrencyHistoricalData, CurrencySnapshotsData } from '@traderalice/opentypebb' import { SDKBaseClient } from './base-client.js' export class SDKCurrencyClient extends SDKBaseClient { async getHistorical(params: Record) { - return this.request('/price/historical', params) + return this.request('/price/historical', params) } async search(params: Record) { @@ -20,6 +21,6 @@ export class SDKCurrencyClient extends SDKBaseClient { } async getSnapshots(params: Record) { - return this.request('/snapshots', params) + return this.request('/snapshots', params) } } diff --git a/src/domain/market-data/client/typebb/derivatives-client.ts b/src/domain/market-data/client/typebb/derivatives-client.ts new file mode 100644 index 00000000..3f1775af --- /dev/null +++ b/src/domain/market-data/client/typebb/derivatives-client.ts @@ -0,0 +1,45 @@ +/** + * SDK Derivatives Client + * + * Maps to openTypeBB derivatives-router endpoints. + */ + +import type { + FuturesHistoricalData, FuturesCurveData, FuturesInfoData, FuturesInstrumentsData, + OptionsChainsData, OptionsSnapshotsData, OptionsUnusualData, +} from '@traderalice/opentypebb' +import { SDKBaseClient } from './base-client.js' + +export class SDKDerivativesClient extends SDKBaseClient { + // ==================== Futures ==================== + + async getFuturesHistorical(params: Record) { + return this.request('/futures/historical', params) + } + + async getFuturesCurve(params: Record) { + return this.request('/futures/curve', params) + } + + async getFuturesInfo(params: Record) { + return this.request('/futures/info', params) + } + + async getFuturesInstruments(params: Record = {}) { + return this.request('/futures/instruments', params) + } + + // ==================== Options ==================== + + async getOptionsChains(params: Record) { + return this.request('/options/chains', params) + } + + async getOptionsSnapshots(params: Record = {}) { + return this.request('/options/snapshots', params) + } + + async getOptionsUnusual(params: Record = {}) { + return this.request('/options/unusual', params) + } +} diff --git a/src/domain/market-data/client/typebb/economy-client.ts b/src/domain/market-data/client/typebb/economy-client.ts index 653f39cd..625b481a 100644 --- a/src/domain/market-data/client/typebb/economy-client.ts +++ b/src/domain/market-data/client/typebb/economy-client.ts @@ -5,183 +5,198 @@ */ import { SDKBaseClient } from './base-client.js' +import type { + EconomicCalendarData, ConsumerPriceIndexData, RiskPremiumData, BalanceOfPaymentsData, + MoneyMeasuresData, UnemploymentData, CompositeLeadingIndicatorData, CountryProfileData, + AvailableIndicatorsData, EconomicIndicatorsData, CentralBankHoldingsData, + SharePriceIndexData, HousePriceIndexData, CountryInterestRatesData, RetailPricesData, + PrimaryDealerPositioningData, PersonalConsumptionExpendituresData, + ExportDestinationsData, PrimaryDealerFailsData, DirectionOfTradeData, + FomcDocumentsData, TotalFactorProductivityData, + FredSearchData, FredSeriesData, FredReleaseTableData, FredRegionalData, + GdpForecastData, GdpNominalData, GdpRealData, + BlsSeriesData, BlsSearchData, SloosData, UniversityOfMichiganData, + EconomicConditionsChicagoData, ManufacturingOutlookTexasData, ManufacturingOutlookNYData, + NonfarmPayrollsData, InflationExpectationsData, + PortInfoData, PortVolumeData, ChokepointInfoData, ChokepointVolumeData, +} from '@traderalice/opentypebb' export class SDKEconomyClient extends SDKBaseClient { // ==================== Core ==================== async getCalendar(params: Record = {}) { - return this.request('/calendar', params) + return this.request('/calendar', params) } async getCPI(params: Record) { - return this.request('/cpi', params) + return this.request('/cpi', params) } async getRiskPremium(params: Record) { - return this.request('/risk_premium', params) + return this.request('/risk_premium', params) } async getBalanceOfPayments(params: Record) { - return this.request('/balance_of_payments', params) + return this.request('/balance_of_payments', params) } async getMoneyMeasures(params: Record = {}) { - return this.request('/money_measures', params) + return this.request('/money_measures', params) } async getUnemployment(params: Record = {}) { - return this.request('/unemployment', params) + return this.request('/unemployment', params) } async getCompositeLeadingIndicator(params: Record = {}) { - return this.request('/composite_leading_indicator', params) + return this.request('/composite_leading_indicator', params) } async getCountryProfile(params: Record) { - return this.request('/country_profile', params) + return this.request('/country_profile', params) } async getAvailableIndicators(params: Record = {}) { - return this.request('/available_indicators', params) + return this.request('/available_indicators', params) } async getIndicators(params: Record) { - return this.request('/indicators', params) + return this.request('/indicators', params) } async getCentralBankHoldings(params: Record = {}) { - return this.request('/central_bank_holdings', params) + return this.request('/central_bank_holdings', params) } async getSharePriceIndex(params: Record = {}) { - return this.request('/share_price_index', params) + return this.request('/share_price_index', params) } async getHousePriceIndex(params: Record = {}) { - return this.request('/house_price_index', params) + return this.request('/house_price_index', params) } async getInterestRates(params: Record = {}) { - return this.request('/interest_rates', params) + return this.request('/interest_rates', params) } async getRetailPrices(params: Record = {}) { - return this.request('/retail_prices', params) + return this.request('/retail_prices', params) } async getPrimaryDealerPositioning(params: Record = {}) { - return this.request('/primary_dealer_positioning', params) + return this.request('/primary_dealer_positioning', params) } async getPCE(params: Record = {}) { - return this.request('/pce', params) + return this.request('/pce', params) } async getExportDestinations(params: Record) { - return this.request('/export_destinations', params) + return this.request('/export_destinations', params) } async getPrimaryDealerFails(params: Record = {}) { - return this.request('/primary_dealer_fails', params) + return this.request('/primary_dealer_fails', params) } async getDirectionOfTrade(params: Record) { - return this.request('/direction_of_trade', params) + return this.request('/direction_of_trade', params) } async getFomcDocuments(params: Record = {}) { - return this.request('/fomc_documents', params) + return this.request('/fomc_documents', params) } async getTotalFactorProductivity(params: Record = {}) { - return this.request('/total_factor_productivity', params) + return this.request('/total_factor_productivity', params) } // ==================== FRED ==================== async fredSearch(params: Record) { - return this.request('/fred_search', params) + return this.request('/fred_search', params) } async fredSeries(params: Record) { - return this.request('/fred_series', params) + return this.request('/fred_series', params) } async fredReleaseTable(params: Record) { - return this.request('/fred_release_table', params) + return this.request('/fred_release_table', params) } async fredRegional(params: Record) { - return this.request('/fred_regional', params) + return this.request('/fred_regional', params) } // ==================== GDP ==================== async getGdpForecast(params: Record = {}) { - return this.request('/gdp/forecast', params) + return this.request('/gdp/forecast', params) } async getGdpNominal(params: Record = {}) { - return this.request('/gdp/nominal', params) + return this.request('/gdp/nominal', params) } async getGdpReal(params: Record = {}) { - return this.request('/gdp/real', params) + return this.request('/gdp/real', params) } // ==================== Survey ==================== async getBlsSeries(params: Record) { - return this.request('/survey/bls_series', params) + return this.request('/survey/bls_series', params) } async getBlsSearch(params: Record) { - return this.request('/survey/bls_search', params) + return this.request('/survey/bls_search', params) } async getSloos(params: Record = {}) { - return this.request('/survey/sloos', params) + return this.request('/survey/sloos', params) } async getUniversityOfMichigan(params: Record = {}) { - return this.request('/survey/university_of_michigan', params) + return this.request('/survey/university_of_michigan', params) } async getEconomicConditionsChicago(params: Record = {}) { - return this.request('/survey/economic_conditions_chicago', params) + return this.request('/survey/economic_conditions_chicago', params) } async getManufacturingOutlookTexas(params: Record = {}) { - return this.request('/survey/manufacturing_outlook_texas', params) + return this.request('/survey/manufacturing_outlook_texas', params) } async getManufacturingOutlookNY(params: Record = {}) { - return this.request('/survey/manufacturing_outlook_ny', params) + return this.request('/survey/manufacturing_outlook_ny', params) } async getNonfarmPayrolls(params: Record = {}) { - return this.request('/survey/nonfarm_payrolls', params) + return this.request('/survey/nonfarm_payrolls', params) } async getInflationExpectations(params: Record = {}) { - return this.request('/survey/inflation_expectations', params) + return this.request('/survey/inflation_expectations', params) } // ==================== Shipping ==================== async getPortInfo(params: Record = {}) { - return this.request('/shipping/port_info', params) + return this.request('/shipping/port_info', params) } async getPortVolume(params: Record = {}) { - return this.request('/shipping/port_volume', params) + return this.request('/shipping/port_volume', params) } async getChokepointInfo(params: Record = {}) { - return this.request('/shipping/chokepoint_info', params) + return this.request('/shipping/chokepoint_info', params) } async getChokepointVolume(params: Record = {}) { - return this.request('/shipping/chokepoint_volume', params) + return this.request('/shipping/chokepoint_volume', params) } } diff --git a/src/domain/market-data/client/typebb/equity-client.ts b/src/domain/market-data/client/typebb/equity-client.ts index b60931d2..1dbeb77e 100644 --- a/src/domain/market-data/client/typebb/equity-client.ts +++ b/src/domain/market-data/client/typebb/equity-client.ts @@ -6,16 +6,31 @@ */ import { SDKBaseClient } from './base-client.js' +import type { + EquityHistoricalData, EquityQuoteData, EquityPerformanceData, + EquitySearchData, EquityScreenerData, EquityInfoData, MarketSnapshotsData, HistoricalMarketCapData, + BalanceSheetData, BalanceSheetGrowthData, IncomeStatementData, IncomeStatementGrowthData, + CashFlowStatementData, CashFlowStatementGrowthData, FinancialRatiosData, KeyMetricsData, + HistoricalDividendsData, HistoricalEpsData, HistoricalEmployeesData, ExecutiveCompensationData, + CompanyFilingsData, HistoricalSplitsData, EarningsCallTranscriptData, + RevenueGeographicData, RevenueBusinessLineData, EsgScoreData, + CalendarIpoData, CalendarDividendData, CalendarSplitsData, CalendarEarningsData, EconomicCalendarData, + PriceTargetData, AnalystEstimatesData, PriceTargetConsensusData, + ForwardEbitdaEstimatesData, ForwardEpsEstimatesData, + EquityDiscoveryData, DiscoveryFilingsData, RecentPerformanceData, + InstitutionalOwnershipData, InsiderTradingData, ShareStatisticsData, GovernmentTradesData, + EquityPeersData, +} from '@traderalice/opentypebb' export class SDKEquityClient extends SDKBaseClient { // ==================== Price ==================== async getHistorical(params: Record) { - return this.request('/price/historical', params) + return this.request('/price/historical', params) } async getQuote(params: Record) { - return this.request('/price/quote', params) + return this.request('/price/quote', params) } async getNBBO(params: Record) { @@ -23,55 +38,55 @@ export class SDKEquityClient extends SDKBaseClient { } async getPricePerformance(params: Record) { - return this.request('/price/performance', params) + return this.request('/price/performance', params) } // ==================== Info ==================== async search(params: Record) { - return this.request('/search', params) + return this.request('/search', params) } async screener(params: Record) { - return this.request('/screener', params) + return this.request('/screener', params) } async getProfile(params: Record) { - return this.request('/profile', params) + return this.request('/profile', params) } async getMarketSnapshots(params: Record = {}) { - return this.request('/market_snapshots', params) + return this.request('/market_snapshots', params) } async getHistoricalMarketCap(params: Record) { - return this.request('/historical_market_cap', params) + return this.request('/historical_market_cap', params) } // ==================== Fundamental ==================== async getBalanceSheet(params: Record) { - return this.request('/fundamental/balance', params) + return this.request('/fundamental/balance', params) } async getBalanceSheetGrowth(params: Record) { - return this.request('/fundamental/balance_growth', params) + return this.request('/fundamental/balance_growth', params) } async getIncomeStatement(params: Record) { - return this.request('/fundamental/income', params) + return this.request('/fundamental/income', params) } async getIncomeStatementGrowth(params: Record) { - return this.request('/fundamental/income_growth', params) + return this.request('/fundamental/income_growth', params) } async getCashFlow(params: Record) { - return this.request('/fundamental/cash', params) + return this.request('/fundamental/cash', params) } async getCashFlowGrowth(params: Record) { - return this.request('/fundamental/cash_growth', params) + return this.request('/fundamental/cash_growth', params) } async getReportedFinancials(params: Record) { @@ -79,23 +94,23 @@ export class SDKEquityClient extends SDKBaseClient { } async getFinancialRatios(params: Record) { - return this.request('/fundamental/ratios', params) + return this.request('/fundamental/ratios', params) } async getKeyMetrics(params: Record) { - return this.request('/fundamental/metrics', params) + return this.request('/fundamental/metrics', params) } async getDividends(params: Record) { - return this.request('/fundamental/dividends', params) + return this.request('/fundamental/dividends', params) } async getEarningsHistory(params: Record) { - return this.request('/fundamental/historical_eps', params) + return this.request('/fundamental/historical_eps', params) } async getEmployeeCount(params: Record) { - return this.request('/fundamental/employee_count', params) + return this.request('/fundamental/employee_count', params) } async getManagement(params: Record) { @@ -103,19 +118,19 @@ export class SDKEquityClient extends SDKBaseClient { } async getManagementCompensation(params: Record) { - return this.request('/fundamental/management_compensation', params) + return this.request('/fundamental/management_compensation', params) } async getFilings(params: Record) { - return this.request('/fundamental/filings', params) + return this.request('/fundamental/filings', params) } async getSplits(params: Record) { - return this.request('/fundamental/historical_splits', params) + return this.request('/fundamental/historical_splits', params) } async getTranscript(params: Record) { - return this.request('/fundamental/transcript', params) + return this.request('/fundamental/transcript', params) } async getTrailingDividendYield(params: Record) { @@ -123,15 +138,15 @@ export class SDKEquityClient extends SDKBaseClient { } async getRevenuePerGeography(params: Record) { - return this.request('/fundamental/revenue_per_geography', params) + return this.request('/fundamental/revenue_per_geography', params) } async getRevenuePerSegment(params: Record) { - return this.request('/fundamental/revenue_per_segment', params) + return this.request('/fundamental/revenue_per_segment', params) } async getEsgScore(params: Record) { - return this.request('/fundamental/esg_score', params) + return this.request('/fundamental/esg_score', params) } async getSearchAttributes(params: Record) { @@ -149,37 +164,37 @@ export class SDKEquityClient extends SDKBaseClient { // ==================== Calendar ==================== async getCalendarIpo(params: Record = {}) { - return this.request('/calendar/ipo', params) + return this.request('/calendar/ipo', params) } async getCalendarDividend(params: Record = {}) { - return this.request('/calendar/dividend', params) + return this.request('/calendar/dividend', params) } async getCalendarSplits(params: Record = {}) { - return this.request('/calendar/splits', params) + return this.request('/calendar/splits', params) } async getCalendarEarnings(params: Record = {}) { - return this.request('/calendar/earnings', params) + return this.request('/calendar/earnings', params) } async getCalendarEvents(params: Record = {}) { - return this.request('/calendar/events', params) + return this.request('/calendar/events', params) } // ==================== Estimates ==================== async getPriceTarget(params: Record) { - return this.request('/estimates/price_target', params) + return this.request('/estimates/price_target', params) } async getAnalystEstimates(params: Record) { - return this.request('/estimates/historical', params) + return this.request('/estimates/historical', params) } async getEstimateConsensus(params: Record) { - return this.request('/estimates/consensus', params) + return this.request('/estimates/consensus', params) } async getAnalystSearch(params: Record) { @@ -191,11 +206,11 @@ export class SDKEquityClient extends SDKBaseClient { } async getForwardEbitda(params: Record) { - return this.request('/estimates/forward_ebitda', params) + return this.request('/estimates/forward_ebitda', params) } async getForwardEps(params: Record) { - return this.request('/estimates/forward_eps', params) + return this.request('/estimates/forward_eps', params) } async getForwardPe(params: Record) { @@ -205,43 +220,43 @@ export class SDKEquityClient extends SDKBaseClient { // ==================== Discovery ==================== async getGainers(params: Record = {}) { - return this.request('/discovery/gainers', params) + return this.request('/discovery/gainers', params) } async getLosers(params: Record = {}) { - return this.request('/discovery/losers', params) + return this.request('/discovery/losers', params) } async getActive(params: Record = {}) { - return this.request('/discovery/active', params) + return this.request('/discovery/active', params) } async getUndervaluedLargeCaps(params: Record = {}) { - return this.request('/discovery/undervalued_large_caps', params) + return this.request('/discovery/undervalued_large_caps', params) } async getUndervaluedGrowth(params: Record = {}) { - return this.request('/discovery/undervalued_growth', params) + return this.request('/discovery/undervalued_growth', params) } async getAggressiveSmallCaps(params: Record = {}) { - return this.request('/discovery/aggressive_small_caps', params) + return this.request('/discovery/aggressive_small_caps', params) } async getGrowthTech(params: Record = {}) { - return this.request('/discovery/growth_tech', params) + return this.request('/discovery/growth_tech', params) } async getTopRetail(params: Record = {}) { - return this.request('/discovery/top_retail', params) + return this.request('/discovery/top_retail', params) } async getDiscoveryFilings(params: Record = {}) { - return this.request('/discovery/filings', params) + return this.request('/discovery/filings', params) } async getLatestFinancialReports(params: Record = {}) { - return this.request('/discovery/latest_financial_reports', params) + return this.request('/discovery/latest_financial_reports', params) } // ==================== Ownership ==================== @@ -251,15 +266,15 @@ export class SDKEquityClient extends SDKBaseClient { } async getInstitutional(params: Record) { - return this.request('/ownership/institutional', params) + return this.request('/ownership/institutional', params) } async getInsiderTrading(params: Record) { - return this.request('/ownership/insider_trading', params) + return this.request('/ownership/insider_trading', params) } async getShareStatistics(params: Record) { - return this.request('/ownership/share_statistics', params) + return this.request('/ownership/share_statistics', params) } async getForm13F(params: Record) { @@ -267,7 +282,7 @@ export class SDKEquityClient extends SDKBaseClient { } async getGovernmentTrades(params: Record = {}) { - return this.request('/ownership/government_trades', params) + return this.request('/ownership/government_trades', params) } // ==================== Shorts ==================== @@ -287,7 +302,7 @@ export class SDKEquityClient extends SDKBaseClient { // ==================== Compare ==================== async getPeers(params: Record) { - return this.request('/compare/peers', params) + return this.request('/compare/peers', params) } async getCompareGroups(params: Record = {}) { diff --git a/src/domain/market-data/client/typebb/etf-client.ts b/src/domain/market-data/client/typebb/etf-client.ts new file mode 100644 index 00000000..a2ab6017 --- /dev/null +++ b/src/domain/market-data/client/typebb/etf-client.ts @@ -0,0 +1,41 @@ +/** + * SDK ETF Client + * + * Maps to openTypeBB etf-router endpoints. + */ + +import type { + EtfSearchData, EtfInfoData, EtfHoldingsData, + EtfSectorsData, EtfCountriesData, EtfEquityExposureData, +} from '@traderalice/opentypebb' +import { SDKBaseClient } from './base-client.js' + +export class SDKEtfClient extends SDKBaseClient { + async search(params: Record) { + return this.request('/search', params) + } + + async getInfo(params: Record) { + return this.request('/info', params) + } + + async getHoldings(params: Record) { + return this.request('/holdings', params) + } + + async getSectors(params: Record) { + return this.request('/sectors', params) + } + + async getCountries(params: Record) { + return this.request('/countries', params) + } + + async getEquityExposure(params: Record) { + return this.request('/equity_exposure', params) + } + + async getHistorical(params: Record) { + return this.request('/historical', params) + } +} diff --git a/src/domain/market-data/client/typebb/index-client.ts b/src/domain/market-data/client/typebb/index-client.ts new file mode 100644 index 00000000..c6468184 --- /dev/null +++ b/src/domain/market-data/client/typebb/index-client.ts @@ -0,0 +1,45 @@ +/** + * SDK Index Client + * + * Maps to openTypeBB index-router endpoints. + */ + +import type { + AvailableIndicesData, IndexSearchData, IndexConstituentsData, + IndexHistoricalData, IndexSectorsData, SP500MultiplesData, RiskPremiumData, +} from '@traderalice/opentypebb' +import { SDKBaseClient } from './base-client.js' + +export class SDKIndexClient extends SDKBaseClient { + async getAvailable(params: Record = {}) { + return this.request('/available', params) + } + + async search(params: Record) { + return this.request('/search', params) + } + + async getConstituents(params: Record) { + return this.request('/constituents', params) + } + + async getHistorical(params: Record) { + return this.request('/price/historical', params) + } + + async getSnapshots(params: Record = {}) { + return this.request('/snapshots', params) + } + + async getSectors(params: Record) { + return this.request('/sectors', params) + } + + async getSP500Multiples(params: Record = {}) { + return this.request('/sp500_multiples', params) + } + + async getRiskPremium(params: Record = {}) { + return this.request('/risk_premium', params) + } +} diff --git a/src/domain/market-data/client/typebb/index.ts b/src/domain/market-data/client/typebb/index.ts index b187e6bf..d665a14a 100644 --- a/src/domain/market-data/client/typebb/index.ts +++ b/src/domain/market-data/client/typebb/index.ts @@ -13,3 +13,6 @@ export { SDKCryptoClient } from './crypto-client.js' export { SDKCurrencyClient } from './currency-client.js' export { SDKEconomyClient } from './economy-client.js' export { SDKCommodityClient } from './commodity-client.js' +export { SDKEtfClient } from './etf-client.js' +export { SDKIndexClient } from './index-client.js' +export { SDKDerivativesClient } from './derivatives-client.js' diff --git a/src/domain/market-data/client/types.ts b/src/domain/market-data/client/types.ts index e4b64b08..7b1ccf2d 100644 --- a/src/domain/market-data/client/types.ts +++ b/src/domain/market-data/client/types.ts @@ -1,25 +1,49 @@ /** - * Duck-typed interfaces for OpenBB clients. + * Typed interfaces for market-data clients. * * Both the HTTP clients (OpenBBEquityClient etc.) and SDK clients (SDKEquityClient etc.) * satisfy these interfaces, allowing adapters to accept either implementation. + * + * Return types come from openTypeBB standard models. */ +import type { + // Equity + EquitySearchData, EquityHistoricalData, EquityInfoData, KeyMetricsData, + IncomeStatementData, BalanceSheetData, CashFlowStatementData, FinancialRatiosData, + PriceTargetConsensusData, CalendarEarningsData, InsiderTradingData, EquityDiscoveryData, + // Crypto + CryptoSearchData, CryptoHistoricalData, + // Currency + CurrencyHistoricalData, CurrencySnapshotsData, + // ETF + EtfSearchData, EtfInfoData, EtfHoldingsData, EtfSectorsData, + EtfCountriesData, EtfEquityExposureData, + // Index + AvailableIndicesData, IndexSearchData, IndexConstituentsData, IndexHistoricalData, + IndexSectorsData, SP500MultiplesData, RiskPremiumData, + // Derivatives + FuturesHistoricalData, FuturesCurveData, FuturesInfoData, FuturesInstrumentsData, + OptionsChainsData, OptionsSnapshotsData, OptionsUnusualData, + // Commodity + CommoditySpotPriceData, +} from '@traderalice/opentypebb' + export interface EquityClientLike { - search(params: Record): Promise[]> - getHistorical(params: Record): Promise[]> - getProfile(params: Record): Promise[]> - getKeyMetrics(params: Record): Promise[]> - getIncomeStatement(params: Record): Promise[]> - getBalanceSheet(params: Record): Promise[]> - getCashFlow(params: Record): Promise[]> - getFinancialRatios(params: Record): Promise[]> - getEstimateConsensus(params: Record): Promise[]> - getCalendarEarnings(params?: Record): Promise[]> - getInsiderTrading(params: Record): Promise[]> - getGainers(params?: Record): Promise[]> - getLosers(params?: Record): Promise[]> - getActive(params?: Record): Promise[]> + search(params: Record): Promise + getHistorical(params: Record): Promise + getProfile(params: Record): Promise + getKeyMetrics(params: Record): Promise + getIncomeStatement(params: Record): Promise + getBalanceSheet(params: Record): Promise + getCashFlow(params: Record): Promise + getFinancialRatios(params: Record): Promise + getEstimateConsensus(params: Record): Promise + getCalendarEarnings(params?: Record): Promise + getInsiderTrading(params: Record): Promise + getGainers(params?: Record): Promise + getLosers(params?: Record): Promise + getActive(params?: Record): Promise } export interface EconomyClientLike { @@ -38,12 +62,46 @@ export interface EconomyClientLike { } export interface CryptoClientLike { - search(params: Record): Promise[]> - getHistorical(params: Record): Promise[]> + search(params: Record): Promise + getHistorical(params: Record): Promise } export interface CurrencyClientLike { search(params: Record): Promise[]> + getHistorical(params: Record): Promise +} + +export interface EtfClientLike { + search(params: Record): Promise + getInfo(params: Record): Promise + getHoldings(params: Record): Promise + getSectors(params: Record): Promise + getCountries(params: Record): Promise + getEquityExposure(params: Record): Promise getHistorical(params: Record): Promise[]> } +export interface IndexClientLike { + getAvailable(params?: Record): Promise + search(params: Record): Promise + getConstituents(params: Record): Promise + getHistorical(params: Record): Promise + getSnapshots(params?: Record): Promise[]> + getSectors(params: Record): Promise + getSP500Multiples(params?: Record): Promise + getRiskPremium(params?: Record): Promise +} + +export interface CommodityClientLike { + getSpotPrices(params: Record): Promise +} + +export interface DerivativesClientLike { + getFuturesHistorical(params: Record): Promise + getFuturesCurve(params: Record): Promise + getFuturesInfo(params: Record): Promise + getFuturesInstruments(params?: Record): Promise + getOptionsChains(params: Record): Promise + getOptionsSnapshots(params?: Record): Promise + getOptionsUnusual(params?: Record): Promise +} diff --git a/src/domain/trading/UnifiedTradingAccount.spec.ts b/src/domain/trading/UnifiedTradingAccount.spec.ts index d2ec209d..10884f53 100644 --- a/src/domain/trading/UnifiedTradingAccount.spec.ts +++ b/src/domain/trading/UnifiedTradingAccount.spec.ts @@ -189,7 +189,7 @@ describe('UTA — getState', () => { broker.setPositions([makePosition()]) // Push a limit order to create a pending entry in git history - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'limit', qty: 5, price: 145 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 5, lmtPrice: 145 }) uta.commit('limit buy') await uta.push() @@ -242,98 +242,126 @@ describe('UTA — stagePlaceOrder', () => { ({ uta } = createUTA()) }) - it('maps buy side to BUY action', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + it('sets BUY action', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) const { order } = getStagedPlaceOrder(uta) expect(order.action).toBe('BUY') }) - it('maps sell side to SELL action', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'sell', type: 'market', qty: 10 }) + it('sets SELL action', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'SELL', orderType: 'MKT', totalQuantity: 10 }) const { order } = getStagedPlaceOrder(uta) expect(order.action).toBe('SELL') }) - it('maps order types correctly', () => { - const cases: Array<[string, string]> = [ - ['market', 'MKT'], - ['limit', 'LMT'], - ['stop', 'STP'], - ['stop_limit', 'STP LMT'], - ['trailing_stop', 'TRAIL'], - ] - for (const [input, expected] of cases) { + it('passes order types through', () => { + const types = ['MKT', 'LMT', 'STP', 'STP LMT', 'TRAIL'] + for (const orderType of types) { const { uta: u } = createUTA() - u.stagePlaceOrder({ aliceId: 'mock-paper|X', side: 'buy', type: input, qty: 1 }) + u.stagePlaceOrder({ aliceId: 'mock-paper|X', action: 'BUY', orderType, totalQuantity: 1 }) const { order } = getStagedPlaceOrder(u) - expect(order.orderType).toBe(expected) + expect(order.orderType).toBe(orderType) } }) - it('maps qty to totalQuantity as Decimal', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 42 }) + it('sets totalQuantity as Decimal', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 42 }) const { order } = getStagedPlaceOrder(uta) expect(order.totalQuantity).toBeInstanceOf(Decimal) expect(order.totalQuantity.toNumber()).toBe(42) }) - it('maps notional to cashQty', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', notional: 5000 }) + it('sets cashQty', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', cashQty: 5000 }) const { order } = getStagedPlaceOrder(uta) expect(order.cashQty).toBe(5000) }) - it('maps price to lmtPrice and stopPrice to auxPrice', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'stop_limit', qty: 10, price: 150, stopPrice: 145 }) + it('sets lmtPrice and auxPrice', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'STP LMT', totalQuantity: 10, lmtPrice: 150, auxPrice: 145 }) const { order } = getStagedPlaceOrder(uta) expect(order.lmtPrice).toBe(150) expect(order.auxPrice).toBe(145) }) - it('maps trailingAmount to trailStopPrice (not auxPrice)', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'sell', type: 'trailing_stop', qty: 10, trailingAmount: 5 }) + it('auxPrice sets trailing offset for TRAIL orders', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'SELL', orderType: 'TRAIL', totalQuantity: 10, auxPrice: 5 }) const { order } = getStagedPlaceOrder(uta) - expect(order.trailStopPrice).toBe(5) + expect(order.auxPrice).toBe(5) expect(order.orderType).toBe('TRAIL') }) - it('trailingAmount and stopPrice use separate fields', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'sell', type: 'trailing_stop', qty: 10, stopPrice: 145, trailingAmount: 5 }) + it('TRAIL order with trailStopPrice and auxPrice', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'SELL', orderType: 'TRAIL', totalQuantity: 10, trailStopPrice: 145, auxPrice: 5 }) const { order } = getStagedPlaceOrder(uta) - expect(order.auxPrice).toBe(145) - expect(order.trailStopPrice).toBe(5) + expect(order.trailStopPrice).toBe(145) + expect(order.auxPrice).toBe(5) }) - it('maps trailingPercent to trailingPercent', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'sell', type: 'trailing_stop', qty: 10, trailingPercent: 2.5 }) + it('sets trailingPercent', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'SELL', orderType: 'TRAIL', totalQuantity: 10, trailingPercent: 2.5 }) const { order } = getStagedPlaceOrder(uta) expect(order.trailingPercent).toBe(2.5) }) - it('defaults timeInForce to DAY', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + it('defaults tif to DAY', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) const { order } = getStagedPlaceOrder(uta) expect(order.tif).toBe('DAY') }) - it('allows overriding timeInForce', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'limit', qty: 10, price: 150, timeInForce: 'gtc' }) + it('allows overriding tif', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 10, lmtPrice: 150, tif: 'GTC' }) const { order } = getStagedPlaceOrder(uta) expect(order.tif).toBe('GTC') }) - it('maps extendedHours to outsideRth', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'limit', qty: 10, price: 150, extendedHours: true }) + it('sets outsideRth', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 10, lmtPrice: 150, outsideRth: true }) const { order } = getStagedPlaceOrder(uta) expect(order.outsideRth).toBe(true) }) it('sets aliceId and symbol on contract', () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) const { contract } = getStagedPlaceOrder(uta) expect(contract.aliceId).toBe('mock-paper|AAPL') expect(contract.symbol).toBe('AAPL') }) + + it('sets tpsl with takeProfit only', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10, takeProfit: { price: '160' } }) + const staged = uta.status().staged + const op = staged[0] as Extract + expect(op.tpsl).toEqual({ takeProfit: { price: '160' }, stopLoss: undefined }) + }) + + it('sets tpsl with stopLoss only', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10, stopLoss: { price: '140' } }) + const staged = uta.status().staged + const op = staged[0] as Extract + expect(op.tpsl).toEqual({ takeProfit: undefined, stopLoss: { price: '140' } }) + }) + + it('sets tpsl with both TP and SL', () => { + uta.stagePlaceOrder({ + aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10, + takeProfit: { price: '160' }, stopLoss: { price: '140', limitPrice: '139.50' }, + }) + const staged = uta.status().staged + const op = staged[0] as Extract + expect(op.tpsl).toEqual({ + takeProfit: { price: '160' }, + stopLoss: { price: '140', limitPrice: '139.50' }, + }) + }) + + it('omits tpsl when neither TP nor SL provided', () => { + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) + const staged = uta.status().staged + const op = staged[0] as Extract + expect(op.tpsl).toBeUndefined() + }) }) // ==================== stageModifyOrder ==================== @@ -345,8 +373,8 @@ describe('UTA — stageModifyOrder', () => { ({ uta } = createUTA()) }) - it('maps provided fields to Partial', () => { - uta.stageModifyOrder({ orderId: 'ord-1', qty: 20, price: 155, type: 'limit', timeInForce: 'gtc' }) + it('sets provided fields on Partial', () => { + uta.stageModifyOrder({ orderId: 'ord-1', totalQuantity: 20, lmtPrice: 155, orderType: 'LMT', tif: 'GTC' }) const staged = uta.status().staged expect(staged).toHaveLength(1) const op = staged[0] as Extract @@ -360,7 +388,7 @@ describe('UTA — stageModifyOrder', () => { }) it('omits fields not provided', () => { - uta.stageModifyOrder({ orderId: 'ord-1', price: 160 }) + uta.stageModifyOrder({ orderId: 'ord-1', lmtPrice: 160 }) const staged = uta.status().staged const op = staged[0] as Extract expect(op.changes.lmtPrice).toBe(160) @@ -425,15 +453,15 @@ describe('UTA — git flow', () => { }) it('push throws when not committed', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) await expect(uta.push()).rejects.toThrow('please commit first') }) it('executes multiple operations in a single push', async () => { const { uta: u, broker: b } = createUTA() const spy = vi.spyOn(b, 'placeOrder') - u.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) - u.stagePlaceOrder({ aliceId: 'mock-paper|MSFT', symbol: 'MSFT', side: 'buy', type: 'market', qty: 5 }) + u.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) + u.stagePlaceOrder({ aliceId: 'mock-paper|MSFT', symbol: 'MSFT', action: 'BUY', orderType: 'MKT', totalQuantity: 5 }) u.commit('buy both') await u.push() @@ -441,7 +469,7 @@ describe('UTA — git flow', () => { }) it('clears staging area after push', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy') await uta.push() @@ -462,7 +490,7 @@ describe('UTA — sync', () => { const { uta, broker } = createUTA() // Limit order → MockBroker keeps it pending naturally - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'limit', qty: 10, price: 150 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 10, lmtPrice: 150 }) uta.commit('limit buy') const pushResult = await uta.push() const orderId = pushResult.submitted[0]?.orderId @@ -481,7 +509,7 @@ describe('UTA — sync', () => { const { uta, broker } = createUTA() // Limit order → pending - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'limit', qty: 10, price: 150 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 10, lmtPrice: 150 }) uta.commit('limit buy') const pushResult = await uta.push() const orderId = pushResult.submitted[0]?.orderId @@ -503,7 +531,7 @@ describe('UTA — guards', () => { }) const spy = vi.spyOn(broker, 'placeOrder') - uta.stagePlaceOrder({ aliceId: 'mock-paper|TSLA', symbol: 'TSLA', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|TSLA', symbol: 'TSLA', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy TSLA (should be blocked)') const result = await uta.push() @@ -518,7 +546,7 @@ describe('UTA — guards', () => { }) const spy = vi.spyOn(broker, 'placeOrder') - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy AAPL (allowed)') await uta.push() @@ -532,7 +560,7 @@ describe('UTA — constructor', () => { it('restores from savedState', async () => { // Create a UTA, push a commit, export state const { uta: original } = createUTA() - original.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + original.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) original.commit('initial buy') await original.push() @@ -660,7 +688,7 @@ describe('UTA — health tracking', () => { await expect(uta.getAccount()).rejects.toThrow() } - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy AAPL') await expect(uta.push()).rejects.toThrow(/offline/) await uta.close() diff --git a/src/domain/trading/UnifiedTradingAccount.ts b/src/domain/trading/UnifiedTradingAccount.ts index e25c021c..7d803e3f 100644 --- a/src/domain/trading/UnifiedTradingAccount.ts +++ b/src/domain/trading/UnifiedTradingAccount.ts @@ -9,7 +9,7 @@ import Decimal from 'decimal.js' import { Contract, Order, ContractDescription, ContractDetails, UNSET_DECIMAL } from '@traderalice/ibkr' -import { BrokerError, type IBroker, type AccountInfo, type Position, type OpenOrder, type PlaceOrderResult, type Quote, type MarketClock, type AccountCapabilities, type BrokerHealth, type BrokerHealthInfo } from './brokers/types.js' +import { BrokerError, type IBroker, type AccountInfo, type Position, type OpenOrder, type PlaceOrderResult, type Quote, type MarketClock, type AccountCapabilities, type BrokerHealth, type BrokerHealthInfo, type TpSlParams } from './brokers/types.js' import { TradingGit } from './git/TradingGit.js' import type { Operation, @@ -30,27 +30,6 @@ import type { import { createGuardPipeline, resolveGuards } from './guards/index.js' import './contract-ext.js' -// ==================== IBKR field mapping ==================== - -/** Map human-readable order type → IBKR short code. */ -function toIbkrOrderType(type: string): string { - switch (type) { - case 'market': return 'MKT' - case 'limit': return 'LMT' - case 'stop': return 'STP' - case 'stop_limit': return 'STP LMT' - case 'trailing_stop': return 'TRAIL' - case 'trailing_stop_limit': return 'TRAIL LIMIT' - case 'moc': return 'MOC' - default: return type.toUpperCase() - } -} - -/** Map human-readable TIF → IBKR short code. */ -function toIbkrTif(tif: string): string { - return tif.toUpperCase() -} - // ==================== Options ==================== export interface UnifiedTradingAccountOptions { @@ -69,30 +48,32 @@ export interface UnifiedTradingAccountOptions { export interface StagePlaceOrderParams { aliceId: string symbol?: string - side: 'buy' | 'sell' - type: string - qty?: number - notional?: number - price?: number - stopPrice?: number - trailingAmount?: number + action: 'BUY' | 'SELL' + orderType: string + totalQuantity?: number + cashQty?: number + lmtPrice?: number + auxPrice?: number + trailStopPrice?: number trailingPercent?: number - timeInForce?: string + tif?: string goodTillDate?: string - extendedHours?: boolean + outsideRth?: boolean parentId?: string ocaGroup?: string + takeProfit?: { price: string } + stopLoss?: { price: string; limitPrice?: string } } export interface StageModifyOrderParams { orderId: string - qty?: number - price?: number - stopPrice?: number - trailingAmount?: number + totalQuantity?: number + lmtPrice?: number + auxPrice?: number + trailStopPrice?: number trailingPercent?: number - type?: string - timeInForce?: string + orderType?: string + tif?: string goodTillDate?: string } @@ -166,7 +147,7 @@ export class UnifiedTradingAccount { const dispatcher = async (op: Operation): Promise => { switch (op.action) { case 'placeOrder': - return broker.placeOrder(op.contract, op.order) + return broker.placeOrder(op.contract, op.order, op.tpsl) case 'modifyOrder': return broker.modifyOrder(op.orderId, op.changes) case 'closePosition': @@ -391,33 +372,38 @@ export class UnifiedTradingAccount { if (params.symbol) contract.symbol = params.symbol const order = new Order() - order.action = params.side === 'buy' ? 'BUY' : 'SELL' - order.orderType = toIbkrOrderType(params.type) - order.tif = toIbkrTif(params.timeInForce ?? 'day') - - if (params.qty != null) order.totalQuantity = new Decimal(String(params.qty)) - if (params.notional != null) order.cashQty = params.notional - if (params.price != null) order.lmtPrice = params.price - if (params.stopPrice != null) order.auxPrice = params.stopPrice - if (params.trailingAmount != null) order.trailStopPrice = params.trailingAmount + order.action = params.action + order.orderType = params.orderType + order.tif = params.tif ?? 'DAY' + + if (params.totalQuantity != null) order.totalQuantity = new Decimal(String(params.totalQuantity)) + if (params.cashQty != null) order.cashQty = params.cashQty + if (params.lmtPrice != null) order.lmtPrice = params.lmtPrice + if (params.auxPrice != null) order.auxPrice = params.auxPrice + if (params.trailStopPrice != null) order.trailStopPrice = params.trailStopPrice if (params.trailingPercent != null) order.trailingPercent = params.trailingPercent if (params.goodTillDate != null) order.goodTillDate = params.goodTillDate - if (params.extendedHours) order.outsideRth = true + if (params.outsideRth) order.outsideRth = true if (params.parentId != null) order.parentId = parseInt(params.parentId, 10) || 0 if (params.ocaGroup != null) order.ocaGroup = params.ocaGroup - return this.git.add({ action: 'placeOrder', contract, order }) + const tpsl: TpSlParams | undefined = + (params.takeProfit || params.stopLoss) + ? { takeProfit: params.takeProfit, stopLoss: params.stopLoss } + : undefined + + return this.git.add({ action: 'placeOrder', contract, order, tpsl }) } stageModifyOrder(params: StageModifyOrderParams): AddResult { const changes: Partial = {} - if (params.qty != null) changes.totalQuantity = new Decimal(String(params.qty)) - if (params.price != null) changes.lmtPrice = params.price - if (params.stopPrice != null) changes.auxPrice = params.stopPrice - if (params.trailingAmount != null) changes.trailStopPrice = params.trailingAmount + if (params.totalQuantity != null) changes.totalQuantity = new Decimal(String(params.totalQuantity)) + if (params.lmtPrice != null) changes.lmtPrice = params.lmtPrice + if (params.auxPrice != null) changes.auxPrice = params.auxPrice + if (params.trailStopPrice != null) changes.trailStopPrice = params.trailStopPrice if (params.trailingPercent != null) changes.trailingPercent = params.trailingPercent - if (params.type != null) changes.orderType = toIbkrOrderType(params.type) - if (params.timeInForce != null) changes.tif = toIbkrTif(params.timeInForce) + if (params.orderType != null) changes.orderType = params.orderType + if (params.tif != null) changes.tif = params.tif if (params.goodTillDate != null) changes.goodTillDate = params.goodTillDate return this.git.add({ action: 'modifyOrder', orderId: params.orderId, changes }) diff --git a/src/domain/trading/__test__/e2e/ccxt-bybit.e2e.spec.ts b/src/domain/trading/__test__/e2e/ccxt-bybit.e2e.spec.ts index 713ac8b1..f616bfae 100644 --- a/src/domain/trading/__test__/e2e/ccxt-bybit.e2e.spec.ts +++ b/src/domain/trading/__test__/e2e/ccxt-bybit.e2e.spec.ts @@ -136,4 +136,100 @@ describe('CcxtBroker — Bybit e2e', () => { // Clean up await b().closePosition(ethPerp.contract, new Decimal('0.01')) }, 15_000) + + it('places order with TPSL and reads back tpsl from getOrder', async ({ skip }) => { + const matches = await b().searchContracts('ETH') + const ethPerp = matches.find(m => m.contract.localSymbol?.includes('USDT:USDT')) + if (!ethPerp) return skip('ETH/USDT perp not found') + + const order = new Order() + order.action = 'BUY' + order.orderType = 'MKT' + order.totalQuantity = new Decimal('0.01') + + // Get current price to set reasonable TP/SL + const quote = await b().getQuote(ethPerp.contract) + const tpPrice = Math.round(quote.last * 1.5) // 50% above — won't trigger + const slPrice = Math.round(quote.last * 0.5) // 50% below — won't trigger + + const placed = await b().placeOrder(ethPerp.contract, order, { + takeProfit: { price: String(tpPrice) }, + stopLoss: { price: String(slPrice) }, + }) + expect(placed.success).toBe(true) + console.log(` placed with TPSL: orderId=${placed.orderId}, tp=${tpPrice}, sl=${slPrice}`) + + // Wait for exchange to register + await new Promise(r => setTimeout(r, 3000)) + + const detail = await b().getOrder(placed.orderId!) + expect(detail).not.toBeNull() + console.log(` getOrder tpsl:`, JSON.stringify(detail!.tpsl)) + + // CCXT should populate takeProfitPrice/stopLossPrice on the fetched order + if (detail!.tpsl) { + if (detail!.tpsl.takeProfit) { + expect(parseFloat(detail!.tpsl.takeProfit.price)).toBe(tpPrice) + } + if (detail!.tpsl.stopLoss) { + expect(parseFloat(detail!.tpsl.stopLoss.price)).toBe(slPrice) + } + } else { + // Some exchanges don't return TP/SL on the parent order — log for visibility + console.log(' NOTE: exchange did not return TPSL on fetched order (may be separate conditional orders)') + } + + // Clean up + await b().closePosition(ethPerp.contract, new Decimal('0.01')) + }, 30_000) + + it('queries conditional/trigger order by ID (#90)', async ({ skip }) => { + // Place a stop-loss trigger order far from market price, then verify getOrder can see it. + // This is the core scenario from issue #90. + const matches = await b().searchContracts('ETH') + const ethPerp = matches.find(m => m.contract.localSymbol?.includes('USDT:USDT')) + if (!ethPerp) return skip('ETH/USDT perp not found') + + // Open a small position first — stop-loss with reduceOnly needs an existing position + const buyOrder = new Order() + buyOrder.action = 'BUY' + buyOrder.orderType = 'MKT' + buyOrder.totalQuantity = new Decimal('0.01') + const buyResult = await b().placeOrder(ethPerp.contract, buyOrder) + if (!buyResult.success) return skip('could not open position for stop-loss test') + + // Get current price to set a trigger far away (won't execute) + const quote = await b().getQuote(ethPerp.contract) + const triggerPrice = Math.round(quote.last * 0.5) // 50% below — will never trigger + + // Place a conditional sell order via raw CCXT (with triggerPrice). + // Bybit requires triggerDirection: price falling below trigger = "descending". + const exchange = (b() as any).exchange + const rawOrder = await exchange.createOrder( + 'ETH/USDT:USDT', 'market', 'sell', 0.01, + undefined, + { triggerPrice, triggerDirection: 'descending', reduceOnly: true }, + ) + console.log(` placed conditional order: id=${rawOrder.id}, triggerPrice=${triggerPrice}`) + expect(rawOrder.id).toBeDefined() + + // Wait for exchange to register the order + await new Promise(r => setTimeout(r, 2000)) + + // Seed the symbol cache (normally done by placeOrder, but we used raw CCXT) + ;(b() as any).orderSymbolCache.set(rawOrder.id, 'ETH/USDT:USDT') + + // This is the bug from #90: getOrder must find a conditional order + const detail = await b().getOrder(rawOrder.id) + console.log(` getOrder(${rawOrder.id}): ${detail ? `status=${detail.orderState.status}` : 'null (BUG: conditional order invisible)'}`) + + expect(detail).not.toBeNull() + + // Clean up — cancel the conditional order, then close position + const cancelResult = await b().cancelOrder(rawOrder.id) + console.log(` cancel conditional: success=${cancelResult.success}`) + expect(cancelResult.success).toBe(true) + + await b().closePosition(ethPerp.contract, new Decimal('0.01')) + }, 30_000) }) diff --git a/src/domain/trading/__test__/e2e/uta-alpaca.e2e.spec.ts b/src/domain/trading/__test__/e2e/uta-alpaca.e2e.spec.ts index aff1961c..68133d7f 100644 --- a/src/domain/trading/__test__/e2e/uta-alpaca.e2e.spec.ts +++ b/src/domain/trading/__test__/e2e/uta-alpaca.e2e.spec.ts @@ -43,11 +43,11 @@ describe('UTA — Alpaca order lifecycle', () => { const addResult = uta!.stagePlaceOrder({ aliceId, symbol: 'AAPL', - side: 'buy', - type: 'limit', - price: 1.00, - qty: 1, - timeInForce: 'gtc', + action: 'BUY', + orderType: 'LMT', + lmtPrice: 1.00, + totalQuantity: 1, + tif: 'GTC', }) expect(addResult.staged).toBe(true) @@ -75,6 +75,49 @@ describe('UTA — Alpaca order lifecycle', () => { }, 30_000) }) +// ==================== TPSL bracket order (market hours only) ==================== + +describe('UTA — Alpaca TPSL bracket', () => { + beforeEach(({ skip }) => { + if (!uta) skip('no Alpaca paper account') + if (!marketOpen) skip('market closed') + }) + + it('market buy with TPSL → getOrder returns bracket legs', async () => { + const nativeKey = broker!.getNativeKey({ symbol: 'AAPL' } as any) + const aliceId = `${uta!.id}|${nativeKey}` + + uta!.stagePlaceOrder({ + aliceId, symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 1, + takeProfit: { price: '999' }, + stopLoss: { price: '1' }, + }) + uta!.commit('e2e: buy AAPL with TPSL') + const pushResult = await uta!.push() + expect(pushResult.submitted).toHaveLength(1) + const orderId = pushResult.submitted[0].orderId! + console.log(` TPSL bracket: orderId=${orderId}`) + + await new Promise(r => setTimeout(r, 2000)) + + const detail = await broker!.getOrder(orderId) + expect(detail).not.toBeNull() + console.log(` fetched tpsl:`, JSON.stringify(detail!.tpsl)) + + if (detail!.tpsl) { + if (detail!.tpsl.takeProfit) expect(detail!.tpsl.takeProfit.price).toBe('999') + if (detail!.tpsl.stopLoss) expect(detail!.tpsl.stopLoss.price).toBe('1') + } else { + console.log(' NOTE: Alpaca did not return legs on fetched bracket order') + } + + // Clean up — cancel the bracket legs then close position + uta!.stageClosePosition({ aliceId, qty: 1 }) + uta!.commit('e2e: close TPSL AAPL') + await uta!.push() + }, 30_000) +}) + // ==================== Full fill flow (market hours only) ==================== describe('UTA — Alpaca fill flow (AAPL)', () => { @@ -96,9 +139,9 @@ describe('UTA — Alpaca fill flow (AAPL)', () => { const addResult = uta!.stagePlaceOrder({ aliceId, symbol: 'AAPL', - side: 'buy', - type: 'market', - qty: 1, + action: 'BUY', + orderType: 'MKT', + totalQuantity: 1, }) expect(addResult.staged).toBe(true) diff --git a/src/domain/trading/__test__/e2e/uta-bybit.e2e.spec.ts b/src/domain/trading/__test__/e2e/uta-bybit.e2e.spec.ts index 4f9123e1..6aa5161e 100644 --- a/src/domain/trading/__test__/e2e/uta-bybit.e2e.spec.ts +++ b/src/domain/trading/__test__/e2e/uta-bybit.e2e.spec.ts @@ -52,9 +52,9 @@ describe('UTA — Bybit lifecycle (ETH perp)', () => { // === Stage + Commit + Push: buy 0.01 ETH === const addResult = uta!.stagePlaceOrder({ aliceId: ethAliceId, - side: 'buy', - type: 'market', - qty: 0.01, + action: 'BUY', + orderType: 'MKT', + totalQuantity: 0.01, }) expect(addResult.staged).toBe(true) console.log(` staged: ok`) @@ -117,4 +117,39 @@ describe('UTA — Bybit lifecycle (ETH perp)', () => { console.log(` log: ${history.length} commits — [${history.map(h => h.message).join(', ')}]`) expect(history.length).toBeGreaterThanOrEqual(2) }, 60_000) + + it('buy with TPSL → tpsl visible on fetched order', async () => { + const quote = await broker!.getQuote(broker!.resolveNativeKey(ethAliceId.split('|')[1])) + const tpPrice = Math.round(quote.last * 1.5) + const slPrice = Math.round(quote.last * 0.5) + + uta!.stagePlaceOrder({ + aliceId: ethAliceId, action: 'BUY', orderType: 'MKT', totalQuantity: 0.01, + takeProfit: { price: String(tpPrice) }, + stopLoss: { price: String(slPrice) }, + }) + uta!.commit('e2e: buy ETH with TPSL') + const pushResult = await uta!.push() + expect(pushResult.submitted).toHaveLength(1) + const orderId = pushResult.submitted[0].orderId! + console.log(` TPSL: orderId=${orderId}, tp=${tpPrice}, sl=${slPrice}`) + + await new Promise(r => setTimeout(r, 3000)) + + const detail = await broker!.getOrder(orderId) + expect(detail).not.toBeNull() + console.log(` fetched tpsl:`, JSON.stringify(detail!.tpsl)) + + if (detail!.tpsl) { + if (detail!.tpsl.takeProfit) expect(parseFloat(detail!.tpsl.takeProfit.price)).toBe(tpPrice) + if (detail!.tpsl.stopLoss) expect(parseFloat(detail!.tpsl.stopLoss.price)).toBe(slPrice) + } else { + console.log(' NOTE: TPSL not returned on fetched order (separate conditional orders)') + } + + // Clean up + uta!.stageClosePosition({ aliceId: ethAliceId, qty: 0.01 }) + uta!.commit('e2e: close TPSL') + await uta!.push() + }, 60_000) }) diff --git a/src/domain/trading/__test__/e2e/uta-ccxt-bybit.e2e.spec.ts b/src/domain/trading/__test__/e2e/uta-ccxt-bybit.e2e.spec.ts index 36d5f684..99d89e1f 100644 --- a/src/domain/trading/__test__/e2e/uta-ccxt-bybit.e2e.spec.ts +++ b/src/domain/trading/__test__/e2e/uta-ccxt-bybit.e2e.spec.ts @@ -48,7 +48,7 @@ describe('UTA — Bybit demo (ETH perp)', () => { console.log(` initial ETH qty=${initialQty}`) // Stage + Commit + Push: buy 0.01 ETH - uta!.stagePlaceOrder({ aliceId: ethAliceId, side: 'buy', type: 'market', qty: 0.01 }) + uta!.stagePlaceOrder({ aliceId: ethAliceId, action: 'BUY', orderType: 'MKT', totalQuantity: 0.01 }) uta!.commit('e2e: buy 0.01 ETH') const pushResult = await uta!.push() expect(pushResult.submitted).toHaveLength(1) @@ -97,9 +97,45 @@ describe('UTA — Bybit demo (ETH perp)', () => { console.log(` log: ${log.length} commits`) }, 60_000) + it('buy with TPSL → getOrder returns tpsl', async () => { + const quote = await broker!.getQuote(broker!.resolveNativeKey(ethAliceId.split('|')[1])) + const tpPrice = Math.round(quote.last * 1.5) + const slPrice = Math.round(quote.last * 0.5) + + uta!.stagePlaceOrder({ + aliceId: ethAliceId, action: 'BUY', orderType: 'MKT', totalQuantity: 0.01, + takeProfit: { price: String(tpPrice) }, + stopLoss: { price: String(slPrice) }, + }) + uta!.commit('e2e: buy 0.01 ETH with TPSL') + const pushResult = await uta!.push() + expect(pushResult.submitted).toHaveLength(1) + const orderId = pushResult.submitted[0].orderId! + console.log(` TPSL order: orderId=${orderId}, tp=${tpPrice}, sl=${slPrice}`) + + // Wait for exchange to settle + await new Promise(r => setTimeout(r, 3000)) + + const detail = await broker!.getOrder(orderId) + expect(detail).not.toBeNull() + console.log(` getOrder tpsl:`, JSON.stringify(detail!.tpsl)) + + if (detail!.tpsl) { + if (detail!.tpsl.takeProfit) expect(parseFloat(detail!.tpsl.takeProfit.price)).toBe(tpPrice) + if (detail!.tpsl.stopLoss) expect(parseFloat(detail!.tpsl.stopLoss.price)).toBe(slPrice) + } else { + console.log(' NOTE: exchange did not return TPSL on fetched order') + } + + // Clean up + uta!.stageClosePosition({ aliceId: ethAliceId, qty: 0.01 }) + uta!.commit('e2e: close TPSL position') + await uta!.push() + }, 60_000) + it('reject records user-rejected commit and clears staging', async () => { // Stage + Commit (but don't push) - uta!.stagePlaceOrder({ aliceId: ethAliceId, side: 'buy', type: 'market', qty: 0.01 }) + uta!.stagePlaceOrder({ aliceId: ethAliceId, action: 'BUY', orderType: 'MKT', totalQuantity: 0.01 }) const commitResult = uta!.commit('e2e: buy to be rejected') expect(commitResult.prepared).toBe(true) @@ -131,7 +167,7 @@ describe('UTA — Bybit demo (ETH perp)', () => { }, 30_000) it('reject without reason still works', async () => { - uta!.stagePlaceOrder({ aliceId: ethAliceId, side: 'sell', type: 'limit', qty: 0.01, price: 99999 }) + uta!.stagePlaceOrder({ aliceId: ethAliceId, action: 'SELL', orderType: 'LMT', totalQuantity: 0.01, lmtPrice: 99999 }) uta!.commit('e2e: sell to be rejected silently') const result = await uta!.reject() diff --git a/src/domain/trading/__test__/e2e/uta-ibkr.e2e.spec.ts b/src/domain/trading/__test__/e2e/uta-ibkr.e2e.spec.ts index 22f9edd6..f76a11f9 100644 --- a/src/domain/trading/__test__/e2e/uta-ibkr.e2e.spec.ts +++ b/src/domain/trading/__test__/e2e/uta-ibkr.e2e.spec.ts @@ -47,11 +47,11 @@ describe('UTA — IBKR order lifecycle', () => { const addResult = uta!.stagePlaceOrder({ aliceId, symbol: 'AAPL', - side: 'buy', - type: 'limit', - price: 1.00, - qty: 1, - timeInForce: 'gtc', + action: 'BUY', + orderType: 'LMT', + lmtPrice: 1.00, + totalQuantity: 1, + tif: 'GTC', }) expect(addResult.staged).toBe(true) @@ -79,6 +79,37 @@ describe('UTA — IBKR order lifecycle', () => { }, 30_000) }) +// ==================== TPSL param pass-through (any time) ==================== + +describe('UTA — IBKR TPSL pass-through', () => { + beforeEach(({ skip }) => { if (!uta) skip('no IBKR paper account') }) + + it('tpsl param does not break order placement', async () => { + const results = await broker!.searchContracts('AAPL') + const nativeKey = broker!.getNativeKey(results[0].contract) + const aliceId = `${uta!.id}|${nativeKey}` + + // Stage limit order with TPSL — IBKR ignores tpsl but it should not error + uta!.stagePlaceOrder({ + aliceId, symbol: 'AAPL', action: 'BUY', orderType: 'LMT', + lmtPrice: 1.00, totalQuantity: 1, tif: 'GTC', + takeProfit: { price: '300' }, + stopLoss: { price: '100' }, + }) + uta!.commit('e2e: IBKR limit with TPSL (ignored)') + const pushResult = await uta!.push() + console.log(` pushed with TPSL: submitted=${pushResult.submitted.length}, status=${pushResult.submitted[0]?.status}`) + expect(pushResult.submitted).toHaveLength(1) + expect(pushResult.rejected).toHaveLength(0) + + // Clean up + const orderId = pushResult.submitted[0].orderId! + uta!.stageCancelOrder({ orderId }) + uta!.commit('e2e: cancel TPSL order') + await uta!.push() + }, 30_000) +}) + // ==================== Full fill flow (market hours only) ==================== describe('UTA — IBKR fill flow (AAPL)', () => { @@ -102,9 +133,9 @@ describe('UTA — IBKR fill flow (AAPL)', () => { const addResult = uta!.stagePlaceOrder({ aliceId, symbol: 'AAPL', - side: 'buy', - type: 'market', - qty: 1, + action: 'BUY', + orderType: 'MKT', + totalQuantity: 1, }) expect(addResult.staged).toBe(true) diff --git a/src/domain/trading/__test__/e2e/uta-lifecycle.e2e.spec.ts b/src/domain/trading/__test__/e2e/uta-lifecycle.e2e.spec.ts index 162784c8..5fa4e1e3 100644 --- a/src/domain/trading/__test__/e2e/uta-lifecycle.e2e.spec.ts +++ b/src/domain/trading/__test__/e2e/uta-lifecycle.e2e.spec.ts @@ -9,7 +9,7 @@ * placeOrder returns submitted — fill confirmed via getOrder/sync. */ -import { describe, it, expect, beforeEach } from 'vitest' +import { describe, it, expect, beforeEach, vi } from 'vitest' import { UnifiedTradingAccount } from '../../UnifiedTradingAccount.js' import { MockBroker } from '../../brokers/mock/index.js' import '../../contract-ext.js' @@ -28,7 +28,7 @@ beforeEach(() => { describe('UTA — full trading lifecycle', () => { it('market buy: push returns submitted, position appears, cash decreases', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) const commitResult = uta.commit('buy 10 AAPL') expect(commitResult.prepared).toBe(true) @@ -50,7 +50,7 @@ describe('UTA — full trading lifecycle', () => { }) it('market buy fills at push time — no sync needed', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy AAPL') const pushResult = await uta.push() @@ -63,12 +63,12 @@ describe('UTA — full trading lifecycle', () => { }) it('getState reflects positions and pending orders', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy AAPL') await uta.push() // Place a limit order (goes submitted) - uta.stagePlaceOrder({ aliceId: 'mock-paper|ETH', symbol: 'ETH', side: 'buy', type: 'limit', qty: 1, price: 1800 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|ETH', symbol: 'ETH', action: 'BUY', orderType: 'LMT', totalQuantity: 1, lmtPrice: 1800 }) uta.commit('limit buy ETH') const limitPush = await uta.push() expect(limitPush.submitted).toHaveLength(1) @@ -80,7 +80,7 @@ describe('UTA — full trading lifecycle', () => { }) it('limit order → submitted → fill → sync detects filled', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'limit', qty: 5, price: 145 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 5, lmtPrice: 145 }) uta.commit('limit buy AAPL') const pushResult = await uta.push() expect(pushResult.submitted).toHaveLength(1) @@ -107,7 +107,7 @@ describe('UTA — full trading lifecycle', () => { }) it('partial close reduces position', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy') await uta.push() @@ -122,7 +122,7 @@ describe('UTA — full trading lifecycle', () => { }) it('full close removes position + restores cash', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy') await uta.push() @@ -136,7 +136,7 @@ describe('UTA — full trading lifecycle', () => { }) it('cancel pending order', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'limit', qty: 5, price: 140 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'LMT', totalQuantity: 5, lmtPrice: 140 }) uta.commit('limit buy') const pushResult = await uta.push() const orderId = pushResult.submitted[0].orderId! @@ -150,7 +150,7 @@ describe('UTA — full trading lifecycle', () => { }) it('trading history records all commits', async () => { - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy AAPL') await uta.push() @@ -165,12 +165,49 @@ describe('UTA — full trading lifecycle', () => { }) }) +// ==================== TPSL end-to-end ==================== + +describe('UTA — TPSL end-to-end', () => { + it('tpsl params flow through to broker.placeOrder', async () => { + const spy = vi.spyOn(broker, 'placeOrder') + + uta.stagePlaceOrder({ + aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10, + takeProfit: { price: '160' }, + stopLoss: { price: '140', limitPrice: '139.50' }, + }) + uta.commit('buy AAPL with TPSL') + const result = await uta.push() + + expect(result.submitted).toHaveLength(1) + expect(spy).toHaveBeenCalledTimes(1) + + // Verify tpsl reached the broker (3rd argument) + const tpslArg = spy.mock.calls[0][2] + expect(tpslArg).toEqual({ + takeProfit: { price: '160' }, + stopLoss: { price: '140', limitPrice: '139.50' }, + }) + }) + + it('order without tpsl passes undefined to broker', async () => { + const spy = vi.spyOn(broker, 'placeOrder') + + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', symbol: 'AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) + uta.commit('buy AAPL no TPSL') + await uta.push() + + const tpslArg = spy.mock.calls[0][2] + expect(tpslArg).toBeUndefined() + }) +}) + // ==================== Precision end-to-end ==================== describe('UTA — precision end-to-end', () => { it('fractional qty survives stage → push → position', async () => { broker.setQuote('ETH', 1920) - uta.stagePlaceOrder({ aliceId: 'mock-paper|ETH', symbol: 'ETH', side: 'buy', type: 'market', qty: 0.123456789 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|ETH', symbol: 'ETH', action: 'BUY', orderType: 'MKT', totalQuantity: 0.123456789 }) uta.commit('buy fractional ETH') const result = await uta.push() @@ -181,7 +218,7 @@ describe('UTA — precision end-to-end', () => { it('partial close precision: 1.0 - 0.3 = 0.7 exactly', async () => { broker.setQuote('ETH', 1920) - uta.stagePlaceOrder({ aliceId: 'mock-paper|ETH', symbol: 'ETH', side: 'buy', type: 'market', qty: 1.0 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|ETH', symbol: 'ETH', action: 'BUY', orderType: 'MKT', totalQuantity: 1.0 }) uta.commit('buy 1 ETH') await uta.push() diff --git a/src/domain/trading/__test__/uta-health.spec.ts b/src/domain/trading/__test__/uta-health.spec.ts index 4dbeaba7..33573772 100644 --- a/src/domain/trading/__test__/uta-health.spec.ts +++ b/src/domain/trading/__test__/uta-health.spec.ts @@ -215,7 +215,7 @@ describe('UTA health — offline behavior', () => { await expect(uta.getAccount()).rejects.toThrow() } - uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) uta.commit('buy AAPL') await expect(uta.push()).rejects.toThrow(/offline/) await uta.close() @@ -231,7 +231,7 @@ describe('UTA health — offline behavior', () => { } // Staging is a local operation — should work even when offline - const result = uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', side: 'buy', type: 'market', qty: 10 }) + const result = uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) expect(result.staged).toBe(true) const commit = uta.commit('buy while offline') diff --git a/src/domain/trading/brokers/alpaca/AlpacaBroker.spec.ts b/src/domain/trading/brokers/alpaca/AlpacaBroker.spec.ts index 266b5351..d5cfdac2 100644 --- a/src/domain/trading/brokers/alpaca/AlpacaBroker.spec.ts +++ b/src/domain/trading/brokers/alpaca/AlpacaBroker.spec.ts @@ -269,6 +269,59 @@ describe('AlpacaBroker — modifyOrder()', () => { }) }) +// ==================== modifyOrder — null-check safety ==================== + +describe('AlpacaBroker — modifyOrder null-check', () => { + beforeEach(() => vi.clearAllMocks()) + + it('does not send undefined lmtPrice/auxPrice/trailingPercent when only qty changes', async () => { + const acc = new AlpacaBroker({ apiKey: 'k', secretKey: 's', paper: true }) + const replaceOrder = vi.fn().mockResolvedValue({ id: 'ord-mod', status: 'accepted' }) + ;(acc as any).client = { replaceOrder } + + // Partial — only totalQuantity set, everything else is undefined + const changes: Partial = { totalQuantity: new Decimal(20) } + + await acc.modifyOrder('ord-1', changes) + const patch = replaceOrder.mock.calls[0][1] + + expect(patch.qty).toBe(20) + // These should NOT be in the patch — they were undefined, not UNSET_DOUBLE + expect(patch).not.toHaveProperty('limit_price') + expect(patch).not.toHaveProperty('stop_price') + expect(patch).not.toHaveProperty('trail') + }) + + it('sends lmtPrice when explicitly set in changes', async () => { + const acc = new AlpacaBroker({ apiKey: 'k', secretKey: 's', paper: true }) + const replaceOrder = vi.fn().mockResolvedValue({ id: 'ord-mod', status: 'accepted' }) + ;(acc as any).client = { replaceOrder } + + const changes: Partial = { lmtPrice: 155.50 } + + await acc.modifyOrder('ord-1', changes) + const patch = replaceOrder.mock.calls[0][1] + + expect(patch.limit_price).toBe(155.50) + expect(patch).not.toHaveProperty('stop_price') + expect(patch).not.toHaveProperty('trail') + }) + + it('sends auxPrice as stop_price when explicitly set', async () => { + const acc = new AlpacaBroker({ apiKey: 'k', secretKey: 's', paper: true }) + const replaceOrder = vi.fn().mockResolvedValue({ id: 'ord-mod', status: 'accepted' }) + ;(acc as any).client = { replaceOrder } + + const changes: Partial = { auxPrice: 140 } + + await acc.modifyOrder('ord-1', changes) + const patch = replaceOrder.mock.calls[0][1] + + expect(patch.stop_price).toBe(140) + expect(patch).not.toHaveProperty('limit_price') + }) +}) + // ==================== cancelOrder ==================== describe('AlpacaBroker — cancelOrder()', () => { @@ -514,6 +567,71 @@ describe('AlpacaBroker — getOrder()', () => { // IBKR orderId is number — UUID can't fit, so it should be 0 expect(result!.order.orderId).toBe(0) }) + + it('extracts tpsl from bracket order legs', async () => { + const acc = new AlpacaBroker({ apiKey: 'k', secretKey: 's', paper: true }) + ;(acc as any).client = { + getOrder: vi.fn().mockResolvedValue({ + id: 'ord-bracket', symbol: 'AAPL', side: 'buy', qty: '10', notional: null, + type: 'market', limit_price: null, stop_price: null, + time_in_force: 'day', extended_hours: false, + status: 'filled', reject_reason: null, + order_class: 'bracket', + legs: [ + { id: 'tp-1', symbol: 'AAPL', side: 'sell', qty: '10', notional: null, + type: 'limit', limit_price: '160.00', stop_price: null, + time_in_force: 'gtc', extended_hours: false, status: 'new', reject_reason: null }, + { id: 'sl-1', symbol: 'AAPL', side: 'sell', qty: '10', notional: null, + type: 'stop', limit_price: null, stop_price: '140.00', + time_in_force: 'gtc', extended_hours: false, status: 'new', reject_reason: null }, + ], + }), + } + + const result = await acc.getOrder('ord-bracket') + expect(result!.tpsl).toEqual({ + takeProfit: { price: '160.00' }, + stopLoss: { price: '140.00' }, + }) + }) + + it('extracts stop-limit SL with limitPrice', async () => { + const acc = new AlpacaBroker({ apiKey: 'k', secretKey: 's', paper: true }) + ;(acc as any).client = { + getOrder: vi.fn().mockResolvedValue({ + id: 'ord-stp-lmt', symbol: 'AAPL', side: 'buy', qty: '10', notional: null, + type: 'market', limit_price: null, stop_price: null, + time_in_force: 'day', extended_hours: false, + status: 'filled', reject_reason: null, + order_class: 'bracket', + legs: [ + { id: 'sl-2', symbol: 'AAPL', side: 'sell', qty: '10', notional: null, + type: 'stop_limit', limit_price: '139.50', stop_price: '140.00', + time_in_force: 'gtc', extended_hours: false, status: 'new', reject_reason: null }, + ], + }), + } + + const result = await acc.getOrder('ord-stp-lmt') + expect(result!.tpsl).toEqual({ + stopLoss: { price: '140.00', limitPrice: '139.50' }, + }) + }) + + it('returns no tpsl for simple (non-bracket) orders', async () => { + const acc = new AlpacaBroker({ apiKey: 'k', secretKey: 's', paper: true }) + ;(acc as any).client = { + getOrder: vi.fn().mockResolvedValue({ + id: 'ord-simple', symbol: 'AAPL', side: 'buy', qty: '10', notional: null, + type: 'market', limit_price: null, stop_price: null, + time_in_force: 'day', extended_hours: false, + status: 'filled', reject_reason: null, + }), + } + + const result = await acc.getOrder('ord-simple') + expect(result!.tpsl).toBeUndefined() + }) }) // ==================== getQuote ==================== diff --git a/src/domain/trading/brokers/alpaca/AlpacaBroker.ts b/src/domain/trading/brokers/alpaca/AlpacaBroker.ts index e7737fb4..8ea49916 100644 --- a/src/domain/trading/brokers/alpaca/AlpacaBroker.ts +++ b/src/domain/trading/brokers/alpaca/AlpacaBroker.ts @@ -23,6 +23,7 @@ import { type Quote, type MarketClock, type BrokerConfigField, + type TpSlParams, } from '../types.js' import { QuoteCache } from '../../quote-cache.js' import '../../contract-ext.js' @@ -286,7 +287,7 @@ export class AlpacaBroker implements IBroker { // ---- Trading operations ---- - async placeOrder(contract: Contract, order: Order): Promise { + async placeOrder(contract: Contract, order: Order, tpsl?: TpSlParams): Promise { const symbol = resolveSymbol(contract) if (!symbol) { return { success: false, error: 'Cannot resolve contract to Alpaca symbol' } @@ -320,6 +321,20 @@ export class AlpacaBroker implements IBroker { if (order.trailingPercent !== UNSET_DOUBLE) alpacaOrder.trail_percent = order.trailingPercent if (order.outsideRth) alpacaOrder.extended_hours = true + // Bracket order (TPSL) + if (tpsl?.takeProfit || tpsl?.stopLoss) { + alpacaOrder.order_class = 'bracket' + if (tpsl.takeProfit) { + alpacaOrder.take_profit = { limit_price: parseFloat(tpsl.takeProfit.price) } + } + if (tpsl.stopLoss) { + alpacaOrder.stop_loss = { + stop_price: parseFloat(tpsl.stopLoss.price), + ...(tpsl.stopLoss.limitPrice && { limit_price: parseFloat(tpsl.stopLoss.limitPrice) }), + } + } + } + const result = await this.client.createOrder(alpacaOrder) as AlpacaOrderRaw return { success: true, @@ -335,9 +350,9 @@ export class AlpacaBroker implements IBroker { try { const patch: Record = {} if (changes.totalQuantity != null && !changes.totalQuantity.equals(UNSET_DECIMAL)) patch.qty = parseFloat(changes.totalQuantity.toString()) - if (changes.lmtPrice !== UNSET_DOUBLE) patch.limit_price = changes.lmtPrice - if (changes.auxPrice !== UNSET_DOUBLE) patch.stop_price = changes.auxPrice - if (changes.trailingPercent !== UNSET_DOUBLE) patch.trail = changes.trailingPercent + if (changes.lmtPrice != null && changes.lmtPrice !== UNSET_DOUBLE) patch.limit_price = changes.lmtPrice + if (changes.auxPrice != null && changes.auxPrice !== UNSET_DOUBLE) patch.stop_price = changes.auxPrice + if (changes.trailingPercent != null && changes.trailingPercent !== UNSET_DOUBLE) patch.trail = changes.trailingPercent if (changes.tif) patch.time_in_force = ibkrTifToAlpaca(changes.tif) const result = await this.client.replaceOrder(orderId, patch) as AlpacaOrderRaw @@ -542,11 +557,31 @@ export class AlpacaBroker implements IBroker { // The real string ID is carried via nativeOrderId on OpenOrder. order.orderId = 0 + const tpsl = this.extractTpSl(o) return { contract, order, orderState: makeOrderState(o.status, o.reject_reason ?? undefined), nativeOrderId: o.id, + ...(tpsl && { tpsl }), + } + } + + private extractTpSl(o: AlpacaOrderRaw): TpSlParams | undefined { + if (o.order_class !== 'bracket' || !o.legs?.length) return undefined + let takeProfit: TpSlParams['takeProfit'] + let stopLoss: TpSlParams['stopLoss'] + for (const leg of o.legs) { + if (leg.limit_price && !leg.stop_price) { + takeProfit = { price: leg.limit_price } + } else if (leg.stop_price) { + stopLoss = { + price: leg.stop_price, + ...(leg.limit_price && { limitPrice: leg.limit_price }), + } + } } + if (!takeProfit && !stopLoss) return undefined + return { takeProfit, stopLoss } } } diff --git a/src/domain/trading/brokers/alpaca/alpaca-types.ts b/src/domain/trading/brokers/alpaca/alpaca-types.ts index 71640fee..927be23c 100644 --- a/src/domain/trading/brokers/alpaca/alpaca-types.ts +++ b/src/domain/trading/brokers/alpaca/alpaca-types.ts @@ -46,6 +46,8 @@ export interface AlpacaOrderRaw { filled_at: string | null created_at: string reject_reason: string | null + order_class?: string + legs?: AlpacaOrderRaw[] } export interface AlpacaSnapshotRaw { diff --git a/src/domain/trading/brokers/ccxt/CcxtBroker.spec.ts b/src/domain/trading/brokers/ccxt/CcxtBroker.spec.ts index 878e5ad7..81e325ac 100644 --- a/src/domain/trading/brokers/ccxt/CcxtBroker.spec.ts +++ b/src/domain/trading/brokers/ccxt/CcxtBroker.spec.ts @@ -27,6 +27,8 @@ vi.mock('ccxt', () => { this.cancelOrder = vi.fn() this.editOrder = vi.fn() this.fetchOrder = vi.fn() + this.fetchOpenOrder = vi.fn() + this.fetchClosedOrder = vi.fn() this.fetchFundingRate = vi.fn() this.fetchOrderBook = vi.fn() }) @@ -72,9 +74,9 @@ function makeSwapMarket(base: string, quote: string, symbol?: string): any { } } -function makeAccount(overrides?: Partial<{ apiKey: string; apiSecret: string }>) { +function makeAccount(overrides?: Partial<{ exchange: string; apiKey: string; apiSecret: string }>) { return new CcxtBroker({ - exchange: 'bybit', + exchange: overrides?.exchange ?? 'bybit', apiKey: overrides?.apiKey ?? 'k', apiSecret: overrides?.apiSecret ?? 's', sandbox: false, @@ -270,15 +272,34 @@ describe('CcxtBroker — placeOrder async', () => { }) }) -// ==================== getOrder ==================== +// ==================== getOrder — Bybit (tested exchange) ==================== -describe('CcxtBroker — getOrder', () => { - it('fetches a specific order by ID using cached symbol', async () => { +describe('CcxtBroker — getOrder (bybit)', () => { + it('uses fetchOpenOrder for open orders', async () => { + const acc = makeAccount() + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-100', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + id: 'ord-100', symbol: 'ETH/USDT:USDT', side: 'buy', amount: 0.1, + type: 'limit', price: 1900, status: 'open', + }) + + const result = await acc.getOrder('ord-100') + expect(result).not.toBeNull() + expect(result!.order.action).toBe('BUY') + expect(result!.orderState.status).toBe('Submitted') + expect((acc as any).exchange.fetchOpenOrder).toHaveBeenCalledWith('ord-100', 'ETH/USDT:USDT') + // Should NOT use fetchOrder (bybit override avoids it) + expect((acc as any).exchange.fetchOrder).not.toHaveBeenCalled() + }) + + it('falls back to fetchClosedOrder for filled orders', async () => { const acc = makeAccount() const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') setInitialized(acc, { 'ETH/USDT:USDT': market }) - // Seed the orderSymbolCache ;(acc as any).orderSymbolCache.set('ord-100', 'ETH/USDT:USDT') ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockRejectedValue(new Error('not open')) ;(acc as any).exchange.fetchClosedOrder = vi.fn().mockResolvedValue({ @@ -292,6 +313,27 @@ describe('CcxtBroker — getOrder', () => { expect(result!.orderState.status).toBe('Filled') }) + it('finds conditional orders via { stop: true } fallback', async () => { + const acc = makeAccount() + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-sl', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn() + .mockRejectedValueOnce(new Error('not found')) // regular open + .mockResolvedValueOnce({ // conditional open (stop: true) + id: 'ord-sl', symbol: 'ETH/USDT:USDT', side: 'sell', amount: 0.5, + type: 'limit', price: 1800, status: 'open', triggerPrice: 1850, + }) + ;(acc as any).exchange.fetchClosedOrder = vi.fn().mockRejectedValue(new Error('not found')) + + const result = await acc.getOrder('ord-sl') + expect(result).not.toBeNull() + expect(result!.orderState.status).toBe('Submitted') + // Second fetchOpenOrder call should have { stop: true } + expect((acc as any).exchange.fetchOpenOrder).toHaveBeenCalledWith('ord-sl', 'ETH/USDT:USDT', { stop: true }) + }) + it('returns null when orderId not in symbol cache', async () => { const acc = makeAccount() setInitialized(acc, {}) @@ -300,7 +342,7 @@ describe('CcxtBroker — getOrder', () => { expect(result).toBeNull() }) - it('returns null when order not found', async () => { + it('returns null when order not found on any endpoint', async () => { const acc = makeAccount() setInitialized(acc, { 'ETH/USDT:USDT': makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') }) ;(acc as any).orderSymbolCache.set('ord-404', 'ETH/USDT:USDT') @@ -310,6 +352,110 @@ describe('CcxtBroker — getOrder', () => { const result = await acc.getOrder('ord-404') expect(result).toBeNull() }) + + it('extracts tpsl from CCXT order with takeProfitPrice/stopLossPrice', async () => { + const acc = makeAccount() + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-tp', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + id: 'ord-tp', symbol: 'ETH/USDT:USDT', side: 'buy', amount: 0.1, + type: 'limit', price: 1900, status: 'open', + takeProfitPrice: 2200, + stopLossPrice: 1800, + }) + + const result = await acc.getOrder('ord-tp') + expect(result!.tpsl).toEqual({ + takeProfit: { price: '2200' }, + stopLoss: { price: '1800' }, + }) + }) + + it('returns no tpsl when CCXT order has no TP/SL prices', async () => { + const acc = makeAccount() + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-plain', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + id: 'ord-plain', symbol: 'ETH/USDT:USDT', side: 'buy', amount: 0.1, + type: 'limit', price: 1900, status: 'open', + }) + + const result = await acc.getOrder('ord-plain') + expect(result!.tpsl).toBeUndefined() + }) + + it('extracts only takeProfit when stopLossPrice is absent', async () => { + const acc = makeAccount() + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-tp-only', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + id: 'ord-tp-only', symbol: 'ETH/USDT:USDT', side: 'buy', amount: 0.1, + type: 'limit', price: 1900, status: 'open', + takeProfitPrice: 2200, + }) + + const result = await acc.getOrder('ord-tp-only') + expect(result!.tpsl).toEqual({ takeProfit: { price: '2200' } }) + }) +}) + +// ==================== getOrder — default path (binance etc) ==================== + +describe('CcxtBroker — getOrder (default/binance)', () => { + it('uses fetchOrder for regular orders', async () => { + const acc = makeAccount({ exchange: 'binance' }) + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-100', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOrder = vi.fn().mockResolvedValue({ + id: 'ord-100', symbol: 'ETH/USDT:USDT', side: 'sell', amount: 0.5, + type: 'market', price: null, status: 'closed', + }) + + const result = await acc.getOrder('ord-100') + expect(result).not.toBeNull() + expect(result!.order.action).toBe('SELL') + expect(result!.orderState.status).toBe('Filled') + expect((acc as any).exchange.fetchOrder).toHaveBeenCalledWith('ord-100', 'ETH/USDT:USDT') + }) + + it('falls back to { stop: true } for conditional orders', async () => { + const acc = makeAccount({ exchange: 'binance' }) + const market = makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') + setInitialized(acc, { 'ETH/USDT:USDT': market }) + + ;(acc as any).orderSymbolCache.set('ord-sl', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOrder = vi.fn() + .mockRejectedValueOnce(new Error('order not found')) + .mockResolvedValueOnce({ + id: 'ord-sl', symbol: 'ETH/USDT:USDT', side: 'sell', amount: 0.5, + type: 'limit', price: 1800, status: 'open', triggerPrice: 1850, + }) + + const result = await acc.getOrder('ord-sl') + expect(result).not.toBeNull() + expect(result!.orderState.status).toBe('Submitted') + expect((acc as any).exchange.fetchOrder).toHaveBeenCalledTimes(2) + expect((acc as any).exchange.fetchOrder).toHaveBeenLastCalledWith('ord-sl', 'ETH/USDT:USDT', { stop: true }) + }) + + it('returns null when order not found on either endpoint', async () => { + const acc = makeAccount({ exchange: 'binance' }) + setInitialized(acc, { 'ETH/USDT:USDT': makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') }) + ;(acc as any).orderSymbolCache.set('ord-404', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOrder = vi.fn().mockRejectedValue(new Error('not found')) + + const result = await acc.getOrder('ord-404') + expect(result).toBeNull() + expect((acc as any).exchange.fetchOrder).toHaveBeenCalledTimes(2) + }) }) // ==================== getContractDetails ==================== @@ -432,7 +578,8 @@ describe('CcxtBroker — modifyOrder', () => { const acc = makeAccount() setInitialized(acc, { 'BTC/USDT:USDT': makeSwapMarket('BTC', 'USDT', 'BTC/USDT:USDT') }) ;(acc as any).orderSymbolCache.set('ord-100', 'BTC/USDT:USDT') - ;(acc as any).exchange.fetchOrder = vi.fn().mockResolvedValue({ + // Bybit override uses fetchOpenOrder to fetch the original order + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ type: 'limit', side: 'buy', amount: 0.5, price: 60000, }) ;(acc as any).exchange.editOrder = vi.fn().mockResolvedValue({ @@ -470,6 +617,86 @@ describe('CcxtBroker — modifyOrder', () => { }) }) +// ==================== modifyOrder — field forwarding ==================== + +describe('CcxtBroker — modifyOrder field forwarding', () => { + it('uses original price when lmtPrice not in changes (Partial)', async () => { + const acc = makeAccount() + setInitialized(acc, { 'ETH/USDT:USDT': makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') }) + ;(acc as any).orderSymbolCache.set('ord-200', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + type: 'limit', side: 'buy', amount: 0.1, price: 1900, + }) + ;(acc as any).exchange.editOrder = vi.fn().mockResolvedValue({ id: 'ord-200-edited', status: 'open' }) + + // Partial — only totalQuantity, no lmtPrice + const changes: Partial = { totalQuantity: new Decimal(0.2) } + + await acc.modifyOrder('ord-200', changes) + const call = (acc as any).exchange.editOrder.mock.calls[0] + + // Should use original price (1900), not undefined + expect(call[4]).toBe(0.2) // amount + expect(call[5]).toBe(1900) // price from original + }) + + it('forwards auxPrice as stopPrice in params', async () => { + const acc = makeAccount() + setInitialized(acc, { 'ETH/USDT:USDT': makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') }) + ;(acc as any).orderSymbolCache.set('ord-300', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + type: 'limit', side: 'sell', amount: 0.1, price: 2100, + }) + ;(acc as any).exchange.editOrder = vi.fn().mockResolvedValue({ id: 'ord-300-edited', status: 'open' }) + + const changes: Partial = { auxPrice: 1850 } + + await acc.modifyOrder('ord-300', changes) + const call = (acc as any).exchange.editOrder.mock.calls[0] + + // 7th argument is the params object with extra fields + const params = call[6] ?? {} + expect(params.stopPrice).toBe(1850) + }) + + it('forwards tif in params', async () => { + const acc = makeAccount() + setInitialized(acc, { 'ETH/USDT:USDT': makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') }) + ;(acc as any).orderSymbolCache.set('ord-400', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + type: 'limit', side: 'buy', amount: 0.1, price: 1900, + }) + ;(acc as any).exchange.editOrder = vi.fn().mockResolvedValue({ id: 'ord-400-edited', status: 'open' }) + + const changes: Partial = { tif: 'GTC' } + + await acc.modifyOrder('ord-400', changes) + const call = (acc as any).exchange.editOrder.mock.calls[0] + + const params = call[6] ?? {} + expect(params.timeInForce).toBe('gtc') + }) + + it('does not include undefined fields in params', async () => { + const acc = makeAccount() + setInitialized(acc, { 'ETH/USDT:USDT': makeSwapMarket('ETH', 'USDT', 'ETH/USDT:USDT') }) + ;(acc as any).orderSymbolCache.set('ord-500', 'ETH/USDT:USDT') + ;(acc as any).exchange.fetchOpenOrder = vi.fn().mockResolvedValue({ + type: 'limit', side: 'buy', amount: 0.1, price: 1900, + }) + ;(acc as any).exchange.editOrder = vi.fn().mockResolvedValue({ id: 'ord-500-edited', status: 'open' }) + + // Only change qty — nothing else should appear in params + const changes: Partial = { totalQuantity: new Decimal(0.5) } + + await acc.modifyOrder('ord-500', changes) + const call = (acc as any).exchange.editOrder.mock.calls[0] + + const params = call[6] ?? {} + expect(params).toEqual({}) + }) +}) + // ==================== closePosition ==================== describe('CcxtBroker — closePosition', () => { @@ -715,7 +942,7 @@ describe('CcxtBroker — getPositions', () => { // ==================== getOrders ==================== describe('CcxtBroker — getOrders', () => { - it('queries each orderId via getOrder and returns results', async () => { + it('queries each orderId via getOrder and returns results (bybit)', async () => { const acc = makeAccount() const market = makeSwapMarket('BTC', 'USDT', 'BTC/USDT:USDT') setInitialized(acc, { 'BTC/USDT:USDT': market }) @@ -723,10 +950,11 @@ describe('CcxtBroker — getOrders', () => { ;(acc as any).orderSymbolCache.set('ord-1', 'BTC/USDT:USDT') ;(acc as any).orderSymbolCache.set('ord-2', 'BTC/USDT:USDT') + // Bybit path: ord-1 not open, found via fetchClosedOrder; ord-2 found via fetchOpenOrder ;(acc as any).exchange.fetchOpenOrder = vi.fn() - .mockRejectedValueOnce(new Error('not open')) // ord-1 not open + .mockRejectedValueOnce(new Error('not open')) // ord-1 regular + .mockRejectedValueOnce(new Error('not open')) // ord-1 conditional .mockResolvedValueOnce({ id: 'ord-2', symbol: 'BTC/USDT:USDT', side: 'buy', type: 'limit', amount: 0.1, price: 55000, status: 'open' }) - ;(acc as any).exchange.fetchClosedOrder = vi.fn() .mockResolvedValueOnce({ id: 'ord-1', symbol: 'BTC/USDT:USDT', side: 'sell', type: 'market', amount: 0.2, status: 'closed' }) diff --git a/src/domain/trading/brokers/ccxt/CcxtBroker.ts b/src/domain/trading/brokers/ccxt/CcxtBroker.ts index d35e5a1a..cc735dcc 100644 --- a/src/domain/trading/brokers/ccxt/CcxtBroker.ts +++ b/src/domain/trading/brokers/ccxt/CcxtBroker.ts @@ -22,6 +22,7 @@ import { type Quote, type MarketClock, type BrokerConfigField, + type TpSlParams, } from '../types.js' import { QuoteCache } from '../../quote-cache.js' import '../../contract-ext.js' @@ -34,6 +35,12 @@ import { marketToContract, contractToCcxt, } from './ccxt-contracts.js' +import { + type CcxtExchangeOverrides, + exchangeOverrides, + defaultFetchOrderById, + defaultCancelOrderById, +} from './overrides.js' /** Map IBKR orderType codes to CCXT order type strings. */ function ibkrOrderTypeToCcxt(orderType: string): string { @@ -100,12 +107,14 @@ export class CcxtBroker implements IBroker { private supportsStreaming = false private readonly quoteCache = new QuoteCache() private readonly watchAborts = new Map() + private overrides: CcxtExchangeOverrides // orderId → ccxtSymbol cache (CCXT needs symbol to cancel) private orderSymbolCache = new Map() constructor(config: CcxtBrokerConfig) { this.exchangeName = config.exchange this.meta = { exchange: config.exchange } + this.overrides = exchangeOverrides[config.exchange] ?? {} this.id = config.id ?? `${config.exchange}-main` this.label = config.label ?? `${config.exchange.charAt(0).toUpperCase() + config.exchange.slice(1)} ${config.sandbox ? 'Testnet' : 'Live'}` @@ -329,7 +338,7 @@ export class CcxtBroker implements IBroker { // ---- Trading operations ---- - async placeOrder(contract: Contract, order: Order, extraParams?: Record): Promise { + async placeOrder(contract: Contract, order: Order, tpsl?: TpSlParams, extraParams?: Record): Promise { this.ensureInit() @@ -360,6 +369,16 @@ export class CcxtBroker implements IBroker { try { const params: Record = { ...extraParams } + if (tpsl?.takeProfit) { + params.takeProfit = { triggerPrice: parseFloat(tpsl.takeProfit.price) } + } + if (tpsl?.stopLoss) { + params.stopLoss = { + triggerPrice: parseFloat(tpsl.stopLoss.price), + ...(tpsl.stopLoss.limitPrice && { price: parseFloat(tpsl.stopLoss.limitPrice) }), + } + } + const ccxtOrderType = ibkrOrderTypeToCcxt(order.orderType) const side = order.action.toLowerCase() as 'buy' | 'sell' @@ -392,7 +411,8 @@ export class CcxtBroker implements IBroker { try { const ccxtSymbol = this.orderSymbolCache.get(orderId) - await this.exchange.cancelOrder(orderId, ccxtSymbol) + const cancel = this.overrides.cancelOrderById ?? defaultCancelOrderById + await cancel(this.exchange, orderId, ccxtSymbol) const orderState = new OrderState() orderState.status = 'Cancelled' return { success: true, orderId, orderState } @@ -410,10 +430,18 @@ export class CcxtBroker implements IBroker { return { success: false, error: `Unknown order ${orderId} — cannot resolve symbol for edit` } } - // editOrder requires type and side — fetch the original order to fill in defaults - const original = await this.exchange.fetchOrder(orderId, ccxtSymbol) + // editOrder requires type and side — fetch the original order to fill in defaults. + const fetch = this.overrides.fetchOrderById ?? defaultFetchOrderById + const original = await fetch(this.exchange, orderId, ccxtSymbol) const qty = changes.totalQuantity != null && !changes.totalQuantity.equals(UNSET_DECIMAL) ? parseFloat(changes.totalQuantity.toString()) : original.amount - const price = changes.lmtPrice !== UNSET_DOUBLE ? changes.lmtPrice : original.price + const price = changes.lmtPrice != null && changes.lmtPrice !== UNSET_DOUBLE ? changes.lmtPrice : original.price + + // Extra params for fields that don't fit editOrder's positional arguments + const params: Record = {} + if (changes.auxPrice != null && changes.auxPrice !== UNSET_DOUBLE) params.stopPrice = changes.auxPrice + if (changes.trailStopPrice != null && changes.trailStopPrice !== UNSET_DOUBLE) params.trailStopPrice = changes.trailStopPrice + if (changes.trailingPercent != null && changes.trailingPercent !== UNSET_DOUBLE) params.trailingPercent = changes.trailingPercent + if (changes.tif) params.timeInForce = changes.tif.toLowerCase() const result = await this.exchange.editOrder( orderId, @@ -422,6 +450,7 @@ export class CcxtBroker implements IBroker { original.side, qty, price, + params, ) return { @@ -456,7 +485,7 @@ export class CcxtBroker implements IBroker { order.orderType = 'MKT' order.totalQuantity = quantity ?? pos.quantity - return this.placeOrder(pos.contract, order, { reduceOnly: true }) + return this.placeOrder(pos.contract, order, undefined, { reduceOnly: true }) } // ---- Queries ---- @@ -566,22 +595,13 @@ export class CcxtBroker implements IBroker { async getOrder(orderId: string): Promise { this.ensureInit() - const ccxtSymbol = this.orderSymbolCache.get(orderId) if (!ccxtSymbol) return null + const fetch = this.overrides.fetchOrderById ?? defaultFetchOrderById try { - // Use singular fetchOpenOrder / fetchClosedOrder — they query by orderId directly, - // instead of fetching a list and searching. Much more reliable on Bybit. - try { - const open = await (this.exchange as any).fetchOpenOrder(orderId, ccxtSymbol) - return this.convertCcxtOrder(open) - } catch { /* not an open order */ } - try { - const closed = await (this.exchange as any).fetchClosedOrder(orderId, ccxtSymbol) - return this.convertCcxtOrder(closed) - } catch { /* not found */ } - return null + const order = await fetch(this.exchange, orderId, ccxtSymbol) + return this.convertCcxtOrder(order) } catch { return null } @@ -604,11 +624,21 @@ export class CcxtBroker implements IBroker { if (o.price != null) order.lmtPrice = o.price order.orderId = parseInt(o.id, 10) || 0 + const tp = o.takeProfitPrice + const sl = o.stopLossPrice + const tpsl: TpSlParams | undefined = (tp != null || sl != null) + ? { + ...(tp != null && { takeProfit: { price: String(tp) } }), + ...(sl != null && { stopLoss: { price: String(sl) } }), + } + : undefined + return { contract, order, orderState: makeOrderState(o.status), nativeOrderId: o.id, + ...(tpsl && { tpsl }), } } diff --git a/src/domain/trading/brokers/ccxt/exchanges/bybit.ts b/src/domain/trading/brokers/ccxt/exchanges/bybit.ts new file mode 100644 index 00000000..4dc79351 --- /dev/null +++ b/src/domain/trading/brokers/ccxt/exchanges/bybit.ts @@ -0,0 +1,32 @@ +/** + * Bybit-specific overrides for CcxtBroker. + * + * Bybit quirks: + * - fetchOrder() requires { acknowledged: true } and only searches last 500 orders + * - fetchOpenOrder / fetchClosedOrder are reliable, query by ID directly with no limit + * - Both support { stop: true } for conditional/trigger orders + */ + +import type { Exchange, Order as CcxtOrder } from 'ccxt' +import type { CcxtExchangeOverrides } from '../overrides.js' + +export const bybitOverrides: CcxtExchangeOverrides = { + async fetchOrderById(exchange: Exchange, orderId: string, symbol: string): Promise { + // Try open regular → open conditional → closed regular → closed conditional + try { + return await (exchange as any).fetchOpenOrder(orderId, symbol) + } catch { /* not an open regular order */ } + try { + return await (exchange as any).fetchOpenOrder(orderId, symbol, { stop: true }) + } catch { /* not an open conditional order */ } + try { + return await (exchange as any).fetchClosedOrder(orderId, symbol) + } catch { /* not a closed regular order */ } + try { + return await (exchange as any).fetchClosedOrder(orderId, symbol, { stop: true }) + } catch { /* not found anywhere */ } + throw new Error(`Order ${orderId} not found`) + }, + + // cancelOrderById: not overridden — default { stop: true } fallback works for Bybit +} diff --git a/src/domain/trading/brokers/ccxt/overrides.ts b/src/domain/trading/brokers/ccxt/overrides.ts new file mode 100644 index 00000000..33ac0aad --- /dev/null +++ b/src/domain/trading/brokers/ccxt/overrides.ts @@ -0,0 +1,64 @@ +/** + * Exchange-specific overrides for CcxtBroker. + * + * CCXT's "unified API" behaves differently across exchanges: + * - Bybit: fetchOrder requires { acknowledged: true }, limited to last 500 orders + * - Binance: fetchOrder works fine, but conditional orders need { stop: true } + * - OKX/Bitget: no fetchOpenOrder/fetchClosedOrder singular methods + * + * Rather than patching one code path with exchange-specific if/else, + * each tested exchange gets its own override file in exchanges/. + * Only override what's different — unset methods fall through to the default. + * + * To add a new exchange: + * 1. Create exchanges/.ts exporting a CcxtExchangeOverrides object + * 2. Only implement the methods that differ from defaults + * 3. Register it in exchangeOverrides below + */ + +import type { Exchange, Order as CcxtOrder } from 'ccxt' +import { bybitOverrides } from './exchanges/bybit.js' + +// ==================== Override interface ==================== + +export interface CcxtExchangeOverrides { + /** Fetch a single order by ID (regular + conditional). */ + fetchOrderById?(exchange: Exchange, orderId: string, symbol: string): Promise + /** Cancel an order by ID (regular + conditional). */ + cancelOrderById?(exchange: Exchange, orderId: string, symbol?: string): Promise +} + +// ==================== Default implementations ==================== + +/** Default: fetchOrder + { stop: true } fallback. Works for binance, okx, bitget, etc. */ +export async function defaultFetchOrderById(exchange: Exchange, orderId: string, symbol: string): Promise { + try { + return await exchange.fetchOrder(orderId, symbol) + } catch { /* not a regular order */ } + try { + return await exchange.fetchOrder(orderId, symbol, { stop: true }) + } catch { /* not found */ } + throw new Error(`Order ${orderId} not found`) +} + +/** Default: cancelOrder + { stop: true } fallback. */ +export async function defaultCancelOrderById(exchange: Exchange, orderId: string, symbol?: string): Promise { + try { + await exchange.cancelOrder(orderId, symbol) + return + } catch (err) { + if (symbol) { + try { + await exchange.cancelOrder(orderId, symbol, { stop: true }) + return + } catch { /* fall through to original error */ } + } + throw err + } +} + +// ==================== Registry ==================== + +export const exchangeOverrides: Record = { + bybit: bybitOverrides, +} diff --git a/src/domain/trading/brokers/ibkr/IbkrBroker.ts b/src/domain/trading/brokers/ibkr/IbkrBroker.ts index 79872840..a5d0e8bd 100644 --- a/src/domain/trading/brokers/ibkr/IbkrBroker.ts +++ b/src/domain/trading/brokers/ibkr/IbkrBroker.ts @@ -33,6 +33,7 @@ import { type Quote, type MarketClock, type BrokerConfigField, + type TpSlParams, } from '../types.js' import '../../contract-ext.js' import { RequestBridge } from './request-bridge.js' @@ -148,7 +149,7 @@ export class IbkrBroker implements IBroker { // ==================== Trading operations ==================== - async placeOrder(contract: Contract, order: Order): Promise { + async placeOrder(contract: Contract, order: Order, _tpsl?: TpSlParams): Promise { // TWS requires exchange and currency on the contract. Upstream layers // (staging, AI tools) typically only populate symbol + secType. // Default to SMART routing. Currency defaults to USD — non-USD markets @@ -188,6 +189,7 @@ export class IbkrBroker implements IBroker { if (changes.tif) mergedOrder.tif = changes.tif if (changes.orderType) mergedOrder.orderType = changes.orderType if (changes.trailingPercent != null) mergedOrder.trailingPercent = changes.trailingPercent + if (changes.trailStopPrice != null) mergedOrder.trailStopPrice = changes.trailStopPrice const numericId = parseInt(orderId, 10) const promise = this.bridge.requestOrder(numericId) diff --git a/src/domain/trading/brokers/index.ts b/src/domain/trading/brokers/index.ts index 870e0978..dfb210d2 100644 --- a/src/domain/trading/brokers/index.ts +++ b/src/domain/trading/brokers/index.ts @@ -9,6 +9,7 @@ export type { MarketClock, AccountCapabilities, BrokerConfigField, + TpSlParams, } from './types.js' // Factory + Registry diff --git a/src/domain/trading/brokers/mock/MockBroker.ts b/src/domain/trading/brokers/mock/MockBroker.ts index 9fe87da9..e100f741 100644 --- a/src/domain/trading/brokers/mock/MockBroker.ts +++ b/src/domain/trading/brokers/mock/MockBroker.ts @@ -20,6 +20,7 @@ import type { OpenOrder, Quote, MarketClock, + TpSlParams, } from '../types.js' import '../../contract-ext.js' @@ -217,8 +218,8 @@ export class MockBroker implements IBroker { // ---- Trading operations ---- - async placeOrder(contract: Contract, order: Order, _extraParams?: Record): Promise { - this._record('placeOrder', [contract, order, _extraParams]) + async placeOrder(contract: Contract, order: Order, tpsl?: TpSlParams): Promise { + this._record('placeOrder', [contract, order, tpsl]) const orderId = `mock-ord-${this._nextOrderId++}` const isMarket = order.orderType === 'MKT' const side = order.action.toUpperCase() @@ -278,6 +279,14 @@ export class MockBroker implements IBroker { if (changes.auxPrice != null && changes.auxPrice !== UNSET_DOUBLE) { internal.order.auxPrice = changes.auxPrice } + if (changes.trailStopPrice != null && changes.trailStopPrice !== UNSET_DOUBLE) { + internal.order.trailStopPrice = changes.trailStopPrice + } + if (changes.trailingPercent != null && changes.trailingPercent !== UNSET_DOUBLE) { + internal.order.trailingPercent = changes.trailingPercent + } + if (changes.orderType) internal.order.orderType = changes.orderType + if (changes.tif) internal.order.tif = changes.tif const orderState = new OrderState() orderState.status = 'Submitted' diff --git a/src/domain/trading/brokers/types.ts b/src/domain/trading/brokers/types.ts index 62b48625..c7591c4f 100644 --- a/src/domain/trading/brokers/types.ts +++ b/src/domain/trading/brokers/types.ts @@ -97,6 +97,8 @@ export interface OpenOrder { nativeOrderId?: string /** Average fill price — from orderStatus callback or broker-specific source. */ avgFillPrice?: number + /** Attached take-profit / stop-loss (CCXT: from order fields; Alpaca: from bracket legs). */ + tpsl?: TpSlParams } // ==================== Account info ==================== @@ -170,6 +172,13 @@ export interface BrokerConfigField { sensitive?: boolean } +// ==================== Take Profit / Stop Loss ==================== + +export interface TpSlParams { + takeProfit?: { price: string } + stopLoss?: { price: string; limitPrice?: string } +} + // ==================== IBroker ==================== export interface IBroker { @@ -194,7 +203,7 @@ export interface IBroker { // ---- Trading operations (IBKR Order as source of truth) ---- - placeOrder(contract: Contract, order: Order): Promise + placeOrder(contract: Contract, order: Order, tpsl?: TpSlParams): Promise modifyOrder(orderId: string, changes: Partial): Promise cancelOrder(orderId: string, orderCancel?: OrderCancel): Promise closePosition(contract: Contract, quantity?: Decimal): Promise diff --git a/src/domain/trading/git/types.ts b/src/domain/trading/git/types.ts index 0cf34ab0..f9f187f0 100644 --- a/src/domain/trading/git/types.ts +++ b/src/domain/trading/git/types.ts @@ -7,7 +7,7 @@ import type { Contract, Order, OrderCancel, Execution, OrderState } from '@traderalice/ibkr' import type Decimal from 'decimal.js' -import type { Position, OpenOrder } from '../brokers/types.js' +import type { Position, OpenOrder, TpSlParams } from '../brokers/types.js' import '../contract-ext.js' // ==================== Commit Hash ==================== @@ -20,7 +20,7 @@ export type CommitHash = string export type OperationAction = Operation['action'] export type Operation = - | { action: 'placeOrder'; contract: Contract; order: Order } + | { action: 'placeOrder'; contract: Contract; order: Order; tpsl?: TpSlParams } | { action: 'modifyOrder'; orderId: string; changes: Partial } | { action: 'closePosition'; contract: Contract; quantity?: Decimal } | { action: 'cancelOrder'; orderId: string; orderCancel?: OrderCancel } diff --git a/src/domain/trading/index.ts b/src/domain/trading/index.ts index 30996722..bf88abaa 100644 --- a/src/domain/trading/index.ts +++ b/src/domain/trading/index.ts @@ -24,6 +24,7 @@ export type { Quote, MarketClock, AccountCapabilities, + TpSlParams, } from './brokers/index.js' export { createBroker, diff --git a/src/main.ts b/src/main.ts index d129cff0..08352722 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,13 +16,14 @@ import type { BrainExportState } from './domain/brain/index.js' import { createBrowserTools } from './tool/browser.js' import { SymbolIndex } from './domain/market-data/equity/index.js' import { createEquityTools } from './tool/equity.js' -import { getSDKExecutor, buildRouteMap, SDKEquityClient, SDKCryptoClient, SDKCurrencyClient, SDKEconomyClient } from './domain/market-data/client/typebb/index.js' -import type { EquityClientLike, CryptoClientLike, CurrencyClientLike, EconomyClientLike } from './domain/market-data/client/types.js' +import { getSDKExecutor, buildRouteMap, SDKEquityClient, SDKCryptoClient, SDKCurrencyClient, SDKEconomyClient, SDKEtfClient, SDKIndexClient, SDKDerivativesClient, SDKCommodityClient } from './domain/market-data/client/typebb/index.js' +import type { EquityClientLike, CryptoClientLike, CurrencyClientLike, EconomyClientLike, EtfClientLike, IndexClientLike, DerivativesClientLike, CommodityClientLike } from './domain/market-data/client/types.js' import { buildSDKCredentials } from './domain/market-data/credential-map.js' import { OpenBBEquityClient } from './domain/market-data/client/openbb-api/equity-client.js' import { OpenBBCryptoClient } from './domain/market-data/client/openbb-api/crypto-client.js' import { OpenBBCurrencyClient } from './domain/market-data/client/openbb-api/currency-client.js' import { OpenBBEconomyClient } from './domain/market-data/client/openbb-api/economy-client.js' +import { OpenBBCommodityClient } from './domain/market-data/client/openbb-api/commodity-client.js' import { OpenBBServerPlugin } from './server/opentypebb.js' import { createMarketSearchTools } from './tool/market.js' import { createAnalysisTools } from './tool/analysis.js' @@ -165,6 +166,10 @@ async function main() { let cryptoClient: CryptoClientLike let currencyClient: CurrencyClientLike let economyClient: EconomyClientLike + let commodityClient: CommodityClientLike + let etfClient: EtfClientLike | undefined + let indexClient: IndexClientLike | undefined + let derivativesClient: DerivativesClientLike | undefined if (config.marketData.backend === 'openbb-api') { const url = config.marketData.apiUrl @@ -173,6 +178,7 @@ async function main() { cryptoClient = new OpenBBCryptoClient(url, providers.crypto, keys) currencyClient = new OpenBBCurrencyClient(url, providers.currency, keys) economyClient = new OpenBBEconomyClient(url, undefined, keys) + commodityClient = new OpenBBCommodityClient(url, providers.equity, keys) } else { const executor = getSDKExecutor() const routeMap = buildRouteMap() @@ -181,6 +187,10 @@ async function main() { cryptoClient = new SDKCryptoClient(executor, 'crypto', providers.crypto, credentials, routeMap) currencyClient = new SDKCurrencyClient(executor, 'currency', providers.currency, credentials, routeMap) economyClient = new SDKEconomyClient(executor, 'economy', undefined, credentials, routeMap) + commodityClient = new SDKCommodityClient(executor, 'commodity', providers.equity, credentials, routeMap) + etfClient = new SDKEtfClient(executor, 'etf', providers.equity, credentials, routeMap) + indexClient = new SDKIndexClient(executor, 'index', providers.equity, credentials, routeMap) + derivativesClient = new SDKDerivativesClient(executor, 'derivatives', providers.equity, credentials, routeMap) } // OpenBB API server is started later via optionalPlugins @@ -209,7 +219,7 @@ async function main() { toolCenter.register(createNewsArchiveTools(newsStore), 'news') toolCenter.register(createNewsSentimentTools(newsStore), 'news-sentiment') } - toolCenter.register(createAnalysisTools(equityClient, cryptoClient, currencyClient), 'analysis') + toolCenter.register(createAnalysisTools(equityClient, cryptoClient, currencyClient, commodityClient), 'analysis') toolCenter.register(createPortfolioAnalyticsTools(accountManager, equityClient), 'portfolio-analytics') toolCenter.register(createScreenerTools(equityClient, symbolIndex), 'screener') toolCenter.register(createVolatilityTools(equityClient), 'volatility') @@ -427,6 +437,7 @@ async function main() { const ctx: EngineContext = { config, connectorCenter, agentCenter, eventLog, toolCallLog, heartbeat, cronEngine, toolCenter, + bbEngine: getSDKExecutor(), accountManager, snapshotService, reconnectConnectors, } diff --git a/src/server/mcp.ts b/src/server/mcp.ts index c87551b6..e6c0c462 100644 --- a/src/server/mcp.ts +++ b/src/server/mcp.ts @@ -3,49 +3,9 @@ import { cors } from 'hono/cors' import { serve } from '@hono/node-server' import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js' -import type { Tool } from 'ai' import type { Plugin, EngineContext } from '../core/types.js' import type { ToolCenter } from '../core/tool-center.js' - -type McpContent = - | { type: 'text'; text: string } - | { type: 'image'; data: string; mimeType: string } - -/** - * Convert a tool result to MCP content blocks. - * - * If the result has a `.content` array (OpenClaw AgentToolResult format), - * map each item to native MCP text/image blocks. This avoids stringify-ing - * base64 image data into a giant JSON text blob. - * - * Otherwise, fall back to JSON.stringify as before. - */ -function toMcpContent(result: unknown): McpContent[] { - if ( - result != null && - typeof result === 'object' && - 'content' in result && - Array.isArray((result as { content: unknown }).content) - ) { - const items = (result as { content: Array> }).content - const blocks: McpContent[] = [] - for (const item of items) { - if (item.type === 'image' && typeof item.data === 'string' && typeof item.mimeType === 'string') { - blocks.push({ type: 'image', data: item.data, mimeType: item.mimeType }) - } else if (item.type === 'text' && typeof item.text === 'string') { - blocks.push({ type: 'text', text: item.text }) - } else { - blocks.push({ type: 'text', text: JSON.stringify(item) }) - } - } - // Also include details as text if present - if ('details' in result && (result as { details: unknown }).details != null) { - blocks.push({ type: 'text', text: JSON.stringify((result as { details: unknown }).details) }) - } - return blocks.length > 0 ? blocks : [{ type: 'text', text: JSON.stringify(result) }] - } - return [{ type: 'text', text: JSON.stringify(result) }] -} +import { extractMcpShape, wrapToolExecute } from '../core/mcp-export.js' /** * MCP Plugin — exposes tools via Streamable HTTP. @@ -72,26 +32,10 @@ export class McpPlugin implements Plugin { for (const [name, t] of Object.entries(tools)) { if (!t.execute) continue - // Extract raw shape from z.object() for MCP's inputSchema - const shape = (t.inputSchema as any)?.shape ?? {} - mcp.registerTool(name, { description: t.description, - inputSchema: shape, - }, async (args: any) => { - try { - const result = await t.execute!(args, { - toolCallId: crypto.randomUUID(), - messages: [], - }) - return { content: toMcpContent(result) } - } catch (err) { - return { - content: [{ type: 'text' as const, text: `Error: ${err}` }], - isError: true, - } - } - }) + inputSchema: extractMcpShape(t), + }, wrapToolExecute(t)) } return mcp diff --git a/src/task/heartbeat/heartbeat.spec.ts b/src/task/heartbeat/heartbeat.spec.ts index b2421e09..7b254ba5 100644 --- a/src/task/heartbeat/heartbeat.spec.ts +++ b/src/task/heartbeat/heartbeat.spec.ts @@ -306,10 +306,12 @@ describe('heartbeat', () => { const jobId = cronEngine.list()[0].id - // First fire — should deliver + // First fire — should deliver. Wait for heartbeat.done to ensure + // the full handleFire cycle (including dedup.record) has completed + // before triggering the second fire. await cronEngine.runNow(jobId) await vi.waitFor(() => { - expect(delivered).toHaveLength(1) + expect(eventLog.recent({ type: 'heartbeat.done' })).toHaveLength(1) }) // Second fire (same response) — should be suppressed diff --git a/src/tool/analysis.ts b/src/tool/analysis.ts index d8c864d8..a9095dd0 100644 --- a/src/tool/analysis.ts +++ b/src/tool/analysis.ts @@ -8,7 +8,7 @@ import { tool } from 'ai' import { z } from 'zod' -import type { EquityClientLike, CryptoClientLike, CurrencyClientLike } from '@/domain/market-data/client/types' +import type { EquityClientLike, CryptoClientLike, CurrencyClientLike, CommodityClientLike } from '@/domain/market-data/client/types' import { IndicatorCalculator } from '@/domain/analysis/indicator/calculator' import type { IndicatorContext, OhlcvData } from '@/domain/analysis/indicator/types' @@ -37,10 +37,11 @@ function buildStartDate(interval: string): string { } function buildContext( - asset: 'equity' | 'crypto' | 'currency', + asset: 'equity' | 'crypto' | 'currency' | 'commodity', equityClient: EquityClientLike, cryptoClient: CryptoClientLike, currencyClient: CurrencyClientLike, + commodityClient: CommodityClientLike, ): IndicatorContext { return { getHistoricalData: async (symbol, interval) => { @@ -57,6 +58,9 @@ function buildContext( case 'currency': raw = await currencyClient.getHistorical({ symbol, start_date, interval }) break + case 'commodity': + raw = await commodityClient.getSpotPrices({ symbol, start_date }) + break } // Filter out bars with null OHLC (yfinance returns null for incomplete/missing data) @@ -75,12 +79,13 @@ export function createAnalysisTools( equityClient: EquityClientLike, cryptoClient: CryptoClientLike, currencyClient: CurrencyClientLike, + commodityClient: CommodityClientLike, ) { return { calculateIndicator: tool({ description: `Calculate technical indicators for any asset (equity, crypto, currency) using formula expressions. -Asset classes: "equity" for stocks, "crypto" for cryptocurrencies, "currency" for forex pairs. +Asset classes: "equity" for stocks, "crypto" for cryptocurrencies, "currency" for forex pairs, "commodity" for commodities (gold, oil, etc.). Data access: CLOSE('AAPL', '1d'), HIGH, LOW, OPEN, VOLUME — args: symbol, interval (e.g. '1d', '1w', '1h'). Statistics: SMA(data, period), EMA, STDEV, MAX, MIN, SUM, AVERAGE. @@ -98,18 +103,22 @@ Technical indicators: Array access: CLOSE('AAPL', '1d')[-1] for latest price. Supports +, -, *, / operators. Examples: - SMA(CLOSE('AAPL', '1d'), 50) - RSI(CLOSE('AAPL', '1d'), 14) + asset="equity": SMA(CLOSE('AAPL', '1d'), 50) + asset="crypto": RSI(CLOSE('BTCUSD', '1d'), 14) + asset="currency": CLOSE('EURUSD', '1d')[-1] + asset="commodity": SMA(CLOSE('GC=F', '1d'), 20) (gold futures) ADX(HIGH('AAPL', '1d'), LOW('AAPL', '1d'), CLOSE('AAPL', '1d'), 14) VWAP(HIGH('AAPL', '1h'), LOW('AAPL', '1h'), CLOSE('AAPL', '1h'), VOLUME('AAPL', '1h')) - PIVOT(HIGH('SPY', '1d'), LOW('SPY', '1d'), CLOSE('SPY', '1d'))`, + PIVOT(HIGH('SPY', '1d'), LOW('SPY', '1d'), CLOSE('SPY', '1d')) + +Use the corresponding search tool first to resolve the correct symbol.`, inputSchema: z.object({ - asset: z.enum(['equity', 'crypto', 'currency']).describe('Asset class'), + asset: z.enum(['equity', 'crypto', 'currency', 'commodity']).describe('Asset class'), formula: z.string().describe("Formula expression, e.g. SMA(CLOSE('AAPL', '1d'), 50)"), precision: z.number().int().min(0).max(10).optional().describe('Decimal places (default: 4)'), }), execute: async ({ asset, formula, precision }) => { - const context = buildContext(asset, equityClient, cryptoClient, currencyClient) + const context = buildContext(asset, equityClient, cryptoClient, currencyClient, commodityClient) const calculator = new IndicatorCalculator(context) return await calculator.calculate(formula, precision) }, diff --git a/src/tool/equity.ts b/src/tool/equity.ts index fd1a249a..c1749629 100644 --- a/src/tool/equity.ts +++ b/src/tool/equity.ts @@ -81,21 +81,6 @@ If unsure about the symbol, use marketSearchForResearch to find it.`, }, }), - equityGetEstimates: tool({ - description: `Get analyst consensus estimates for a stock. - -Returns consensus rating (buy/hold/sell counts), average target price, and EPS estimates. -Useful for understanding how the market views a stock's prospects. - -If unsure about the symbol, use marketSearchForResearch to find it.`, - inputSchema: z.object({ - symbol: z.string().describe('Ticker symbol, e.g. "AAPL"'), - }), - execute: async ({ symbol }) => { - return await equityClient.getEstimateConsensus({ symbol, provider: 'yfinance' }) - }, - }), - equityGetEarningsCalendar: tool({ description: `Get upcoming and recent earnings release dates. diff --git a/src/tool/thinking.ts b/src/tool/thinking.ts index 90d9073d..9ffbc591 100644 --- a/src/tool/thinking.ts +++ b/src/tool/thinking.ts @@ -5,82 +5,14 @@ import { calculate } from '@/domain/thinking/tools/calculate.tool'; /** * Create thinking AI tools (cognition + utility, no data dependency) * - * Tools: - * - think: Record observations and analysis - * - plan: Record action plans + * Active tools: * - calculate: Safe mathematical expression evaluation - * - reportWarning: Report anomalies or unexpected situations - * - getConfirm: Request user confirmation before actions + * + * Disabled (low usage, overlaps with current architecture): + * - think, plan, reportWarning, getConfirm */ export function createThinkingTools() { return { - think: tool({ - description: ` -Use this to analyze current market situation and your observations. -Call this tool to: -- Summarize what you observe from market data, positions, and account -- Analyze what these observations mean -- Identify key factors influencing your decision - -This is for analysis only. Use 'plan' tool separately to decide your next actions. - `.trim(), - inputSchema: z.object({ - observations: z - .string() - .describe( - 'What you currently observe from market data, positions, and account status', - ), - analysis: z - .string() - .describe( - 'Your analysis of the situation - what do these observations mean? What are the key factors?', - ), - }), - execute: async () => { - return { - status: 'acknowledged', - message: - 'Your analysis has been recorded. Now use the plan tool to decide your next actions.', - }; - }, - }), - - plan: tool({ - description: ` -Use this to plan your next trading actions based on your analysis. -Call this tool after using 'think' to: -- List possible actions you could take -- Decide which action to take and explain why -- Outline the specific steps you will execute - -This commits you to a specific action plan before execution. - `.trim(), - inputSchema: z.object({ - options: z - .array(z.string()) - .describe( - 'List of possible actions you could take (e.g., "Buy BTC", "Close ETH position", "Hold and wait")', - ), - decision: z - .string() - .describe( - 'Which option you choose and WHY - explain your reasoning for this specific choice', - ), - steps: z - .array(z.string()) - .describe( - 'Specific steps you will execute (e.g., "1. placeOrder BTC buy $1000", "2. Set stop loss at $66000")', - ), - }), - execute: async () => { - return { - status: 'acknowledged', - message: - 'Your plan has been recorded. You may now execute the planned actions.', - }; - }, - }), - calculate: tool({ description: 'Perform mathematical calculations with precision. Use this for any arithmetic operations instead of calculating yourself. Supports basic operators: +, -, *, /, (), decimals.', @@ -95,59 +27,5 @@ This commits you to a specific action plan before execution. return calculate(expression); }, }), - - reportWarning: tool({ - description: - 'Report a warning when you detect anomalies or unexpected situations in the sandbox. Use this to alert about suspicious data, unexpected PnL, zero prices, or any other concerning conditions.', - inputSchema: z.object({ - message: z.string().describe('Clear description of the warning'), - details: z.string().describe('Additional details or context'), - }), - execute: async ({ message, details }) => { - console.warn('\n⚠️ AI REPORTED WARNING:'); - console.warn(` ${message}`); - if (details) { - console.warn(' Details:', details); - } - console.warn(''); - return { success: true, message: 'Warning logged' }; - }, - }), - - getConfirm: tool({ - description: ` -Request user confirmation before executing an action. - -Currently: Automatically approved. -In production environment: Will wait for user approval before proceeding. - -Use this when you want to: -- Get approval for risky operations -- Ask for permission before major position changes -- Confirm strategy adjustments with the user - -Example use cases: -- "I want to open a 10x leveraged position on BTC" -- "Should I close all positions due to negative market sentiment?" -- "Planning to switch from long to short strategy" - `.trim(), - inputSchema: z.object({ - action: z - .string() - .describe( - 'Clear description of the action you want to perform and why', - ), - }), - execute: async ({ action }) => { - console.log('\n🤖 AI requesting confirmation:'); - console.log(` Action: ${action}`); - console.log(' ✅ Auto-approved'); - console.log(''); - return { - approved: true, - message: 'Approved automatically', - }; - }, - }), }; } diff --git a/src/tool/trading.spec.ts b/src/tool/trading.spec.ts index 4ce66f19..4d95c0ad 100644 --- a/src/tool/trading.spec.ts +++ b/src/tool/trading.spec.ts @@ -1,5 +1,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest' -import { ContractDescription } from '@traderalice/ibkr' +import Decimal from 'decimal.js' +import { ContractDescription, Order, OrderState, UNSET_DOUBLE, UNSET_DECIMAL } from '@traderalice/ibkr' +import type { OpenOrder } from '../domain/trading/brokers/types.js' import { MockBroker, makeContract } from '../domain/trading/brokers/mock/index.js' import { AccountManager } from '../domain/trading/account-manager.js' import { UnifiedTradingAccount } from '../domain/trading/UnifiedTradingAccount.js' @@ -98,3 +100,137 @@ describe('createTradingTools — searchContracts', () => { expect(result).toHaveLength(2) }) }) + +// ==================== getOrders — summarization ==================== + +describe('createTradingTools — getOrders summarization', () => { + function makeOpenOrder(overrides?: Partial<{ action: string; orderType: string; qty: number; lmtPrice: number; status: string; symbol: string }>): OpenOrder { + const contract = makeContract({ symbol: overrides?.symbol ?? 'AAPL' }) + contract.aliceId = `mock-paper|${overrides?.symbol ?? 'AAPL'}` + const order = new Order() + order.action = overrides?.action ?? 'BUY' + order.orderType = overrides?.orderType ?? 'MKT' + order.totalQuantity = new Decimal(overrides?.qty ?? 10) + if (overrides?.lmtPrice != null) order.lmtPrice = overrides.lmtPrice + const orderState = new OrderState() + orderState.status = overrides?.status ?? 'Submitted' + return { contract, order, orderState } + } + + it('returns compact summaries without UNSET fields', async () => { + const broker = new MockBroker({ id: 'mock-paper' }) + broker.setQuote('AAPL', 150) + const mgr = makeManager(broker) + const uta = mgr.resolve('mock-paper')[0] + + uta.stagePlaceOrder({ aliceId: 'mock-paper|AAPL', action: 'BUY', orderType: 'MKT', totalQuantity: 10 }) + uta.commit('buy') + await uta.push() + + const tools = createTradingTools(mgr) + const ids = uta.getPendingOrderIds().map(p => p.orderId) + // getPendingOrderIds may be empty after market fill — test the tool output shape instead + const result = await (tools.getOrders.execute as Function)({ source: 'mock-paper' }) + + // Result should be an array of compact objects, not raw OpenOrder + if (Array.isArray(result) && result.length > 0) { + const first = result[0] + // Should have summarized fields + expect(first).toHaveProperty('source') + expect(first).toHaveProperty('action') + expect(first).toHaveProperty('orderType') + expect(first).toHaveProperty('totalQuantity') + expect(first).toHaveProperty('status') + // Should NOT have raw IBKR fields + expect(first).not.toHaveProperty('softDollarTier') + expect(first).not.toHaveProperty('transmit') + expect(first).not.toHaveProperty('blockOrder') + expect(first).not.toHaveProperty('sweepToFill') + } + }) + + it('filters UNSET values from order summary', async () => { + const broker = new MockBroker({ id: 'mock-paper' }) + const mgr = makeManager(broker) + const tools = createTradingTools(mgr) + + // Mock getOrders to return a raw OpenOrder with UNSET fields + const uta = mgr.resolve('mock-paper')[0] + vi.spyOn(uta, 'getPendingOrderIds').mockReturnValue([{ orderId: 'ord-1', symbol: 'AAPL' }]) + vi.spyOn(uta, 'getOrders').mockResolvedValue([makeOpenOrder()]) + + const result = await (tools.getOrders.execute as Function)({ source: 'mock-paper' }) + expect(Array.isArray(result)).toBe(true) + const order = result[0] + + // lmtPrice is UNSET_DOUBLE — should be absent + expect(order.lmtPrice).toBeUndefined() + // auxPrice is UNSET_DOUBLE — should be absent + expect(order.auxPrice).toBeUndefined() + // trailStopPrice is UNSET_DOUBLE — should be absent + expect(order.trailStopPrice).toBeUndefined() + // parentId is 0 — should be absent + expect(order.parentId).toBeUndefined() + // tpsl not set — should be absent + expect(order.tpsl).toBeUndefined() + }) + + it('includes non-UNSET optional fields', async () => { + const broker = new MockBroker({ id: 'mock-paper' }) + const mgr = makeManager(broker) + const tools = createTradingTools(mgr) + + const uta = mgr.resolve('mock-paper')[0] + vi.spyOn(uta, 'getPendingOrderIds').mockReturnValue([{ orderId: 'ord-2', symbol: 'AAPL' }]) + const openOrder = makeOpenOrder({ lmtPrice: 150, orderType: 'LMT' }) + openOrder.tpsl = { takeProfit: { price: '160' }, stopLoss: { price: '140' } } + vi.spyOn(uta, 'getOrders').mockResolvedValue([openOrder]) + + const result = await (tools.getOrders.execute as Function)({ source: 'mock-paper' }) + const order = result[0] + + expect(order.lmtPrice).toBe(150) + expect(order.tpsl).toEqual({ takeProfit: { price: '160' }, stopLoss: { price: '140' } }) + }) + + it('preserves string orderId from getPendingOrderIds', async () => { + const broker = new MockBroker({ id: 'mock-paper' }) + const mgr = makeManager(broker) + const tools = createTradingTools(mgr) + + const uta = mgr.resolve('mock-paper')[0] + vi.spyOn(uta, 'getPendingOrderIds').mockReturnValue([{ orderId: 'uuid-abc-123', symbol: 'AAPL' }]) + vi.spyOn(uta, 'getOrders').mockResolvedValue([makeOpenOrder()]) + + const result = await (tools.getOrders.execute as Function)({ source: 'mock-paper' }) + // Should use the string orderId, not order.orderId (which is 0) + expect(result[0].orderId).toBe('uuid-abc-123') + }) + + it('groupBy contract clusters orders by aliceId', async () => { + const broker = new MockBroker({ id: 'mock-paper' }) + const mgr = makeManager(broker) + const tools = createTradingTools(mgr) + + const uta = mgr.resolve('mock-paper')[0] + vi.spyOn(uta, 'getPendingOrderIds').mockReturnValue([ + { orderId: 'ord-1', symbol: 'AAPL' }, + { orderId: 'ord-2', symbol: 'AAPL' }, + { orderId: 'ord-3', symbol: 'ETH' }, + ]) + vi.spyOn(uta, 'getOrders').mockResolvedValue([ + makeOpenOrder({ symbol: 'AAPL', action: 'BUY' }), + makeOpenOrder({ symbol: 'AAPL', action: 'SELL', orderType: 'LMT', lmtPrice: 160 }), + makeOpenOrder({ symbol: 'ETH', action: 'BUY' }), + ]) + + const result = await (tools.getOrders.execute as Function)({ source: 'mock-paper', groupBy: 'contract' }) + + // Should be an object keyed by aliceId + expect(result).not.toBeInstanceOf(Array) + expect(result['mock-paper|AAPL']).toBeDefined() + expect(result['mock-paper|AAPL'].orders).toHaveLength(2) + expect(result['mock-paper|ETH']).toBeDefined() + expect(result['mock-paper|ETH'].orders).toHaveLength(1) + }) +}) diff --git a/src/tool/trading.ts b/src/tool/trading.ts index 67ab7b5f..7bfd2993 100644 --- a/src/tool/trading.ts +++ b/src/tool/trading.ts @@ -8,9 +8,9 @@ import { tool, type Tool } from 'ai' import { z } from 'zod' -import { Contract } from '@traderalice/ibkr' +import { Contract, UNSET_DOUBLE, UNSET_DECIMAL } from '@traderalice/ibkr' import type { AccountManager } from '@/domain/trading/account-manager.js' -import { BrokerError } from '@/domain/trading/brokers/types.js' +import { BrokerError, type OpenOrder } from '@/domain/trading/brokers/types.js' import '@/domain/trading/contract-ext.js' /** Classify a broker error into a structured response for AI consumption. */ @@ -26,6 +26,31 @@ function handleBrokerError(err: unknown): { error: string; code: string; transie } } +/** Summarize an OpenOrder into a compact object for AI consumption. */ +function summarizeOrder(o: OpenOrder, source: string, stringOrderId?: string) { + const order = o.order + return { + source, + orderId: stringOrderId ?? String(order.orderId), + aliceId: o.contract.aliceId ?? '', + symbol: o.contract.symbol || o.contract.localSymbol || '', + action: order.action, + orderType: order.orderType, + totalQuantity: order.totalQuantity.equals(UNSET_DECIMAL) ? '0' : order.totalQuantity.toString(), + status: o.orderState.status, + ...(order.lmtPrice !== UNSET_DOUBLE && { lmtPrice: order.lmtPrice }), + ...(order.auxPrice !== UNSET_DOUBLE && { auxPrice: order.auxPrice }), + ...(order.trailStopPrice !== UNSET_DOUBLE && { trailStopPrice: order.trailStopPrice }), + ...(order.trailingPercent !== UNSET_DOUBLE && { trailingPercent: order.trailingPercent }), + ...(order.tif && { tif: order.tif }), + ...(!order.filledQuantity.equals(UNSET_DECIMAL) && { filledQuantity: order.filledQuantity.toString() }), + ...(o.avgFillPrice != null && { avgFillPrice: o.avgFillPrice }), + ...(order.parentId !== 0 && { parentId: order.parentId }), + ...(order.ocaGroup && { ocaGroup: order.ocaGroup }), + ...(o.tpsl && { tpsl: o.tpsl }), + } +} + const sourceDesc = (required: boolean, extra?: string) => { const base = `Account source — matches account id (e.g. "alpaca-paper") or provider (e.g. "alpaca", "ccxt").` const req = required @@ -143,21 +168,33 @@ If this tool returns an error with transient=true, wait a few seconds and retry getOrders: tool({ description: `Query orders by ID. If no orderIds provided, queries all pending (submitted) orders. +Use groupBy: "contract" to group orders by contract/aliceId (useful with many positions + TPSL). If this tool returns an error with transient=true, wait a few seconds and retry once before reporting to the user.`, inputSchema: z.object({ source: z.string().optional().describe(sourceDesc(false)), orderIds: z.array(z.string()).optional().describe('Order IDs to query. If omitted, queries all pending orders.'), + groupBy: z.enum(['contract']).optional().describe('Group orders by contract (aliceId)'), }), - execute: async ({ source, orderIds }) => { + execute: async ({ source, orderIds, groupBy }) => { const targets = manager.resolve(source) if (targets.length === 0) return [] try { - const results = await Promise.all(targets.map(async (uta) => { + const summaries = (await Promise.all(targets.map(async (uta) => { const ids = orderIds ?? uta.getPendingOrderIds().map(p => p.orderId) const orders = await uta.getOrders(ids) - return orders.map((o) => ({ source: uta.id, ...o })) - })) - return results.flat() + return orders.map((o, i) => summarizeOrder(o, uta.id, ids[i])) + }))).flat() + + if (groupBy === 'contract') { + const grouped: Record[] }> = {} + for (const s of summaries) { + const key = s.aliceId || s.symbol + if (!grouped[key]) grouped[key] = { symbol: s.symbol, orders: [] } + grouped[key].orders.push(s) + } + return grouped + } + return summaries } catch (err) { return handleBrokerError(err) } @@ -265,24 +302,40 @@ IMPORTANT: Check this BEFORE making new trading decisions.`, placeOrder: tool({ description: `Stage an order (will execute on tradingPush). BEFORE placing orders: check tradingLog, getPortfolio, verify strategy alignment. -NOTE: This stages the operation. Call tradingCommit + tradingPush to execute.`, +NOTE: This stages the operation. Call tradingCommit + tradingPush to execute. +Required params by orderType: + MKT: totalQuantity (or cashQty) + LMT: totalQuantity + lmtPrice + STP: totalQuantity + auxPrice (stop trigger) + STP LMT: totalQuantity + auxPrice (stop trigger) + lmtPrice + TRAIL: totalQuantity + auxPrice (trailing offset) or trailingPercent + TRAIL LIMIT: totalQuantity + auxPrice (trailing offset) + lmtPrice + MOC: totalQuantity +Optional: attach takeProfit and/or stopLoss for automatic exit orders.`, inputSchema: z.object({ source: z.string().describe(sourceDesc(true)), aliceId: z.string().describe('Contract ID (format: accountId|nativeKey, from searchContracts)'), - symbol: z.string().optional().describe('Human-readable symbol. Optional.'), - side: z.enum(['buy', 'sell']).describe('Buy or sell'), - type: z.enum(['market', 'limit', 'stop', 'stop_limit', 'trailing_stop', 'trailing_stop_limit', 'moc']).describe('Order type'), - qty: z.number().positive().optional().describe('Number of shares'), - notional: z.number().positive().optional().describe('Dollar amount'), - price: z.number().positive().optional().describe('Limit price'), - stopPrice: z.number().positive().optional().describe('Stop trigger price'), - trailingAmount: z.number().positive().optional().describe('Trailing stop offset'), - trailingPercent: z.number().positive().optional().describe('Trailing stop percentage'), - timeInForce: z.enum(['day', 'gtc', 'ioc', 'fok', 'opg', 'gtd']).default('day').describe('Time in force'), - goodTillDate: z.string().optional().describe('Expiration date for GTD'), - extendedHours: z.boolean().optional().describe('Allow pre/after-hours'), - parentId: z.string().optional().describe('Parent order ID for bracket orders'), + symbol: z.string().optional().describe('Human-readable symbol (optional, for display only)'), + action: z.enum(['BUY', 'SELL']).describe('Order direction'), + orderType: z.enum(['MKT', 'LMT', 'STP', 'STP LMT', 'TRAIL', 'TRAIL LIMIT', 'MOC']).describe('Order type'), + totalQuantity: z.number().positive().optional().describe('Number of shares/contracts (mutually exclusive with cashQty)'), + cashQty: z.number().positive().optional().describe('Notional dollar amount (mutually exclusive with totalQuantity)'), + lmtPrice: z.number().positive().optional().describe('Limit price (required for LMT, STP LMT, TRAIL LIMIT)'), + auxPrice: z.number().positive().optional().describe('Stop trigger price for STP/STP LMT; trailing offset amount for TRAIL/TRAIL LIMIT'), + trailStopPrice: z.number().positive().optional().describe('Initial trailing stop price (TRAIL/TRAIL LIMIT only)'), + trailingPercent: z.number().positive().optional().describe('Trailing stop percentage offset (alternative to auxPrice for TRAIL)'), + tif: z.enum(['DAY', 'GTC', 'IOC', 'FOK', 'OPG', 'GTD']).default('DAY').describe('Time in force'), + goodTillDate: z.string().optional().describe('Expiration datetime for GTD orders'), + outsideRth: z.boolean().optional().describe('Allow execution outside regular trading hours'), + parentId: z.string().optional().describe('Parent order ID (bracket orders)'), ocaGroup: z.string().optional().describe('One-Cancels-All group name'), + takeProfit: z.object({ + price: z.string().describe('Take profit price'), + }).optional().describe('Take profit order (single-level, full quantity)'), + stopLoss: z.object({ + price: z.string().describe('Stop loss trigger price'), + limitPrice: z.string().optional().describe('Limit price for stop-limit SL (omit for stop-market)'), + }).optional().describe('Stop loss order (single-level, full quantity)'), }), execute: ({ source, ...params }) => manager.resolveOne(source).stagePlaceOrder(params), }), @@ -292,13 +345,13 @@ NOTE: This stages the operation. Call tradingCommit + tradingPush to execute.`, inputSchema: z.object({ source: z.string().describe(sourceDesc(true)), orderId: z.string().describe('Order ID to modify'), - qty: z.number().positive().optional().describe('New quantity'), - price: z.number().positive().optional().describe('New limit price'), - stopPrice: z.number().positive().optional().describe('New stop trigger price'), - trailingAmount: z.number().positive().optional().describe('New trailing stop offset'), + totalQuantity: z.number().positive().optional().describe('New quantity'), + lmtPrice: z.number().positive().optional().describe('New limit price'), + auxPrice: z.number().positive().optional().describe('New stop trigger price or trailing offset (depends on order type)'), + trailStopPrice: z.number().positive().optional().describe('New initial trailing stop price'), trailingPercent: z.number().positive().optional().describe('New trailing stop percentage'), - type: z.enum(['market', 'limit', 'stop', 'stop_limit', 'trailing_stop', 'trailing_stop_limit', 'moc']).optional().describe('New order type'), - timeInForce: z.enum(['day', 'gtc', 'ioc', 'fok', 'opg', 'gtd']).optional().describe('New time in force'), + orderType: z.enum(['MKT', 'LMT', 'STP', 'STP LMT', 'TRAIL', 'TRAIL LIMIT', 'MOC']).optional().describe('New order type'), + tif: z.enum(['DAY', 'GTC', 'IOC', 'FOK', 'OPG', 'GTD']).optional().describe('New time in force'), goodTillDate: z.string().optional().describe('New expiration date'), }), execute: ({ source, ...params }) => manager.resolveOne(source).stageModifyOrder(params), diff --git a/turbo.json b/turbo.json new file mode 100644 index 00000000..dd313e82 --- /dev/null +++ b/turbo.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://turbo.build/schema.json", + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "open-alice-ui#build": { + "dependsOn": [], + "outputs": [] + } + } +} diff --git a/ui/src/pages/MarketDataPage.tsx b/ui/src/pages/MarketDataPage.tsx index 49e3d1e7..808578b3 100644 --- a/ui/src/pages/MarketDataPage.tsx +++ b/ui/src/pages/MarketDataPage.tsx @@ -11,35 +11,28 @@ type MarketDataConfig = Record // ==================== Constants ==================== const PROVIDER_OPTIONS: Record = { - equity: ['yfinance', 'fmp', 'intrinio', 'tiingo', 'alpha_vantage'], - crypto: ['yfinance', 'fmp', 'tiingo'], - currency: ['yfinance', 'fmp', 'tiingo'], + equity: ['yfinance', 'fmp', 'intrinio'], + crypto: ['yfinance', 'fmp'], + currency: ['yfinance', 'fmp'], + commodity: ['yfinance', 'fmp'], } const ASSET_LABELS: Record = { equity: 'Equity', crypto: 'Crypto', currency: 'Currency', + commodity: 'Commodity', } -/** Maps provider name → providerKeys key. null means free, no key required. */ -const PROVIDER_KEY_MAP: Record = { - yfinance: null, - fmp: 'fmp', - intrinio: 'intrinio', - tiingo: 'tiingo', - alpha_vantage: 'alpha_vantage', - benzinga: 'benzinga', - biztoc: 'biztoc', -} - -const UTILITY_PROVIDERS = [ +const ALL_PROVIDERS = [ + { key: 'fmp', name: 'FMP', desc: 'Equity, crypto, currency, ETF, index — fundamentals, calendars, discovery.', hint: 'financialmodelingprep.com' }, { key: 'fred', name: 'FRED', desc: 'Federal Reserve Economic Data — CPI, GDP, interest rates, macro indicators.', hint: 'Free — fredaccount.stlouisfed.org/apikeys' }, { key: 'bls', name: 'BLS', desc: 'Bureau of Labor Statistics — employment, payrolls, wages, CPI.', hint: 'Free — registrationapps.bls.gov/bls_registration' }, { key: 'eia', name: 'EIA', desc: 'Energy Information Administration — petroleum status, energy reports.', hint: 'Free — eia.gov/opendata' }, - { key: 'econdb', name: 'EconDB', desc: 'Global macro indicators, country profiles, shipping data.', hint: 'Optional — works without key (limited). econdb.com' }, - { key: 'nasdaq', name: 'Nasdaq', desc: 'Nasdaq Data Link — dividend/earnings calendars, short interest.', hint: 'Freemium — data.nasdaq.com' }, - { key: 'tradingeconomics', name: 'Trading Economics', desc: '20M+ indicators across 196 countries, economic calendar.', hint: 'Paid — tradingeconomics.com' }, + { key: 'econdb', name: 'EconDB', desc: 'Global macro indicators, country profiles, shipping data.', hint: 'Optional — econdb.com' }, + { key: 'intrinio', name: 'Intrinio', desc: 'Options snapshots, equity data.', hint: 'intrinio.com' }, + { key: 'nasdaq', name: 'Nasdaq', desc: 'Nasdaq Data Link — dividend/earnings calendars, short interest.', hint: 'data.nasdaq.com' }, + { key: 'tradingeconomics', name: 'Trading Economics', desc: '20M+ indicators across 196 countries, economic calendar.', hint: 'tradingeconomics.com' }, ] as const // ==================== Test Button ==================== @@ -65,7 +58,7 @@ function TestButton({ : 'border-border text-text-muted hover:bg-bg-tertiary hover:text-text' }`} > - {status === 'testing' ? '…' : status === 'ok' ? 'OK' : status === 'error' ? 'Fail' : 'Test'} + {status === 'testing' ? '...' : status === 'ok' ? 'OK' : status === 'error' ? 'Fail' : 'Test'} ) } @@ -85,7 +78,7 @@ export function MarketDataPage() {
-

Loading…

+

Loading...

) @@ -94,7 +87,7 @@ export function MarketDataPage() { const dataBackend = (config.backend as string) || 'typebb-sdk' const apiUrl = (config.apiUrl as string) || 'http://localhost:6900' const apiServer = (config.apiServer as { enabled: boolean; port: number } | undefined) ?? { enabled: false, port: 6901 } - const providers = (config.providers ?? { equity: 'yfinance', crypto: 'yfinance', currency: 'yfinance' }) as Record + const providers = (config.providers ?? { equity: 'yfinance', crypto: 'yfinance', currency: 'yfinance', commodity: 'yfinance' }) as Record const providerKeys = (config.providerKeys ?? {}) as Record const handleProviderChange = (asset: string, provider: string) => { @@ -126,59 +119,27 @@ export function MarketDataPage() {
- {/* Data Backend */} - { updateConfigImmediate({ backend }); }} - onApiUrlChange={(url) => updateConfig({ apiUrl: url })} - /> - - {/* Asset Providers */} + {/* Asset Providers — route selection only, no keys */} - {/* Embedded API Server */} - -
-
-

Enable HTTP server

-

- Serves at http://localhost:{apiServer.port} -

-
- updateConfigImmediate({ apiServer: { ...apiServer, enabled: v } })} - /> -
- {apiServer.enabled && ( - - updateConfig({ apiServer: { ...apiServer, port: Number(e.target.value) || 6901 } })} - /> - - )} -
- - {/* Macro & Utility Providers */} - + + {/* Advanced — backend switch + embedded server */} + updateConfigImmediate({ backend })} + onApiUrlChange={(url) => updateConfig({ apiUrl: url })} + onApiServerChange={(server) => updateConfigImmediate({ apiServer: server })} + />
{loadError &&

Failed to load configuration.

}
@@ -186,160 +147,34 @@ export function MarketDataPage() { ) } -// ==================== Data Backend Section ==================== - -function DataBackendSection({ - backend, - apiUrl, - onBackendChange, - onApiUrlChange, -}: { - backend: string - apiUrl: string - onBackendChange: (backend: string) => void - onApiUrlChange: (url: string) => void -}) { - const [testing, setTesting] = useState(false) - const [testStatus, setTestStatus] = useState<'idle' | 'ok' | 'error'>('idle') - - const testConnection = async () => { - setTesting(true) - setTestStatus('idle') - try { - const res = await fetch(`${apiUrl}/api/v1/equity/search?query=AAPL&provider=sec`, { signal: AbortSignal.timeout(5000) }) - setTestStatus(res.ok ? 'ok' : 'error') - } catch { - setTestStatus('error') - } finally { - setTesting(false) - } - } - - return ( - -
- {(['typebb-sdk', 'openbb-api'] as const).map((opt, i) => ( - - ))} -
-

- {backend === 'typebb-sdk' - ? 'Uses the built-in TypeBB engine. No external process required.' - : 'Connects to an external OpenBB-compatible HTTP endpoint.'} -

- - {backend === 'openbb-api' && ( -
- -
- { onApiUrlChange(e.target.value); setTestStatus('idle') }} - placeholder="http://localhost:6900" - /> - -
-
-
- )} -
- ) -} - // ==================== Asset Providers Section ==================== function AssetProvidersSection({ providers, - providerKeys, onProviderChange, - onKeyChange, -}: AssetProviderGridProps) { - const [localKeys, setLocalKeys] = useState>(() => ({ ...providerKeys })) - const [testStatus, setTestStatus] = useState>({}) - - const handleKeyChange = (keyName: string, value: string) => { - setLocalKeys((prev) => ({ ...prev, [keyName]: value })) - setTestStatus((prev) => ({ ...prev, [keyName]: 'idle' })) - onKeyChange(keyName, value) - } - - const testProvider = async (provider: string, keyName: string) => { - const key = localKeys[keyName] - if (!key) return - setTestStatus((prev) => ({ ...prev, [keyName]: 'testing' })) - try { - const result = await api.marketData.testProvider(provider, key) - setTestStatus((prev) => ({ ...prev, [keyName]: result.ok ? 'ok' : 'error' })) - } catch { - setTestStatus((prev) => ({ ...prev, [keyName]: 'error' })) - } - } - +}: { + providers: Record + onProviderChange: (asset: string, provider: string) => void +}) { return (
{Object.entries(PROVIDER_OPTIONS).map(([asset, options]) => { const selectedProvider = providers[asset] || options[0] - const keyName = PROVIDER_KEY_MAP[selectedProvider] ?? null - const status = keyName ? (testStatus[keyName] || 'idle') : 'idle' - return (
- {ASSET_LABELS[asset]} + {ASSET_LABELS[asset]} - {keyName ? ( - <> - handleKeyChange(keyName, e.target.value)} - placeholder="API key" - /> - testProvider(selectedProvider, keyName)} - /> - - ) : ( + {selectedProvider === 'yfinance' && ( Free )}
@@ -350,16 +185,9 @@ function AssetProvidersSection({ ) } -interface AssetProviderGridProps { - providers: Record - providerKeys: Record - onProviderChange: (asset: string, provider: string) => void - onKeyChange: (keyName: string, value: string) => void -} +// ==================== API Keys Section ==================== -// ==================== Utility Providers Section ==================== - -function UtilityProvidersSection({ +function ApiKeysSection({ providerKeys, onKeyChange, }: { @@ -368,7 +196,7 @@ function UtilityProvidersSection({ }) { const [localKeys, setLocalKeys] = useState>(() => { const init: Record = {} - for (const p of UTILITY_PROVIDERS) init[p.key] = providerKeys[p.key] || '' + for (const p of ALL_PROVIDERS) init[p.key] = providerKeys[p.key] || '' return init }) const [testStatus, setTestStatus] = useState>({}) @@ -393,11 +221,11 @@ function UtilityProvidersSection({ return (
- {UTILITY_PROVIDERS.map(({ key, name, desc, hint }) => { + {ALL_PROVIDERS.map(({ key, name, desc, hint }) => { const status = testStatus[key] || 'idle' return ( @@ -423,3 +251,113 @@ function UtilityProvidersSection({ ) } + +// ==================== Advanced Section ==================== + +function AdvancedSection({ + backend, + apiUrl, + apiServer, + onBackendChange, + onApiUrlChange, + onApiServerChange, +}: { + backend: string + apiUrl: string + apiServer: { enabled: boolean; port: number } + onBackendChange: (backend: string) => void + onApiUrlChange: (url: string) => void + onApiServerChange: (server: { enabled: boolean; port: number }) => void +}) { + const [expanded, setExpanded] = useState(false) + + return ( +
+ + {!expanded && ( +

Data backend, embedded API server.

+ )} + {expanded && ( +
+ {/* Data Backend */} +
+

Data Backend

+
+ {(['typebb-sdk', 'openbb-api'] as const).map((opt, i) => ( + + ))} +
+

+ {backend === 'typebb-sdk' + ? 'Uses the built-in TypeBB engine. No external process required.' + : 'Connects to an external OpenBB-compatible HTTP endpoint.'} +

+ {backend === 'openbb-api' && ( +
+ + onApiUrlChange(e.target.value)} + placeholder="http://localhost:6900" + /> + +
+ )} +
+ + {/* Embedded API Server */} +
+

Embedded API Server

+

+ Expose an OpenBB-compatible HTTP API from Alice. Other services can connect to query market data. +

+
+
+

Enable HTTP server

+

+ Serves at http://localhost:{apiServer.port} +

+
+ onApiServerChange({ ...apiServer, enabled: v })} + /> +
+ {apiServer.enabled && ( + + onApiServerChange({ ...apiServer, port: Number(e.target.value) || 6901 })} + /> + + )} +
+
+ )} +
+ ) +} diff --git a/vitest.bbProvider.config.ts b/vitest.bbProvider.config.ts new file mode 100644 index 00000000..57810970 --- /dev/null +++ b/vitest.bbProvider.config.ts @@ -0,0 +1,17 @@ +import { fileURLToPath } from 'node:url' +import { resolve, dirname } from 'node:path' + +const __dirname = dirname(fileURLToPath(import.meta.url)) + +export default { + resolve: { + alias: { + '@': resolve(__dirname, './src'), + }, + }, + test: { + include: ['src/**/*.bbProvider.spec.*'], + testTimeout: 30_000, + fileParallelism: false, + }, +} diff --git a/vitest.config.ts b/vitest.config.ts index 1e904e7b..f59b3f75 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -22,7 +22,7 @@ export default defineConfig({ name: 'node', environment: 'node', include: ['src/**/*.spec.*', 'packages/**/*.spec.*'], - exclude: ['**/*.e2e.spec.*', '**/node_modules/**'], + exclude: ['**/*.e2e.spec.*', '**/*.bbProvider.spec.*', '**/node_modules/**'], }, }, {